[leafnode-list] IPv6 support for fetchnews

J.H.M. Dassen (Ray) fsmla at xinara.org
Sun Mar 28 18:05:27 CEST 2004


[Please Cc:, I'm not on this list]

I just noticed that fetchnews unfortunately doesn't support IPv6 connections
as nntputil.c's nntpconnect function is IPv4-specific. As the only
newsserver I currently have access to is an IPv6-only one, I'd love to see
fetchnews support IPv6. I've messed around a bit, using code I contributed
to slrn and have gotten it to the point where it can establish an IPv6
socket connection. 

Unfortunately I don't currently have time to make a proper patch, so I'm
attaching my work-in-progress, hoping someone will pick things up from here.
It shows how to establish the socket connection in an address family
independent way. If you want to turn it into real IPv6 support, you should
refactor that code into the complete nntpconnect's flow (fdopen, signal
handling, inital NNTP stuff, error handling).

Regards,
Ray
-- 
Obsig: developing a new sig
-------------- next part --------------
diff -ruN leafnode-1.9.52.rc11/config.h.in leafnode-1.9.52.rc11-wip/config.h.in
--- leafnode-1.9.52.rc11/config.h.in	2004-03-27 12:34:02.000000000 +0100
+++ leafnode-1.9.52.rc11-wip/config.h.in	2004-03-28 16:46:37.000000000 +0200
@@ -13,9 +13,15 @@
 /* Define to 1 if you have the `fork' function. */
 #undef HAVE_FORK
 
+/* Define to 1 if you have the `getaddrinfo' function. */
+#undef HAVE_GETADDRINFO
+
 /* Define to 1 if you have the `getline' function. */
 #undef HAVE_GETLINE
 
+/* Define to 1 if you have the `getnameinfo' function. */
+#undef HAVE_GETNAMEINFO
+
 /* Define to 1 if you have the <inttypes.h> header file. */
 #undef HAVE_INTTYPES_H
 
diff -ruN leafnode-1.9.52.rc11/configure.ac leafnode-1.9.52.rc11-wip/configure.ac
--- leafnode-1.9.52.rc11/configure.ac	2004-03-27 12:33:28.000000000 +0100
+++ leafnode-1.9.52.rc11-wip/configure.ac	2004-03-28 16:45:51.000000000 +0200
@@ -17,6 +17,7 @@
     AC_DEFINE(HAVE_IPV6, 1, [Define to 1 this to compile with IPv6 support for leafnode.])
   fi
 )
