opnsense-ports/net/sock/files/patch-src__servopen.c
Franco Fichtner 92f7f399cd */*: sync with upstream
Taken from: FreeBSD
2016-05-25 07:17:49 +02:00

282 lines
8.7 KiB
C

--- src/servopen.c.orig 2010-05-28 00:03:25 UTC
+++ src/servopen.c
@@ -19,38 +19,67 @@
int
servopen(char *host, char *port)
{
- int fd, newfd, i, on, pid;
- char *protocol;
+ int fd, newfd, i, on, pid;
+ char *protocol;
struct in_addr inaddr;
struct servent *sp;
+ socklen_t len;
+ char inaddr_buf[INET6_ADDRSTRLEN];
protocol = udp ? "udp" : "tcp";
- /* Initialize the socket address structure */
- bzero(&servaddr, sizeof(servaddr));
- servaddr.sin_family = AF_INET;
+ /* Initialize the socket address structure */
+ bzero(&servaddr4, sizeof(servaddr4));
+ servaddr4.sin_family = AF_INET;
- /* Caller normally wildcards the local Internet address, meaning
- a connection will be accepted on any connected interface.
- We only allow an IP address for the "host", not a name. */
- if (host == NULL)
- servaddr.sin_addr.s_addr = htonl(INADDR_ANY); /* wildcard */
- else {
- if (inet_aton(host, &inaddr) == 0)
- err_quit("invalid host name for server: %s", host);
- servaddr.sin_addr = inaddr;
+ bzero(&servaddr6, sizeof(servaddr6));
+ servaddr6.sin6_family = AF_INET6;
+
+ /*
+ * Caller normally wildcards the local Internet address, meaning
+ * a connection will be accepted on any connected interface.
+ * We only allow an IP address for the "host", not a name.
+ */
+ if (host == NULL) {
+ if (AF_INET == af_46) {
+ /* wildcard */
+ servaddr4.sin_addr.s_addr = htonl(INADDR_ANY);
+ } else {
+ /* wildcard */
+ servaddr6.sin6_addr = in6addr_any;
+ }
+ } else {
+ if (AF_INET == af_46) {
+ if (inet_pton(AF_INET, host, &inaddr) == 0) {
+ err_quit("invalid host name for server: %s",
+ host);
+ }
+ /* IPv4 address */
+ servaddr4.sin_addr = inaddr;
+ } else {
+ if (inet_pton(AF_INET6, host, inaddr_buf) == 0) {
+ err_quit("invalid host name for server: %s",
+ host);
+ }
+ /* IPv6 address */
+ memcpy(&servaddr6.sin6_addr, inaddr_buf,
+ sizeof(struct in6_addr));
+ }
}
- /* See if "port" is a service name or number */
+ /* See if "port" is a service name or number */
if ( (i = atoi(port)) == 0) {
if ( (sp = getservbyname(port, protocol)) == NULL)
- err_ret("getservbyname() error for: %s/%s", port, protocol);
-
- servaddr.sin_port = sp->s_port;
- } else
- servaddr.sin_port = htons(i);
+ err_ret("getservbyname() error for: %s/%s", port,
+ protocol);
+ servaddr4.sin_port = sp->s_port;
+ servaddr6.sin6_port = sp->s_port;
+ } else {
+ servaddr4.sin_port = htons(i);
+ servaddr6.sin6_port = htons(i);
+ }
- if ( (fd = socket(AF_INET, udp ? SOCK_DGRAM : SOCK_STREAM, 0)) < 0)
+ if ( (fd = socket(af_46, udp ? SOCK_DGRAM : SOCK_STREAM, 0)) < 0)
err_sys("socket() error");
if (reuseaddr) {
@@ -67,28 +96,37 @@ servopen(char *host, char *port)
}
#endif
- /* Bind our well-known port so the client can connect to us. */
- if (bind(fd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0)
- err_sys("can't bind local address");
+ /* Bind our well-known port so the client can connect to us. */
+ if (AF_INET == af_46) {
+ if (bind(fd, (struct sockaddr *) &servaddr4,
+ sizeof(servaddr4)) < 0) {
+ err_sys("can't bind local address");
+ }
+ } else {
+ if (bind(fd, (struct sockaddr *) &servaddr6,
+ sizeof(servaddr6)) < 0) {
+ err_sys("can't bind local address");
+ }
+ }
- join_mcast(fd, &servaddr);
+ join_mcast_server(fd, &servaddr4, &servaddr6);
if (udp) {
buffers(fd);
- if (foreignip[0] != 0) { /* connect to foreignip/port# */
- bzero(&cliaddr, sizeof(cliaddr));
- if (inet_aton(foreignip, &cliaddr.sin_addr) == 0)
+ /* Fixme: Not ported for IPv6 */
+ if (foreignip[0] != 0) { /* connect to foreignip/port# */
+ bzero(&cliaddr4, sizeof(cliaddr4));
+ if (inet_aton(foreignip, &cliaddr4.sin_addr) == 0)
err_quit("invalid IP address: %s", foreignip);
- cliaddr.sin_family = AF_INET;
- cliaddr.sin_port = htons(foreignport);
- /* connect() for datagram socket doesn't appear to allow
- wildcarding of either IP address or port number */
+ cliaddr4.sin_family = AF_INET;
+ cliaddr4.sin_port = htons(foreignport);
+ /* connect() for datagram socket doesn't appear to allow
+ wildcarding of either IP address or port number */
- if (connect(fd, (struct sockaddr *) &cliaddr, sizeof(cliaddr))
- < 0)
+ if (connect(fd, (struct sockaddr *) &cliaddr4,
+ sizeof(cliaddr4)) < 0)
err_sys("connect() error");
-
}
sockopts(fd, 1);
@@ -96,58 +134,108 @@ servopen(char *host, char *port)
return(fd); /* nothing else to do */
}
- buffers(fd); /* may set receive buffer size; must do here to get
- correct window advertised on SYN */
+ buffers(fd); /* may set receive buffer size; must do here to
+ get correct window advertised on SYN */
sockopts(fd, 0); /* only set some socket options for fd */
listen(fd, listenq);
- if (pauselisten)
- sleep_us(pauselisten*1000); /* lets connection queue build up */
+ if (pauselisten) {
+ /* lets connection queue build up */
+ sleep_us(pauselisten*1000);
+ }
- if (dofork)
- TELL_WAIT(); /* initialize synchronization primitives */
+ if (dofork) {
+ /* initialize synchronization primitives */
+ TELL_WAIT();
+ }
for ( ; ; ) {
- i = sizeof(cliaddr);
- if ( (newfd = accept(fd, (struct sockaddr *) &cliaddr, &i)) < 0)
- err_sys("accept() error");
+ if (AF_INET == af_46) {
+ len = sizeof(cliaddr4);
+ if ( (newfd = accept(fd, (struct sockaddr *) &cliaddr4,
+ &len)) < 0) {
+ err_sys("accept() error");
+ }
+ } else {
+ len = sizeof(cliaddr6);
+ if ( (newfd = accept(fd, (struct sockaddr *) &cliaddr6,
+ &len)) < 0) {
+ err_sys("accept() error");
+ }
+ }
if (dofork) {
if ( (pid = fork()) < 0)
err_sys("fork error");
if (pid > 0) {
- close(newfd); /* parent closes connected socket */
- WAIT_CHILD(); /* wait for child to output to terminal */
- continue; /* and back to for(;;) for another accept() */
+ /* parent closes connected socket */
+ close(newfd);
+ /* wait for child to output to terminal */
+ WAIT_CHILD();
+ /* and back to for(;;) for another accept() */
+ continue;
} else {
- close(fd); /* child closes listening socket */
+ /* child closes listening socket */
+ close(fd);
}
}
- /* child (or iterative server) continues here */
+ /* child (or iterative server) continues here */
if (verbose) {
- /* Call getsockname() to find local address bound to socket:
- local internet address is now determined (if multihomed). */
- i = sizeof(servaddr);
- if (getsockname(newfd, (struct sockaddr *) &servaddr, &i) < 0)
- err_sys("getsockname() error");
+ /*
+ * Call getsockname() to find local address bound
+ * to socket: local internet address is now
+ * determined (if multihomed).
+ */
+ if (AF_INET == af_46) {
+ len = sizeof(servaddr4);
+ if (getsockname(newfd,
+ (struct sockaddr *)&servaddr4, &len) < 0) {
+ err_sys("getsockname() error");
+ }
- /* Can't do one fprintf() since inet_ntoa() stores
- the result in a static location. */
- fprintf(stderr, "connection on %s.%d ",
- INET_NTOA(servaddr.sin_addr), ntohs(servaddr.sin_port));
- fprintf(stderr, "from %s.%d\n",
- INET_NTOA(cliaddr.sin_addr), ntohs(cliaddr.sin_port));
+ /*
+ * Can't do one fprintf() since inet_ntoa()
+ * stores the result in a static location.
+ */
+ fprintf(stderr, "connection on %s.%d ",
+ INET_NTOA(servaddr4.sin_addr),
+ ntohs(servaddr4.sin_port));
+ fprintf(stderr, "from %s.%d\n",
+ INET_NTOA(cliaddr4.sin_addr),
+ ntohs(cliaddr4.sin_port));
+ } else {
+ len = sizeof(servaddr6);
+ if (getsockname(newfd,
+ (struct sockaddr *)&servaddr6, &len) < 0) {
+ err_sys("getsockname() error");
+ }
+ inet_ntop(AF_INET6,
+ &servaddr6.sin6_addr.__u6_addr.__u6_addr8,
+ inaddr_buf, sizeof(inaddr_buf));
+ fprintf(stderr, "connection on %s.%d ",
+ inaddr_buf, ntohs(servaddr6.sin6_port));
+ inet_ntop(AF_INET6,
+ &cliaddr6.sin6_addr.__u6_addr.__u6_addr8,
+ inaddr_buf, sizeof(inaddr_buf));
+ fprintf(stderr, "from %s.%d\n",
+ inaddr_buf, ntohs(cliaddr6.sin6_port));
+ }
}
- buffers(newfd); /* setsockopt() again, in case it didn't propagate
- from listening socket to connected socket */
- sockopts(newfd, 1); /* can set all socket options for this socket */
+ /* setsockopt() again, in case it didn't propagate
+ from listening socket to connected socket */
+ buffers(newfd);
- if (dofork)
- TELL_PARENT(getppid()); /* tell parent we're done with terminal */
+ /* can set all socket options for this socket */
+ sockopts(newfd, 1);
+
+ if (dofork) {
+ /* tell parent we're done with terminal */
+ TELL_PARENT(getppid());
+ }
return(newfd);
}