1 diff -Nur inn-2.3.2.orig/authprogs/auth_pass.c inn-2.3.2/authprogs/auth_pass.c
2 --- inn-2.3.2.orig/authprogs/auth_pass.c Thu May 3 22:27:32 2001
3 +++ inn-2.3.2/authprogs/auth_pass.c Tue Jun 19 16:06:41 2001
12 - struct sockaddr_in sin;
13 + struct sockaddr_storage ss;
19 * Get the hostname of the peer.
21 - length = sizeof(sin);
22 - if (getpeername(0, (struct sockaddr *)&sin, &length) < 0) {
23 + length = sizeof(ss);
24 + if (getpeername(0, (struct sockaddr *)&ss, &length) < 0) {
26 fprintf(stderr, "cant getpeername()::%s:+:!*\n", username);
29 (void)strcpy(peername, "stdin");
30 - } else if (sin.sin_family != AF_INET) {
32 + } else if (ss.ss_family != AF_INET && ss.ss_family != AF_INET6) {
34 + } else if (ss.ss_family != AF_INET) {
36 fprintf(stderr, "Bad address family %ld::%s:+:!*\n",
37 - (long)sin.sin_family, username);
38 + (long)ss.ss_family, username);
40 - } else if ((hp = gethostbyaddr((char *)&sin.sin_addr, sizeof(sin.sin_addr), AF_INET)) == NULL) {
41 - strcpy(peername, inet_ntoa(sin.sin_addr));
44 +#ifdef HAVE_SOCKADDR_LEN
45 + getnameinfo((struct sockaddr *)&ss, ss.ss_len, peername,
46 + sizeof(peername), NULL, 0, 0);
48 + getnameifno((struct sockaddr *)&ss, SA_LEN((struct sockaddr *)&ss),
49 + peername, sizeof(peername), NULL, 0, 0);
50 +#endif /* HAVE_SOCKADDR_LEN */
51 + if (strchr(peername, ':') != NULL) {
52 + sprintf(tmpname, "[%s]", peername);
53 + if (strlen(tmpname) < sizeof(peername))
54 + strcpy(peername, tmpname);
58 + } else if ((hp = gethostbyaddr((char *)&((struct sockaddr_in *)&ss)-sin_addr, sizeof(struct in_addr), AF_INET)) == NULL) {
59 + strcpy(peername, inet_ntoa(((struct sockaddr *)&ss)->sin_addr));
61 strncpy(peername, hp->h_name, sizeof(peername));
66 * Get the user name in the passwd file.
67 diff -Nur inn-2.3.2.orig/configure.in inn-2.3.2/configure.in
68 --- inn-2.3.2.orig/configure.in Thu May 3 22:27:32 2001
69 +++ inn-2.3.2/configure.in Tue Jun 19 16:06:41 2001
74 +dnl === part for IPv6 support ===
75 +AC_MSG_CHECKING([whether to enable ipv6])
77 +[ --enable-ipv6 Enable ipv6 (with ipv4) support
78 + --disable-ipv6 Disable ipv6 support],
79 +[ case "$enableval" in
84 + *) AC_MSG_RESULT(yes)
85 + AC_DEFINE(ENABLE_IPV6)
90 + AC_TRY_RUN([ /* AF_INET6 avalable check */
91 +#include <sys/types.h>
92 +#include <sys/socket.h>
95 + if (socket(AF_INET6, SOCK_STREAM, 0) < 0)
102 + AC_DEFINE(ENABLE_IPV6)
113 +if test "$ipv6" = "yes"; then
114 + AC_MSG_CHECKING([IPv6 stack type])
115 + for i in inria kame linux-glibc linux-inet6 toshiba v6d zeta; do
118 + dnl http://www.kame.net/
119 + AC_EGREP_CPP(%%%yes%%%, [dnl
120 +#include <netinet/in.h>
121 +#ifdef IPV6_INRIA_VERSION
125 + CFLAGS="-DINET6 $CFLAGS"])
128 + dnl http://www.kame.net/
129 + AC_EGREP_CPP(%%%yes%%%, [dnl
130 +#include <netinet/in.h>
135 + CFLAGS="-DINET6 $CFLAGS"])
138 + dnl http://www.v6.linux.or.jp/
139 + AC_EGREP_CPP(%%%yes%%%, [dnl
140 +#include <features.h>
141 +#if defined(__GLIBC__) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1
145 + CFLAGS="-DINET6 $CFLAGS"])
148 + dnl http://www.v6.linux.or.jp/
149 + if test -d /usr/inet6; then
152 + ipv6libdir=/usr/inet6/lib
153 + CFLAGS="-DINET6 -I/usr/inet6/include $CFLAGS"
157 + AC_EGREP_CPP(%%%yes%%%, [dnl
158 +#include <sys/param.h>
159 +#ifdef _TOSHIBA_INET6
164 + ipv6libdir=/usr/local/v6/lib;
165 + CFLAGS="-DINET6 $CFLAGS"])
168 + AC_EGREP_CPP(%%%yes%%%, [dnl
169 +#include </usr/local/v6/include/sys/v6config.h>
175 + ipv6libdir=/usr/local/v6/lib;
176 + CFLAGS="-I/usr/local/v6/include $CFLAGS"])
179 + AC_EGREP_CPP(%%%yes%%%, [dnl
180 +#include <sys/param.h>
181 +#ifdef _ZETA_MINAMI_INET6
186 + ipv6libdir=/usr/local/v6/lib;
187 + CFLAGS="-DINET6 $CFLAGS"])
190 + if test "$ipv6type" != "unknown"; then
194 + AC_MSG_RESULT($ipv6type)
197 +if test "$ipv6" = "yes"; then
198 + if test -d /usr/local/v6/lib; then
199 + ac_inet6_LDFLAGS="inet6"
200 + ipv6libdir=/usr/local/v6/lib
201 + LDFLAGS="$LDFLAGS -L/usr/local/v6/lib"
202 + AC_CHECK_LIB(inet6, getaddrinfo, , ipv6lib="$ac_inet6_LDFLAGS")
204 + AC_CHECK_FUNCS(getaddrinfo)
208 +if test "$ipv6" = "yes" -a "$ipv6lib" != "none"; then
209 + if test -d $ipv6libdir -a -f $ipv6libdir/lib$ipv6lib.a; then
210 + LIBS="-L$ipv6libdir -l$ipv6lib $LIBS"
215 +dnl checking for sa_len;
216 +dnl the following check says 'yes' if your system has __libc_sa_len
217 +dnl AC_EGREP_HEADER(sa_len, sys/socket.h,
218 +dnl [ AC_DEFINE(HAVE_SOCKADDR_LEN) AC_MSG_RESULT(yes)], AC_MSG_RESULT(no))
219 +AC_MSG_CHECKING([whether struct sockaddr has sa_len])
221 +#include <sys/types.h>
222 +#include <sys/socket.h>
228 + AC_DEFINE(HAVE_SOCKADDR_LEN)],
231 +AC_MSG_CHECKING([whether sys/socket.h has SA_LEN])
233 +#include <sys/types.h>
234 +#include <sys/socket.h>
236 +int main(){ int i = SA_LEN((struct sockaddr*)&sa); return 0;}
239 + AC_DEFINE(HAVE_SA_LEN)],
240 +AC_MSG_RESULT(no),AC_MSG_RESULT(no))
242 +AC_MSG_CHECKING([whether sys/socket.h has struct sockaddr_storage])
244 +#include <sys/types.h>
245 +#include <sys/socket.h>
247 +struct sockaddr_storage ss;
250 + AC_DEFINE(HAVE_SOCKADDR_STORAGE)],
253 +AC_MSG_CHECKING([whether struct sockaddr_storage has __ss_family])
255 +#include <sys/types.h>
256 +#include <sys/socket.h>
258 +struct sockaddr_storage ss;
259 +int i = ss.__ss_family;
262 + AC_DEFINE(HAVE_2553_STYLE_SS_FAMILY)],
263 +AC_MSG_RESULT(no), AC_MSG_RESULT(no))
265 +dnl === end of part for IPv6 support ===
267 dnl Checks for pathnames.
269 dnl See if we have ctags; if so, set CTAGS to its full path plus the -t -w
270 @@ -1061,7 +1254,7 @@
271 AC_CHECK_FUNCS(atexit fchmod fcntl gethostname getpagesize getrusage \
272 getspnam gettimeofday mkfifo setbuffer sigaction setsid \
273 socketpair statvfs strcspn strncasecmp strstr strtoul \
275 + symlink waitpid inet_ntoa)
277 dnl We only care if we have setreuid() if we don't have seteuid().
278 AC_CHECK_FUNCS(seteuid setreuid, break)
279 @@ -1095,7 +1288,7 @@
282 dnl If we can't find any of the following, we have replacements for them.
283 -AC_REPLACE_FUNCS(fseeko ftello getopt inet_aton inet_ntoa pread pwrite \
284 +AC_REPLACE_FUNCS(fseeko ftello getopt inet_aton pread pwrite \
285 strcasecmp strdup strerror strspn setenv hstrerror)
287 dnl If replacing fseeko or ftello, see if we can use fsetpos/fgetpos.
288 diff -Nur inn-2.3.2.orig/doc/man/inn.conf.5 inn-2.3.2/doc/man/inn.conf.5
289 --- inn-2.3.2.orig/doc/man/inn.conf.5 Thu May 3 22:27:32 2001
290 +++ inn-2.3.2/doc/man/inn.conf.5 Tue Jun 19 16:06:41 2001
291 @@ -1055,6 +1055,25 @@
292 directory). It must be on the same partition as \fIpathincoming\fR for
293 \&\fIrnews\fR\|(1) to work correctly. The default value is set at configure time
294 and defaults to \fIpathnews\fR/tmp.
295 +.Sh "IPv6 Configurations"
296 +.IX Subsection "IPv6 Configurations"
297 +If your system can use IPv6, the following parameters are available.
298 +.Ip "\fIlistenonipv6\fR" 4
299 +.IX Item "listenonipv6"
300 +If set to true, \fIinnd\fR\|(8) creates an IPv6 socket for waiting connections
302 +.Ip "\fIbindipv6address\fR" 4
303 +.IX Item "bindipv6address"
304 +Which IPv6 address \fIinnd\fR\|(8) should bind itself to. This must be in
305 +numeric IPv6 address format. If set to \f(CW\*(C`all\*(C'\fR or not set, innd
306 +defaults to listening on all interfaces. The default value is unset.
307 +.Ip "\fIsourceipv6address\fR" 4
308 +.IX Item "sourceipv6address"
309 +Which local IPv6 address to bind to outgoing NNTP sockets (used by
310 +\fIinnxmit\fR\|(8) among other programs). This must be in numeric IPv6
311 +address format. If set to \f(CW\*(C`all\*(C'\fR or not set,
312 +the operating system will choose the source IPv6 address for outgoing
313 +connections. The default value is unset.
316 Here is a very minimalist example that only sets those parameters that are
317 diff -Nur inn-2.3.2.orig/include/clibrary.h inn-2.3.2/include/clibrary.h
318 --- inn-2.3.2.orig/include/clibrary.h Thu May 3 22:27:32 2001
319 +++ inn-2.3.2/include/clibrary.h Tue Jun 19 16:06:41 2001
322 extern ssize_t pwrite(int fd, void *buf, size_t nbyte, OFFSET_T offset);
324 -#ifndef HAVE_INET_NTOA
325 -extern char *inet_ntoa();
327 +extern char *Inet_NtoA();
329 extern char *strdup();
331 diff -Nur inn-2.3.2.orig/include/config.h.in inn-2.3.2/include/config.h.in
332 --- inn-2.3.2.orig/include/config.h.in Thu May 3 22:27:32 2001
333 +++ inn-2.3.2/include/config.h.in Tue Jun 19 16:06:41 2001
335 /* All incoming control commands (ctlinnd, etc). */
336 #define L_CC_CMD LOG_INFO
340 +/* sockaddr.sa_len */
341 +#undef HAVE_SOCKADDR_LEN
346 +/* struct sockaddr_storage */
347 +#undef HAVE_SOCKADDR_STORAGE
350 +#undef HAVE_GETADDRINFO
352 +/* sockaddr_storage.__ss_family */
353 +#undef HAVE_2553_STYLE_SS_FAMILY
355 +#ifdef HAVE_2553_STYLE_SS_FAMILY
356 +# define ss_family __ss_family
357 +# define ss_len __ss_len
360 #endif /* !__CONFIG_H__ */
361 diff -Nur inn-2.3.2.orig/include/innconf.h inn-2.3.2/include/innconf.h
362 --- inn-2.3.2.orig/include/innconf.h Thu May 3 22:27:32 2001
363 +++ inn-2.3.2/include/innconf.h Tue Jun 19 16:06:41 2001
365 { _CONF_WIPCHECK, "", 2, 1 },
366 #define _CONF_NNRPPYTHONAUTH "nnrppythonauth"
367 #define CONF_VAR_NNRPPYTHONAUTH 103
368 - { _CONF_NNRPPYTHONAUTH, "", 2, 1 }
369 + { _CONF_NNRPPYTHONAUTH, "", 2, 1 },
370 +#define _CONF_LISTENONIPV6 "listenonipv6"
371 +#define CONF_VAR_LISTENONIPV6 104
372 + { _CONF_LISTENONIPV6, "", 2, 0 },
373 +#define _CONF_BINDIPV6ADDRESS "bindipv6address"
374 +#define CONF_VAR_BINDIPV6ADDRESS 105
375 + { _CONF_BINDIPV6ADDRESS, "", 1, 0 },
376 +#define _CONF_SOURCEIPV6ADDRESS "sourceipv6address"
377 +#define CONF_VAR_SOURCEIPV6ADDRESS 106
378 + { _CONF_SOURCEIPV6ADDRESS, "", 1, 0 }
380 -#define MAX_CONF_VAR 104
381 +#define MAX_CONF_VAR 106
383 diff -Nur inn-2.3.2.orig/include/libinn.h inn-2.3.2/include/libinn.h
384 --- inn-2.3.2.orig/include/libinn.h Thu May 3 22:27:32 2001
385 +++ inn-2.3.2/include/libinn.h Tue Jun 19 16:06:41 2001
387 /* Feed Configuration */
388 int artcutoff; /* Max accepted article age */
389 char *bindaddress; /* Which interface IP to bind to */
390 + char *bindipv6address; /* Which interface IP to bind to */
391 int hiscachesize; /* Size of the history cache in kB */
392 int ignorenewsgroups; /* Propagate cmsgs by affected group? */
393 int immediatecancel; /* Immediately cancel timecaf messages? */
394 @@ -112,11 +113,13 @@
395 int refusecybercancels; /* Reject message IDs with "<cancel."? */
396 int remembertrash; /* Put unwanted article IDs into history */
397 char *sourceaddress; /* Source IP for outgoing NNTP connections */
398 + char *sourceipv6address; /* Source IP for outgoing NNTP connections */
399 int usecontrolchan; /* Use a channel feed for control messages? */
400 int verifycancels; /* Verify cancels against article author */
401 int wanttrash; /* Put unwanted articles in junk */
402 int wipcheck; /* How long to defer other copies of article */
403 int wipexpire; /* How long to keep pending article record */
404 + int listenonipv6; /* Listen on IPv6 socket */
406 /* Article Storage */
407 long cnfscheckfudgesize; /* Additional CNFS integrity checking */
408 diff -Nur inn-2.3.2.orig/include/sa_len.h inn-2.3.2/include/sa_len.h
409 --- inn-2.3.2.orig/include/sa_len.h Thu Jan 1 01:00:00 1970
410 +++ inn-2.3.2/include/sa_len.h Tue Jun 19 16:06:41 2001
413 + * sa_len.h : tiny version of SA_LEN
414 + * (original written by <yoshfuji@ecei.tohoku.ac.jp>)
417 +#include <sys/types.h>
418 +#include <sys/socket.h>
419 +#include <netinet/in.h>
424 +#define SA_LEN(s_) ap_sa_len((s_)->sa_family)
426 +static int ap_sa_len (int af)
429 +#if defined(AF_INET)
431 + return (sizeof(struct sockaddr_in));
432 +#endif /* AF_INET */
435 + return (sizeof(struct sockaddr_in6));
436 +#endif /* AF_INET6 */
437 +#if defined(AF_LOCAL)
439 +#endif /* AF_LOCAL */
440 +#if defined(AF_UNIX) && !(AF_UNIX == AF_LOCAL)
442 +#endif /* AF_UNIX */
443 +#if defined(AF_FILE) && !(AF_FILE == AF_LOCAL)
445 +#endif /* AF_FILE */
446 +#if defined(AF_LOCAL) || defined(AF_UNIX) || defined(AF_FILE)
447 + return (sizeof(struct sockaddr_un));
448 +#endif /* fdefined(AF_LOCAL) || defined(AF_UNIX) || defined(AF_FILE) */
456 +#endif /* SIN6_LEN */
458 diff -Nur inn-2.3.2.orig/include/sockaddr_storage.h inn-2.3.2/include/sockaddr_storage.h
459 --- inn-2.3.2.orig/include/sockaddr_storage.h Thu Jan 1 01:00:00 1970
460 +++ inn-2.3.2/include/sockaddr_storage.h Tue Jun 19 16:06:41 2001
463 +struct sockaddr_storage
465 + RFC2553 proposes struct sockaddr_storage.
466 + This is a placeholder for all sockaddr-variant structures. This is
467 + implemented like follows:
469 + You should use this structure to hold any of sockaddr-variant
472 +#ifndef HAVE_SOCKADDR_STORAGE
474 +struct sockaddr_storage {
475 +#ifdef HAVE_SOCKADDR_LEN
481 + u_char __padding[128 - 2];
487 + Alternatively, you may want to implement sockunion.h, with the
490 + NOTE: For better portability, struct sockaddr_storage should be used.
491 + union sockunion is okay, but is not really portable enough.
495 +#ifdef HAVE_SOCKADDR_LEN
503 + struct sockaddr_in su_sin;
505 + struct sockaddr_in6 su_sin6;
508 +#ifdef HAVE_SOCKADDR_LEN
509 +#define su_len su_si.si_len
511 +#define su_family su_si.si_family
512 +#define su_port su_si.si_port
514 +#endif /* HAVE_SOCKADDR_STORAGE */
515 diff -Nur inn-2.3.2.orig/innd/chan.c inn-2.3.2/innd/chan.c
516 --- inn-2.3.2.orig/innd/chan.c Thu May 3 22:27:32 2001
517 +++ inn-2.3.2/innd/chan.c Tue Jun 19 16:06:41 2001
520 #define PRIORITISE_REMCONN
521 #ifdef PRIORITISE_REMCONN
522 -STATIC int CHANrcfd;
523 -STATIC CHANNEL *CHANrc;
524 +STATIC int CHANrcfd[2];
525 +STATIC CHANNEL *CHANrc[2];
526 #endif /* PRIORITISE_REMCONN */
530 (void)memset((POINTER)CHANtable, 0,
531 (SIZE_T)(CHANtablesize * sizeof *CHANtable));
532 CHANnull.NextLog = innconf->chaninacttime;
533 - CHANnull.Address.s_addr = MyAddress.s_addr;
534 + memcpy((POINTER)&CHANnull.Address, (POINTER)&MyAddress, sizeof MyAddress);
535 for (cp = CHANtable; --i >= 0; cp++)
539 #ifdef PRIORITISE_REMCONN
540 /* Note remconn channel, for efficiency */
541 if (Type == CTremconn) {
544 + if (CHANrc[0] == NULL) {
552 #endif /* PRIORITISE_REMCONN */
555 syslog(L_NOTICE, "%s trace badwrites %d blockwrites %d badreads %d",
556 p, cp->BadWrites, cp->BlockedWrites, cp->BadReads);
557 syslog(L_NOTICE, "%s trace address %s lastactive %ld nextlog %ld",
558 - p, inet_ntoa(cp->Address), cp->LastActive, cp->NextLog);
559 + p, Inet_NtoA(&cp->Address), cp->LastActive, cp->NextLog);
560 if (FD_ISSET(cp->fd, &SCHANmask))
561 syslog(L_NOTICE, "%s trace sleeping %ld 0x%x",
562 p, (long)cp->Waketime, cp->Waker);
566 (void)sprintf(buff, "%s:%d",
567 - cp->Address.s_addr == 0 ? "localhost" : RChostname(cp),
568 + cp->Address.ss_family == 0 ? "localhost" : RChostname(cp),
572 @@ -922,11 +927,14 @@
574 #ifdef PRIORITISE_REMCONN
575 /* Try the remconn channel next. */
576 - if (FD_ISSET(CHANrcfd, &RCHANmask) && FD_ISSET(CHANrcfd, &MyRead)) {
578 - if (count > 3) count = 3; /* might be more requests */
579 - (*CHANrc->Reader)(CHANrc);
580 - FD_CLR(CHANrcfd, &MyRead);
581 + for (i = 0; i < 2; i++) {
582 + if (FD_ISSET(CHANrcfd[i], &RCHANmask) &&
583 + FD_ISSET(CHANrcfd[i], &MyRead)) {
585 + if (count > 3) count = 3; /* might be more requests */
586 + (*CHANrc[i]->Reader)(CHANrc[i]);
587 + FD_CLR(CHANrcfd[i], &MyRead);
590 #endif /* PRIORITISE_REMCONN */
592 diff -Nur inn-2.3.2.orig/innd/innd.c inn-2.3.2/innd/innd.c
593 --- inn-2.3.2.orig/innd/innd.c Thu May 3 22:27:32 2001
594 +++ inn-2.3.2/innd/innd.c Tue Jun 19 16:06:41 2001
597 static char WHEN[] = "PID file";
605 ShouldRenumber = FALSE;
606 ShouldSyntaxCheck = FALSE;
607 logflags = L_OPENLOG_FLAGS | LOG_NOWAIT;
609 + fd[0] = fd[1] = -1;
611 #if defined(DO_FAST_RESOLV)
612 /* We only use FQDN's in the hosts.nntp file. */
613 @@ -680,10 +680,12 @@
615 /* Silently ignore multiple -p flags, in case ctlinnd xexec
616 * called inndstart. */
620 + fd[0] = atoi(optarg);
623 + } else if (fd[1] == -1) {
624 + fd[1] = atoi(optarg);
628 innconf->port = atoi(optarg);
630 syslog(L_FATAL, "%s internal cant stat control directory %m", LogName);
633 - if (fd != -1 && setgid(NewsGID) < 0)
634 + if (fd[0] != -1 && setgid(NewsGID) < 0)
635 syslog(L_ERROR, "%s cant setgid running as %d not %d %m",
636 LogName, (int)getgid(), (int)NewsGID);
645 + if (innconf->listenonipv6 && fd[1] != -1)
651 diff -Nur inn-2.3.2.orig/innd/innd.h inn-2.3.2/innd/innd.h
652 --- inn-2.3.2.orig/innd/innd.h Thu May 3 22:27:32 2001
653 +++ inn-2.3.2/innd/innd.h Tue Jun 19 16:06:41 2001
658 +#include "sockaddr_storage.h"
664 ** Some convenient shorthands.
666 -typedef struct in_addr INADDR;
667 +typedef struct sockaddr_storage INADDR;
670 #define u_long unsigned long
671 diff -Nur inn-2.3.2.orig/innd/inndstart.c inn-2.3.2/innd/inndstart.c
672 --- inn-2.3.2.orig/innd/inndstart.c Thu May 3 22:27:32 2001
673 +++ inn-2.3.2/innd/inndstart.c Tue Jun 19 16:06:41 2001
675 unsigned long address;
677 struct sockaddr_in server;
680 + struct sockaddr_in6 server6;
681 + char p6flag[SMBUF];
689 /* Create a socket and name it. innconf->bindaddress controls what
690 address we bind as, defaulting to INADDR_ANY. */
694 + if (innconf->listenonipv6) {
695 + s6 = socket(AF_INET6, SOCK_STREAM, 0);
697 + syslog(L_FATAL, "can't open inet6 socket: %m");
702 + if (setsockopt(s6, SOL_SOCKET, SO_REUSEADDR, (char *)&i, sizeof i) < 0)
703 + syslog(L_ERROR, "can't setsockopt: %m");
705 + memset(&server6, 0, sizeof server6);
706 + server6.sin6_port = htons(port);
707 + server6.sin6_family = AF_INET6;
708 + server6.sin6_addr = in6addr_any;
709 + p = innconf->bindipv6address;
710 + if (p && !EQ(p, "all") && !EQ(p, "any")) {
711 + if (inet_pton(AF_INET6, p, &server6.sin6_addr) < 1) {
712 + syslog(L_FATAL, "invalid bindipv6address in inn.conf (%s)", p);
717 +#ifdef HAVE_SOCKADDR_LEN
718 + server6.sin6_len = sizeof server6;
720 + for (i = 1; i < argc; i++) {
721 + if (EQn("-6", argv[i], 2)) {
722 + if (strlen(argv[i]) > 2) {
726 + if (argv[i] == NULL) {
727 + syslog(L_FATAL, "missing address after -6");
728 + fprintf(stderr, "Missing address after -6\n");
733 + if (inet_pton(AF_INET6, p, &server6) < 1) {
734 + syslog(L_FATAL, "invalid ipv6 address %s", p);
735 + fprintf(stderr, "Invalid ipv6 address %s\n", p);
741 + if (bind(s6, (struct sockaddr *)&server6, sizeof server6) < 0) {
742 + syslog(L_FATAL, "can't bind: %m");
746 + if (!innconf->listenonipv6 || !in6any)
749 s = socket(AF_INET, SOCK_STREAM, 0);
751 syslog(L_FATAL, "can't open socket: %m");
753 syslog(L_FATAL, "can't bind: %m");
759 /* Now, permanently drop privileges. */
760 if (setgid(news_gid) < 0 || getgid() != news_gid) {
761 @@ -330,24 +396,47 @@
763 /* Build the argument vector for innd. Pass -p<port> to innd to tell it
764 what port we just created and bound to for it. */
765 - innd_argv = NEW(char *, 1 + argc + 1);
767 + if (innconf->listenonipv6 && !in6any)
768 + innd_argv = NEW(char *, 1 + argc + 2);
771 + innd_argv = NEW(char *, 1 + argc + 1);
774 innd_argv[i++] = DEBUGGER;
775 innd_argv[i++] = cpcatpath(innconf->pathbin, "innd");
778 + if (innconf->listenonipv6)
779 + printf("When starting innd, use -d -p%d [-p%d]\n", s6, s);
782 printf("When starting innd, use -dp%d\n", s);
784 - sprintf(pflag, "-p%d", s);
785 innd_argv[i++] = cpcatpath(innconf->pathbin, "innd");
786 - innd_argv[i++] = pflag;
788 + if (innconf->listenonipv6) {
789 + sprintf(p6flag, "-p%d", s6);
790 + innd_argv[i++] = p6flag;
792 + if (innconf->listenonipv6 && in6any)
794 + sprintf(pflag, "-p-1");
795 + innd_argv[i++] = pflag;
799 + sprintf(pflag, "-p%d", s);
800 + innd_argv[i++] = pflag;
803 - /* Don't pass along -p, -P, or -I. Check the length of the argument
804 + /* Don't pass along -p, -P, -6, or -I. Check the length of the argument
805 string, and if it's == 2 (meaning there's nothing after the -p or -P
806 - or -I), skip the next argument too, to support leaving a space
807 + or -6 or -I), skip the next argument too, to support leaving a space
808 between the argument and the value. */
809 for (j = 1; j < argc; j++) {
810 - if (argv[j][0] == '-' && strchr("pPI", argv[j][1])) {
811 + if (argv[j][0] == '-' && strchr("6pPI", argv[j][1])) {
812 if (strlen(argv[j]) == 2) j++;
815 diff -Nur inn-2.3.2.orig/innd/lc.c inn-2.3.2/innd/lc.c
816 --- inn-2.3.2.orig/innd/lc.c Thu May 3 22:27:32 2001
817 +++ inn-2.3.2/innd/lc.c Tue Jun 19 16:06:41 2001
821 if ((new = NCcreate(fd, FALSE, TRUE)) != NULL) {
822 - new->Address.s_addr = MyAddress.s_addr;
823 + memcpy(&new->Address, &MyAddress, sizeof(MyAddress));
824 syslog(L_NOTICE, "%s connected %d", "localhost", new->fd);
825 NCwritereply(new, (char *)NCgreeting);
827 diff -Nur inn-2.3.2.orig/innd/rc.c inn-2.3.2/innd/rc.c
828 --- inn-2.3.2.orig/innd/rc.c Thu May 3 22:27:32 2001
829 +++ inn-2.3.2/innd/rc.c Tue Jun 19 16:06:41 2001
831 # define INADDR_NONE 0xffffffff
834 -#define COPYADDR(dest, src) \
835 - (void)memcpy((POINTER)dest, (POINTER)src, (SIZE_T)sizeof (INADDR))
837 #define TEST_CONFIG(a, b) \
839 b = ((peer_params.Keysetbit & (1 << a)) != 0) ? TRUE : FALSE; \
841 STATIC char *RCslaveflag;
842 STATIC char *RCnnrpd = NULL;
843 STATIC char *RCnntpd = NULL;
844 -STATIC CHANNEL *RCchan;
845 +STATIC CHANNEL *RCchan[2];
846 STATIC REMOTEHOST_DATA *RCpeerlistfile;
847 STATIC REMOTEHOST *RCpeerlist;
848 STATIC int RCnpeerlist;
850 STATIC int remotecount;
851 STATIC int remotefirst;
854 +COPYADDR(INADDR *dst, char *src)
856 + struct sockaddr_in sin;
858 + memset(&sin, 0, sizeof(sin));
859 + sin.sin_family = AF_INET;
860 +#if defined(HAVE_SOCKADDR_LEN)
861 + sin.sin_len = sizeof(sin);
862 +#endif /* defined(HAVE_SOCKADDR_LEN) */
863 + (void)memcpy((POINTER)&sin.sin_addr, src, sizeof(sin.sin_addr));
865 + (void)memcpy((POINTER)dst, (POINTER)&sin, sizeof(sin));
869 +RCaddressmatch(INADDR *cp, INADDR *rp)
872 + struct sockaddr_in *sin_cp, *sin_rp;
873 + struct sockaddr_in6 *sin6_cp, *sin6_rp;
875 + if (cp->ss_family == AF_INET6 && rp->ss_family == AF_INET) {
876 + sin6_cp = (struct sockaddr_in6 *)cp;
877 + sin_rp = (struct sockaddr_in *)rp;
878 + if (IN6_IS_ADDR_V4MAPPED(&sin6_cp->sin6_addr) &&
879 + memcmp(&sin6_cp->sin6_addr.s6_addr[12], &sin_rp->sin_addr.s_addr,
880 + sizeof(struct in_addr)) == 0)
884 + } else if (cp->ss_family == AF_INET && rp->ss_family == AF_INET6) {
885 + sin_cp = (struct sockaddr_in *)cp;
886 + sin6_rp = (struct sockaddr_in6 *)rp;
887 + if (IN6_IS_ADDR_V4MAPPED(&sin6_rp->sin6_addr) &&
888 + memcmp(&sin6_rp->sin6_addr.s6_addr[12], &sin_cp->sin_addr.s_addr,
889 + sizeof(struct in_addr)) == 0)
895 + if (cp->ss_family != rp->ss_family)
898 + switch (cp->ss_family) {
900 + if (((struct sockaddr_in *)cp)->sin_addr.s_addr ==
901 + ((struct sockaddr_in *)rp)->sin_addr.s_addr)
906 + if (IN6_ARE_ADDR_EQUAL(&((struct sockaddr_in6 *)cp)->sin6_addr,
907 + &((struct sockaddr_in6 *)rp)->sin6_addr))
917 * Split text into comma-separated fields. Return an allocated
922 -RCfix_options(int fd, struct sockaddr_in *remote)
923 +RCfix_options(int fd, INADDR *remote)
926 unsigned char optbuf[BUFSIZ / 3], *cp;
927 @@ -177,10 +236,22 @@
931 - if ((ip = getprotobyname("ip")) != 0)
932 - ipproto = ip->p_proto;
934 - ipproto = IPPROTO_IP;
935 + switch (remote->ss_family) {
937 + if ((ip = getprotobyname("ip")) != 0)
938 + ipproto = ip->p_proto;
940 + ipproto = IPPROTO_IP;
944 + if ((ip = getprotobyname("ipv6")) != 0)
945 + ipproto = ip->p_proto;
947 + ipproto = IPPROTO_IPV6;
949 +#endif /* defined(INET6) */
952 if (getsockopt(fd, ipproto, IP_OPTIONS, (char *) optbuf, &optsize) == 0
955 sprintf(lp, " %2.2x", *cp);
957 "connect from %s with IP options (ignored):%s",
958 - inet_ntoa(remote->sin_addr), lbuf);
959 + Inet_NtoA(remote), lbuf);
960 if (setsockopt(fd, ipproto, IP_OPTIONS, (char *) 0, optsize) != 0) {
961 syslog(LOG_ERR, "setsockopt IP_OPTIONS NULL: %m");
963 @@ -210,17 +281,17 @@
966 for (rp = RCpeerlist, i = RCnpeerlist; --i >= 0; rp++)
967 - if (cp->Address.s_addr == rp->Address.s_addr) {
968 + if (RCaddressmatch(&cp->Address, &rp->Address)) {
969 if (rp->Password[0] == '\0' || EQ(pass, rp->Password))
971 syslog(L_ERROR, "%s (%s) bad_auth", rp->Label,
972 - inet_ntoa(cp->Address));
973 + Inet_NtoA(&cp->Address));
978 /* Not found in our table; this can't happen. */
979 - syslog(L_ERROR, "%s not_found", inet_ntoa(cp->Address));
980 + syslog(L_ERROR, "%s not_found", Inet_NtoA(&cp->Address));
982 /* Anonymous hosts should not authenticate. */
987 for (rp = RCpeerlist, i = RCnpeerlist; --i >= 0; rp++)
988 - if (cp->Address.s_addr == rp->Address.s_addr)
989 + if (RCaddressmatch(&cp->Address, &rp->Address))
996 for (rp = RCpeerlist, i = RCnpeerlist; --i >= 0; rp++)
997 - if (cp->Address.s_addr == rp->Address.s_addr)
998 + if (RCaddressmatch(&cp->Address, &rp->Address))
1000 /* Not found in our table; this can't happen. */
1003 RCrejectreader(CHANNEL *cp)
1005 syslog(L_ERROR, "%s internal RCrejectreader (%s)", LogName,
1006 - inet_ntoa(cp->Address));
1007 + Inet_NtoA(&cp->Address));
1012 RCreader(CHANNEL *cp)
1015 - struct sockaddr_in remote;
1019 register REMOTEHOST *rp;
1024 - if (cp != RCchan) {
1025 - syslog(L_ERROR, "%s internal RCreader wrong channel 0x%x not 0x%x",
1026 - LogName, cp, RCchan);
1027 + if (cp != RCchan[0] && cp != RCchan[1]) {
1028 + syslog(L_ERROR, "%s internal RCreader wrong channel 0x%x",
1034 ** Finally, if neither rejection happened, add the entry to the
1035 ** table, and continue on as a normal connect.
1037 - tempchan.Address.s_addr = remote.sin_addr.s_addr;
1038 + memcpy(&tempchan.Address, &remote, sizeof(remote));
1039 reject_message = NULL;
1040 if (RemoteTimer != 0) {
1043 i = (i + 1) & (REMOTETABLESIZE - 1);
1046 - if (remotetable[i].Address.s_addr == remote.sin_addr.s_addr)
1047 + if (RCaddressmatch(&remotetable[i].Address, &remote))
1049 i = (i + 1) & (REMOTETABLESIZE - 1);
1054 i = (remotefirst + remotecount) & (REMOTETABLESIZE - 1);
1055 - remotetable[i].Address = remote.sin_addr;
1056 + memcpy(&remotetable[i].Address, &remote, sizeof(remote));
1057 remotetable[i].Expires = now + RemoteTimer;
1061 if (reject_message) {
1062 new = CHANcreate(fd, CTreject, CSwritegoodbye, RCrejectreader,
1064 - new->Address.s_addr = remote.sin_addr.s_addr;
1065 + memcpy(&new->Address, &remote, sizeof(remote));
1066 new->Rejected = reject_val;
1068 WCHANset(new, reject_message, (int)strlen(reject_message));
1071 /* See if it's one of our servers. */
1072 for (name = NULL, rp = RCpeerlist, i = RCnpeerlist; --i >= 0; rp++)
1073 - if (rp->Address.s_addr == remote.sin_addr.s_addr) {
1074 + if (RCaddressmatch(&rp->Address, &remote)) {
1079 new->NoResendId = rp->NoResendId;
1080 new->MaxCnx = rp->MaxCnx;
1081 new->HoldTime = rp->HoldTime;
1082 - new->Address.s_addr = remote.sin_addr.s_addr;
1083 + memcpy(&new->Address, &remote, sizeof(remote));
1084 if (new->MaxCnx > 0 && new->HoldTime == 0) {
1085 CHANsetActiveCnx(new);
1086 if((new->ActiveCnx > new->MaxCnx) && (new->fd > 0)) {
1088 reject_message = NNTP_ACCESS;
1089 new = CHANcreate(fd, CTreject, CSwritegoodbye, RCrejectreader,
1091 - new->Address.s_addr = remote.sin_addr.s_addr;
1092 + memcpy(&new->Address, &remote, sizeof(remote));
1093 new->Rejected = reject_val;
1095 WCHANset(new, reject_message, (int)strlen(reject_message));
1100 - new->Address.s_addr = remote.sin_addr.s_addr;
1101 + memcpy(&new->Address, &remote, sizeof(remote));
1102 syslog(L_NOTICE, "%s connected %d streaming %s",
1103 - name ? name : inet_ntoa(new->Address), new->fd,
1104 + name ? name : Inet_NtoA(&new->Address), new->fd,
1105 (!StreamingOff && new->Streaming) ? "allowed" : "not allowed");
1109 register REMOTEHOST peer_params;
1110 register REMOTEHOST default_params;
1111 BOOL flag, bit, toolong;
1113 +#if defined(HAVE_GETADDRINFO)
1114 + struct addrinfo hints, *res, *res0;
1115 +#endif /* defined(HAVE_GETADDRINFO) */
1119 @@ -880,9 +953,51 @@
1120 RENEW (*list, REMOTEHOST, *count);
1123 +#if defined(HAVE_GETADDRINFO)
1124 + (void)memset((POINTER)&hints, 0, sizeof hints);
1125 + hints.ai_family = PF_UNSPEC;
1126 + hints.ai_socktype = SOCK_STREAM;
1127 + if (getaddrinfo(*q, NULL, &hints, &res0) != 0) {
1128 + syslog(L_ERROR, "%s cant getaddrinfo %s %m", LogName, *q);
1129 + /* decrement *count, since we never got to add this record. */
1133 + /* Count the addresses and see if we have to grow the list */
1135 + for (res = res0; res != NULL; res = res->ai_next)
1137 + /* Grow the array */
1140 + RENEW(*list, REMOTEHOST, *count);
1143 + /* Add all hosts */
1144 + for (res = res0; res != NULL; res = res->ai_next) {
1145 + (void)memcpy(&rp->Address, res->ai_addr, res->ai_addrlen);
1146 + rp->Name = COPY (*q);
1147 + rp->Label = COPY (peer_params.Label);
1148 + rp->Email = COPY(peer_params.Email);
1149 + rp->Comment = COPY(peer_params.Comment);
1150 + rp->Streaming = peer_params.Streaming;
1151 + rp->Skip = peer_params.Skip;
1152 + rp->NoResendId = peer_params.NoResendId;
1153 + rp->Password = COPY(peer_params.Password);
1154 + rp->Patterns = peer_params.Pattern != NULL ?
1155 + RCCommaSplit(COPY(peer_params.Pattern)) : NULL;
1156 + rp->MaxCnx = peer_params.MaxCnx;
1157 + rp->HoldTime = peer_params.HoldTime;
1160 + freeaddrinfo(res0);
1161 +#else /* defined(HAVE_GETADDRINFO) */
1162 /* Was host specified as a dotted quad ? */
1163 - if ((rp->Address.s_addr = inet_addr(*q)) != INADDR_NONE) {
1164 + if (inet_addr(*q) != INADDR_NONE) {
1166 /* syslog(LOG_NOTICE, "think it's a dotquad: %s", *q); */
1167 + addr = inet_addr(*q);
1168 + COPYADDR(&rp->Address, (char *)&addr);
1169 rp->Name = COPY (*q);
1170 rp->Label = COPY (peer_params.Label);
1171 rp->Password = COPY(peer_params.Password);
1172 @@ -920,7 +1035,9 @@
1174 /* Strange DNS ? try this.. */
1175 for (r = hp->h_aliases; *r != 0; r++) {
1176 - if (inet_addr(*r) == INADDR_NONE) /* IP address ? */
1178 + addr = inet_addr(*r);
1179 + if (addr == INADDR_NONE) /* IP address ? */
1182 /* Grow the array */
1183 @@ -928,7 +1045,7 @@
1184 RENEW (*list, REMOTEHOST, *count);
1187 - rp->Address.s_addr = inet_addr(*r);
1188 + COPYADDR(&rp->Address, (char *)&addr);
1189 rp->Name = COPY (*q);
1190 rp->Label = COPY (peer_params.Label);
1191 rp->Email = COPY(peer_params.Email);
1192 @@ -1003,6 +1120,7 @@
1193 rp->HoldTime = peer_params.HoldTime;
1195 #endif /* defined(h_addr) */
1196 +#endif /* defined(HAVE_GETADDRINFO) */
1200 @@ -1496,9 +1614,9 @@
1203 for (rp = RCpeerlist, i = RCnpeerlist; --i >= 0; rp++)
1204 - if (cp->Address.s_addr == rp->Address.s_addr)
1205 + if (RCaddressmatch(&cp->Address, &rp->Address))
1207 - (void)strcpy(buff, inet_ntoa(cp->Address));
1208 + (void)strcpy(buff, Inet_NtoA(&cp->Address));
1212 @@ -1511,7 +1629,7 @@
1215 for (rp = RCpeerlist, i = RCnpeerlist; --i >= 0; rp++) {
1216 - if (cp->Address.s_addr == rp->Address.s_addr)
1217 + if (RCaddressmatch(&cp->Address, &rp->Address))
1221 @@ -1530,7 +1648,7 @@
1224 for (rp = RCpeerlist, i = RCnpeerlist; --i >= 0; rp++) {
1225 - if (cp->Address.s_addr != rp->Address.s_addr)
1226 + if (RCaddressmatch(&cp->Address, &rp->Address))
1228 if (rp->Patterns == NULL)
1230 @@ -1559,12 +1677,53 @@
1233 struct sockaddr_in server;
1235 + struct sockaddr_in6 server6;
1236 +#endif /* defined(INET6) */
1237 #if defined(SO_REUSEADDR)
1239 #endif /* defined(SO_REUSEADDR) */
1243 /* Create a socket and name it. */
1245 + if (RCchan[0] != NULL && innconf->listenonipv6) {
1246 + if ((i = socket(AF_INET6, SOCK_STREAM, 0)) < 0) {
1247 + syslog(L_FATAL, "%s cant ipv6 socket RCreader %m", LogName);
1250 +#if defined(SO_REUSEADDR)
1252 + if (setsockopt(i, SOL_SOCKET, SO_REUSEADDR, (caddr_t)&on,
1254 + syslog(L_ERROR, "%s cant setsockopt RCreader %m", LogName);
1255 +#endif /* defined(SO_REUSEADDR) */
1256 + (void)memset((POINTER)&server6, 0, sizeof server6);
1257 + server6.sin6_port = htons(innconf->port);
1258 + server6.sin6_family = AF_INET6;
1259 + server6.sin6_addr = in6addr_any;
1260 +#if defined(HAVE_SOCKADDR_LEN)
1261 + server6.sin6_len = sizeof server6;
1262 +#endif /* defined(HAVE_SOCKADDR_LEN) */
1263 + if (innconf->bindipv6address) {
1264 + if (inet_pton(AF_INET6, innconf->bindipv6address,
1265 + &server6.sin6_addr) < 1) {
1266 + syslog(L_FATAL, "unable to determine bind ipv6 (%s) %m",
1267 + innconf->bindipv6address);
1271 + if (bind(i, (struct sockaddr *)&server6, sizeof server6) < 0) {
1272 + syslog(L_FATAL, "%s cant bind RCreader %m", LogName);
1275 + } else if (RCchan[0] != NULL) {
1276 + /* If "listenonipv6" not set, and one socket has already been
1277 + created, no need to create more socket */
1280 +#endif /* defined(INET6) */
1281 if ((i = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
1282 syslog(L_FATAL, "%s cant socket RCreader %m", LogName);
1284 @@ -1599,9 +1758,15 @@
1285 syslog(L_FATAL, "%s cant listen RCreader %m", LogName);
1288 - RCchan = CHANcreate(i, CTremconn, CSwaiting, RCreader, RCwritedone);
1289 - syslog(L_NOTICE, "%s rcsetup %s", LogName, CHANname(RCchan));
1292 + if (RCchan[0] == NULL)
1296 + RCchan[idx] = CHANcreate(i, CTremconn, CSwaiting, RCreader, RCwritedone);
1298 + syslog(L_NOTICE, "%s rcsetup %s", LogName, CHANname(RCchan[idx]));
1299 + RCHANadd(RCchan[idx]);
1301 /* Get the list of hosts we handle. */
1303 @@ -1617,8 +1782,11 @@
1304 register REMOTEHOST *rp;
1307 - CHANclose(RCchan, CHANname(RCchan));
1309 + for (i = 0; i < 2; i++)
1310 + if (RCchan[i] != NULL) {
1311 + CHANclose(RCchan[i], CHANname(RCchan[i]));
1315 for (rp = RCpeerlist, i = RCnpeerlist; --i >= 0; rp++) {
1317 diff -Nur inn-2.3.2.orig/innd/status.c inn-2.3.2/innd/status.c
1318 --- inn-2.3.2.orig/innd/status.c Thu May 3 22:27:32 2001
1319 +++ inn-2.3.2/innd/status.c Tue Jun 19 16:06:41 2001
1322 typedef struct _STATUS {
1327 unsigned short activeCxn;
1328 unsigned short sleepingCxns;
1331 for (i = 0; (cp = CHANiter(&i, CTnntp)) != NULL; ) {
1333 - strcpy(TempString, cp->Address.s_addr == 0 ? "localhost" : RChostname(cp));
1334 + strcpy(TempString, cp->Address.ss_family == 0 ? "localhost" :
1336 for (status = head ; status != NULL ; status = status->next) {
1337 if (strcmp(TempString, status->name) == 0)
1340 status = NEW(STATUS, 1);
1341 peers++; /* a new peer */
1342 strcpy (status->name, TempString); /* name */
1343 - strcpy (status->ip_addr, inet_ntoa(cp->Address)); /* ip address */
1344 + strcpy (status->ip_addr, Inet_NtoA(&cp->Address)); /* ip address */
1345 status->can_stream = cp->Streaming;
1346 status->seconds = status->Size = status->DuplicateSize = 0;
1347 status->Ihave = status->Ihave_Duplicate =
1348 diff -Nur inn-2.3.2.orig/innfeed/connection.c inn-2.3.2/innfeed/connection.c
1349 --- inn-2.3.2.orig/innfeed/connection.c Thu May 3 22:27:32 2001
1350 +++ inn-2.3.2/innfeed/connection.c Tue Jun 19 16:06:41 2001
1351 @@ -131,6 +131,12 @@
1355 +#ifndef HAVE_SOCKADDR_STORAGE
1356 +#include "sockaddr_storage.h"
1359 +#include "sa_len.h"
1361 #if defined (NDEBUG)
1362 #define VALIDATE_CONNECTION(x) ((void) 0)
1365 static u_int gCxnCount = 0 ;
1366 static u_int max_reconnect_period = MAX_RECON_PER ;
1367 static u_int init_reconnect_period = INIT_RECON_PER ;
1368 -static u_long bind_addr = INADDR_ANY;
1369 +static struct sockaddr_storage bind_addr;
1370 +static int bind_addr_flag = 0;
1372 static bool inited = false ;
1374 @@ -406,17 +413,33 @@
1375 iv = INIT_RECON_PER ;
1376 init_reconnect_period = (u_int) iv ;
1378 + memset (&bind_addr, 0, sizeof(bind_addr));
1379 if (getString (topScope,"bindaddress",&sv,NO_INHERIT))
1381 - bind_addr = inet_addr(sv);
1382 - if (bind_addr == INADDR_NONE)
1384 + if (inet_addr(sv) != INADDR_NONE) {
1385 + bind_addr.ss_family = AF_INET;
1386 + ((struct sockaddr_in *)&bind_addr)->sin_addr.s_addr = inet_addr(sv);
1387 +#ifdef HAVE_SOCKADDR_LEN
1388 + bind_addr.ss_len = sizeof(struct sockaddr_in);
1390 + bind_addr_flag = 1;
1393 + else if (inet_pton(AF_INET6, sv,
1394 + &((struct sockaddr_in6 *)&bind_addr)->sin6_addr) == 1) {
1395 + bind_addr.ss_family = AF_INET6;
1396 +#ifdef HAVE_SOCKADDR_LEN
1397 + bind_addr.ss_len = sizeof(struct sockaddr_in6);
1399 + bind_addr_flag = 1;
1403 logOrPrint (LOG_ERR,fp,"innfeed unable to determine bind ip") ;
1404 - bind_addr = INADDR_ANY;
1405 + bind_addr_flag = 0;
1409 - bind_addr = INADDR_ANY;
1411 + bind_addr_flag = 0;
1417 bool cxnConnect (Connection cxn)
1419 - struct sockaddr_in cxnAddr, cxnSelf ;
1420 + struct sockaddr_storage cxnAddr, cxnSelf ;
1422 - struct in_addr *addr = NULL;
1423 + struct sockaddr_storage *addr = NULL;
1424 const char *peerName = hostPeerName (cxn->myHost) ;
1426 ASSERT (cxn->myEp == NULL) ;
1427 @@ -566,12 +589,15 @@
1431 - memset (&cxnAddr, 0, sizeof (cxnAddr)) ;
1432 - cxnAddr.sin_family = AF_INET ;
1433 - cxnAddr.sin_port = htons(cxn->port) ;
1434 - cxnAddr.sin_addr.s_addr = addr->s_addr ;
1435 + memcpy (&cxnAddr, addr, sizeof(cxnAddr));
1436 + if (cxnAddr.ss_family == AF_INET)
1437 + ((struct sockaddr_in *)&cxnAddr)->sin_port = htons(cxn->port);
1439 + else if (cxnAddr.ss_family == AF_INET6)
1440 + ((struct sockaddr_in6 *)&cxnAddr)->sin6_port = htons(cxn->port);
1443 - if ((fd = socket (AF_INET, SOCK_STREAM, 0)) < 0)
1444 + if ((fd = socket (cxnAddr.ss_family, SOCK_STREAM, 0)) < 0)
1446 syslog (LOG_ERR, SOCKET_CREATE_ERROR, peerName, cxn->ident) ;
1447 d_printf (1,"Can't get a socket: %m\n") ;
1448 @@ -582,13 +608,15 @@
1451 /* bind to a specified virtual host */
1452 - if (bind_addr != INADDR_ANY)
1453 + if (bind_addr_flag == 1)
1455 - memset (&cxnSelf, 0, sizeof (cxnSelf)) ;
1456 - cxnSelf.sin_family = AF_INET ;
1457 - cxnSelf.sin_port = 0 ;
1458 - cxnSelf.sin_addr.s_addr = bind_addr;
1459 - if (bind (fd, (struct sockaddr *) &cxnSelf,sizeof (cxnSelf)) < 0)
1460 + (void)memcpy (&cxnSelf, &bind_addr, sizeof(cxnSelf));
1461 +#ifdef HAVE_SOCKADDR_LEN
1462 + if (bind (fd, (struct sockaddr *) &cxnSelf, cxnSelf.ss_len) < 0)
1464 + if (bind (fd, (struct sockaddr *) &cxnSelf,
1465 + SA_LEN((struct sockaddr *) &cxnSelf)) < 0)
1468 syslog (LOG_ERR,"bind: %m") ;
1470 @@ -620,7 +648,12 @@
1474 - rval = connect (fd, (struct sockaddr *) &cxnAddr, sizeof (cxnAddr)) ;
1475 +#ifdef HAVE_SOCKADDR_LEN
1476 + rval = connect (fd, (struct sockaddr *) &cxnAddr, cxnAddr.ss_len);
1478 + rval = connect (fd, (struct sockaddr *) &cxnAddr,
1479 + SA_LEN((struct sockaddr *) &cxnAddr));
1481 if (rval < 0 && errno != EINPROGRESS)
1483 syslog (LOG_ERR, CONNECT_ERROR, peerName, cxn->ident) ;
1484 diff -Nur inn-2.3.2.orig/innfeed/endpoint.c inn-2.3.2/innfeed/endpoint.c
1485 --- inn-2.3.2.orig/innfeed/endpoint.c Thu May 3 22:27:32 2001
1486 +++ inn-2.3.2/innfeed/endpoint.c Tue Jun 19 16:06:41 2001
1487 @@ -1628,6 +1628,11 @@
1489 struct sockaddr_in accNet ;
1490 int accFd = socket (AF_INET,SOCK_STREAM,0) ;
1492 + EndPoint accConn6;
1493 + struct sockaddr_in6 accNet6;
1494 + int accFd6 = socket (AF_INET6,SOCK_STREAM,0);
1496 u_short port = atoi (argc > 1 ? argv[1] : "10000") ;
1497 time_t t = theTime() ;
1499 @@ -1663,6 +1668,26 @@
1500 accConn = newEndPoint (accFd) ;
1502 prepareRead (accConn,NULL,newConn,NULL,0) ;
1505 + ASSERT(accFd6 >= 0);
1506 + memset (&accNet6,0,sizeof (accNet6));
1507 + accNet6.sin6_family = AF_INET6;
1508 + accNet6.sin6_addr = in6addr_any;
1509 + accNet6.sin6_port = htons (port);
1511 + if (bind (accFd6, (struct sockaddr_in6 *) &accNet6, sizeof (accNet6)) < 0)
1513 + perror ("bind: %m") ;
1517 + listen (accFd6,5);
1519 + accCon6 = newEndPoint (accFd6);
1521 + prepareRead (accCon6,NULL,newConn,NULL,0) ;
1524 prepareSleep (Timeout,5,(void *) 0x10) ;
1526 diff -Nur inn-2.3.2.orig/innfeed/host.c inn-2.3.2/innfeed/host.c
1527 --- inn-2.3.2.orig/innfeed/host.c Thu May 3 22:27:32 2001
1528 +++ inn-2.3.2/innfeed/host.c Tue Jun 19 16:06:41 2001
1531 #include "clibrary.h"
1533 +#include <sys/types.h>
1534 +#include <sys/socket.h>
1535 #include <netinet/in.h>
1536 #include <arpa/inet.h>
1542 +#ifndef HAVE_SOCKADDR_STORAGE
1543 +#include "sockaddr_storage.h"
1548 #define NOTREQNOADD 2
1549 @@ -1128,22 +1134,63 @@
1553 -struct in_addr *hostIpAddr (Host host)
1554 +struct sockaddr_storage *hostIpAddr (Host host)
1558 char **newIpAddrs = NULL;
1559 - struct in_addr ipAddr, *returnAddr ;
1560 + struct sockaddr_storage ipAddr, *returnAddr;
1561 struct hostent *hostEnt ;
1562 +#ifdef HAVE_GETADDRINFO
1563 + struct addrinfo hints, *res, *pr;
1565 char *msgstr[SMBUF] ;
1567 ASSERT(host->params != NULL);
1568 + returnAddr = NULL;
1570 /* check to see if need to look up the host name */
1571 if (host->nextIpLookup <= theTime())
1573 +#ifdef HAVE_GETADDRINFO
1574 + memset(&hints, 0, sizeof(hints));
1575 + hints.ai_family = PF_UNSPEC;
1576 + hints.ai_socktype = SOCK_STREAM;
1577 + i = getaddrinfo(host->params->ipName, NULL, &hints, &res);
1580 + syslog (LOG_ERR, HOST_RESOLV_ERROR, host->params->peerName,
1581 + host->params->ipName, gai_strerror(i));
1585 + /* figure number of pointers that need space */
1587 + for (pr = res; pr != NULL; pr = pr->ai_next, i++)
1592 + (char **) MALLOC ( (i * sizeof(char *)) +
1593 + ( (i - 1) * sizeof(struct sockaddr_storage)) ) ;
1594 + ASSERT (newIpAddrs != NULL) ;
1596 + p = (char *)&newIpAddrs [ i ] ;
1598 + for (pr = res; pr != NULL; pr = pr->ai_next)
1600 + newIpAddrs[i] = p;
1601 + memcpy (p, pr->ai_addr, pr->ai_addrlen);
1602 + p += sizeof(struct sockaddr_storage);
1605 + newIpAddrs[i] = NULL;
1606 + freeaddrinfo(res);
1609 /* see if the ipName we're given is a dotted quad */
1610 - if ( !inet_aton (host->params->ipName,&ipAddr) )
1611 + if ( !inet_aton (host->params->ipName,
1612 + &((struct sockaddr_in *)&ipAddr)->sin_addr) )
1614 if ((hostEnt = gethostbyname (host->params->ipName)) == NULL)
1616 @@ -1159,7 +1206,8 @@
1619 (char **) MALLOC ( (i * sizeof(char *)) +
1620 - ( (i - 1) * hostEnt->h_length) ) ;
1622 + sizeof(struct sockaddr_storage) ) );
1623 ASSERT (newIpAddrs != NULL) ;
1625 /* copy the addresses from gethostbyname() static space */
1626 @@ -1168,7 +1216,13 @@
1627 for (i = 0 ; hostEnt->h_addr_list[i] ; i++)
1630 - memcpy (p, hostEnt->h_addr_list[i], hostEnt->h_length) ;
1631 + memcpy (&((struct sockaddr_in *)p)->sin_addr,
1632 + hostEnt->h_addr_list[i], hostEnt->h_length) ;
1633 + ((struct sockaddr_in *)p)->sin_family = AF_INET;
1634 +#ifdef HAVE_SOCKADDR_LEN
1635 + ((struct sockaddr_in *)p)->sin_len =
1636 + sizeof(struct sockaddr_in);
1638 p += hostEnt->h_length ;
1640 newIpAddrs[i] = NULL ;
1641 @@ -1181,9 +1235,13 @@
1642 p = (char *)&newIpAddrs [ 2 ];
1644 memcpy (p, (char *)&ipAddr, sizeof(ipAddr)) ;
1645 + ((struct sockaddr_in *)p)->sin_family = AF_INET;
1646 +#ifdef HAVE_SOCKADDR_LEN
1647 + ((struct sockaddr_in *)p)->sin_len = sizeof(struct sockaddr_in);
1649 newIpAddrs[1] = NULL;
1652 +#endif /* HAVE_GETADDRINFO */
1656 @@ -1201,7 +1259,7 @@
1660 - returnAddr = (struct in_addr *)(host->nextIpAddr[0]) ;
1661 + returnAddr = (struct sockaddr_storage *)(host->nextIpAddr[0]) ;
1662 if (*(++host->nextIpAddr) == NULL)
1663 host->nextIpAddr = host->ipAddrs ;
1665 diff -Nur inn-2.3.2.orig/innfeed/host.h inn-2.3.2/innfeed/host.h
1666 --- inn-2.3.2.orig/innfeed/host.h Thu May 3 22:27:32 2001
1667 +++ inn-2.3.2/innfeed/host.h Tue Jun 19 16:06:41 2001
1669 void hostSendArticle (Host host, Article article) ;
1671 /* return an IP address for the host */
1672 -struct in_addr *hostIpAddr (Host host) ;
1673 +struct sockaddr_storage *hostIpAddr (Host host) ;
1676 * Functions used by the Connection to indicate Connection state.
1677 diff -Nur inn-2.3.2.orig/lib/Makefile inn-2.3.2/lib/Makefile
1678 --- inn-2.3.2.orig/lib/Makefile Thu May 3 22:27:32 2001
1679 +++ inn-2.3.2/lib/Makefile Tue Jun 19 16:06:41 2001
1681 md5.c nonblocking.c parsedate.c perl.c qio.c radix32.c readin.c \
1682 remopen.c reservedfd.c resource.c rwlock.c sendarticle.c \
1683 sendpass.c tempname.c waitnb.c wildmat.c version.c xfopena.c \
1684 - xmalloc.c xsignal.c xwrite.c xwritev.c
1685 + xmalloc.c xsignal.c xwrite.c xwritev.c inet_ntoa.c
1687 OBJECTS = $(MISSING_OBJ) \
1688 argparse.o checkart.o cleanfrom.o clientactive.o clientlib.o \
1690 md5.o nonblocking.o parsedate.o qio.o radix32.o readin.o \
1691 remopen.o reservedfd.o resource.o rwlock.o sendarticle.o \
1692 sendpass.o tempname.o waitnb.o wildmat.o version.o xfopena.o \
1693 - xmalloc.o xsignal.o xwrite.o xwritev.o
1694 + xmalloc.o xsignal.o xwrite.o xwritev.o inet_ntoa.o
1696 LOBJECTS= $(OBJECTS:.o=.lo)
1698 diff -Nur inn-2.3.2.orig/lib/getconfig.c inn-2.3.2/lib/getconfig.c
1699 --- inn-2.3.2.orig/lib/getconfig.c Thu May 3 22:27:32 2001
1700 +++ inn-2.3.2/lib/getconfig.c Tue Jun 19 16:06:41 2001
1702 innconf->groupbaseexpiry = TRUE;
1703 innconf->wipcheck = 5;
1704 innconf->wipexpire = 10;
1705 + innconf->listenonipv6 = FALSE;
1706 + innconf->bindipv6address = NULL;
1707 + innconf->sourceipv6address = NULL;
1712 if (innconf->backoff_db != NULL) DISPOSE(innconf->backoff_db);
1713 if (innconf->ovmethod != NULL) DISPOSE(innconf->ovmethod);
1714 if (innconf->ovgrouppat != NULL) DISPOSE(innconf->ovgrouppat);
1715 + if (innconf->bindipv6address != NULL) DISPOSE(innconf->bindipv6address);
1716 + if (innconf->sourceipv6address != NULL) DISPOSE(innconf->sourceipv6address);
1718 memset(ConfigBit, '\0', ConfigBitsize);
1721 @@ -981,6 +987,21 @@
1722 TEST_CONFIG(CONF_VAR_WIPEXPIRE, bit);
1723 if (!bit) innconf->wipexpire = atoi(p);
1724 SET_CONFIG(CONF_VAR_WIPEXPIRE);
1726 + if (EQ(ConfigBuff, _CONF_LISTENONIPV6)) {
1727 + TEST_CONFIG(CONF_VAR_LISTENONIPV6, bit);
1728 + if (!bit && boolval != -1) innconf->listenonipv6 = boolval;
1729 + SET_CONFIG(CONF_VAR_LISTENONIPV6);
1731 + if (EQ(ConfigBuff, _CONF_BINDIPV6ADDRESS)) {
1732 + TEST_CONFIG(CONF_VAR_BINDIPV6ADDRESS, bit);
1733 + if (!bit) innconf->bindipv6address = COPY(p);
1734 + SET_CONFIG(CONF_VAR_BINDIPV6ADDRESS);
1736 + if (EQ(ConfigBuff, _CONF_SOURCEIPV6ADDRESS)) {
1737 + TEST_CONFIG(CONF_VAR_SOURCEIPV6ADDRESS, bit);
1738 + if (!bit) innconf->sourceipv6address = COPY(p);
1739 + SET_CONFIG(CONF_VAR_SOURCEIPV6ADDRESS);
1743 diff -Nur inn-2.3.2.orig/lib/inet_ntoa.c inn-2.3.2/lib/inet_ntoa.c
1744 --- inn-2.3.2.orig/lib/inet_ntoa.c Thu May 3 22:27:32 2001
1745 +++ inn-2.3.2/lib/inet_ntoa.c Tue Jun 19 16:06:41 2001
1749 #include <sys/types.h>
1750 +#include <sys/socket.h>
1751 +#include <netinet/in.h>
1752 +#include <arpa/inet.h>
1754 #include "configdata.h"
1755 #include "clibrary.h"
1756 +#include "sockaddr_storage.h"
1758 +#if !defined(HAVE_SOCKADDR_LEN)
1759 +#include "sa_len.h"
1763 * Copyright (c) 1983 Regents of the University of California.
1765 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
1766 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
1771 #if defined(LIBC_SCCS) && !defined(lint)
1772 static char sccsid[] = "@(#)inet_ntoa.c 5.6 (Berkeley) 2/24/91";
1774 * Convert network-format internet address
1775 * to base 256 d.d.d.d representation.
1777 -#include <netinet/in.h>
1779 #define UC(c) (((int)c) & 0xFF)
1781 -char *inet_ntoa(struct in_addr in)
1782 +char *Inet_NtoA(struct sockaddr_storage *ss)
1784 +#if !defined(INET6)
1785 +#if defined(HAVE_INET_NTOA)
1786 + return inet_ntoa(((struct sockaddr_in *)ss)->sin_addr);
1788 static char buff[18];
1792 (void)sprintf(buff, "%d.%d.%d.%d", UC(p[0]), UC(p[1]), UC(p[2]), UC(p[3]));
1794 +#endif /* HAVE_INET_NTOA */
1796 + static char buff[256];
1797 + struct sockaddr_in sin;
1798 + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)ss;
1800 + if (ss->ss_family == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) ) {
1801 + memcpy(&sin.sin_addr, sin6->sin6_addr.s6_addr+12,
1802 + sizeof(sin.sin_addr));
1803 + sin.sin_port = ((struct sockaddr_in6 *)ss)->sin6_port;
1804 + sin.sin_family = AF_INET;
1805 +#if defined(HAVE_SOCKADDR_LEN)
1806 + sin.sin_len = sizeof(struct sockaddr_in);
1808 + return inet_ntoa(sin.sin_addr);
1810 +#if defined(HAVE_SOCKADDR_LEN)
1811 + getnameinfo((struct sockaddr *)ss, ss->ss_len, buff, sizeof(buff), NULL, 0,
1814 + getnameinfo((struct sockaddr *)ss, SA_LEN((struct sockaddr *)ss), buff,
1815 + sizeof(buff), NULL, 0, NI_NUMERICHOST);
1816 +#endif /* HAVE_SOCKADDR_IN */
1821 diff -Nur inn-2.3.2.orig/lib/remopen.c inn-2.3.2/lib/remopen.c
1822 --- inn-2.3.2.orig/lib/remopen.c Thu May 3 22:27:32 2001
1823 +++ inn-2.3.2/lib/remopen.c Tue Jun 19 16:06:41 2001
1828 +#if defined(HAVE_GETADDRINFO)
1829 + struct addrinfo hints, *res, *addr;
1831 + struct sockaddr_storage client;
1834 struct hostent fakehp;
1835 struct in_addr quadaddr;
1836 struct sockaddr_in server, client;
1837 +#endif /* defined(HAVE_GETADDRINFO) */
1839 buff = errbuff ? errbuff : mybuff;
1842 +#if defined(HAVE_GETADDRINFO)
1843 + (void)memset((POINTER)&hints, 0, sizeof hints);
1844 + hints.ai_family = PF_UNSPEC;
1845 + hints.ai_socktype = SOCK_STREAM;
1846 + sprintf(portbuf, "%d", port);
1847 + if (getaddrinfo(host, portbuf, &hints, &res) != 0)
1850 + for (addr = res; addr; addr = addr->ai_next) {
1851 + /* Make a socket and try to connect */
1852 + if ((i = socket(addr->ai_family, SOCK_STREAM, 0)) < 0)
1854 + (void)memset((POINTER)&client, 0, sizeof client);
1855 + if (addr->ai_family == AF_INET) {
1856 + if (innconf->sourceaddress &&
1857 + inet_pton(AF_INET, innconf->sourceaddress,
1858 + &((struct sockaddr_in *)&client)->sin_addr) < 1) {
1859 + freeaddrinfo(addr);
1862 + ((struct sockaddr_in *)&client)->sin_family = AF_INET;
1865 + if (addr->ai_family == AF_INET6) {
1866 + if (innconf->sourceipv6address &&
1867 + inet_pton(AF_INET6, innconf->sourceipv6address,
1868 + &((struct sockaddr_in6 *)&client)->sin6_addr) < 1) {
1869 + freeaddrinfo(addr);
1872 + ((struct sockaddr_in6 *)&client)->sin6_family = AF_INET6;
1874 +#endif /* defined(INET6) */
1875 + /* Bind to the source address we want. */
1876 + if (bind(i, (struct sockaddr *)&client, addr->ai_addrlen) < 0) {
1882 + if (connect(i, addr->ai_addr, addr->ai_addrlen) < 0) {
1889 +#else /* HAVE_GETADDRINFO */
1891 quadaddr.s_addr = inet_addr(host);
1892 if (quadaddr.s_addr != (unsigned int) -1) {
1893 /* Host was specified as a dotted-quad internet address. Fill in
1898 +#endif /* defined(HAVE_GETADDRINFO) */
1900 /* Connected -- now make sure we can post. */
1901 if ((F = fdopen(i, "r")) == NULL) {
1902 diff -Nur inn-2.3.2.orig/nnrpd/commands.c inn-2.3.2/nnrpd/commands.c
1903 --- inn-2.3.2.orig/nnrpd/commands.c Thu May 3 22:27:32 2001
1904 +++ inn-2.3.2/nnrpd/commands.c Tue Jun 19 16:06:41 2001
1905 @@ -184,7 +184,22 @@
1907 /*syslog(L_NOTICE, "%s (%ld) returned: %d %s %d\n", av[0], (long) pid, i, path, status);*/
1908 /* Split "host:permissions:user:pass:groups" into fields. */
1909 - for (fields[0] = path, i = 0, p = path; *p; p++)
1910 + /* "host" field for IPv6 address must be enclosed with "[" and "]" */
1911 + if (path[0] == '[') {
1912 + fields[0] = path + 1;
1915 + while (*p && *p != ']')
1918 + p += 2; /* Skip next ':' */
1928 fields[++i] = p + 1;
1930 /* Acquire lock (this could be in RateLimit but that would
1931 * invoke the spaghetti factor).
1933 - if ((path = (char *) PostRecFilename(ClientIP,PERMuser)) == NULL) {
1934 + if ((path = (char *) PostRecFilename(&ClientIP,PERMuser)) == NULL) {
1935 Reply("%s\r\n", NNTP_CANTPOST);
1938 diff -Nur inn-2.3.2.orig/nnrpd/misc.c inn-2.3.2/nnrpd/misc.c
1939 --- inn-2.3.2.orig/nnrpd/misc.c Thu May 3 22:27:32 2001
1940 +++ inn-2.3.2/nnrpd/misc.c Tue Jun 19 16:06:41 2001
1941 @@ -664,12 +664,12 @@
1944 *PostRecFilename(ip,user)
1949 static char buff[SPOOLNAMEBUFF];
1950 char dirbuff[SPOOLNAMEBUFF];
1951 - unsigned char addr[4];
1952 + unsigned char addr[16];
1955 if (PERMaccessconf->backoff_auth) {
1956 @@ -677,11 +677,27 @@
1960 - for (i=0; i<4; i++) {
1961 - addr[i] = (unsigned char) (0x000000ff & (ip>>(i*8)));
1962 + switch (ip->ss_family) {
1964 + for (i=0; i<4; i++) {
1965 + addr[i] = (unsigned char)
1966 + (0x000000ff & (((struct sockaddr_in *)ip)->sin_addr.s_addr >>
1969 + sprintf(dirbuff,"%s/%03d%03d/%03d",postrec_dir,addr[3],addr[2],addr[1]);
1973 + for (i=0;i<15;i++)
1974 + addr[i] = ((struct sockaddr_in6 *)ip)->sin6_addr.s6_addr[i];
1975 + sprintf(dirbuff,"%s/%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x/%02x%02x",
1976 + postrec_dir,addr[0],addr[1],addr[2],addr[3],addr[4],addr[5],
1977 + addr[6],addr[7],addr[8],addr[9],addr[10],addr[11],
1978 + addr[12],addr[13]);
1983 - sprintf(dirbuff,"%s/%03d%03d/%03d",postrec_dir,addr[3],addr[2],addr[1]);
1984 if (!MakeDirectory(dirbuff,TRUE)) {
1985 syslog(L_ERROR,"%s Unable to create postrec directories '%s': %s",
1986 ClientHost,dirbuff,strerror(errno));
1987 diff -Nur inn-2.3.2.orig/nnrpd/nnrpd.c inn-2.3.2/nnrpd/nnrpd.c
1988 --- inn-2.3.2.orig/nnrpd/nnrpd.c Thu May 3 22:27:32 2001
1989 +++ inn-2.3.2/nnrpd/nnrpd.c Tue Jun 19 16:12:24 2001
1991 int nnrpd_starttls_done = 0;
1994 +#include "sa_len.h"
1996 #if defined(hpux) || defined(__hpux) || defined(_SCO_DS)
1999 @@ -362,11 +364,82 @@
2000 Address2Name(INADDR *ap, char *hostname, int i)
2004 + struct addrinfo hints, *res, *res0;
2006 + struct sockaddr_in sin;
2007 + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)ap;
2013 +#endif /* defined (INET6) */
2016 + /* Get the official hostname, store it away. (with new API) */
2017 + if (ap->ss_family == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) ) {
2018 + memcpy(&sin.sin_addr, sin6->sin6_addr.s6_addr+12,
2019 + sizeof(sin.sin_addr));
2020 + sin.sin_port = ((struct sockaddr_in6 *)ap)->sin6_port;
2021 + sin.sin_family = AF_INET;
2022 +#if defined(HAVE_SOCKADDR_LEN)
2023 + sin.sin_len = sizeof(struct sockaddr_in);
2024 +#endif /* defined(HAVE_SOCKADDR_LEN) */
2028 +#if defined(HAVE_SOCKADDR_LEN)
2031 + len = SA_LEN((struct sockaddr *)ap);
2032 +#endif /* defined(HAVE_SOCKADDR_LEN) */
2033 + ret = getnameinfo((struct sockaddr *)ap, len, hostname, i, NULL, 0,
2036 + HostErrorStr = gai_strerror(ret);
2040 + /* Get the address for this host */
2041 + (void)memset(&hints, 0, sizeof(hints));
2042 + hints.ai_family = PF_UNSPEC;
2043 + hints.ai_flags = AI_CANONNAME;
2044 + hints.ai_socktype = SOCK_STREAM;
2045 + ret = getaddrinfo(hostname, NULL, &hints, &res0);
2047 + HostErrorStr = gai_strerror(ret);
2051 + /* Make sure one of those addresses is the address we got. */
2052 + for (res = res0; res != NULL; res = res->ai_next) {
2053 + if (res->ai_addr->sa_family == ap->ss_family) {
2054 + if (ap->ss_family == AF_INET &&
2055 + memcmp(&((struct sockaddr_in *)ap)->sin_addr,
2056 + &((struct sockaddr_in *)res->ai_addr)->sin_addr,
2057 + sizeof(struct in_addr)) == 0)
2059 + else if (ap->ss_family == AF_INET6 &&
2060 + memcmp(&((struct sockaddr_in6 *)ap)->sin6_addr,
2061 + &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr,
2062 + sizeof(struct in6_addr)) == 0)
2066 + if (res == NULL) {
2067 + freeaddrinfo(res0);
2070 + if (res->ai_canonname == NULL) { /* XXX */
2071 + freeaddrinfo(res0);
2074 + (void)strncpy(hostname, res->ai_canonname, i);
2075 + freeaddrinfo(res0);
2077 +#else /* defined(INET6) */
2079 /* Get the official hostname, store it away. */
2080 if ((hp = gethostbyaddr((char *)ap, sizeof *ap, AF_INET)) == NULL) {
2081 HostErrorStr = (char *)hstrerror(h_errno);
2082 @@ -385,25 +458,27 @@
2084 /* We have many addresses */
2085 for (pp = hp->h_addr_list; *pp; pp++)
2086 - if (memcmp((POINTER)&ap->s_addr, (POINTER)*pp,
2087 - (SIZE_T)hp->h_length) == 0)
2088 + if (memcmp((POINTER)&(((struct sockaddr_in *)ap)->sin_addr.s_addr),
2089 + (POINTER)*pp, (SIZE_T)hp->h_length) == 0)
2094 /* We have one address. */
2095 - if (memcmp((POINTER)&ap->s_addr, (POINTER)hp->h_addr,
2096 - (SIZE_T)hp->h_length) != 0)
2097 + if (memcmp((POINTER)&(((struct sockaddr_in *)ap)->sin_addr.s_addr),
2098 + (POINTER)hp->h_addr, (SIZE_T)hp->h_length) != 0)
2102 /* Only needed for misconfigured YP/NIS systems. */
2103 - if (ap->s_addr != INADDR_LOOPBACK && strchr(hostname, '.') == NULL
2104 - && (p = innconf->domain) != NULL) {
2105 + if (((struct sockaddr_in *)ap)->sin_addr.s_addr != INADDR_LOOPBACK &&
2106 + strchr(hostname, '.') == NULL && (p = innconf->domain) != NULL) {
2107 (void)strcat(hostname, ".");
2108 (void)strcat(hostname, p);
2111 +#endif /* defined(INET6) */
2113 /* Make all lowercase, for wildmat. */
2114 for (p = hostname; *p; p++)
2115 if (CTYPE(isupper, (int)*p))
2118 STATIC void StartConnection()
2120 - struct sockaddr_in sin;
2121 + struct sockaddr_storage ss;
2126 static ACCESSGROUP *authconf;
2128 /* Get the peer's name. */
2129 - length = sizeof sin;
2130 + length = sizeof ss;
2132 - if (getpeername(STDIN, (struct sockaddr *)&sin, &length) < 0) {
2133 + if (getpeername(STDIN, (struct sockaddr *)&ss, &length) < 0) {
2134 if (!isatty(STDIN)) {
2135 syslog(L_TRACE, "%s cant getpeername %m", "?");
2136 (void)strcpy(ClientHost, "?"); /* so stats generation looks correct. */
2137 @@ -437,14 +512,18 @@
2138 ExitWithStats(1, TRUE);
2140 (void)strcpy(ClientHost, "stdin");
2142 + memset(&ClientIP, 0, sizeof(ClientIP));
2143 ServerHost[0] = '\0';
2147 - if (sin.sin_family != AF_INET) {
2149 + if (ss.ss_family != AF_INET && ss.ss_family != AF_INET6) {
2151 + if (ss.ss_family != AF_INET) {
2152 +#endif /* defined(INET6) */
2153 syslog(L_ERROR, "%s bad_address_family %ld",
2154 - "?", (long)sin.sin_family);
2155 + "?", (long)ss.ss_family);
2156 Printf("%d Bad address family. Goodbye.\r\n", NNTP_ACCESS_VAL);
2157 ExitWithStats(1, TRUE);
2160 /* Get client's name. */
2161 #if defined(DO_NNRP_GETHOSTBYADDR)
2162 HostErrorStr = NULL;
2163 - if (!Address2Name(&sin.sin_addr, ClientHost, (int)sizeof ClientHost)) {
2164 - (void)strcpy(ClientHost, inet_ntoa(sin.sin_addr));
2165 + if (!Address2Name(&ss, ClientHost, (int)sizeof ClientHost)) {
2166 + (void)strcpy(ClientHost, Inet_NtoA(&ss));
2167 if (HostErrorStr == NULL) {
2169 "? cant gethostbyaddr %s %m -- using IP address for access",
2170 @@ -464,32 +543,32 @@
2171 ClientHost, HostErrorStr);
2173 ClientAddr = ClientHost;
2174 - ClientIP = inet_addr(ClientHost);
2175 + (void)memcpy(&ClientIP, &ss, sizeof(ss));
2179 - (void)strcpy(buff, inet_ntoa(sin.sin_addr));
2180 - ClientIP = inet_addr(buff);
2181 + (void)strcpy(buff, Inet_NtoA(&ss));
2182 + (void)memcpy(&ClientIP, &ss, sizeof(ss));
2185 - (void)strcpy(ClientHost, inet_ntoa(sin.sin_addr));
2186 - ClientIP = inet_addr(ClientHost);
2187 + (void)strcpy(ClientHost, Inet_NtoA(&ss));
2188 + (void)memcpy(&ClientIP, &ss, sizeof(ss));
2189 #endif /* defined(DO_NNRP_GETHOSTBYADDR) */
2190 - (void)strncpy(ClientIp, inet_ntoa(sin.sin_addr), sizeof(ClientIp));
2191 - length = sizeof sin;
2192 - if (getsockname(STDIN, (struct sockaddr *)&sin, &length) < 0) {
2193 + (void)strncpy(ClientIp, Inet_NtoA(&ss), sizeof(ClientIp));
2194 + length = sizeof ss;
2195 + if (getsockname(STDIN, (struct sockaddr *)&ss, &length) < 0) {
2196 syslog(L_NOTICE, "%s can't getsockname %m", ClientHost);
2197 Printf("%d Can't figure out where you connected to. Goodbye\r\n", NNTP_ACCESS_VAL);
2198 ExitWithStats(1, TRUE);
2200 #ifdef DO_NNRP_GETHOSTBYADDR
2201 HostErrorStr = NULL;
2202 - if (!Address2Name(&sin.sin_addr, ServerHost, sizeof(ServerHost))) {
2203 - strcpy(ServerHost, inet_ntoa(sin.sin_addr));
2204 + if (!Address2Name(&ss, ServerHost, sizeof(ServerHost))) {
2205 + strcpy(ServerHost, Inet_NtoA(&ss));
2206 /* suppress error reason */
2209 - strcpy(ServerHost, inet_ntoa(sin.sin_addr));
2210 + strcpy(ServerHost, Inet_NtoA(&ss));
2211 #endif /* DO_NNRP_GETHOSTBYADDR */
2214 @@ -741,9 +820,14 @@
2216 unsigned short ListenPort = NNTP_PORT;
2217 unsigned long ListenAddr = htonl(INADDR_ANY);
2219 + int lfd[2], fd, maxfd, tmpfd;
2222 + struct sockaddr_in6 ListenAddr6;
2225 - struct sockaddr_in ssa, csa;
2226 + struct sockaddr_in ssa;
2227 + struct sockaddr_storage csa;
2231 @@ -777,17 +861,27 @@
2233 openlog("nnrpd", L_OPENLOG_FLAGS | LOG_PID, LOG_INN_PROG);
2236 + memset(&ListenAddr6, '\0', sizeof(ListenAddr6));
2239 if (ReadInnConf() < 0) exit(1);
2242 - while ((i = getopt(argc, argv, "b:Di:g:op:Rr:s:tS")) != EOF)
2243 + while ((i = getopt(argc, argv, "6:b:Di:g:op:Rr:s:tS")) != EOF)
2245 - while ((i = getopt(argc, argv, "b:Di:g:op:Rr:s:t")) != EOF)
2246 + while ((i = getopt(argc, argv, "6:b:Di:g:op:Rr:s:t")) != EOF)
2247 #endif /* HAVE_SSL */
2252 + case '6': /* bind to a certain ipv6 address in
2255 + inet_pton(AF_INET6, optarg, &ListenAddr6.sin6_addr);
2258 case 'b': /* bind to a certain address in
2260 ListenAddr = inet_addr(optarg);
2261 @@ -849,12 +943,12 @@
2262 SPOOLlen = strlen(innconf->patharticles);
2265 - if ((lfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
2266 + if ((lfd[0] = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
2267 syslog(L_FATAL, "can't open socket (%m)");
2271 - if (setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(one)) < 0) {
2272 + if (setsockopt(lfd[0], SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(one)) < 0) {
2273 syslog(L_FATAL, "can't setsockopt(SO_REUSEADDR) (%m)");
2276 @@ -864,11 +958,38 @@
2277 ssa.sin_addr.s_addr = ListenAddr;
2278 ssa.sin_port = htons(ListenPort);
2280 - if (bind(lfd, (struct sockaddr *) &ssa, sizeof(ssa)) < 0) {
2281 + if (bind(lfd[0], (struct sockaddr *) &ssa, sizeof(ssa)) < 0) {
2282 fprintf(stderr, "%s: can't bind (%s)\n", argv[0], strerror(errno));
2283 syslog(L_FATAL, "can't bind local address (%m)");
2289 + if (innconf->bindipv6address) {
2290 + if ((lfd[1] = socket(AF_INET6, SOCK_STREAM, 0)) < 0) {
2291 + syslog(L_FATAL, "can't open socket(%m)");
2294 + if (setsockopt(lfd[1], SOL_SOCKET, SO_REUSEADDR, (char *)&one,
2295 + sizeof(one)) < 0) {
2296 + syslog(L_FATAL, "can't setsockopt(SO_REUSEADDR) (%m)");
2299 + ListenAddr6.sin6_family = AF_INET6;
2300 + ListenAddr6.sin6_port = htons(ListenPort);
2301 +#ifdef HAVE_SOCKADDR_LEN
2302 + ListenAddr6.sin6_len = sizeof(ListenAddr6);
2304 + if (bind(lfd[1], (struct sockaddr *)&ListenAddr6,
2305 + sizeof(ListenAddr6)) < 0) {
2306 + fprintf(stderr, "%s: can't bind (%s)\n", argv[0],
2308 + syslog(L_FATAL, "can't bind local address (%m)");
2314 /* If started as root, switch to news uid */
2315 if (getuid() == 0) {
2316 @@ -953,11 +1074,33 @@
2318 TITLEset("nnrpd: accepting connections");
2321 + listen(lfd[0], 128);
2323 + if (lfd[1] != -1) {
2324 + if (maxfd < lfd[1])
2326 + listen(lfd[1], 128);
2332 + FD_SET(lfd[0], &fds);
2334 + FD_SET(lfd[1], &fds);
2336 + if (select(maxfd, &fds, NULL, NULL, NULL) < 0) {
2337 + syslog(L_FATAL, "%s: select cause error (%m)");
2342 - fd = accept(lfd, (struct sockaddr *) &csa, &clen);
2343 + if (FD_ISSET(lfd[0], &fds))
2345 + else if (lfd[1] != -1 && FD_ISSET(lfd[1], &fds))
2347 + fd = accept(tmpfd, (struct sockaddr *) &csa, &clen);
2352 @@ -980,7 +1123,9 @@
2354 /* child process starts here */
2355 TITLEset("nnrpd: connected");
2363 diff -Nur inn-2.3.2.orig/nnrpd/nnrpd.h inn-2.3.2/nnrpd/nnrpd.h
2364 --- inn-2.3.2.orig/nnrpd/nnrpd.h Thu May 3 22:27:32 2001
2365 +++ inn-2.3.2/nnrpd/nnrpd.h Tue Jun 19 16:06:41 2001
2370 +#ifndef HAVE_SOCKADDR_STORAGE
2371 +#include "sockaddr_storage.h"
2375 ** Maximum input line length, sigh.
2378 ** Some convenient shorthands.
2380 -typedef struct in_addr INADDR;
2381 +typedef struct sockaddr_storage INADDR;
2386 EXTERN char ClientHost[SMBUF];
2387 EXTERN char ServerHost[SMBUF];
2388 EXTERN char Username[SMBUF];
2389 -EXTERN char ClientIp[20];
2390 +EXTERN char ClientIp[64];
2391 EXTERN char LogName[256] ;
2392 extern char *ACTIVETIMES;
2393 extern char *HISTORY;
2395 EXTERN long POSTrejected;
2397 EXTERN BOOL BACKOFFenabled;
2398 -EXTERN long ClientIP;
2399 +EXTERN INADDR ClientIP;
2400 EXTERN char *VirtualPath;
2401 EXTERN int VirtualPathlen;
2403 diff -Nur inn-2.3.2.orig/nnrpd/perm.c inn-2.3.2/nnrpd/perm.c
2404 --- inn-2.3.2.orig/nnrpd/perm.c Thu May 3 22:27:32 2001
2405 +++ inn-2.3.2/nnrpd/perm.c Tue Jun 19 16:06:41 2001
2406 @@ -1488,6 +1488,10 @@
2407 if (!ret && (p = strchr(pat, '/')) != (char *)NULL) {
2409 struct in_addr ia, net;
2412 + struct in6_addr ia6, net6;
2417 @@ -1505,6 +1509,23 @@
2418 if ((ia.s_addr & mask) == (net.s_addr & mask))
2422 + if (inet_pton(AF_INET6, ClientIp, &ia6) == 1 &&
2423 + inet_pton(AF_INET6, pat, &net6) == 1) {
2424 + if (strchr(p+1, '.') == (char *)NULL) {
2428 + for (c = 0; c < n; c++)
2429 + if (ia6.s6_addr[c] != net6.s6_addr[c])
2432 + (ia6.s6_addr[c] & (0x00ff << (8 - bits))) ==
2433 + (net6.s6_addr[c] & (0x00ff << (8 - bits))))
2441 diff -Nur inn-2.3.2.orig/samples/inn.conf.in inn-2.3.2/samples/inn.conf.in
2442 --- inn-2.3.2.orig/samples/inn.conf.in Thu May 3 22:27:32 2001
2443 +++ inn-2.3.2/samples/inn.conf.in Tue Jun 19 16:06:41 2001
2446 pathspool: @SPOOLDIR@
2451 +listenonipv6: @ipv6@