forked from Lainports/opnsense-ports
282 lines
8.7 KiB
C
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);
|
|
}
|