diff -urpN popa3d-0.6.3.orig/params.h popa3d-0.6.3/params.h --- popa3d-0.6.3.orig/params.h Sat Apr 12 16:16:01 2003 +++ popa3d-0.6.3/params.h Wed Sep 24 14:53:08 2003 @@ -18,6 +18,11 @@ #if POP_STANDALONE /* + * Enable IPv6 support? + */ +#define HAVE_INET6 1 + +/* * Should the command line options be supported? * If enabled, popa3d will default to inetd mode and will require a -D * to actually enable the standalone mode. @@ -28,6 +33,7 @@ * The address and port to listen on. */ #define DAEMON_ADDR "0.0.0.0" /* INADDR_ANY */ +#define DAEMON_ADDR6 "[::]" /* INADDR_ANY for IPv6 */ #define DAEMON_PORT 110 /* diff -urpN popa3d-0.6.3.orig/standalone.c popa3d-0.6.3/standalone.c --- popa3d-0.6.3.orig/standalone.c Sun Mar 9 20:34:23 2003 +++ popa3d-0.6.3/standalone.c Wed Sep 24 14:50:48 2003 @@ -15,12 +15,14 @@ #include #include #include +#include #include #include #include #include #include #include +#include #if DAEMON_LIBWRAP #include @@ -29,6 +31,12 @@ int deny_severity = SYSLOG_PRI_HI; #endif /* + * XXX + * Hardcoded, but sufficient for me :) + */ +#define DEVICE "eth0" + +/* * These are defined in pop_root.c. */ extern int log_error(char *s); @@ -45,6 +53,9 @@ typedef volatile sig_atomic_t va_int; */ static struct { struct in_addr addr; /* Source IP address */ +#if HAVE_INET6 + struct in6_addr addr6; /* Source IPv6 address */ +#endif volatile int pid; /* PID of the server, or 0 for none */ clock_t start; /* When the server was started */ clock_t log; /* When we've last logged a failure */ @@ -110,8 +121,15 @@ int main(void) { int true = 1; int sock, new; +#if !HAVE_INET6 struct sockaddr_in addr; int addrlen; +#else + struct sockaddr_in6 addr6; + struct ifreq ifr; + char temp[24]; + int addrlen6; +#endif int pid; struct tms buf; clock_t now, log; @@ -119,19 +137,46 @@ int main(void) if (do_pop_startup()) return 1; +#if HAVE_INET6 + if ((sock = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP)) < 0) + return log_error("socket"); +#else if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) return log_error("socket"); +#endif if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&true, sizeof(true))) return log_error("setsockopt"); +#if !HAVE_INET6 memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = inet_addr(DAEMON_ADDR); addr.sin_port = htons(DAEMON_PORT); - if (bind(sock, (struct sockaddr *)&addr, sizeof(addr))) + +#else + memset(&addr6, 0, sizeof(addr6)); + addr6.sin6_family = AF_INET6; + addr6.sin6_port = htons(DAEMON_PORT); + + if (inet_pton(AF_INET6, DAEMON_ADDR6, &addr6.sin6_addr) < 0) + return log_error("inet_pton"); + + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_name, DEVICE, sizeof(ifr.ifr_name)); + if (ioctl(sock, SIOCGIFINDEX, &ifr) < 0) + return log_error("ioctl"); + +#endif + +#if HAVE_INET6 + if (bind(sock, (struct sockaddr *)&addr6, sizeof(addr6))) { +#else + if (bind(sock, (struct sockaddr *)&addr, sizeof(addr))) { return log_error("bind"); +#endif + } if (listen(sock, MAX_BACKLOG)) return log_error("listen"); @@ -168,8 +213,13 @@ int main(void) if (new > 0) if (close(new)) return log_error("close"); +#if !HAVE_INET6 addrlen = sizeof(addr); new = accept(sock, (struct sockaddr *)&addr, &addrlen); +#else + addrlen6 = sizeof(addr6); + new = accept(sock, (struct sockaddr *)&addr6, &addrlen6); +#endif /* * I wish there was a portable way to classify errno's... In this case, @@ -191,9 +241,13 @@ int main(void) if (sessions[i].pid || (sessions[i].start && now - sessions[i].start < MIN_DELAY * CLK_TCK)) { - if (sessions[i].addr.s_addr == - addr.sin_addr.s_addr) - if (++n >= MAX_SESSIONS_PER_SOURCE) break; +#if !HAVE_INET6 + if (sessions[i].addr.s_addr == addr.sin_addr.s_addr) + if (++n >= MAX_SESSIONS_PER_SOURCE) break; +#else + if (sessions[i].addr6.s6_addr == addr6.sin6_addr.s6_addr) + if (++n >= MAX_SESSIONS_PER_SOURCE) break; +#endif } else if (j < 0) j = i; } @@ -202,9 +256,15 @@ int main(void) if (!sessions[i].log || now < sessions[i].log || now - sessions[i].log >= MIN_DELAY * CLK_TCK) { +#if !HAVE_INET6 syslog(SYSLOG_PRI_HI, "%s: per source limit reached", inet_ntoa(addr.sin_addr)); +#else + syslog(SYSLOG_PRI_HI, + "%s: per source limit reached", + inet_ntop(AF_INET6, &addr6.sin6_addr, temp, sizeof(temp))); +#endif sessions[i].log = now; } continue; @@ -213,9 +273,15 @@ int main(void) if (j < 0) { if (!log || now < log || now - log >= MIN_DELAY * CLK_TCK) { +#if !HAVE_INET6 syslog(SYSLOG_PRI_HI, "%s: sessions limit reached", inet_ntoa(addr.sin_addr)); +#else + syslog(SYSLOG_PRI_HI, + "%s: sessions limit reached", + inet_ntop(AF_INET6, &addr6.sin6_addr, temp, sizeof(temp))); +#endif log = now; } continue; @@ -223,8 +289,13 @@ int main(void) switch ((pid = fork())) { case -1: +#if !HAVE_INET6 syslog(SYSLOG_PRI_ERROR, "%s: fork: %m", inet_ntoa(addr.sin_addr)); +#else + syslog(SYSLOG_PRI_ERROR, "%s: fork: %m", + inet_ntop(AF_INET6, &addr6.sin6_addr, temp, sizeof(temp))); +#endif break; case 0: @@ -232,8 +303,14 @@ int main(void) #if DAEMON_LIBWRAP check_access(new); #endif +#if !HAVE_INET6 syslog(SYSLOG_PRI_LO, "Session from %s", inet_ntoa(addr.sin_addr)); +#else + syslog(SYSLOG_PRI_LO, "Session from %s", + inet_ntop(AF_INET6, &addr6.sin6_addr, temp, sizeof(temp))); +#endif + if (dup2(new, 0) < 0) return log_error("dup2"); if (dup2(new, 1) < 0) return log_error("dup2"); if (dup2(new, 2) < 0) return log_error("dup2"); @@ -241,7 +318,11 @@ int main(void) return do_pop_session(); default: +#if !HAVE_INET6 sessions[j].addr = addr.sin_addr; +#else + sessions[j].addr6 = addr6.sin6_addr; +#endif sessions[j].pid = pid; sessions[j].start = now; sessions[j].log = 0;