d66b1112ff
I have created a patch that can be applied to provide IPv6 support for sysutils/socket utility. The patch imported from NetBSD and cleaned up to be cleanly work on FreeBSD. PR: ports/36202 Submitted by: Janos Mohacsi <janos.mohacsi@dante.org.uk> Approved by: maintainer timeout
358 lines
8.9 KiB
Text
358 lines
8.9 KiB
Text
*** socketp.c.orig Fri Mar 22 11:42:23 2002
|
|
--- socketp.c Fri Mar 22 12:07:59 2002
|
|
***************
|
|
*** 21,26 ****
|
|
--- 21,27 ----
|
|
|
|
extern int is_number A((char *));
|
|
|
|
+ #ifndef USE_INET6
|
|
/*
|
|
* create a server socket on PORT accepting QUEUE_LENGTH connections
|
|
*/
|
|
***************
|
|
*** 31,39 ****
|
|
struct sockaddr_in sa ;
|
|
int s;
|
|
|
|
! if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
|
return -1 ;
|
|
- }
|
|
|
|
bzero((char *) &sa, sizeof(sa)) ;
|
|
sa.sin_family = AF_INET ;
|
|
--- 32,40 ----
|
|
struct sockaddr_in sa ;
|
|
int s;
|
|
|
|
! s = socket(AF_INET, SOCK_STREAM, 0);
|
|
! if (s < 0)
|
|
return -1 ;
|
|
|
|
bzero((char *) &sa, sizeof(sa)) ;
|
|
sa.sin_family = AF_INET ;
|
|
***************
|
|
*** 41,56 ****
|
|
sa.sin_port = htons(port) ;
|
|
|
|
if (bind(s, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
|
|
! return -1 ;
|
|
}
|
|
if (listen(s, 1) < 0) {
|
|
! return -1 ;
|
|
}
|
|
|
|
return s ;
|
|
}
|
|
|
|
|
|
/* create a client socket connected to PORT on HOSTNAME */
|
|
int create_client_socket(hostname, port)
|
|
char **hostname ;
|
|
--- 42,126 ----
|
|
sa.sin_port = htons(port) ;
|
|
|
|
if (bind(s, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
|
|
! return -1 ;
|
|
}
|
|
if (listen(s, 1) < 0) {
|
|
! return -1 ;
|
|
}
|
|
|
|
return s ;
|
|
}
|
|
+ #else /* USE_INET6 */
|
|
+ /*
|
|
+ * create a server socket(s) on PORT accepting QUEUE_LENGTH connections
|
|
+ *
|
|
+ * FWD (ifdef USE_INET6):
|
|
+ * there can be more than one socket; one for each supported address
|
|
+ * family. This is for portability as not all IPv6 stacks implement
|
|
+ * the wildcard bind as a bind to *ll IPv4 *and* IPv6 addresses.
|
|
+ * so we'll just open a socket for each address getaddrinfo() gives
|
|
+ * back to us. The price of portability...
|
|
+ */
|
|
+ int *create_server_sockets(port, queue_length)
|
|
+ char **port ;
|
|
+ int queue_length ;
|
|
+ {
|
|
+ struct addrinfo hints, *r, *res;
|
|
+ int *s, *slist, error, maxs;
|
|
+ int reuse_addr = 1;
|
|
+
|
|
+ memset(&hints, 0, sizeof(hints));
|
|
+ hints.ai_flags = AI_PASSIVE;
|
|
+ hints.ai_family = AF_UNSPEC;
|
|
+ hints.ai_socktype = SOCK_STREAM;
|
|
+ hints.ai_protocol = 0;
|
|
+ error = getaddrinfo(NULL, *port, &hints, &res);
|
|
+
|
|
+ if (!error) {
|
|
+ for (maxs = 0, r = res; r; r = r->ai_next, maxs++);
|
|
+ slist = malloc ((maxs+1) * sizeof(int));
|
|
+ if (slist) {
|
|
+ slist[0] = maxs; /* max. num of sockets */
|
|
+
|
|
+ s = slist+1;
|
|
+ for (r = res; r; r = r->ai_next) {
|
|
+ *s = socket(r->ai_family, r->ai_socktype, r->ai_protocol);
|
|
+ if (*s < 0)
|
|
+ continue;
|
|
+
|
|
+ setsockopt(*s,SOL_SOCKET,SO_REUSEADDR,&reuse_addr,sizeof(reuse_addr));
|
|
+
|
|
+ if (bind(*s, r->ai_addr, r->ai_addrlen) < 0) {
|
|
+ close (*s);
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ if (listen(*s, 1) < 0) {
|
|
+ close (*s);
|
|
+ continue;
|
|
+ }
|
|
+ s++;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ else
|
|
+ slist = NULL;
|
|
|
|
+ if (res)
|
|
+ freeaddrinfo(res);
|
|
|
|
+ if (slist && !slist[0]) {
|
|
+ free (slist);
|
|
+ slist = NULL;
|
|
+ }
|
|
+
|
|
+ return (slist);
|
|
+ }
|
|
+ #endif /* USE_INET6 */
|
|
+
|
|
+
|
|
+ /* create a client socket connected to PORT on HOSTNAME */
|
|
+ #ifndef USE_INET6
|
|
/* create a client socket connected to PORT on HOSTNAME */
|
|
int create_client_socket(hostname, port)
|
|
char **hostname ;
|
|
***************
|
|
*** 64,94 ****
|
|
|
|
bzero(&sa, sizeof(sa)) ;
|
|
if ((addr = inet_addr(*hostname)) != -1) {
|
|
! /* is Internet addr in octet notation */
|
|
! bcopy(&addr, (char *) &sa.sin_addr, sizeof(addr)) ; /* set address */
|
|
! sa.sin_family = AF_INET ;
|
|
} else {
|
|
! /* do we know the host's address? */
|
|
! if ((hp = gethostbyname(*hostname)) == NULL) {
|
|
! return -2 ;
|
|
! }
|
|
! *hostname = hp->h_name ;
|
|
! bcopy(hp->h_addr, (char *) &sa.sin_addr, hp->h_length) ;
|
|
! sa.sin_family = hp->h_addrtype ;
|
|
}
|
|
|
|
sa.sin_port = htons((u_short) port) ;
|
|
|
|
if ((s = socket(sa.sin_family, SOCK_STREAM, 0)) < 0) { /* get socket */
|
|
! return -1 ;
|
|
}
|
|
if (connect(s, (struct sockaddr *)&sa, sizeof(sa)) < 0) { /* connect */
|
|
! close(s) ;
|
|
! return -1 ;
|
|
}
|
|
return s ;
|
|
}
|
|
|
|
/* return the port number for service NAME_OR_NUMBER. If NAME is non-null,
|
|
* the name is the service is written there.
|
|
*/
|
|
--- 134,311 ----
|
|
|
|
bzero(&sa, sizeof(sa)) ;
|
|
if ((addr = inet_addr(*hostname)) != -1) {
|
|
! /* is Internet addr in octet notation */
|
|
! bcopy(&addr, (char *) &sa.sin_addr, sizeof(addr)) ; /* set address */
|
|
! sa.sin_family = AF_INET ;
|
|
} else {
|
|
! /* do we know the host's address? */
|
|
! if ((hp = gethostbyname(*hostname)) == NULL) {
|
|
! return -2 ;
|
|
! }
|
|
! *hostname = hp->h_name ;
|
|
! bcopy(hp->h_addr, (char *) &sa.sin_addr, hp->h_length) ;
|
|
! sa.sin_family = hp->h_addrtype ;
|
|
}
|
|
|
|
sa.sin_port = htons((u_short) port) ;
|
|
|
|
if ((s = socket(sa.sin_family, SOCK_STREAM, 0)) < 0) { /* get socket */
|
|
! return -1 ;
|
|
}
|
|
if (connect(s, (struct sockaddr *)&sa, sizeof(sa)) < 0) { /* connect */
|
|
! close(s) ;
|
|
! return -1 ;
|
|
}
|
|
return s ;
|
|
}
|
|
|
|
+ #else /* USE_INET6 */
|
|
+ int create_client_socket(hostname, port)
|
|
+ char **hostname ;
|
|
+ char **port ;
|
|
+ {
|
|
+ int s, connected, err ;
|
|
+ struct addrinfo hints, *r, *res;
|
|
+
|
|
+ memset(&hints, 0, sizeof(hints));
|
|
+ hints.ai_flags = AI_NUMERICHOST;
|
|
+ hints.ai_family = AF_UNSPEC;
|
|
+ hints.ai_socktype= SOCK_STREAM;
|
|
+ err = getaddrinfo(*hostname, *port, &hints, &res);
|
|
+ if (res) freeaddrinfo(res);
|
|
+
|
|
+ if (!err) {
|
|
+ /* numeric */
|
|
+ memset(&hints, 0, sizeof(hints));
|
|
+ hints.ai_flags = AI_CANONNAME;
|
|
+ hints.ai_family = AF_UNSPEC;
|
|
+ hints.ai_socktype = SOCK_STREAM;
|
|
+ hints.ai_protocol = 0;
|
|
+ err = getaddrinfo(*hostname, *port, &hints, &res);
|
|
+ if (err) s = -2;
|
|
+ } else {
|
|
+ /* non-numeric */
|
|
+ memset(&hints, 0, sizeof(hints));
|
|
+ hints.ai_family = AF_UNSPEC;
|
|
+ hints.ai_socktype = SOCK_STREAM;
|
|
+ hints.ai_protocol = 0;
|
|
+ err = getaddrinfo(*hostname, *port, &hints, &res);
|
|
+ if (err) s = -2;
|
|
+ }
|
|
+
|
|
+
|
|
+ if (!err) {
|
|
+ err = 0; s = -1;
|
|
+ connected = 0;
|
|
+ for (r = res; r && !connected; r = r->ai_next) {
|
|
+ s = socket(r->ai_family, r->ai_socktype, r->ai_protocol);
|
|
+ if (s < 0)
|
|
+ continue;
|
|
+
|
|
+ if (connect(s, r->ai_addr, r->ai_addrlen) < 0) {
|
|
+ err = errno;
|
|
+ close(s);
|
|
+ s = -1;
|
|
+ continue;
|
|
+ }
|
|
+ connected++;
|
|
+ break;
|
|
+ }
|
|
+ if (!connected) s = -1;
|
|
+ }
|
|
+
|
|
+ if (res)
|
|
+ freeaddrinfo(res);
|
|
+
|
|
+ return (s);
|
|
+ }
|
|
+ #endif /* USE_INET6 */
|
|
+
|
|
+ #ifdef USE_INET6
|
|
+ /* Determines hostname, address and port number used for the peer of socket */
|
|
+ int socket_remote_name(socket, name, ipname, port)
|
|
+ int socket;
|
|
+ char **name;
|
|
+ char **ipname;
|
|
+ char **port;
|
|
+ {
|
|
+ struct sockaddr_storage server;
|
|
+ int length=sizeof(server), retval, error;
|
|
+ static char host[NI_MAXHOST],ip[NI_MAXHOST],portstr[NI_MAXSERV];
|
|
+
|
|
+ error = getpeername(socket,(struct sockaddr*)&server,&length);
|
|
+ if(!error) {
|
|
+ error = getnameinfo((struct sockaddr*)&server, length, host,
|
|
+ NI_MAXHOST, NULL, 0, 0);
|
|
+ error = getnameinfo((struct sockaddr*)&server, length, ip,
|
|
+ NI_MAXHOST, NULL, NI_MAXSERV,
|
|
+ NI_NUMERICHOST);
|
|
+ retval = error;
|
|
+
|
|
+ error = getnameinfo((struct sockaddr*)&server, length, NULL, 0,
|
|
+ portstr, NI_MAXSERV, 0);
|
|
+
|
|
+ if (error)
|
|
+ retval = getnameinfo((struct sockaddr*)&server, length, ip,
|
|
+ NI_MAXHOST, portstr, NI_MAXSERV,
|
|
+ NI_NUMERICSERV);
|
|
+ }
|
|
+ else
|
|
+ retval = error;
|
|
+
|
|
+ if(name)
|
|
+ *name=host;
|
|
+ if(ipname)
|
|
+ *ipname=ip;
|
|
+ if(port)
|
|
+ *port=portstr;
|
|
+
|
|
+ return(retval);
|
|
+ }
|
|
+
|
|
+ /* Determines the hostname, address and port number used for our socket */
|
|
+ int socket_local_name(socket, name, ipname, port)
|
|
+ int socket;
|
|
+ char **name;
|
|
+ char **ipname;
|
|
+ char **port;
|
|
+ {
|
|
+ struct sockaddr_storage server;
|
|
+ int length=sizeof(server), retval, error;
|
|
+ static char host[NI_MAXHOST],ip[NI_MAXHOST],portstr[NI_MAXSERV];
|
|
+
|
|
+ error = getsockname(socket,(struct sockaddr*)&server,&length);
|
|
+ if(!error) {
|
|
+ error = getnameinfo((struct sockaddr*)&server, length, host,
|
|
+ NI_MAXHOST, NULL, 0, 0);
|
|
+ error = getnameinfo((struct sockaddr*)&server, length, ip,
|
|
+ NI_MAXHOST, NULL, NI_MAXSERV,
|
|
+ NI_NUMERICHOST);
|
|
+ retval = error;
|
|
+
|
|
+ error = getnameinfo((struct sockaddr*)&server, length, NULL, 0,
|
|
+ portstr, NI_MAXSERV, 0);
|
|
+
|
|
+ if (error)
|
|
+ retval = getnameinfo((struct sockaddr*)&server, length, ip,
|
|
+ NI_MAXHOST, portstr, NI_MAXSERV,
|
|
+ NI_NUMERICSERV);
|
|
+ }
|
|
+ else
|
|
+ retval = error;
|
|
+
|
|
+ if(name)
|
|
+ *name=host;
|
|
+ if(ipname)
|
|
+ *ipname=ip;
|
|
+ if(port)
|
|
+ *port=portstr;
|
|
+
|
|
+ return(retval);
|
|
+ }
|
|
+ #endif /* USE_INET6 */
|
|
+
|
|
+ #ifndef USE_INET6
|
|
/* return the port number for service NAME_OR_NUMBER. If NAME is non-null,
|
|
* the name is the service is written there.
|
|
*/
|
|
***************
|
|
*** 122,126 ****
|
|
--- 339,344 ----
|
|
return ntohs(servent->s_port) ;
|
|
}
|
|
}
|
|
+ #endif /* !USE_INET6 */
|
|
|
|
/*EOF*/
|