summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/netinet/ip_divert.c
diff options
context:
space:
mode:
Diffstat (limited to 'freebsd/sys/netinet/ip_divert.c')
-rw-r--r--freebsd/sys/netinet/ip_divert.c27
1 files changed, 12 insertions, 15 deletions
diff --git a/freebsd/sys/netinet/ip_divert.c b/freebsd/sys/netinet/ip_divert.c
index 53a0445e..84f39023 100644
--- a/freebsd/sys/netinet/ip_divert.c
+++ b/freebsd/sys/netinet/ip_divert.c
@@ -76,7 +76,6 @@ __FBSDID("$FreeBSD$");
#endif
#include <security/mac/mac_framework.h>
-
/*
* Divert sockets
*/
@@ -237,7 +236,7 @@ divert_packet(struct mbuf *m, int incoming)
/* Find IP address for receive interface */
ifp = m->m_pkthdr.rcvif;
if_addr_rlock(ifp);
- TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
+ CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
if (ifa->ifa_addr->sa_family != AF_INET)
continue;
divsrc.sin_addr =
@@ -471,13 +470,15 @@ div_output(struct socket *so, struct mbuf *m, struct sockaddr_in *sin,
bzero(sin->sin_zero, sizeof(sin->sin_zero));
sin->sin_port = 0;
+ NET_EPOCH_ENTER();
ifa = ifa_ifwithaddr((struct sockaddr *) sin);
if (ifa == NULL) {
error = EADDRNOTAVAIL;
+ NET_EPOCH_EXIT();
goto cantsend;
}
m->m_pkthdr.rcvif = ifa->ifa_ifp;
- ifa_free(ifa);
+ NET_EPOCH_EXIT();
}
#ifdef MAC
mac_socket_create_mbuf(so, m);
@@ -553,6 +554,7 @@ div_detach(struct socket *so)
KASSERT(inp != NULL, ("div_detach: inp == NULL"));
INP_INFO_WLOCK(&V_divcbinfo);
INP_WLOCK(inp);
+ /* XXX defer destruction to epoch_call */
in_pcbdetach(inp);
in_pcbfree(inp);
INP_INFO_WUNLOCK(&V_divcbinfo);
@@ -632,6 +634,7 @@ static int
div_pcblist(SYSCTL_HANDLER_ARGS)
{
int error, i, n;
+ struct in_pcblist *il;
struct inpcb *inp, **inp_list;
inp_gen_t gencnt;
struct xinpgen xig;
@@ -671,9 +674,8 @@ div_pcblist(SYSCTL_HANDLER_ARGS)
if (error)
return error;
- inp_list = malloc(n * sizeof *inp_list, M_TEMP, M_WAITOK);
- if (inp_list == NULL)
- return ENOMEM;
+ il = malloc(sizeof(struct in_pcblist) + n * sizeof(struct inpcb *), M_TEMP, M_WAITOK|M_ZERO_INVARIANTS);
+ inp_list = il->il_inp_list;
INP_INFO_RLOCK(&V_divcbinfo);
for (inp = LIST_FIRST(V_divcbinfo.ipi_listhead), i = 0; inp && i < n;
@@ -702,14 +704,9 @@ div_pcblist(SYSCTL_HANDLER_ARGS)
} else
INP_RUNLOCK(inp);
}
- INP_INFO_WLOCK(&V_divcbinfo);
- for (i = 0; i < n; i++) {
- inp = inp_list[i];
- INP_RLOCK(inp);
- if (!in_pcbrele_rlocked(inp))
- INP_RUNLOCK(inp);
- }
- INP_INFO_WUNLOCK(&V_divcbinfo);
+ il->il_count = n;
+ il->il_pcbinfo = &V_divcbinfo;
+ epoch_call(net_epoch_preempt, &il->il_epoch_ctx, in_pcblist_rele_rlocked);
if (!error) {
/*
@@ -726,7 +723,6 @@ div_pcblist(SYSCTL_HANDLER_ARGS)
INP_INFO_RUNLOCK(&V_divcbinfo);
error = SYSCTL_OUT(req, &xig, sizeof xig);
}
- free(inp_list, M_TEMP);
return error;
}
@@ -806,6 +802,7 @@ div_modevent(module_t mod, int type, void *unused)
break;
}
ip_divert_ptr = NULL;
+ /* XXX defer to epoch_call ? */
err = pf_proto_unregister(PF_INET, IPPROTO_DIVERT, SOCK_RAW);
INP_INFO_WUNLOCK(&V_divcbinfo);
#ifndef VIMAGE