;; IPv6 patch for UUCP on FreeBSD 2.X or 3.X ;; Jan 29, 2000 by Hajimu UMEMOTO ;; --- gnu/libexec/uucp/Makefile.inc.orig Mon Jun 24 13:22:39 1996 +++ gnu/libexec/uucp/Makefile.inc Fri Jan 28 14:31:03 2000 @@ -16,6 +16,8 @@ LIBUUCP= $(.CURDIR)/../libuucp/libuucp.a .endif +LDADD+= -L/usr/local/v6/lib -linet6 + VERSION= 1.06.1 owner= uucp group= uucp --- gnu/libexec/uucp/libunix/Makefile.orig Sun Aug 29 23:29:22 1999 +++ gnu/libexec/uucp/libunix/Makefile Thu Jan 27 21:58:28 2000 @@ -14,6 +14,7 @@ unknwn.c uuto.c walk.c wldcrd.c work.c xqtfil.c xqtsub.c ftw.c CFLAGS+= -I$(.CURDIR)/../common_sources \ -DOWNER=\"$(owner)\" -DSBINDIR=\"$(libxdir)\" +CFLAGS+= -DINET6 NOMAN= noman NOPROFILE= noprofile --- gnu/libexec/uucp/libunix/tcp.c.orig Sun Aug 29 23:29:27 1999 +++ gnu/libexec/uucp/libunix/tcp.c Fri Jan 28 23:06:00 2000 @@ -131,6 +131,33 @@ { xfree (qconn->psysdep); } + +#ifdef INET6 +static boolean +utcp_init (qsysdep) + struct ssysdep_conn *qsysdep; +{ + if (!qsysdep) + return FALSE; + if (fcntl (qsysdep->o, F_SETFD, + fcntl (qsysdep->o, F_GETFD, 0) | FD_CLOEXEC) < 0) + { + ulog (LOG_ERROR, "fcntl (FD_CLOEXEC): %s", strerror (errno)); + (void) close (qsysdep->o); + qsysdep->o = -1; + return FALSE; + } + + qsysdep->iflags = fcntl (qsysdep->o, F_GETFL, 0); + if (qsysdep->iflags < 0) + { + ulog (LOG_ERROR, "fcntl: %s", strerror (errno)); + (void) close (qsysdep->o); + qsysdep->o = -1; + return FALSE; + } +} +#endif /* Open a TCP connection. If the fwait argument is TRUE, we are running as a server. Otherwise we are just trying to reach another @@ -143,7 +170,12 @@ boolean fwait; { struct ssysdep_conn *qsysdep; +#ifdef INET6 + struct addrinfo hints, *res; + struct sockaddr_storage s; +#else struct sockaddr_in s; +#endif const char *zport; uid_t ieuid; boolean fswap; @@ -152,6 +184,9 @@ qsysdep = (struct ssysdep_conn *) qconn->psysdep; +#ifdef INET6 + qsysdep->o = -1; +#else qsysdep->o = socket (AF_INET, SOCK_STREAM, 0); if (qsysdep->o < 0) { @@ -176,6 +211,7 @@ qsysdep->o = -1; return FALSE; } +#endif /* We save our process ID in the qconn structure. This is checked in ftcp_close. */ @@ -190,11 +226,36 @@ From this point on if the server gets an error we exit; we only return if we have received a connection. It would be more robust to respawn the server if it fails; someday. */ +#ifdef INET6 + zport = qconn->qport->uuconf_u.uuconf_stcp.uuconf_zport; + memset (&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET6; /* XXX: */ + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; + if (getaddrinfo (NULL, zport, &hints, &res)) + { + ulog (LOG_ERROR, "getaddrinfo (NULL, %s): %s", zport, strerror (errno)); + return FALSE; + } + qsysdep->o = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + if (qsysdep->o < 0) + { + freeaddrinfo (res); + ulog (LOG_ERROR, "socket: %s", strerror (errno)); + return FALSE; + } + if (!utcp_init(qsysdep)) + { + freeaddrinfo (res); + return FALSE; + } +#else bzero ((pointer) &s, sizeof s); s.sin_family = AF_INET; zport = qconn->qport->uuconf_u.uuconf_stcp.uuconf_zport; s.sin_port = itcp_port_number (zport); s.sin_addr.s_addr = htonl (INADDR_ANY); +#endif /* Swap to our real user ID when doing the bind call. This will permit the server to use privileged TCP ports when invoked by @@ -208,16 +269,30 @@ { (void) close (qsysdep->o); qsysdep->o = -1; +#ifdef INET6 + freeaddrinfo (res); +#endif return FALSE; } } +#ifdef INET6 + if (bind (qsysdep->o, res->ai_addr, res->ai_addrlen) < 0) + { + freeaddrinfo (res); + if (fswap) + (void) fsuucp_perms ((long) ieuid); + ulog (LOG_FATAL, "bind: %s", strerror (errno)); + } + freeaddrinfo (res); +#else if (bind (qsysdep->o, (struct sockaddr *) &s, sizeof s) < 0) { if (fswap) (void) fsuucp_perms ((long) ieuid); ulog (LOG_FATAL, "bind: %s", strerror (errno)); } +#endif /* Now swap back to the uucp user ID. */ if (fswap) @@ -333,8 +408,13 @@ { struct ssysdep_conn *qsysdep; const char *zhost; +#ifdef INET6 + struct addrinfo hints, *res, *res0; + int connected = FALSE; +#else struct hostent *q; struct sockaddr_in s; +#endif const char *zport; char **pzdialer; @@ -354,6 +434,40 @@ } errno = 0; +#ifdef INET6 + zport = qconn->qport->uuconf_u.uuconf_stcp.uuconf_zport; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = 0; + if (getaddrinfo (zhost, zport, &hints, &res0) != 0) + { + ulog (LOG_ERROR, "getaddrinfo (%s, %s): %s", + zhost, zport, strerror (errno)); + return FALSE; + } + + for (res = res0; res; res = res->ai_next) + { + qsysdep->o = socket (res->ai_family, res->ai_socktype, res->ai_protocol); + if (qsysdep->o < 0) + continue; + if (connect (qsysdep->o, res->ai_addr, res->ai_addrlen) >= 0) + { + connected = TRUE; + break; + } + close(qsysdep->o); + } + freeaddrinfo (res0); + if (!connected) + { + ulog (LOG_ERROR, "connect: %s", strerror (errno)); + return FALSE; + } + if (!utcp_init(qsysdep)) + return FALSE; +#else q = gethostbyname ((char *) zhost); if (q != NULL) { @@ -385,6 +499,7 @@ ulog (LOG_ERROR, "connect: %s", strerror (errno)); return FALSE; } +#endif /* Handle the dialer sequence, if any. */ pzdialer = qconn->qport->uuconf_u.uuconf_stcp.uuconf_pzdialer;