+AC_CHECK_FUNCS(getaddrinfo getnameinfo)
 
 dnl check where to put the confdir
 AC_ARG_WITH(confdir,
diff -ruN leafnode-1.9.52.rc11/nntputil.c leafnode-1.9.52.rc11-wip/nntputil.c
--- leafnode-1.9.52.rc11/nntputil.c	2004-03-23 14:00:34.000000000 +0100
+++ leafnode-1.9.52.rc11-wip/nntputil.c	2004-03-28 17:50:45.000000000 +0200
@@ -25,6 +25,7 @@
 #include "leafnode.h"
 #include "mysigact.h"
 
+#include <assert.h>
 #include <fcntl.h>
 #include <sys/uio.h>
 #include <sys/param.h>
@@ -287,6 +288,126 @@
 int
 nntpconnect(const struct server *upstream)
 {
+#ifdef HAVE_GETADDRINFO
+# error INCOMPLETE CODE
+/* This code only illustrates how to get a socket connection to a newsserver in
+ * an address family independent manner.
+*/
+	/* Be AF-independent, so IPv6 works as well */
+	int fd;
+	int connected = 0;
+	static /*@observer@*/ struct servent *sp;
+
+	int port = 0; /* NNTP port number in host order */
+	char portstr[6]; /* To pass a port number as a string */
+
+	/* We need to give a hint to getaddrinfo to get it to resolve a
+	 * numerical port number */
+	struct addrinfo hint;
+
+	struct addrinfo *res, *ai;
+	int tries = 1;
+	int r;
+	char *host;
+	int TCP_Verbose_Reporting = 1;
+
+	if (upstream->port == 0) {
+		sp = getservbyname("nntp", "tcp");
+		if (sp == NULL) {
+			ln_log(LNLOG_SERR, LNLOG_CTOP, "error: unable to find service name nntp/tcp");
+			return FALSE;
+		}
+		port = ntohs(sp->s_port);
+	} else {
+		port = upstream->port;
+	}
+
+	hint.ai_flags = 0;
+	hint.ai_family = PF_UNSPEC;
+	hint.ai_socktype = SOCK_STREAM;
+	hint.ai_protocol = IPPROTO_IP;
+	hint.ai_addrlen = 0;
+	hint.ai_addr = NULL;
+	hint.ai_canonname = NULL;
+	hint.ai_next = NULL;
+
+	host = upstream->name;
+	do {
+		snprintf(portstr, 6, "%i", port);
+		if ((r = getaddrinfo(host, portstr, &hint, &res)) != 0) {
+			if (TCP_Verbose_Reporting) {
+				fprintf (stderr, "Error resolving %s (port %s): %s\n", host, portstr, gai_strerror(r));
+			}
+			if (r == EAI_AGAIN) {
+				sleep (1);
+			};
+		}
+	} while (r && (tries++ <= 3));
+
+	if (r) {
+		fprintf (stderr, "Failed to resolve %s\n", host);
+		return FALSE;
+	}
+	if (TCP_Verbose_Reporting) {
+		fprintf (stderr, "Successfully resolved %s\n", host);
+	}
+
+	ai = res;
+	do { /* Loop over all the list of struct addrinfo returned and try
+	      * to get a socket connection */
+		if (TCP_Verbose_Reporting) {
+			struct sockaddr *a = ai->ai_addr;
+			static char buf[NI_MAXHOST];
+			int l;
+			if (a->sa_family == AF_INET) {
+				l = sizeof(struct sockaddr_in);
+				fprintf (stderr, "Address family: AF_INET\n");
+			} else {
+				assert(a->sa_family == AF_INET6);
+				l = sizeof(struct sockaddr_in6);
+				fprintf (stderr, "Address family: AF_INET6\n");
+			}
+# ifdef HAVE_GETNAMEINFO
+			if (!getnameinfo(a, l, buf, NI_MAXHOST-1, NULL, 0, NI_NUMERICHOST)) {
+				fprintf (stderr, "Will try with address %s", buf);
+			} else {
+				fprintf (stderr, "getnameinfo failed: %s\n", strerror(errno));
+			}
+# endif /* HAVE_GETNAMEINFO */
+		}
+		if ((fd = socket(ai->ai_family, SOCK_STREAM, 0)) == -1) {
+			if (TCP_Verbose_Reporting) {
+				fprintf (stderr, "Error creating socket: %s\n", strerror(errno));
+			}
+		} else {
+			if (TCP_Verbose_Reporting) {
+				fprintf (stderr, "Created socket; descriptor is = %i\n", fd);
+			}
+			if ((r = connect(fd, ai->ai_addr, ai->ai_addrlen)) == 0) {
+				if (TCP_Verbose_Reporting) {
+					fprintf (stderr, "Successfully connected\n");
+				}
+				connected = 1;
+			} else {
+				if (TCP_Verbose_Reporting) {
+					fprintf (stderr, "Error connecting: %i, %s\n", errno, strerror(errno));
+				}
+			}
+		}
+		ai = ai->ai_next;
+	} while ((!connected) && (ai != NULL));
+
+	freeaddrinfo(res);
+
+	if (!connected) {
+		fprintf(stderr, "Unable to make connection. Giving up.\n");
+		return FALSE;
+	}
+	exit(0);
+
+	/* FIXME */
+	return FALSE;
+#else
     struct hostent *hp;
     static /*@observer@*/ struct servent *sp;
     struct servent sp_def;
@@ -294,6 +415,8 @@
     int sock, reply;
     static int i;
 
+/* IPv4 only implementation */
+
     memset((void *)&s_in, 0, sizeof(s_in));
     if (upstream->port == 0) {
 	sp = getservbyname("nntp", "tcp");
@@ -449,6 +572,7 @@
 		"warning: %s: cannot resolve host name: %s", upstream->name, e);
     }
     return FALSE;
+#endif
 }				/* end of connect function */
 
 /*


More information about the leafnode-list mailing list