diff options
Diffstat (limited to 'smtpd/to.c')
-rw-r--r-- | smtpd/to.c | 61 |
1 files changed, 57 insertions, 4 deletions
@@ -18,6 +18,8 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include "includes.h" + #include <sys/types.h> #include <sys/queue.h> #include <sys/tree.h> @@ -56,12 +58,14 @@ static int alias_is_filename(struct expandnode *, const char *, size_t); static int alias_is_include(struct expandnode *, const char *, size_t); static int alias_is_error(struct expandnode *, const char *, size_t); +static int broken_inet_net_pton_ipv6(const char *, void *, size_t); + const char * sockaddr_to_text(struct sockaddr *sa) { static char buf[NI_MAXHOST]; - if (getnameinfo(sa, sa->sa_len, buf, sizeof(buf), NULL, 0, + if (getnameinfo(sa, SA_LEN(sa), buf, sizeof(buf), NULL, 0, NI_NUMERICHOST)) return ("(unknown)"); else @@ -75,7 +79,9 @@ in6addr_to_text(const struct in6_addr *addr) uint16_t tmp16; memset(&sa_in6, 0, sizeof(sa_in6)); +#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN sa_in6.sin6_len = sizeof(sa_in6); +#endif sa_in6.sin6_family = AF_INET6; memcpy(&sa_in6.sin6_addr, addr, sizeof(sa_in6.sin6_addr)); @@ -192,15 +198,20 @@ time_to_text(time_t when) char *day[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; char *month[] = {"Jan","Feb","Mar","Apr","May","Jun", "Jul","Aug","Sep","Oct","Nov","Dec"}; - char *tz; + const char *tz; long offset; lt = localtime(&when); if (lt == NULL || when == 0) fatalx("time_to_text: localtime"); +#if HAVE_STRUCT_TM_TM_GMTOFF offset = lt->tm_gmtoff; tz = lt->tm_zone; +#elif defined HAVE_DECL_ALTZONE && defined HAVE_DECL_TIMEZONE + offset = lt->tm_isdst > 0 ? altzone : timezone; + tz = lt->tm_isdst > 0 ? tzname[1] : tzname[0]; +#endif /* We do not use strftime because it is subject to locale substitution*/ if (!bsnprintf(buf, sizeof(buf), @@ -282,15 +293,25 @@ text_to_netaddr(struct netaddr *netaddr, const char *s) if (bits != -1) { ssin.sin_family = AF_INET; memcpy(&ss, &ssin, sizeof(ssin)); +#ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN ss.ss_len = sizeof(struct sockaddr_in); +#endif } else { bits = inet_net_pton(AF_INET6, s, &ssin6.sin6_addr, sizeof(struct in6_addr)); - if (bits == -1) - return 0; + if (bits == -1) { + if (errno != EAFNOSUPPORT) + return 0; + bits = broken_inet_net_pton_ipv6(s, &ssin6.sin6_addr, + sizeof(struct in6_addr)); + if (bits == -1) + return 0; + } ssin6.sin6_family = AF_INET6; memcpy(&ss, &ssin6, sizeof(ssin6)); +#ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN ss.ss_len = sizeof(struct sockaddr_in6); +#endif } netaddr->ss = ss; @@ -809,3 +830,35 @@ alias_is_error(struct expandnode *alias, const char *line, size_t len) alias->type = EXPAND_ERROR; return 1; } + +static int +broken_inet_net_pton_ipv6(const char *src, void *dst, size_t size) +{ + int ret; + int bits; + char buf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255:255:255:255/128")]; + char *sep; + const char *errstr; + + if (strlcpy(buf, src, sizeof buf) >= sizeof buf) { + errno = EMSGSIZE; + return (-1); + } + + sep = strchr(buf, '/'); + if (sep != NULL) + *sep++ = '\0'; + + ret = inet_pton(AF_INET6, buf, dst); + if (ret != 1) + return (-1); + + if (sep == NULL) + return 128; + + bits = strtonum(sep, 0, 128, &errstr); + if (errstr) + return (-1); + + return bits; +} |