Module Name:    src
Committed By:   christos
Date:           Mon Jan  1 00:51:36 UTC 2018

Modified Files:
        src/share/man/man4: ip.4
        src/sys/netinet: in.h in_pcb.c in_pcb.h ip_input.c ip_output.c
        src/sys/sys: param.h

Log Message:
1) "#define ipi_spec_dst ipi_addr" in <netinet/in.h>
2) Change the IP_RECVPKTINFO option to control the generation of
   IP_PKTINFO control messages, the way it's done in Solaris.
3) Remove the superfluous IP_RECVPKTINFO control message.
4) Change the IP_PKTINFO option to do different things depending on
   the parameter it's supplied with:
   - If it's sizeof(int), assume it's being used as in Linux:
     - If it's non-zero, turn on the IP_RECVPKTINFO option.
     - If it's zero, turn off the IP_RECVPKTINFO option.
   - If it's sizeof(struct in_pktinfo), assume it's being used as in
     Solaris, to set a default for the source interface and/or
     source address for outgoing packets on the socket.
5) Return what Linux or Solaris compatible code expects, depending
   on data size, and just added a fallback to a Linux (and current NetBSD)
   compatible value if the size is unknown (as it is now), or,
   in the future, if the calling application specifies a receiving
   buffer that doesn't match either data item.

From: Tom Ivar Helbekkmo


To generate a diff of this commit:
cvs rdiff -u -r1.40 -r1.41 src/share/man/man4/ip.4
cvs rdiff -u -r1.101 -r1.102 src/sys/netinet/in.h
cvs rdiff -u -r1.180 -r1.181 src/sys/netinet/in_pcb.c
cvs rdiff -u -r1.64 -r1.65 src/sys/netinet/in_pcb.h
cvs rdiff -u -r1.363 -r1.364 src/sys/netinet/ip_input.c
cvs rdiff -u -r1.288 -r1.289 src/sys/netinet/ip_output.c
cvs rdiff -u -r1.554 -r1.555 src/sys/sys/param.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/share/man/man4/ip.4
diff -u src/share/man/man4/ip.4:1.40 src/share/man/man4/ip.4:1.41
--- src/share/man/man4/ip.4:1.40	Sun Aug 13 14:19:44 2017
+++ src/share/man/man4/ip.4	Sun Dec 31 19:51:36 2017
@@ -1,4 +1,4 @@
-.\"	$NetBSD: ip.4,v 1.40 2017/08/13 18:19:44 wiz Exp $
+.\"	$NetBSD: ip.4,v 1.41 2018/01/01 00:51:36 christos Exp $
 .\"
 .\" Copyright (c) 1983, 1991, 1993
 .\"	The Regents of the University of California.  All rights reserved.
@@ -29,7 +29,7 @@
 .\"
 .\"     @(#)ip.4	8.2 (Berkeley) 11/30/93
 .\"
-.Dd August 10, 2017
+.Dd December 31, 2017
 .Dt IP 4
 .Os
 .Sh NAME
