vBulletin Search Engine Optimization
| |||||||
| Register | FAQ | Members List | Calendar | Search | Today's Posts | Mark Forums Read |
| ||||
| apologies, the patch is incorrect, i diff'ed in the wrong direction. please disregard the previous one. this is the correct patch file. thanks Ronnel P. Maglasang wrote: > hi, i have here a patch for ftp-proxy to support both ipv4 and ipv6 ftp > sessions. the codebase was based on OPENBSD_3_6 tag. > > any feedbacks greatly appreciated. > > thanks > - ronnel > > eric wrote: > >> On Fri, 2005-03-18 at 14:10:41 +0800, Ronnel P. Maglasang proclaimed... >> >> >> >>> Hello everyone, I have upgraded the 3.6 ftp-proxy >>> implementation to support ipv6. I have it tested >>> on our local testbed. It now support both ipv4 and >>> ipv6 ftp sessions. Support for ipv6 can be disabled >>> during compilation. Does anyone here know how >>> to contribute my work to the community? >>> >> >> >> Submit a patch to tech@ >> >> > >------------------------------------------------------------------------ > >diff -C 3 -r ftp-proxy-new/Makefile ftp-proxy/Makefile >*** ftp-proxy-new/Makefile Fri Mar 18 16:34:47 2005 >--- ftp-proxy/Makefile Fri Nov 21 07:23:09 2003 >*************** >*** 14,20 **** > DPADD+= ${LIBWRAP} > .endif > >- # For ipv6 support >- CFLAGS+= -DIPV6_SUP >- > .include <bsd.prog.mk> >--- 14,17 ---- >diff -C 3 -r ftp-proxy-new/ftp-proxy.c ftp-proxy/ftp-proxy.c >*** ftp-proxy-new/ftp-proxy.c Fri Mar 18 16:34:13 2005 >--- ftp-proxy/ftp-proxy.c Sun Jul 11 09:54:36 2004 >*************** >*** 55,67 **** > * the real destination address - the tcp wrapper stuff is done after > * the real destination address is retrieved from pf > * >- * Added support for IPv6. >- * Changed all address structures to accomodate IPv4 and IPv6 addresses. >- * Modified processing of EPRT. Added support for processing the response >- * of LPRT to support IPv6 ftp session. >- * >- * - Ronnel Maglasang(rmaglasang@infoweapons.com) >- * www.infoweapons.com > */ > > /* >--- 55,60 ---- >*************** >*** 132,155 **** > > double xfer_start_time; > >- #ifdef IPV6_SUP >- struct sockaddr_storage real_server_sa; >- struct sockaddr_storage client_listen_sa; >- struct sockaddr_storage server_listen_sa; >- struct sockaddr_storage proxy_sa; >- int address_family; >- #else > struct sockaddr_in real_server_sa; > struct sockaddr_in client_listen_sa; > struct sockaddr_in server_listen_sa; > struct sockaddr_in proxy_sa; >- #endif >- >- #ifdef IPV6_SUP >- struct sockaddr_storage src_addr; >- #else > struct in_addr src_addr; >- #endif > > int client_listen_socket = -1; /* Only used in PASV mode */ > int client_data_socket = -1; /* Connected socket to real client */ >--- 125,135 ---- >*************** >*** 166,198 **** > char RealServerName[NI_MAXHOST]; > char OurName[NI_MAXHOST]; > >- #ifdef IPV6_SUP >- char ClientPortName[NI_MAXHOST]; >- char RealServerPortName[NI_MAXHOST]; >- char OurPortName[NI_MAXHOST]; >- #endif >- > char *User = "proxy"; > char *Group; > > extern int Debug_Level; > extern int Use_Rdns; >- #ifdef IPV6_SUP >- extern int Bind_Addr_Flag; >- extern struct sockaddr_storage Bind_Addr; >- #else > extern in_addr_t Bind_Addr; >- #endif > extern char *__progname; > > typedef enum { > UNKNOWN_MODE, > PORT_MODE, > PASV_MODE, >- #ifdef IPV6_SUP >- LPRT_MODE, >- LPSV_MODE, >- #endif > EPRT_MODE, > EPSV_MODE > } connection_mode_t; >--- 146,163 ---- >*************** >*** 281,336 **** > * if we are set to do reverse DNS, otherwise no. > */ > static int >- #ifdef IPV6_SUP >- check_host(struct sockaddr_storage *client_sin, struct sockaddr_storage *server_sin) >- #else > check_host(struct sockaddr_in *client_sin, struct sockaddr_in *server_sin) >- #endif > { > char cname[NI_MAXHOST]; > char sname[NI_MAXHOST]; >- #ifdef IPV6_SUP >- char caddr[NI_MAXHOST]; >- char saddr[NI_MAXHOST]; >- #endif > struct request_info request; > int i; > >- #ifdef IPV6_SUP >- #ifdef DEBUG_LOG >- syslog(LOG_INFO, "entering check_host()\n"); >- #endif >- #endif >- >- #ifdef IPV6_SUP >- /* retrieve client address */ >- i = getnameinfo((struct sockaddr *)client_sin, >- client_sin->ss_len, caddr, sizeof(caddr), >- NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV); >- >- if (i != 0 && i != EAI_NONAME && i != EAI_AGAIN) { >- syslog(LOG_NOTICE, "1 getnameinfo() failed!\n"); >- return(0); >- } >- >- /* retrieve server address */ >- i = getnameinfo((struct sockaddr *)server_sin, >- server_sin->ss_len, saddr, sizeof(saddr), >- NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV); >- >- if (i != 0 && i != EAI_NONAME && i != EAI_AGAIN) { >- syslog(LOG_NOTICE, "2 getnameinfo() failed!\n"); >- return(0); >- } >- >- request_init(&request, RQ_DAEMON, __progname, RQ_CLIENT_SIN, >- client_sin, RQ_SERVER_SIN, server_sin, RQ_CLIENT_ADDR, >- caddr, 0); >- #else > request_init(&request, RQ_DAEMON, __progname, RQ_CLIENT_SIN, > client_sin, RQ_SERVER_SIN, server_sin, RQ_CLIENT_ADDR, > inet_ntoa(client_sin->sin_addr), 0); >- #endif > > if (Use_Rdns) { > /* >--- 246,261 ---- >*************** >*** 339,359 **** > * the tcp wrapper cares about these things, and we don't > * want to pass in a printed address as a name. > */ >- #ifdef IPV6_SUP >- i = getnameinfo((struct sockaddr *)client_sin, >- client_sin->ss_len, cname, sizeof(cname), >- NULL, 0, NI_NAMEREQD); >- >- if (i != 0 && i != EAI_NONAME && i != EAI_AGAIN) >- strlcpy(cname, STRING_UNKNOWN, sizeof(cname)); >- >- i = getnameinfo((struct sockaddr *)server_sin, >- server_sin->ss_len, sname, sizeof(sname), >- NULL, 0, NI_NAMEREQD); >- >- if (i != 0 && i != EAI_NONAME && i != EAI_AGAIN) >- strlcpy(sname, STRING_UNKNOWN, sizeof(sname)); >- #else > i = getnameinfo((struct sockaddr *) &client_sin->sin_addr, > sizeof(&client_sin->sin_addr), cname, sizeof(cname), > NULL, 0, NI_NAMEREQD); >--- 264,269 ---- >*************** >*** 367,373 **** > > if (i != 0 && i != EAI_NONAME && i != EAI_AGAIN) > strlcpy(sname, STRING_UNKNOWN, sizeof(sname)); >- #endif > } else { > /* > * ensure the TCP wrapper doesn't start doing >--- 277,282 ---- >*************** >*** 377,388 **** > strlcpy(sname, STRING_UNKNOWN, sizeof(sname)); > } > >- #ifdef IPV6_SUP >- request_set(&request, RQ_SERVER_ADDR, saddr, 0); >- #else > request_set(&request, RQ_SERVER_ADDR, inet_ntoa(server_sin->sin_addr), > 0); >- #endif > request_set(&request, RQ_CLIENT_NAME, cname, RQ_SERVER_NAME, sname, 0); > > if (!hosts_access(&request)) { >--- 286,293 ---- >*************** >*** 517,528 **** > * Close existing data conn. > */ > >- #ifdef IPV6_SUP >- #ifdef DEBUG_LOG >- syslog(LOG_INFO, "new_dataconn() server: [%d]\n", server); >- #endif >- #endif >- > if (client_listen_socket != -1) { > close(client_listen_socket); > client_listen_socket = -1; >--- 422,427 ---- >*************** >*** 537,549 **** > > if (server) { > bzero(&server_listen_sa, sizeof(server_listen_sa)); >- #ifdef IPV6_SUP >- server_listen_socket = get_backchannel_socket(address_family, >- SOCK_STREAM, min_port, max_port, -1, 1, &server_listen_sa); >- #else > server_listen_socket = get_backchannel_socket(SOCK_STREAM, > min_port, max_port, -1, 1, &server_listen_sa); >- #endif > > if (server_listen_socket == -1) { > syslog(LOG_INFO, "server socket bind() failed (%m)"); >--- 436,443 ---- >*************** >*** 555,567 **** > } > } else { > bzero(&client_listen_sa, sizeof(client_listen_sa)); >- #ifdef IPV6_SUP >- client_listen_socket = get_backchannel_socket(address_family, >- SOCK_STREAM, min_port, max_port, -1, 1, &client_listen_sa); >- #else > client_listen_socket = get_backchannel_socket(SOCK_STREAM, > min_port, max_port, -1, 1, &client_listen_sa); >- #endif > > if (client_listen_socket == -1) { > syslog(LOG_NOTICE, >--- 449,456 ---- >*************** >*** 580,611 **** > static void > connect_pasv_backchannel(void) > { >- #ifdef IPV6_SUP >- struct sockaddr_storage listen_sa; >- #else > struct sockaddr_in listen_sa; >- #endif > socklen_t salen; >- #ifdef IPV6_SUP >- #ifdef DEBUG_LOG >- char host[NI_MAXHOST]; >- char port[NI_MAXHOST]; >- #endif >- #endif > > /* > * We are about to accept a connection from the client. > * This is a PASV data connection. > */ >- #ifdef IPV6_SUP >- #ifdef DEBUG_LOG >- syslog(LOG_INFO, "client listen socket ready"); >- #endif >- >- debuglog(2, "client listen socket ready"); >- #else > debuglog(2, "client listen socket ready"); >- #endif > > close_server_data(); > close_client_data(); >--- 469,482 ---- >*************** >*** 622,662 **** > client_listen_socket = -1; > memset(&listen_sa, 0, sizeof(listen_sa)); > >- #ifdef IPV6_SUP >- server_data_socket = get_backchannel_socket(address_family, SOCK_STREAM, min_port, >- max_port, -1, 1, (struct sockaddr_storage *)&listen_sa); >- #else > server_data_socket = get_backchannel_socket(SOCK_STREAM, min_port, >! max_port, -1, 1, &listen_sa); >! #endif > if (server_data_socket < 0) { > syslog(LOG_NOTICE, "get_backchannel_socket() failed (%m)"); > exit(EX_OSERR); > } >- #ifdef IPV6_SUP >- #ifdef DEBUG_LOG >- getnameinfo((struct sockaddr *)&server_listen_sa, >- server_listen_sa.ss_len, >- host, sizeof(host), >- port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV); >- >- syslog(LOG_INFO, "1 server_data_socket: [%d], host: [%s], port: [%s]\n", >- server_data_socket, host, port); >- >- getnameinfo((struct sockaddr *)&listen_sa, >- listen_sa.ss_len, >- host, sizeof(host), >- port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV); >- >- syslog(LOG_INFO, "2 host: [%s], port: [%s]\n", host, port); >- #endif >- >- if (connect(server_data_socket, (struct sockaddr *) &server_listen_sa, >- server_listen_sa.ss_len) != 0) { >- #else > if (connect(server_data_socket, (struct sockaddr *) &server_listen_sa, > sizeof(server_listen_sa)) != 0) { >- #endif > syslog(LOG_NOTICE, "connect() failed (%m)"); > exit(EX_NOHOST); > } >--- 493,506 ---- > client_listen_socket = -1; > memset(&listen_sa, 0, sizeof(listen_sa)); > > server_data_socket = get_backchannel_socket(SOCK_STREAM, min_port, >! max_port, -1, 1, &listen_sa); > if (server_data_socket < 0) { > syslog(LOG_NOTICE, "get_backchannel_socket() failed (%m)"); > exit(EX_OSERR); > } > if (connect(server_data_socket, (struct sockaddr *) &server_listen_sa, > sizeof(server_listen_sa)) != 0) { > syslog(LOG_NOTICE, "connect() failed (%m)"); > exit(EX_NOHOST); > } >*************** >*** 668,701 **** > static void > connect_port_backchannel(void) > { >- #ifdef IPV6_SUP >- struct sockaddr_storage listen_sa; >- struct sockaddr_in *sockaddr4; >- struct sockaddr_in6 *sockaddr6; >- #else > struct sockaddr_in listen_sa; >- #endif > socklen_t salen; >- #ifdef IPV6_SUP >- #ifdef DEBUG_LOG >- char host[NI_MAXHOST]; >- char port[NI_MAXHOST]; >- #endif >- #endif > > /* > * We are about to accept a connection from the server. > * This is a PORT or EPRT data connection. > */ >- #ifdef IPV6_SUP >- #ifdef DEBUG_LOG >- syslog(LOG_INFO, "server listen socket ready"); >- #endif >- > debuglog(2, "server listen socket ready"); >- #else >- debuglog(2, "server listen socket ready"); >- #endif > > close_server_data(); > close_client_data(); >--- 512,525 ---- >*************** >*** 707,723 **** > syslog(LOG_NOTICE, "accept() failed (%m)"); > exit(EX_OSERR); > } >- #ifdef IPV6_SUP >- #ifdef DEBUG_LOG >- getnameinfo((struct sockaddr *)&listen_sa, >- listen_sa.ss_len, >- host, sizeof(host), >- port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV); >- >- syslog(LOG_INFO, "server_listen_socket: [%d], host: [%s], port: [%s]\n", >- server_listen_socket, host, port); >- #endif >- #endif > close(server_listen_socket); > server_listen_socket = -1; > >--- 531,536 ---- >*************** >*** 728,761 **** > * getting one bound to port 20 - This is deliberately > * not RFC compliant. > */ >- #ifdef IPV6_SUP >- #ifdef DEBUG_LOG >- syslog(LOG_INFO, "running as non-root\n"); >- syslog(LOG_INFO, "address_family: [%d]\n", address_family); >- #endif >- #endif >- >- #ifdef IPV6_SUP >- /* clear address based on address family */ >- if (address_family == AF_INET) { >- sockaddr4 = (struct sockaddr_in *)&listen_sa; >- bzero(&sockaddr4->sin_addr, sizeof(struct in_addr)); >- } >- else { >- sockaddr6 = (struct sockaddr_in6 *)&listen_sa; >- bzero(&sockaddr6->sin6_addr, sizeof(struct in6_addr)); >- } >- #else > bzero(&listen_sa.sin_addr, sizeof(struct in_addr)); >- #endif >- >- #ifdef IPV6_SUP >- client_data_socket = get_backchannel_socket(address_family, SOCK_STREAM, >- min_port, max_port, -1, 1, (struct sockaddr_storage *)&listen_sa); >- #else > client_data_socket = get_backchannel_socket(SOCK_STREAM, >! min_port, max_port, -1, 1, &listen_sa); >! #endif > if (client_data_socket < 0) { > syslog(LOG_NOTICE, "get_backchannel_socket() failed (%m)"); > exit(EX_OSERR); >--- 541,549 ---- > * getting one bound to port 20 - This is deliberately > * not RFC compliant. > */ > bzero(&listen_sa.sin_addr, sizeof(struct in_addr)); > client_data_socket = get_backchannel_socket(SOCK_STREAM, >! min_port, max_port, -1, 1, &listen_sa); > if (client_data_socket < 0) { > syslog(LOG_NOTICE, "get_backchannel_socket() failed (%m)"); > exit(EX_OSERR); >*************** >*** 767,799 **** > * We're root, get our backchannel socket bound to port > * 20 here, so we're fully RFC compliant. > */ >- #ifdef IPV6_SUP >- #ifdef DEBUG_LOG >- syslog(LOG_INFO, "running as root\n"); >- #endif >- #endif >- >- #ifdef IPV6_SUP >- client_data_socket = socket(address_family, SOCK_STREAM, 0); >- >- salen = 1; >- if (address_family == AF_INET) { >- sockaddr4 = (struct sockaddr_in *)&listen_sa; >- sockaddr4->sin_family = AF_INET; >- bcopy(&((struct sockaddr_in *)&src_addr)->sin_addr, >- &sockaddr4->sin_addr, sizeof(struct in_addr)); >- sockaddr4->sin_port = htons(20); >- } >- else { >- } >- #else > client_data_socket = socket(AF_INET, SOCK_STREAM, 0); > > salen = 1; > listen_sa.sin_family = AF_INET; > bcopy(&src_addr, &listen_sa.sin_addr, sizeof(struct in_addr)); > listen_sa.sin_port = htons(20); >- #endif > > if (setsockopt(client_data_socket, SOL_SOCKET, SO_REUSEADDR, > &salen, sizeof(salen)) == -1) { >--- 555,566 ---- >*************** >*** 808,830 **** > } > } > >- #ifdef IPV6_SUP >- #ifdef DEBUG_LOG >- getnameinfo((struct sockaddr *)&client_listen_sa, >- client_listen_sa.ss_len, >- host, sizeof(host), >- port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV); >- >- syslog(LOG_INFO, "client_data_socket: [%d], host: [%s], port: [%s]\n", >- client_data_socket, host, port); >- #endif >- >- if (connect(client_data_socket, (struct sockaddr *) &client_listen_sa, >- client_listen_sa.ss_len) != 0) { >- #else > if (connect(client_data_socket, (struct sockaddr *) &client_listen_sa, > sizeof(client_listen_sa)) != 0) { >- #endif > syslog(LOG_INFO, "cannot connect data channel (%m)"); > exit(EX_NOHOST); > } >--- 575,582 ---- >*************** >*** 840,871 **** > int i, j, rv; > char tbuf[100]; > char *sendbuf = NULL; >- #ifdef IPV6_SUP >- char c_addr_str[NI_MAXHOST]; >- char c_port_str[NI_MAXHOST]; >- char s_addr_str[NI_MAXHOST]; >- char s_port_str[NI_MAXHOST]; >- int ret; >- #endif > > log_control_command((char *)client->line_buffer, 1); > >- #ifdef IPV6_SUP >- #ifdef DEBUG_LOG >- syslog(LOG_INFO, "client->line_buffer: [%s]\n", (char *)client->line_buffer); >- #endif >- #endif >- >- #ifdef IPV6_SUP >- ret = getnameinfo((struct sockaddr *)&server->sa, server->sa.ss_len, s_addr_str, >- sizeof(s_addr_str), NULL, 0, >- NI_NUMERICHOST | NI_NUMERICSERV); >- >- if (ret != 0) { >- strcpy(s_addr_str, "unknown server address"); >- } >- #endif >- > /* client->line_buffer is an ftp control command. > * There is no reason for these to be very long. > * In the interest of limiting buffer overrun attempts, >--- 592,600 ---- >*************** >*** 938,957 **** > goto protounsupp; > > memset(&hints, 0, sizeof(hints)); >- #ifdef IPV6_SUP >- /* Support for both IPV4 and IPV6 */ >- if ((proto != 1) && (proto != 2)) >- goto protounsupp; >- hints.ai_family = AF_UNSPEC; >- hints.ai_socktype = SOCK_STREAM; >- hints.ai_flags = AI_NUMERICHOST; /*no DNS*/ >- #else > if (proto != 1) /* 1 == AF_INET - all we support for now */ > goto protounsupp; > hints.ai_family = AF_INET; > hints.ai_socktype = SOCK_STREAM; > hints.ai_flags = AI_NUMERICHOST; /*no DNS*/ >- #endif > if (getaddrinfo(result[1], result[2], &hints, &res)) > goto parsefail; > if (res->ai_next) >--- 667,677 ---- >*************** >*** 960,987 **** > goto parsefail; > memcpy(&client_listen_sa, res->ai_addr, res->ai_addrlen); > >- #ifdef IPV6_SUP >- ret = getnameinfo(res->ai_addr, res->ai_addrlen, c_addr_str, >- sizeof(c_addr_str), c_port_str, sizeof(c_port_str), >- NI_NUMERICHOST | NI_NUMERICSERV); >- >- if (ret != 0) { >- strcpy(c_addr_str, "unknown client address"); >- strcpy(c_port_str, "unknown client port"); >- } >- >- #ifdef DEBUG_LOG >- syslog(LOG_INFO, "client wants us to use %s:%s", >- c_addr_str, c_port_str); >- #endif >- >- debuglog(1, "client wants us to use %s:%s", >- c_addr_str, c_port_str); >- #else > debuglog(1, "client wants us to use %s:%u", > inet_ntoa(client_listen_sa.sin_addr), > htons(client_listen_sa.sin_port)); >- #endif > > /* > * Configure our own listen socket and tell the server about it >--- 680,688 ---- >*************** >*** 989,1030 **** > new_dataconn(1); > connection_mode = EPRT_MODE; > >- #ifdef IPV6_SUP >- i = getnameinfo((struct sockaddr *)&server_listen_sa, server_listen_sa.ss_len, NULL, >- 0, s_port_str, sizeof(s_port_str), >- NI_NUMERICHOST | NI_NUMERICSERV); >- >- if (ret != 0) { >- strcpy(s_port_str, "unknown server port"); >- } >- >- #ifdef DEBUG_LOG >- syslog(LOG_INFO, "we want server to use %s:%s", >- s_addr_str, s_port_str); >- #endif >- >- debuglog(1, "we want server to use %s:%s", >- s_addr_str, s_port_str); >- #else > debuglog(1, "we want server to use %s:%u", > inet_ntoa(server->sa.sin_addr), > ntohs(server_listen_sa.sin_port)); >- #endif > >- #ifdef IPV6_SUP >- snprintf(tbuf, sizeof(tbuf), "EPRT |%u|%s|%s|\r\n", (unsigned int)proto, >- s_addr_str, s_port_str); >- #else > snprintf(tbuf, sizeof(tbuf), "EPRT |%d|%s|%u|\r\n", 1, > inet_ntoa(server->sa.sin_addr), > ntohs(server_listen_sa.sin_port)); >- #endif >- >- #ifdef IPV6_SUP >- #ifdef DEBUG_LOG >- syslog(LOG_INFO, "to server (modified): %s", tbuf); >- #endif >- #endif > debuglog(1, "to server (modified): %s", tbuf); > sendbuf = tbuf; > goto out; >--- 690,702 ---- >*************** >*** 1034,1044 **** > sendbuf = NULL; > goto out; > protounsupp: >- #ifdef IPV6_SUP >- /* we support AF_INET and AF_INET6 now */ >- snprintf(tbuf, sizeof(tbuf), >- "501 Protocol not supported\r\n"); >- #else > /* we only support AF_INET for now */ > if (proto == 2) > snprintf(tbuf, sizeof(tbuf), >--- 706,711 ---- >*************** >*** 1046,1052 **** > else > snprintf(tbuf, sizeof(tbuf), > "501 Protocol not supported\r\n"); >- #endif > sendbuf = NULL; > out: > if (line) >--- 713,718 ---- >*************** >*** 1099,1109 **** > strlen("port ")) == 0) { > unsigned int values[6]; > char *tailptr; >- #ifdef IPV6_SUP >- struct sockaddr_in *client_sockaddr_in; >- struct sockaddr_in *server_sockaddr_in; >- struct sockaddr_in *server_listen_sockaddr_in; >- #endif > > debuglog(1, "Got a PORT command"); > >--- 765,770 ---- >*************** >*** 1128,1146 **** > } > } > >- #ifdef IPV6_SUP >- client_sockaddr_in = (struct sockaddr_in *)&client_listen_sa; >- client_sockaddr_in->sin_family = AF_INET; >- client_sockaddr_in->sin_addr.s_addr = htonl((values[0] << 24) | >- (values[1] << 16) | (values[2] << 8) | >- (values[3] << 0)); >- >- client_sockaddr_in->sin_port = htons((values[4] << 8) | >- values[5]); >- debuglog(1, "client wants us to use %u.%u.%u.%u:%u", >- values[0], values[1], values[2], values[3], >- (values[4] << 8) | values[5]); >- #else > client_listen_sa.sin_family = AF_INET; > client_listen_sa.sin_addr.s_addr = htonl((values[0] << 24) | > (values[1] << 16) | (values[2] << 8) | >--- 789,794 ---- >*************** >*** 1151,1157 **** > debuglog(1, "client wants us to use %u.%u.%u.%u:%u", > values[0], values[1], values[2], values[3], > (values[4] << 8) | values[5]); >- #endif > > /* > * Configure our own listen socket and tell the server about it >--- 799,804 ---- >*************** >*** 1159,1197 **** > new_dataconn(1); > connection_mode = PORT_MODE; > >- #ifdef IPV6_SUP >- i = getnameinfo((struct sockaddr *)&server_listen_sa, server_listen_sa.ss_len, NULL, >- 0, s_port_str, sizeof(s_port_str), >- NI_NUMERICHOST | NI_NUMERICSERV); >- >- if (ret != 0) { >- strcpy(s_port_str, "unknown server port"); >- } >- >- #ifdef DEBUG_LOG >- syslog(LOG_INFO, "we want server to use %s:%s", >- s_addr_str, s_port_str); >- #endif >- >- debuglog(1, "we want server to use %s:%s", >- s_addr_str, s_port_str); >- #else > debuglog(1, "we want server to use %s:%u", > inet_ntoa(server->sa.sin_addr), > ntohs(server_listen_sa.sin_port)); >- #endif > >- #ifdef IPV6_SUP >- server_sockaddr_in = (struct sockaddr_in *)&server->sa; >- server_listen_sockaddr_in = (struct sockaddr_in *)&server_listen_sa; >- snprintf(tbuf, sizeof(tbuf), "PORT %u,%u,%u,%u,%u,%u\r\n", >- ((u_char *)&server_sockaddr_in->sin_addr.s_addr)[0], >- ((u_char *)&server_sockaddr_in->sin_addr.s_addr)[1], >- ((u_char *)&server_sockaddr_in->sin_addr.s_addr)[2], >- ((u_char *)&server_sockaddr_in->sin_addr.s_addr)[3], >- ((u_char *)&server_listen_sockaddr_in->sin_port)[0], >- ((u_char *)&server_listen_sockaddr_in->sin_port)[1]); >- #else > snprintf(tbuf, sizeof(tbuf), "PORT %u,%u,%u,%u,%u,%u\r\n", > ((u_char *)&server->sa.sin_addr.s_addr)[0], > ((u_char *)&server->sa.sin_addr.s_addr)[1], >--- 806,815 ---- >*************** >*** 1199,1211 **** > ((u_char *)&server->sa.sin_addr.s_addr)[3], > ((u_char *)&server_listen_sa.sin_port)[0], > ((u_char *)&server_listen_sa.sin_port)[1]); >- #endif > >- #ifdef IPV6_SUP >- #ifdef DEBUG_LOG >- syslog(LOG_INFO, "to server (modified): %s", tbuf); >- #endif >- #endif > debuglog(1, "to server (modified): %s", tbuf); > > sendbuf = tbuf; >--- 817,823 ---- >*************** >*** 1236,1260 **** > struct in_addr *iap; > static int continuing = 0; > char tbuf[100], *sendbuf, *p; >- #ifdef IPV6_SUP >- struct sockaddr_in *client_sockaddr_in; >- struct sockaddr_in *server_sockaddr_in; >- struct sockaddr_in *proxy_sockaddr_in; >- struct sockaddr_in6 *client_sockaddr_in6; >- struct sockaddr_in6 *server_sockaddr_in6; >- struct sockaddr_in6 *use_sockaddr_in6; >- char host[NI_MAXHOST]; >- char port[NI_MAXHOST]; >- #endif > > log_control_command((char *)server->line_buffer, 0); > >- #ifdef IPV6_SUP >- #ifdef DEBUG_LOG >- syslog(LOG_INFO, "server->line_buffer: [%s]\n", (char *)server->line_buffer); >- #endif >- #endif >- > if (strlen((char *)server->line_buffer) > 512) { > /* > * someone's playing games. Have a cow in the syslogs and >--- 848,856 ---- >*************** >*** 1291,1303 **** > unsigned int values[6]; > char *tailptr; > >- #ifdef IPV6_SUP >- #ifdef DEBUG_LOG >- syslog(LOG_INFO, "PASV reply\n"); >- syslog(LOG_INFO, "address_family: [%d]\n", address_family); >- #endif >- #endif >- > debuglog(1, "Got a PASV reply"); > debuglog(1, "{%s}", (char *)server->line_buffer); > >--- 887,892 ---- >*************** >*** 1328,1359 **** > exit(EX_DATAERR); > } > >- #ifdef IPV6_SUP >- if (address_family == AF_INET) { >- server_sockaddr_in = (struct sockaddr_in *)&server_listen_sa; >- server_sockaddr_in->sin_family = AF_INET; >- server_sockaddr_in->sin_len = sizeof(struct sockaddr_in); >- server_sockaddr_in->sin_addr.s_addr = htonl((values[0] << 24) | >- (values[1] << 16) | (values[2] << 8) | (values[3] << 0)); >- server_sockaddr_in->sin_port = htons((values[4] << 8) | >- values[5]); >- >- #ifdef DEBUG_LOG >- syslog(LOG_INFO, "server wants us to use %s:%u", >- inet_ntoa(server_sockaddr_in->sin_addr), (values[4] << 8) | >- values[5]); >- #endif >- >- debuglog(1, "server wants us to use %s:%u", >- inet_ntoa(server_sockaddr_in->sin_addr), (values[4] << 8) | >- values[5]); >- } >- else { >- syslog(LOG_NOTICE, "failed in do_server_reply(), unknown af: [%d]\n", >- address_family); >- exit(EX_DATAERR); >- } >- #else > server_listen_sa.sin_family = AF_INET; > server_listen_sa.sin_addr.s_addr = htonl((values[0] << 24) | > (values[1] << 16) | (values[2] << 8) | (values[3] << 0)); >--- 917,922 ---- >*************** >*** 1363,1404 **** > debuglog(1, "server wants us to use %s:%u", > inet_ntoa(server_listen_sa.sin_addr), (values[4] << 8) | > values[5]); >- #endif > > new_dataconn(0); > connection_mode = PASV_MODE; >- >- #ifdef IPV6_SUP >- if (ReverseMode) { >- if (address_family == AF_INET) { >- proxy_sockaddr_in = (struct sockaddr_in *)&proxy_sa; >- iap = &(proxy_sockaddr_in->sin_addr); >- } >- } >- else { >- if (address_family == AF_INET) { >- server_sockaddr_in = (struct sockaddr_in *)&server->sa; >- iap = &(server_sockaddr_in->sin_addr); >- } >- } >- >- if (address_family == AF_INET) { >- client_sockaddr_in = (struct sockaddr_in *)&client_listen_sa; >- #ifdef DEBUG_LOG >- syslog(LOG_INFO, "we want client to use %s:%u", inet_ntoa(*iap), >- htons(client_sockaddr_in->sin_port)); >- #endif >- debuglog(1, "we want client to use %s:%u", inet_ntoa(*iap), >- htons(client_sockaddr_in->sin_port)); >- >- snprintf(tbuf, sizeof(tbuf), >- "227 Entering Passive Mode (%u,%u,%u,%u,%u,%u)\r\n", >- ((u_char *)iap)[0], ((u_char *)iap)[1], >- ((u_char *)iap)[2], ((u_char *)iap)[3], >- ((u_char *)&client_sockaddr_in->sin_port)[0], >- ((u_char *)&client_sockaddr_in->sin_port)[1]); >- } >- #else > if (ReverseMode) > iap = &(proxy_sa.sin_addr); > else >--- 926,934 ---- >*************** >*** 1413,1676 **** > ((u_char *)iap)[2], ((u_char *)iap)[3], > ((u_char *)&client_listen_sa.sin_port)[0], > ((u_char *)&client_listen_sa.sin_port)[1]); >- #endif >- > debuglog(1, "to client (modified): %s", tbuf); > sendbuf = tbuf; >! } >! #ifdef IPV6_SUP >! /* >! * Hack to support IPV6. >! * Process LPSV response which includes IPV6 packets. >! * Basically same processing with PASV. >! */ >! else if (code == 228 && !NatMode) { >! >! unsigned int af = 0; >! unsigned int hal = 0; >! unsigned int pal = 0; >! unsigned int h_values[16]; >! unsigned int p_values[2]; >! char *tailptr; >! int x; >! >! #ifdef DEBUG_LOG >! syslog(LOG_INFO, "LPSV reply\n"); >! syslog(LOG_INFO, "address_family: [%d]\n", address_family); >! #endif >! >! /* support only IPV6 */ >! if (address_family != AF_INET6) { >! syslog(LOG_NOTICE, "for LPSV only IPv6 is supported"); >! exit(EX_DATAERR); >! } >! >! debuglog(1, "Got a LPSV reply"); >! debuglog(1, "{%s}", (char *)server->line_buffer); >! >! tailptr = (char *)strchr((char *)server->line_buffer, '('); >! if (tailptr == NULL) { >! tailptr = strrchr((char *)server->line_buffer, ' '); >! if (tailptr == NULL) { >! syslog(LOG_NOTICE, "malformed 228 reply"); >! exit(EX_DATAERR); >! } >! } >! >! tailptr++; /* skip past space or ( */ >! >! /* read af */ >! i = sscanf(tailptr, "%u", &af); >! if (i != 1) { >! syslog(LOG_INFO, "1 malformed LPSV reply (%s)", >! client->line_buffer); >! exit(EX_DATAERR); >! } >! >! #ifdef DEBUG_LOG >! syslog(LOG_INFO, "af: [%d]\n", af); >! #endif >! >! /* move past af */ >! tailptr = (char *)strchr(tailptr, ','); >! if (tailptr == NULL) { >! syslog(LOG_NOTICE, "malformed 228 reply, af not found"); >! exit(EX_DATAERR); >! } >! >! tailptr++; >! >! /* read address length */ >! i = sscanf(tailptr, "%u", &hal); >! if (i != 1) { >! syslog(LOG_INFO, "2 malformed LPSV reply (%s)", >! client->line_buffer); >! exit(EX_DATAERR); >! } >! >! #ifdef DEBUG_LOG >! syslog(LOG_INFO, "hal: [%d]\n", hal); >! #endif >! /* we only support a hack for IPV6 for now */ >! if (hal != 16) { >! syslog(LOG_NOTICE, "malformed 228 reply, address length not supported"); >! exit(EX_DATAERR); >! } >! >! /* move past hal */ >! tailptr = (char *)strchr(tailptr, ','); >! if (tailptr == NULL) { >! syslog(LOG_NOTICE, "malformed 228 reply, hal not found"); >! exit(EX_DATAERR); >! } >! >! tailptr++; >! >! /* read address */ >! bzero(&h_values, sizeof(h_values)); >! i = sscanf(tailptr, "%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u, %u", >! &h_values[0], &h_values[1], &h_values[2], &h_values[3], >! &h_values[4], &h_values[5], &h_values[6], &h_values[7], >! &h_values[8], &h_values[9], &h_values[10], &h_values[11], >! &h_values[12], &h_values[13], &h_values[14], &h_values[15]); >! if (i != 16) { >! syslog(LOG_INFO, "3 malformed LPSV reply (%s)", >! client->line_buffer); >! exit(EX_DATAERR); >! } >! >! /* move past address */ >! #ifdef DEBUG_LOG >! syslog(LOG_INFO, "h_values: "); >! #endif >! for (x = 0; x < i; x++) { >! #ifdef DEBUG_LOG >! syslog(LOG_INFO, "h_values[%d]: %d\n", x, h_values[x]); >! #endif >! if (tailptr != NULL) { >! tailptr = (char *)strchr(tailptr, ','); >! if (tailptr != NULL) >! tailptr++; >! } >! } >! >! if (tailptr == NULL) { >! syslog(LOG_NOTICE, "malformed 228 reply, adderess not found"); >! exit(EX_DATAERR); >! } >! >! /* read port length */ >! i = sscanf(tailptr, "%u", &pal); >! if (i != 1) { >! syslog(LOG_INFO, "4 malformed LPSV reply (%s)", >! client->line_buffer); >! exit(EX_DATAERR); >! } >! >! #ifdef DEBUG_LOG >! syslog(LOG_INFO, "pal: [%d]\n", pal); >! #endif >! /* we only support a hack for IPV6 for now */ >! if (pal != 2) { >! syslog(LOG_NOTICE, "malformed 228 reply, port length not supported"); >! exit(EX_DATAERR); >! } >! >! /* move past pal */ >! tailptr = (char *)strchr(tailptr, ','); >! if (tailptr == NULL) { >! syslog(LOG_NOTICE, "malformed 228 reply, pal not found"); >! exit(EX_DATAERR); >! } >! tailptr++; >! >! /* read port */ >! bzero(&p_values, sizeof(p_values)); >! i = sscanf(tailptr, "%u,%u", &p_values[0], &p_values[1]); >! if (i != 2) { >! syslog(LOG_INFO, "5 malformed LPSV reply (%s)", >! client->line_buffer); >! exit(EX_DATAERR); >! } >! >! #ifdef DEBUG_LOG >! syslog(LOG_INFO, "p_values: "); >! #endif >! for (x = 0; x < i; x++) { >! #ifdef DEBUG_LOG >! syslog(LOG_INFO, "p_values[%d]: %d\n", x, p_values[x]); >! #endif >! >! if (tailptr != NULL) >! tailptr = (char *)strchr(tailptr, ','); >! } >! >! if (address_family == AF_INET6) { >! bzero(&server_listen_sa, sizeof(server_listen_sa)); >! server_sockaddr_in6 = (struct sockaddr_in6 *)&server_listen_sa; >! server_sockaddr_in6->sin6_family = AF_INET6; >! server_sockaddr_in6->sin6_len = sizeof(struct sockaddr_in6); >! server_sockaddr_in6->sin6_port = htons((p_values[0] << 8) | p_values[1]); >! server_sockaddr_in6->sin6_addr.s6_addr[0] = h_values[0]; >! server_sockaddr_in6->sin6_addr.s6_addr[1] = h_values[1]; >! server_sockaddr_in6->sin6_addr.s6_addr[2] = h_values[2]; >! server_sockaddr_in6->sin6_addr.s6_addr[3] = h_values[3]; >! server_sockaddr_in6->sin6_addr.s6_addr[4] = h_values[4]; >! server_sockaddr_in6->sin6_addr.s6_addr[5] = h_values[5]; >! server_sockaddr_in6->sin6_addr.s6_addr[6] = h_values[6]; >! server_sockaddr_in6->sin6_addr.s6_addr[7] = h_values[7]; >! server_sockaddr_in6->sin6_addr.s6_addr[8] = h_values[8]; >! server_sockaddr_in6->sin6_addr.s6_addr[9] = h_values[9]; >! server_sockaddr_in6->sin6_addr.s6_addr[10] = h_values[10]; >! server_sockaddr_in6->sin6_addr.s6_addr[11] = h_values[11]; >! server_sockaddr_in6->sin6_addr.s6_addr[12] = h_values[12]; >! server_sockaddr_in6->sin6_addr.s6_addr[13] = h_values[13]; >! server_sockaddr_in6->sin6_addr.s6_addr[14] = h_values[14]; >! server_sockaddr_in6->sin6_addr.s6_addr[15] = h_values[15]; >! >! getnameinfo((struct sockaddr *)&server_listen_sa, server_listen_sa.ss_len, >! host, sizeof(host), port, sizeof(port), >! NI_NUMERICHOST | NI_NUMERICSERV); >! >! #ifdef DEBUG_LOG >! syslog(LOG_INFO, "server wants us to use %s:%s\n", host, port); >! #endif >! } >! >! new_dataconn(0); >! >! connection_mode = LPSV_MODE; >! >! if (ReverseMode) { >! if (address_family == AF_INET6) { >! use_sockaddr_in6 = (struct sockaddr_in6 *)&proxy_sa; >! } >! } >! else { >! if (address_family == AF_INET6) { >! use_sockaddr_in6 = (struct sockaddr_in6 *)&server->sa; >! } >! } >! >! if (address_family == AF_INET6) { >! client_sockaddr_in6 = (struct sockaddr_in6 *)&client_listen_sa; >! #ifdef DEBUG_LOG >! getnameinfo((struct sockaddr *)&use_sockaddr_in6, use_sockaddr_in6->sin6_len, >! host, sizeof(host), NULL, 0, >! NI_NUMERICHOST | NI_NUMERICSERV); >! syslog(LOG_INFO, "we want client to use %s:%u", host, >! htons(client_sockaddr_in6->sin6_port)); >! #endif >! snprintf(tbuf, sizeof(tbuf), >! "228 Entering Long Passive Mode (%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,% u,%u,%u,%u,%u)\r\n", >! 6, 16, use_sockaddr_in6->sin6_addr.s6_addr[0], >! use_sockaddr_in6->sin6_addr.s6_addr[1], >! use_sockaddr_in6->sin6_addr.s6_addr[2], >! use_sockaddr_in6->sin6_addr.s6_addr[3], >! use_sockaddr_in6->sin6_addr.s6_addr[4], >! use_sockaddr_in6->sin6_addr.s6_addr[5], >! use_sockaddr_in6->sin6_addr.s6_addr[6], >! use_sockaddr_in6->sin6_addr.s6_addr[7], >! use_sockaddr_in6->sin6_addr.s6_addr[8], >! use_sockaddr_in6->sin6_addr.s6_addr[9], >! use_sockaddr_in6->sin6_addr.s6_addr[10], >! use_sockaddr_in6->sin6_addr.s6_addr[11], >! use_sockaddr_in6->sin6_addr.s6_addr[12], >! use_sockaddr_in6->sin6_addr.s6_addr[13], >! use_sockaddr_in6->sin6_addr.s6_addr[14], >! use_sockaddr_in6->sin6_addr.s6_addr[15], >! 2, ((u_char *)&client_sockaddr_in6->sin6_port)[0], >! ((u_char *)&client_sockaddr_in6->sin6_port)[1]); >! } >! >! #ifdef DEBUG_LOG >! syslog(LOG_INFO, "to client (modified): %s", tbuf); >! #endif >! debuglog(1, "to client (modified): %s", tbuf); >! sendbuf = tbuf; >! } >! #endif >! else { > sendit: > sendbuf = (char *)server->line_buffer; > } >--- 943,951 ---- > ((u_char *)iap)[2], ((u_char *)iap)[3], > ((u_char *)&client_listen_sa.sin_port)[0], > ((u_char *)&client_listen_sa.sin_port)[1]); > debuglog(1, "to client (modified): %s", tbuf); > sendbuf = tbuf; >! } else { > sendit: > sendbuf = (char *)server->line_buffer; > } >*************** >*** 1688,1693 **** >--- 963,969 ---- > else if (rv != -1) > j += rv; > } while (j >= 0 && j < i); >+ > } > > int >*************** >*** 1703,1728 **** > #ifdef LIBWRAP > int use_tcpwrapper = 0; > #endif /* LIBWRAP */ >- #ifdef IPV6_SUP >- struct addrinfo hints; >- struct addrinfo *res; >- #ifdef DEBUG_LOG >- char addr_str[NI_MAXHOST]; >- char port_str[NI_MAXHOST]; >- #endif >- #endif >- >- #ifdef IPV6_SUP >- openlog(__progname, LOG_NDELAY|LOG_PID, LOG_DAEMON); >- #ifdef DEBUG_LOG >- syslog(LOG_INFO, "Starting ftp-proxy... argc: [%d]\n", argc); >- >- for (i=0; i< argc; i++) >- { >- syslog(LOG_INFO, " argv[%d]: [%s]\n", i, argv[i]); >- } >- #endif >- #endif > > while ((ch = getopt(argc, argv, "a > char *p; >--- 979,984 ---- >*************** >*** 1730,1765 **** > case 'a': > if (!*optarg) > usage(); >- #ifdef IPV6_SUP >- Bind_Addr_Flag = 1; >- >- bzero(&hints, sizeof(hints)); >- hints.ai_family = PF_UNSPEC; >- hints.ai_socktype = SOCK_STREAM; >- hints.ai_flags = AI_NUMERICHOST; >- if (getaddrinfo(optarg, NULL, &hints, &res) != 0) { >- syslog(LOG_NOTICE, >- "%s: invalid address", optarg); >- usage(); >- } >- >- memcpy(&Bind_Addr, res->ai_addr, res->ai_addrlen); >- >- #ifdef DEBUG_LOG >- getnameinfo((struct sockaddr *)&Bind_Addr, >- Bind_Addr.ss_len, addr_str, sizeof(addr_str), >- NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV); >- >- syslog(LOG_INFO, "Bind Address: [%s]\n", addr_str); >- #endif >- freeaddrinfo(res); >- #else > if ((Bind_Addr = inet_addr(optarg)) == INADDR_NONE) { > syslog(LOG_NOTICE, > "%s: invalid address", optarg); > usage(); > } >- #endif > break; > case 'A': > AnonFtpOnly = 1; /* restrict to anon usernames only */ >--- 986,996 ---- >*************** >*** 1793,1874 **** > Use_Rdns = 1; /* look up hostnames */ > break; > case 'R': { >- #ifdef IPV6_SUP >- char *s, *t, *b, *a, *p; >- >- if (!*optarg) >- usage(); >- >- if ((s = strdup(optarg)) == NULL) { >- syslog (LOG_NOTICE, >- "Insufficient memory (malloc failed)"); >- exit(EX_UNAVAILABLE); >- } >- >- a = strchr(s, '['); >- if (a != NULL) { >- /* IPV6 address */ >- a++; >- >- if (a == NULL) { >- syslog(LOG_NOTICE, >- "%s: invalid address or port", optarg); >- usage(); >- } >- >- p = strchr(a, ']'); >- if (p == NULL) { >- syslog(LOG_NOTICE, >- "%s: invalid address or port", optarg); >- usage(); >- } >- >- b = p; >- >- p = strchr(p, ':'); >- if (p == NULL) { >- p = "21"; >- } >- else { >- p++; >- } >- >- *b = 0; >- } >- else { >- /* IPV6 address */ >- a = s; >- t = strchr(s, ':'); >- if (t == NULL) >- p = "21"; >- else { >- p = t+1; >- *t = 0; >- } >- } >- >- bzero(&hints, sizeof(hints)); >- hints.ai_family = PF_UNSPEC; >- hints.ai_socktype = SOCK_STREAM; >- hints.ai_flags = AI_NUMERICHOST; >- if (getaddrinfo(a, p, &hints, &res) != 0) { >- syslog(LOG_NOTICE, >- "%s: invalid address or port", optarg); >- usage(); >- } >- >- memcpy(&real_server_sa, res->ai_addr, res->ai_addrlen); >- >- #ifdef DEBUG_LOG >- getnameinfo((struct sockaddr *)&real_server_sa, >- real_server_sa.ss_len, addr_str, sizeof(addr_str), >- port_str, sizeof(port_str), NI_NUMERICHOST | NI_NUMERICSERV); >- >- syslog(LOG_INFO, "Reverse Address: [%s]/[%s]\n", addr_str, port_str); >- #endif >- freeaddrinfo(res); >- free(s); >- #else > char *s, *t; > > if (!*optarg) >--- 1024,1029 ---- >*************** >*** 1896,1929 **** > if (real_server_sa.sin_addr.s_addr == INADDR_NONE) > usage(); > free(s); >- #endif > ReverseMode = 1; > break; > } > case 'S': >- #ifdef IPV6_SUP >- bzero(&hints, sizeof(hints)); >- hints.ai_family = PF_UNSPEC; >- hints.ai_socktype = SOCK_STREAM; >- hints.ai_flags = AI_NUMERICHOST; >- if (getaddrinfo(optarg, NULL, &hints, &res) != 0) { >- usage(); >- } >- >- memcpy(&src_addr, res->ai_addr, res->ai_addrlen); >- >- #ifdef DEBUG_LOG >- getnameinfo((struct sockaddr *)&src_addr, >- src_addr.ss_len, addr_str, sizeof(addr_str), >- NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV); >- >- syslog(LOG_INFO, "Source Address: [%s]\n", addr_str); >- #endif >- freeaddrinfo(res); >- #else > if (!inet_aton(optarg, &src_addr)) > usage(); >- #endif > break; > case 't': > timeout_seconds = strtol(optarg, &p, 10); >--- 1051,1062 ---- >*************** >*** 1952,1960 **** > if (max_port < min_port) > usage(); > >- #ifndef IPV6_SUP > openlog(__progname, LOG_NDELAY|LOG_PID, LOG_DAEMON); >- #endif > > setlinebuf(stdout); > setlinebuf(stderr); >--- 1085,1091 ---- >*************** >*** 1987,2022 **** > else > flags = NI_NUMERICHOST | NI_NUMERICSERV; > >- #ifdef IPV6_SUP >- i = getnameinfo((struct sockaddr *)&client_iob.sa, >- client_iob.sa.ss_len, ClientName, sizeof(ClientName), >- ClientPortName, sizeof(ClientPortName), >- flags); >- #else > i = getnameinfo((struct sockaddr *)&client_iob.sa, > sizeof(client_iob.sa), ClientName, sizeof(ClientName), NULL, 0, > flags); >- #endif > > if (i != 0 && i != EAI_NONAME && i != EAI_AGAIN) { > debuglog(2, "name resolution failure (client)"); >- syslog(LOG_INFO, "1 name resolution failure: [%d]\n", i); > exit(EX_OSERR); > } > >- #ifdef IPV6_SUP >- i = getnameinfo((struct sockaddr *)&real_server_sa, >- real_server_sa.ss_len, RealServerName, sizeof(RealServerName), >- RealServerPortName, sizeof(RealServerPortName), flags); >- #else > i = getnameinfo((struct sockaddr *)&real_server_sa, > sizeof(real_server_sa), RealServerName, sizeof(RealServerName), > NULL, 0, flags); >- #endif > > if (i != 0 && i != EAI_NONAME && i != EAI_AGAIN) { > debuglog(2, "name resolution failure (server)"); >- syslog(LOG_INFO, "2 name resolution failure: [%d]\n", i); > exit(EX_OSERR); > } > >--- 1118,1138 ---- >*************** >*** 2027,2061 **** > > client_iob.fd = 0; > >- #ifdef IPV6_SUP >- syslog(LOG_INFO, "accepted connection from %s:%s to %s:%s", ClientName, >- ClientPortName, RealServerName, RealServerPortName); >- #else > syslog(LOG_INFO, "accepted connection from %s:%u to %s:%u", ClientName, > ntohs(client_iob.sa.sin_port), RealServerName, > ntohs(real_server_sa.sin_port)); >- #endif > >- #ifdef IPV6_SUP >- server_iob.fd = get_backchannel_socket(real_server_sa.ss_family, >- SOCK_STREAM, min_port, max_port, >- -1, 1, &server_iob.sa); >- #else > server_iob.fd = get_backchannel_socket(SOCK_STREAM, min_port, max_port, > -1, 1, &server_iob.sa); >- #endif > >- #ifdef IPV6_SUP >- if (connect(server_iob.fd, (struct sockaddr *)&real_server_sa, >- real_server_sa.ss_len) != 0) { >- syslog(LOG_INFO, "cannot connect to %s:%s (%m)", RealServerName, >- RealServerPortName); >- #else > if (connect(server_iob.fd, (struct sockaddr *)&real_server_sa, > sizeof(real_server_sa)) != 0) { > syslog(LOG_INFO, "cannot connect to %s:%u (%m)", RealServerName, > ntohs(real_server_sa.sin_port)); >- #endif > exit(EX_NOHOST); > } > >--- 1143,1159 ---- >*************** >*** 2067,2098 **** > salen = sizeof(server_iob.sa); > getsockname(server_iob.fd, (struct sockaddr *)&server_iob.sa, &salen); > >- #ifdef IPV6_SUP >- i = getnameinfo((struct sockaddr *)&server_iob.sa, >- server_iob.sa.ss_len, OurName, sizeof(OurName), >- OurPortName, sizeof(OurPortName), flags); >- #else > i = getnameinfo((struct sockaddr *)&server_iob.sa, > sizeof(server_iob.sa), OurName, sizeof(OurName), NULL, 0, flags); >- #endif > > if (i != 0 && i != EAI_NONAME && i != EAI_AGAIN) { > debuglog(2, "name resolution failure (local)"); > exit(EX_OSERR); > } > >- #ifdef IPV6_SUP >- #ifdef DEBUG_LOG >- syslog(LOG_INFO, "local socket is %s:%s", OurName, >- OurPortName); >- #endif >- >- debuglog(1, "local socket is %s:%s", OurName, >- OurPortName); >- #else > debuglog(1, "local socket is %s:%u", OurName, > ntohs(server_iob.sa.sin_port)); >- #endif > > /* ignore SIGPIPE */ > bzero(&new_sa, sizeof(new_sa)); >--- 1165,1180 ---- >*************** >*** 2142,2153 **** > int maxfd = 0; > fd_set *fdsp; > >- #ifdef IPV6_SUP >- #ifdef DEBUG_LOG >- syslog(LOG_INFO, "main loop\n"); >- #endif >- #endif >- > if (client_iob.fd > maxfd) > maxfd = client_iob.fd; > if (client_listen_socket > maxfd) >--- 1224,1229 ---- >*************** >*** 2161,2173 **** > if (server_data_socket > maxfd) > maxfd = server_data_socket; > >- #ifdef IPV6_SUP >- #ifdef DEBUG_LOG >- syslog(LOG_INFO, "client is %s; server is %s", >- client_iob.alive ? "alive" : "dead", >- server_iob.alive ? "alive" : "dead"); >- #endif >- #endif > debuglog(3, "client is %s; server is %s", > client_iob.alive ? "alive" : "dead", > server_iob.alive ? "alive" : "dead"); >--- 1237,1242 ---- >*************** >*** 2234,2258 **** > FD_ISSET(client_data_socket, fdsp)) { > int rval; > >- #ifdef IPV6_SUP >- #ifdef DEBUG_LOG >- syslog(LOG_INFO, "transfer: client to server"); >- #endif >- #endif > debuglog(3, "transfer: client to server"); >- #ifdef IPV6_SUP >- rval = xfer_data("client to server", >- client_data_socket, >- server_data_socket, >- &client_iob.sa, >- &real_server_sa); >- #else > rval = xfer_data("client to server", > client_data_socket, > server_data_socket, > client_iob.sa.sin_addr, > real_server_sa.sin_addr); >- #endif > if (rval <= 0) { > close_client_data(); > close_server_data(); >--- 1303,1314 ---- >*************** >*** 2264,2288 **** > FD_ISSET(server_data_socket, fdsp)) { > int rval; > >- #ifdef IPV6_SUP >- #ifdef DEBUG_LOG >- syslog(LOG_INFO, "transfer: server to client"); >- #endif >- #endif > debuglog(3, "transfer: server to client"); >- #ifdef IPV6_SUP >- rval = xfer_data("server to client", >- server_data_socket, >- client_data_socket, >- &real_server_sa, >- &client_iob.sa); >- #else > rval = xfer_data("server to client", > server_data_socket, > client_data_socket, > real_server_sa.sin_addr, > client_iob.sa.sin_addr); >- #endif > if (rval <= 0) { > close_client_data(); > close_server_data(); >--- 1320,1331 ---- >Only in ftp-proxy-new: ftp-proxy.cat8 >diff -C 3 -r ftp-proxy-new/util.c ftp-proxy/util.c >*** ftp-proxy-new/util.c Thu Mar 17 22:37:28 2005 >--- ftp-proxy/util.c Wed Jul 7 03:49:11 2004 >*************** >*** 58,76 **** > > extern int ReverseMode; > >- #ifdef IPV6_SUP >- /* address family type (AF_INET|AF_INET6) */ >- extern int address_family; >- #endif >- > int Debug_Level; > int Use_Rdns; >- #ifdef IPV6_SUP >- int Bind_Addr_Flag = 0; >- struct sockaddr_storage Bind_Addr; >- #else > in_addr_t Bind_Addr = INADDR_NONE; >- #endif > > void debuglog(int debug_level, const char *fmt, ...); > >--- 58,66 ---- >*************** >*** 86,112 **** > } > > int >- #ifdef IPV6_SUP >- get_proxy_env(int connected_fd, struct sockaddr_storage *real_server_sa_ptr, >- struct sockaddr_storage *client_sa_ptr, struct sockaddr_storage *proxy_sa_ptr) >- #else > get_proxy_env(int connected_fd, struct sockaddr_in *real_server_sa_ptr, > struct sockaddr_in *client_sa_ptr, struct sockaddr_in *proxy_sa_ptr) >- #endif > { > struct pfioc_natlook natlook; > socklen_t slen; > int fd; >- #ifdef IPV6_SUP >- struct sockaddr_in *ipv4; >- struct sockaddr_in6 *ipv6; >- char client_host[NI_MAXHOST]; >- char client_port[NI_MAXHOST]; >- char proxy_host[NI_MAXHOST]; >- char proxy_port[NI_MAXHOST]; >- int ret; >- char af; >- #endif > > slen = sizeof(*proxy_sa_ptr); > if (getsockname(connected_fd, (struct sockaddr *)proxy_sa_ptr, >--- 76,87 ---- >*************** >*** 121,216 **** > return(-1); > } > >- #ifdef IPV6_SUP >- ret = getnameinfo((struct sockaddr *)proxy_sa_ptr, >- ((struct sockaddr *)proxy_sa_ptr)->sa_len, >- proxy_host, sizeof(proxy_host), >- proxy_port, sizeof(proxy_port), NI_NUMERICHOST | NI_NUMERICSERV); >- >- if (ret != 0) >- { >- syslog(LOG_INFO, "getnameinfo() failed: [%d]\n", ret); >- return(-1); >- } >- >- #ifdef DEBUG_LOG >- syslog(LOG_INFO, "proxy_host: [%s], proxy_port: [%s]\n", >- proxy_host, proxy_port); >- #endif >- >- /* updated global address family variable */ >- af = ((struct sockaddr *)proxy_sa_ptr)->sa_family; >- switch (af) >- { >- case AF_INET: >- /* set adderss family to AF_INET */ >- address_family = AF_INET; >- break; >- >- case AF_INET6: >- /* set adderss family to AF_INET */ >- address_family = AF_INET6; >- break; >- >- default: >- syslog(LOG_ERR, "unsupported address family: [%d]\n", af); >- return(-1); >- break; >- } >- >- ret = getnameinfo((struct sockaddr *)client_sa_ptr, >- ((struct sockaddr *)client_sa_ptr)->sa_len, >- client_host, sizeof(client_host), >- client_port, sizeof(client_port), NI_NUMERICHOST | NI_NUMERICSERV); >- >- if (ret != 0) >- { >- syslog(LOG_INFO, "getnameinfo() failed: [%d]\n", ret); >- return(-1); >- } >- >- #ifdef DEBUG_LOG >- syslog(LOG_INFO, "client_host: [%s], client_port: [%s]\n", >- client_host, client_port); >- #endif >- #endif >- > if (ReverseMode) > return(0); > >- #ifdef IPV6_SUP >- /* >- * Build up the pf natlook structure. >- * Support only IPV4 and IPV6. >- */ >- memset((void *)&natlook, 0, sizeof(natlook)); >- switch (af) >- { >- case AF_INET: >- natlook.af = AF_INET; >- ipv4 = (struct sockaddr_in *)client_sa_ptr; >- natlook.saddr.addr32[0] = ipv4->sin_addr.s_addr; >- natlook.sport = ipv4->sin_port; >- ipv4 = (struct sockaddr_in *)proxy_sa_ptr; >- natlook.daddr.addr32[0] = ipv4->sin_addr.s_addr; >- natlook.dport = ipv4->sin_port; >- natlook.proto = IPPROTO_TCP; >- natlook.direction = PF_OUT; >- break; >- >- case AF_INET6: >- natlook.af = AF_INET6; >- ipv6 = (struct sockaddr_in6 *)client_sa_ptr; >- natlook.saddr.v6 = ipv6->sin6_addr; >- natlook.sport = ipv6->sin6_port; >- ipv6 = (struct sockaddr_in6 *)proxy_sa_ptr; >- natlook.daddr.v6 = ipv6->sin6_addr; >- natlook.dport = ipv6->sin6_port; >- natlook.proto = IPPROTO_TCP; >- natlook.direction = PF_OUT; >- break; >- } >- #else > /* > * Build up the pf natlook structure. > * Just for IPv4 right now >--- 96,104 ---- >*************** >*** 223,229 **** > natlook.sport = client_sa_ptr->sin_port; > natlook.dport = proxy_sa_ptr->sin_port; > natlook.direction = PF_OUT; >- #endif > > /* > * Open the pf device and lookup the mapping pair to find >--- 111,116 ---- >*************** >*** 236,251 **** > } > > if (ioctl(fd, DIOCNATLOOK, &natlook) == -1) { >- #ifdef IPV6_SUP >- syslog(LOG_INFO, >- "pf nat lookup failed %s:%s (%m)", >- client_host, client_port); >- #else > syslog(LOG_INFO, > "pf nat lookup failed %s:%hu (%m)", > inet_ntoa(client_sa_ptr->sin_addr), > ntohs(client_sa_ptr->sin_port)); >- #endif > close(fd); > return(-1); > } >--- 123,132 ---- >*************** >*** 255,292 **** > * Now jam the original address and port back into the into > * destination sockaddr_in for the proxy to deal with. > */ >- #ifdef IPV6_SUP >- memset((void *)real_server_sa_ptr, 0, sizeof(struct sockaddr_storage)); >- switch (af) >- { >- case AF_INET: >- ipv4 = (struct sockaddr_in *)real_server_sa_ptr; >- ipv4->sin_port = natlook.rdport; >- ipv4->sin_addr.s_addr = natlook.rdaddr.addr32[0]; >- ipv4->sin_len = sizeof(struct sockaddr_in); >- ipv4->sin_family = AF_INET; >- break; >- >- case AF_INET6: >- ipv6 = (struct sockaddr_in6 *)real_server_sa_ptr; >- ipv6->sin6_port = natlook.rdport; >- ipv6->sin6_addr = natlook.rdaddr.v6; >- ipv6->sin6_len = sizeof(struct sockaddr_in6); >- ipv6->sin6_family = AF_INET6; >- break; >- >- default: >- syslog(LOG_ERR, "unsupported address family returned by pf: [%d]\n", af); >- return(-1); >- } >- #else > memset((void *)real_server_sa_ptr, 0, sizeof(struct sockaddr_in)); > real_server_sa_ptr->sin_port = natlook.rdport; > real_server_sa_ptr->sin_addr.s_addr = natlook.rdaddr.addr32[0]; > real_server_sa_ptr->sin_len = sizeof(struct sockaddr_in); > real_server_sa_ptr->sin_family = AF_INET; >- #endif >- > return(0); > } > >--- 136,146 ---- >*************** >*** 297,309 **** > * A unit of data is as much as we get with a single read(2) call. > */ > int >- #ifdef IPV6_SUP >- xfer_data(const char *what_read,int from_fd, int to_fd, struct sockaddr_storage *from, >- struct sockaddr_storage *to) >- #else > xfer_data(const char *what_read,int from_fd, int to_fd, struct in_addr from, > struct in_addr to) >- #endif > { > int rlen, offset, xerrno, mark, flags = 0; > char tbuf[4096]; >--- 151,158 ---- >*************** >*** 367,450 **** > } > } > >- >- #ifdef IPV6_SUP >- /* >- * create sockaddr_storage structure for the INADDR_ANY for both >- * IPV4 and IPV6 address family. >- */ >- int >- create_sockaddr_any(int af, int type, int port, struct sockaddr_storage *sa) >- { >- struct addrinfo hints; >- struct addrinfo *res; >- char port_str[NI_MAXHOST]; >- int ret; >- >- #ifdef DEBUG_LOG >- char addr_buf[NI_MAXHOST]; >- char port_buf[NI_MAXHOST]; >- #endif >- >- bzero(&hints, sizeof(hints)); >- hints.ai_family = af; >- hints.ai_socktype = type; >- hints.ai_flags = AI_NUMERICHOST; >- >- /* convert port into string */ >- snprintf(port_str, NI_MAXHOST, "%d", port); >- >- /* create based on address family type */ >- if (af == AF_INET) >- ret = getaddrinfo("0.0.0.0", port_str, &hints, &res); >- else if (af == AF_INET6) >- ret = getaddrinfo("::", port_str, &hints, &res); >- else { >- syslog(LOG_INFO, "unknown af: [%d]\n", af); >- return(-1); >- } >- >- if (ret != 0) { >- syslog(LOG_INFO, "getaddrinfo() failed: [%d]\n", ret); >- } >- >- /* copy resulting address to our ouput argument */ >- memcpy(sa, res->ai_addr, res->ai_addrlen); >- >- #ifdef DEBUG_LOG >- getnameinfo(res->ai_addr, res->ai_addrlen, addr_buf, >- sizeof(addr_buf), port_buf, sizeof(port_buf), >- NI_NUMERICHOST | NI_NUMERICSERV); >- >- syslog(LOG_INFO, "addr_buf: [%s], port_buf: [%s]\n", addr_buf, port_buf); >- #endif >- freeaddrinfo(res); >- >- return(0); >- } >- #endif >- >- > /* > * get_backchannel_socket gets us a socket bound somewhere in a > * particular range of ports > */ > int >- #ifdef IPV6_SUP >- get_backchannel_socket(int af, int type, int min_port, int max_port, int start_port, >- int direction, struct sockaddr_storage *sap) >- #else > get_backchannel_socket(int type, int min_port, int max_port, int start_port, > int direction, struct sockaddr_in *sap) >- #endif > { > int count; >- #ifdef IPV6_SUP >- #ifdef DEBUG_LOG >- char host[NI_MAXHOST]; >- char port[NI_MAXHOST]; >- #endif >- #endif > > /* > * Make sure that direction is 'defined' and that min_port is not >--- 216,230 ---- >*************** >*** 477,515 **** > } > > while (count-- > 0) { >- #ifdef IPV6_SUP >- struct sockaddr_storage sa; >- struct sockaddr_in *sockaddr4; >- struct sockaddr_in6 *sockaddr6; >- #else > struct sockaddr_in sa; >- #endif > int one, fd; > >- #ifdef IPV6_SUP >- fd = socket(af, type, 0); >- >- bzero(&sa, sizeof(sa)); >- if (Bind_Addr_Flag == 0) { >- if (sap == NULL) { >- if (create_sockaddr_any(af, type, start_port, &sa) != 0) >- return(-1); >- } >- else { >- if ((sap->ss_family == AF_INET) || >- (sap->ss_family == AF_INET6)) { >- memcpy(&sa, sap, sap->ss_len); >- } >- else { >- if (create_sockaddr_any(af, type, start_port, &sa) != 0) >- return(-1); >- } >- } >- } >- else { >- memcpy(&sa, &Bind_Addr, sizeof(sa)); >- } >- #else > fd = socket(AF_INET, type, 0); > > bzero(&sa, sizeof sa); >--- 257,265 ---- >*************** >*** 521,527 **** > sa.sin_addr.s_addr = sap->sin_addr.s_addr; > else > sa.sin_addr.s_addr = Bind_Addr; >- #endif > > /* > * Indicate that we want to reuse a port if it happens that the >--- 271,276 ---- >*************** >*** 532,573 **** > sizeof(one)) == -1) > return(-1); > >- #ifdef IPV6_SUP >- /* update port */ >- if (af == AF_INET) { >- sockaddr4 = (struct sockaddr_in *)&sa; >- sockaddr4->sin_port = htons(start_port); >- } >- else { >- sockaddr6 = (struct sockaddr_in6 *)&sa; >- sockaddr6->sin6_port = htons(start_port); >- } >- #else > sa.sin_port = htons(start_port); >- #endif > >- #ifdef IPV6_SUP >- #ifdef DEBUG_LOG >- getnameinfo((struct sockaddr *)&sa, >- sa.ss_len, >- host, sizeof(host), >- port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV); >- >- syslog(LOG_INFO, "binding to host: [%s], port: [%s]\n", >- host, port); >- #endif >- if (bind(fd, (struct sockaddr *)&sa, sa.ss_len) == 0) { >- #else > if (bind(fd, (struct sockaddr *)&sa, sizeof(sa)) == 0) { >- #endif > if (sap != NULL) > *sap = sa; > return(fd); > } >- >- #ifdef IPV6_SUP >- syslog(LOG_INFO, "bind() failed\n"); >- #endif > > if (errno != EADDRINUSE) > return(-1); >--- 281,293 ---- >diff -C 3 -r ftp-proxy-new/util.h ftp-proxy/util.h >*** ftp-proxy-new/util.h Fri Mar 11 23:30:48 2005 >--- ftp-proxy/util.h Wed Jul 7 03:49:11 2004 >*************** >*** 45,55 **** > int fd; > int line_buffer_size, io_buffer_size, io_buffer_len, next_byte; > unsigned char *io_buffer, *line_buffer; >- #ifdef IPV6_SUP >- struct sockaddr_storage sa, real_sa; >- #else > struct sockaddr_in sa, real_sa; >- #endif > char *who; > char alive, got_eof, data_available; > int send_oob_flags; >--- 45,51 ---- >*************** >*** 58,86 **** > extern int telnet_getline(struct csiob *iobp, > struct csiob *telnet_passthrough); > >- #ifdef IPV6_SUP >- extern int get_proxy_env(int fd, struct sockaddr_storage *server_sa_ptr, >- struct sockaddr_storage *client_sa_ptr, struct sockaddr_storage *proxy_sa_ptr); >- #else > extern int get_proxy_env(int fd, struct sockaddr_in *server_sa_ptr, > struct sockaddr_in *client_sa_ptr, struct sockaddr_in *proxy_sa_ptr); >- #endif > >- #ifdef IPV6_SUP >- extern int get_backchannel_socket(int af, int type, int min_port, int max_port, >- int start_port, int direction, struct sockaddr_storage *sap); >- #else > extern int get_backchannel_socket(int type, int min_port, int max_port, > int start_port, int direction, struct sockaddr_in *sap); >- #endif > >- #ifdef IPV6_SUP >- extern int xfer_data(const char *what_read, int from_fd, int to_fd, >- struct sockaddr_storage *from, struct sockaddr_storage *to); >- #else > extern int xfer_data(const char *what_read, int from_fd, int to_fd, > struct in_addr from, struct in_addr to); >- #endif > > extern char *ProgName; > >--- 54,67 ---- > > diff -C 3 -r ftp-proxy/Makefile ftp-proxy-new/Makefile *** ftp-proxy/Makefile Fri Nov 21 07:23:09 2003 --- ftp-proxy-new/Makefile Fri Mar 18 16:34:47 2005 *************** *** 14,17 **** --- 14,20 ---- DPADD+= ${LIBWRAP} .endif + # For ipv6 support + CFLAGS+= -DIPV6_SUP + .include <bsd.prog.mk> diff -C 3 -r ftp-proxy/ftp-proxy.c ftp-proxy-new/ftp-proxy.c *** ftp-proxy/ftp-proxy.c Sun Jul 11 09:54:36 2004 --- ftp-proxy-new/ftp-proxy.c Fri Mar 18 16:34:13 2005 *************** *** 55,60 **** --- 55,67 ---- * the real destination address - the tcp wrapper stuff is done after * the real destination address is retrieved from pf * + * Added support for IPv6. + * Changed all address structures to accomodate IPv4 and IPv6 addresses. + * Modified processing of EPRT. Added support for processing the response + * of LPRT to support IPv6 ftp session. + * + * - Ronnel Maglasang(rmaglasang@infoweapons.com) + * www.infoweapons.com */ /* *************** *** 125,135 **** --- 132,155 ---- double xfer_start_time; + #ifdef IPV6_SUP + struct sockaddr_storage real_server_sa; + struct sockaddr_storage client_listen_sa; + struct sockaddr_storage server_listen_sa; + struct sockaddr_storage proxy_sa; + int address_family; + #else struct sockaddr_in real_server_sa; struct sockaddr_in client_listen_sa; struct sockaddr_in server_listen_sa; struct sockaddr_in proxy_sa; + #endif + + #ifdef IPV6_SUP + struct sockaddr_storage src_addr; + #else struct in_addr src_addr; + #endif int client_listen_socket = -1; /* Only used in PASV mode */ int client_data_socket = -1; /* Connected socket to real client */ *************** *** 146,163 **** --- 166,198 ---- char RealServerName[NI_MAXHOST]; char OurName[NI_MAXHOST]; + #ifdef IPV6_SUP + char ClientPortName[NI_MAXHOST]; + char RealServerPortName[NI_MAXHOST]; + char OurPortName[NI_MAXHOST]; + #endif + char *User = "proxy"; char *Group; extern int Debug_Level; extern int Use_Rdns; + #ifdef IPV6_SUP + extern int Bind_Addr_Flag; + extern struct sockaddr_storage Bind_Addr; + #else extern in_addr_t Bind_Addr; + #endif extern char *__progname; typedef enum { UNKNOWN_MODE, PORT_MODE, PASV_MODE, + #ifdef IPV6_SUP + LPRT_MODE, + LPSV_MODE, + #endif EPRT_MODE, EPSV_MODE } connection_mode_t; *************** *** 246,261 **** --- 281,336 ---- * if we are set to do reverse DNS, otherwise no. */ static int + #ifdef IPV6_SUP + check_host(struct sockaddr_storage *client_sin, struct sockaddr_storage *server_sin) + #else check_host(struct sockaddr_in *client_sin, struct sockaddr_in *server_sin) + #endif { char cname[NI_MAXHOST]; char sname[NI_MAXHOST]; + #ifdef IPV6_SUP + char caddr[NI_MAXHOST]; + char saddr[NI_MAXHOST]; + #endif struct request_info request; int i; + #ifdef IPV6_SUP + #ifdef DEBUG_LOG + syslog(LOG_INFO, "entering check_host()\n"); + #endif + #endif + + #ifdef IPV6_SUP + /* retrieve client address */ + i = getnameinfo((struct sockaddr *)client_sin, + client_sin->ss_len, caddr, sizeof(caddr), + NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV); + + if (i != 0 && i != EAI_NONAME && i != EAI_AGAIN) { + syslog(LOG_NOTICE, "1 getnameinfo() failed!\n"); + return(0); + } + + /* retrieve server address */ + i = getnameinfo((struct sockaddr *)server_sin, + server_sin->ss_len, saddr, sizeof(saddr), + NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV); + + if (i != 0 && i != EAI_NONAME && i != EAI_AGAIN) { + syslog(LOG_NOTICE, "2 getnameinfo() failed!\n"); + return(0); + } + + request_init(&request, RQ_DAEMON, __progname, RQ_CLIENT_SIN, + client_sin, RQ_SERVER_SIN, server_sin, RQ_CLIENT_ADDR, + caddr, 0); + #else request_init(&request, RQ_DAEMON, __progname, RQ_CLIENT_SIN, client_sin, RQ_SERVER_SIN, server_sin, RQ_CLIENT_ADDR, inet_ntoa(client_sin->sin_addr), 0); + #endif if (Use_Rdns) { /* *************** *** 264,269 **** --- 339,359 ---- * the tcp wrapper cares about these things, and we don't * want to pass in a printed address as a name. */ + #ifdef IPV6_SUP + i = getnameinfo((struct sockaddr *)client_sin, + client_sin->ss_len, cname, sizeof(cname), + NULL, 0, NI_NAMEREQD); + + if (i != 0 && i != EAI_NONAME && i != EAI_AGAIN) + strlcpy(cname, STRING_UNKNOWN, sizeof(cname)); + + i = getnameinfo((struct sockaddr *)server_sin, + server_sin->ss_len, sname, sizeof(sname), + NULL, 0, NI_NAMEREQD); + + if (i != 0 && i != EAI_NONAME && i != EAI_AGAIN) + strlcpy(sname, STRING_UNKNOWN, sizeof(sname)); + #else i = getnameinfo((struct sockaddr *) &client_sin->sin_addr, sizeof(&client_sin->sin_addr), cname, sizeof(cname), NULL, 0, NI_NAMEREQD); *************** *** 277,282 **** --- 367,373 ---- if (i != 0 && i != EAI_NONAME && i != EAI_AGAIN) strlcpy(sname, STRING_UNKNOWN, sizeof(sname)); + #endif } else { /* * ensure the TCP wrapper doesn't start doing *************** *** 286,293 **** --- 377,388 ---- strlcpy(sname, STRING_UNKNOWN, sizeof(sname)); } + #ifdef IPV6_SUP + request_set(&request, RQ_SERVER_ADDR, saddr, 0); + #else request_set(&request, RQ_SERVER_ADDR, inet_ntoa(server_sin->sin_addr), 0); + #endif request_set(&request, RQ_CLIENT_NAME, cname, RQ_SERVER_NAME, sname, 0); if (!hosts_access(&request)) { *************** *** 422,427 **** --- 517,528 ---- * Close existing data conn. */ + #ifdef IPV6_SUP + #ifdef DEBUG_LOG + syslog(LOG_INFO, "new_dataconn() server: [%d]\n", server); + #endif + #endif + if (client_listen_socket != -1) { close(client_listen_socket); client_listen_socket = -1; *************** *** 436,443 **** --- 537,549 ---- if (server) { bzero(&server_listen_sa, sizeof(server_listen_sa)); + #ifdef IPV6_SUP + server_listen_socket = get_backchannel_socket(address_family, + SOCK_STREAM, min_port, max_port, -1, 1, &server_listen_sa); + #else server_listen_socket = get_backchannel_socket(SOCK_STREAM, min_port, max_port, -1, 1, &server_listen_sa); + #endif if (server_listen_socket == -1) { syslog(LOG_INFO, "server socket bind() failed (%m)"); *************** *** 449,456 **** --- 555,567 ---- } } else { bzero(&client_listen_sa, sizeof(client_listen_sa)); + #ifdef IPV6_SUP + client_listen_socket = get_backchannel_socket(address_family, + SOCK_STREAM, min_port, max_port, -1, 1, &client_listen_sa); + #else client_listen_socket = get_backchannel_socket(SOCK_STREAM, min_port, max_port, -1, 1, &client_listen_sa); + #endif if (client_listen_socket == -1) { syslog(LOG_NOTICE, *************** *** 469,482 **** --- 580,611 ---- static void connect_pasv_backchannel(void) { + #ifdef IPV6_SUP + struct sockaddr_storage listen_sa; + #else struct sockaddr_in listen_sa; + #endif socklen_t salen; + #ifdef IPV6_SUP + #ifdef DEBUG_LOG + char host[NI_MAXHOST]; + char port[NI_MAXHOST]; + #endif + #endif /* * We are about to accept a connection from the client. * This is a PASV data connection. */ + #ifdef IPV6_SUP + #ifdef DEBUG_LOG + syslog(LOG_INFO, "client listen socket ready"); + #endif + + debuglog(2, "client listen socket ready"); + #else debuglog(2, "client listen socket ready"); + #endif close_server_data(); close_client_data(); *************** *** 493,506 **** client_listen_socket = -1; memset(&listen_sa, 0, sizeof(listen_sa)); server_data_socket = get_backchannel_socket(SOCK_STREAM, min_port, ! max_port, -1, 1, &listen_sa); if (server_data_socket < 0) { syslog(LOG_NOTICE, "get_backchannel_socket() failed (%m)"); exit(EX_OSERR); } if (connect(server_data_socket, (struct sockaddr *) &server_listen_sa, sizeof(server_listen_sa)) != 0) { syslog(LOG_NOTICE, "connect() failed (%m)"); exit(EX_NOHOST); } --- 622,662 ---- client_listen_socket = -1; memset(&listen_sa, 0, sizeof(listen_sa)); + #ifdef IPV6_SUP + server_data_socket = get_backchannel_socket(address_family, SOCK_STREAM, min_port, + max_port, -1, 1, (struct sockaddr_storage *)&listen_sa); + #else server_data_socket = get_backchannel_socket(SOCK_STREAM, min_port, ! max_port, -1, 1, &listen_sa); ! #endif if (server_data_socket < 0) { syslog(LOG_NOTICE, "get_backchannel_socket() failed (%m)"); exit(EX_OSERR); } + #ifdef IPV6_SUP + #ifdef DEBUG_LOG + getnameinfo((struct sockaddr *)&server_listen_sa, + server_listen_sa.ss_len, + host, sizeof(host), + port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV); + + syslog(LOG_INFO, "1 server_data_socket: [%d], host: [%s], port: [%s]\n", + server_data_socket, host, port); + + getnameinfo((struct sockaddr *)&listen_sa, + listen_sa.ss_len, + host, sizeof(host), + port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV); + + syslog(LOG_INFO, "2 host: [%s], port: [%s]\n", host, port); + #endif + + if (connect(server_data_socket, (struct sockaddr *) &server_listen_sa, + server_listen_sa.ss_len) != 0) { + #else if (connect(server_data_socket, (struct sockaddr *) &server_listen_sa, sizeof(server_listen_sa)) != 0) { + #endif syslog(LOG_NOTICE, "connect() failed (%m)"); exit(EX_NOHOST); } *************** *** 512,525 **** --- 668,701 ---- static void connect_port_backchannel(void) { + #ifdef IPV6_SUP + struct sockaddr_storage listen_sa; + struct sockaddr_in *sockaddr4; + struct sockaddr_in6 *sockaddr6; + #else struct sockaddr_in listen_sa; + #endif socklen_t salen; + #ifdef IPV6_SUP + #ifdef DEBUG_LOG + char host[NI_MAXHOST]; + char port[NI_MAXHOST]; + #endif + #endif /* * We are about to accept a connection from the server. * This is a PORT or EPRT data connection. */ + #ifdef IPV6_SUP + #ifdef DEBUG_LOG + syslog(LOG_INFO, "server listen socket ready"); + #endif + debuglog(2, "server listen socket ready"); + #else + debuglog(2, "server listen socket ready"); + #endif close_server_data(); close_client_data(); *************** *** 531,536 **** --- 707,723 ---- syslog(LOG_NOTICE, "accept() failed (%m)"); exit(EX_OSERR); } + #ifdef IPV6_SUP + #ifdef DEBUG_LOG + getnameinfo((struct sockaddr *)&listen_sa, + listen_sa.ss_len, + host, sizeof(host), + port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV); + + syslog(LOG_INFO, "server_listen_socket: [%d], host: [%s], port: [%s]\n", + server_listen_socket, host, port); + #endif + #endif close(server_listen_socket); server_listen_socket = -1; *************** *** 541,549 **** * getting one bound to port 20 - This is deliberately * not RFC compliant. */ bzero(&listen_sa.sin_addr, sizeof(struct in_addr)); client_data_socket = get_backchannel_socket(SOCK_STREAM, ! min_port, max_port, -1, 1, &listen_sa); if (client_data_socket < 0) { syslog(LOG_NOTICE, "get_backchannel_socket() failed (%m)"); exit(EX_OSERR); --- 728,761 ---- * getting one bound to port 20 - This is deliberately * not RFC compliant. */ + #ifdef IPV6_SUP + #ifdef DEBUG_LOG + syslog(LOG_INFO, "running as non-root\n"); + syslog(LOG_INFO, "address_family: [%d]\n", address_family); + #endif + #endif + + #ifdef IPV6_SUP + /* clear address based on address family */ + if (address_family == AF_INET) { + sockaddr4 = (struct sockaddr_in *)&listen_sa; + bzero(&sockaddr4->sin_addr, sizeof(struct in_addr)); + } + else { + sockaddr6 = (struct sockaddr_in6 *)&listen_sa; + bzero(&sockaddr6->sin6_addr, sizeof(struct in6_addr)); + } + #else bzero(&listen_sa.sin_addr, sizeof(struct in_addr)); + #endif + + #ifdef IPV6_SUP + client_data_socket = get_backchannel_socket(address_family, SOCK_STREAM, + min_port, max_port, -1, 1, (struct sockaddr_storage *)&listen_sa); + #else client_data_socket = get_backchannel_socket(SOCK_STREAM, ! min_port, max_port, -1, 1, &listen_sa); ! #endif if (client_data_socket < 0) { syslog(LOG_NOTICE, "get_backchannel_socket() failed (%m)"); exit(EX_OSERR); *************** *** 555,566 **** --- 767,799 ---- * We're root, get our backchannel socket bound to port * 20 here, so we're fully RFC compliant. */ + #ifdef IPV6_SUP + #ifdef DEBUG_LOG + syslog(LOG_INFO, "running as root\n"); + #endif + #endif + + #ifdef IPV6_SUP + client_data_socket = socket(address_family, SOCK_STREAM, 0); + + salen = 1; + if (address_family == AF_INET) { + sockaddr4 = (struct sockaddr_in *)&listen_sa; + sockaddr4->sin_family = AF_INET; + bcopy(&((struct sockaddr_in *)&src_addr)->sin_addr, + &sockaddr4->sin_addr, sizeof(struct in_addr)); + sockaddr4->sin_port = htons(20); + } + else { + } + #else client_data_socket = socket(AF_INET, SOCK_STREAM, 0); salen = 1; listen_sa.sin_family = AF_INET; bcopy(&src_addr, &listen_sa.sin_addr, sizeof(struct in_addr)); listen_sa.sin_port = htons(20); + #endif if (setsockopt(client_data_socket, SOL_SOCKET, SO_REUSEADDR, &salen, sizeof(salen)) == -1) { *************** *** 575,582 **** --- 808,830 ---- } } + #ifdef IPV6_SUP + #ifdef DEBUG_LOG + getnameinfo((struct sockaddr *)&client_listen_sa, + client_listen_sa.ss_len, + host, sizeof(host), + port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV); + + syslog(LOG_INFO, "client_data_socket: [%d], host: [%s], port: [%s]\n", + client_data_socket, host, port); + #endif + + if (connect(client_data_socket, (struct sockaddr *) &client_listen_sa, + client_listen_sa.ss_len) != 0) { + #else if (connect(client_data_socket, (struct sockaddr *) &client_listen_sa, sizeof(client_listen_sa)) != 0) { + #endif syslog(LOG_INFO, "cannot connect data channel (%m)"); exit(EX_NOHOST); } *************** *** 592,600 **** --- 840,871 ---- int i, j, rv; char tbuf[100]; char *sendbuf = NULL; + #ifdef IPV6_SUP + char c_addr_str[NI_MAXHOST]; + char c_port_str[NI_MAXHOST]; + char s_addr_str[NI_MAXHOST]; + char s_port_str[NI_MAXHOST]; + int ret; + #endif log_control_command((char *)client->line_buffer, 1); + #ifdef IPV6_SUP + #ifdef DEBUG_LOG + syslog(LOG_INFO, "client->line_buffer: [%s]\n", (char *)client->line_buffer); + #endif + #endif + + #ifdef IPV6_SUP + ret = getnameinfo((struct sockaddr *)&server->sa, server->sa.ss_len, s_addr_str, + sizeof(s_addr_str), NULL, 0, + NI_NUMERICHOST | NI_NUMERICSERV); + + if (ret != 0) { + strcpy(s_addr_str, "unknown server address"); + } + #endif + /* client->line_buffer is an ftp control command. * There is no reason for these to be very long. * In the interest of limiting buffer overrun attempts, *************** *** 667,677 **** --- 938,957 ---- goto protounsupp; memset(&hints, 0, sizeof(hints)); + #ifdef IPV6_SUP + /* Support for both IPV4 and IPV6 */ + if ((proto != 1) && (proto != 2)) + goto protounsupp; + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_NUMERICHOST; /*no DNS*/ + #else if (proto != 1) /* 1 == AF_INET - all we support for now */ goto protounsupp; hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_NUMERICHOST; /*no DNS*/ + #endif if (getaddrinfo(result[1], result[2], &hints, &res)) goto parsefail; if (res->ai_next) *************** *** 680,688 **** --- 960,987 ---- goto parsefail; memcpy(&client_listen_sa, res->ai_addr, res->ai_addrlen); + #ifdef IPV6_SUP + ret = getnameinfo(res->ai_addr, res->ai_addrlen, c_addr_str, + sizeof(c_addr_str), c_port_str, sizeof(c_port_str), + NI_NUMERICHOST | NI_NUMERICSERV); + + if (ret != 0) { + strcpy(c_addr_str, "unknown client address"); + strcpy(c_port_str, "unknown client port"); + } + + #ifdef DEBUG_LOG + syslog(LOG_INFO, "client wants us to use %s:%s", + c_addr_str, c_port_str); + #endif + + debuglog(1, "client wants us to use %s:%s", + c_addr_str, c_port_str); + #else debuglog(1, "client wants us to use %s:%u", inet_ntoa(client_listen_sa.sin_addr), htons(client_listen_sa.sin_port)); + #endif /* * Configure our own listen socket and tell the server about it *************** *** 690,702 **** --- 989,1030 ---- new_dataconn(1); connection_mode = EPRT_MODE; + #ifdef IPV6_SUP + i = getnameinfo((struct sockaddr *)&server_listen_sa, server_listen_sa.ss_len, NULL, + 0, s_port_str, sizeof(s_port_str), + NI_NUMERICHOST | NI_NUMERICSERV); + + if (ret != 0) { + strcpy(s_port_str, "unknown server port"); + } + + #ifdef DEBUG_LOG + syslog(LOG_INFO, "we want server to use %s:%s", + s_addr_str, s_port_str); + #endif + + debuglog(1, "we want server to use %s:%s", + s_addr_str, s_port_str); + #else debuglog(1, "we want server to use %s:%u", inet_ntoa(server->sa.sin_addr), ntohs(server_listen_sa.sin_port)); + #endif + #ifdef IPV6_SUP + snprintf(tbuf, sizeof(tbuf), "EPRT |%u|%s|%s|\r\n", (unsigned int)proto, + s_addr_str, s_port_str); + #else snprintf(tbuf, sizeof(tbuf), "EPRT |%d|%s|%u|\r\n", 1, inet_ntoa(server->sa.sin_addr), ntohs(server_listen_sa.sin_port)); + #endif + + #ifdef IPV6_SUP + #ifdef DEBUG_LOG + syslog(LOG_INFO, "to server (modified): %s", tbuf); + #endif + #endif debuglog(1, "to server (modified): %s", tbuf); sendbuf = tbuf; goto out; *************** *** 706,711 **** --- 1034,1044 ---- sendbuf = NULL; goto out; protounsupp: + #ifdef IPV6_SUP + /* we support AF_INET and AF_INET6 now */ + snprintf(tbuf, sizeof(tbuf), + "501 Protocol not supported\r\n"); + #else /* we only support AF_INET for now */ if (proto == 2) snprintf(tbuf, sizeof(tbuf), *************** *** 713,718 **** --- 1046,1052 ---- else snprintf(tbuf, sizeof(tbuf), "501 Protocol not supported\r\n"); + #endif sendbuf = NULL; out: if (line) *************** *** 765,770 **** --- 1099,1109 ---- strlen("port ")) == 0) { unsigned int values[6]; char *tailptr; + #ifdef IPV6_SUP + struct sockaddr_in *client_sockaddr_in; + struct sockaddr_in *server_sockaddr_in; + struct sockaddr_in *server_listen_sockaddr_in; + #endif debuglog(1, "Got a PORT command"); *************** *** 789,794 **** --- 1128,1146 ---- } } + #ifdef IPV6_SUP + client_sockaddr_in = (struct sockaddr_in *)&client_listen_sa; + client_sockaddr_in->sin_family = AF_INET; + client_sockaddr_in->sin_addr.s_addr = htonl((values[0] << 24) | + (values[1] << 16) | (values[2] << 8) | + (values[3] << 0)); + + client_sockaddr_in->sin_port = htons((values[4] << 8) | + values[5]); + debuglog(1, "client wants us to use %u.%u.%u.%u:%u", + values[0], values[1], values[2], values[3], + (values[4] << 8) | values[5]); + #else client_listen_sa.sin_family = AF_INET; client_listen_sa.sin_addr.s_addr = htonl((values[0] << 24) | (values[1] << 16) | (values[2] << 8) | *************** *** 799,804 **** --- 1151,1157 ---- debuglog(1, "client wants us to use %u.%u.%u.%u:%u", values[0], values[1], values[2], values[3], (values[4] << 8) | values[5]); + #endif /* * Configure our own listen socket and tell the server about it *************** *** 806,815 **** --- 1159,1197 ---- new_dataconn(1); connection_mode = PORT_MODE; + #ifdef IPV6_SUP + i = getnameinfo((struct sockaddr *)&server_listen_sa, server_listen_sa.ss_len, NULL, + 0, s_port_str, sizeof(s_port_str), + NI_NUMERICHOST | NI_NUMERICSERV); + + if (ret != 0) { + strcpy(s_port_str, "unknown server port"); + } + + #ifdef DEBUG_LOG + syslog(LOG_INFO, "we want server to use %s:%s", + s_addr_str, s_port_str); + #endif + + debuglog(1, "we want server to use %s:%s", + s_addr_str, s_port_str); + #else debuglog(1, "we want server to use %s:%u", inet_ntoa(server->sa.sin_addr), ntohs(server_listen_sa.sin_port)); + #endif + #ifdef IPV6_SUP + server_sockaddr_in = (struct sockaddr_in *)&server->sa; + server_listen_sockaddr_in = (struct sockaddr_in *)&server_listen_sa; + snprintf(tbuf, sizeof(tbuf), "PORT %u,%u,%u,%u,%u,%u\r\n", + ((u_char *)&server_sockaddr_in->sin_addr.s_addr)[0], + ((u_char *)&server_sockaddr_in->sin_addr.s_addr)[1], + ((u_char *)&server_sockaddr_in->sin_addr.s_addr)[2], + ((u_char *)&server_sockaddr_in->sin_addr.s_addr)[3], + ((u_char *)&server_listen_sockaddr_in->sin_port)[0], + ((u_char *)&server_listen_sockaddr_in->sin_port)[1]); + #else snprintf(tbuf, sizeof(tbuf), "PORT %u,%u,%u,%u,%u,%u\r\n", ((u_char *)&server->sa.sin_addr.s_addr)[0], ((u_char *)&server->sa.sin_addr.s_addr)[1], *************** *** 817,823 **** --- 1199,1211 ---- ((u_char *)&server->sa.sin_addr.s_addr)[3], ((u_char *)&server_listen_sa.sin_port)[0], ((u_char *)&server_listen_sa.sin_port)[1]); + #endif + #ifdef IPV6_SUP + #ifdef DEBUG_LOG + syslog(LOG_INFO, "to server (modified): %s", tbuf); + #endif + #endif debuglog(1, "to server (modified): %s", tbuf); sendbuf = tbuf; *************** *** 848,856 **** --- 1236,1260 ---- struct in_addr *iap; static int continuing = 0; char tbuf[100], *sendbuf, *p; + #ifdef IPV6_SUP + struct sockaddr_in *client_sockaddr_in; + struct sockaddr_in *server_sockaddr_in; + struct sockaddr_in *proxy_sockaddr_in; + struct sockaddr_in6 *client_sockaddr_in6; + struct sockaddr_in6 *server_sockaddr_in6; + struct sockaddr_in6 *use_sockaddr_in6; + char host[NI_MAXHOST]; + char port[NI_MAXHOST]; + #endif log_control_command((char *)server->line_buffer, 0); + #ifdef IPV6_SUP + #ifdef DEBUG_LOG + syslog(LOG_INFO, "server->line_buffer: [%s]\n", (char *)server->line_buffer); + #endif + #endif + if (strlen((char *)server->line_buffer) > 512) { /* * someone's playing games. Have a cow in the syslogs and *************** *** 887,892 **** --- 1291,1303 ---- unsigned int values[6]; char *tailptr; + #ifdef IPV6_SUP + #ifdef DEBUG_LOG + syslog(LOG_INFO, "PASV reply\n"); + syslog(LOG_INFO, "address_family: [%d]\n", address_family); + #endif + #endif + debuglog(1, "Got a PASV reply"); debuglog(1, "{%s}", (char *)server->line_buffer); *************** *** 917,922 **** --- 1328,1359 ---- exit(EX_DATAERR); } + #ifdef IPV6_SUP + if (address_family == AF_INET) { + server_sockaddr_in = (struct sockaddr_in *)&server_listen_sa; + server_sockaddr_in->sin_family = AF_INET; + server_sockaddr_in->sin_len = sizeof(struct sockaddr_in); + server_sockaddr_in->sin_addr.s_addr = htonl((values[0] << 24) | + (values[1] << 16) | (values[2] << 8) | (values[3] << 0)); + server_sockaddr_in->sin_port = htons((values[4] << 8) | + values[5]); + + #ifdef DEBUG_LOG + syslog(LOG_INFO, "server wants us to use %s:%u", + inet_ntoa(server_sockaddr_in->sin_addr), (values[4] << 8) | + values[5]); + #endif + + debuglog(1, "server wants us to use %s:%u", + inet_ntoa(server_sockaddr_in->sin_addr), (values[4] << 8) | + values[5]); + } + else { + syslog(LOG_NOTICE, "failed in do_server_reply(), unknown af: [%d]\n", + address_family); + exit(EX_DATAERR); + } + #else server_listen_sa.sin_family = AF_INET; server_listen_sa.sin_addr.s_addr = htonl((values[0] << 24) | (values[1] << 16) | (values[2] << 8) | (values[3] << 0)); *************** *** 926,934 **** --- 1363,1404 ---- debuglog(1, "server wants us to use %s:%u", inet_ntoa(server_listen_sa.sin_addr), (values[4] |