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
This commit is contained in:
parent
fe1f2b747b
commit
645664bc7b
|
@ -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_POLICY, buf, ipsec_get_policylen(buf));
|
|||
.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; or
|
|||
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 ,
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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"
|
||||
|
@ -1532,15 +1532,6 @@ ip_savecontrol(struct inpcb *inp, struct mbuf **mp, struct ip *ip,
|
|||
}
|
||||
|
||||
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;
|
||||
|
|
|
@ -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 sockopt *sopt)
|
|||
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, struct sockopt *sopt)
|
|||
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, struct sockopt *sopt)
|
|||
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, struct sockopt *sopt)
|
|||
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, struct sockopt *sopt)
|
|||
}
|
||||
break;
|
||||
}
|
||||
case IP_PKTINFO:
|
||||
case IP_TOS:
|
||||
case IP_TTL:
|
||||
case IP_MINTTL:
|
||||
|
@ -1269,10 +1303,6 @@ ip_ctloutput(int op, struct socket *so, struct sockopt *sopt)
|
|||
|
||||
#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, struct sockopt *sopt)
|
|||
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, struct ip_pktopts *pktopts, int *flags,
|
|||
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, struct ip_pktopts *pktopts, int *flags,
|
|||
|
||||
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:
|
||||
|
|
|
@ -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__)
|
||||
|
|
Loading…
Reference in New Issue