diff options
53 files changed, 2416 insertions, 980 deletions
diff --git a/am/ipv6.m4 b/am/ipv6.m4 new file mode 100644 index 000000000..2357314b9 --- /dev/null +++ b/am/ipv6.m4 @@ -0,0 +1,56 @@ +dnl This file is part of GNU Mailutils. -*- autoconf -*- +dnl Copyright (C) 2011 Free Software Foundation, Inc. +dnl +dnl GNU Mailutils is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 3 of the License, or +dnl (at your option) any later version. +dnl +dnl GNU Mailutils is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. + +AC_DEFUN([MU_ENABLE_IPV6], + [AC_ARG_ENABLE(ipv6, + [AC_HELP_STRING([--enable-ipv6], [enable IPv6 support])], + [status_ipv6=$enableval], + [status_ipv6=maybe]) + + if test $status_ipv6 != no; then + working_ipv6=no + AC_EGREP_CPP(MAILUTILS_AF_INET6_DEFINED,[ +#include <sys/socket.h> +#if defined(AF_INET6) +MAILUTILS_AF_INET6_DEFINED +#endif +],[working_ipv6=yes]) + + AC_CHECK_TYPE([struct sockaddr_storage], + [working_ipv6=yes], [working_ipv6=no], + [#include <sys/socket.h>]) + AC_CHECK_TYPE([struct sockaddr_in6], + [working_ipv6=yes], [working_ipv6=no], + [#include <sys/types.h> + #include <netinet/in.h>]) + AC_CHECK_TYPE([struct addrinfo], + [working_ipv6=yes], [working_ipv6=no], + [#include <netdb.h>]) + AC_CHECK_FUNC([getnameinfo], + [working_ipv6=yes], [working_ipv6=no], + [#include <netdb.h>]) + + if test $working_ipv6 = no; then + if test $status_ipv6 = yes; then + AC_MSG_ERROR([IPv6 support is required but not available]) + fi + fi + status_ipv6=$working_ipv6 + if test $status_ipv6 = yes; then + AC_DEFINE_UNQUOTED([MAILUTILS_IPV6],1, + [Define to 1 if IPv6 support is enabled]) + fi + fi])
\ No newline at end of file diff --git a/configure.ac b/configure.ac index e03a4c3b3..2edb49459 100644 --- a/configure.ac +++ b/configure.ac @@ -538,12 +538,16 @@ dnl Check for libraries AH_BOTTOM([ /* program_name is used by lib/error.c */ #define program_name program_invocation_name ]) +# IPv6 support +MU_ENABLE_IPV6 + + ## FriBidi support AC_CHECK_FUNCS(wcwidth) AC_SUBST(FRIBIDI_LIBS) @@ -1282,12 +1286,14 @@ Readline support .............. $status_readline MySQL support ................. $status_mysql PostgreSQL support ............ $status_pgsql LDAP support .................. $status_ldap Radius support ................ $status_radius Support for virtual domains ... $status_virtual_domains +IPv6 support .................. $status_ipv6 + Interfaces: Guile ......................... $status_guile C++ ........................... $status_cxx Python ........................ $status_python @@ -1329,12 +1335,13 @@ status_virtual_domains=$mu_cv_enable_virtual_domains status_imap=$mu_cv_enable_imap status_pop=$mu_cv_enable_pop status_mh=$mu_cv_enable_mh status_maildir=$mu_cv_enable_maildir status_smtp=$mu_cv_enable_smtp status_sendmail=$mu_cv_enable_sendmail +status_ipv6=$status_ipv6 ]) dnl Output Makefiles AC_CONFIG_FILES([ include/confpaths.h Makefile @@ -1379,12 +1386,14 @@ AC_CONFIG_FILES([ maidag/Makefile mail/Makefile mail/testsuite/Makefile libmailutils/auth/Makefile libmailutils/base/Makefile libmailutils/address/Makefile + libmailutils/sockaddr/Makefile + libmailutils/cidr/Makefile libmailutils/cfg/Makefile libmailutils/diag/Makefile libmailutils/filter/Makefile libmailutils/mailbox/Makefile libmailutils/mailer/Makefile libmailutils/mime/Makefile diff --git a/examples/.gitignore b/examples/.gitignore index af4156be3..890812aae 100644 --- a/examples/.gitignore +++ b/examples/.gitignore @@ -8,17 +8,19 @@ encode2047 header http iconv listop lsf mailcap +mblconv mimetest msg-send mta muauth mucat muemail murun musocio nntpclient +sa sfrom url-parse diff --git a/examples/Makefile.am b/examples/Makefile.am index e22a8d355..9df91ea62 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -40,12 +40,13 @@ noinst_PROGRAMS = \ mucat\ muauth\ muemail\ murun\ musocio\ $(NNTPCLIENT)\ + sa\ sfrom EXTRA_PROGRAMS = nntpclient ## NOTE: Numaddr must be an installable target, otherwise libtool ## will not create a shared library and `make check' will fail in diff --git a/examples/aclck.c b/examples/aclck.c index 57f5c0388..033c444b1 100644 --- a/examples/aclck.c +++ b/examples/aclck.c @@ -25,41 +25,15 @@ #include <sys/un.h> #include <arpa/inet.h> #include <stdlib.h> #include <string.h> -struct sockaddr *target_sa; -int target_salen; +struct mu_sockaddr *target_sa; mu_acl_t acl; -struct sockaddr * -parse_address (int *psalen, char *str) -{ - struct sockaddr_in in; - struct sockaddr *sa; - - in.sin_family = AF_INET; - if (inet_aton (str, &in.sin_addr) == 0) - { - mu_error ("Invalid IPv4: %s", str); - exit (1); - } - in.sin_port = 0; - *psalen = sizeof (in); - sa = malloc (*psalen); - if (!sa) - { - mu_error ("%s", mu_strerror (errno)); - exit (1); - } - - memcpy (sa, &in, sizeof (in)); - return sa; -} - void read_rules (FILE *fp) { char buf[512]; int line = 0; int wsflags = MU_WRDSF_DEFFLAGS | MU_WRDSF_COMMENT; @@ -73,18 +47,15 @@ read_rules (FILE *fp) exit (1); } ws.ws_comment = "#"; while (fgets (buf, sizeof buf, fp)) { - unsigned long netmask; - int salen; - struct sockaddr *sa; + struct mu_cidr cidr; mu_acl_action_t action; void *data = NULL; - char *p; int len = strlen (buf); if (len == 0) continue; if (buf[len-1] != '\n') { @@ -106,53 +77,25 @@ read_rules (FILE *fp) if (ws.ws_wordc < 2) { mu_error ("%d: invalid input", line); continue; } - p = strchr (ws.ws_wordv[1], '/'); - if (p) + if (strcmp (ws.ws_wordv[1], "any") == 0) + memset (&cidr, 0, sizeof (cidr)); + else { - char *q; - unsigned netlen; - - *p++ = 0; - netlen = strtoul (p, &q, 10); - if (*q == 0) - { - if (netlen == 0) - netmask = 0; - else - { - netmask = 0xfffffffful >> (32 - netlen); - netmask <<= (32 - netlen); - netmask = htonl (netmask); - } - } - else if (*q == '.') + rc = mu_cidr_from_string (&cidr, ws.ws_wordv[1]); + if (rc) { - struct in_addr addr; - - if (inet_aton (p, &addr) == 0) - { - mu_error ("%d: invalid netmask", line); - continue; - } - netmask = addr.s_addr; - } - else - { - mu_error ("%d: invalid netmask", line); + mu_error ("%d: invalid source CIDR: %s", + line, mu_strerror (rc)); continue; } } - else - netmask = 0xfffffffful; - - sa = parse_address (&salen, ws.ws_wordv[1]); - + /* accept addr deny addr log addr [rest ...] exec addr [rest ...] execif addr rest ....] */ @@ -171,13 +114,13 @@ read_rules (FILE *fp) case mu_acl_log: case mu_acl_exec: case mu_acl_ifexec: data = strdup (ws.ws_wordv[2]); } - rc = mu_acl_append (acl, action, data, sa, salen, netmask); + rc = mu_acl_append (acl, action, data, &cidr); if (rc) mu_error ("%d: cannot append acl entry: %s", line, mu_strerror (rc)); } mu_wordsplit_free (&ws); } @@ -200,13 +143,18 @@ main (int argc, char **argv) case 'd': mu_debug_parse_spec (optarg); break; case 'a': - target_sa = parse_address (&target_salen, optarg); + rc = mu_sockaddr_from_node (&target_sa, optarg, NULL, NULL); + if (rc) + { + mu_error ("mu_sockaddr_from_node: %s", mu_strerror (rc)); + exit (1); + } break; case 'f': file = fopen (optarg, "r"); if (file == 0) { @@ -222,13 +170,14 @@ main (int argc, char **argv) } argv += optind; argc -= optind; read_rules (file ? file : stdin); - rc = mu_acl_check_sockaddr (acl, target_sa, target_salen, &result); + rc = mu_acl_check_sockaddr (acl, target_sa->addr, target_sa->addrlen, + &result); if (rc) { mu_error ("mu_acl_check_sockaddr failed: %s", mu_strerror (rc)); exit (1); } switch (result) diff --git a/examples/echosrv.c b/examples/echosrv.c index fb68e7aee..fffde7343 100644 --- a/examples/echosrv.c +++ b/examples/echosrv.c @@ -36,33 +36,39 @@ mu_server_t server; int echo_conn (int fd, struct sockaddr *s, int len, void *server_data, void *call_data, mu_ip_server_t srv) { - struct sockaddr_in srv_addr, *s_in = (struct sockaddr_in *)s; - int addrlen = sizeof srv_addr; pid_t pid; char buf[512]; FILE *in, *out; - - mu_ip_server_get_sockaddr (srv, (struct sockaddr *)&srv_addr, &addrlen); pid = fork (); if (pid == -1) { mu_error ("fork failed: %s", mu_strerror (errno)); return 0; } if (pid) { - mu_diag_output (MU_DIAG_INFO, "%lu: opened connection %s:%d => %s:%d", + struct mu_sockaddr *clt_addr; + int rc = mu_sockaddr_create (&clt_addr, s, len); + if (rc) + { + mu_error ("mu_sockaddr_create failed: %s", mu_strerror (rc)); + return 0; + } + + mu_diag_output (MU_DIAG_INFO, "%lu: opened connection %s => %s", (unsigned long) pid, - inet_ntoa (srv_addr.sin_addr), ntohs (srv_addr.sin_port), - inet_ntoa (s_in->sin_addr), ntohs (s_in->sin_port)); + mu_ip_server_addrstr (srv), + mu_sockaddr_str (clt_addr)); + + mu_sockaddr_free (clt_addr); return 0; } mu_ip_server_shutdown (srv); in = fdopen (fd, "r"); @@ -105,40 +111,51 @@ tcp_conn_free (void *conn_data, void *server_data) mu_ip_server_destroy (&tcpsrv); } void create_server (char *arg) { - char *p, *q; - struct sockaddr_in s; + struct mu_sockaddr *s; mu_ip_server_t tcpsrv; - unsigned n; - - p = strchr (arg, ':'); - if (!*p) + int rc; + mu_url_t url, url_hint; + struct mu_sockaddr_hints hints; + + if (arg[0] == '/') + url_hint = NULL; + else { - mu_error ("invalid specification: %s\n", arg); - exit (1); + rc = mu_url_create (&url_hint, "inet://"); + if (rc) + { + mu_error ("cannot create URL hints: %s", mu_strerror (rc)); + exit (1); + } } - *p++ = 0; - s.sin_family = AF_INET; - if (inet_aton (arg, &s.sin_addr) == 0) + rc = mu_url_create_hint (&url, arg, MU_URL_PARSE_DEFAULT, url_hint); + mu_url_destroy (&url_hint); + if (rc) { - mu_error ("invalid IP address: %s\n", arg); + mu_error ("cannot parse URL `%s': %s", arg, mu_strerror (rc)); exit (1); } - n = strtoul (p, &q, 0); - if (*q) + + memset (&hints, sizeof(hints), 0); + hints.flags = MU_AH_PASSIVE; + hints.socktype = SOCK_STREAM; + hints.protocol = IPPROTO_TCP; + rc = mu_sockaddr_from_url (&s, url, &hints); + mu_url_destroy (&url); + + if (rc) { - mu_error ("invalid port number: %s\n", p); + mu_error ("cannot create sockaddr: %s", mu_strerror (rc)); exit (1); - } - s.sin_port = htons (n); + } - MU_ASSERT (mu_ip_server_create (&tcpsrv, (struct sockaddr*) &s, sizeof s, - MU_IP_TCP)); + MU_ASSERT (mu_ip_server_create (&tcpsrv, s, MU_IP_TCP)); MU_ASSERT (mu_ip_server_open (tcpsrv)); MU_ASSERT (mu_ip_server_set_conn (tcpsrv, echo_conn)); MU_ASSERT (mu_server_add_connection (server, mu_ip_server_get_fd (tcpsrv), tcpsrv, tcp_conn_handler, tcp_conn_free)); diff --git a/examples/sa.c b/examples/sa.c new file mode 100644 index 000000000..7cc7e93b5 --- /dev/null +++ b/examples/sa.c @@ -0,0 +1,93 @@ +/* GNU Mailutils -- a suite of utilities for electronic mail + Copyright (C) 1999, 2000, 2001, 2002, 2005, 2007, 2010, 2011 Free + Software Foundation, Inc. + + GNU Mailutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GNU Mailutils is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif +#include <mailutils/mailutils.h> + +int +main (int argc, char **argv) +{ + struct mu_sockaddr_hints hints; + struct mu_sockaddr *sa, *ap; + int rc, i; + char *node = NULL, *serv = NULL; + char *urlstr; + + mu_set_program_name (argv[0]); + + memset (&hints, 0, sizeof (hints)); + hints.family = AF_UNSPEC; + for (i = 1; i < argc; i++) + { + if (strcmp (argv[i], "passive") == 0) + hints.flags |= MU_AH_PASSIVE; + else if (strcmp (argv[i], "detect") == 0) + hints.flags |= MU_AH_DETECT_FAMILY; + else if (strncmp (argv[i], "node=", 5) == 0) + node = argv[i] + 5; + else if (strncmp (argv[i], "serv=", 5) == 0) + serv = argv[i] + 5; + else if (strncmp (argv[i], "url=", 4) == 0) + urlstr = argv[i] + 4; + else if (strncmp (argv[i], "proto=", 6) == 0) + hints.protocol = atoi(argv[i] + 6); + else if (strncmp (argv[i], "family=", 7) == 0) + hints.family = atoi (argv[i] + 7); + else if (strncmp (argv[i], "socktype=", 9) == 0) + hints.socktype = atoi (argv[i] + 9); + else + { + mu_error ("unknown argument: %s", argv[i]); + exit (1); + } + } + + if (urlstr) + { + mu_url_t url; + + if (node || serv) + { + mu_error ("both url and host/serv are given"); + exit (1); + } + + rc = mu_url_create (&url, urlstr); + if (rc) + { + mu_error ("cannot create url: %s", mu_strerror (rc)); + exit (2); + } + rc = mu_sockaddr_from_url (&sa, url, &hints); + } + else + rc = mu_sockaddr_from_node (&sa, node, serv, &hints); + if (rc) + { + mu_error ("cannot create sockaddr: %s", mu_strerror (rc)); + exit (2); + } + + for (ap = sa; ap; ap = ap->next) + printf ("%s\n", mu_sockaddr_str (ap)); + + mu_sockaddr_free (sa); + exit (0); +} + diff --git a/include/mailutils/Makefile.am b/include/mailutils/Makefile.am index daa46e9fe..1e2189437 100644 --- a/include/mailutils/Makefile.am +++ b/include/mailutils/Makefile.am @@ -33,12 +33,13 @@ pkginclude_HEADERS = \ assoc.h\ attribute.h\ auth.h\ body.h\ cctype.h\ cfg.h\ + cidr.h\ cstr.h\ daemon.h\ debug.h\ diag.h\ envelope.h\ errno.h\ @@ -86,12 +87,13 @@ pkginclude_HEADERS = \ registrar.h\ sha1.h\ secret.h\ server.h\ sieve.h\ smtp.h\ + sockaddr.h\ stdstream.h\ stream.h\ syslog.h\ sql.h\ tls.h\ url.h\ diff --git a/include/mailutils/acl.h b/include/mailutils/acl.h index b898463eb..167acc82c 100644 --- a/include/mailutils/acl.h +++ b/include/mailutils/acl.h @@ -44,19 +44,17 @@ struct in_addr; int mu_acl_create (mu_acl_t *acl); int mu_acl_destroy (mu_acl_t *acl); int mu_acl_count (mu_acl_t acl, size_t *pcount); int mu_acl_get_iterator (mu_acl_t acl, mu_iterator_t *pitr); int mu_acl_append (mu_acl_t acl, mu_acl_action_t act, void *data, - struct sockaddr *sa, int salen, - unsigned long netmask); + struct mu_cidr *); int mu_acl_prepend (mu_acl_t acl, mu_acl_action_t act, void *data, - struct sockaddr *sa, int salen, unsigned long netmask); + struct mu_cidr *); int mu_acl_insert (mu_acl_t acl, size_t pos, int before, - mu_acl_action_t act, void *data, - struct sockaddr *sa, int salen, unsigned long netmask); + mu_acl_action_t act, void *data, struct mu_cidr *); int mu_acl_check_ipv4 (mu_acl_t acl, unsigned int addr, mu_acl_result_t *pres); int mu_acl_check_inaddr (mu_acl_t acl, const struct in_addr *inp, mu_acl_result_t *pres); int mu_acl_check_sockaddr (mu_acl_t acl, const struct sockaddr *sa, int salen, mu_acl_result_t *pres); diff --git a/include/mailutils/cidr.h b/include/mailutils/cidr.h new file mode 100644 index 000000000..c54bf6224 --- /dev/null +++ b/include/mailutils/cidr.h @@ -0,0 +1,61 @@ +/* GNU Mailutils -- a suite of utilities for electronic mail + Copyright (C) 2011 Free Software Foundation, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library. If not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef _MAILUTILS_CIDR_H +#define _MAILUTILS_CIDR_H + +#include <sys/types.h> +#include <sys/socket.h> +#include <mailutils/types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#define MU_INADDR_BYTES 16 + +struct mu_cidr +{ + int family; + int len; + unsigned char address[MU_INADDR_BYTES]; + unsigned char netmask[MU_INADDR_BYTES]; +}; + +#define MU_CIDR_MAXBUFSIZE 81 + +int mu_cidr_from_sockaddr (struct mu_cidr *cp, const struct sockaddr *sa); +int mu_cidr_from_string (struct mu_cidr *cp, const char *str); + +#define MU_CIDR_FMT_ADDRONLY 0x01 + +int mu_cidr_to_string (struct mu_cidr *cidr, int flags, char *buf, size_t size, + size_t *pret); +int mu_cidr_format (struct mu_cidr *, int flags, char **pbuf); +int mu_cidr_to_sockaddr (struct mu_cidr *, struct sockaddr **sa); + +int mu_cidr_match (struct mu_cidr *a, struct mu_cidr *b); + +int _mu_inaddr_to_bytes (int af, void *buf, unsigned char *bytes); + +#ifdef __cplusplus +} +#endif + +#endif /* _MA |