about summary refs log tree commit diff stats
path: root/WWW/Library/Implementation/HTFTP.c
diff options
context:
space:
mode:
authorThomas E. Dickey <dickey@invisible-island.net>2000-08-03 18:00:32 -0400
committerThomas E. Dickey <dickey@invisible-island.net>2000-08-03 18:00:32 -0400
commit0726d2fa354eae3a7913d3ea28f19115ca904e02 (patch)
tree804a08df540b512940cf9681b299ac1c0f5a1e4b /WWW/Library/Implementation/HTFTP.c
parent56683faadde77d4d27712644e54769a77ac705bb (diff)
downloadlynx-snapshots-0726d2fa354eae3a7913d3ea28f19115ca904e02.tar.gz
snapshot of project "lynx", label v2-8-4dev_7
Diffstat (limited to 'WWW/Library/Implementation/HTFTP.c')
-rw-r--r--WWW/Library/Implementation/HTFTP.c176
1 files changed, 176 insertions, 0 deletions
diff --git a/WWW/Library/Implementation/HTFTP.c b/WWW/Library/Implementation/HTFTP.c
index 2c01085a..e725080a 100644
--- a/WWW/Library/Implementation/HTFTP.c
+++ b/WWW/Library/Implementation/HTFTP.c
@@ -1079,8 +1079,15 @@ PRIVATE int close_master_socket NOARGS
 */
 PRIVATE int get_listen_socket NOARGS
 {
+#ifdef INET6
+    struct sockaddr_storage soc_address;	/* Binary network address */
+    struct sockaddr_in* soc_in = (struct sockaddr_in *)&soc_address;
+    int af;
+    int slen;
+#else
     struct sockaddr_in soc_address;	/* Binary network address */
     struct sockaddr_in* soc_in = &soc_address;
+#endif /* INET6 */
     int new_socket;			/* Will be master_socket */
 
 
@@ -1092,9 +1099,24 @@ PRIVATE int get_listen_socket NOARGS
 	return master_socket;  /* Done already */
 #endif /* !REPEAT_LISTEN */
 
+#ifdef INET6
+    /* query address family of control connection */
+    slen = sizeof(soc_address);
+    if (getsockname(control->socket, (struct sockaddr *)&soc_address,
+		&slen) < 0) {
+	return HTInetStatus("getsockname failed");
+    }
+    af = ((struct sockaddr *)&soc_address)->sa_family;
+    memset(&soc_address, 0, sizeof(soc_address));
+#endif /* INET6 */
+
 /*  Create internet socket
 */
+#ifdef INET6
+    new_socket = socket(af, SOCK_STREAM, IPPROTO_TCP);
+#else
     new_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+#endif /* INET6 */
 
     if (new_socket < 0)
 	return HTInetStatus(gettext("socket for master socket"));
@@ -1103,8 +1125,27 @@ PRIVATE int get_listen_socket NOARGS
 
 /*  Search for a free port.
 */
+#ifdef INET6
+    memset(&soc_address, 0, sizeof(soc_address));
+    ((struct sockaddr *)&soc_address)->sa_family = af;
+    switch (af) {
+    case AF_INET:
+#ifdef SIN6_LEN
+	((struct sockaddr *)&soc_address)->sa_len = sizeof(struct sockaddr_in);
+#endif /* SIN6_LEN */
+	break;
+    case AF_INET6:
+#ifdef SIN6_LEN
+	((struct sockaddr *)&soc_address)->sa_len = sizeof(struct sockaddr_in6);
+#endif /* SIN6_LEN */
+	break;
+    default:
+	HTInetStatus("AF");
+    }
+#else
     soc_in->sin_family = AF_INET;	    /* Family = internet, host order  */
     soc_in->sin_addr.s_addr = INADDR_ANY;   /* Any peer address */
+#endif /* INET6 */
 #ifdef POLL_PORTS
     {
 	unsigned short old_port_number = port_number;
@@ -1115,15 +1156,31 @@ PRIVATE int get_listen_socket NOARGS
 	    if (port_number == old_port_number) {
 		return HTInetStatus("bind");
 	    }
+#ifdef INET6
+	    soc_in->sin_port = htons(port_number);
+#else
 	    soc_address.sin_port = htons(port_number);
+#endif /* INET6 */
 #ifdef SOCKS
 	    if (socks_flag)
 		if ((status=Rbind(new_socket,
 			(struct sockaddr*)&soc_address,
 			    /* Cast to generic sockaddr */
+#ifdef INET6
+#ifdef SIN6_LEN
+			((struct sockaddr *)&soc_address)->sa_len,
+#else
+			SA_LEN((struct sockaddr *)&soc_address),
+#endif /* SIN6_LEN */
+#else
 			sizeof(soc_address)
+#endif /* INET6 */
 #ifndef SHORTENED_RBIND
+#ifdef INET6
+			socks_bind_remoteAddr
+#else
 			,socks_bind_remoteAddr
+#endif /* INET6 */
 #endif /* !SHORTENED_RBIND */
 						)) == 0) {
 		    break;
@@ -1132,7 +1189,16 @@ PRIVATE int get_listen_socket NOARGS
 	    if ((status=bind(new_socket,
 		    (struct sockaddr*)&soc_address,
 			    /* Cast to generic sockaddr */
+#ifdef INET6
+#ifdef SIN6_LEN
+		    ((struct sockaddr *)&soc_address)->sa_len
+#else
+		    SA_LEN((struct sockaddr *)&soc_address)
+#endif /* SIN6_LEN */
+		    )) == 0) {
+#else
 		    sizeof(soc_address))) == 0) {
+#endif /* INET6 */
 		break;
 	    }
 	    CTRACE((tfp, "TCP bind attempt to port %d yields %d, errno=%d\n",
@@ -1154,10 +1220,17 @@ PRIVATE int get_listen_socket NOARGS
 			     (struct sockaddr *)&soc_address,
 			     (void *)&address_length);
 	if (status<0) return HTInetStatus("getsockname");
+#ifdef INET6
+	CTRACE((tfp, "HTFTP: This host is %s\n",
+ 	    HTInetString((SockA *)soc_in)));
+  
+ 	soc_in->sin_port = 0;	/* Unspecified: please allocate */
+#else
 	CTRACE((tfp, "HTFTP: This host is %s\n",
 	    HTInetString(soc_in)));
 
 	soc_address.sin_port = 0;	/* Unspecified: please allocate */
+#endif /* INET6 */
 #ifdef SOCKS
 	if (socks_flag)
 	    status=Rbind(new_socket,
@@ -1165,7 +1238,11 @@ PRIVATE int get_listen_socket NOARGS
 			 /* Cast to generic sockaddr */
 			 sizeof(soc_address)
 #ifndef SHORTENED_RBIND
+#ifdef INET6
+			socks_bind_remoteAddr
+#else
 			,socks_bind_remoteAddr
+#endif /* INET6 */
 #endif /* !SHORTENED_RBIND */
 						);
 	else
@@ -1173,7 +1250,16 @@ PRIVATE int get_listen_socket NOARGS
 	status=bind(new_socket,
 		    (struct sockaddr*)&soc_address,
 		    /* Cast to generic sockaddr */
+#ifdef INET6
+#ifdef SIN6_LEN
+		    ((struct sockaddr *)&soc_address)->sa_len
+#else
+		    SA_LEN((struct sockaddr *)&soc_address)
+#endif /* SIN6_LEN */
+		    );
+#else
 		    sizeof(soc_address));
+#endif /* INET6 */
 	if (status<0) return HTInetStatus("bind");
 
 	address_length = sizeof(soc_address);
@@ -1191,9 +1277,15 @@ PRIVATE int get_listen_socket NOARGS
     }
 #endif /* POLL_PORTS */
 
