mirror of
https://git.freebsd.org/ports.git
synced 2025-07-18 01:39:16 -04:00
net/sock: update 0.3.2 -> 0.4.2
- IPv6 is supported now - supports SCTP in addition to UDP and TCP - socket options can now be used PR: 217909, 218298 Changes: https://github.com/sjac999/sock_ipv6_sctp/blob/master/ChangeLog Submitted by: Steve Jacobson <sjac@cs.stanford.edu> (maintainer)
This commit is contained in:
parent
acab8f76a0
commit
c18ae79509
Notes:
svn2git
2021-03-31 03:12:20 +00:00
svn path=/head/; revision=437575
12 changed files with 30 additions and 1226 deletions
|
@ -2,12 +2,19 @@
|
||||||
# $FreeBSD$
|
# $FreeBSD$
|
||||||
|
|
||||||
PORTNAME= sock
|
PORTNAME= sock
|
||||||
PORTVERSION= 0.3.2
|
PORTVERSION= 0.4.2
|
||||||
CATEGORIES= net
|
CATEGORIES= net
|
||||||
MASTER_SITES= http://www.icir.org/christian/downloads/
|
MASTER_SITES= http://www-cs-students.stanford.edu/~sjac/sock/
|
||||||
|
|
||||||
MAINTAINER= sjac@cs.stanford.edu
|
MAINTAINER= sjac@cs.stanford.edu
|
||||||
COMMENT= W. Richard Stevens' sock program
|
COMMENT= W. Richard Stevens' sock program plus IPv6 and SCTP
|
||||||
|
|
||||||
|
LICENSE= WRSTEVENS
|
||||||
|
LICENSE_NAME= WRSTEVENS
|
||||||
|
LICENSE_FILE= ${WRKSRC}/COPYING
|
||||||
|
LICENSE_PERMS= dist-mirror pkg-mirror auto-accept
|
||||||
|
|
||||||
|
USES= tar:tgz
|
||||||
|
|
||||||
HAS_CONFIGURE= yes
|
HAS_CONFIGURE= yes
|
||||||
|
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
SHA256 (sock-0.3.2.tar.gz) = 4ddc33767900e7cd0a4cc0f4d808638d7cfcb746c23e12274c8eba0622eee2eb
|
TIMESTAMP = 1491161724
|
||||||
SIZE (sock-0.3.2.tar.gz) = 113640
|
SHA256 (sock-0.4.2.tgz) = 42974b5f8f81c534d1e5236628658f6567ac0539c577cbc46d54b5b11d3b582c
|
||||||
|
SIZE (sock-0.4.2.tgz) = 119882
|
||||||
|
|
|
@ -1,264 +0,0 @@
|
||||||
--- src/cliopen.c.orig 2010-05-28 00:03:25 UTC
|
|
||||||
+++ src/cliopen.c
|
|
||||||
@@ -10,42 +10,107 @@
|
|
||||||
|
|
||||||
#include "sock.h"
|
|
||||||
|
|
||||||
+/*
|
|
||||||
+ * Try to convert the host name as an IPv4 dotted-decimal number
|
|
||||||
+ * or an IPv6 address.
|
|
||||||
+ */
|
|
||||||
+int convert_host_address(char *host)
|
|
||||||
+{
|
|
||||||
+ struct in_addr inaddr;
|
|
||||||
+ char inaddr_buf[INET6_ADDRSTRLEN];
|
|
||||||
+
|
|
||||||
+ if (AF_INET == af_46) {
|
|
||||||
+ if (inet_pton(AF_INET, host, &inaddr) == 1) {
|
|
||||||
+ /* IPv4 dotted-decimal */
|
|
||||||
+ servaddr4.sin_addr = inaddr;
|
|
||||||
+
|
|
||||||
+ return (1);
|
|
||||||
+ }
|
|
||||||
+ } else {
|
|
||||||
+ if (inet_pton(AF_INET6, host, inaddr_buf) == 1) {
|
|
||||||
+ /* IPv6 address */
|
|
||||||
+ memcpy(&servaddr6.sin6_addr, inaddr_buf,
|
|
||||||
+ sizeof(struct in6_addr));
|
|
||||||
+
|
|
||||||
+ return (1);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return (0);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/*
|
|
||||||
+ * Try to convert the host name as a host name string.
|
|
||||||
+ */
|
|
||||||
+int convert_host_name(char *host)
|
|
||||||
+{
|
|
||||||
+ struct hostent *hp;
|
|
||||||
+
|
|
||||||
+ if (AF_INET == af_46) {
|
|
||||||
+ if ( (hp = gethostbyname2(host, AF_INET)) != NULL) {
|
|
||||||
+ /* IPv4 address */
|
|
||||||
+ memcpy(&servaddr4.sin_addr, hp->h_addr, hp->h_length);
|
|
||||||
+
|
|
||||||
+ return (1);
|
|
||||||
+ }
|
|
||||||
+ } else {
|
|
||||||
+ /*
|
|
||||||
+ * Fixme: This doesn't work on FreeBSD 8.4.
|
|
||||||
+ * Only an IPv4 address is returned.
|
|
||||||
+ * getaddrinfo() doesn't work either.
|
|
||||||
+ */
|
|
||||||
+ if ( (hp = gethostbyname2(host, AF_INET6)) != NULL) {
|
|
||||||
+ /* IPv6 address */
|
|
||||||
+ memcpy(&servaddr6.sin6_addr, hp->h_addr, hp->h_length);
|
|
||||||
+
|
|
||||||
+ return (1);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return (0);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
int cliopen(char *host, char *port)
|
|
||||||
{
|
|
||||||
int fd, i, on;
|
|
||||||
char *protocol;
|
|
||||||
- struct in_addr inaddr;
|
|
||||||
+ char inaddr_buf[INET6_ADDRSTRLEN];
|
|
||||||
struct servent *sp;
|
|
||||||
- struct hostent *hp;
|
|
||||||
+ socklen_t socklen;
|
|
||||||
|
|
||||||
protocol = udp ? "udp" : "tcp";
|
|
||||||
|
|
||||||
/* initialize socket address structure */
|
|
||||||
- bzero(&servaddr, sizeof(servaddr));
|
|
||||||
- servaddr.sin_family = AF_INET;
|
|
||||||
+ bzero(&servaddr4, sizeof(servaddr4));
|
|
||||||
+ servaddr4.sin_family = AF_INET;
|
|
||||||
+
|
|
||||||
+ bzero(&servaddr6, sizeof(servaddr6));
|
|
||||||
+ servaddr6.sin6_family = AF_INET6;
|
|
||||||
|
|
||||||
/* see if "port" is a service name or number */
|
|
||||||
if ( (i = atoi(port)) == 0) {
|
|
||||||
if ( (sp = getservbyname(port, protocol)) == NULL)
|
|
||||||
- err_quit("getservbyname() error for: %s/%s", port, protocol);
|
|
||||||
-
|
|
||||||
- servaddr.sin_port = sp->s_port;
|
|
||||||
- } else
|
|
||||||
- servaddr.sin_port = htons(i);
|
|
||||||
+ err_quit("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);
|
|
||||||
+ }
|
|
||||||
|
|
||||||
/*
|
|
||||||
- * First try to convert the host name as a dotted-decimal number.
|
|
||||||
- * Only if that fails do we call gethostbyname().
|
|
||||||
+ * First try to convert the host name as an IPv4 dotted-decimal number
|
|
||||||
+ * or an IPv6 address. Only if that fails do we try to convert the
|
|
||||||
+ * host name as a host name string.
|
|
||||||
*/
|
|
||||||
-
|
|
||||||
- if (inet_aton(host, &inaddr) == 1)
|
|
||||||
- servaddr.sin_addr = inaddr; /* it's dotted-decimal */
|
|
||||||
- else if ( (hp = gethostbyname(host)) != NULL)
|
|
||||||
- bcopy(hp->h_addr, &servaddr.sin_addr, hp->h_length);
|
|
||||||
- else
|
|
||||||
- err_quit("invalid hostname: %s", host);
|
|
||||||
+ if (convert_host_address(host) != 1) {
|
|
||||||
+ if (convert_host_name(host) != 1) {
|
|
||||||
+ err_quit("invalid hostname: %s", host);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
|
|
||||||
- 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) {
|
|
||||||
@@ -71,21 +136,46 @@ int cliopen(char *host, char *port)
|
|
||||||
* (and port) using -l option. Allow localip[] to be set but bindport
|
|
||||||
* to be 0.
|
|
||||||
*/
|
|
||||||
-
|
|
||||||
if (bindport != 0 || localip[0] != 0 || udp) {
|
|
||||||
- bzero(&cliaddr, sizeof(cliaddr));
|
|
||||||
- cliaddr.sin_family = AF_INET;
|
|
||||||
- cliaddr.sin_port = htons(bindport); /* can be 0 */
|
|
||||||
- if (localip[0] != 0) {
|
|
||||||
- if (inet_aton(localip, &cliaddr.sin_addr) == 0)
|
|
||||||
- err_quit("invalid IP address: %s", localip);
|
|
||||||
- } else
|
|
||||||
- cliaddr.sin_addr.s_addr = htonl(INADDR_ANY); /* wildcard */
|
|
||||||
-
|
|
||||||
- if (bind(fd, (struct sockaddr *) &cliaddr, sizeof(cliaddr)) < 0)
|
|
||||||
- err_sys("bind() error");
|
|
||||||
+ if (af_46 == AF_INET) {
|
|
||||||
+ bzero(&cliaddr4, sizeof(cliaddr4));
|
|
||||||
+ cliaddr4.sin_family = AF_INET;
|
|
||||||
+ /* can be 0 */
|
|
||||||
+ cliaddr4.sin_port = htons(bindport);
|
|
||||||
+ if (localip[0] != 0) {
|
|
||||||
+ if (inet_aton(localip, &cliaddr4.sin_addr) == 0)
|
|
||||||
+ err_quit("invalid IP address: %s",
|
|
||||||
+ localip);
|
|
||||||
+ } else {
|
|
||||||
+ /* wildcard */
|
|
||||||
+ cliaddr4.sin_addr.s_addr = htonl(INADDR_ANY);
|
|
||||||
+ }
|
|
||||||
+ if (bind(fd, (struct sockaddr *) &cliaddr4,
|
|
||||||
+ sizeof(cliaddr4)) < 0) {
|
|
||||||
+ err_sys("bind() error");
|
|
||||||
+ }
|
|
||||||
+ } else {
|
|
||||||
+ bzero(&cliaddr6, sizeof(cliaddr6));
|
|
||||||
+ cliaddr6.sin6_len = sizeof(struct sockaddr_in6);
|
|
||||||
+ cliaddr6.sin6_family = AF_INET6;
|
|
||||||
+ /* can be 0 */
|
|
||||||
+ cliaddr6.sin6_port = htons(bindport);
|
|
||||||
+
|
|
||||||
+ /* Fixme: localip not implemented for IPv6 */
|
|
||||||
+ cliaddr6.sin6_addr = in6addr_any;
|
|
||||||
+
|
|
||||||
+ /* Fixme: Want to set IPV6_BINDANY? */
|
|
||||||
+
|
|
||||||
+ if (bind(fd, (struct sockaddr *) &cliaddr6,
|
|
||||||
+ sizeof(cliaddr6)) < 0) {
|
|
||||||
+ err_sys("bind() error");
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
-
|
|
||||||
+
|
|
||||||
+ /* Fixme: Does not work */
|
|
||||||
+ //join_mcast_client(fd, &cliaddr4, &cliaddr6, &servaddr4, &servaddr6);
|
|
||||||
+
|
|
||||||
/* Need to allocate buffers before connect(), since they can affect
|
|
||||||
* TCP options (window scale, etc.).
|
|
||||||
*/
|
|
||||||
@@ -96,13 +186,21 @@ int cliopen(char *host, char *port)
|
|
||||||
/*
|
|
||||||
* Connect to the server. Required for TCP, optional for UDP.
|
|
||||||
*/
|
|
||||||
-
|
|
||||||
if (udp == 0 || connectudp) {
|
|
||||||
for ( ; ; ) {
|
|
||||||
- if (connect(fd, (struct sockaddr *) &servaddr, sizeof(servaddr))
|
|
||||||
- == 0)
|
|
||||||
+ if (AF_INET == af_46) {
|
|
||||||
+ if (connect(fd, (struct sockaddr *) &servaddr4,
|
|
||||||
+ sizeof(servaddr4)) == 0)
|
|
||||||
break; /* all OK */
|
|
||||||
- if (errno == EINTR) /* can happen with SIGIO */
|
|
||||||
+ } else {
|
|
||||||
+ servaddr6.sin6_len =
|
|
||||||
+ sizeof(struct sockaddr_in6);
|
|
||||||
+ servaddr6.sin6_family = AF_INET6;
|
|
||||||
+ if (connect(fd, (struct sockaddr *) &servaddr6,
|
|
||||||
+ sizeof(servaddr6)) == 0)
|
|
||||||
+ break; /* all OK */
|
|
||||||
+ }
|
|
||||||
+ if (errno == EINTR) /* can happen with SIGIO */
|
|
||||||
continue;
|
|
||||||
if (errno == EISCONN) /* can happen with SIGIO */
|
|
||||||
break;
|
|
||||||
@@ -114,16 +212,38 @@ int cliopen(char *host, char *port)
|
|
||||||
/* Call getsockname() to find local address bound to socket:
|
|
||||||
TCP ephemeral port was assigned by connect() or bind();
|
|
||||||
UDP ephemeral port was assigned by bind(). */
|
|
||||||
- i = sizeof(cliaddr);
|
|
||||||
- if (getsockname(fd, (struct sockaddr *) &cliaddr, &i) < 0)
|
|
||||||
- err_sys("getsockname() error");
|
|
||||||
-
|
|
||||||
- /* Can't do one fprintf() since inet_ntoa() stores
|
|
||||||
- the result in a static location. */
|
|
||||||
- fprintf(stderr, "connected on %s.%d ",
|
|
||||||
- INET_NTOA(cliaddr.sin_addr), ntohs(cliaddr.sin_port));
|
|
||||||
- fprintf(stderr, "to %s.%d\n",
|
|
||||||
- INET_NTOA(servaddr.sin_addr), ntohs(servaddr.sin_port));
|
|
||||||
+ if (AF_INET == af_46) {
|
|
||||||
+ socklen = sizeof(cliaddr4);
|
|
||||||
+ if (getsockname(fd,
|
|
||||||
+ (struct sockaddr *) &cliaddr4, &socklen) < 0) {
|
|
||||||
+ err_sys("getsockname() error");
|
|
||||||
+ }
|
|
||||||
+ /* Can't do one fprintf() since inet_ntoa() stores
|
|
||||||
+ the result in a static location. */
|
|
||||||
+ fprintf(stderr, "connected on %s.%d ",
|
|
||||||
+ INET_NTOA(cliaddr4.sin_addr),
|
|
||||||
+ ntohs(cliaddr4.sin_port));
|
|
||||||
+ fprintf(stderr, "to %s.%d\n",
|
|
||||||
+ INET_NTOA(servaddr4.sin_addr),
|
|
||||||
+ ntohs(servaddr4.sin_port));
|
|
||||||
+ } else {
|
|
||||||
+ socklen = sizeof(cliaddr6);
|
|
||||||
+ if (getsockname(fd,
|
|
||||||
+ (struct sockaddr *) &cliaddr6, &socklen) < 0) {
|
|
||||||
+ err_sys("getsockname() error");
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ inet_ntop(AF_INET6,
|
|
||||||
+ &cliaddr6.sin6_addr.__u6_addr.__u6_addr8,
|
|
||||||
+ inaddr_buf, sizeof(inaddr_buf));
|
|
||||||
+ fprintf(stderr, "connected on %s.%d ",
|
|
||||||
+ inaddr_buf, ntohs(cliaddr6.sin6_port));
|
|
||||||
+ inet_ntop(AF_INET6,
|
|
||||||
+ &servaddr6.sin6_addr.__u6_addr.__u6_addr8,
|
|
||||||
+ inaddr_buf, sizeof(inaddr_buf));
|
|
||||||
+ fprintf(stderr, "to %s.%d\n",
|
|
||||||
+ inaddr_buf, ntohs(servaddr6.sin6_port));
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
|
|
||||||
sockopts(fd, 1); /* some options get set after connect() */
|
|
|
@ -1,261 +0,0 @@
|
||||||
--- src/loopudp.c.orig 2010-05-28 00:03:25 UTC
|
|
||||||
+++ src/loopudp.c
|
|
||||||
@@ -21,17 +21,28 @@
|
|
||||||
void
|
|
||||||
loop_udp(int sockfd)
|
|
||||||
{
|
|
||||||
- int maxfdp1, nread, ntowrite, stdineof, clilen, servlen, flags;
|
|
||||||
+ int maxfdp1, nread, ntowrite, stdineof, clilen, flags;
|
|
||||||
+ socklen_t servlen;
|
|
||||||
fd_set rset;
|
|
||||||
- struct sockaddr_in cliaddr; /* for UDP server */
|
|
||||||
- struct sockaddr_in servaddr; /* for UDP client */
|
|
||||||
+ struct sockaddr_in cliaddr4; /* for IPv4 UDP server */
|
|
||||||
+ struct sockaddr_in6 cliaddr6; /* for IPv6 UDP server */
|
|
||||||
+ /*
|
|
||||||
+ * The original local variable servaddr, and later servaddr4 and
|
|
||||||
+ * servaddr6, were not initialized before use. Using the initialized
|
|
||||||
+ * global sockaddr structs allows the sendto() code, below, to work
|
|
||||||
+ * correctly. This was a problem with the original IPv4 code, and
|
|
||||||
+ * later the IPv6 code.
|
|
||||||
+ */
|
|
||||||
+ //struct sockaddr_in servaddr4; /* for IPv4 UDP client */
|
|
||||||
+ //struct sockaddr_in6 servaddr6; /* for IPv6 UDP client */
|
|
||||||
+ char inaddr_buf[INET6_ADDRSTRLEN];
|
|
||||||
|
|
||||||
- struct iovec iov[1];
|
|
||||||
- struct msghdr msg;
|
|
||||||
+ struct iovec iov[1];
|
|
||||||
+ struct msghdr msg;
|
|
||||||
#ifdef HAVE_MSGHDR_MSG_CONTROL
|
|
||||||
#ifdef IP_RECVDSTADDR /* 4.3BSD Reno and later */
|
|
||||||
static struct cmsghdr *cmptr = NULL; /* malloc'ed */
|
|
||||||
- struct in_addr dstinaddr; /* for UDP server */
|
|
||||||
+ struct in_addr dstinaddr; /* for UDP server */
|
|
||||||
#define CONTROLLEN (sizeof(struct cmsghdr) + sizeof(struct in_addr))
|
|
||||||
#endif /* IP_RECVDSTADDR */
|
|
||||||
|
|
||||||
@@ -68,8 +79,10 @@ loop_udp(int sockfd)
|
|
||||||
err_sys("shutdown() error");
|
|
||||||
|
|
||||||
FD_CLR(STDIN_FILENO, &rset);
|
|
||||||
- stdineof = 1; /* don't read stdin anymore */
|
|
||||||
- continue; /* back to select() */
|
|
||||||
+ /* don't read stdin anymore */
|
|
||||||
+ stdineof = 1;
|
|
||||||
+ /* back to select() */
|
|
||||||
+ continue;
|
|
||||||
}
|
|
||||||
break; /* default: stdin EOF -> done */
|
|
||||||
}
|
|
||||||
@@ -77,23 +90,43 @@ loop_udp(int sockfd)
|
|
||||||
if (crlf) {
|
|
||||||
ntowrite = crlf_add(wbuf, writelen, rbuf, nread);
|
|
||||||
if (connectudp) {
|
|
||||||
- if (write(sockfd, wbuf, ntowrite) != ntowrite)
|
|
||||||
+ if (write(sockfd, wbuf, ntowrite) !=
|
|
||||||
+ ntowrite) {
|
|
||||||
err_sys("write error");
|
|
||||||
+ }
|
|
||||||
} else {
|
|
||||||
- if (sendto(sockfd, wbuf, ntowrite, 0,
|
|
||||||
- (struct sockaddr *) &servaddr, sizeof(servaddr))
|
|
||||||
- != ntowrite)
|
|
||||||
- err_sys("sendto error");
|
|
||||||
+ if (af_46 == AF_INET) {
|
|
||||||
+ if (sendto(sockfd, wbuf, ntowrite, 0,
|
|
||||||
+ (struct sockaddr *)&servaddr4,
|
|
||||||
+ sizeof(servaddr4)) != ntowrite) {
|
|
||||||
+ err_sys("sendto error");
|
|
||||||
+ }
|
|
||||||
+ } else {
|
|
||||||
+ if (sendto(sockfd, wbuf, ntowrite, 0,
|
|
||||||
+ (struct sockaddr *)&servaddr6,
|
|
||||||
+ sizeof(servaddr6)) != ntowrite) {
|
|
||||||
+ err_sys("sendto error");
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (connectudp) {
|
|
||||||
if (write(sockfd, rbuf, nread) != nread)
|
|
||||||
err_sys("write error");
|
|
||||||
} else {
|
|
||||||
- if (sendto(sockfd, rbuf, nread, 0,
|
|
||||||
- (struct sockaddr *) &servaddr, sizeof(servaddr))
|
|
||||||
- != nread)
|
|
||||||
- err_sys("sendto error");
|
|
||||||
+ if (af_46 == AF_INET) {
|
|
||||||
+ if (sendto(sockfd, rbuf, nread, 0,
|
|
||||||
+ (struct sockaddr *)&servaddr4,
|
|
||||||
+ sizeof(servaddr4)) != nread) {
|
|
||||||
+ err_sys("sendto error");
|
|
||||||
+ }
|
|
||||||
+ } else {
|
|
||||||
+ if (sendto(sockfd, rbuf, nread, 0,
|
|
||||||
+ (struct sockaddr *)&servaddr6,
|
|
||||||
+ sizeof(servaddr6)) != nread) {
|
|
||||||
+ err_sys("sendto error");
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -101,35 +134,54 @@ loop_udp(int sockfd)
|
|
||||||
if (FD_ISSET(sockfd, &rset)) {
|
|
||||||
/* data to read from socket */
|
|
||||||
if (server) {
|
|
||||||
- clilen = sizeof(cliaddr);
|
|
||||||
-#ifndef MSG_TRUNC /* vanilla BSD sockets */
|
|
||||||
+ if (af_46 == AF_INET) {
|
|
||||||
+ clilen = sizeof(cliaddr4);
|
|
||||||
+ } else {
|
|
||||||
+ clilen = sizeof(cliaddr6);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+#ifndef MSG_TRUNC /* vanilla BSD sockets */
|
|
||||||
+
|
|
||||||
+ /* Fixme: Not ported for IPv6 */
|
|
||||||
+ /* Not compiled in for FreeBSD 8.4 */
|
|
||||||
nread = recvfrom(sockfd, rbuf, readlen, 0,
|
|
||||||
- (struct sockaddr *) &cliaddr, &clilen);
|
|
||||||
-
|
|
||||||
+ (struct sockaddr *) &cliaddr4, &clilen);
|
|
||||||
+
|
|
||||||
#else /* 4.3BSD Reno and later; use recvmsg() to get at MSG_TRUNC flag */
|
|
||||||
- /* Also lets us get at control information (destination address) */
|
|
||||||
-
|
|
||||||
+ /* Also lets us get at control information (destination address) */
|
|
||||||
+
|
|
||||||
+ /* FreeBSD 8.4 */
|
|
||||||
iov[0].iov_base = rbuf;
|
|
||||||
iov[0].iov_len = readlen;
|
|
||||||
- msg.msg_iov = iov;
|
|
||||||
- msg.msg_iovlen = 1;
|
|
||||||
- msg.msg_name = (caddr_t) &cliaddr;
|
|
||||||
- msg.msg_namelen = clilen;
|
|
||||||
-
|
|
||||||
+ msg.msg_iov = iov;
|
|
||||||
+ msg.msg_iovlen = 1;
|
|
||||||
+ if (af_46 == AF_INET) {
|
|
||||||
+ msg.msg_name = (caddr_t) &cliaddr4;
|
|
||||||
+ } else {
|
|
||||||
+ msg.msg_name = (caddr_t) &cliaddr6;
|
|
||||||
+ }
|
|
||||||
+ msg.msg_namelen = clilen;
|
|
||||||
+
|
|
||||||
#ifdef HAVE_MSGHDR_MSG_CONTROL
|
|
||||||
#ifdef IP_RECVDSTADDR
|
|
||||||
+ /* FreeBSD 8.4 */
|
|
||||||
if (cmptr == NULL && (cmptr = malloc(CONTROLLEN)) == NULL)
|
|
||||||
err_sys("malloc error for control buffer");
|
|
||||||
|
|
||||||
- msg.msg_control = (caddr_t) cmptr; /* for dest address */
|
|
||||||
+ /* for dest address */
|
|
||||||
+ msg.msg_control = (caddr_t) cmptr;
|
|
||||||
msg.msg_controllen = CONTROLLEN;
|
|
||||||
#else
|
|
||||||
- msg.msg_control = (caddr_t) 0; /* no ancillary data */
|
|
||||||
+ /* Not used for FreeBSD 8.4 */
|
|
||||||
+ /* no ancillary data */
|
|
||||||
+ msg.msg_control = (caddr_t) 0;
|
|
||||||
msg.msg_controllen = 0;
|
|
||||||
#endif /* IP_RECVDSTADDR */
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_MSGHDR_MSG_FLAGS
|
|
||||||
- msg.msg_flags = 0; /* flags returned here */
|
|
||||||
+ /* FreeBSD 8.4 */
|
|
||||||
+ /* flags returned here */
|
|
||||||
+ msg.msg_flags = 0;
|
|
||||||
#endif
|
|
||||||
nread = recvmsg(sockfd, &msg, 0);
|
|
||||||
#endif /* MSG_TRUNC */
|
|
||||||
@@ -137,22 +189,39 @@ loop_udp(int sockfd)
|
|
||||||
err_sys("datagram receive error");
|
|
||||||
|
|
||||||
if (verbose) {
|
|
||||||
- printf("from %s", INET_NTOA(cliaddr.sin_addr));
|
|
||||||
+ if (af_46 == AF_INET) {
|
|
||||||
+ printf("from %s",
|
|
||||||
+ INET_NTOA(cliaddr4.sin_addr));
|
|
||||||
+ } else {
|
|
||||||
+ inet_ntop(AF_INET6,
|
|
||||||
+ &cliaddr6.sin6_addr.
|
|
||||||
+ __u6_addr.__u6_addr8,
|
|
||||||
+ inaddr_buf,
|
|
||||||
+ sizeof(inaddr_buf));
|
|
||||||
+ printf("from %s", inaddr_buf);
|
|
||||||
+ }
|
|
||||||
#ifdef HAVE_MSGHDR_MSG_CONTROL
|
|
||||||
#ifdef IP_RECVDSTADDR
|
|
||||||
+ /*
|
|
||||||
+ * Fixme: not ported for IPv6
|
|
||||||
+ * Fixme: recvdstaddr fails (earlier,
|
|
||||||
+ * in setsockopt()) for IPv6 under
|
|
||||||
+ * FreeBSD 8.4
|
|
||||||
+ */
|
|
||||||
if (recvdstaddr) {
|
|
||||||
if (cmptr->cmsg_len != CONTROLLEN)
|
|
||||||
err_quit("control length (%d) != %d",
|
|
||||||
- cmptr->cmsg_len, CONTROLLEN);
|
|
||||||
+ cmptr->cmsg_len, CONTROLLEN);
|
|
||||||
if (cmptr->cmsg_level != IPPROTO_IP)
|
|
||||||
err_quit("control level != IPPROTO_IP");
|
|
||||||
if (cmptr->cmsg_type != IP_RECVDSTADDR)
|
|
||||||
err_quit("control type != IP_RECVDSTADDR");
|
|
||||||
bcopy(CMSG_DATA(cmptr), &dstinaddr,
|
|
||||||
- sizeof(struct in_addr));
|
|
||||||
+ sizeof(struct in_addr));
|
|
||||||
bzero(cmptr, CONTROLLEN);
|
|
||||||
|
|
||||||
- printf(", to %s", INET_NTOA(dstinaddr));
|
|
||||||
+ printf(", to %s",
|
|
||||||
+ INET_NTOA(dstinaddr));
|
|
||||||
}
|
|
||||||
#endif /* IP_RECVDSTADDR */
|
|
||||||
#endif /* HAVE_MSGHDR_MSG_CONTROL */
|
|
||||||
@@ -178,15 +247,37 @@ loop_udp(int sockfd)
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
- /* Must use recvfrom() for unconnected UDP client */
|
|
||||||
- servlen = sizeof(servaddr);
|
|
||||||
- nread = recvfrom(sockfd, rbuf, readlen, 0,
|
|
||||||
- (struct sockaddr *) &servaddr, &servlen);
|
|
||||||
- if (nread < 0)
|
|
||||||
+ /*
|
|
||||||
+ * Must use recvfrom() for unconnected
|
|
||||||
+ * UDP client
|
|
||||||
+ */
|
|
||||||
+ /* Fixme: not tested on FreeBSD 8.4 */
|
|
||||||
+ if (af_46 == AF_INET) {
|
|
||||||
+ servlen = sizeof(servaddr4);
|
|
||||||
+ nread = recvfrom(sockfd, rbuf, readlen,
|
|
||||||
+ 0, (struct sockaddr *)&servaddr4,
|
|
||||||
+ &servlen);
|
|
||||||
+ } else {
|
|
||||||
+ servlen = sizeof(servaddr6);
|
|
||||||
+ nread = recvfrom(sockfd, rbuf, readlen,
|
|
||||||
+ 0, (struct sockaddr *)&servaddr6,
|
|
||||||
+ &servlen);
|
|
||||||
+ }
|
|
||||||
+ if (nread < 0) {
|
|
||||||
err_sys("datagram recvfrom() error");
|
|
||||||
-
|
|
||||||
+ }
|
|
||||||
if (verbose) {
|
|
||||||
- printf("from %s", INET_NTOA(servaddr.sin_addr));
|
|
||||||
+ if (af_46 == AF_INET) {
|
|
||||||
+ printf("from %s",
|
|
||||||
+ INET_NTOA(servaddr4.sin_addr));
|
|
||||||
+ } else {
|
|
||||||
+ inet_ntop(AF_INET6,
|
|
||||||
+ &servaddr6.sin6_addr.
|
|
||||||
+ __u6_addr.__u6_addr8,
|
|
||||||
+ inaddr_buf,
|
|
||||||
+ sizeof(inaddr_buf));
|
|
||||||
+ printf("from %s", inaddr_buf);
|
|
||||||
+ }
|
|
||||||
printf(": ");
|
|
||||||
fflush(stdout);
|
|
||||||
}
|
|
|
@ -1,60 +0,0 @@
|
||||||
--- src/main.c.orig 2010-05-28 00:03:25 UTC
|
|
||||||
+++ src/main.c
|
|
||||||
@@ -23,9 +23,10 @@
|
|
||||||
char *host; /* hostname or dotted-decimal string */
|
|
||||||
char *port;
|
|
||||||
|
|
||||||
- /* DefinE global variables */
|
|
||||||
+ /* Define global variables */
|
|
||||||
+int af_46 = AF_INET; /* AF_INET or AF_INET6 */
|
|
||||||
int bindport; /* 0 or TCP or UDP port number to bind */
|
|
||||||
- /* set by -b or -l options */
|
|
||||||
+ /* set by -b or -l options */
|
|
||||||
int broadcast; /* SO_BROADCAST */
|
|
||||||
int cbreak; /* set terminal to cbreak mode */
|
|
||||||
int chunkwrite; /* write in small chunks; not all-at-once */
|
|
||||||
@@ -76,7 +77,8 @@ int urgwrite; /* write urgent byte af
|
|
||||||
int verbose; /* each -v increments this by 1 */
|
|
||||||
int usewritev; /* use writev() instead of write() */
|
|
||||||
|
|
||||||
-struct sockaddr_in cliaddr, servaddr;
|
|
||||||
+struct sockaddr_in cliaddr4, servaddr4;
|
|
||||||
+struct sockaddr_in6 cliaddr6, servaddr6;
|
|
||||||
|
|
||||||
static void usage(const char *);
|
|
||||||
|
|
||||||
@@ -90,13 +92,16 @@ main(int argc, char *argv[])
|
|
||||||
usage("");
|
|
||||||
|
|
||||||
opterr = 0; /* don't want getopt() writing to stderr */
|
|
||||||
- while ( (c = getopt(argc, argv, "2b:cf:g:hij:kl:n:op:q:r:st:uvw:x:y:ABCDEFG:H:IJ:KL:NO:P:Q:R:S:TU:VWX:YZ")) != -1) {
|
|
||||||
+ while ( (c = getopt(argc, argv, "26b:cf:g:hij:kl:n:op:q:r:st:uvw:x:y:ABCDEFG:H:IJ:KL:NO:P:Q:R:S:TU:VWX:YZ")) != -1) {
|
|
||||||
switch (c) {
|
|
||||||
#ifdef IP_ONESBCAST
|
|
||||||
case '2': /* use 255.255.255.255 as broadcast address */
|
|
||||||
onesbcast = 1;
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
+ case '6': /* use IPv6 */
|
|
||||||
+ af_46 = AF_INET6;
|
|
||||||
+ break;
|
|
||||||
|
|
||||||
case 'b':
|
|
||||||
bindport = atoi(optarg);
|
|
||||||
@@ -309,7 +314,7 @@ main(int argc, char *argv[])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- /* check for options that don't make sense */
|
|
||||||
+ /* check for options that don't make sense */
|
|
||||||
if (udp && halfclose)
|
|
||||||
usage("can't specify -h and -u");
|
|
||||||
if (udp && debug)
|
|
||||||
@@ -439,6 +444,7 @@ usage(const char *msg)
|
|
||||||
#ifdef IP_ONESBCAST
|
|
||||||
" -2 IP_ONESBCAST option (255.255.255.255 for broadcast\n"
|
|
||||||
#endif
|
|
||||||
+" -6 use IPv6 instead of IPv4\n"
|
|
||||||
);
|
|
||||||
|
|
||||||
if (msg[0] != 0)
|
|
|
@ -1,111 +0,0 @@
|
||||||
--- src/multicast.c.orig 2010-05-28 00:03:25 UTC
|
|
||||||
+++ src/multicast.c
|
|
||||||
@@ -10,24 +10,96 @@
|
|
||||||
|
|
||||||
#include "sock.h"
|
|
||||||
|
|
||||||
+/*
|
|
||||||
+ * Works for IPv4 and IPv6.
|
|
||||||
+ * For IPv4, the server is able to join a multicast group such as 224.0.0.1.
|
|
||||||
+ * The client is able to connect to the same multicast address and port
|
|
||||||
+ * assigned to the server. The client can then send data, which the server
|
|
||||||
+ * receives.
|
|
||||||
+ * For IPv6, the server is able to join a multicast group of the form ff02::n.
|
|
||||||
+ * The client is never able to connect to that address/port, however.
|
|
||||||
+ */
|
|
||||||
void
|
|
||||||
-join_mcast(int fd, struct sockaddr_in *sin)
|
|
||||||
+join_mcast_server(int fd, struct sockaddr_in *sin, struct sockaddr_in6 *sin6)
|
|
||||||
{
|
|
||||||
#ifdef IP_ADD_MEMBERSHIP /* only include if host supports mcasting */
|
|
||||||
- u_long inaddr;
|
|
||||||
- struct ip_mreq mreq;
|
|
||||||
+ u_long inaddr;
|
|
||||||
+ struct ip_mreq mreq;
|
|
||||||
+ struct ipv6_mreq mreq6;
|
|
||||||
|
|
||||||
- inaddr = sin->sin_addr.s_addr;
|
|
||||||
- if (IN_MULTICAST(inaddr) == 0)
|
|
||||||
- return; /* not a multicast address */
|
|
||||||
+ if (af_46 == AF_INET) {
|
|
||||||
+ inaddr = sin->sin_addr.s_addr;
|
|
||||||
+ /*
|
|
||||||
+ * FreeBSD 8.4: IN_MULTICAST() test fails in the original code
|
|
||||||
+ * because it was testing inaddr with the wrong endianness.
|
|
||||||
+ * Fixed in this version of the code, at least for FreeBSD.
|
|
||||||
+ */
|
|
||||||
+ inaddr = ntohl(inaddr);
|
|
||||||
|
|
||||||
- mreq.imr_multiaddr.s_addr = inaddr;
|
|
||||||
- mreq.imr_interface.s_addr = htonl(INADDR_ANY); /* need way to change */
|
|
||||||
- if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq,
|
|
||||||
- sizeof(mreq)) == -1 )
|
|
||||||
- err_sys("IP_ADD_MEMBERSHIP error");
|
|
||||||
+ if (IN_MULTICAST(inaddr) == 0) {
|
|
||||||
+ return; /* not a multicast address */
|
|
||||||
+ }
|
|
||||||
+ } else {
|
|
||||||
+ if (IN6_IS_ADDR_MULTICAST(&(sin6->sin6_addr)) == 0) {
|
|
||||||
+ return; /* not a multicast address */
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (af_46 == AF_INET) {
|
|
||||||
+ mreq.imr_multiaddr.s_addr = sin->sin_addr.s_addr;
|
|
||||||
+ /* need way to change */
|
|
||||||
+ mreq.imr_interface.s_addr = htonl(INADDR_ANY);
|
|
||||||
+ if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq,
|
|
||||||
+ sizeof(mreq)) == -1 ) {
|
|
||||||
+ err_sys("IP_ADD_MEMBERSHIP error");
|
|
||||||
+ }
|
|
||||||
+ } else {
|
|
||||||
+ memset((char *)&mreq6, 0, sizeof(mreq6));
|
|
||||||
+ mreq6.ipv6mr_multiaddr = sin6->sin6_addr;
|
|
||||||
+ mreq6.ipv6mr_interface = sin6->sin6_scope_id;
|
|
||||||
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq6,
|
|
||||||
+ sizeof(mreq6)) == -1 ) {
|
|
||||||
+ err_sys("IP_ADD_MEMBERSHIP error");
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
|
|
||||||
if (verbose)
|
|
||||||
- fprintf(stderr, "multicast group joined\n");
|
|
||||||
+ fprintf(stderr, "multicast group joined\n");
|
|
||||||
+#endif /* IP_ADD_MEMBERSHIP */
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/*
|
|
||||||
+ * Added for IPv6. Fixme: Does not work at present.
|
|
||||||
+ * The client is currently unable to connect to the multicast address/port
|
|
||||||
+ * which was joined by the server. A function similar to this may be needed
|
|
||||||
+ * to permit that connection to be made.
|
|
||||||
+ */
|
|
||||||
+void
|
|
||||||
+join_mcast_client(int fd,
|
|
||||||
+ struct sockaddr_in *cli_sin, struct sockaddr_in6 *cli_sin6,
|
|
||||||
+ struct sockaddr_in *serv_sin, struct sockaddr_in6 *serv_sin6)
|
|
||||||
+{
|
|
||||||
+#ifdef IP_ADD_MEMBERSHIP /* only include if host supports mcasting */
|
|
||||||
+ struct ipv6_mreq mreq6;
|
|
||||||
+
|
|
||||||
+ if (af_46 == AF_INET6) {
|
|
||||||
+ if (IN6_IS_ADDR_MULTICAST(&(serv_sin6->sin6_addr)) == 0) {
|
|
||||||
+ return; /* not a multicast address */
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (af_46 == AF_INET6) {
|
|
||||||
+ memset((char *)&mreq6, 0, sizeof(mreq6));
|
|
||||||
+ mreq6.ipv6mr_multiaddr = serv_sin6->sin6_addr;
|
|
||||||
+ mreq6.ipv6mr_interface = serv_sin6->sin6_scope_id;
|
|
||||||
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq6,
|
|
||||||
+ sizeof(mreq6)) == -1 ) {
|
|
||||||
+ err_sys("IP_ADD_MEMBERSHIP error");
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (verbose) {
|
|
||||||
+ fprintf(stderr, "multicast group joined\n");
|
|
||||||
+ }
|
|
||||||
#endif /* IP_ADD_MEMBERSHIP */
|
|
||||||
}
|
|
|
@ -1,282 +0,0 @@
|
||||||
--- 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);
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
--- src/sock.h.orig 2010-05-28 00:03:25 UTC
|
|
||||||
+++ src/sock.h
|
|
||||||
@@ -62,6 +62,7 @@ extern int errno;
|
|
||||||
#define max(a,b) ((a) > (b) ? (a) : (b))
|
|
||||||
|
|
||||||
/* declare global variables */
|
|
||||||
+extern int af_46;
|
|
||||||
extern int bindport;
|
|
||||||
extern int broadcast;
|
|
||||||
extern int cbreak;
|
|
||||||
@@ -114,6 +115,8 @@ extern int verbose;
|
|
||||||
extern int usewritev;
|
|
||||||
|
|
||||||
extern struct sockaddr_in cliaddr, servaddr;
|
|
||||||
+extern struct sockaddr_in cliaddr4, servaddr4;
|
|
||||||
+extern struct sockaddr_in6 cliaddr6, servaddr6;
|
|
||||||
|
|
||||||
/* Earlier versions of gcc under SunOS 4.x have problems passing arguments
|
|
||||||
that are structs (as opposed to pointers to structs). This shows up
|
|
||||||
@@ -130,7 +133,9 @@ void buffers(int);
|
|
||||||
int cliopen(char *, char *);
|
|
||||||
int crlf_add(char *, int, const char *, int);
|
|
||||||
int crlf_strip(char *, int, const char *, int);
|
|
||||||
-void join_mcast(int, struct sockaddr_in *);
|
|
||||||
+void join_mcast_server(int, struct sockaddr_in *, struct sockaddr_in6 *);
|
|
||||||
+void join_mcast_client(int, struct sockaddr_in *, struct sockaddr_in6 *,
|
|
||||||
+ struct sockaddr_in *, struct sockaddr_in6 *);
|
|
||||||
void loop_tcp(int);
|
|
||||||
void loop_udp(int);
|
|
||||||
void pattern(char *, int);
|
|
|
@ -1,122 +0,0 @@
|
||||||
--- src/sockopts.c.orig 2010-05-28 00:03:25 UTC
|
|
||||||
+++ src/sockopts.c
|
|
||||||
@@ -30,6 +30,13 @@ sockopts(int sockfd, int doall)
|
|
||||||
unsigned optlen;
|
|
||||||
struct linger ling;
|
|
||||||
struct timeval timer;
|
|
||||||
+ int level;
|
|
||||||
+
|
|
||||||
+ if (AF_INET == af_46) {
|
|
||||||
+ level = IPPROTO_IP;
|
|
||||||
+ } else {
|
|
||||||
+ level = IPPROTO_IPV6;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
/* "doall" is 0 for a server's listening socket (i.e., before
|
|
||||||
accept() has returned.) Some socket options such as SO_KEEPALIVE
|
|
||||||
@@ -73,13 +80,13 @@ sockopts(int sockfd, int doall)
|
|
||||||
|
|
||||||
#ifdef IP_TOS
|
|
||||||
if (iptos != -1 && doall == 0) {
|
|
||||||
- if (setsockopt(sockfd, IPPROTO_IP, IP_TOS,
|
|
||||||
+ if (setsockopt(sockfd, level, IP_TOS,
|
|
||||||
&iptos, sizeof(iptos)) < 0)
|
|
||||||
err_sys("IP_TOS setsockopt error");
|
|
||||||
|
|
||||||
option = 0;
|
|
||||||
optlen = sizeof(option);
|
|
||||||
- if (getsockopt(sockfd, IPPROTO_IP, IP_TOS,
|
|
||||||
+ if (getsockopt(sockfd, level, IP_TOS,
|
|
||||||
&option, &optlen) < 0)
|
|
||||||
err_sys("IP_TOS getsockopt error");
|
|
||||||
if (option != iptos)
|
|
||||||
@@ -92,13 +99,13 @@ sockopts(int sockfd, int doall)
|
|
||||||
|
|
||||||
#ifdef IP_TTL
|
|
||||||
if (ipttl != -1 && doall == 0) {
|
|
||||||
- if (setsockopt(sockfd, IPPROTO_IP, IP_TTL,
|
|
||||||
+ if (setsockopt(sockfd, level, IP_TTL,
|
|
||||||
&ipttl, sizeof(ipttl)) < 0)
|
|
||||||
err_sys("IP_TTL setsockopt error");
|
|
||||||
|
|
||||||
option = 0;
|
|
||||||
optlen = sizeof(option);
|
|
||||||
- if (getsockopt(sockfd, IPPROTO_IP, IP_TTL,
|
|
||||||
+ if (getsockopt(sockfd, level, IP_TTL,
|
|
||||||
&option, &optlen) < 0)
|
|
||||||
err_sys("IP_TTL getsockopt error");
|
|
||||||
if (option != ipttl)
|
|
||||||
@@ -150,13 +157,13 @@ sockopts(int sockfd, int doall)
|
|
||||||
#ifdef IP_ONESBCAST
|
|
||||||
if (onesbcast) {
|
|
||||||
option = 1;
|
|
||||||
- if (setsockopt(sockfd, IPPROTO_IP, IP_ONESBCAST,
|
|
||||||
+ if (setsockopt(sockfd, level, IP_ONESBCAST,
|
|
||||||
&option, sizeof(option)) < 0)
|
|
||||||
err_sys("IP_ONESBCAST setsockopt error");
|
|
||||||
|
|
||||||
option = 0;
|
|
||||||
optlen = sizeof(option);
|
|
||||||
- if (getsockopt(sockfd, IPPROTO_IP, IP_ONESBCAST,
|
|
||||||
+ if (getsockopt(sockfd, level, IP_ONESBCAST,
|
|
||||||
&option, &optlen) < 0)
|
|
||||||
err_sys("IP_ONESBCAST getsockopt error");
|
|
||||||
if (option == 0)
|
|
||||||
@@ -175,7 +182,7 @@ sockopts(int sockfd, int doall)
|
|
||||||
if (inet_aton(joinip, &join.imr_multiaddr) == 0)
|
|
||||||
err_quit("invalid multicast address: %s", joinip);
|
|
||||||
join.imr_interface.s_addr = htonl(INADDR_ANY);
|
|
||||||
- if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
|
|
||||||
+ if (setsockopt(sockfd, level, IP_ADD_MEMBERSHIP,
|
|
||||||
&join, sizeof(join)) < 0)
|
|
||||||
err_sys("IP_ADD_MEMBERSHIP setsockopt error");
|
|
||||||
|
|
||||||
@@ -188,12 +195,12 @@ sockopts(int sockfd, int doall)
|
|
||||||
if (mcastttl) {
|
|
||||||
u_char ttl = mcastttl;
|
|
||||||
|
|
||||||
- if (setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_TTL,
|
|
||||||
+ if (setsockopt(sockfd, level, IP_MULTICAST_TTL,
|
|
||||||
&ttl, sizeof(ttl)) < 0)
|
|
||||||
err_sys("IP_MULTICAST_TTL setsockopt error");
|
|
||||||
|
|
||||||
optlen = sizeof(ttl);
|
|
||||||
- if (getsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_TTL,
|
|
||||||
+ if (getsockopt(sockfd, level, IP_MULTICAST_TTL,
|
|
||||||
&ttl, &optlen) < 0)
|
|
||||||
err_sys("IP_MULTICAST_TTL getsockopt error");
|
|
||||||
if (ttl != mcastttl)
|
|
||||||
@@ -288,7 +295,7 @@ sockopts(int sockfd, int doall)
|
|
||||||
|
|
||||||
if (verbose)
|
|
||||||
fprintf(stderr, "SO_RCVTIMEO: %ld.%06ld\n",
|
|
||||||
- timer.tv_sec, timer.tv_usec);
|
|
||||||
+ (long)timer.tv_sec, timer.tv_usec);
|
|
||||||
#else
|
|
||||||
fprintf(stderr, "warning: SO_RCVTIMEO not supported by host\n");
|
|
||||||
#endif
|
|
||||||
@@ -311,7 +318,7 @@ sockopts(int sockfd, int doall)
|
|
||||||
|
|
||||||
if (verbose)
|
|
||||||
fprintf(stderr, "SO_SNDTIMEO: %ld.%06ld\n",
|
|
||||||
- timer.tv_sec, timer.tv_usec);
|
|
||||||
+ (long)timer.tv_sec, timer.tv_usec);
|
|
||||||
#else
|
|
||||||
fprintf(stderr, "warning: SO_SNDTIMEO not supported by host\n");
|
|
||||||
#endif
|
|
||||||
@@ -320,13 +327,13 @@ sockopts(int sockfd, int doall)
|
|
||||||
if (recvdstaddr && udp) {
|
|
||||||
#ifdef IP_RECVDSTADDR
|
|
||||||
option = 1;
|
|
||||||
- if (setsockopt(sockfd, IPPROTO_IP, IP_RECVDSTADDR,
|
|
||||||
+ if (setsockopt(sockfd, level, IP_RECVDSTADDR,
|
|
||||||
&option, sizeof(option)) < 0)
|
|
||||||
err_sys("IP_RECVDSTADDR setsockopt error");
|
|
||||||
|
|
||||||
option = 0;
|
|
||||||
optlen = sizeof(option);
|
|
||||||
- if (getsockopt(sockfd, IPPROTO_IP, IP_RECVDSTADDR,
|
|
||||||
+ if (getsockopt(sockfd, level, IP_RECVDSTADDR,
|
|
||||||
&option, &optlen) < 0)
|
|
||||||
err_sys("IP_RECVDSTADDR getsockopt error");
|
|
||||||
if (option == 0)
|
|
|
@ -1,16 +0,0 @@
|
||||||
--- src/sourceroute.c.orig 2010-05-28 00:03:25 UTC
|
|
||||||
+++ src/sourceroute.c
|
|
||||||
@@ -88,10 +88,11 @@ sroute_set(int sockfd)
|
|
||||||
sroute_opt[1] = 3 + (sroute_cnt * 4); /* total length, incl. destination */
|
|
||||||
|
|
||||||
/* destination must be stored as final entry */
|
|
||||||
- bcopy(&servaddr.sin_addr, optr, sizeof(u_long));
|
|
||||||
+ bcopy(&servaddr4.sin_addr, optr, sizeof(u_long));
|
|
||||||
optr += sizeof(u_long);
|
|
||||||
if (verbose) {
|
|
||||||
- fprintf(stderr, "source route to %s\n", inet_ntoa(servaddr.sin_addr));
|
|
||||||
+ fprintf(stderr, "source route to %s\n",
|
|
||||||
+ inet_ntoa(servaddr4.sin_addr));
|
|
||||||
fprintf(stderr, "source route size %d bytes\n", sroute_opt[1]);
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,62 +0,0 @@
|
||||||
--- src/sourceudp.c.orig 2010-05-28 00:03:25 UTC
|
|
||||||
+++ src/sourceudp.c
|
|
||||||
@@ -29,28 +29,41 @@ source_udp(int sockfd) /* TODO: use send
|
|
||||||
if (connectudp) {
|
|
||||||
if ( (n = write(sockfd, wbuf, writelen)) != writelen) {
|
|
||||||
if (ignorewerr) {
|
|
||||||
- err_ret("write returned %d, expected %d", n, writelen);
|
|
||||||
- /* also call getsockopt() to clear so_error */
|
|
||||||
+ err_ret("write returned %d, expected %d",
|
|
||||||
+ n, writelen);
|
|
||||||
+ /* also call getsockopt() to clear so_error */
|
|
||||||
optlen = sizeof(option);
|
|
||||||
- if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR,
|
|
||||||
- &option, &optlen) < 0)
|
|
||||||
- err_sys("SO_ERROR getsockopt error");
|
|
||||||
- } else
|
|
||||||
- err_sys("write returned %d, expected %d", n, writelen);
|
|
||||||
+ if (getsockopt(sockfd, SOL_SOCKET,
|
|
||||||
+ SO_ERROR, &option, &optlen) < 0)
|
|
||||||
+ err_sys("SO_ERROR getsockopt error");
|
|
||||||
+ } else {
|
|
||||||
+ err_sys("write returned %d, expected %d",
|
|
||||||
+ n, writelen);
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
- if ( (n = sendto(sockfd, wbuf, writelen, 0,
|
|
||||||
- (struct sockaddr *) &servaddr,
|
|
||||||
- sizeof(struct sockaddr))) != writelen) {
|
|
||||||
- if (ignorewerr) {
|
|
||||||
- err_ret("sendto returned %d, expected %d", n, writelen);
|
|
||||||
- /* also call getsockopt() to clear so_error */
|
|
||||||
+ if (af_46 == AF_INET) {
|
|
||||||
+ n = sendto(sockfd, wbuf, writelen, 0,
|
|
||||||
+ (struct sockaddr *) &servaddr4,
|
|
||||||
+ sizeof(servaddr4));
|
|
||||||
+ } else {
|
|
||||||
+ n = sendto(sockfd, wbuf, writelen, 0,
|
|
||||||
+ (struct sockaddr *) &servaddr6,
|
|
||||||
+ sizeof(servaddr6));
|
|
||||||
+ }
|
|
||||||
+ if (n != writelen) {
|
|
||||||
+ if (ignorewerr) {
|
|
||||||
+ err_ret("sendto returned %d, expected %d",
|
|
||||||
+ n, writelen);
|
|
||||||
+ /* also call getsockopt() to clear so_error */
|
|
||||||
optlen = sizeof(option);
|
|
||||||
- if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR,
|
|
||||||
- &option, &optlen) < 0)
|
|
||||||
- err_sys("SO_ERROR getsockopt error");
|
|
||||||
- } else
|
|
||||||
- err_sys("sendto returned %d, expected %d", n, writelen);
|
|
||||||
+ if (getsockopt(sockfd, SOL_SOCKET,
|
|
||||||
+ SO_ERROR, &option, &optlen) < 0)
|
|
||||||
+ err_sys("SO_ERROR getsockopt error");
|
|
||||||
+ } else {
|
|
||||||
+ err_sys("sendto returned %d, expected %d",
|
|
||||||
+ n, writelen);
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,17 +1,21 @@
|
||||||
This is a standalone version of W. Richard Stevens' "sock" program,
|
In TCP/IP Illustrated Vol. 1, Richard Stevens used a program called
|
||||||
based on the code available for the UNIX Network Programming book.
|
"sock" to demonstrate the many properties of TCP/IP. This is a
|
||||||
|
standalone version, adapted and reworked by Christian Kreibich.
|
||||||
Adapted and reworked code for W. Richard Stevens' "sock" utility
|
|
||||||
by Christian Kreibich.
|
|
||||||
|
|
||||||
From the author: In TCP/IP Illustrated Vol. 1, Richard Stevens used
|
|
||||||
a program called "sock" to demonstrate the many properties of TCP/IP.
|
|
||||||
Unfortunately, the book only speaks about how to use the program but
|
|
||||||
does not point to a site for downloading its sources. While sock is
|
|
||||||
contained in the code package accompanying UNIX Network Programming,
|
|
||||||
this code is also getting dated.
|
|
||||||
|
|
||||||
The program can be used to generate TCP or UDP packets for testing
|
The program can be used to generate TCP or UDP packets for testing
|
||||||
various network features. It runs as either client or server.
|
various network features. It runs as either client or server.
|
||||||
|
|
||||||
WWW: http://www.icir.org/christian/sock.html
|
This FreeBSD port is built on top of the original 0.3.2 tarball from
|
||||||
|
2010, above, downloaded from the icir.org webpage.
|
||||||
|
|
||||||
|
Version 0.4.2 of sock supports IPv6, SCTP and those socket options:
|
||||||
|
- IPv6:
|
||||||
|
o hop limit
|
||||||
|
o multicast hop limit
|
||||||
|
o disable/enable header flow label
|
||||||
|
o header traffic class
|
||||||
|
o don't fragment
|
||||||
|
- IPv4:
|
||||||
|
o don't fragment
|
||||||
|
|
||||||
|
WWW: http://www-cs-students.stanford.edu/~sjac/sock_info.html
|
||||||
|
|
Loading…
Add table
Reference in a new issue