@@ -96,8 +96,8 @@ setsockopt(s, IPPROTO_IP, IP_IPSEC_POLIC
 .Ed
 .Pp
 The
-.Dv IP_PKTINFO
-option can be used to turn on receiving of information about the source
+.Dv IP_RECVPKTINFO
+option can be used to turn on receiving of information about the destination
 address of the packet, and the interface index.
 The information is passed in a
 .Vt struct in_pktinfo
@@ -117,13 +117,24 @@ cmsg_type = IP_PKTINFO
 .Pp
 For
 .Xr sendmsg 2 ,
-the source address or output interface can be specified by adding
+the source address or output interface can be specified by adding an
 .Dv IP_PKTINFO
-to the control part of the message on a
+message to the control part of the message on a
 .Dv SOCK_DGRAM
 or
 .Dv SOCK_RAW
-socket.
+socket.  Setting ipi_ifindex will cause the primary address of that
+interface to be used; setting ipi_addr will directly choose that address.
+The IP_PKTINFO cmsghdr structure from a received message may be used
+unchanged, in which case the outgoing message will be sent from the
+address the incoming message was received on.
+.Pp
+Setting the
+.Dv IP_PKTINFO
+option on a socket, with the same
+.Vt struct in_pktinfo
+structure, will set the default source address to be used until set
+again, unless explicitly overridden on a per-packet basis, as above.
 .Pp
 The
 .Dv IP_PORTALGO
@@ -177,6 +188,18 @@ cmsg_level = IPPROTO_IP
 cmsg_type = IP_RECVDSTADDR
 .Ed
 .Pp
+For
+.Xr sendmsg 2 ,
+the source address can be specified by adding
+.Dv IP_SENDSRCADDR
+to the control part of the message on a
+.Dv SOCK_DGRAM
+or
+.Dv SOCK_RAW
+socket.  The IP_RECVDSTADDR cmsghdr structure from a received message
+may be used unchanged, in which case the outgoing message will be sent
+from the address the incoming message was received on.
+.Pp
 If the
 .Dv IP_RECVIF
 option is enabled on a
@@ -197,12 +220,6 @@ cmsg_level = IPPROTO_IP
 cmsg_type = IP_RECVIF
 .Ed
 .Pp
-The
-.Dv IP_RECVPKTINFO
-option is similar to the
-.Dv IP_PKTINFO
-one, only in this case the inbound information is returned.
-.Pp
 If the
 .Dv IP_RECVTTL
 option is enabled on a
@@ -452,6 +469,24 @@ An unknown socket option name was given;
 the IP option field was improperly formed; an option field was
 shorter than the minimum value or longer than the option buffer provided.
 .El
+.Sh COMPATIBILITY
+The
+.Dv IP_RECVPKTINFO
+option is used because it is directly compatible with Solaris, AIX, etc.,
+and the
+.Dv IP_PKTINFO
+option is intended to be used in their manner, to set the default source
+address for outgoing packets on a
+.Dv SOCK_DGRAM
+or
+.Dv SOCK_RAW
+socket.  For compatibility with Linux, however, if you attempt to set the
+.Dv IP_PKTINFO
+option, using an integer parameter as a boolean value, this will
+transparently manipulate the
+.Dv IP_RECVPKTINFO
+option instead.  Source code compatbility with both environments is thus
+maintained.
 .Sh SEE ALSO
 .Xr getsockopt 2 ,
 .Xr recv 2 ,

Index: src/sys/netinet/in.h
diff -u src/sys/netinet/in.h:1.101 src/sys/netinet/in.h:1.102
--- src/sys/netinet/in.h:1.101	Thu Aug 10 00:31:58 2017
+++ src/sys/netinet/in.h	Sun Dec 31 19:51:36 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: in.h,v 1.101 2017/08/10 04:31:58 ryo Exp $	*/
+/*	$NetBSD: in.h,v 1.102 2018/01/01 00:51:36 christos Exp $	*/
 
 /*
  * Copyright (c) 1982, 1986, 1990, 1993
@@ -289,8 +289,10 @@ struct ip_opts {
 #define	IP_IPSEC_POLICY		22   /* struct; get/set security policy */
 #define	IP_RECVTTL		23   /* bool; receive IP TTL w/dgram */
 #define	IP_MINTTL		24   /* minimum TTL for packet or drop */
-#define	IP_PKTINFO		25   /* int; send interface and src addr */
-#define	IP_RECVPKTINFO		26   /* int; send interface and dst addr */
+#define	IP_PKTINFO		25   /* struct; set default src if/addr */
+#define	IP_RECVPKTINFO		26   /* int; receive dst if/addr w/dgram */
+
+#define IP_SENDSRCADDR IP_RECVDSTADDR /* FreeBSD compatibility */
 
 /*
  * Information sent in the control message of a datagram socket for
@@ -301,6 +303,8 @@ struct in_pktinfo {
 	unsigned int ipi_ifindex;	/* interface index */
 };
 
+#define ipi_spec_dst ipi_addr	/* Solaris/Linux compatibility */
+
 /*
  * Defaults and limits for options
  */

