buffer. Later it may be used to protect more of the PCB or socket.
In divert input replace the kernel lock with this mutex.
OK mvs@
-/* $OpenBSD: in_pcb.c,v 1.270 2022/08/08 12:06:30 bluhm Exp $ */
+/* $OpenBSD: in_pcb.c,v 1.271 2022/08/21 11:44:53 bluhm Exp $ */
/* $NetBSD: in_pcb.c,v 1.25 1996/02/13 23:41:53 christos Exp $ */
/*
inp->inp_table = table;
inp->inp_socket = so;
refcnt_init_trace(&inp->inp_refcnt, DT_REFCNT_IDX_INPCB);
+ mtx_init(&inp->inp_mtx, IPL_SOFTNET);
inp->inp_seclevel[SL_AUTH] = IPSEC_AUTH_LEVEL_DEFAULT;
inp->inp_seclevel[SL_ESP_TRANS] = IPSEC_ESP_TRANS_LEVEL_DEFAULT;
inp->inp_seclevel[SL_ESP_NETWORK] = IPSEC_ESP_NETWORK_LEVEL_DEFAULT;
-/* $OpenBSD: in_pcb.h,v 1.129 2022/05/15 09:12:20 dlg Exp $ */
+/* $OpenBSD: in_pcb.h,v 1.130 2022/08/21 11:44:53 bluhm Exp $ */
/* $NetBSD: in_pcb.h,v 1.14 1996/02/13 23:42:00 christos Exp $ */
/*
* I immutable after creation
* N net lock
* t inpt_mtx pcb table mutex
+ * p inpcb_mtx pcb mutex
*/
struct pf_state_key;
#define inp_route inp_ru.ru_route
#define inp_route6 inp_ru.ru_route6
struct refcnt inp_refcnt; /* refcount PCB, delay memory free */
+ struct mutex inp_mtx; /* protect PCB and socket members */
int inp_flags; /* generic IP/datagram flags */
union { /* Header prototype. */
struct ip hu_ip;
-/* $OpenBSD: ip_divert.c,v 1.70 2022/08/20 23:48:58 mvs Exp $ */
+/* $OpenBSD: ip_divert.c,v 1.71 2022/08/21 11:44:54 bluhm Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
if_put(ifp);
}
+ mtx_enter(&inp->inp_mtx);
so = inp->inp_socket;
- /*
- * XXXSMP sbappendaddr() is not MP safe and this function is called
- * from pf with shared netlock. To call only one sbappendaddr() from
- * divert_packet(), protect it with kernel lock. All other places
- * call sbappendaddr() with exclusive net lock. This blocks
- * divert_packet() as we have the shared lock.
- */
- KERNEL_LOCK();
if (sbappendaddr(so, &so->so_rcv, sintosa(&sin), m, NULL) == 0) {
- KERNEL_UNLOCK();
+ mtx_leave(&inp->inp_mtx);
divstat_inc(divs_fullsock);
goto bad;
}
- sorwakeup(inp->inp_socket);
- KERNEL_UNLOCK();
+ mtx_leave(&inp->inp_mtx);
+ sorwakeup(so);
in_pcbunref(inp);
return;
-/* $OpenBSD: ip6_divert.c,v 1.69 2022/08/20 23:48:58 mvs Exp $ */
+/* $OpenBSD: ip6_divert.c,v 1.70 2022/08/21 11:44:54 bluhm Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
if_put(ifp);
}
+ mtx_enter(&inp->inp_mtx);
so = inp->inp_socket;
- /*
- * XXXSMP sbappendaddr() is not MP safe and this function is called
- * from pf with shared netlock. To call only one sbappendaddr() from
- * divert_packet(), protect it with kernel lock. All other places
- * call sbappendaddr() with exclusive net lock. This blocks
- * divert_packet() as we have the shared lock.
- */
- KERNEL_LOCK();
if (sbappendaddr(so, &so->so_rcv, sin6tosa(&sin6), m, NULL) == 0) {
- KERNEL_UNLOCK();
+ mtx_leave(&inp->inp_mtx);
div6stat_inc(div6s_fullsock);
goto bad;
}
- sorwakeup(inp->inp_socket);
- KERNEL_UNLOCK();
+ mtx_leave(&inp->inp_mtx);
+ sorwakeup(so);
in_pcbunref(inp);
return;