Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 24 May 2016 16:59:54 +0000 (UTC)
From:      Steve Wills <swills@FreeBSD.org>
To:        ports-committers@freebsd.org, svn-ports-all@freebsd.org, svn-ports-head@freebsd.org
Subject:   svn commit: r415801 - in head/net: . sock sock/files
Message-ID:  <201605241659.u4OGxsC4057181@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: swills
Date: Tue May 24 16:59:54 2016
New Revision: 415801
URL: https://svnweb.freebsd.org/changeset/ports/415801

Log:
  net/sock: create port
  
  This is a standalone version of W. Richard Stevens' "sock" program,
  based on the code available for the UNIX Network Programming book.
  
  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
  various network features.  It runs as either client or server.
  
  WWW: http://www.icir.org/christian/sock.html
  
  PR:		206345
  Submitted by:	Steve Jacobson <sjac998@yahoo.com> (with slight modification)

Added:
  head/net/sock/
  head/net/sock/Makefile   (contents, props changed)
  head/net/sock/distinfo   (contents, props changed)
  head/net/sock/files/
  head/net/sock/files/patch-src__cliopen.c   (contents, props changed)
  head/net/sock/files/patch-src__loopudp.c   (contents, props changed)
  head/net/sock/files/patch-src__main.c   (contents, props changed)
  head/net/sock/files/patch-src__multicast.c   (contents, props changed)
  head/net/sock/files/patch-src__servopen.c   (contents, props changed)
  head/net/sock/files/patch-src__sock.h   (contents, props changed)
  head/net/sock/files/patch-src__sockopts.c   (contents, props changed)
  head/net/sock/files/patch-src__sourceroute.c   (contents, props changed)
  head/net/sock/files/patch-src__sourceudp.c   (contents, props changed)
  head/net/sock/pkg-descr   (contents, props changed)
Modified:
  head/net/Makefile

Modified: head/net/Makefile
==============================================================================
--- head/net/Makefile	Tue May 24 16:15:40 2016	(r415800)
+++ head/net/Makefile	Tue May 24 16:59:54 2016	(r415801)
@@ -1226,6 +1226,7 @@
     SUBDIR += sntop
     SUBDIR += sobby
     SUBDIR += socat
+    SUBDIR += sock
     SUBDIR += socketbind
     SUBDIR += socketpipe
     SUBDIR += socketw

Added: head/net/sock/Makefile
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/net/sock/Makefile	Tue May 24 16:59:54 2016	(r415801)
@@ -0,0 +1,16 @@
+# Created by: Steve Jacobson <sjac@cs.stanford.edu>
+# $FreeBSD$
+
+PORTNAME=	sock
+PORTVERSION=	0.3.2
+CATEGORIES=	net
+MASTER_SITES=	http://www.icir.org/christian/downloads/
+
+MAINTAINER=	sjac@cs.stanford.edu
+COMMENT=	W. Richard Stevens' sock program
+
+HAS_CONFIGURE=	yes
+
+PLIST_FILES=	bin/sock
+
+.include <bsd.port.mk>

Added: head/net/sock/distinfo
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/net/sock/distinfo	Tue May 24 16:59:54 2016	(r415801)
@@ -0,0 +1,2 @@
+SHA256 (sock-0.3.2.tar.gz) = 4ddc33767900e7cd0a4cc0f4d808638d7cfcb746c23e12274c8eba0622eee2eb
+SIZE (sock-0.3.2.tar.gz) = 113640

Added: head/net/sock/files/patch-src__cliopen.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/net/sock/files/patch-src__cliopen.c	Tue May 24 16:59:54 2016	(r415801)
@@ -0,0 +1,264 @@
+--- 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() */

Added: head/net/sock/files/patch-src__loopudp.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/net/sock/files/patch-src__loopudp.c	Tue May 24 16:59:54 2016	(r415801)
@@ -0,0 +1,261 @@
+--- 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);
+ 				}

Added: head/net/sock/files/patch-src__main.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/net/sock/files/patch-src__main.c	Tue May 24 16:59:54 2016	(r415801)
@@ -0,0 +1,60 @@
+--- 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)

Added: head/net/sock/files/patch-src__multicast.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/net/sock/files/patch-src__multicast.c	Tue May 24 16:59:54 2016	(r415801)
@@ -0,0 +1,111 @@
+--- 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 */
+ }

Added: head/net/sock/files/patch-src__servopen.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/net/sock/files/patch-src__servopen.c	Tue May 24 16:59:54 2016	(r415801)
@@ -0,0 +1,282 @@
+--- 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));

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201605241659.u4OGxsC4057181>