Index: src/sys/netinet/in_pcb.c
diff -u src/sys/netinet/in_pcb.c:1.180 src/sys/netinet/in_pcb.c:1.181
--- src/sys/netinet/in_pcb.c:1.180	Thu Dec 14 23:03:46 2017
+++ src/sys/netinet/in_pcb.c	Sun Dec 31 19:51:36 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: in_pcb.c,v 1.180 2017/12/15 04:03:46 ozaki-r Exp $	*/
+/*	$NetBSD: in_pcb.c,v 1.181 2018/01/01 00:51:36 christos Exp $	*/
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -93,7 +93,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: in_pcb.c,v 1.180 2017/12/15 04:03:46 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: in_pcb.c,v 1.181 2018/01/01 00:51:36 christos Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -204,6 +204,7 @@ in_pcballoc(struct socket *so, void *v)
 	inp->inp_errormtu = -1;
 	inp->inp_portalgo = PORTALGO_DEFAULT;
 	inp->inp_bindportonsend = false;
+	inp->inp_prefsrcip.s_addr = INADDR_ANY;
 #if defined(IPSEC)
 	if (ipsec_enabled) {
 		int error = ipsec_init_pcbpolicy(so, &inp->inp_sp);

Index: src/sys/netinet/in_pcb.h
diff -u src/sys/netinet/in_pcb.h:1.64 src/sys/netinet/in_pcb.h:1.65
--- src/sys/netinet/in_pcb.h:1.64	Thu Aug 10 00:31:58 2017
+++ src/sys/netinet/in_pcb.h	Sun Dec 31 19:51:36 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: in_pcb.h,v 1.64 2017/08/10 04:31:58 ryo Exp $	*/
+/*	$NetBSD: in_pcb.h,v 1.65 2018/01/01 00:51:36 christos Exp $	*/
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -95,6 +95,7 @@ struct inpcb {
 	int	  inp_errormtu;		/* MTU of last xmit status = EMSGSIZE */
 	uint8_t	  inp_ip_minttl;
 	bool      inp_bindportonsend;
+	struct    in_addr inp_prefsrcip; /* preferred src IP when wild  */
 };
 
 #define	inp_faddr	inp_ip.ip_dst
@@ -121,11 +122,9 @@ struct inpcb {
 					 * Cancels INP_HDRINCL.
 					 */
 #define	INP_RECVTTL		0x0800	/* receive incoming IP TTL */
-#define	INP_PKTINFO		0x1000	/* receive dst packet info */
-#define	INP_RECVPKTINFO		0x2000	/* receive dst packet info */
+#define	INP_RECVPKTINFO		0x1000	/* receive IP dst if/addr */
 #define	INP_CONTROLOPTS		(INP_RECVOPTS|INP_RECVRETOPTS|INP_RECVDSTADDR|\
-				INP_RECVIF|INP_RECVTTL|INP_RECVPKTINFO|\
-				INP_PKTINFO)
+				INP_RECVIF|INP_RECVTTL|INP_RECVPKTINFO)
 
 #define	sotoinpcb(so)		((struct inpcb *)(so)->so_pcb)
 #define	inp_lock(inp)		solock((inp)->inp_socket)

