! ! Make ftp work on IPv6-only hosts where we cannot open an IPv4 ! socket to query buffer sizes. ! ! While here make it possible to compile ftp without INET as we ! seem to have supported to compile without INET6. The result ! is not perfect but a start. ! ! Add FreeBSD specific feature_present(3) checks to allow a binary ! compiled with both IPv4 and IPv6 support to also work without ! troubles on INET only or INET6 only kernels. ! ! Reviewed by: ! Sponsored by: The FreeBSD Foundation ! Sponsored by: iXsystems ! Index: usr.bin/ftp/Makefile =================================================================== --- usr.bin/ftp/Makefile (revision 222278) +++ usr.bin/ftp/Makefile (working copy) @@ -18,6 +18,9 @@ SRCS= cmds.c cmdtab.c complete.c domacro.c fetch.c .if ${MK_INET6_SUPPORT} != "no" CFLAGS+= -DINET6 .endif +.if ${MK_INET_SUPPORT} != "no" +CFLAGS+= -DINET +.endif CFLAGS+= -I${.CURDIR} -I${LUKEMFTP} LDADD= -ledit -ltermcap -lutil Index: contrib/lukemftp/src/main.c =================================================================== --- contrib/lukemftp/src/main.c (revision 222278) +++ contrib/lukemftp/src/main.c (working copy) @@ -204,7 +204,23 @@ main(int argc, char *argv[]) * call no socket buffer sizes will have been modified, so we are * guaranteed to get the system defaults. */ - s = socket(AF_INET, SOCK_STREAM, 0); + s = -1; +#ifdef INET6 + if (s < 0 +#ifdef __FreeBSD__ + && feature_present("inet6") +#endif + ) + s = socket(AF_INET6, SOCK_STREAM, 0); +#endif /* INET6 */ +#ifdef INET + if (s < 0 +#ifdef __FreeBSD__ + && feature_present("inet") +#endif + ) + s = socket(AF_INET, SOCK_STREAM, 0); +#endif /* INET6 */ if (s == -1) err(1, "can't create socket"); slen = sizeof(rcvbuf_size); @@ -289,15 +305,33 @@ main(int argc, char *argv[]) while ((ch = getopt(argc, argv, "46AadefginN:o:pP:q:r:RtT:u:vV")) != -1) { switch (ch) { case '4': +#ifdef INET +#ifdef __FreeBSD__ + if (feature_present("inet")) + family = AF_INET; + else + warnx("INET support is not available; ignoring -4"); +#else family = AF_INET; +#endif /* __FreeBSD__ */ +#else + warnx("INET support is not available; ignoring -4"); +#endif /* INET */ break; case '6': #ifdef INET6 +#ifdef __FreeBSD__ + if (feature_present("inet6")) + family = AF_INET6; + else + warnx("INET6 support is not available; ignoring -6"); +#else family = AF_INET6; +#endif /* __FreeBSD__ */ #else warnx("INET6 support is not available; ignoring -6"); -#endif +#endif /* INET */ break; case 'A': Index: contrib/lukemftp/src/ftp.c =================================================================== --- contrib/lukemftp/src/ftp.c (revision 222278) +++ contrib/lukemftp/src/ftp.c (working copy) @@ -141,7 +141,10 @@ static int empty(FILE *, FILE *, int); struct sockinet { union sockunion { + struct sockaddr su_sa; +#ifdef INET struct sockaddr_in su_sin; +#endif #ifdef INET6 struct sockaddr_in6 su_sin6; #endif @@ -154,10 +157,18 @@ struct sockinet { #if !HAVE_SOCKADDR_SA_LEN # define su_len si_len #else -# define su_len si_su.su_sin.sin_len +# define su_len si_su.su_sa.sa_len +#endif /* !HAVE_SOCKADDR_SA_LEN */ +#define su_family si_su.su_sa.sa_family +#ifdef INET6 +#define su_port si_su.su_sin6.sin6_port +#else +#ifdef INET +#define su_port si_su.su_sin.sin_port +#else +#error Need either INET6 or INET support. #endif -#define su_family si_su.su_sin.sin_family -#define su_port si_su.su_sin.sin_port +#endif struct sockinet myctladdr, hisctladdr, data_addr; @@ -1302,6 +1313,7 @@ initconn(void) } result = COMPLETE + 1; switch (data_addr.su_family) { +#ifdef INET case AF_INET: if (epsv4 && !epsv4bad) { pasvcmd = "EPSV"; @@ -1333,6 +1345,7 @@ initconn(void) return (1); } break; +#endif #ifdef INET6 case AF_INET6: pasvcmd = "EPSV"; @@ -1384,6 +1397,7 @@ initconn(void) * one-byte unsigned integer values, separated by commas. */ if (strcmp(pasvcmd, "PASV") == 0) { +#ifdef INET if (data_addr.su_family != AF_INET) { fputs( "Passive mode AF mismatch. Shouldn't happen!\n", ttyout); @@ -1412,6 +1426,12 @@ initconn(void) data_addr.si_su.su_sin.sin_addr.s_addr = htonl(pack4(addr, 0)); data_addr.su_port = htons(pack2(port, 0)); +#else + fputs( + "Passive mode INET not supported. Shouldn't happen!\n", ttyout); + error = 1; + goto bad; +#endif } else if (strcmp(pasvcmd, "LPSV") == 0) { if (code / 10 == 22 && code != 228) { fputs("wrong server: return code must be 228\n", @@ -1420,6 +1440,7 @@ initconn(void) goto bad; } switch (data_addr.su_family) { +#ifdef INET case AF_INET: error = sscanf(pasv, "%u,%u,%u,%u,%u,%u,%u,%u,%u", @@ -1447,6 +1468,7 @@ initconn(void) htonl(pack4(addr, 0)); data_addr.su_port = htons(pack2(port, 0)); break; +#endif #ifdef INET6 case AF_INET6: error = sscanf(pasv, @@ -1590,12 +1612,14 @@ initconn(void) struct sockinet tmp; switch (data_addr.su_family) { +#ifdef INET case AF_INET: if (!epsv4 || epsv4bad) { result = COMPLETE + 1; break; } /* FALLTHROUGH */ +#endif #ifdef INET6 case AF_INET6: #endif @@ -1631,6 +1655,7 @@ initconn(void) goto skip_port; switch (data_addr.su_family) { +#ifdef INET case AF_INET: a = (char *)&data_addr.si_su.su_sin.sin_addr; p = (char *)&data_addr.su_port; @@ -1638,6 +1663,7 @@ initconn(void) UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1])); break; +#endif #ifdef INET6 case AF_INET6: a = (char *)&data_addr.si_su.su_sin6.sin6_addr;