Index: conf/GENERIC =================================================================== RCS file: /cvs/src/sys/conf/GENERIC,v retrieving revision 1.271 diff -u -p -r1.271 GENERIC --- conf/GENERIC 23 Jun 2020 23:35:39 -0000 1.271 +++ conf/GENERIC 24 Jul 2020 10:22:14 -0000 @@ -82,6 +82,7 @@ pseudo-device msts 1 # MSTS line discipl pseudo-device endrun 1 # EndRun line discipline pseudo-device vnd 4 # vnode disk devices pseudo-device ksyms 1 # kernel symbols device +pseudo-device kstat # kernel statistics #pseudo-device dt # Dynamic Tracer # clonable devices Index: kern/uipc_mbuf.c =================================================================== RCS file: /cvs/src/sys/kern/uipc_mbuf.c,v retrieving revision 1.275 diff -u -p -r1.275 uipc_mbuf.c --- kern/uipc_mbuf.c 21 Jun 2020 05:37:26 -0000 1.275 +++ kern/uipc_mbuf.c 24 Jul 2020 10:22:14 -0000 @@ -1573,6 +1573,17 @@ ml_enqueue(struct mbuf_list *ml, struct } void +ml_requeue(struct mbuf_list *ml, struct mbuf *m) +{ + m->m_nextpkt = ml->ml_head; + ml->ml_head = m; + if (ml->ml_tail == NULL) + ml->ml_tail = m; + + ml->ml_len++; +} + +void ml_enlist(struct mbuf_list *mla, struct mbuf_list *mlb) { if (!ml_empty(mlb)) { Index: net/bpf.h =================================================================== RCS file: /cvs/src/sys/net/bpf.h,v retrieving revision 1.69 diff -u -p -r1.69 bpf.h --- net/bpf.h 18 Jun 2020 23:27:58 -0000 1.69 +++ net/bpf.h 24 Jul 2020 10:22:15 -0000 @@ -237,6 +237,7 @@ struct bpf_hdr { #define BPF_MEM 0x60 #define BPF_LEN 0x80 #define BPF_MSH 0xa0 +#define BPF_RND 0xc0 /* alu/jmp fields */ #define BPF_OP(code) ((code) & 0xf0) Index: net/bpf_filter.c =================================================================== RCS file: /cvs/src/sys/net/bpf_filter.c,v retrieving revision 1.33 diff -u -p -r1.33 bpf_filter.c --- net/bpf_filter.c 8 Sep 2017 05:36:53 -0000 1.33 +++ net/bpf_filter.c 24 Jul 2020 10:22:15 -0000 @@ -199,6 +199,10 @@ _bpf_filter(const struct bpf_insn *pc, c X = wirelen; continue; + case BPF_LD|BPF_W|BPF_RND: + A = arc4random(); + continue; + case BPF_LD|BPF_W|BPF_IND: k = X + pc->k; A = ops->ldw(pkt, k, &err); @@ -414,6 +418,7 @@ bpf_validate(struct bpf_insn *f, int len return 0; break; case BPF_LEN: + case BPF_RND: break; default: return 0; Index: net/if.c =================================================================== RCS file: /cvs/src/sys/net/if.c,v retrieving revision 1.615 diff -u -p -r1.615 if.c --- net/if.c 22 Jul 2020 02:16:01 -0000 1.615 +++ net/if.c 24 Jul 2020 10:22:15 -0000 @@ -195,17 +195,20 @@ void if_map_dtor(void *, void *); struct ifnet *if_ref(struct ifnet *); /* - * struct if_map + * union if_map * * bounded array of ifnet srp pointers used to fetch references of live * interfaces with if_get(). */ -struct if_map { - unsigned long limit; - /* followed by limit ifnet srp pointers */ +union if_map { + unsigned int limit; + /* followed by limit-1 ifnet srp pointers */ + struct srp srp; }; +#define IF_MAP_SRP(_if_map, _i) (&(_if_map)[(_i)].srp) + /* * struct if_idxmap * @@ -235,7 +238,7 @@ int ifq_congestion; int netisr; -#define NET_TASKQ 1 +#define NET_TASKQ 4 struct taskq *nettqmp[NET_TASKQ]; struct task if_input_task_locked = TASK_INITIALIZER(if_netisr, NULL); @@ -281,19 +284,15 @@ struct ifnet_head ifnet = TAILQ_HEAD_INI void if_idxmap_init(unsigned int limit) { - struct if_map *if_map; - struct srp *map; + union if_map *if_map; unsigned int i; - if_idxmap.serial = 1; /* skip ifidx 0 so it can return NULL */ - - if_map = malloc(sizeof(*if_map) + limit * sizeof(*map), - M_IFADDR, M_WAITOK); + if_idxmap.serial = 1; /* skip ifidx 0 */ + if_map = mallocarray(limit, sizeof(*if_map), M_IFADDR, M_WAITOK); if_map->limit = limit; - map = (struct srp *)(if_map + 1); - for (i = 0; i < limit; i++) - srp_init(&map[i]); + for (i = 1; i < limit; i++) + srp_init(IF_MAP_SRP(if_map, i)); /* this is called early so there's nothing to race with */ srp_update_locked(&if_map_gc, &if_idxmap.map, if_map); @@ -302,8 +301,7 @@ if_idxmap_init(unsigned int limit) void if_idxmap_insert(struct ifnet *ifp) { - struct if_map *if_map; - struct srp *map; + union if_map *if_map; unsigned int index, i; refcnt_init(&ifp->if_refcnt); @@ -315,44 +313,41 @@ if_idxmap_insert(struct ifnet *ifp) panic("too many interfaces"); if_map = srp_get_locked(&if_idxmap.map); - map = (struct srp *)(if_map + 1); index = if_idxmap.serial++ & USHRT_MAX; if (index >= if_map->limit) { - struct if_map *nif_map; - struct srp *nmap; + union if_map *nif_map; unsigned int nlimit; struct ifnet *nifp; nlimit = if_map->limit * 2; - nif_map = malloc(sizeof(*nif_map) + nlimit * sizeof(*nmap), + nif_map = mallocarray(nlimit, sizeof(*nif_map), M_IFADDR, M_WAITOK); - nmap = (struct srp *)(nif_map + 1); nif_map->limit = nlimit; - for (i = 0; i < if_map->limit; i++) { - srp_init(&nmap[i]); - nifp = srp_get_locked(&map[i]); + for (i = 1; i < if_map->limit; i++) { + srp_init(IF_MAP_SRP(nif_map, i)); + nifp = srp_get_locked(IF_MAP_SRP(if_map, i)); if (nifp != NULL) { - srp_update_locked(&if_ifp_gc, &nmap[i], - if_ref(nifp)); + srp_update_locked(&if_ifp_gc, + IF_MAP_SRP(nif_map, i), if_ref(nifp)); } } while (i < nlimit) { - srp_init(&nmap[i]); + srp_init(IF_MAP_SRP(nif_map, i)); i++; } srp_update_locked(&if_map_gc, &if_idxmap.map, nif_map); if_map = nif_map; - map = nmap; } /* pick the next free index */ - for (i = 0; i < USHRT_MAX; i++) { - if (index != 0 && srp_get_locked(&map[index]) == NULL) + for (i = 1; i < USHRT_MAX; i++) { + if (index != 0 && + srp_get_locked(IF_MAP_SRP(if_map, index)) == NULL) break; index = if_idxmap.serial++ & USHRT_MAX; @@ -360,14 +355,13 @@ if_idxmap_insert(struct ifnet *ifp) /* commit */ ifp->if_index = index; - srp_update_locked(&if_ifp_gc, &map[index], if_ref(ifp)); + srp_update_locked(&if_ifp_gc, IF_MAP_SRP(if_map, index), if_ref(ifp)); } void if_idxmap_remove(struct ifnet *ifp) { - struct if_map *if_map; - struct srp *map; + union if_map *if_map; unsigned int index; index = ifp->if_index; @@ -378,10 +372,9 @@ if_idxmap_remove(struct ifnet *ifp) if_map = srp_get_locked(&if_idxmap.map); KASSERT(index < if_map->limit); - map = (struct srp *)(if_map + 1); - KASSERT(ifp == (struct ifnet *)srp_get_locked(&map[index])); + KASSERT(ifp == srp_get_locked(IF_MAP_SRP(if_map, index))); - srp_update_locked(&if_ifp_gc, &map[index], NULL); + srp_update_locked(&if_ifp_gc, IF_MAP_SRP(if_map, index), NULL); if_idxmap.count--; /* end of if_idxmap modifications */ @@ -398,18 +391,17 @@ if_ifp_dtor(void *null, void *ifp) void if_map_dtor(void *null, void *m) { - struct if_map *if_map = m; - struct srp *map = (struct srp *)(if_map + 1); + union if_map *if_map = m; unsigned int i; /* * dont need to serialize the use of update_locked since this is * the last reference to this map. there's nothing to race against. */ - for (i = 0; i < if_map->limit; i++) - srp_update_locked(&if_ifp_gc, &map[i], NULL); + for (i = 1; i < if_map->limit; i++) + srp_update_locked(&if_ifp_gc, IF_MAP_SRP(if_map, i), NULL); - free(if_map, M_IFADDR, sizeof(*if_map) + if_map->limit * sizeof(*map)); + free(if_map, M_IFADDR, sizeof(*if_map) * if_map->limit); } /* @@ -828,10 +820,10 @@ if_input_process(struct ifnet *ifp, stru * to PF globals, pipex globals, unicast and multicast addresses * lists and the socket layer. */ - NET_LOCK(); +// NET_LOCK(); while ((m = ml_dequeue(ml)) != NULL) (*ifp->if_input)(ifp, m); - NET_UNLOCK(); +// NET_UNLOCK(); } void @@ -1660,15 +1652,15 @@ struct ifnet * if_get(unsigned int index) { struct srp_ref sr; - struct if_map *if_map; - struct srp *map; + union if_map *if_map; struct ifnet *ifp = NULL; + if (index == 0) + return (NULL); + if_map = srp_enter(&sr, &if_idxmap.map); if (index < if_map->limit) { - map = (struct srp *)(if_map + 1); - - ifp = srp_follow(&sr, &map[index]); + ifp = srp_follow(&sr, IF_MAP_SRP(if_map, index)); if (ifp != NULL) { KASSERT(ifp->if_index == index); if_ref(ifp); Index: net/if_pfsync.c =================================================================== RCS file: /cvs/src/sys/net/if_pfsync.c,v retrieving revision 1.274 diff -u -p -r1.274 if_pfsync.c --- net/if_pfsync.c 10 Jul 2020 13:26:42 -0000 1.274 +++ net/if_pfsync.c 24 Jul 2020 10:22:15 -0000 @@ -1754,8 +1754,6 @@ pfsync_insert_state(struct pf_state *st) { struct pfsync_softc *sc = pfsyncif; - NET_ASSERT_LOCKED(); - if (ISSET(st->rule.ptr->rule_flag, PFRULE_NOSYNC) || st->key[PF_SK_WIRE]->proto == IPPROTO_PFSYNC) { SET(st->state_flags, PFSTATE_NOSYNC); @@ -1765,6 +1763,8 @@ pfsync_insert_state(struct pf_state *st) if (sc == NULL || !ISSET(sc->sc_if.if_flags, IFF_RUNNING) || ISSET(st->state_flags, PFSTATE_NOSYNC)) return; + + NET_ASSERT_LOCKED(); #ifdef PFSYNC_DEBUG KASSERT(st->sync_state == PFSYNC_S_NONE); Index: net/ifq.c =================================================================== RCS file: /cvs/src/sys/net/ifq.c,v retrieving revision 1.41 diff -u -p -r1.41 ifq.c --- net/ifq.c 7 Jul 2020 00:00:03 -0000 1.41 +++ net/ifq.c 24 Jul 2020 10:22:15 -0000 @@ -243,7 +243,7 @@ void ifq_init(struct ifqueue *ifq, struct ifnet *ifp, unsigned int idx) { ifq->ifq_if = ifp; - ifq->ifq_softnet = net_tq(ifp->if_index); /* + idx */ + ifq->ifq_softnet = net_tq(ifp->if_index + idx); ifq->ifq_softc = NULL; mtx_init(&ifq->ifq_mtx, IPL_NET); @@ -617,7 +617,7 @@ void ifiq_init(struct ifiqueue *ifiq, struct ifnet *ifp, unsigned int idx) { ifiq->ifiq_if = ifp; - ifiq->ifiq_softnet = net_tq(ifp->if_index); /* + idx */ + ifiq->ifiq_softnet = net_tq(ifp->if_index + idx); ifiq->ifiq_softc = NULL; mtx_init(&ifiq->ifiq_mtx, IPL_NET); Index: net/pf.c =================================================================== RCS file: /cvs/src/sys/net/pf.c,v retrieving revision 1.1093 diff -u -p -r1.1093 pf.c --- net/pf.c 24 Jun 2020 22:03:42 -0000 1.1093 +++ net/pf.c 24 Jul 2020 10:22:15 -0000 @@ -7321,6 +7321,16 @@ done: } int +pf_test_unlocked(sa_family_t af, int fwdir, struct ifnet *ifp, struct mbuf **m0) +{ + int rv; + NET_LOCK(); + rv = pf_test(af, fwdir, ifp, m0); + NET_UNLOCK(); + return (rv); +} + +int pf_ouraddr(struct mbuf *m) { struct pf_state_key *sk; Index: net/pfvar.h =================================================================== RCS file: /cvs/src/sys/net/pfvar.h,v retrieving revision 1.494 diff -u -p -r1.494 pfvar.h --- net/pfvar.h 21 Jul 2020 14:10:51 -0000 1.494 +++ net/pfvar.h 24 Jul 2020 10:22:15 -0000 @@ -1742,6 +1742,7 @@ int pf_setup_pdesc(struct pf_pdesc * u_short *); int pf_test(sa_family_t, int, struct ifnet *, struct mbuf **); +int pf_test_unlocked(sa_family_t, int, struct ifnet *, struct mbuf **); void pf_poolmask(struct pf_addr *, struct pf_addr*, struct pf_addr *, struct pf_addr *, sa_family_t); Index: net/pfvar_priv.h =================================================================== RCS file: /cvs/src/sys/net/pfvar_priv.h,v retrieving revision 1.5 diff -u -p -r1.5 pfvar_priv.h --- net/pfvar_priv.h 11 Sep 2018 07:53:38 -0000 1.5 +++ net/pfvar_priv.h 24 Jul 2020 10:22:15 -0000 @@ -104,12 +104,13 @@ extern struct timeout pf_purge_to; struct pf_state *pf_state_ref(struct pf_state *); void pf_state_unref(struct pf_state *); +#define WITH_PF_LOCK #ifdef WITH_PF_LOCK extern struct rwlock pf_lock; extern struct rwlock pf_state_lock; #define PF_LOCK() do { \ - NET_ASSERT_LOCKED(); \ + /*NET_ASSERT_LOCKED();*/ \ rw_enter_write(&pf_lock); \ } while (0) Index: netinet/in_pcb.c =================================================================== RCS file: /cvs/src/sys/netinet/in_pcb.c,v retrieving revision 1.249 diff -u -p -r1.249 in_pcb.c --- netinet/in_pcb.c 27 May 2020 20:44:07 -0000 1.249 +++ netinet/in_pcb.c 24 Jul 2020 10:22:15 -0000 @@ -95,6 +95,11 @@ #include #endif /* IPSEC */ +#include "stoeplitz.h" +#if NSTOEPLITZ > 0 +#include +#endif + const struct in_addr zeroin_addr; union { @@ -516,6 +521,10 @@ in_pcbconnect(struct inpcb *inp, struct inp->inp_faddr = sin->sin_addr; inp->inp_fport = sin->sin_port; in_pcbrehash(inp); +#if NSTOEPLITZ > 0 + inp->inp_flowid = stoeplitz_ip4port(inp->inp_laddr.s_addr, + inp->inp_faddr.s_addr, inp->inp_lport, inp->inp_fport); +#endif #ifdef IPSEC { /* Cause an IPsec SA to be established. */ @@ -549,6 +558,7 @@ in_pcbdisconnect(struct inpcb *inp) } inp->inp_fport = 0; + inp->inp_flowid = 0; in_pcbrehash(inp); if (inp->inp_socket->so_state & SS_NOFDREF) in_pcbdetach(inp); Index: netinet/in_pcb.h =================================================================== RCS file: /cvs/src/sys/netinet/in_pcb.h,v retrieving revision 1.120 diff -u -p -r1.120 in_pcb.h --- netinet/in_pcb.h 21 Jun 2020 05:14:04 -0000 1.120 +++ netinet/in_pcb.h 24 Jul 2020 10:22:15 -0000 @@ -148,6 +148,7 @@ struct inpcb { void *inp_upcall_arg; u_int inp_rtableid; int inp_pipex; /* pipex indication */ + uint16_t inp_flowid; }; LIST_HEAD(inpcbhead, inpcb); Index: netinet/ip_input.c =================================================================== RCS file: /cvs/src/sys/netinet/ip_input.c,v retrieving revision 1.348 diff -u -p -r1.348 ip_input.c --- netinet/ip_input.c 12 Apr 2020 11:56:52 -0000 1.348 +++ netinet/ip_input.c 24 Jul 2020 10:22:15 -0000 @@ -313,8 +313,14 @@ ip_input_if(struct mbuf **mp, int *offp, * Packet filter */ pfrdr = ip->ip_dst.s_addr; - if (pf_test(AF_INET, PF_IN, ifp, mp) != PF_PASS) - goto bad; + { + int pfrv; + //int nlock = net_enter(); + pfrv = pf_test(AF_INET, PF_IN, ifp, mp); + //net_leave(nlock); + if (pfrv != PF_PASS) + goto bad; + } m = *mp; if (m == NULL) goto bad; @@ -359,6 +365,7 @@ ip_input_if(struct mbuf **mp, int *offp, #ifdef MROUTING if (ipmforwarding && ip_mrouter[ifp->if_rdomain]) { + int nlock; int error; if (m->m_flags & M_EXT) { @@ -380,9 +387,9 @@ ip_input_if(struct mbuf **mp, int *offp, * as expected when ip_mforward() is called from * ip_output().) */ - KERNEL_LOCK(); + nlock = net_enter(); error = ip_mforward(m, ifp); - KERNEL_UNLOCK(); + net_leave(nlock); if (error) { ipstat_inc(ips_cantforward); goto bad; @@ -429,9 +436,11 @@ ip_input_if(struct mbuf **mp, int *offp, } #ifdef IPSEC if (ipsec_in_use) { - int rv; + int nlock, rv; + nlock = net_enter(); rv = ipsec_forward_check(m, hlen, AF_INET); + net_leave(nlock); if (rv != 0) { ipstat_inc(ips_cantforward); goto bad; @@ -578,6 +587,7 @@ ip_ours(struct mbuf **mp, int *offp, int int ip_deliver(struct mbuf **mp, int *offp, int nxt, int af) { + int nlock; const struct protosw *psw; int naf = af; #ifdef INET6 @@ -665,7 +675,9 @@ ip_deliver(struct mbuf **mp, int *offp, break; #endif /* INET6 */ } + nlock = net_enter(); nxt = (*psw->pr_input)(mp, offp, nxt, af); + net_leave(nlock); af = naf; } return nxt; @@ -723,6 +735,7 @@ in_ouraddr(struct mbuf *m, struct ifnet if (!match) { struct ifaddr *ifa; + int nlock; /* * No local address or broadcast address found, so check for @@ -741,7 +754,8 @@ in_ouraddr(struct mbuf *m, struct ifnet * interface, and that M_BCAST will only be set on a BROADCAST * interface. */ - NET_ASSERT_LOCKED(); + + nlock = net_enter(); TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { if (ifa->ifa_addr->sa_family != AF_INET) continue; @@ -752,6 +766,7 @@ in_ouraddr(struct mbuf *m, struct ifnet break; } } + net_leave(nlock); } else if (ipforwarding == 0 && rt->rt_ifidx != ifp->if_index && !((ifp->if_flags & IFF_LOOPBACK) || (ifp->if_type == IFT_ENC) || (m->m_pkthdr.pf.flags & PF_TAG_TRANSLATE_LOCALHOST))) { @@ -1781,19 +1796,14 @@ ip_send_dispatch(void *xmq) struct mbuf_list ml; mq_delist(mq, &ml); - if (ml_empty(&ml)) - return; - - NET_LOCK(); while ((m = ml_dequeue(&ml)) != NULL) { ip_output(m, NULL, NULL, 0, NULL, NULL, 0); } - NET_UNLOCK(); } void ip_send(struct mbuf *m) { - mq_enqueue(&ipsend_mq, m); - task_add(net_tq(0), &ipsend_task); + if (mq_enqueue(&ipsend_mq, m) == 0) + task_add(net_tq(0), &ipsend_task); } Index: netinet/ip_ipsp.c =================================================================== RCS file: /cvs/src/sys/netinet/ip_ipsp.c,v retrieving revision 1.236 diff -u -p -r1.236 ip_ipsp.c --- netinet/ip_ipsp.c 24 Jun 2020 22:03:43 -0000 1.236 +++ netinet/ip_ipsp.c 24 Jul 2020 10:22:15 -0000 @@ -801,6 +801,7 @@ tdb_alloc(u_int rdomain) tdbp = malloc(sizeof(*tdbp), M_TDB, M_WAITOK | M_ZERO); + refcnt_init(&tdbp->tdb_refcnt); TAILQ_INIT(&tdbp->tdb_policy_head); /* Record establishment time. */ @@ -825,6 +826,9 @@ tdb_free(struct tdb *tdbp) struct ipsec_policy *ipo; NET_ASSERT_LOCKED(); + + tdbp->tdb_flags |= TDBF_INVALID; + refcnt_finalize(&tdbp->tdb_refcnt, "tdbfree"); if (tdbp->tdb_xform) { (*(tdbp->tdb_xform->xf_zeroize))(tdbp); Index: netinet/ip_ipsp.h =================================================================== RCS file: /cvs/src/sys/netinet/ip_ipsp.h,v retrieving revision 1.194 diff -u -p -r1.194 ip_ipsp.h --- netinet/ip_ipsp.h 23 Apr 2020 19:38:08 -0000 1.194 +++ netinet/ip_ipsp.h 24 Jul 2020 10:22:15 -0000 @@ -43,6 +43,7 @@ /* IPSP global definitions. */ #include +#include #include union sockaddr_union { @@ -319,6 +320,8 @@ struct tdb { /* tunnel descriptor blo struct tdb *tdb_inext; struct tdb *tdb_onext; + struct refcnt tdb_refcnt; + struct xformsw *tdb_xform; /* Transform to use */ struct enc_xform *tdb_encalgxform; /* Enc algorithm */ struct auth_hash *tdb_authalgxform; /* Auth algorithm */ @@ -595,6 +598,9 @@ void tdb_free(struct tdb *); int tdb_init(struct tdb *, u_int16_t, struct ipsecinit *); void tdb_unlink(struct tdb *); int tdb_walk(u_int, int (*)(struct tdb *, void *, int), void *); + +#define tdb_ref(_tdb) refcnt_take(&(_tdb)->tdb_refcnt) +#define tdb_rel(_tdb) refcnt_rele_wake(&(_tdb)->tdb_refcnt) /* XF_IP4 */ int ipe4_attach(void); Index: netinet/ip_output.c =================================================================== RCS file: /cvs/src/sys/netinet/ip_output.c,v retrieving revision 1.357 diff -u -p -r1.357 ip_output.c --- netinet/ip_output.c 24 Jun 2020 22:03:43 -0000 1.357 +++ netinet/ip_output.c 24 Jul 2020 10:22:15 -0000 @@ -110,8 +110,6 @@ ip_output(struct mbuf *m0, struct mbuf * int rv; #endif - NET_ASSERT_LOCKED(); - #ifdef IPSEC if (inp && (inp->inp_flags & INP_IPV6) != 0) panic("ip_output: IPv6 pcb is passed"); @@ -237,10 +235,14 @@ reroute: #ifdef IPSEC if (ipsec_in_use || inp != NULL) { + int nlock; + /* Do we have any pending SAs to apply ? */ + nlock = net_enter(); tdb = ip_output_ipsec_lookup(m, hlen, &error, inp, ipsecflowinfo); if (error != 0) { + net_leave(nlock); /* Should silently drop packet */ if (error == -EINVAL) error = 0; @@ -248,12 +250,14 @@ reroute: goto done; } if (tdb != NULL) { + tdb_ref(tdb); /* * If it needs TCP/UDP hardware-checksumming, do the * computation now. */ in_proto_cksum_out(m, NULL); } + net_leave(nlock); } #endif /* IPSEC */ @@ -407,9 +411,12 @@ sendit: * Check if the packet needs encapsulation. */ if (tdb != NULL) { + int nlock; /* Callee frees mbuf */ + nlock = net_enter(); error = ip_output_ipsec_send(tdb, m, ro, (flags & IP_FORWARDING) ? 1 : 0); + net_leave(nlock); goto done; } #endif /* IPSEC */ @@ -418,11 +425,17 @@ sendit: * Packet filter */ #if NPF > 0 - if (pf_test(AF_INET, (flags & IP_FORWARDING) ? PF_FWD : PF_OUT, - ifp, &m) != PF_PASS) { - error = EACCES; - m_freem(m); - goto done; + { + int pfrv; + //int nlock = net_enter(); + pfrv = pf_test(AF_INET, + (flags & IP_FORWARDING) ? PF_FWD : PF_OUT, ifp, &m); + //net_leave(nlock); + if (pfrv != PF_PASS) { + error = EACCES; + m_freem(m); + goto done; + } } if (m == NULL) goto done; @@ -518,6 +531,10 @@ done: if (ro == &iproute && ro->ro_rt) rtfree(ro->ro_rt); if_put(ifp); +#ifdef IPSEC + if (tdb != NULL) + tdb_rel(tdb); +#endif /* IPSEC */ return (error); bad: m_freem(m0); Index: netinet/tcp_output.c =================================================================== RCS file: /cvs/src/sys/netinet/tcp_output.c,v retrieving revision 1.128 diff -u -p -r1.128 tcp_output.c --- netinet/tcp_output.c 10 Nov 2018 18:40:34 -0000 1.128 +++ netinet/tcp_output.c 24 Jul 2020 10:22:15 -0000 @@ -1037,6 +1037,8 @@ send: ip->ip_tos |= IPTOS_ECN_ECT0; #endif } + SET(m->m_pkthdr.csum_flags, M_FLOWID); + m->m_pkthdr.ph_flowid = tp->t_inpcb->inp_flowid; error = ip_output(m, tp->t_inpcb->inp_options, &tp->t_inpcb->inp_route, (ip_mtudisc ? IP_MTUDISC : 0), NULL, tp->t_inpcb, 0); Index: netinet6/ip6_forward.c =================================================================== RCS file: /cvs/src/sys/netinet6/ip6_forward.c,v retrieving revision 1.98 diff -u -p -r1.98 ip6_forward.c --- netinet6/ip6_forward.c 24 Jun 2020 22:03:44 -0000 1.98 +++ netinet6/ip6_forward.c 24 Jul 2020 10:22:15 -0000 @@ -144,8 +144,11 @@ reroute: #ifdef IPSEC if (ipsec_in_use) { + int nlock; + nlock = net_enter(); tdb = ip6_output_ipsec_lookup(m, &error, NULL); if (error != 0) { + net_leave(nlock); /* * -EINVAL is used to indicate that the packet should * be silently dropped, typically because we've asked @@ -157,6 +160,9 @@ reroute: m_freem(m); goto freecopy; } + if (tdb != NULL) + tdb_ref(tdb); + net_leave(nlock); } #endif /* IPSEC */ @@ -219,8 +225,11 @@ reroute: * PMTU notification. is it okay? */ if (tdb != NULL) { + int nlock; /* Callee frees mbuf */ + nlock = net_enter(); error = ip6_output_ipsec_send(tdb, m, 0, 1); + net_leave(nlock); if (error) goto senderr; goto freecopy; @@ -287,9 +296,16 @@ reroute: ip6->ip6_dst.s6_addr16[1] = 0; #if NPF > 0 - if (pf_test(AF_INET6, PF_FWD, ifp, &m) != PF_PASS) { - m_freem(m); - goto senderr; + { + int pfrv, nlock; + + nlock = net_enter(); + pfrv = pf_test(AF_INET6, PF_FWD, ifp, &m); + net_leave(nlock); + if (pfrv != PF_PASS) { + m_freem(m); + goto senderr; + } } if (m == NULL) goto senderr; @@ -371,4 +387,8 @@ freecopy: out: rtfree(rt); if_put(ifp); +#ifdef IPSEC + if (tdb != NULL) + tdb_rel(tdb); +#endif } Index: netinet6/ip6_input.c =================================================================== RCS file: /cvs/src/sys/netinet6/ip6_input.c,v retrieving revision 1.226 diff -u -p -r1.226 ip6_input.c --- netinet6/ip6_input.c 6 May 2020 07:08:53 -0000 1.226 +++ netinet6/ip6_input.c 24 Jul 2020 10:22:15 -0000 @@ -297,8 +297,15 @@ ip6_input_if(struct mbuf **mp, int *offp * Packet filter */ odst = ip6->ip6_dst; - if (pf_test(AF_INET6, PF_IN, ifp, mp) != PF_PASS) - goto bad; + { + int pfrv, nlock; + + nlock = net_enter(); + pfrv = pf_test(AF_INET6, PF_IN, ifp, mp); + net_leave(nlock); + if (pfrv != PF_PASS) + goto bad; + } m = *mp; if (m == NULL) goto bad; @@ -502,9 +509,11 @@ ip6_input_if(struct mbuf **mp, int *offp #ifdef IPSEC if (ipsec_in_use) { - int rv; + int rv, nlock; + nlock = net_enter(); rv = ipsec_forward_check(m, *offp, AF_INET6); + net_leave(nlock); if (rv != 0) { ip6stat_inc(ip6s_cantforward); goto bad; Index: netinet6/ip6_output.c =================================================================== RCS file: /cvs/src/sys/netinet6/ip6_output.c,v retrieving revision 1.247 diff -u -p -r1.247 ip6_output.c --- netinet6/ip6_output.c 17 Jul 2020 15:21:36 -0000 1.247 +++ netinet6/ip6_output.c 24 Jul 2020 10:22:15 -0000 @@ -206,8 +206,12 @@ ip6_output(struct mbuf *m0, struct ip6_p #ifdef IPSEC if (ipsec_in_use || inp) { + int nlock; + + nlock = net_enter(); tdb = ip6_output_ipsec_lookup(m, &error, inp); if (error != 0) { + net_leave(nlock); /* * -EINVAL is used to indicate that the packet should * be silently dropped, typically because we've asked @@ -218,6 +222,9 @@ ip6_output(struct mbuf *m0, struct ip6_p goto freehdrs; } + if (tdb != NULL) + tdb_ref(tdb); + net_leave(nlock); } #endif /* IPSEC */ @@ -417,6 +424,7 @@ reroute: #ifdef IPSEC if (tdb) { + int nlock; /* * XXX what should we do if ip6_hlim == 0 and the * packet gets tunneled? @@ -426,8 +434,10 @@ reroute: * packet just because ip6_dst is different from what tdb has. * XXX */ + nlock = net_enter(); error = ip6_output_ipsec_send(tdb, m, exthdrs.ip6e_rthdr ? 1 : 0, 0); + net_leave(nlock); goto done; } #endif /* IPSEC */ @@ -765,7 +775,10 @@ done: } else if (ro_pmtu == &ip6route && ro_pmtu->ro_rt) { rtfree(ro_pmtu->ro_rt); } - +#ifdef IPSEC + if (tdb != NULL) + tdb_rel(tdb); +#endif return (error); freehdrs: Index: sys/mbuf.h =================================================================== RCS file: /cvs/src/sys/sys/mbuf.h,v retrieving revision 1.249 diff -u -p -r1.249 mbuf.h --- sys/mbuf.h 21 Jun 2020 11:44:12 -0000 1.249 +++ sys/mbuf.h 24 Jul 2020 10:22:15 -0000 @@ -505,6 +505,7 @@ struct m_tag *m_tag_next(struct mbuf *, void ml_init(struct mbuf_list *); void ml_enqueue(struct mbuf_list *, struct mbuf *); struct mbuf * ml_dequeue(struct mbuf_list *); +void ml_requeue(struct mbuf_list *, struct mbuf *); void ml_enlist(struct mbuf_list *, struct mbuf_list *); struct mbuf * ml_dechain(struct mbuf_list *); unsigned int ml_purge(struct mbuf_list *); Index: sys/systm.h =================================================================== RCS file: /cvs/src/sys/sys/systm.h,v retrieving revision 1.147 diff -u -p -r1.147 systm.h --- sys/systm.h 29 May 2020 04:42:25 -0000 1.147 +++ sys/systm.h 24 Jul 2020 10:22:15 -0000 @@ -328,6 +328,22 @@ extern struct rwlock netlock; #define NET_LOCK() do { rw_enter_write(&netlock); } while (0) #define NET_UNLOCK() do { rw_exit_write(&netlock); } while (0) +static inline int +net_enter(void) +{ + int unlocked = (rw_status(&netlock) != RW_WRITE); + if (unlocked) + NET_LOCK(); + return (unlocked); +} + +static inline void +net_leave(int unlocked) +{ + if (unlocked) + NET_UNLOCK(); +} + /* * Reader version of NET_LOCK() to be used in "softnet" thread only.