Index: src/sys/netinet/ip_input.c
diff -u src/sys/netinet/ip_input.c:1.363 src/sys/netinet/ip_input.c:1.364
--- src/sys/netinet/ip_input.c:1.363	Fri Nov 24 09:03:25 2017
+++ src/sys/netinet/ip_input.c	Sun Dec 31 19:51:36 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: ip_input.c,v 1.363 2017/11/24 14:03:25 roy Exp $	*/
+/*	$NetBSD: ip_input.c,v 1.364 2018/01/01 00:51:36 christos Exp $	*/
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -91,7 +91,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.363 2017/11/24 14:03:25 roy Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.364 2018/01/01 00:51:36 christos Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -1533,15 +1533,6 @@ ip_savecontrol(struct inpcb *inp, struct
 
 	if (inpflags & INP_RECVPKTINFO) {
 		struct in_pktinfo ipi;
-		ipi.ipi_addr = ip->ip_src;
-		ipi.ipi_ifindex = ifp->if_index;
-		*mp = sbcreatecontrol(&ipi,
-		    sizeof(ipi), IP_RECVPKTINFO, IPPROTO_IP);
-		if (*mp)
-			mp = &(*mp)->m_next;
-	}
-	if (inpflags & INP_PKTINFO) {
-		struct in_pktinfo ipi;
 		ipi.ipi_addr = ip->ip_dst;
 		ipi.ipi_ifindex = ifp->if_index;
 		*mp = sbcreatecontrol(&ipi,

Index: src/sys/netinet/ip_output.c
diff -u src/sys/netinet/ip_output.c:1.288 src/sys/netinet/ip_output.c:1.289
--- src/sys/netinet/ip_output.c:1.288	Fri Dec 22 06:22:37 2017
+++ src/sys/netinet/ip_output.c	Sun Dec 31 19:51:36 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: ip_output.c,v 1.288 2017/12/22 11:22:37 ozaki-r Exp $	*/
+/*	$NetBSD: ip_output.c,v 1.289 2018/01/01 00:51:36 christos Exp $	*/
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -91,7 +91,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip_output.c,v 1.288 2017/12/22 11:22:37 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip_output.c,v 1.289 2018/01/01 00:51:36 christos Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -1081,6 +1081,7 @@ ip_ctloutput(int op, struct socket *so, 
 	struct ip *ip = &inp->inp_ip;
 	int inpflags = inp->inp_flags;
 	int optval = 0, error = 0;
+	struct in_pktinfo pktinfo;
 
 	KASSERT(solocked(so));
 
@@ -1103,7 +1104,6 @@ ip_ctloutput(int op, struct socket *so, 
 		case IP_TOS:
 		case IP_TTL:
 		case IP_MINTTL:
-		case IP_PKTINFO:
 		case IP_RECVOPTS:
 		case IP_RECVRETOPTS:
 		case IP_RECVDSTADDR:
@@ -1135,10 +1135,6 @@ ip_ctloutput(int op, struct socket *so, 
 	else \
 		inpflags &= ~bit;
 
-			case IP_PKTINFO:
-				OPTSET(INP_PKTINFO);
-				break;
-
 			case IP_RECVOPTS:
 				OPTSET(INP_RECVOPTS);
 				break;
@@ -1163,6 +1159,45 @@ ip_ctloutput(int op, struct socket *so, 
 				OPTSET(INP_RECVTTL);
 				break;
 			}
+			break;
+		case IP_PKTINFO:
+			error = sockopt_getint(sopt, &optval);
+			if (!error) {
+				/* Linux compatibility */
+				OPTSET(INP_RECVPKTINFO);
+				break;
+			}
+			error = sockopt_get(sopt, &pktinfo, sizeof(pktinfo));
+			if (error)
+				break;
+
+			if (pktinfo.ipi_ifindex == 0) {
+				inp->inp_prefsrcip = pktinfo.ipi_addr;
+				break;
+			}
+
+			/* Solaris compatibility */
+			struct ifnet *ifp;
+			struct in_ifaddr *ia;
+			int s;
+
+			/* pick up primary address */
+			s = pserialize_read_enter();
+			ifp = if_byindex(pktinfo.ipi_ifindex);
+			if (ifp == NULL) {
+				pserialize_read_exit(s);
+				error = EADDRNOTAVAIL;
+				break;
+			}
+			ia = in_get_ia_from_ifp(ifp);
+			if (ia == NULL) {
+				pserialize_read_exit(s);
+				error = EADDRNOTAVAIL;
+				break;
+			}
+			inp->inp_prefsrcip = IA_SIN(ia)->sin_addr;
+			pserialize_read_exit(s);
+			break;
 		break;
 #undef OPTSET
 
@@ -1239,7 +1274,6 @@ ip_ctloutput(int op, struct socket *so, 
 			}
 			break;
 		}
-		case IP_PKTINFO:
 		case IP_TOS:
 		case IP_TTL:
 		case IP_MINTTL:
@@ -1269,10 +1303,6 @@ ip_ctloutput(int op, struct socket *so, 
 
 #define	OPTBIT(bit)	(inpflags & bit ? 1 : 0)
 
-			case IP_PKTINFO:
-				optval = OPTBIT(INP_PKTINFO);
-				break;
-
 			case IP_RECVOPTS:
 				optval = OPTBIT(INP_RECVOPTS);
 				break;
@@ -1300,6 +1330,35 @@ ip_ctloutput(int op, struct socket *so, 
 			error = sockopt_setint(sopt, optval);
 			break;
 
+		case IP_PKTINFO:
+			/* XXX these tests fail until size gets propagated */
+			/* It needs to be passed through from the caller */
+			switch (sopt->sopt_size) {
+			case sizeof(int):
+				/* Linux compatibility */
+				optval = OPTBIT(INP_RECVPKTINFO);
+				error = sockopt_setint(sopt, optval);
+				break;
+			case sizeof(struct in_pktinfo):
+				/* Solaris compatibility */
+				pktinfo.ipi_ifindex = 0;
+				pktinfo.ipi_addr = inp->inp_prefsrcip;
+				error = sockopt_set(sopt, &pktinfo,
+				    sizeof(pktinfo));
+				break;
+			default:
+				/*
+				 * While size is stuck at 0, and, later, if
+				 * the caller doesn't use an exactly sized
+				 * recipient for the data, default to Linux
+				 * compatibility
+				 */
+				optval = OPTBIT(INP_RECVPKTINFO);
+				error = sockopt_setint(sopt, optval);
+				break;
+			}
+			break;
+
 #if 0	/* defined(IPSEC) */
 		case IP_IPSEC_POLICY:
 		{
@@ -1416,11 +1475,14 @@ ip_setpktopts(struct mbuf *control, stru
     struct inpcb *inp, kauth_cred_t cred)
 {
 	struct cmsghdr *cm;
-	struct in_pktinfo *pktinfo;
+	struct in_pktinfo pktinfo;
 	int error;
 
 	pktopts->ippo_imo = inp->inp_moptions;
-	sockaddr_in_init(&pktopts->ippo_laddr, &inp->inp_laddr, 0);
+
+	struct in_addr *ia = in_nullhost(inp->inp_prefsrcip) ? &inp->inp_laddr :
+	    &inp->inp_prefsrcip;
+	sockaddr_in_init(&pktopts->ippo_laddr, ia, 0);
 
 	if (control == NULL)
 		return 0;
@@ -1446,13 +1508,23 @@ ip_setpktopts(struct mbuf *control, stru
 
 		switch (cm->cmsg_type) {
 		case IP_PKTINFO:
-			if (cm->cmsg_len != CMSG_LEN(sizeof(struct in_pktinfo)))
+			if (cm->cmsg_len != CMSG_LEN(sizeof(pktinfo)))
 				return EINVAL;
-
-			pktinfo = (struct in_pktinfo *)CMSG_DATA(cm);
-			error = ip_pktinfo_prepare(pktinfo, pktopts, flags,
+			memcpy(&pktinfo, CMSG_DATA(cm), sizeof(pktinfo));
+			error = ip_pktinfo_prepare(&pktinfo, pktopts, flags,
 			    cred);
-			if (error != 0)
+			if (error)
+				return error;
+			break;
+		case IP_SENDSRCADDR: /* FreeBSD compatibility */
+			if (cm->cmsg_len != CMSG_LEN(sizeof(struct in_addr)))
+				return EINVAL;
+			pktinfo.ipi_ifindex = 0;
+			pktinfo.ipi_addr =
+			    ((struct in_pktinfo *)CMSG_DATA(cm))->ipi_addr;
+			error = ip_pktinfo_prepare(&pktinfo, pktopts, flags,
+			    cred);
+			if (error)
 				return error;
 			break;
 		default:

Index: src/sys/sys/param.h
diff -u src/sys/sys/param.h:1.554 src/sys/sys/param.h:1.555
--- src/sys/sys/param.h:1.554	Wed Dec  6 03:25:47 2017
+++ src/sys/sys/param.h	Sun Dec 31 19:51:36 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: param.h,v 1.554 2017/12/06 08:25:47 knakahara Exp $	*/
+/*	$NetBSD: param.h,v 1.555 2018/01/01 00:51:36 christos Exp $	*/
 
 /*-
  * Copyright (c) 1982, 1986, 1989, 1993
@@ -67,7 +67,7 @@
  *	2.99.9		(299000900)
  */
 
-#define	__NetBSD_Version__	899000900	/* NetBSD 8.99.9 */
+#define	__NetBSD_Version__	899001000	/* NetBSD 8.99.10 */
 
 #define __NetBSD_Prereq__(M,m,p) (((((M) * 100000000) + \
     (m) * 1000000) + (p) * 100) <= __NetBSD_Version__)

Reply via email to