pkgsrc/sysutils/socket/patches/patch-ah
2006-01-25 02:12:10 +00:00

332 lines
8.2 KiB
Text

$NetBSD: patch-ah,v 1.3 2006/01/25 02:12:10 joerg Exp $
--- socketp.c.orig 1992-08-09 01:41:42.000000000 +0000
+++ socketp.c
@@ -9,12 +9,19 @@ Please read the file COPYRIGHT for furth
#include <sys/types.h>
#include <sys/socket.h>
-#include <sys/errno.h>
+#include <errno.h>
#include <netinet/in.h>
+#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
#include "globals.h"
+extern int is_number A((char *));
+
+#ifndef USE_INET6
/*
* create a server socket on PORT accepting QUEUE_LENGTH connections
*/
@@ -25,9 +32,9 @@ int queue_length ;
struct sockaddr_in sa ;
int s;
- if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+ s = socket(AF_INET, SOCK_STREAM, 0);
+ if (s < 0)
return -1 ;
- }
bzero((char *) &sa, sizeof(sa)) ;
sa.sin_family = AF_INET ;
@@ -35,54 +42,270 @@ int queue_length ;
sa.sin_port = htons(port) ;
if (bind(s, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
- return -1 ;
+ return -1 ;
}
if (listen(s, 1) < 0) {
- return -1 ;
+ 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 ;
int port ;
{
struct sockaddr_in sa ;
struct hostent *hp ;
- int a, s ;
+ int s ;
long addr ;
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 ;
+ /* 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 ;
+ /* 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 ;
+ return -1 ;
}
- if (connect(s, &sa, sizeof(sa)) < 0) { /* connect */
- close(s) ;
- 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.
*/
@@ -116,5 +339,6 @@ char **name ;
return ntohs(servent->s_port) ;
}
}
+#endif /* !USE_INET6 */
/*EOF*/