Module Name: src
Committed By: ozaki-r
Date: Fri Jun 10 13:31:45 UTC 2016
Modified Files:
src/sys/altq: altq_cdnr.c
src/sys/dev/pci: if_lmc.c
src/sys/dist/pf/net: if_pfsync.c
src/sys/external/bsd/ipf/netinet: ip_compat.h
src/sys/kern: uipc_mbuf.c
src/sys/net: bpf.c if.c if.h if_bridge.c if_mpls.c if_pppoe.c if_stf.c
src/sys/netatalk: ddp_input.c
src/sys/netinet: if_arp.c igmp.c in_gif.c ip_carp.c ip_flow.c ip_icmp.c
ip_input.c sctp_input.c sctp_output.c tcp_input.c udp_usrreq.c
src/sys/netinet6: icmp6.c in6_gif.c ip6_forward.c ip6_input.c
ip6_mroute.c ip6_var.h mld6.c nd6_nbr.c nd6_rtr.c raw_ip6.c
sctp6_usrreq.c udp6_output.c udp6_usrreq.c
src/sys/netipsec: ipsec_input.c key_debug.c xform_ipip.c
src/sys/netmpls: mpls_ttl.c
src/sys/netnatm: natm.c
src/sys/sys: mbuf.h
Log Message:
Avoid storing a pointer of an interface in a mbuf
Having a pointer of an interface in a mbuf isn't safe if we remove big
kernel locks; an interface object (ifnet) can be destroyed anytime in any
packet processing and accessing such object via a pointer is racy. Instead
we have to get an object from the interface collection (ifindex2ifnet) via
an interface index (if_index) that is stored to a mbuf instead of an
pointer.
The change provides two APIs: m_{get,put}_rcvif_psref that use psref(9)
for sleep-able critical sections and m_{get,put}_rcvif that use
pserialize(9) for other critical sections. The change also adds another
API called m_get_rcvif_NOMPSAFE, that is NOT MP-safe and for transition
moratorium, i.e., it is intended to be used for places where are not
planned to be MP-ified soon.
The change adds some overhead due to psref to performance sensitive paths,
however the overhead is not serious, 2% down at worst.
Proposed on tech-kern and tech-net.
To generate a diff of this commit:
cvs rdiff -u -r1.20 -r1.21 src/sys/altq/altq_cdnr.c
cvs rdiff -u -r1.60 -r1.61 src/sys/dev/pci/if_lmc.c
cvs rdiff -u -r1.13 -r1.14 src/sys/dist/pf/net/if_pfsync.c
cvs rdiff -u -r1.9 -r1.10 src/sys/external/bsd/ipf/netinet/ip_compat.h
cvs rdiff -u -r1.166 -r1.167 src/sys/kern/uipc_mbuf.c
cvs rdiff -u -r1.197 -r1.198 src/sys/net/bpf.c
cvs rdiff -u -r1.337 -r1.338 src/sys/net/if.c
cvs rdiff -u -r1.206 -r1.207 src/sys/net/if.h
cvs rdiff -u -r1.124 -r1.125 src/sys/net/if_bridge.c
cvs rdiff -u -r1.22 -r1.23 src/sys/net/if_mpls.c
cvs rdiff -u -r1.107 -r1.108 src/sys/net/if_pppoe.c
cvs rdiff -u -r1.89 -r1.90 src/sys/net/if_stf.c
cvs rdiff -u -r1.26 -r1.27 src/sys/netatalk/ddp_input.c
cvs rdiff -u -r1.210 -r1.211 src/sys/netinet/if_arp.c
cvs rdiff -u -r1.57 -r1.58 src/sys/netinet/igmp.c
cvs rdiff -u -r1.75 -r1.76 src/sys/netinet/in_gif.c
cvs rdiff -u -r1.66 -r1.67 src/sys/netinet/ip_carp.c \
src/sys/netinet/ip_flow.c
cvs rdiff -u -r1.146 -r1.147 src/sys/netinet/ip_icmp.c
cvs rdiff -u -r1.328 -r1.329 src/sys/netinet/ip_input.c
cvs rdiff -u -r1.2 -r1.3 src/sys/netinet/sctp_input.c
cvs rdiff -u -r1.5 -r1.6 src/sys/netinet/sctp_output.c
cvs rdiff -u -r1.346 -r1.347 src/sys/netinet/tcp_input.c
cvs rdiff -u -r1.225 -r1.226 src/sys/netinet/udp_usrreq.c
cvs rdiff -u -r1.187 -r1.188 src/sys/netinet6/icmp6.c
cvs rdiff -u -r1.73 -r1.74 src/sys/netinet6/in6_gif.c
cvs rdiff -u -r1.78 -r1.79 src/sys/netinet6/ip6_forward.c
cvs rdiff -u -r1.159 -r1.160 src/sys/netinet6/ip6_input.c
cvs rdiff -u -r1.109 -r1.110 src/sys/netinet6/ip6_mroute.c
cvs rdiff -u -r1.64 -r1.65 src/sys/netinet6/ip6_var.h
cvs rdiff -u -r1.65 -r1.66 src/sys/netinet6/mld6.c
cvs rdiff -u -r1.118 -r1.119 src/sys/netinet6/nd6_nbr.c
cvs rdiff -u -r1.110 -r1.111 src/sys/netinet6/nd6_rtr.c
cvs rdiff -u -r1.143 -r1.144 src/sys/netinet6/raw_ip6.c
cvs rdiff -u -r1.4 -r1.5 src/sys/netinet6/sctp6_usrreq.c
cvs rdiff -u -r1.50 -r1.51 src/sys/netinet6/udp6_output.c
cvs rdiff -u -r1.122 -r1.123 src/sys/netinet6/udp6_usrreq.c
cvs rdiff -u -r1.35 -r1.36 src/sys/netipsec/ipsec_input.c
cvs rdiff -u -r1.12 -r1.13 src/sys/netipsec/key_debug.c
cvs rdiff -u -r1.38 -r1.39 src/sys/netipsec/xform_ipip.c
cvs rdiff -u -r1.7 -r1.8 src/sys/netmpls/mpls_ttl.c
cvs rdiff -u -r1.51 -r1.52 src/sys/netnatm/natm.c
cvs rdiff -u -r1.163 -r1.164 src/sys/sys/mbuf.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/altq/altq_cdnr.c
diff -u src/sys/altq/altq_cdnr.c:1.20 src/sys/altq/altq_cdnr.c:1.21
--- src/sys/altq/altq_cdnr.c:1.20 Sat Nov 19 22:51:18 2011
+++ src/sys/altq/altq_cdnr.c Fri Jun 10 13:31:43 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: altq_cdnr.c,v 1.20 2011/11/19 22:51:18 tls Exp $ */
+/* $NetBSD: altq_cdnr.c,v 1.21 2016/06/10 13:31:43 ozaki-r Exp $ */
/* $KAME: altq_cdnr.c,v 1.15 2005/04/13 03:44:24 suz Exp $ */
/*
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: altq_cdnr.c,v 1.20 2011/11/19 22:51:18 tls Exp $");
+__KERNEL_RCSID(0, "$NetBSD: altq_cdnr.c,v 1.21 2016/06/10 13:31:43 ozaki-r Exp $");
#ifdef _KERNEL_OPT
#include "opt_altq.h"
@@ -139,7 +139,7 @@ altq_cdnr_input(struct mbuf *m, int af)
struct cdnr_block *cb;
struct cdnr_pktinfo pktinfo;
- ifp = m->m_pkthdr.rcvif;
+ ifp = m_get_rcvif_NOMPSAFE(m);
if (!ALTQ_IS_CNDTNING(&ifp->if_snd))
/* traffic conditioner is not enabled on this interface */
return (1);
Index: src/sys/dev/pci/if_lmc.c
diff -u src/sys/dev/pci/if_lmc.c:1.60 src/sys/dev/pci/if_lmc.c:1.61
--- src/sys/dev/pci/if_lmc.c:1.60 Fri Jun 10 13:27:14 2016
+++ src/sys/dev/pci/if_lmc.c Fri Jun 10 13:31:43 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: if_lmc.c,v 1.60 2016/06/10 13:27:14 ozaki-r Exp $ */
+/* $NetBSD: if_lmc.c,v 1.61 2016/06/10 13:31:43 ozaki-r Exp $ */
/*-
* Copyright (c) 2002-2006 David Boggs. <[email protected]>
@@ -74,7 +74,7 @@
*/
# include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_lmc.c,v 1.60 2016/06/10 13:27:14 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_lmc.c,v 1.61 2016/06/10 13:31:43 ozaki-r Exp $");
# include <sys/param.h> /* OS version */
# include "opt_inet.h" /* INET6, INET */
# include "opt_altq_enabled.h" /* ALTQ */
@@ -4279,7 +4279,7 @@ rxintr_cleanup(softc_t *sc)
MGETHDR(new_mbuf, M_DONTWAIT, MT_DATA);
if (new_mbuf)
{
- m_set_rcvif(new_mbuf, first_mbuf->m_pkthdr.rcvif);
+ m_copy_rcvif(new_mbuf, first_mbuf);
new_mbuf->m_pkthdr.len = first_mbuf->m_pkthdr.len;
new_mbuf->m_len = first_mbuf->m_len;
memcpy(new_mbuf->m_data, first_mbuf->m_data,
Index: src/sys/dist/pf/net/if_pfsync.c
diff -u src/sys/dist/pf/net/if_pfsync.c:1.13 src/sys/dist/pf/net/if_pfsync.c:1.14
--- src/sys/dist/pf/net/if_pfsync.c:1.13 Fri Jun 10 13:27:15 2016
+++ src/sys/dist/pf/net/if_pfsync.c Fri Jun 10 13:31:44 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: if_pfsync.c,v 1.13 2016/06/10 13:27:15 ozaki-r Exp $ */
+/* $NetBSD: if_pfsync.c,v 1.14 2016/06/10 13:31:44 ozaki-r Exp $ */
/* $OpenBSD: if_pfsync.c,v 1.83 2007/06/26 14:44:12 mcbride Exp $ */
/*
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_pfsync.c,v 1.13 2016/06/10 13:27:15 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_pfsync.c,v 1.14 2016/06/10 13:31:44 ozaki-r Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -374,7 +374,7 @@ pfsync_input(struct mbuf *m, ...)
goto done;
/* verify that the packet came in on the right interface */
- if (sc->sc_sync_ifp != m->m_pkthdr.rcvif) {
+ if (sc->sc_sync_ifp->if_index != m->m_pkthdr.rcvif_index) {
PFSYNC_STATINC(PFSYNC_STAT_BADIF);
goto done;
}
Index: src/sys/external/bsd/ipf/netinet/ip_compat.h
diff -u src/sys/external/bsd/ipf/netinet/ip_compat.h:1.9 src/sys/external/bsd/ipf/netinet/ip_compat.h:1.10
--- src/sys/external/bsd/ipf/netinet/ip_compat.h:1.9 Fri Jun 10 13:27:15 2016
+++ src/sys/external/bsd/ipf/netinet/ip_compat.h Fri Jun 10 13:31:44 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: ip_compat.h,v 1.9 2016/06/10 13:27:15 ozaki-r Exp $ */
+/* $NetBSD: ip_compat.h,v 1.10 2016/06/10 13:31:44 ozaki-r Exp $ */
/*
* Copyright (C) 2012 by Darren Reed.
@@ -1964,8 +1964,7 @@ MALLOC_DECLARE(M_IPFILTER);
if (_o->m_flags & M_PKTHDR) { \
(m)->m_pkthdr.len += \
_o->m_pkthdr.len; \
- m_set_rcvif((m), \
- _o->m_pkthdr.rcvif); \
+ m_copy_rcvif((m), _o); \
} \
} while (0)
# endif
Index: src/sys/kern/uipc_mbuf.c
diff -u src/sys/kern/uipc_mbuf.c:1.166 src/sys/kern/uipc_mbuf.c:1.167
--- src/sys/kern/uipc_mbuf.c:1.166 Fri Jun 10 13:27:15 2016
+++ src/sys/kern/uipc_mbuf.c Fri Jun 10 13:31:44 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: uipc_mbuf.c,v 1.166 2016/06/10 13:27:15 ozaki-r Exp $ */
+/* $NetBSD: uipc_mbuf.c,v 1.167 2016/06/10 13:31:44 ozaki-r Exp $ */
/*-
* Copyright (c) 1999, 2001 The NetBSD Foundation, Inc.
@@ -62,7 +62,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uipc_mbuf.c,v 1.166 2016/06/10 13:27:15 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uipc_mbuf.c,v 1.167 2016/06/10 13:31:44 ozaki-r Exp $");
#ifdef _KERNEL_OPT
#include "opt_mbuftrace.h"
@@ -1171,7 +1171,7 @@ m_split0(struct mbuf *m0, int len0, int
if (n == NULL)
return NULL;
MCLAIM(n, m0->m_owner);
- m_set_rcvif(n, m0->m_pkthdr.rcvif);
+ m_copy_rcvif(n, m0);
n->m_pkthdr.len = m0->m_pkthdr.len - len0;
len_save = m0->m_pkthdr.len;
m0->m_pkthdr.len = len0;
@@ -1783,7 +1783,7 @@ nextchain:
snprintb(buf, sizeof(buf), M_CSUM_BITS, m->m_pkthdr.csum_flags);
(*pr)(" pktlen=%d, rcvif=%p, csum_flags=0x%s, csum_data=0x%"
PRIx32 ", segsz=%u\n",
- m->m_pkthdr.len, m->m_pkthdr.rcvif,
+ m->m_pkthdr.len, m_get_rcvif_NOMPSAFE(m),
buf, m->m_pkthdr.csum_data, m->m_pkthdr.segsz);
}
if ((m->m_flags & M_EXT)) {
Index: src/sys/net/bpf.c
diff -u src/sys/net/bpf.c:1.197 src/sys/net/bpf.c:1.198
--- src/sys/net/bpf.c:1.197 Fri Jun 10 13:27:15 2016
+++ src/sys/net/bpf.c Fri Jun 10 13:31:44 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: bpf.c,v 1.197 2016/06/10 13:27:15 ozaki-r Exp $ */
+/* $NetBSD: bpf.c,v 1.198 2016/06/10 13:31:44 ozaki-r Exp $ */
/*
* Copyright (c) 1990, 1991, 1993
@@ -39,7 +39,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: bpf.c,v 1.197 2016/06/10 13:27:15 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: bpf.c,v 1.198 2016/06/10 13:31:44 ozaki-r Exp $");
#if defined(_KERNEL_OPT)
#include "opt_bpf.h"
@@ -1469,7 +1469,7 @@ _bpf_mtap2(struct bpf_if *bp, void *data
struct mbuf mb;
/* Skip outgoing duplicate packets. */
- if ((m->m_flags & M_PROMISC) != 0 && m->m_pkthdr.rcvif == NULL) {
+ if ((m->m_flags & M_PROMISC) != 0 && m->m_pkthdr.rcvif_index == 0) {
m->m_flags &= ~M_PROMISC;
return;
}
@@ -1486,7 +1486,7 @@ _bpf_mtap2(struct bpf_if *bp, void *data
mb.m_data = data;
mb.m_len = dlen;
- bpf_deliver(bp, bpf_mcpy, &mb, pktlen, 0, m->m_pkthdr.rcvif != NULL);
+ bpf_deliver(bp, bpf_mcpy, &mb, pktlen, 0, m->m_pkthdr.rcvif_index != 0);
}
/*
@@ -1500,7 +1500,7 @@ _bpf_mtap(struct bpf_if *bp, struct mbuf
void *marg;
/* Skip outgoing duplicate packets. */
- if ((m->m_flags & M_PROMISC) != 0 && m->m_pkthdr.rcvif == NULL) {
+ if ((m->m_flags & M_PROMISC) != 0 && m->m_pkthdr.rcvif_index == 0) {
m->m_flags &= ~M_PROMISC;
return;
}
@@ -1517,7 +1517,7 @@ _bpf_mtap(struct bpf_if *bp, struct mbuf
buflen = 0;
}
- bpf_deliver(bp, cpfn, marg, pktlen, buflen, m->m_pkthdr.rcvif != NULL);
+ bpf_deliver(bp, cpfn, marg, pktlen, buflen, m->m_pkthdr.rcvif_index != 0);
}
/*
Index: src/sys/net/if.c
diff -u src/sys/net/if.c:1.337 src/sys/net/if.c:1.338
--- src/sys/net/if.c:1.337 Tue May 31 04:05:01 2016
+++ src/sys/net/if.c Fri Jun 10 13:31:44 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: if.c,v 1.337 2016/05/31 04:05:01 ozaki-r Exp $ */
+/* $NetBSD: if.c,v 1.338 2016/06/10 13:31:44 ozaki-r Exp $ */
/*-
* Copyright (c) 1999, 2000, 2001, 2008 The NetBSD Foundation, Inc.
@@ -90,7 +90,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.337 2016/05/31 04:05:01 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.338 2016/06/10 13:31:44 ozaki-r Exp $");
#if defined(_KERNEL_OPT)
#include "opt_inet.h"
@@ -1245,7 +1245,7 @@ if_detach_queues(struct ifnet *ifp, stru
KASSERT((m->m_flags & M_PKTHDR) != 0);
next = m->m_nextpkt;
- if (m->m_pkthdr.rcvif != ifp) {
+ if (m->m_pkthdr.rcvif_index != ifp->if_index) {
prev = m;
continue;
}
@@ -2223,6 +2223,26 @@ if_get_byindex(u_int idx, struct psref *
return ifp;
}
+/*
+ * XXX unsafe
+ */
+void
+if_acquire_unsafe(struct ifnet *ifp, struct psref *psref)
+{
+
+ KASSERT(ifp->if_index != 0);
+ KASSERT(if_byindex(ifp->if_index) != NULL);
+ psref_acquire(psref, &ifp->if_psref, ifnet_psref_class);
+}
+
+bool
+if_held(struct ifnet *ifp)
+{
+
+ return psref_held(&ifp->if_psref, ifnet_psref_class);
+}
+
+
/* common */
int
ifioctl_common(struct ifnet *ifp, u_long cmd, void *data)
Index: src/sys/net/if.h
diff -u src/sys/net/if.h:1.206 src/sys/net/if.h:1.207
--- src/sys/net/if.h:1.206 Mon May 16 01:16:24 2016
+++ src/sys/net/if.h Fri Jun 10 13:31:44 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: if.h,v 1.206 2016/05/16 01:16:24 ozaki-r Exp $ */
+/* $NetBSD: if.h,v 1.207 2016/06/10 13:31:44 ozaki-r Exp $ */
/*-
* Copyright (c) 1999, 2000, 2001 The NetBSD Foundation, Inc.
@@ -890,17 +890,21 @@ int ifaddrpref_ioctl(struct socket *, u_
extern int (*ifioctl)(struct socket *, u_long, void *, struct lwp *);
int ifioctl_common(struct ifnet *, u_long, void *);
int ifpromisc(struct ifnet *, int);
-struct ifnet *ifunit(const char *);
-struct ifnet *if_get(const char *, struct psref *);
-ifnet_t *if_byindex(u_int);
-ifnet_t *if_get_byindex(u_int, struct psref *);
-void if_put(const struct ifnet *, struct psref *);
int if_addr_init(ifnet_t *, struct ifaddr *, bool);
int if_do_dad(struct ifnet *);
int if_mcast_op(ifnet_t *, const unsigned long, const struct sockaddr *);
int if_flags_set(struct ifnet *, const short);
int if_clone_list(int, char *, int *);
+struct ifnet *ifunit(const char *);
+struct ifnet *if_get(const char *, struct psref *);
+ifnet_t *if_byindex(u_int);
+ifnet_t *if_get_byindex(u_int, struct psref *);
+void if_put(const struct ifnet *, struct psref *);
+void if_acquire_unsafe(struct ifnet *, struct psref *);
+
+bool if_held(struct ifnet *);
+
void if_input(struct ifnet *, struct mbuf *);
struct if_percpuq *
Index: src/sys/net/if_bridge.c
diff -u src/sys/net/if_bridge.c:1.124 src/sys/net/if_bridge.c:1.125
--- src/sys/net/if_bridge.c:1.124 Fri Jun 10 13:27:16 2016
+++ src/sys/net/if_bridge.c Fri Jun 10 13:31:44 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: if_bridge.c,v 1.124 2016/06/10 13:27:16 ozaki-r Exp $ */
+/* $NetBSD: if_bridge.c,v 1.125 2016/06/10 13:31:44 ozaki-r Exp $ */
/*
* Copyright 2001 Wasabi Systems, Inc.
@@ -80,7 +80,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_bridge.c,v 1.124 2016/06/10 13:27:16 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_bridge.c,v 1.125 2016/06/10 13:31:44 ozaki-r Exp $");
#ifdef _KERNEL_OPT
#include "opt_bridge_ipf.h"
@@ -1610,12 +1610,18 @@ bridge_forward(struct bridge_softc *sc,
struct ifnet *src_if, *dst_if;
struct ether_header *eh;
struct psref psref;
+ struct psref psref_src;
DECLARE_LOCK_VARIABLE;
if ((sc->sc_if.if_flags & IFF_RUNNING) == 0)
return;
- src_if = m->m_pkthdr.rcvif;
+ src_if = m_get_rcvif_psref(m, &psref_src);
+ if (src_if == NULL) {
+ /* Interface is being destroyed? */
+ m_freem(m);
+ goto out;
+ }
sc->sc_if.if_ipackets++;
sc->sc_if.if_ibytes += m->m_pkthdr.len;
@@ -1690,8 +1696,7 @@ bridge_forward(struct bridge_softc *sc,
dst_if = NULL;
}
- if (pfil_run_hooks(sc->sc_if.if_pfil, &m,
- m->m_pkthdr.rcvif, PFIL_IN) != 0) {
+ if (pfil_run_hooks(sc->sc_if.if_pfil, &m, src_if, PFIL_IN) != 0) {
if (m != NULL)
m_freem(m);
goto out;
@@ -1704,6 +1709,9 @@ bridge_forward(struct bridge_softc *sc,
goto out;
}
+ m_put_rcvif_psref(src_if, &psref_src);
+ src_if = NULL;
+
/*
* At this point, we're dealing with a unicast frame
* going to a different interface.
@@ -1736,7 +1744,8 @@ bridge_forward(struct bridge_softc *sc,
bridge_enqueue(sc, dst_if, m, 1);
RELEASE_GLOBAL_LOCKS();
out:
- /* XXX gcc */
+ if (src_if != NULL)
+ m_put_rcvif_psref(src_if, &psref_src);
return;
}
@@ -2642,7 +2651,7 @@ bridge_ip_checkbasic(struct mbuf **mp)
}
switch (m->m_pkthdr.csum_flags &
- ((m->m_pkthdr.rcvif->if_csum_flags_rx & M_CSUM_IPv4) |
+ ((m_get_rcvif_NOMPSAFE(m)->if_csum_flags_rx & M_CSUM_IPv4) |
M_CSUM_IPv4_BAD)) {
case M_CSUM_IPv4|M_CSUM_IPv4_BAD:
/* INET_CSUM_COUNTER_INCR(&ip_hwcsum_bad); */
@@ -2710,7 +2719,7 @@ bridge_ip6_checkbasic(struct mbuf **mp)
* IPv6 header is in the first mbuf of the chain.
*/
if (IP6_HDR_ALIGNED_P(mtod(m, void *)) == 0) {
- struct ifnet *inifp = m->m_pkthdr.rcvif;
+ struct ifnet *inifp = m_get_rcvif_NOMPSAFE(m);
if ((m = m_copyup(m, sizeof(struct ip6_hdr),
(max_linkhdr + 3) & ~3)) == NULL) {
/* XXXJRT new stat, please */
@@ -2719,7 +2728,7 @@ bridge_ip6_checkbasic(struct mbuf **mp)
goto bad;
}
} else if (__predict_false(m->m_len < sizeof(struct ip6_hdr))) {
- struct ifnet *inifp = m->m_pkthdr.rcvif;
+ struct ifnet *inifp = m_get_rcvif_NOMPSAFE(m);
if ((m = m_pullup(m, sizeof(struct ip6_hdr))) == NULL) {
ip6_statinc(IP6_STAT_TOOSMALL);
in6_ifstat_inc(inifp, ifs6_in_hdrerr);
@@ -2731,7 +2740,7 @@ bridge_ip6_checkbasic(struct mbuf **mp)
if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
ip6_statinc(IP6_STAT_BADVERS);
- in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr);
+ in6_ifstat_inc(m_get_rcvif_NOMPSAFE(m), ifs6_in_hdrerr);
goto bad;
}
Index: src/sys/net/if_mpls.c
diff -u src/sys/net/if_mpls.c:1.22 src/sys/net/if_mpls.c:1.23
--- src/sys/net/if_mpls.c:1.22 Thu Apr 28 00:16:56 2016
+++ src/sys/net/if_mpls.c Fri Jun 10 13:31:44 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: if_mpls.c,v 1.22 2016/04/28 00:16:56 ozaki-r Exp $ */
+/* $NetBSD: if_mpls.c,v 1.23 2016/06/10 13:31:44 ozaki-r Exp $ */
/*
* Copyright (c) 2010 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_mpls.c,v 1.22 2016/04/28 00:16:56 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_mpls.c,v 1.23 2016/06/10 13:31:44 ozaki-r Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -188,13 +188,13 @@ mplsintr(void)
return;
if (((m->m_flags & M_PKTHDR) == 0) ||
- (m->m_pkthdr.rcvif == 0))
+ (m->m_pkthdr.rcvif_index == 0))
panic("mplsintr(): no pkthdr or rcvif");
#ifdef MBUFTRACE
m_claimm(m, &mpls_owner);
#endif
- mpls_input(m->m_pkthdr.rcvif, m);
+ mpls_input(m_get_rcvif_NOMPSAFE(m), m);
}
}
Index: src/sys/net/if_pppoe.c
diff -u src/sys/net/if_pppoe.c:1.107 src/sys/net/if_pppoe.c:1.108
--- src/sys/net/if_pppoe.c:1.107 Fri Jun 10 13:27:16 2016
+++ src/sys/net/if_pppoe.c Fri Jun 10 13:31:44 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: if_pppoe.c,v 1.107 2016/06/10 13:27:16 ozaki-r Exp $ */
+/* $NetBSD: if_pppoe.c,v 1.108 2016/06/10 13:31:44 ozaki-r Exp $ */
/*-
* Copyright (c) 2002, 2008 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_pppoe.c,v 1.107 2016/06/10 13:27:16 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_pppoe.c,v 1.108 2016/06/10 13:31:44 ozaki-r Exp $");
#include "pppoe.h"
@@ -495,7 +495,9 @@ pppoe_dispatch_disc_pkt(struct mbuf *m,
}
}
break; /* ignored */
- case PPPOE_TAG_HUNIQUE:
+ case PPPOE_TAG_HUNIQUE: {
+ struct ifnet *rcvif;
+ int s;
if (sc != NULL)
break;
n = m_pulldown(m, off + sizeof(*pt), len, &noff);
@@ -508,11 +510,14 @@ pppoe_dispatch_disc_pkt(struct mbuf *m,
hunique = mtod(n, uint8_t *) + noff;
hunique_len = len;
#endif
+ rcvif = m_get_rcvif(m, &s);
sc = pppoe_find_softc_by_hunique(mtod(n, char *) + noff,
- len, m->m_pkthdr.rcvif);
+ len, rcvif);
+ m_put_rcvif(rcvif, &s);
if (sc != NULL)
devname = sc->sc_sppp.pp_if.if_xname;
break;
+ }
case PPPOE_TAG_ACCOOKIE:
if (ac_cookie == NULL) {
n = m_pulldown(m, off + sizeof(*pt), len,
@@ -623,7 +628,7 @@ breakbreak:;
}
sc = pppoe_find_softc_by_hunique(ac_cookie,
ac_cookie_len,
- m->m_pkthdr.rcvif);
+ m_get_rcvif_NOMPSAFE(m));
if (sc == NULL) {
/* be quiet if there is not a single pppoe instance */
if (!LIST_EMPTY(&pppoe_softc_list))
@@ -718,12 +723,18 @@ breakbreak:;
sc->sc_state = PPPOE_STATE_SESSION;
sc->sc_sppp.pp_up(&sc->sc_sppp); /* notify upper layers */
break;
- case PPPOE_CODE_PADT:
- sc = pppoe_find_softc_by_session(session, m->m_pkthdr.rcvif);
+ case PPPOE_CODE_PADT: {
+ struct ifnet *rcvif;
+ int s;
+
+ rcvif = m_get_rcvif(m, &s);
+ sc = pppoe_find_softc_by_session(session, rcvif);
+ m_put_rcvif(rcvif, &s);
if (sc == NULL)
goto done;
pppoe_clear_softc(sc, "received PADT");
break;
+ }
default:
printf("%s: unknown code (0x%04x) session = 0x%04x\n",
sc? sc->sc_sppp.pp_if.if_xname : "pppoe",
@@ -755,6 +766,8 @@ pppoe_data_input(struct mbuf *m)
uint16_t session, plen;
struct pppoe_softc *sc;
struct pppoehdr *ph;
+ struct ifnet *rcvif;
+ struct psref psref;
#ifdef PPPOE_TERM_UNKNOWN_SESSIONS
uint8_t shost[ETHER_ADDR_LEN];
#endif
@@ -789,15 +802,18 @@ pppoe_data_input(struct mbuf *m)
goto drop;
session = ntohs(ph->session);
- sc = pppoe_find_softc_by_session(session, m->m_pkthdr.rcvif);
+ rcvif = m_get_rcvif_psref(m, &psref);
+ sc = pppoe_find_softc_by_session(session, rcvif);
if (sc == NULL) {
#ifdef PPPOE_TERM_UNKNOWN_SESSIONS
printf("pppoe: input for unknown session 0x%x, sending PADT\n",
session);
- pppoe_send_padt(m->m_pkthdr.rcvif, session, shost);
+ pppoe_send_padt(rcvif, session, shost);
#endif
+ m_put_rcvif_psref(rcvif, &psref);
goto drop;
}
+ m_put_rcvif_psref(rcvif, &psref);
plen = ntohs(ph->plen);
Index: src/sys/net/if_stf.c
diff -u src/sys/net/if_stf.c:1.89 src/sys/net/if_stf.c:1.90
--- src/sys/net/if_stf.c:1.89 Fri Jun 10 13:27:16 2016
+++ src/sys/net/if_stf.c Fri Jun 10 13:31:44 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: if_stf.c,v 1.89 2016/06/10 13:27:16 ozaki-r Exp $ */
+/* $NetBSD: if_stf.c,v 1.90 2016/06/10 13:31:44 ozaki-r Exp $ */
/* $KAME: if_stf.c,v 1.62 2001/06/07 22:32:16 itojun Exp $ */
/*
@@ -75,7 +75,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_stf.c,v 1.89 2016/06/10 13:27:16 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_stf.c,v 1.90 2016/06/10 13:31:44 ozaki-r Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -584,7 +584,7 @@ in_stf_input(struct mbuf *m, int off, in
* for source, perform ingress filter as well.
*/
if (stf_checkaddr4(sc, &ip->ip_dst, NULL) < 0 ||
- stf_checkaddr4(sc, &ip->ip_src, m->m_pkthdr.rcvif) < 0) {
+ stf_checkaddr4(sc, &ip->ip_src, m_get_rcvif_NOMPSAFE(m)) < 0) {
m_freem(m);
return;
}
@@ -604,7 +604,7 @@ in_stf_input(struct mbuf *m, int off, in
* for source, perform ingress filter as well.
*/
if (stf_checkaddr6(sc, &ip6->ip6_dst, NULL) < 0 ||
- stf_checkaddr6(sc, &ip6->ip6_src, m->m_pkthdr.rcvif) < 0) {
+ stf_checkaddr6(sc, &ip6->ip6_src, m_get_rcvif_NOMPSAFE(m)) < 0) {
m_freem(m);
return;
}
Index: src/sys/netatalk/ddp_input.c
diff -u src/sys/netatalk/ddp_input.c:1.26 src/sys/netatalk/ddp_input.c:1.27
--- src/sys/netatalk/ddp_input.c:1.26 Wed Aug 31 18:31:03 2011
+++ src/sys/netatalk/ddp_input.c Fri Jun 10 13:31:44 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: ddp_input.c,v 1.26 2011/08/31 18:31:03 plunky Exp $ */
+/* $NetBSD: ddp_input.c,v 1.27 2016/06/10 13:31:44 ozaki-r Exp $ */
/*
* Copyright (c) 1990,1994 Regents of The University of Michigan.
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ddp_input.c,v 1.26 2011/08/31 18:31:03 plunky Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ddp_input.c,v 1.27 2016/06/10 13:31:44 ozaki-r Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -79,7 +79,7 @@ atintr(void)
break;
m_claimm(m, &atalk_rx_mowner);
- ifp = m->m_pkthdr.rcvif;
+ ifp = m_get_rcvif_NOMPSAFE(m);
for (aa = at_ifaddr.tqh_first; aa; aa = aa->aa_list.tqe_next) {
if (aa->aa_ifp == ifp && (aa->aa_flags & AFA_PHASE2))
break;
@@ -103,7 +103,7 @@ atintr(void)
break;
m_claimm(m, &atalk_rx_mowner);
- ifp = m->m_pkthdr.rcvif;
+ ifp = m_get_rcvif_NOMPSAFE(m);
for (aa = at_ifaddr.tqh_first; aa; aa = aa->aa_list.tqe_next) {
if (aa->aa_ifp == ifp &&
(aa->aa_flags & AFA_PHASE2) == 0)
Index: src/sys/netinet/if_arp.c
diff -u src/sys/netinet/if_arp.c:1.210 src/sys/netinet/if_arp.c:1.211
--- src/sys/netinet/if_arp.c:1.210 Tue May 17 09:00:24 2016
+++ src/sys/netinet/if_arp.c Fri Jun 10 13:31:44 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: if_arp.c,v 1.210 2016/05/17 09:00:24 ozaki-r Exp $ */
+/* $NetBSD: if_arp.c,v 1.211 2016/06/10 13:31:44 ozaki-r Exp $ */
/*-
* Copyright (c) 1998, 2000, 2008 The NetBSD Foundation, Inc.
@@ -68,7 +68,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.210 2016/05/17 09:00:24 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.211 2016/06/10 13:31:44 ozaki-r Exp $");
#ifdef _KERNEL_OPT
#include "opt_ddb.h"
@@ -890,6 +890,8 @@ arpintr(void)
mutex_enter(softnet_lock);
KERNEL_LOCK(1, NULL);
while (arpintrq.ifq_head) {
+ struct ifnet *rcvif;
+
s = splnet();
IF_DEQUEUE(&arpintrq, m);
splx(s);
@@ -906,7 +908,8 @@ arpintr(void)
(ar = mtod(m, struct arphdr *)) == NULL)
goto badlen;
- switch (m->m_pkthdr.rcvif->if_type) {
+ rcvif = m_get_rcvif(m, &s);
+ switch (rcvif->if_type) {
case IFT_IEEE1394:
arplen = sizeof(struct arphdr) +
ar->ar_hln + 2 * ar->ar_pln;
@@ -916,6 +919,7 @@ arpintr(void)
2 * ar->ar_hln + 2 * ar->ar_pln;
break;
}
+ m_put_rcvif(rcvif, &s);
if (/* XXX ntohs(ar->ar_hrd) == ARPHRD_ETHER && */
m->m_len >= arplen)
@@ -955,7 +959,7 @@ static void
in_arpinput(struct mbuf *m)
{
struct arphdr *ah;
- struct ifnet *ifp = m->m_pkthdr.rcvif;
+ struct ifnet *ifp, *rcvif = NULL;
struct llentry *la = NULL;
struct in_ifaddr *ia;
#if NBRIDGE > 0
@@ -969,12 +973,14 @@ in_arpinput(struct mbuf *m)
int op;
void *tha;
uint64_t *arps;
+ struct psref psref;
if (__predict_false(m_makewritable(&m, 0, m->m_pkthdr.len, M_DONTWAIT)))
goto out;
ah = mtod(m, struct arphdr *);
op = ntohs(ah->ar_op);
+ rcvif = ifp = m_get_rcvif_psref(m, &psref);
/*
* Fix up ah->ar_hrd if necessary, before using ar_tha() or
* ar_tpa().
@@ -1014,14 +1020,14 @@ in_arpinput(struct mbuf *m)
((ia->ia_ifp->if_flags & (IFF_UP|IFF_RUNNING)) ==
(IFF_UP|IFF_RUNNING))) {
index++;
- if (ia->ia_ifp == m->m_pkthdr.rcvif &&
+ if (ia->ia_ifp == rcvif &&
carp_iamatch(ia, ar_sha(ah),
&count, index)) {
break;
}
} else
#endif
- if (ia->ia_ifp == m->m_pkthdr.rcvif)
+ if (ia->ia_ifp == rcvif)
break;
#if NBRIDGE > 0
/*
@@ -1031,8 +1037,8 @@ in_arpinput(struct mbuf *m)
* layer. Note we still prefer a perfect match,
* but allow this weaker match if necessary.
*/
- if (m->m_pkthdr.rcvif->if_bridge != NULL &&
- m->m_pkthdr.rcvif->if_bridge == ia->ia_ifp->if_bridge)
+ if (rcvif->if_bridge != NULL &&
+ rcvif->if_bridge == ia->ia_ifp->if_bridge)
bridge_ia = ia;
#endif /* NBRIDGE > 0 */
@@ -1042,13 +1048,16 @@ in_arpinput(struct mbuf *m)
#if NBRIDGE > 0
if (ia == NULL && bridge_ia != NULL) {
ia = bridge_ia;
+ m_put_rcvif_psref(rcvif, &psref);
+ rcvif = NULL;
+ /* FIXME */
ifp = bridge_ia->ia_ifp;
}
#endif
if (ia == NULL) {
INADDR_TO_IA(isaddr, ia);
- while ((ia != NULL) && ia->ia_ifp != m->m_pkthdr.rcvif)
+ while ((ia != NULL) && ia->ia_ifp != rcvif)
NEXT_IA_WITH_SAME_ADDR(ia);
if (ia == NULL) {
@@ -1272,11 +1281,12 @@ reply:
/* Proxy ARP */
struct llentry *lle = NULL;
struct sockaddr_in sin;
-
#if NCARP > 0
- if (ifp->if_type == IFT_CARP &&
- m->m_pkthdr.rcvif->if_type != IFT_CARP)
+ int s;
+ struct ifnet *_rcvif = m_get_rcvif(m, &s);
+ if (ifp->if_type == IFT_CARP && _rcvif->if_type != IFT_CARP)
goto out;
+ m_put_rcvif(_rcvif, &s);
#endif
tha = ar_tha(ah);
@@ -1325,12 +1335,16 @@ reply:
arps[ARP_STAT_SNDREPLY]++;
ARP_STAT_PUTREF();
(*ifp->if_output)(ifp, m, &sa, NULL);
+ if (rcvif != NULL)
+ m_put_rcvif_psref(rcvif, &psref);
return;
out:
if (la != NULL)
LLE_WUNLOCK(la);
drop:
+ if (rcvif != NULL)
+ m_put_rcvif_psref(rcvif, &psref);
m_freem(m);
}
@@ -1784,15 +1798,17 @@ out:
void
in_revarpinput(struct mbuf *m)
{
- struct ifnet *ifp;
struct arphdr *ah;
void *tha;
int op;
+ struct ifnet *rcvif;
+ int s;
ah = mtod(m, struct arphdr *);
op = ntohs(ah->ar_op);
- switch (m->m_pkthdr.rcvif->if_type) {
+ rcvif = m_get_rcvif(m, &s);
+ switch (rcvif->if_type) {
case IFT_IEEE1394:
/* ARP without target hardware address is not supported */
goto out;
@@ -1803,6 +1819,7 @@ in_revarpinput(struct mbuf *m)
switch (op) {
case ARPOP_REQUEST:
case ARPOP_REPLY: /* per RFC */
+ m_put_rcvif(rcvif, &s);
in_arpinput(m);
return;
case ARPOP_REVREPLY:
@@ -1813,15 +1830,14 @@ in_revarpinput(struct mbuf *m)
}
if (!revarp_in_progress)
goto out;
- ifp = m->m_pkthdr.rcvif;
- if (ifp != myip_ifp) /* !same interface */
+ if (rcvif != myip_ifp) /* !same interface */
goto out;
if (myip_initialized)
goto wake;
tha = ar_tha(ah);
if (tha == NULL)
goto out;
- if (memcmp(tha, CLLADDR(ifp->if_sadl), ifp->if_sadl->sdl_alen))
+ if (memcmp(tha, CLLADDR(rcvif->if_sadl), rcvif->if_sadl->sdl_alen))
goto out;
memcpy(&srv_ip, ar_spa(ah), sizeof(srv_ip));
memcpy(&myip, ar_tpa(ah), sizeof(myip));
@@ -1830,6 +1846,7 @@ wake: /* Do wakeup every time in case it
wakeup((void *)&myip);
out:
+ m_put_rcvif(rcvif, &s);
m_freem(m);
}
Index: src/sys/netinet/igmp.c
diff -u src/sys/netinet/igmp.c:1.57 src/sys/netinet/igmp.c:1.58
--- src/sys/netinet/igmp.c:1.57 Tue Apr 26 08:44:44 2016
+++ src/sys/netinet/igmp.c Fri Jun 10 13:31:44 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: igmp.c,v 1.57 2016/04/26 08:44:44 ozaki-r Exp $ */
+/* $NetBSD: igmp.c,v 1.58 2016/06/10 13:31:44 ozaki-r Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -40,7 +40,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: igmp.c,v 1.57 2016/04/26 08:44:44 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: igmp.c,v 1.58 2016/06/10 13:31:44 ozaki-r Exp $");
#ifdef _KERNEL_OPT
#include "opt_mrouting.h"
@@ -184,7 +184,7 @@ igmp_init(void)
void
igmp_input(struct mbuf *m, ...)
{
- ifnet_t *ifp = m->m_pkthdr.rcvif;
+ ifnet_t *ifp;
struct ip *ip = mtod(m, struct ip *);
struct igmp *igmp;
u_int minlen, timer;
@@ -192,6 +192,7 @@ igmp_input(struct mbuf *m, ...)
struct in_ifaddr *ia;
int proto, ip_len, iphlen;
va_list ap;
+ struct psref psref;
va_start(ap, m);
iphlen = va_arg(ap, int);
@@ -234,6 +235,7 @@ igmp_input(struct mbuf *m, ...)
m->m_data -= iphlen;
m->m_len += iphlen;
+ ifp = m_get_rcvif_psref(m, &psref);
switch (igmp->igmp_type) {
case IGMP_HOST_MEMBERSHIP_QUERY:
@@ -248,8 +250,7 @@ igmp_input(struct mbuf *m, ...)
if (ip->ip_dst.s_addr != INADDR_ALLHOSTS_GROUP) {
IGMP_STATINC(IGMP_STAT_RCV_BADQUERIES);
- m_freem(m);
- return;
+ goto drop;
}
in_multi_lock(RW_WRITER);
@@ -286,8 +287,7 @@ igmp_input(struct mbuf *m, ...)
if (!IN_MULTICAST(ip->ip_dst.s_addr)) {
IGMP_STATINC(IGMP_STAT_RCV_BADQUERIES);
- m_freem(m);
- return;
+ goto drop;
}
timer = igmp->igmp_code * PR_FASTHZ / IGMP_TIMER_SCALE;
@@ -345,8 +345,7 @@ igmp_input(struct mbuf *m, ...)
if (!IN_MULTICAST(igmp->igmp_group.s_addr) ||
!in_hosteq(igmp->igmp_group, ip->ip_dst)) {
IGMP_STATINC(IGMP_STAT_RCV_BADREPORTS);
- m_freem(m);
- return;
+ goto drop;
}
/*
@@ -412,8 +411,7 @@ igmp_input(struct mbuf *m, ...)
if (!IN_MULTICAST(igmp->igmp_group.s_addr) ||
!in_hosteq(igmp->igmp_group, ip->ip_dst)) {
IGMP_STATINC(IGMP_STAT_RCV_BADREPORTS);
- m_freem(m);
- return;
+ goto drop;
}
/*
@@ -458,6 +456,7 @@ igmp_input(struct mbuf *m, ...)
break;
}
+ m_put_rcvif_psref(ifp, &psref);
/*
* Pass all valid IGMP packets up to any process(es) listening
@@ -465,6 +464,11 @@ igmp_input(struct mbuf *m, ...)
*/
rip_input(m, iphlen, proto);
return;
+
+drop:
+ m_put_rcvif_psref(ifp, &psref);
+ m_freem(m);
+ return;
}
int
Index: src/sys/netinet/in_gif.c
diff -u src/sys/netinet/in_gif.c:1.75 src/sys/netinet/in_gif.c:1.76
--- src/sys/netinet/in_gif.c:1.75 Tue Jan 26 06:00:10 2016
+++ src/sys/netinet/in_gif.c Fri Jun 10 13:31:44 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: in_gif.c,v 1.75 2016/01/26 06:00:10 knakahara Exp $ */
+/* $NetBSD: in_gif.c,v 1.76 2016/06/10 13:31:44 ozaki-r Exp $ */
/* $KAME: in_gif.c,v 1.66 2001/07/29 04:46:09 itojun Exp $ */
/*
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: in_gif.c,v 1.75 2016/01/26 06:00:10 knakahara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: in_gif.c,v 1.76 2016/06/10 13:31:44 ozaki-r Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -199,6 +199,8 @@ in_gif_input(struct mbuf *m, int off, in
const struct ip *ip;
int af;
u_int8_t otos;
+ struct ifnet *rcvif;
+ struct psref psref;
ip = mtod(m, const struct ip *);
@@ -218,11 +220,14 @@ in_gif_input(struct mbuf *m, int off, in
return;
}
- if (!gif_validate4(ip, sc, m->m_pkthdr.rcvif)) {
+ rcvif = m_get_rcvif_psref(m, &psref);
+ if (!gif_validate4(ip, sc, rcvif)) {
+ m_put_rcvif_psref(rcvif, &psref);
m_freem(m);
ip_statinc(IP_STAT_NOGIF);
return;
}
+ m_put_rcvif_psref(rcvif, &psref);
#endif
otos = ip->ip_tos;
m_adj(m, off);
@@ -349,7 +354,7 @@ gif_encapcheck4(struct mbuf *m, int off,
sc = arg;
m_copydata(m, 0, sizeof(ip), &ip);
- ifp = ((m->m_flags & M_PKTHDR) != 0) ? m->m_pkthdr.rcvif : NULL;
+ ifp = ((m->m_flags & M_PKTHDR) != 0) ? m_get_rcvif_NOMPSAFE(m) : NULL;
return gif_validate4(&ip, sc, ifp);
}
Index: src/sys/netinet/ip_carp.c
diff -u src/sys/netinet/ip_carp.c:1.66 src/sys/netinet/ip_carp.c:1.67
--- src/sys/netinet/ip_carp.c:1.66 Fri Jun 10 13:27:16 2016
+++ src/sys/netinet/ip_carp.c Fri Jun 10 13:31:44 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: ip_carp.c,v 1.66 2016/06/10 13:27:16 ozaki-r Exp $ */
+/* $NetBSD: ip_carp.c,v 1.67 2016/06/10 13:31:44 ozaki-r Exp $ */
/* $OpenBSD: ip_carp.c,v 1.113 2005/11/04 08:11:54 mcbride Exp $ */
/*
@@ -33,7 +33,7 @@
#endif
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip_carp.c,v 1.66 2016/06/10 13:27:16 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip_carp.c,v 1.67 2016/06/10 13:31:44 ozaki-r Exp $");
/*
* TODO:
@@ -475,6 +475,7 @@ carp_proto_input(struct mbuf *m, ...)
struct carp_header *ch;
int iplen, len;
va_list ap;
+ struct ifnet *rcvif;
va_start(ap, m);
va_end(ap);
@@ -487,11 +488,12 @@ carp_proto_input(struct mbuf *m, ...)
return;
}
+ rcvif = m_get_rcvif_NOMPSAFE(m);
/* check if received on a valid carp interface */
- if (m->m_pkthdr.rcvif->if_type != IFT_CARP) {
+ if (rcvif->if_type != IFT_CARP) {
CARP_STATINC(CARP_STAT_BADIF);
CARP_LOG(sc, ("packet received on non-carp interface: %s",
- m->m_pkthdr.rcvif->if_xname));
+ rcvif->if_xname));
m_freem(m);
return;
}
@@ -500,7 +502,7 @@ carp_proto_input(struct mbuf *m, ...)
if (ip->ip_ttl != CARP_DFLTTL) {
CARP_STATINC(CARP_STAT_BADTTL);
CARP_LOG(sc, ("received ttl %d != %d on %s", ip->ip_ttl,
- CARP_DFLTTL, m->m_pkthdr.rcvif->if_xname));
+ CARP_DFLTTL, rcvif->if_xname));
m_freem(m);
return;
}
@@ -514,7 +516,7 @@ carp_proto_input(struct mbuf *m, ...)
if (len > m->m_pkthdr.len) {
CARP_STATINC(CARP_STAT_BADLEN);
CARP_LOG(sc, ("packet too short %d on %s", m->m_pkthdr.len,
- m->m_pkthdr.rcvif->if_xname));
+ rcvif->if_xname));
m_freem(m);
return;
}
@@ -530,7 +532,7 @@ carp_proto_input(struct mbuf *m, ...)
if (carp_cksum(m, len - iplen)) {
CARP_STATINC(CARP_STAT_BADSUM);
CARP_LOG(sc, ("checksum failed on %s",
- m->m_pkthdr.rcvif->if_xname));
+ rcvif->if_xname));
m_freem(m);
return;
}
@@ -548,6 +550,7 @@ carp6_proto_input(struct mbuf **mp, int
struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
struct carp_header *ch;
u_int len;
+ struct ifnet *rcvif;
CARP_STATINC(CARP_STAT_IPACKETS6);
MCLAIM(m, &carp_proto6_mowner_rx);
@@ -557,11 +560,13 @@ carp6_proto_input(struct mbuf **mp, int
return (IPPROTO_DONE);
}
+ rcvif = m_get_rcvif_NOMPSAFE(m);
+
/* check if received on a valid carp interface */
- if (m->m_pkthdr.rcvif->if_type != IFT_CARP) {
+ if (rcvif->if_type != IFT_CARP) {
CARP_STATINC(CARP_STAT_BADIF);
CARP_LOG(sc, ("packet received on non-carp interface: %s",
- m->m_pkthdr.rcvif->if_xname));
+ rcvif->if_xname));
m_freem(m);
return (IPPROTO_DONE);
}
@@ -570,7 +575,7 @@ carp6_proto_input(struct mbuf **mp, int
if (ip6->ip6_hlim != CARP_DFLTTL) {
CARP_STATINC(CARP_STAT_BADTTL);
CARP_LOG(sc, ("received ttl %d != %d on %s", ip6->ip6_hlim,
- CARP_DFLTTL, m->m_pkthdr.rcvif->if_xname));
+ CARP_DFLTTL, rcvif->if_xname));
m_freem(m);
return (IPPROTO_DONE);
}
@@ -589,8 +594,7 @@ carp6_proto_input(struct mbuf **mp, int
m->m_data += *offp;
if (carp_cksum(m, sizeof(*ch))) {
CARP_STATINC(CARP_STAT_BADSUM);
- CARP_LOG(sc, ("checksum failed, on %s",
- m->m_pkthdr.rcvif->if_xname));
+ CARP_LOG(sc, ("checksum failed, on %s", rcvif->if_xname));
m_freem(m);
return (IPPROTO_DONE);
}
@@ -609,7 +613,7 @@ carp_proto_input_c(struct mbuf *m, struc
struct timeval sc_tv, ch_tv;
TAILQ_FOREACH(sc, &((struct carp_if *)
- m->m_pkthdr.rcvif->if_carpdev->if_carp)->vhif_vrs, sc_list)
+ m_get_rcvif_NOMPSAFE(m)->if_carpdev->if_carp)->vhif_vrs, sc_list)
if (sc->sc_vhid == ch->carp_vhid)
break;
@@ -1387,7 +1391,7 @@ int
carp_input(struct mbuf *m, u_int8_t *shost, u_int8_t *dhost, u_int16_t etype)
{
struct ether_header eh;
- struct carp_if *cif = (struct carp_if *)m->m_pkthdr.rcvif->if_carp;
+ struct carp_if *cif = (struct carp_if *)m_get_rcvif_NOMPSAFE(m)->if_carp;
struct ifnet *ifp;
memcpy(&eh.ether_shost, shost, sizeof(eh.ether_shost));
@@ -1412,7 +1416,7 @@ carp_input(struct mbuf *m, u_int8_t *sho
return (1);
}
- ifp = carp_ourether(cif, &eh, m->m_pkthdr.rcvif->if_type, 0);
+ ifp = carp_ourether(cif, &eh, m_get_rcvif_NOMPSAFE(m)->if_type, 0);
if (ifp == NULL) {
return (1);
}
Index: src/sys/netinet/ip_flow.c
diff -u src/sys/netinet/ip_flow.c:1.66 src/sys/netinet/ip_flow.c:1.67
--- src/sys/netinet/ip_flow.c:1.66 Mon Mar 23 18:33:17 2015
+++ src/sys/netinet/ip_flow.c Fri Jun 10 13:31:44 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: ip_flow.c,v 1.66 2015/03/23 18:33:17 roy Exp $ */
+/* $NetBSD: ip_flow.c,v 1.67 2016/06/10 13:31:44 ozaki-r Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip_flow.c,v 1.66 2015/03/23 18:33:17 roy Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip_flow.c,v 1.67 2016/06/10 13:31:44 ozaki-r Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -177,6 +177,8 @@ ipflow_fastforward(struct mbuf *m)
const struct sockaddr *dst;
int error;
int iplen;
+ struct ifnet *ifp;
+ int s;
/*
* Are we forwarding packets? Big enough for an IP packet?
@@ -210,14 +212,16 @@ ipflow_fastforward(struct mbuf *m)
if ((ipf = ipflow_lookup(ip)) == NULL)
return 0;
+ ifp = m_get_rcvif(m, &s);
/*
* Verify the IP header checksum.
*/
switch (m->m_pkthdr.csum_flags &
- ((m->m_pkthdr.rcvif->if_csum_flags_rx & M_CSUM_IPv4) |
+ ((ifp->if_csum_flags_rx & M_CSUM_IPv4) |
M_CSUM_IPv4_BAD)) {
case M_CSUM_IPv4|M_CSUM_IPv4_BAD:
- return (0);
+ m_put_rcvif(ifp, &s);
+ return 0;
case M_CSUM_IPv4:
/* Checksum was okay. */
@@ -225,10 +229,13 @@ ipflow_fastforward(struct mbuf *m)
default:
/* Must compute it ourselves. */
- if (in_cksum(m, sizeof(struct ip)) != 0)
- return (0);
+ if (in_cksum(m, sizeof(struct ip)) != 0) {
+ m_put_rcvif(ifp, &s);
+ return 0;
+ }
break;
}
+ m_put_rcvif(ifp, &s);
/*
* Route and interface still up?
Index: src/sys/netinet/ip_icmp.c
diff -u src/sys/netinet/ip_icmp.c:1.146 src/sys/netinet/ip_icmp.c:1.147
--- src/sys/netinet/ip_icmp.c:1.146 Fri Jun 10 13:27:16 2016
+++ src/sys/netinet/ip_icmp.c Fri Jun 10 13:31:44 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: ip_icmp.c,v 1.146 2016/06/10 13:27:16 ozaki-r Exp $ */
+/* $NetBSD: ip_icmp.c,v 1.147 2016/06/10 13:31:44 ozaki-r Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -94,7 +94,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip_icmp.c,v 1.146 2016/06/10 13:27:16 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip_icmp.c,v 1.147 2016/06/10 13:31:44 ozaki-r Exp $");
#ifdef _KERNEL_OPT
#include "opt_ipsec.h"
@@ -339,7 +339,7 @@ icmp_error(struct mbuf *n, int type, int
m->m_data -= sizeof(struct ip);
m->m_len += sizeof(struct ip);
m->m_pkthdr.len = m->m_len;
- m_set_rcvif(m, n->m_pkthdr.rcvif);
+ m_copy_rcvif(m, n);
nip = mtod(m, struct ip *);
/* ip_v set in ip_output */
nip->ip_hl = sizeof(struct ip) >> 2;
@@ -560,7 +560,10 @@ icmp_input(struct mbuf *m, ...)
icp->icmp_ttime = icp->icmp_rtime; /* bogus, do later! */
goto reflect;
- case ICMP_MASKREQ:
+ case ICMP_MASKREQ: {
+ struct ifnet *rcvif;
+ int s;
+
if (icmpmaskrepl == 0)
break;
/*
@@ -576,8 +579,10 @@ icmp_input(struct mbuf *m, ...)
icmpdst.sin_addr = ip->ip_src;
else
icmpdst.sin_addr = ip->ip_dst;
+ rcvif = m_get_rcvif(m, &s);
ia = ifatoia(ifaof_ifpforaddr(sintosa(&icmpdst),
- m->m_pkthdr.rcvif));
+ rcvif));
+ m_put_rcvif(rcvif, &s);
if (ia == 0)
break;
icp->icmp_type = ICMP_MASKREPLY;
@@ -597,6 +602,7 @@ reflect:
}
icmp_reflect(m);
return;
+ }
case ICMP_REDIRECT:
if (code > 3)
@@ -686,6 +692,8 @@ icmp_reflect(struct mbuf *m)
struct in_addr t;
struct mbuf *opts = NULL;
int optlen = (ip->ip_hl << 2) - sizeof(struct ip);
+ struct ifnet *rcvif;
+ struct psref psref;
if (!in_canforward(ip->ip_src) &&
((ip->ip_src.s_addr & IN_CLASSA_NET) !=
@@ -708,10 +716,12 @@ icmp_reflect(struct mbuf *m)
if (ia && (ia->ia4_flags & IN_IFF_NOTREADY))
ia = NULL;
+ rcvif = m_get_rcvif_psref(m, &psref);
+
/* look for packet sent to broadcast address */
- if (ia == NULL && m->m_pkthdr.rcvif &&
- (m->m_pkthdr.rcvif->if_flags & IFF_BROADCAST)) {
- IFADDR_FOREACH(ifa, m->m_pkthdr.rcvif) {
+ if (ia == NULL && rcvif &&
+ (rcvif->if_flags & IFF_BROADCAST)) {
+ IFADDR_FOREACH(ifa, rcvif) {
if (ifa->ifa_addr->sa_family != AF_INET)
continue;
if (in_hosteq(t,ifatoia(ifa)->ia_broadaddr.sin_addr)) {
@@ -733,7 +743,7 @@ icmp_reflect(struct mbuf *m)
* use that, if it's an address on the interface which
* received the packet
*/
- if (sin == NULL && m->m_pkthdr.rcvif) {
+ if (sin == NULL && rcvif) {
struct sockaddr_in sin_dst;
struct route icmproute;
int errornum;
@@ -750,7 +760,7 @@ icmp_reflect(struct mbuf *m)
sin = NULL;
INADDR_TO_IA(t, ia);
while (ia) {
- if (ia->ia_ifp == m->m_pkthdr.rcvif) {
+ if (ia->ia_ifp == rcvif) {
sin = &ia->ia_addr;
break;
}
@@ -765,8 +775,8 @@ icmp_reflect(struct mbuf *m)
* interface. This can happen when routing is asymmetric, or
* when the incoming packet was encapsulated
*/
- if (sin == NULL && m->m_pkthdr.rcvif) {
- IFADDR_FOREACH(ifa, m->m_pkthdr.rcvif) {
+ if (sin == NULL && rcvif) {
+ IFADDR_FOREACH(ifa, rcvif) {
if (ifa->ifa_addr->sa_family != AF_INET)
continue;
sin = &(ifatoia(ifa)->ia_addr);
@@ -774,6 +784,8 @@ icmp_reflect(struct mbuf *m)
}
}
+ m_put_rcvif_psref(rcvif, &psref);
+
/*
* The following happens if the packet was not addressed to us,
* and was received on an interface with no IP address:
Index: src/sys/netinet/ip_input.c
diff -u src/sys/netinet/ip_input.c:1.328 src/sys/netinet/ip_input.c:1.329
--- src/sys/netinet/ip_input.c:1.328 Thu Jan 21 15:41:30 2016
+++ src/sys/netinet/ip_input.c Fri Jun 10 13:31:44 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: ip_input.c,v 1.328 2016/01/21 15:41:30 riastradh Exp $ */
+/* $NetBSD: ip_input.c,v 1.329 2016/06/10 13:31:44 ozaki-r 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.328 2016/01/21 15:41:30 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.329 2016/06/10 13:31:44 ozaki-r Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -284,7 +284,7 @@ struct mowner ip_tx_mowner = MOWNER_INIT
static void ipintr(void *);
static void ip_input(struct mbuf *);
-static void ip_forward(struct mbuf *, int);
+static void ip_forward(struct mbuf *, int, struct ifnet *);
static bool ip_dooptions(struct mbuf *);
static struct in_ifaddr *ip_rtaddr(struct in_addr);
static void sysctl_net_inet_ip_setup(struct sysctllog **);
@@ -374,13 +374,15 @@ ip_input(struct mbuf *m)
int checkif;
int srcrt = 0;
ifnet_t *ifp;
+ struct psref psref;
KASSERTMSG(cpu_softintr_p(), "ip_input: not in the software "
"interrupt handler; synchronization assumptions violated");
MCLAIM(m, &ip_rx_mowner);
KASSERT((m->m_flags & M_PKTHDR) != 0);
- ifp = m->m_pkthdr.rcvif;
+
+ ifp = m_get_rcvif_psref(m, &psref);
/*
* If no IP addresses have been set yet but the interfaces
@@ -403,12 +405,12 @@ ip_input(struct mbuf *m)
(max_linkhdr + 3) & ~3)) == NULL) {
/* XXXJRT new stat, please */
IP_STATINC(IP_STAT_TOOSMALL);
- return;
+ goto out;
}
} else if (__predict_false(m->m_len < sizeof (struct ip))) {
if ((m = m_pullup(m, sizeof (struct ip))) == NULL) {
IP_STATINC(IP_STAT_TOOSMALL);
- return;
+ goto out;
}
}
ip = mtod(m, struct ip *);
@@ -424,7 +426,7 @@ ip_input(struct mbuf *m)
if (hlen > m->m_len) {
if ((m = m_pullup(m, hlen)) == NULL) {
IP_STATINC(IP_STAT_BADHLEN);
- return;
+ goto out;
}
ip = mtod(m, struct ip *);
}
@@ -528,7 +530,7 @@ ip_input(struct mbuf *m)
freed = pfil_run_hooks(inet_pfil_hook, &m, ifp, PFIL_IN) != 0;
SOFTNET_UNLOCK();
if (freed || m == NULL) {
- return;
+ goto out;
}
ip = mtod(m, struct ip *);
hlen = ip->ip_hl << 2;
@@ -557,7 +559,7 @@ ip_input(struct mbuf *m)
if ((*altq_input)(m, AF_INET) == 0) {
/* Packet dropped by traffic conditioner. */
SOFTNET_UNLOCK();
- return;
+ goto out;
}
SOFTNET_UNLOCK();
}
@@ -571,7 +573,7 @@ ip_input(struct mbuf *m)
*/
ip_nhops = 0; /* for source routed packets */
if (hlen > sizeof (struct ip) && ip_dooptions(m))
- return;
+ goto out;
/*
* Enable a consistency check between the destination address
@@ -659,8 +661,7 @@ ip_input(struct mbuf *m)
if (ip_mforward(m, ifp) != 0) {
SOFTNET_UNLOCK();
IP_STATINC(IP_STAT_CANTFORWARD);
- m_freem(m);
- return;
+ goto bad;
}
SOFTNET_UNLOCK();
@@ -681,8 +682,7 @@ ip_input(struct mbuf *m)
*/
if (!in_multi_group(ip->ip_dst, ifp, 0)) {
IP_STATINC(IP_STAT_CANTFORWARD);
- m_freem(m);
- return;
+ goto bad;
}
goto ours;
}
@@ -694,6 +694,7 @@ ip_input(struct mbuf *m)
* Not for us; forward if possible and desirable.
*/
if (ipforwarding == 0) {
+ m_put_rcvif_psref(ifp, &psref);
IP_STATINC(IP_STAT_CANTFORWARD);
m_freem(m);
} else {
@@ -704,6 +705,7 @@ ip_input(struct mbuf *m)
* forwarding loop till TTL goes to 0.
*/
if (downmatch) {
+ m_put_rcvif_psref(ifp, &psref);
icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, 0, 0);
IP_STATINC(IP_STAT_CANTFORWARD);
return;
@@ -720,11 +722,14 @@ ip_input(struct mbuf *m)
SOFTNET_UNLOCK();
}
#endif
- ip_forward(m, srcrt);
+ ip_forward(m, srcrt, ifp);
+ m_put_rcvif_psref(ifp, &psref);
}
return;
ours:
+ m_put_rcvif_psref(ifp, &psref);
+
/*
* If offset or IP_MF are set, must reassemble.
*/
@@ -781,12 +786,17 @@ ours:
SOFTNET_UNLOCK();
return;
bad:
+ m_put_rcvif_psref(ifp, &psref);
m_freem(m);
return;
badcsum:
+ m_put_rcvif_psref(ifp, &psref);
IP_STATINC(IP_STAT_BADSUM);
m_freem(m);
+ return;
+out:
+ m_put_rcvif_psref(ifp, &psref);
}
/*
@@ -988,7 +998,10 @@ ip_dooptions(struct mbuf *m)
case IPOPT_TS_TSONLY:
break;
- case IPOPT_TS_TSANDADDR:
+ case IPOPT_TS_TSANDADDR: {
+ struct ifnet *rcvif;
+ int s;
+
if (ipt->ipt_ptr - 1 + sizeof(n_time) +
sizeof(struct in_addr) > ipt->ipt_len) {
code = (u_char *)&ipt->ipt_ptr -
@@ -996,14 +1009,17 @@ ip_dooptions(struct mbuf *m)
goto bad;
}
ipaddr.sin_addr = dst;
+ rcvif = m_get_rcvif(m, &s);
ia = ifatoia(ifaof_ifpforaddr(sintosa(&ipaddr),
- m->m_pkthdr.rcvif));
+ rcvif));
+ m_put_rcvif(rcvif, &s);
if (ia == 0)
continue;
bcopy(&ia->ia_addr.sin_addr,
cp0, sizeof(struct in_addr));
ipt->ipt_ptr += sizeof(struct in_addr);
break;
+ }
case IPOPT_TS_PRESPEC:
if (ipt->ipt_ptr - 1 + sizeof(n_time) +
@@ -1034,12 +1050,18 @@ ip_dooptions(struct mbuf *m)
}
}
if (forward) {
+ struct ifnet *rcvif;
+ struct psref psref;
+
if (ip_forwsrcrt == 0) {
type = ICMP_UNREACH;
code = ICMP_UNREACH_SRCFAIL;
goto bad;
}
- ip_forward(m, 1);
+
+ rcvif = m_get_rcvif_psref(m, &psref);
+ ip_forward(m, 1, rcvif);
+ m_put_rcvif_psref(rcvif, &psref);
return true;
}
return false;
@@ -1186,7 +1208,7 @@ ip_drainstub(void)
* via a source route.
*/
static void
-ip_forward(struct mbuf *m, int srcrt)
+ip_forward(struct mbuf *m, int srcrt, struct ifnet *rcvif)
{
struct ip *ip = mtod(m, struct ip *);
struct rtentry *rt;
@@ -1254,7 +1276,7 @@ ip_forward(struct mbuf *m, int srcrt)
* Also, don't send redirect if forwarding using a default route
* or a route modified by a redirect.
*/
- if (rt->rt_ifp == m->m_pkthdr.rcvif &&
+ if (rt->rt_ifp == rcvif &&
(rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0 &&
!in_nullhost(satocsin(rt_getkey(rt))->sin_addr) &&
ipsendredirects && !srcrt) {
@@ -1360,9 +1382,11 @@ ip_savecontrol(struct inpcb *inp, struct
struct mbuf *m)
{
struct socket *so = inp->inp_socket;
- ifnet_t *ifp = m->m_pkthdr.rcvif;
+ ifnet_t *ifp;
int inpflags = inp->inp_flags;
+ struct psref psref;
+ ifp = m_get_rcvif_psref(m, &psref);
if (so->so_options & SO_TIMESTAMP
#ifdef SO_OTIMESTAMP
|| so->so_options & SO_OTIMESTAMP
@@ -1423,6 +1447,7 @@ ip_savecontrol(struct inpcb *inp, struct
if (*mp)
mp = &(*mp)->m_next;
}
+ m_put_rcvif_psref(ifp, &psref);
}
/*
Index: src/sys/netinet/sctp_input.c
diff -u src/sys/netinet/sctp_input.c:1.2 src/sys/netinet/sctp_input.c:1.3
--- src/sys/netinet/sctp_input.c:1.2 Mon Apr 25 21:21:02 2016
+++ src/sys/netinet/sctp_input.c Fri Jun 10 13:31:44 2016
@@ -1,5 +1,5 @@
/* $KAME: sctp_input.c,v 1.28 2005/04/21 18:36:21 nishida Exp $ */
-/* $NetBSD: sctp_input.c,v 1.2 2016/04/25 21:21:02 rjs Exp $ */
+/* $NetBSD: sctp_input.c,v 1.3 2016/06/10 13:31:44 ozaki-r Exp $ */
/*
* Copyright (C) 2002, 2003, 2004 Cisco Systems Inc,
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sctp_input.c,v 1.2 2016/04/25 21:21:02 rjs Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sctp_input.c,v 1.3 2016/06/10 13:31:44 ozaki-r Exp $");
#ifdef _KERNEL_OPT
#include "opt_ipsec.h"
@@ -4121,7 +4121,7 @@ sctp_input(struct mbuf *m, ...)
sctp_pegs[SCTP_IN_MCAST]++;
goto bad;
}
- if (in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif)) {
+ if (in_broadcast(ip->ip_dst, m_get_rcvif_NOMPSAFE(m))) {
sctp_pegs[SCTP_IN_MCAST]++;
goto bad;
}
@@ -4134,8 +4134,8 @@ sctp_input(struct mbuf *m, ...)
/* validate SCTP checksum */
if ((sctp_no_csum_on_loopback == 0) ||
- (m->m_pkthdr.rcvif == NULL) ||
- (m->m_pkthdr.rcvif->if_type != IFT_LOOP)) {
+ (m_get_rcvif_NOMPSAFE(m) == NULL) ||
+ (m_get_rcvif_NOMPSAFE(m)->if_type != IFT_LOOP)) {
/* we do NOT validate things from the loopback if the
* sysctl is set to 1.
*/
Index: src/sys/netinet/sctp_output.c
diff -u src/sys/netinet/sctp_output.c:1.5 src/sys/netinet/sctp_output.c:1.6
--- src/sys/netinet/sctp_output.c:1.5 Fri Jun 10 13:27:16 2016
+++ src/sys/netinet/sctp_output.c Fri Jun 10 13:31:44 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: sctp_output.c,v 1.5 2016/06/10 13:27:16 ozaki-r Exp $ */
+/* $NetBSD: sctp_output.c,v 1.6 2016/06/10 13:31:44 ozaki-r Exp $ */
/* $KAME: sctp_output.c,v 1.48 2005/06/16 18:29:24 jinmei Exp $ */
/*
@@ -30,7 +30,7 @@
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sctp_output.c,v 1.5 2016/06/10 13:27:16 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sctp_output.c,v 1.6 2016/06/10 13:31:44 ozaki-r Exp $");
#ifdef _KERNEL_OPT
#include "opt_ipsec.h"
@@ -3470,7 +3470,7 @@ sctp_send_initiate_ack(struct sctp_inpcb
/* pull out the scope_id from incoming pkt */
#if defined(SCTP_BASE_FREEBSD) || defined(__APPLE__)
(void)in6_recoverscope(sin6, &in6_src,
- init_pkt->m_pkthdr.rcvif);
+ m_get_rcvif_NOMPSAFE(init_pkt));
in6_embedscope(&sin6->sin6_addr, sin6, NULL,
NULL);
#else
@@ -8104,9 +8104,8 @@ sctp_send_shutdown_complete2(struct mbuf
mout->m_pkthdr.len = mout->m_len;
/* add checksum */
- if ((sctp_no_csum_on_loopback) &&
- (m->m_pkthdr.rcvif) &&
- (m->m_pkthdr.rcvif->if_type == IFT_LOOP)) {
+ if ((sctp_no_csum_on_loopback) && m_get_rcvif_NOMPSAFE(m) != NULL &&
+ m_get_rcvif_NOMPSAFE(m)->if_type == IFT_LOOP) {
comp_cp->sh.checksum = 0;
} else {
comp_cp->sh.checksum = sctp_calculate_sum(mout, NULL, offset_out);
@@ -9046,9 +9045,8 @@ sctp_send_abort(struct mbuf *m, int iphl
}
/* add checksum */
- if ((sctp_no_csum_on_loopback) &&
- (m->m_pkthdr.rcvif) &&
- (m->m_pkthdr.rcvif->if_type == IFT_LOOP)) {
+ if ((sctp_no_csum_on_loopback) && m_get_rcvif_NOMPSAFE(m) != NULL &&
+ m_get_rcvif_NOMPSAFE(m)->if_type == IFT_LOOP) {
abm->sh.checksum = 0;
} else {
abm->sh.checksum = sctp_calculate_sum(mout, NULL, iphlen_out);
@@ -9130,9 +9128,8 @@ sctp_send_operr_to(struct mbuf *m, int i
padlen = 4 - (scm->m_pkthdr.len % 4);
m_copyback(scm, scm->m_pkthdr.len, padlen, (void *)&cpthis);
}
- if ((sctp_no_csum_on_loopback) &&
- (m->m_pkthdr.rcvif) &&
- (m->m_pkthdr.rcvif->if_type == IFT_LOOP)) {
+ if ((sctp_no_csum_on_loopback) && m_get_rcvif_NOMPSAFE(m) != NULL &&
+ m_get_rcvif_NOMPSAFE(m)->if_type == IFT_LOOP) {
val = 0;
} else {
val = sctp_calculate_sum(scm, NULL, 0);
Index: src/sys/netinet/tcp_input.c
diff -u src/sys/netinet/tcp_input.c:1.346 src/sys/netinet/tcp_input.c:1.347
--- src/sys/netinet/tcp_input.c:1.346 Fri Jun 10 13:27:16 2016
+++ src/sys/netinet/tcp_input.c Fri Jun 10 13:31:44 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: tcp_input.c,v 1.346 2016/06/10 13:27:16 ozaki-r Exp $ */
+/* $NetBSD: tcp_input.c,v 1.347 2016/06/10 13:31:44 ozaki-r Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -148,7 +148,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tcp_input.c,v 1.346 2016/06/10 13:27:16 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tcp_input.c,v 1.347 2016/06/10 13:31:44 ozaki-r Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -894,17 +894,21 @@ int
tcp_input_checksum(int af, struct mbuf *m, const struct tcphdr *th,
int toff, int off, int tlen)
{
+ struct ifnet *rcvif;
+ int s;
/*
* XXX it's better to record and check if this mbuf is
* already checked.
*/
+ rcvif = m_get_rcvif(m, &s);
+
switch (af) {
#ifdef INET
case AF_INET:
switch (m->m_pkthdr.csum_flags &
- ((m->m_pkthdr.rcvif->if_csum_flags_rx & M_CSUM_TCPv4) |
+ ((rcvif->if_csum_flags_rx & M_CSUM_TCPv4) |
M_CSUM_TCP_UDP_BAD | M_CSUM_DATA)) {
case M_CSUM_TCPv4|M_CSUM_TCP_UDP_BAD:
TCP_CSUM_COUNTER_INCR(&tcp_hwcsum_bad);
@@ -937,8 +941,7 @@ tcp_input_checksum(int af, struct mbuf *
* Must compute it ourselves. Maybe skip checksum
* on loopback interfaces.
*/
- if (__predict_true(!(m->m_pkthdr.rcvif->if_flags &
- IFF_LOOPBACK) ||
+ if (__predict_true(!(rcvif->if_flags & IFF_LOOPBACK) ||
tcp_do_loopback_cksum)) {
TCP_CSUM_COUNTER_INCR(&tcp_swcsum);
if (in4_cksum(m, IPPROTO_TCP, toff,
@@ -953,7 +956,7 @@ tcp_input_checksum(int af, struct mbuf *
#ifdef INET6
case AF_INET6:
switch (m->m_pkthdr.csum_flags &
- ((m->m_pkthdr.rcvif->if_csum_flags_rx & M_CSUM_TCPv6) |
+ ((rcvif->if_csum_flags_rx & M_CSUM_TCPv6) |
M_CSUM_TCP_UDP_BAD | M_CSUM_DATA)) {
case M_CSUM_TCPv6|M_CSUM_TCP_UDP_BAD:
TCP_CSUM_COUNTER_INCR(&tcp6_hwcsum_bad);
@@ -984,10 +987,12 @@ tcp_input_checksum(int af, struct mbuf *
break;
#endif /* INET6 */
}
+ m_put_rcvif(rcvif, &s);
return 0;
badcsum:
+ m_put_rcvif(rcvif, &s);
TCP_STATINC(TCP_STAT_RCVBADSUM);
return -1;
}
@@ -1548,7 +1553,8 @@ findpcb:
case AF_INET:
mc = (IN_MULTICAST(ip->ip_dst.s_addr)
- || in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif));
+ || in_broadcast(ip->ip_dst,
+ m_get_rcvif_NOMPSAFE(m)));
break;
}
@@ -1747,7 +1753,8 @@ findpcb:
#endif /* INET6 */
case AF_INET:
if (IN_MULTICAST(ip->ip_dst.s_addr) ||
- in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif))
+ in_broadcast(ip->ip_dst,
+ m_get_rcvif_NOMPSAFE(m)))
goto drop;
break;
}
@@ -1790,12 +1797,18 @@ findpcb:
*/
if (af == AF_INET6 && !ip6_use_deprecated) {
struct in6_ifaddr *ia6;
- if ((ia6 = in6ifa_ifpwithaddr(m->m_pkthdr.rcvif,
+ int s;
+ struct ifnet *rcvif = m_get_rcvif(m, &s);
+ if (rcvif == NULL)
+ goto dropwithreset; /* XXX */
+ if ((ia6 = in6ifa_ifpwithaddr(rcvif,
&ip6->ip6_dst)) &&
(ia6->ia6_flags & IN6_IFF_DEPRECATED)) {
tp = NULL;
+ m_put_rcvif(rcvif, &s);
goto dropwithreset;
}
+ m_put_rcvif(rcvif, &s);
}
#endif
@@ -3081,7 +3094,7 @@ dropwithreset:
#endif /* INET6 */
case AF_INET:
if (IN_MULTICAST(ip->ip_dst.s_addr) ||
- in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif))
+ in_broadcast(ip->ip_dst, m_get_rcvif_NOMPSAFE(m)))
goto drop;
}
@@ -4417,7 +4430,7 @@ syn_cache_add(struct sockaddr *src, stru
}
sc->sc_peermaxseg = oi->maxseg;
sc->sc_ourmaxseg = tcp_mss_to_advertise(m->m_flags & M_PKTHDR ?
- m->m_pkthdr.rcvif : NULL,
+ m_get_rcvif_NOMPSAFE(m) : NULL,
sc->sc_src.sa.sa_family);
sc->sc_win = win;
sc->sc_timebase = tcp_now - 1; /* see tcp_newtcpcb() */
Index: src/sys/netinet/udp_usrreq.c
diff -u src/sys/netinet/udp_usrreq.c:1.225 src/sys/netinet/udp_usrreq.c:1.226
--- src/sys/netinet/udp_usrreq.c:1.225 Tue Apr 26 08:44:45 2016
+++ src/sys/netinet/udp_usrreq.c Fri Jun 10 13:31:44 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: udp_usrreq.c,v 1.225 2016/04/26 08:44:45 ozaki-r Exp $ */
+/* $NetBSD: udp_usrreq.c,v 1.226 2016/06/10 13:31:44 ozaki-r Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -66,7 +66,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: udp_usrreq.c,v 1.225 2016/04/26 08:44:45 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: udp_usrreq.c,v 1.226 2016/06/10 13:31:44 ozaki-r Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -276,7 +276,7 @@ udp4_input_checksum(struct mbuf *m, cons
return 0;
switch (m->m_pkthdr.csum_flags &
- ((m->m_pkthdr.rcvif->if_csum_flags_rx & M_CSUM_UDPv4) |
+ ((m_get_rcvif_NOMPSAFE(m)->if_csum_flags_rx & M_CSUM_UDPv4) |
M_CSUM_TCP_UDP_BAD | M_CSUM_DATA)) {
case M_CSUM_UDPv4|M_CSUM_TCP_UDP_BAD:
UDP_CSUM_COUNTER_INCR(&udp_hwcsum_bad);
@@ -309,7 +309,7 @@ udp4_input_checksum(struct mbuf *m, cons
* Need to compute it ourselves. Maybe skip checksum
* on loopback interfaces.
*/
- if (__predict_true(!(m->m_pkthdr.rcvif->if_flags &
+ if (__predict_true(!(m_get_rcvif_NOMPSAFE(m)->if_flags &
IFF_LOOPBACK) ||
udp_do_loopback_cksum)) {
UDP_CSUM_COUNTER_INCR(&udp_swcsum);
@@ -529,7 +529,7 @@ udp4_realinput(struct sockaddr_in *src,
dport = &dst->sin_port;
if (IN_MULTICAST(dst4->s_addr) ||
- in_broadcast(*dst4, m->m_pkthdr.rcvif)) {
+ in_broadcast(*dst4, m_get_rcvif_NOMPSAFE(m))) {
/*
* Deliver a multicast or broadcast datagram to *all* sockets
* for which the local and remote addresses and ports match
Index: src/sys/netinet6/icmp6.c
diff -u src/sys/netinet6/icmp6.c:1.187 src/sys/netinet6/icmp6.c:1.188
--- src/sys/netinet6/icmp6.c:1.187 Fri Jun 10 13:27:16 2016
+++ src/sys/netinet6/icmp6.c Fri Jun 10 13:31:44 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: icmp6.c,v 1.187 2016/06/10 13:27:16 ozaki-r Exp $ */
+/* $NetBSD: icmp6.c,v 1.188 2016/06/10 13:31:44 ozaki-r Exp $ */
/* $KAME: icmp6.c,v 1.217 2001/06/20 15:03:29 jinmei Exp $ */
/*
@@ -62,7 +62,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: icmp6.c,v 1.187 2016/06/10 13:27:16 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: icmp6.c,v 1.188 2016/06/10 13:31:44 ozaki-r Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -453,8 +453,10 @@ icmp6_input(struct mbuf **mp, int *offp,
int off = *offp;
int icmp6len = m->m_pkthdr.len - *offp;
int code, sum, noff, i;
- struct ifnet *rcvif = m->m_pkthdr.rcvif;
+ struct ifnet *rcvif;
+ struct psref psref;
+ rcvif = m_get_rcvif_psref(m, &psref);
#define ICMP6_MAXLEN (sizeof(*nip6) + sizeof(*nicmp6) + 4)
KASSERT(ICMP6_MAXLEN < MCLBYTES);
icmp6_ifstat_inc(rcvif, ifs6_in_msg);
@@ -484,6 +486,7 @@ icmp6_input(struct mbuf **mp, int *offp,
*/
IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off, sizeof(*icmp6));
if (icmp6 == NULL) {
+ m_put_rcvif_psref(rcvif, &psref);
ICMP6_STATINC(ICMP6_STAT_TOOSHORT);
/* m is invalid */
/*icmp6_ifstat_inc(rcvif, ifs6_in_error);*/
@@ -865,6 +868,7 @@ icmp6_input(struct mbuf **mp, int *offp,
deliver:
if (icmp6_notify_error(m, off, icmp6len, code)) {
/* In this case, m should've been freed. */
+ m_put_rcvif_psref(rcvif, &psref);
return (IPPROTO_DONE);
}
break;
@@ -877,6 +881,7 @@ icmp6_input(struct mbuf **mp, int *offp,
ICMP6_STATINC(ICMP6_STAT_BADLEN);
break;
}
+ m_put_rcvif_psref(rcvif, &psref);
/* deliver the packet to appropriate sockets */
icmp6_rip6_input(&m, *offp);
@@ -884,6 +889,7 @@ icmp6_input(struct mbuf **mp, int *offp,
return IPPROTO_DONE;
freeit:
+ m_put_rcvif_psref(rcvif, &psref);
m_freem(m);
return IPPROTO_DONE;
}
@@ -921,6 +927,8 @@ icmp6_notify_error(struct mbuf *m, int o
struct ip6_rthdr *rth;
struct ip6_rthdr0 *rth0;
int rthlen;
+ struct ifnet *rcvif;
+ int s;
while (1) { /* XXX: should avoid infinite loop explicitly? */
struct ip6_ext *eh;
@@ -1034,13 +1042,20 @@ icmp6_notify_error(struct mbuf *m, int o
*/
eip6 = (struct ip6_hdr *)(icmp6 + 1);
+ rcvif = m_get_rcvif(m, &s);
sockaddr_in6_init(&icmp6dst,
(finaldst == NULL) ? &eip6->ip6_dst : finaldst, 0, 0, 0);
- if (in6_setscope(&icmp6dst.sin6_addr, m->m_pkthdr.rcvif, NULL))
+ if (in6_setscope(&icmp6dst.sin6_addr, rcvif, NULL)) {
+ m_put_rcvif(rcvif, &s);
goto freeit;
+ }
sockaddr_in6_init(&icmp6src, &eip6->ip6_src, 0, 0, 0);
- if (in6_setscope(&icmp6src.sin6_addr, m->m_pkthdr.rcvif, NULL))
+ if (in6_setscope(&icmp6src.sin6_addr, rcvif, NULL)) {
+ m_put_rcvif(rcvif, &s);
goto freeit;
+ }
+ m_put_rcvif(rcvif, &s);
+
icmp6src.sin6_flowinfo =
(eip6->ip6_flow & IPV6_FLOWLABEL_MASK);
@@ -1084,6 +1099,8 @@ icmp6_mtudisc_update(struct ip6ctlparam
u_int mtu = ntohl(icmp6->icmp6_mtu);
struct rtentry *rt = NULL;
struct sockaddr_in6 sin6;
+ struct ifnet *rcvif;
+ int s;
/*
* The MTU should not be less than the minimal IPv6 MTU except for the
@@ -1122,8 +1139,13 @@ icmp6_mtudisc_update(struct ip6ctlparam
sin6.sin6_family = PF_INET6;
sin6.sin6_len = sizeof(struct sockaddr_in6);
sin6.sin6_addr = *dst;
- if (in6_setscope(&sin6.sin6_addr, m->m_pkthdr.rcvif, NULL))
+ s = pserialize_read_enter();
+ rcvif = m_get_rcvif(m, &s);
+ if (in6_setscope(&sin6.sin6_addr, rcvif, NULL)) {
+ m_put_rcvif(rcvif, &s);
return;
+ }
+ m_put_rcvif(rcvif, &s);
rt = icmp6_mtudisc_clone((struct sockaddr *)&sin6);
@@ -1175,6 +1197,8 @@ ni6_input(struct mbuf *m, int off)
struct ip6_hdr *ip6;
int oldfqdn = 0; /* if 1, return pascal string (03 draft) */
char *subj = NULL;
+ int s;
+ struct ifnet *rcvif;
ip6 = mtod(m, struct ip6_hdr *);
IP6_EXTHDR_GET(ni6, struct icmp6_nodeinfo *, m, off, sizeof(*ni6));
@@ -1252,8 +1276,12 @@ ni6_input(struct mbuf *m, int off)
/* m_pulldown instead of copy? */
m_copydata(m, off + sizeof(struct icmp6_nodeinfo),
subjlen, (void *)&in6_subj);
- if (in6_setscope(&in6_subj, m->m_pkthdr.rcvif, NULL))
+ rcvif = m_get_rcvif(m, &s);
+ if (in6_setscope(&in6_subj, rcvif, NULL)) {
+ m_put_rcvif(rcvif, &s);
goto bad;
+ }
+ m_put_rcvif(rcvif, &s);
subj = (char *)&in6_subj;
if (IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, &in6_subj))
@@ -1961,6 +1989,8 @@ icmp6_reflect(struct mbuf *m, size_t off
struct ifnet *outif = NULL;
struct in6_addr origdst;
const struct in6_addr *src = NULL;
+ struct ifnet *rcvif;
+ int s;
/* too short to reflect */
if (off < sizeof(struct ip6_hdr)) {
@@ -2077,11 +2107,13 @@ icmp6_reflect(struct mbuf *m, size_t off
ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
ip6->ip6_vfc |= IPV6_VERSION;
ip6->ip6_nxt = IPPROTO_ICMPV6;
- if (m->m_pkthdr.rcvif) {
+ rcvif = m_get_rcvif(m, &s);
+ if (rcvif) {
/* XXX: This may not be the outgoing interface */
- ip6->ip6_hlim = ND_IFINFO(m->m_pkthdr.rcvif)->chlim;
+ ip6->ip6_hlim = ND_IFINFO(rcvif)->chlim;
} else
ip6->ip6_hlim = ip6_defhlim;
+ m_put_rcvif(rcvif, &s);
m->m_pkthdr.csum_flags = 0;
icmp6->icmp6_cksum = 0;
@@ -2100,10 +2132,9 @@ icmp6_reflect(struct mbuf *m, size_t off
* Note that only echo and node information replies are affected,
* since the length of ICMP6 errors is limited to the minimum MTU.
*/
- if (ip6_output(m, NULL, NULL, IPV6_MINMTU, NULL, NULL, &outif) != 0 &&
- outif)
+ if (ip6_output(m, NULL, NULL, IPV6_MINMTU, NULL, NULL, &outif)
+ != 0 && outif)
icmp6_ifstat_inc(outif, ifs6_out_error);
-
if (outif)
icmp6_ifoutstat_inc(outif, type, code);
@@ -2127,7 +2158,7 @@ icmp6_redirect_diag(struct in6_addr *src
void
icmp6_redirect_input(struct mbuf *m, int off)
{
- struct ifnet *ifp = m->m_pkthdr.rcvif;
+ struct ifnet *ifp;
struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
struct nd_redirect *nd_rd;
int icmp6len = ntohs(ip6->ip6_plen);
@@ -2140,7 +2171,9 @@ icmp6_redirect_input(struct mbuf *m, int
struct in6_addr redtgt6;
struct in6_addr reddst6;
union nd_opts ndopts;
+ struct psref psref;
+ ifp = m_get_rcvif_psref(m, &psref);
if (ifp == NULL)
goto freeit;
@@ -2153,6 +2186,7 @@ icmp6_redirect_input(struct mbuf *m, int
IP6_EXTHDR_GET(nd_rd, struct nd_redirect *, m, off, icmp6len);
if (nd_rd == NULL) {
ICMP6_STATINC(ICMP6_STAT_TOOSHORT);
+ m_put_rcvif_psref(ifp, &psref);
return;
}
redtgt6 = nd_rd->nd_rd_target;
@@ -2260,6 +2294,9 @@ icmp6_redirect_input(struct mbuf *m, int
nd6_cache_lladdr(ifp, &redtgt6, lladdr, lladdrlen, ND_REDIRECT,
is_onlink ? ND_REDIRECT_ONLINK : ND_REDIRECT_ROUTER);
+ m_put_rcvif_psref(ifp, &psref);
+ ifp = NULL;
+
if (!is_onlink) { /* better router case. perform rtredirect. */
/* perform rtredirect */
struct sockaddr_in6 sdst;
@@ -2319,10 +2356,13 @@ icmp6_redirect_input(struct mbuf *m, int
}
freeit:
+ if (ifp != NULL)
+ m_put_rcvif_psref(ifp, &psref);
m_freem(m);
return;
bad:
+ m_put_rcvif_psref(ifp, &psref);
ICMP6_STATINC(ICMP6_STAT_BADREDIRECT);
m_freem(m);
}
Index: src/sys/netinet6/in6_gif.c
diff -u src/sys/netinet6/in6_gif.c:1.73 src/sys/netinet6/in6_gif.c:1.74
--- src/sys/netinet6/in6_gif.c:1.73 Mon Feb 29 01:29:15 2016
+++ src/sys/netinet6/in6_gif.c Fri Jun 10 13:31:44 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: in6_gif.c,v 1.73 2016/02/29 01:29:15 knakahara Exp $ */
+/* $NetBSD: in6_gif.c,v 1.74 2016/06/10 13:31:44 ozaki-r Exp $ */
/* $KAME: in6_gif.c,v 1.62 2001/07/29 04:27:25 itojun Exp $ */
/*
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: in6_gif.c,v 1.73 2016/02/29 01:29:15 knakahara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: in6_gif.c,v 1.74 2016/06/10 13:31:44 ozaki-r Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -229,11 +229,15 @@ in6_gif_input(struct mbuf **mp, int *off
return IPPROTO_DONE;
}
- if (!gif_validate6(ip6, sc, m->m_pkthdr.rcvif)) {
+ struct psref psref;
+ struct ifnet *rcvif = m_get_rcvif_psref(m, &psref);
+ if (!gif_validate6(ip6, sc, rcvif)) {
+ m_put_rcvif_psref(rcvif, &psref);
m_freem(m);
IP6_STATINC(IP6_STAT_NOGIF);
return IPPROTO_DONE;
}
+ m_put_rcvif_psref(rcvif, &psref);
#endif
otos = ip6->ip6_flow;
@@ -350,7 +354,7 @@ gif_encapcheck6(struct mbuf *m, int off,
sc = arg;
m_copydata(m, 0, sizeof(ip6), (void *)&ip6);
- ifp = ((m->m_flags & M_PKTHDR) != 0) ? m->m_pkthdr.rcvif : NULL;
+ ifp = ((m->m_flags & M_PKTHDR) != 0) ? m_get_rcvif_NOMPSAFE(m) : NULL;
return gif_validate6(&ip6, sc, ifp);
}
Index: src/sys/netinet6/ip6_forward.c
diff -u src/sys/netinet6/ip6_forward.c:1.78 src/sys/netinet6/ip6_forward.c:1.79
--- src/sys/netinet6/ip6_forward.c:1.78 Mon Aug 24 22:21:27 2015
+++ src/sys/netinet6/ip6_forward.c Fri Jun 10 13:31:44 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: ip6_forward.c,v 1.78 2015/08/24 22:21:27 pooka Exp $ */
+/* $NetBSD: ip6_forward.c,v 1.79 2016/06/10 13:31:44 ozaki-r Exp $ */
/* $KAME: ip6_forward.c,v 1.109 2002/09/11 08:10:17 sakane Exp $ */
/*
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip6_forward.c,v 1.78 2015/08/24 22:21:27 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip6_forward.c,v 1.79 2016/06/10 13:31:44 ozaki-r Exp $");
#ifdef _KERNEL_OPT
#include "opt_gateway.h"
@@ -133,6 +133,8 @@ ip6_forward(struct mbuf *m, int srcrt)
struct ifnet *origifp; /* maybe unnecessary */
uint32_t inzone, outzone;
struct in6_addr src_in6, dst_in6;
+ struct ifnet *rcvif = NULL;
+ struct psref psref;
#ifdef IPSEC
int needipsec = 0;
struct secpolicy *sp = NULL;
@@ -143,6 +145,7 @@ ip6_forward(struct mbuf *m, int srcrt)
*/
m->m_pkthdr.csum_flags = 0;
+ rcvif = m_get_rcvif_psref(m, &psref);
/*
* Do not forward packets to multicast destination (should be handled
* by ip6_mforward().
@@ -152,19 +155,18 @@ ip6_forward(struct mbuf *m, int srcrt)
if ((m->m_flags & (M_BCAST|M_MCAST)) != 0 ||
IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) ||
IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src)) {
- ip6_cantforward(ip6, m->m_pkthdr.rcvif, NULL,
+ ip6_cantforward(ip6, rcvif, NULL,
((m->m_flags & (M_BCAST|M_MCAST)) != 0) ? "bcast/mcast" :
IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) ? "mcast/dst" :
"unspec/src");
- m_freem(m);
- return;
+ goto drop;
}
if (ip6->ip6_hlim <= IPV6_HLIMDEC) {
/* XXX in6_ifstat_inc(rt->rt_ifp, ifs6_in_discard) */
icmp6_error(m, ICMP6_TIME_EXCEEDED,
ICMP6_TIME_EXCEED_TRANSIT, 0);
- return;
+ goto out;
}
ip6->ip6_hlim -= IPV6_HLIMDEC;
@@ -212,8 +214,7 @@ ip6_forward(struct mbuf *m, int srcrt)
icmp6_error(mcopy, ICMP6_DST_UNREACH,
ICMP6_DST_UNREACH_NOROUTE, 0);
}
- m_freem(m);
- return;
+ goto drop;
}
} else if ((rt = rtcache_validate(&ip6_forward_rt)) == NULL &&
(rt = rtcache_update(&ip6_forward_rt, 1)) == NULL) {
@@ -227,8 +228,7 @@ ip6_forward(struct mbuf *m, int srcrt)
icmp6_error(mcopy, ICMP6_DST_UNREACH,
ICMP6_DST_UNREACH_NOROUTE, 0);
}
- m_freem(m);
- return;
+ goto drop;
}
dst = satocsin6(rtcache_getdst(&ip6_forward_rt));
@@ -244,16 +244,15 @@ ip6_forward(struct mbuf *m, int srcrt)
src_in6 = ip6->ip6_src;
inzone = outzone = ~0;
if (in6_setscope(&src_in6, rt->rt_ifp, &outzone) != 0 ||
- in6_setscope(&src_in6, m->m_pkthdr.rcvif, &inzone) != 0 ||
+ in6_setscope(&src_in6, rcvif, &inzone) != 0 ||
inzone != outzone) {
- ip6_cantforward(ip6, m->m_pkthdr.rcvif, rt->rt_ifp,
+ ip6_cantforward(ip6, rcvif, rt->rt_ifp,
"src[%s] inzone %d outzone %d",
in6_getscopename(&ip6->ip6_src), inzone, outzone);
if (mcopy)
icmp6_error(mcopy, ICMP6_DST_UNREACH,
ICMP6_DST_UNREACH_BEYONDSCOPE, 0);
- m_freem(m);
- return;
+ goto drop;
}
#ifdef IPSEC
@@ -279,17 +278,16 @@ ip6_forward(struct mbuf *m, int srcrt)
*/
dst_in6 = ip6->ip6_dst;
inzone = outzone = ~0;
- if (in6_setscope(&dst_in6, m->m_pkthdr.rcvif, &inzone) != 0 ||
+ if (in6_setscope(&dst_in6, rcvif, &inzone) != 0 ||
in6_setscope(&dst_in6, rt->rt_ifp, &outzone) != 0 ||
inzone != outzone) {
- ip6_cantforward(ip6, m->m_pkthdr.rcvif, rt->rt_ifp,
+ ip6_cantforward(ip6, rcvif, rt->rt_ifp,
"dst[%s] inzone %d outzone %d",
in6_getscopename(&ip6->ip6_dst), inzone, outzone);
if (mcopy)
icmp6_error(mcopy, ICMP6_DST_UNREACH,
ICMP6_DST_UNREACH_BEYONDSCOPE, 0);
- m_freem(m);
- return;
+ goto drop;
}
if (m->m_pkthdr.len > IN6_LINKMTU(rt->rt_ifp)) {
@@ -300,8 +298,7 @@ ip6_forward(struct mbuf *m, int srcrt)
mtu = IN6_LINKMTU(rt->rt_ifp);
icmp6_error(mcopy, ICMP6_PACKET_TOO_BIG, 0, mtu);
}
- m_freem(m);
- return;
+ goto drop;
}
if (rt->rt_flags & RTF_GATEWAY)
@@ -316,7 +313,7 @@ ip6_forward(struct mbuf *m, int srcrt)
* Also, don't send redirect if forwarding using a route
* modified by a redirect.
*/
- if (rt->rt_ifp == m->m_pkthdr.rcvif && !srcrt && ip6_sendredirects &&
+ if (rt->rt_ifp == rcvif && !srcrt && ip6_sendredirects &&
(rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0) {
if ((rt->rt_ifp->if_flags & IFF_POINTOPOINT) &&
nd6_is_addr_neighbor(
@@ -339,8 +336,7 @@ ip6_forward(struct mbuf *m, int srcrt)
*/
icmp6_error(mcopy, ICMP6_DST_UNREACH,
ICMP6_DST_UNREACH_ADDR, 0);
- m_freem(m);
- return;
+ goto drop;
}
type = ND_REDIRECT;
}
@@ -373,12 +369,12 @@ ip6_forward(struct mbuf *m, int srcrt)
"src %s, dst %s, nxt %d, rcvif %s, outif %s\n",
ip6_sprintf(&ip6->ip6_src),
ip6_sprintf(&ip6->ip6_dst),
- ip6->ip6_nxt, if_name(m->m_pkthdr.rcvif),
+ ip6->ip6_nxt, if_name(rcvif),
if_name(rt->rt_ifp));
}
/* we can just use rcvif in forwarding. */
- origifp = m->m_pkthdr.rcvif;
+ origifp = rcvif;
}
else
origifp = rt->rt_ifp;
@@ -420,12 +416,12 @@ ip6_forward(struct mbuf *m, int srcrt)
senderr:
if (mcopy == NULL)
- return;
+ goto out;
switch (error) {
case 0:
if (type == ND_REDIRECT) {
icmp6_redirect_output(mcopy, rt);
- return;
+ goto out;
}
goto freecopy;
@@ -447,9 +443,15 @@ ip6_forward(struct mbuf *m, int srcrt)
break;
}
icmp6_error(mcopy, type, code, 0);
- return;
+ goto out;
freecopy:
m_freem(mcopy);
+ goto out;
+ drop:
+ m_freem(m);
+ out:
+ if (rcvif != NULL)
+ m_put_rcvif_psref(rcvif, &psref);
return;
}
Index: src/sys/netinet6/ip6_input.c
diff -u src/sys/netinet6/ip6_input.c:1.159 src/sys/netinet6/ip6_input.c:1.160
--- src/sys/netinet6/ip6_input.c:1.159 Thu May 19 08:53:25 2016
+++ src/sys/netinet6/ip6_input.c Fri Jun 10 13:31:44 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: ip6_input.c,v 1.159 2016/05/19 08:53:25 ozaki-r Exp $ */
+/* $NetBSD: ip6_input.c,v 1.160 2016/06/10 13:31:44 ozaki-r Exp $ */
/* $KAME: ip6_input.c,v 1.188 2001/03/29 05:34:31 itojun Exp $ */
/*
@@ -62,7 +62,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip6_input.c,v 1.159 2016/05/19 08:53:25 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip6_input.c,v 1.160 2016/06/10 13:31:44 ozaki-r Exp $");
#ifdef _KERNEL_OPT
#include "opt_gateway.h"
@@ -217,16 +217,23 @@ ip6intr(void *arg __unused)
mutex_enter(softnet_lock);
while ((m = pktq_dequeue(ip6_pktq)) != NULL) {
- const ifnet_t *ifp = m->m_pkthdr.rcvif;
+ struct psref psref;
+ struct ifnet *rcvif = m_get_rcvif_psref(m, &psref);
+ if (rcvif == NULL) {
+ m_freem(m);
+ continue;
+ }
/*
* Drop the packet if IPv6 is disabled on the interface.
*/
- if ((ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED)) {
+ if ((ND_IFINFO(rcvif)->flags & ND6_IFF_IFDISABLED)) {
+ m_put_rcvif_psref(rcvif, &psref);
m_freem(m);
continue;
}
- ip6_input(m);
+ ip6_input(m, rcvif);
+ m_put_rcvif_psref(rcvif, &psref);
}
mutex_exit(softnet_lock);
}
@@ -234,7 +241,7 @@ ip6intr(void *arg __unused)
extern struct route ip6_forward_rt;
void
-ip6_input(struct mbuf *m)
+ip6_input(struct mbuf *m, struct ifnet *rcvif)
{
struct ip6_hdr *ip6;
int hit, off = sizeof(struct ip6_hdr), nest;
@@ -248,7 +255,6 @@ ip6_input(struct mbuf *m)
struct sockaddr dst;
struct sockaddr_in6 dst6;
} u;
- struct ifnet *rcvif = m->m_pkthdr.rcvif;
/*
* make sure we don't have onion peering information into m_tag.
@@ -1058,8 +1064,7 @@ ip6_savecontrol(struct in6pcb *in6p, str
memcpy(&pi6.ipi6_addr, &ip6->ip6_dst, sizeof(struct in6_addr));
in6_clearscope(&pi6.ipi6_addr); /* XXX */
- pi6.ipi6_ifindex = m->m_pkthdr.rcvif ?
- m->m_pkthdr.rcvif->if_index : 0;
+ pi6.ipi6_ifindex = m->m_pkthdr.rcvif_index;
*mp = sbcreatecontrol((void *) &pi6,
sizeof(struct in6_pktinfo),
IS2292(IPV6_2292PKTINFO, IPV6_PKTINFO), IPPROTO_IPV6);
Index: src/sys/netinet6/ip6_mroute.c
diff -u src/sys/netinet6/ip6_mroute.c:1.109 src/sys/netinet6/ip6_mroute.c:1.110
--- src/sys/netinet6/ip6_mroute.c:1.109 Mon Aug 24 22:21:27 2015
+++ src/sys/netinet6/ip6_mroute.c Fri Jun 10 13:31:44 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: ip6_mroute.c,v 1.109 2015/08/24 22:21:27 pooka Exp $ */
+/* $NetBSD: ip6_mroute.c,v 1.110 2016/06/10 13:31:44 ozaki-r Exp $ */
/* $KAME: ip6_mroute.c,v 1.49 2001/07/25 09:21:18 jinmei Exp $ */
/*
@@ -117,7 +117,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip6_mroute.c,v 1.109 2015/08/24 22:21:27 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip6_mroute.c,v 1.110 2016/06/10 13:31:44 ozaki-r Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -1080,8 +1080,8 @@ ip6_mforward(struct ip6_hdr *ip6, struct
ip6_sprintf(&ip6->ip6_src),
ip6_sprintf(&ip6->ip6_dst),
ip6->ip6_nxt,
- m->m_pkthdr.rcvif ?
- if_name(m->m_pkthdr.rcvif) : "?");
+ m->m_pkthdr.rcvif_index ?
+ if_name(m_get_rcvif_NOMPSAFE(m)) : "?");
}
return 0;
}
@@ -1473,7 +1473,7 @@ ip6_mdq(struct mbuf *m, struct ifnet *if
} /* if wrong iif */
/* If I sourced this packet, it counts as output, else it was input. */
- if (m->m_pkthdr.rcvif == NULL) {
+ if (m->m_pkthdr.rcvif_index == 0) {
/* XXX: is rcvif really NULL when output?? */
mif6table[mifi].m6_pkt_out++;
mif6table[mifi].m6_bytes_out += plen;
@@ -1561,7 +1561,7 @@ phyint_send(struct ip6_hdr *ip6, struct
* Otherwise, we can simply send the packet to the interface
* sending queue.
*/
- if (m->m_pkthdr.rcvif == NULL) {
+ if (m->m_pkthdr.rcvif_index == 0) {
struct ip6_moptions im6o;
im6o.im6o_multicast_ifp = ifp;
Index: src/sys/netinet6/ip6_var.h
diff -u src/sys/netinet6/ip6_var.h:1.64 src/sys/netinet6/ip6_var.h:1.65
--- src/sys/netinet6/ip6_var.h:1.64 Tue Jan 20 21:27:36 2015
+++ src/sys/netinet6/ip6_var.h Fri Jun 10 13:31:44 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: ip6_var.h,v 1.64 2015/01/20 21:27:36 roy Exp $ */
+/* $NetBSD: ip6_var.h,v 1.65 2016/06/10 13:31:44 ozaki-r Exp $ */
/* $KAME: ip6_var.h,v 1.33 2000/06/11 14:59:20 jinmei Exp $ */
/*
@@ -323,7 +323,7 @@ int icmp6_ctloutput(int, struct socket *
struct mbuf;
void ip6_init(void);
-void ip6_input(struct mbuf *);
+void ip6_input(struct mbuf *, struct ifnet *);
const struct ip6aux *ip6_getdstifaddr(struct mbuf *);
void ip6_freepcbopts(struct ip6_pktopts *);
void ip6_freemoptions(struct ip6_moptions *);
Index: src/sys/netinet6/mld6.c
diff -u src/sys/netinet6/mld6.c:1.65 src/sys/netinet6/mld6.c:1.66
--- src/sys/netinet6/mld6.c:1.65 Fri Jun 10 13:27:16 2016
+++ src/sys/netinet6/mld6.c Fri Jun 10 13:31:44 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: mld6.c,v 1.65 2016/06/10 13:27:16 ozaki-r Exp $ */
+/* $NetBSD: mld6.c,v 1.66 2016/06/10 13:31:44 ozaki-r Exp $ */
/* $KAME: mld6.c,v 1.25 2001/01/16 14:14:18 itojun Exp $ */
/*
@@ -102,7 +102,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mld6.c,v 1.65 2016/06/10 13:27:16 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mld6.c,v 1.66 2016/06/10 13:31:44 ozaki-r Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -336,16 +336,18 @@ mld_input(struct mbuf *m, int off)
{
struct ip6_hdr *ip6;
struct mld_hdr *mldh;
- struct ifnet *ifp = m->m_pkthdr.rcvif;
+ struct ifnet *ifp;
struct in6_multi *in6m = NULL;
struct in6_addr mld_addr, all_in6;
struct in6_ifaddr *ia;
u_long timer = 0; /* timer value in the MLD query header */
+ int s;
+ ifp = m_get_rcvif(m, &s);
IP6_EXTHDR_GET(mldh, struct mld_hdr *, m, off, sizeof(*mldh));
if (mldh == NULL) {
ICMP6_STATINC(ICMP6_STAT_TOOSHORT);
- return;
+ goto out_nodrop;
}
/* source address validation */
@@ -375,8 +377,7 @@ mld_input(struct mbuf *m, int off)
"mld_input: src %s is not link-local (grp=%s)\n",
ip6_sprintf(&ip6->ip6_src), ip6_sprintf(&mldh->mld_addr));
#endif
- m_freem(m);
- return;
+ goto out;
}
/*
@@ -385,8 +386,7 @@ mld_input(struct mbuf *m, int off)
mld_addr = mldh->mld_addr;
if (in6_setscope(&mld_addr, ifp, NULL)) {
/* XXX: this should not happen! */
- m_free(m);
- return;
+ goto out;
}
/*
@@ -497,7 +497,10 @@ mld_input(struct mbuf *m, int off)
break;
}
+out:
m_freem(m);
+out_nodrop:
+ m_put_rcvif(ifp, &s);
}
static void
Index: src/sys/netinet6/nd6_nbr.c
diff -u src/sys/netinet6/nd6_nbr.c:1.118 src/sys/netinet6/nd6_nbr.c:1.119
--- src/sys/netinet6/nd6_nbr.c:1.118 Fri Jun 10 13:27:16 2016
+++ src/sys/netinet6/nd6_nbr.c Fri Jun 10 13:31:44 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: nd6_nbr.c,v 1.118 2016/06/10 13:27:16 ozaki-r Exp $ */
+/* $NetBSD: nd6_nbr.c,v 1.119 2016/06/10 13:31:44 ozaki-r Exp $ */
/* $KAME: nd6_nbr.c,v 1.61 2001/02/10 16:06:14 jinmei Exp $ */
/*
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nd6_nbr.c,v 1.118 2016/06/10 13:27:16 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nd6_nbr.c,v 1.119 2016/06/10 13:31:44 ozaki-r Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -96,7 +96,7 @@ static int dad_maxtry = 15; /* max # of
void
nd6_ns_input(struct mbuf *m, int off, int icmp6len)
{
- struct ifnet *ifp = m->m_pkthdr.rcvif;
+ struct ifnet *ifp;
struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
struct nd_neighbor_solicit *nd_ns;
struct in6_addr saddr6 = ip6->ip6_src;
@@ -111,10 +111,16 @@ nd6_ns_input(struct mbuf *m, int off, in
int tlladdr;
union nd_opts ndopts;
const struct sockaddr_dl *proxydl = NULL;
+ struct psref psref;
+
+ ifp = m_get_rcvif_psref(m, &psref);
+ if (ifp == NULL)
+ goto freeit;
IP6_EXTHDR_GET(nd_ns, struct nd_neighbor_solicit *, m, off, icmp6len);
if (nd_ns == NULL) {
ICMP6_STATINC(ICMP6_STAT_TOOSHORT);
+ m_put_rcvif_psref(ifp, &psref);
return;
}
ip6 = mtod(m, struct ip6_hdr *); /* adjust pointer for safety */
@@ -325,6 +331,7 @@ nd6_ns_input(struct mbuf *m, int off, in
(router ? ND_NA_FLAG_ROUTER : 0) | ND_NA_FLAG_SOLICITED,
tlladdr, (const struct sockaddr *)proxydl);
freeit:
+ m_put_rcvif_psref(ifp, &psref);
m_freem(m);
return;
@@ -333,6 +340,7 @@ nd6_ns_input(struct mbuf *m, int off, in
nd6log(LOG_ERR, "dst=%s\n", ip6_sprintf(&daddr6));
nd6log(LOG_ERR, "tgt=%s\n", ip6_sprintf(&taddr6));
ICMP6_STATINC(ICMP6_STAT_BADNS);
+ m_put_rcvif_psref(ifp, &psref);
m_freem(m);
}
@@ -532,7 +540,7 @@ nd6_ns_output(struct ifnet *ifp, const s
void
nd6_na_input(struct mbuf *m, int off, int icmp6len)
{
- struct ifnet *ifp = m->m_pkthdr.rcvif;
+ struct ifnet *ifp;
struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
struct nd_neighbor_advert *nd_na;
struct in6_addr saddr6 = ip6->ip6_src;
@@ -550,6 +558,11 @@ nd6_na_input(struct mbuf *m, int off, in
struct sockaddr_in6 ssin6;
int rt_announce;
bool checklink = false;
+ struct psref psref;
+
+ ifp = m_get_rcvif_psref(m, &psref);
+ if (ifp == NULL)
+ goto freeit;
if (ip6->ip6_hlim != 255) {
nd6log(LOG_ERR,
@@ -561,6 +574,7 @@ nd6_na_input(struct mbuf *m, int off, in
IP6_EXTHDR_GET(nd_na, struct nd_neighbor_advert *, m, off, icmp6len);
if (nd_na == NULL) {
+ m_put_rcvif_psref(ifp, &psref);
ICMP6_STATINC(ICMP6_STAT_TOOSHORT);
return;
}
@@ -571,8 +585,10 @@ nd6_na_input(struct mbuf *m, int off, in
is_override = ((flags & ND_NA_FLAG_OVERRIDE) != 0);
taddr6 = nd_na->nd_na_target;
- if (in6_setscope(&taddr6, ifp, NULL))
+ if (in6_setscope(&taddr6, ifp, NULL)) {
+ m_put_rcvif_psref(ifp, &psref);
return; /* XXX: impossible */
+ }
if (IN6_IS_ADDR_MULTICAST(&taddr6)) {
nd6log(LOG_ERR, "invalid target address %s\n",
@@ -815,6 +831,7 @@ nd6_na_input(struct mbuf *m, int off, in
if (checklink)
pfxlist_onlink_check();
+ m_put_rcvif_psref(ifp, &psref);
m_freem(m);
return;
@@ -823,6 +840,7 @@ nd6_na_input(struct mbuf *m, int off, in
LLE_WUNLOCK(ln);
ICMP6_STATINC(ICMP6_STAT_BADNA);
+ m_put_rcvif_psref(ifp, &psref);
m_freem(m);
}
Index: src/sys/netinet6/nd6_rtr.c
diff -u src/sys/netinet6/nd6_rtr.c:1.110 src/sys/netinet6/nd6_rtr.c:1.111
--- src/sys/netinet6/nd6_rtr.c:1.110 Tue Apr 26 08:44:45 2016
+++ src/sys/netinet6/nd6_rtr.c Fri Jun 10 13:31:44 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: nd6_rtr.c,v 1.110 2016/04/26 08:44:45 ozaki-r Exp $ */
+/* $NetBSD: nd6_rtr.c,v 1.111 2016/06/10 13:31:44 ozaki-r Exp $ */
/* $KAME: nd6_rtr.c,v 1.95 2001/02/07 08:09:47 itojun Exp $ */
/*
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nd6_rtr.c,v 1.110 2016/04/26 08:44:45 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nd6_rtr.c,v 1.111 2016/06/10 13:31:44 ozaki-r Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -131,14 +131,21 @@ nd6_is_llinfo_probreach(struct nd_defrou
void
nd6_rs_input(struct mbuf *m, int off, int icmp6len)
{
- struct ifnet *ifp = m->m_pkthdr.rcvif;
- struct nd_ifinfo *ndi = ND_IFINFO(ifp);
+ struct ifnet *ifp;
+ struct nd_ifinfo *ndi;
struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
struct nd_router_solicit *nd_rs;
struct in6_addr saddr6 = ip6->ip6_src;
char *lladdr = NULL;
int lladdrlen = 0;
union nd_opts ndopts;
+ struct psref psref;
+
+ ifp = m_get_rcvif_psref(m, &psref);
+ if (ifp == NULL)
+ goto freeit;
+
+ ndi = ND_IFINFO(ifp);
/* If I'm not a router, ignore it. */
if (nd6_accepts_rtadv(ndi) || !ip6_forwarding)
@@ -188,11 +195,13 @@ nd6_rs_input(struct mbuf *m, int off, in
nd6_cache_lladdr(ifp, &saddr6, lladdr, lladdrlen, ND_ROUTER_SOLICIT, 0);
freeit:
+ m_put_rcvif_psref(ifp, &psref);
m_freem(m);
return;
bad:
ICMP6_STATINC(ICMP6_STAT_BADRS);
+ m_put_rcvif_psref(ifp, &psref);
m_freem(m);
}
@@ -206,8 +215,8 @@ nd6_rs_input(struct mbuf *m, int off, in
void
nd6_ra_input(struct mbuf *m, int off, int icmp6len)
{
- struct ifnet *ifp = m->m_pkthdr.rcvif;
- struct nd_ifinfo *ndi = ND_IFINFO(ifp);
+ struct ifnet *ifp;
+ struct nd_ifinfo *ndi;
struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
struct nd_router_advert *nd_ra;
struct in6_addr saddr6 = ip6->ip6_src;
@@ -220,7 +229,13 @@ nd6_ra_input(struct mbuf *m, int off, in
int mcast = 0;
union nd_opts ndopts;
struct nd_defrouter *dr;
+ struct psref psref;
+
+ ifp = m_get_rcvif_psref(m, &psref);
+ if (ifp == NULL)
+ goto freeit;
+ ndi = ND_IFINFO(ifp);
/*
* We only accept RAs when
* the system-wide variable allows the acceptance, and the
@@ -245,6 +260,7 @@ nd6_ra_input(struct mbuf *m, int off, in
IP6_EXTHDR_GET(nd_ra, struct nd_router_advert *, m, off, icmp6len);
if (nd_ra == NULL) {
ICMP6_STATINC(ICMP6_STAT_TOOSHORT);
+ m_put_rcvif_psref(ifp, &psref);
return;
}
@@ -335,7 +351,7 @@ nd6_ra_input(struct mbuf *m, int off, in
memset(&prc, 0, sizeof(prc));
sockaddr_in6_init(&prc.ndprc_prefix,
&pi->nd_opt_pi_prefix, 0, 0, 0);
- prc.ndprc_ifp = (struct ifnet *)m->m_pkthdr.rcvif;
+ prc.ndprc_ifp = ifp;
prc.ndprc_raf_onlink = (pi->nd_opt_pi_flags_reserved &
ND_OPT_PI_FLAG_ONLINK) ? 1 : 0;
@@ -415,11 +431,13 @@ nd6_ra_input(struct mbuf *m, int off, in
}
freeit:
+ m_put_rcvif_psref(ifp, &psref);
m_freem(m);
return;
bad:
ICMP6_STATINC(ICMP6_STAT_BADRA);
+ m_put_rcvif_psref(ifp, &psref);
m_freem(m);
}
Index: src/sys/netinet6/raw_ip6.c
diff -u src/sys/netinet6/raw_ip6.c:1.143 src/sys/netinet6/raw_ip6.c:1.144
--- src/sys/netinet6/raw_ip6.c:1.143 Thu May 12 02:24:17 2016
+++ src/sys/netinet6/raw_ip6.c Fri Jun 10 13:31:44 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: raw_ip6.c,v 1.143 2016/05/12 02:24:17 ozaki-r Exp $ */
+/* $NetBSD: raw_ip6.c,v 1.144 2016/06/10 13:31:44 ozaki-r Exp $ */
/* $KAME: raw_ip6.c,v 1.82 2001/07/23 18:57:56 jinmei Exp $ */
/*
@@ -62,7 +62,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: raw_ip6.c,v 1.143 2016/05/12 02:24:17 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: raw_ip6.c,v 1.144 2016/06/10 13:31:44 ozaki-r Exp $");
#ifdef _KERNEL_OPT
#include "opt_ipsec.h"
@@ -260,8 +260,11 @@ rip6_input(struct mbuf **mp, int *offp,
if (proto == IPPROTO_NONE)
m_freem(m);
else {
+ int s;
+ struct ifnet *rcvif = m_get_rcvif(m, &s);
u_int8_t *prvnxtp = ip6_get_prevhdr(m, *offp); /* XXX */
- in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_protounknown);
+ in6_ifstat_inc(rcvif, ifs6_in_protounknown);
+ m_put_rcvif(rcvif, &s);
icmp6_error(m, ICMP6_PARAM_PROB,
ICMP6_PARAMPROB_NEXTHEADER,
prvnxtp - mtod(m, u_int8_t *));
@@ -384,6 +387,9 @@ rip6_output(struct mbuf *m, struct socke
int type, code; /* for ICMPv6 output statistics only */
int scope_ambiguous = 0;
struct in6_addr *in6a;
+ int bound = curlwp->l_pflag & LP_BOUND;
+
+ curlwp->l_pflag |= LP_BOUND;
in6p = sotoin6pcb(so);
@@ -444,8 +450,7 @@ rip6_output(struct mbuf *m, struct socke
* Source address selection.
*/
if ((in6a = in6_selectsrc(dstsock, optp, in6p->in6p_moptions,
- &in6p->in6p_route, &in6p->in6p_laddr, &oifp,
- &error)) == 0) {
+ &in6p->in6p_route, &in6p->in6p_laddr, &oifp, &error)) == 0) {
if (error == 0)
error = EADDRNOTAVAIL;
goto bad;
@@ -507,14 +512,18 @@ rip6_output(struct mbuf *m, struct socke
}
}
- error = ip6_output(m, optp, &in6p->in6p_route, 0,
- in6p->in6p_moptions, so, &oifp);
- if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) {
- if (oifp)
- icmp6_ifoutstat_inc(oifp, type, code);
- ICMP6_STATINC(ICMP6_STAT_OUTHIST + type);
- } else
- RIP6_STATINC(RIP6_STAT_OPACKETS);
+ {
+ struct ifnet *ret_oifp = NULL;
+
+ error = ip6_output(m, optp, &in6p->in6p_route, 0,
+ in6p->in6p_moptions, so, &ret_oifp);
+ if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) {
+ if (ret_oifp)
+ icmp6_ifoutstat_inc(ret_oifp, type, code);
+ ICMP6_STATINC(ICMP6_STAT_OUTHIST + type);
+ } else
+ RIP6_STATINC(RIP6_STAT_OPACKETS);
+ }
goto freectl;
@@ -527,6 +536,7 @@ rip6_output(struct mbuf *m, struct socke
ip6_clearpktopts(&opt, -1);
m_freem(control);
}
+ curlwp->l_pflag ^= bound ^ LP_BOUND;
return error;
}
@@ -736,17 +746,18 @@ rip6_connect(struct socket *so, struct s
&in6p->in6p_laddr, &ifp, &error);
if (in6a == NULL) {
if (error == 0)
- return EADDRNOTAVAIL;
- return error;
+ error = EADDRNOTAVAIL;
+ goto out;
}
/* XXX: see above */
if (ifp && scope_ambiguous &&
(error = in6_setscope(&addr->sin6_addr, ifp, NULL)) != 0) {
- return error;
+ goto out;
}
in6p->in6p_laddr = *in6a;
in6p->in6p_faddr = addr->sin6_addr;
soisconnected(so);
+out:
return error;
}
Index: src/sys/netinet6/sctp6_usrreq.c
diff -u src/sys/netinet6/sctp6_usrreq.c:1.4 src/sys/netinet6/sctp6_usrreq.c:1.5
--- src/sys/netinet6/sctp6_usrreq.c:1.4 Mon Apr 25 21:21:02 2016
+++ src/sys/netinet6/sctp6_usrreq.c Fri Jun 10 13:31:44 2016
@@ -1,5 +1,5 @@
/* $KAME: sctp6_usrreq.c,v 1.38 2005/08/24 08:08:56 suz Exp $ */
-/* $NetBSD: sctp6_usrreq.c,v 1.4 2016/04/25 21:21:02 rjs Exp $ */
+/* $NetBSD: sctp6_usrreq.c,v 1.5 2016/06/10 13:31:44 ozaki-r Exp $ */
/*
* Copyright (c) 2001, 2002, 2003, 2004 Cisco Systems, Inc.
@@ -33,7 +33,7 @@
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sctp6_usrreq.c,v 1.4 2016/04/25 21:21:02 rjs Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sctp6_usrreq.c,v 1.5 2016/06/10 13:31:44 ozaki-r Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -160,8 +160,8 @@ sctp6_input(struct mbuf **mp, int *offp,
if (sh->dest_port == 0)
goto bad;
if ((sctp_no_csum_on_loopback == 0) ||
- (m->m_pkthdr.rcvif == NULL) ||
- (m->m_pkthdr.rcvif->if_type != IFT_LOOP)) {
+ (m_get_rcvif_NOMPSAFE(m) == NULL) ||
+ (m_get_rcvif_NOMPSAFE(m)->if_type != IFT_LOOP)) {
/* we do NOT validate things from the loopback if the
* sysctl is set to 1.
*/
Index: src/sys/netinet6/udp6_output.c
diff -u src/sys/netinet6/udp6_output.c:1.50 src/sys/netinet6/udp6_output.c:1.51
--- src/sys/netinet6/udp6_output.c:1.50 Mon Aug 24 22:21:27 2015
+++ src/sys/netinet6/udp6_output.c Fri Jun 10 13:31:44 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: udp6_output.c,v 1.50 2015/08/24 22:21:27 pooka Exp $ */
+/* $NetBSD: udp6_output.c,v 1.51 2016/06/10 13:31:44 ozaki-r Exp $ */
/* $KAME: udp6_output.c,v 1.43 2001/10/15 09:19:52 itojun Exp $ */
/*
@@ -62,7 +62,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: udp6_output.c,v 1.50 2015/08/24 22:21:27 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: udp6_output.c,v 1.51 2016/06/10 13:31:44 ozaki-r Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -232,9 +232,8 @@ udp6_output(struct in6pcb * const in6p,
&in6p->in6p_laddr, &oifp, &error);
if (oifp && scope_ambiguous &&
(error = in6_setscope(&sin6->sin6_addr,
- oifp, NULL))) {
+ oifp, NULL)))
goto release;
- }
} else {
/*
* XXX: freebsd[34] does not have in_selectsrc, but
Index: src/sys/netinet6/udp6_usrreq.c
diff -u src/sys/netinet6/udp6_usrreq.c:1.122 src/sys/netinet6/udp6_usrreq.c:1.123
--- src/sys/netinet6/udp6_usrreq.c:1.122 Tue Apr 26 08:44:45 2016
+++ src/sys/netinet6/udp6_usrreq.c Fri Jun 10 13:31:44 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: udp6_usrreq.c,v 1.122 2016/04/26 08:44:45 ozaki-r Exp $ */
+/* $NetBSD: udp6_usrreq.c,v 1.123 2016/06/10 13:31:44 ozaki-r Exp $ */
/* $KAME: udp6_usrreq.c,v 1.86 2001/05/27 17:33:00 itojun Exp $ */
/*
@@ -62,7 +62,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: udp6_usrreq.c,v 1.122 2016/04/26 08:44:45 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: udp6_usrreq.c,v 1.123 2016/06/10 13:31:44 ozaki-r Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -519,7 +519,7 @@ udp6_input_checksum(struct mbuf *m, cons
}
switch (m->m_pkthdr.csum_flags &
- ((m->m_pkthdr.rcvif->if_csum_flags_rx & M_CSUM_UDPv6) |
+ ((m_get_rcvif_NOMPSAFE(m)->if_csum_flags_rx & M_CSUM_UDPv6) |
M_CSUM_TCP_UDP_BAD | M_CSUM_DATA)) {
case M_CSUM_UDPv6|M_CSUM_TCP_UDP_BAD:
UDP_CSUM_COUNTER_INCR(&udp6_hwcsum_bad);
Index: src/sys/netipsec/ipsec_input.c
diff -u src/sys/netipsec/ipsec_input.c:1.35 src/sys/netipsec/ipsec_input.c:1.36
--- src/sys/netipsec/ipsec_input.c:1.35 Thu Jan 21 15:41:30 2016
+++ src/sys/netipsec/ipsec_input.c Fri Jun 10 13:31:44 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: ipsec_input.c,v 1.35 2016/01/21 15:41:30 riastradh Exp $ */
+/* $NetBSD: ipsec_input.c,v 1.36 2016/06/10 13:31:44 ozaki-r Exp $ */
/* $FreeBSD: /usr/local/www/cvsroot/FreeBSD/src/sys/netipsec/ipsec_input.c,v 1.2.4.2 2003/03/28 20:32:53 sam Exp $ */
/* $OpenBSD: ipsec_input.c,v 1.63 2003/02/20 18:35:43 deraadt Exp $ */
@@ -39,7 +39,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ipsec_input.c,v 1.35 2016/01/21 15:41:30 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ipsec_input.c,v 1.36 2016/06/10 13:31:44 ozaki-r Exp $");
/*
* IPsec input processing.
@@ -769,7 +769,8 @@ ipsec6_common_input_cb(struct mbuf *m, s
*/
if (m->m_pkthdr.len < skip) {
IP6_STATINC(IP6_STAT_TOOSHORT);
- in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated);
+ in6_ifstat_inc(m_get_rcvif_NOMPSAFE(m),
+ ifs6_in_truncated);
error = EINVAL;
goto bad;
}
Index: src/sys/netipsec/key_debug.c
diff -u src/sys/netipsec/key_debug.c:1.12 src/sys/netipsec/key_debug.c:1.13
--- src/sys/netipsec/key_debug.c:1.12 Mon Mar 30 03:51:50 2015
+++ src/sys/netipsec/key_debug.c Fri Jun 10 13:31:44 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: key_debug.c,v 1.12 2015/03/30 03:51:50 ozaki-r Exp $ */
+/* $NetBSD: key_debug.c,v 1.13 2016/06/10 13:31:44 ozaki-r Exp $ */
/* $FreeBSD: src/sys/netipsec/key_debug.c,v 1.1.4.1 2003/01/24 05:11:36 sam Exp $ */
/* $KAME: key_debug.c,v 1.26 2001/06/27 10:46:50 sakane Exp $ */
@@ -33,7 +33,7 @@
#ifdef _KERNEL
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: key_debug.c,v 1.12 2015/03/30 03:51:50 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: key_debug.c,v 1.13 2016/06/10 13:31:44 ozaki-r Exp $");
#endif
#include "opt_inet.h"
@@ -620,7 +620,7 @@ kdebug_mbufhdr(const struct mbuf *m)
if (m->m_flags & M_PKTHDR) {
printf(" m_pkthdr{ len:%d rcvif:%p }\n",
- m->m_pkthdr.len, m->m_pkthdr.rcvif);
+ m->m_pkthdr.len, m_get_rcvif_NOMPSAFE(m));
}
if (m->m_flags & M_EXT) {
Index: src/sys/netipsec/xform_ipip.c
diff -u src/sys/netipsec/xform_ipip.c:1.38 src/sys/netipsec/xform_ipip.c:1.39
--- src/sys/netipsec/xform_ipip.c:1.38 Thu May 12 02:24:17 2016
+++ src/sys/netipsec/xform_ipip.c Fri Jun 10 13:31:44 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: xform_ipip.c,v 1.38 2016/05/12 02:24:17 ozaki-r Exp $ */
+/* $NetBSD: xform_ipip.c,v 1.39 2016/06/10 13:31:44 ozaki-r Exp $ */
/* $FreeBSD: src/sys/netipsec/xform_ipip.c,v 1.3.2.1 2003/01/24 05:11:36 sam Exp $ */
/* $OpenBSD: ip_ipip.c,v 1.25 2002/06/10 18:04:55 itojun Exp $ */
@@ -39,7 +39,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: xform_ipip.c,v 1.38 2016/05/12 02:24:17 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xform_ipip.c,v 1.39 2016/06/10 13:31:44 ozaki-r Exp $");
/*
* IP-inside-IP processing
@@ -330,8 +330,8 @@ _ipip_input(struct mbuf *m, int iphlen,
}
/* Check for local address spoofing. */
- if ((m->m_pkthdr.rcvif == NULL ||
- !(m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK)) &&
+ if ((m_get_rcvif_NOMPSAFE(m) == NULL ||
+ !(m_get_rcvif_NOMPSAFE(m)->if_flags & IFF_LOOPBACK)) &&
ipip_allow != 2) {
int s = pserialize_read_enter();
IFNET_READER_FOREACH(ifp) {
Index: src/sys/netmpls/mpls_ttl.c
diff -u src/sys/netmpls/mpls_ttl.c:1.7 src/sys/netmpls/mpls_ttl.c:1.8
--- src/sys/netmpls/mpls_ttl.c:1.7 Fri Jun 10 13:27:16 2016
+++ src/sys/netmpls/mpls_ttl.c Fri Jun 10 13:31:44 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: mpls_ttl.c,v 1.7 2016/06/10 13:27:16 ozaki-r Exp $ */
+/* $NetBSD: mpls_ttl.c,v 1.8 2016/06/10 13:31:44 ozaki-r Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -97,7 +97,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mpls_ttl.c,v 1.7 2016/06/10 13:27:16 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mpls_ttl.c,v 1.8 2016/06/10 13:31:44 ozaki-r Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -311,7 +311,7 @@ mpls_icmp_error(struct mbuf *n, int type
m->m_data -= sizeof(struct ip);
m->m_len += sizeof(struct ip);
m->m_pkthdr.len = m->m_len;
- m_set_rcvif(m, n->m_pkthdr.rcvif);
+ m_copy_rcvif(m, n);
nip = mtod(m, struct ip *);
/* ip_v set in ip_output */
nip->ip_hl = sizeof(struct ip) >> 2;
Index: src/sys/netnatm/natm.c
diff -u src/sys/netnatm/natm.c:1.51 src/sys/netnatm/natm.c:1.52
--- src/sys/netnatm/natm.c:1.51 Fri Jun 10 13:27:16 2016
+++ src/sys/netnatm/natm.c Fri Jun 10 13:31:44 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: natm.c,v 1.51 2016/06/10 13:27:16 ozaki-r Exp $ */
+/* $NetBSD: natm.c,v 1.52 2016/06/10 13:31:44 ozaki-r Exp $ */
/*
* Copyright (c) 1996 Charles D. Cranor and Washington University.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: natm.c,v 1.51 2016/06/10 13:27:16 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: natm.c,v 1.52 2016/06/10 13:31:44 ozaki-r Exp $");
#include <sys/param.h>
#include <sys/kmem.h>
@@ -457,7 +457,7 @@ next:
panic("natmintr no HDR");
#endif
- npcb = (struct natmpcb *) m->m_pkthdr.rcvif; /* XXX: overloaded */
+ npcb = (struct natmpcb *) m_get_rcvif_NOMPSAFE(m); /* XXX: overloaded */
so = npcb->npcb_socket;
s = splnet(); /* could have atm devs @ different levels */
Index: src/sys/sys/mbuf.h
diff -u src/sys/sys/mbuf.h:1.163 src/sys/sys/mbuf.h:1.164
--- src/sys/sys/mbuf.h:1.163 Fri Jun 10 13:27:17 2016
+++ src/sys/sys/mbuf.h Fri Jun 10 13:31:45 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: mbuf.h,v 1.163 2016/06/10 13:27:17 ozaki-r Exp $ */
+/* $NetBSD: mbuf.h,v 1.164 2016/06/10 13:31:45 ozaki-r Exp $ */
/*-
* Copyright (c) 1996, 1997, 1999, 2001, 2007 The NetBSD Foundation, Inc.
@@ -76,6 +76,7 @@
#if defined(_KERNEL)
#include <sys/percpu_types.h>
#include <sys/socket.h> /* for AF_UNSPEC */
+#include <sys/psref.h>
#endif /* defined(_KERNEL) */
/* For offsetof() */
@@ -87,6 +88,8 @@
#include <uvm/uvm_param.h> /* for MIN_PAGE_SIZE */
+#include <net/if.h>
+
/*
* Mbufs are of a single size, MSIZE (machine/param.h), which
* includes overhead. An mbuf may add a single "mbuf cluster" of size
@@ -175,7 +178,11 @@ struct m_hdr {
* LP64: 56
*/
struct pkthdr {
- struct ifnet *rcvif; /* rcv interface */
+ union {
+ void *ctx; /* for M_GETCTX/M_SETCTX */
+ uint16_t index; /* rcv interface index */
+ } _rcvif;
+#define rcvif_index _rcvif.index
SLIST_HEAD(packet_tags, m_tag) tags; /* list of packet tags */
int len; /* total packet length */
int csum_flags; /* checksum flags */
@@ -710,11 +717,10 @@ do { \
#define m_copy(m, o, l) m_copym((m), (o), (l), M_DONTWAIT)
/*
- * Allow drivers and/or protocols to use the rcvif member of
- * PKTHDR mbufs to store private context information.
+ * Allow drivers and/or protocols to store private context information.
*/
-#define M_GETCTX(m, t) ((t)(m)->m_pkthdr.rcvif)
-#define M_SETCTX(m, c) ((void)((m)->m_pkthdr.rcvif = (void *)(c)))
+#define M_GETCTX(m, t) ((t)(m)->m_pkthdr._rcvif.ctx)
+#define M_SETCTX(m, c) ((void)((m)->m_pkthdr._rcvif.ctx = (void *)(c)))
#define M_CLEARCTX(m) M_SETCTX((m), NULL)
#endif /* defined(_KERNEL) */
@@ -964,17 +970,24 @@ m_hdr_init(struct mbuf *m, short type, s
}
static __inline void
-m_set_rcvif(struct mbuf *m, struct ifnet *ifp)
+m_set_rcvif(struct mbuf *m, const struct ifnet *ifp)
{
- m->m_pkthdr.rcvif = ifp;
+ m->m_pkthdr.rcvif_index = ifp->if_index;
}
static __inline void
m_reset_rcvif(struct mbuf *m)
{
- m_set_rcvif(m, NULL);
+ m->m_pkthdr.rcvif_index = 0;
+}
+
+static __inline void
+m_copy_rcvif(struct mbuf *m, const struct mbuf *n)
+{
+
+ m->m_pkthdr.rcvif_index = n->m_pkthdr.rcvif_index;
}
static __inline void
@@ -1000,5 +1013,63 @@ m_pkthdr_init(struct mbuf *m)
void m_print(const struct mbuf *, const char *, void (*)(const char *, ...)
__printflike(1, 2));
+/*
+ * Get rcvif of a mbuf.
+ *
+ * The caller must call m_put_rcvif after using rcvif. The caller cannot
+ * block or sleep during using rcvif. Insofar as the constraint is satisfied,
+ * the API ensures a got rcvif isn't be freed until m_put_rcvif is called.
+ */
+static __inline struct ifnet *
+m_get_rcvif(const struct mbuf *m, int *s)
+{
+
+ *s = pserialize_read_enter();
+ return if_byindex(m->m_pkthdr.rcvif_index);
+}
+
+static __inline void
+m_put_rcvif(struct ifnet *ifp, int *s)
+{
+
+ if (ifp == NULL)
+ return;
+ pserialize_read_exit(*s);
+}
+
+/*
+ * Get rcvif of a mbuf.
+ *
+ * The caller must call m_put_rcvif_psref after using rcvif. The API ensures
+ * a got rcvif isn't be freed until m_put_rcvif_psref is called.
+ */
+static __inline struct ifnet *
+m_get_rcvif_psref(const struct mbuf *m, struct psref *psref)
+{
+
+ return if_get_byindex(m->m_pkthdr.rcvif_index, psref);
+}
+
+static __inline void
+m_put_rcvif_psref(struct ifnet *ifp, struct psref *psref)
+{
+
+ if (ifp == NULL)
+ return;
+ if_put(ifp, psref);
+}
+
+/*
+ * Get rcvif of a mbuf.
+ *
+ * This is NOT an MP-safe API and shouldn't be used at where we want MP-safe.
+ */
+static __inline struct ifnet *
+m_get_rcvif_NOMPSAFE(const struct mbuf *m)
+{
+
+ return if_byindex(m->m_pkthdr.rcvif_index);
+}
+
#endif /* _KERNEL */
#endif /* !_SYS_MBUF_H_ */