aboutsummaryrefslogtreecommitdiff
path: root/sys/netinet/raw_ip.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet/raw_ip.c')
-rw-r--r--sys/netinet/raw_ip.c38
1 files changed, 27 insertions, 11 deletions
diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c
index a6bef1c7e275..66070faf97e9 100644
--- a/sys/netinet/raw_ip.c
+++ b/sys/netinet/raw_ip.c
@@ -30,7 +30,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
#include "opt_inet.h"
#include "opt_inet6.h"
#include "opt_ipsec.h"
@@ -50,6 +49,7 @@
#include <sys/signalvar.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
+#include <sys/stdarg.h>
#include <sys/sx.h>
#include <sys/sysctl.h>
#include <sys/systm.h>
@@ -75,7 +75,6 @@
#include <netipsec/ipsec_support.h>
-#include <machine/stdarg.h>
#include <security/mac/mac_framework.h>
extern ipproto_input_t *ip_protox[];
@@ -128,6 +127,12 @@ int (*ip_rsvp_vif)(struct socket *, struct sockopt *);
void (*ip_rsvp_force_done)(struct socket *);
#endif /* INET */
+#define V_rip_bind_all_fibs VNET(rip_bind_all_fibs)
+VNET_DEFINE(int, rip_bind_all_fibs) = 1;
+SYSCTL_INT(_net_inet_raw, OID_AUTO, bind_all_fibs, CTLFLAG_VNET | CTLFLAG_RDTUN,
+ &VNET_NAME(rip_bind_all_fibs), 0,
+ "Bound sockets receive traffic from all FIBs");
+
u_long rip_sendspace = 9216;
SYSCTL_ULONG(_net_inet_raw, OID_AUTO, maxdgram, CTLFLAG_RW,
&rip_sendspace, 0, "Maximum outgoing raw IP datagram size");
@@ -302,7 +307,9 @@ rip_input(struct mbuf **mp, int *offp, int proto)
struct mbuf *m = *mp;
struct inpcb *inp;
struct sockaddr_in ripsrc;
- int appended;
+ int appended, fib;
+
+ M_ASSERTPKTHDR(m);
*mp = NULL;
appended = 0;
@@ -312,6 +319,7 @@ rip_input(struct mbuf **mp, int *offp, int proto)
ripsrc.sin_family = AF_INET;
ripsrc.sin_addr = ctx.ip->ip_src;
+ fib = M_GETFIB(m);
ifp = m->m_pkthdr.rcvif;
inpi.hash = INP_PCBHASH_RAW(proto, ctx.ip->ip_src.s_addr,
@@ -326,6 +334,12 @@ rip_input(struct mbuf **mp, int *offp, int proto)
*/
continue;
}
+ if (V_rip_bind_all_fibs == 0 && fib != inp->inp_inc.inc_fibnum)
+ /*
+ * Sockets bound to a specific FIB can only receive
+ * packets from that FIB.
+ */
+ continue;
appended += rip_append(inp, ctx.ip, m, &ripsrc);
}
@@ -343,6 +357,9 @@ rip_input(struct mbuf **mp, int *offp, int proto)
* and fall through into normal filter path if so.
*/
continue;
+ if (V_rip_bind_all_fibs == 0 && fib != inp->inp_inc.inc_fibnum)
+ continue;
+
/*
* If this raw socket has multicast state, and we
* have received a multicast, check if this socket
@@ -584,7 +601,7 @@ rip_send(struct socket *so, int pruflags, struct mbuf *m, struct sockaddr *nam,
* but we got this limitation from the beginning of history.
*/
if (ip->ip_id == 0)
- ip_fillid(ip);
+ ip_fillid(ip, V_ip_random_id);
/*
* XXX prevent ip_output from overwriting header fields.
@@ -625,8 +642,6 @@ rip_send(struct socket *so, int pruflags, struct mbuf *m, struct sockaddr *nam,
*
* When adding new socket options here, make sure to add access control
* checks here as necessary.
- *
- * XXX-BZ inp locking?
*/
int
rip_ctloutput(struct socket *so, struct sockopt *sopt)
@@ -635,11 +650,10 @@ rip_ctloutput(struct socket *so, struct sockopt *sopt)
int error, optval;
if (sopt->sopt_level != IPPROTO_IP) {
- if ((sopt->sopt_level == SOL_SOCKET) &&
- (sopt->sopt_name == SO_SETFIB)) {
- inp->inp_inc.inc_fibnum = so->so_fibnum;
- return (0);
- }
+ if (sopt->sopt_dir == SOPT_SET &&
+ sopt->sopt_level == SOL_SOCKET &&
+ sopt->sopt_name == SO_SETFIB)
+ return (ip_ctloutput(so, sopt));
return (EINVAL);
}
@@ -707,10 +721,12 @@ rip_ctloutput(struct socket *so, struct sockopt *sopt)
sizeof optval);
if (error)
break;
+ INP_WLOCK(inp);
if (optval)
inp->inp_flags |= INP_HDRINCL;
else
inp->inp_flags &= ~INP_HDRINCL;
+ INP_WUNLOCK(inp);
break;
case IP_FW3: /* generic ipfw v.3 functions */