+#ifdef INET6
+    CTRACE((tfp, "HTFTP: bound to port %d on %s\n",
+		(int)ntohs(soc_in->sin_port),
+ 		HTInetString((SockA *)soc_in)));
+#else
     CTRACE((tfp, "HTFTP: bound to port %d on %s\n",
 		(int)ntohs(soc_in->sin_port),
 		HTInetString(soc_in)));
+#endif /* INET6 */
 
 #ifdef REPEAT_LISTEN
     if (master_socket >= 0)
@@ -1205,7 +1297,13 @@ PRIVATE int get_listen_socket NOARGS
 /*	Now we must find out who we are to tell the other guy
 */
     (void)HTHostName();		/* Make address valid - doesn't work*/
+#ifdef INET6
+    switch (((struct sockaddr *)&soc_address)->sa_family) {
+    case AF_INET:
+	sprintf(port_command, "PORT %d,%d,%d,%d,%d,%d%c%c",
+#else
     sprintf(port_command, "PORT %d,%d,%d,%d,%d,%d%c%c",
+#endif /* INET6 */
 		    (int)*((unsigned char *)(&soc_in->sin_addr)+0),
 		    (int)*((unsigned char *)(&soc_in->sin_addr)+1),
 		    (int)*((unsigned char *)(&soc_in->sin_addr)+2),
@@ -1214,6 +1312,30 @@ PRIVATE int get_listen_socket NOARGS
 		    (int)*((unsigned char *)(&soc_in->sin_port)+1),
 		    CR, LF);
 
+#ifdef INET6
+	break;
+
+    case AF_INET6:
+      {
+	char hostbuf[MAXHOSTNAMELEN];
+	char portbuf[MAXHOSTNAMELEN];
+	getnameinfo((struct sockaddr *)&soc_address,
+#ifdef SIN6_LEN
+	    ((struct sockaddr *)&soc_address)->sa_len,
+#else
+	    SA_LEN((struct sockaddr *)&soc_address),
+#endif /* SIN6_LEN */
+	    hostbuf, sizeof(hostbuf), portbuf, sizeof(portbuf),
+	    NI_NUMERICHOST | NI_NUMERICSERV);
+	sprintf(port_command, "EPRT |%d|%s|%s|%c%c", 2, hostbuf, portbuf,
+		CR, LF);
+	break;
+      }
+    default:
+	sprintf(port_command, "JUNK%c%c", CR, LF);
+	break;
+    }
+#endif /* INET6 */
 
 /*	Inform TCP that we will accept connections
 */
@@ -2871,7 +2993,12 @@ PUBLIC int HTFTPLoad ARGS4(
 	    if (status < 0) {
 		NETCLOSE (control->socket);
 		control->socket = -1;
+#ifdef INET6
+	        if (master_socket >= 0)
+		    (void)close_master_socket ();
+#else
 		close_master_socket ();
+#endif /* INET6 */
 		/* HT_INTERRUPTED would fall through, if we could interrupt
 		   somehow in the middle of it, which we currently can't. */
 		return status;
@@ -2903,6 +3030,50 @@ PUBLIC int HTFTPLoad ARGS4(
 
 	    data_soc = status;
 
+#ifdef INET6
+	    status = send_cmd_1("EPSV");
+	    if (status < 0)	/* retry or Bad return */
+		continue;
+	    else if (status != 2) {
+		status = send_cmd_1("PASV");
+		if (status < 0)	/* retry or Bad return */
+		    continue;
+		else if (status != 2) {
+		    return -status; 	/* bad reply */
+		}
+ 	    }
+
+	    if (strncmp(command, "PASV", 4) == 0) {
+		for (p = response_text; *p && *p != ','; p++)
+		    ; /* null body */
+
+		while (--p > response_text && '0' <= *p && *p <= '9')
+		    ; /* null body */
+	       status = sscanf(p+1, "%d,%d,%d,%d,%d,%d",
+		       &h0, &h1, &h2, &h3, &p0, &p1);
+	       if (status < 4) {
+		   fprintf(tfp, "HTFTP: PASV reply has no inet address!\n");
+		   return -99;
+	       }
+	       passive_port = (p0<<8) + p1;
+	    } else if (strncmp(command, "EPSV", 4) == 0) {
+		char ch;
+		/*
+		 * EPSV |||port|
+		 */
+		for (p = response_text; *p && !isspace(*p); p++)
+		    ; /* null body */
+		for (p = response_text; *p && isspace(*p); p++)
+		    ; /* null body */
+		status = sscanf(p+1, "%c%c%c%d%c",
+		       &h0, &h1, &h2, &p0, &h3);
+		if (status != 5) {
+		    fprintf(tfp, "HTFTP: EPSV reply has invalid format!\n");
+		    return -99;
+		}
+		passive_port = p0;
+ 	    }
+#else
 	    status = send_cmd_1("PASV");
 	    if (status != 2) {
 		if (status < 0)
@@ -2922,6 +3093,7 @@ PUBLIC int HTFTPLoad ARGS4(
 		return -99;
 	    }
 	    passive_port = (p0<<8) + p1;
+#endif /* INET6 */
 	    CTRACE((tfp, "HTFTP: Server is listening on port %d\n",
 			 passive_port));
 
@@ -3423,7 +3595,11 @@ PUBLIC int HTFTPLoad ARGS4(
 listen:
     if(!ftp_passive) {
 	/* Wait for the connection */
+#ifdef INET6
+ 	struct sockaddr_storage soc_address;
+#else
 	struct sockaddr_in soc_address;
+#endif /* INET6 */
 	int	soc_addrlen=sizeof(soc_address);
 #ifdef SOCKS
 	if (socks_flag)