Index: standalone.c =================================================================== RCS file: /cvsroot/apps/popa3d/standalone.c,v retrieving revision 1.1.1.1 retrieving revision 1.4 diff -u -r1.1.1.1 -r1.4 --- standalone.c 28 Sep 2002 04:26:00 -0000 1.1.1.1 +++ standalone.c 28 Sep 2002 06:12:39 -0000 1.4 @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -34,6 +35,7 @@ extern int log_error(char *s); extern int do_pop_startup(void); extern int do_pop_session(void); +extern int af; typedef sig_atomic_t a_int; typedef volatile a_int va_int; @@ -45,7 +47,7 @@ * information about sessions that we could have allowed to proceed. */ static struct { - struct in_addr addr; /* Source IP address */ + char addr[NI_MAXHOST]; /* Source IP address */ a_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 */ @@ -111,28 +113,56 @@ { int true = 1; int sock, new; - struct sockaddr_in addr; + struct sockaddr_storage addr; int addrlen; int pid; struct tms buf; clock_t now; int i, j, n; + struct addrinfo hints, *res; + char hbuf[NI_MAXHOST]; + char sbuf[NI_MAXSERV]; + int error; if (do_pop_startup()) return 1; if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) return log_error("socket"); + snprintf(sbuf, sizeof(sbuf), "%u", DAEMON_PORT); + memset(&hints, 0, sizeof(hints)); + hints.ai_socktype = SOCK_STREAM; + hints.ai_family = af; + hints.ai_flags = AI_PASSIVE; + error = getaddrinfo(NULL, sbuf, &hints, &res); + if (error) + return log_error("getaddrinfo"); + + sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + if (sock < 0) { + freeaddrinfo(res); + return log_error("socket"); + } + if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, - (void *)&true, sizeof(true))) + (void *)&true, sizeof(true))) { + freeaddrinfo(res); return log_error("setsockopt"); + } - 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))) +#ifdef IPV6_V6ONLY + if (res->ai_family == AF_INET6 && setsockopt(sock, IPPROTO_IPV6, + IPV6_V6ONLY, (void *)&true, sizeof(true))) { + freeaddrinfo(res); + return log_error("setsockopt"); + } +#endif + + if (bind(sock, res->ai_addr, res->ai_addrlen)) { + freeaddrinfo(res); return log_error("bind"); + } + freeaddrinfo(res); if (listen(sock, MAX_BACKLOG)) return log_error("listen"); @@ -170,6 +200,12 @@ addrlen = sizeof(addr); new = accept(sock, (struct sockaddr *)&addr, &addrlen); + error = getnameinfo((struct sockaddr *)&addr, addrlen, + hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST); + if (error) + ; /* XXX */ + + /* * I wish there was a portable way to classify errno's... In this case, * it appears to be better to risk eating up the CPU on a fatal error @@ -189,9 +225,9 @@ 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 (strcmp(sessions[i].addr, hbuf) == 0) + if (++n >= MAX_SESSIONS_PER_SOURCE) + break; } else if (j < 0) j = i; } @@ -202,7 +238,7 @@ now - sessions[i].log >= MIN_DELAY * CLK_TCK) { syslog(SYSLOG_PRI_HI, "%s: per source limit reached", - inet_ntoa(addr.sin_addr)); + hbuf); sessions[i].log = now; } continue; @@ -210,14 +246,13 @@ if (j < 0) { syslog(SYSLOG_PRI_HI, "%s: sessions limit reached", - inet_ntoa(addr.sin_addr)); + hbuf); continue; } switch ((pid = fork())) { case -1: - syslog(SYSLOG_PRI_ERROR, "%s: fork: %m", - inet_ntoa(addr.sin_addr)); + syslog(SYSLOG_PRI_ERROR, "%s: fork: %m", hbuf); break; case 0: @@ -226,7 +261,7 @@ check_access(new); #endif syslog(SYSLOG_PRI_LO, "Session from %s", - inet_ntoa(addr.sin_addr)); + hbuf); 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"); @@ -234,7 +269,8 @@ return do_pop_session(); default: - sessions[j].addr = addr.sin_addr; + strlcpy(sessions[j].addr, hbuf, + sizeof(sessions[j].addr)); (va_int)sessions[j].pid = pid; sessions[j].start = now; sessions[j].log = 0; Index: startup.c =================================================================== RCS file: /cvsroot/apps/popa3d/startup.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- startup.c 28 Sep 2002 04:26:02 -0000 1.1.1.1 +++ startup.c 28 Sep 2002 06:12:39 -0000 1.2 @@ -6,6 +6,7 @@ #if POP_OPTIONS +#include #include #include #include @@ -24,6 +25,8 @@ static char *progname; #endif +int af = AF_INET; + static void usage(void) { fprintf(stderr, "Usage: %s [-D]\n", progname); @@ -40,10 +43,16 @@ progname = POP_SERVER; #endif - while ((c = getopt(argc, argv, "D")) != -1) { + while ((c = getopt(argc, argv, "D46")) != -1) { switch (c) { case 'D': standalone++; + break; + case '4': + af = AF_INET; + break; + case '6': + af = AF_INET6; break; default: Index: virtual.c =================================================================== RCS file: /cvsroot/apps/popa3d/virtual.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- virtual.c 28 Sep 2002 04:26:02 -0000 1.1.1.1 +++ virtual.c 28 Sep 2002 06:05:00 -0000 1.2 @@ -38,20 +38,28 @@ return 0; } -static char *lookup(void) +static const char *lookup(void) { - struct sockaddr_in sin; + struct sockaddr_storage ss; int length; + int error; + static char hbuf[NI_MAXHOST]; - length = sizeof(sin); - if (getsockname(0, (struct sockaddr *)&sin, &length)) { + length = sizeof(ss); + if (getsockname(0, (struct sockaddr *)&ss, &length)) { if (errno == ENOTSOCK) return ""; log_error("getsockname"); return NULL; } - if (length != sizeof(sin) || sin.sin_family != AF_INET) return NULL; - return inet_ntoa(sin.sin_addr); + error = getnameinfo((struct sockaddr *)&ss, length, hbuf, sizeof(hbuf), + NULL, 0, NI_NUMERICHOST); + if (error) { + /* logging? */ + return NULL; + } + + return hbuf; } static int is_valid_user(char *user)