Fri Jan 27 17:25:34 2017 UTC ()
Don't hold softnet_lock if NET_MPSAFE.

Some functions lock softnet_lock while waiting in pserialize_perform() in pfil_add_hook().
(e.g. key_timehandler(), etc)


(ryo)
diff -r1.5 -r1.6 src/sys/net/npf/npf_os.c

cvs diff -r1.5 -r1.6 src/sys/net/npf/npf_os.c (switch to unified diff)

--- src/sys/net/npf/npf_os.c 2017/01/03 00:58:05 1.5
+++ src/sys/net/npf/npf_os.c 2017/01/27 17:25:34 1.6
@@ -1,497 +1,506 @@ @@ -1,497 +1,506 @@
1/* $NetBSD: npf_os.c,v 1.5 2017/01/03 00:58:05 rmind Exp $ */ 1/* $NetBSD: npf_os.c,v 1.6 2017/01/27 17:25:34 ryo Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2009-2016 The NetBSD Foundation, Inc. 4 * Copyright (c) 2009-2016 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This material is based upon work partially supported by The 7 * This material is based upon work partially supported by The
8 * NetBSD Foundation under a contract with Mindaugas Rasiukevicius. 8 * NetBSD Foundation under a contract with Mindaugas Rasiukevicius.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32/* 32/*
33 * NPF main: dynamic load/initialisation and unload routines. 33 * NPF main: dynamic load/initialisation and unload routines.
34 */ 34 */
35 35
36#ifdef _KERNEL 36#ifdef _KERNEL
37#include <sys/cdefs.h> 37#include <sys/cdefs.h>
38__KERNEL_RCSID(0, "$NetBSD: npf_os.c,v 1.5 2017/01/03 00:58:05 rmind Exp $"); 38__KERNEL_RCSID(0, "$NetBSD: npf_os.c,v 1.6 2017/01/27 17:25:34 ryo Exp $");
39 39
40#ifdef _KERNEL_OPT 40#ifdef _KERNEL_OPT
41#include "pf.h" 41#include "pf.h"
42#if NPF > 0 42#if NPF > 0
43#error "NPF and PF are mutually exclusive; please select one" 43#error "NPF and PF are mutually exclusive; please select one"
44#endif 44#endif
45#endif 45#endif
46 46
47#include <sys/param.h> 47#include <sys/param.h>
48#include <sys/types.h> 48#include <sys/types.h>
49 49
50#include <sys/conf.h> 50#include <sys/conf.h>
51#include <sys/kauth.h> 51#include <sys/kauth.h>
52#include <sys/kmem.h> 52#include <sys/kmem.h>
53#include <sys/lwp.h> 53#include <sys/lwp.h>
54#include <sys/module.h> 54#include <sys/module.h>
55#include <sys/socketvar.h> 55#include <sys/socketvar.h>
56#include <sys/uio.h> 56#include <sys/uio.h>
57 57
58#include <netinet/in.h> 58#include <netinet/in.h>
59#include <netinet6/in6_var.h> 59#include <netinet6/in6_var.h>
60#endif 60#endif
61 61
62#include "npf_impl.h" 62#include "npf_impl.h"
63#include "npfkern.h" 63#include "npfkern.h"
64 64
65#ifdef _KERNEL 65#ifdef _KERNEL
66#ifndef _MODULE 66#ifndef _MODULE
67#include "opt_modular.h" 67#include "opt_modular.h"
 68#include "opt_net_mpsafe.h"
68#endif 69#endif
69#include "ioconf.h" 70#include "ioconf.h"
70#endif 71#endif
71 72
72/* 73/*
73 * Module and device structures. 74 * Module and device structures.
74 */ 75 */
75#ifndef _MODULE 76#ifndef _MODULE
76/* 77/*
77 * Modular kernels load drivers too early, and we need percpu to be inited 78 * Modular kernels load drivers too early, and we need percpu to be inited
78 * So we make this misc; a better way would be to have early boot and late 79 * So we make this misc; a better way would be to have early boot and late
79 * boot drivers. 80 * boot drivers.
80 */ 81 */
81MODULE(MODULE_CLASS_MISC, npf, NULL); 82MODULE(MODULE_CLASS_MISC, npf, NULL);
82#else 83#else
83/* This module autoloads via /dev/npf so it needs to be a driver */ 84/* This module autoloads via /dev/npf so it needs to be a driver */
84MODULE(MODULE_CLASS_DRIVER, npf, NULL); 85MODULE(MODULE_CLASS_DRIVER, npf, NULL);
85#endif 86#endif
86 87
87static int npf_dev_open(dev_t, int, int, lwp_t *); 88static int npf_dev_open(dev_t, int, int, lwp_t *);
88static int npf_dev_close(dev_t, int, int, lwp_t *); 89static int npf_dev_close(dev_t, int, int, lwp_t *);
89static int npf_dev_ioctl(dev_t, u_long, void *, int, lwp_t *); 90static int npf_dev_ioctl(dev_t, u_long, void *, int, lwp_t *);
90static int npf_dev_poll(dev_t, int, lwp_t *); 91static int npf_dev_poll(dev_t, int, lwp_t *);
91static int npf_dev_read(dev_t, struct uio *, int); 92static int npf_dev_read(dev_t, struct uio *, int);
92 93
93const struct cdevsw npf_cdevsw = { 94const struct cdevsw npf_cdevsw = {
94 .d_open = npf_dev_open, 95 .d_open = npf_dev_open,
95 .d_close = npf_dev_close, 96 .d_close = npf_dev_close,
96 .d_read = npf_dev_read, 97 .d_read = npf_dev_read,
97 .d_write = nowrite, 98 .d_write = nowrite,
98 .d_ioctl = npf_dev_ioctl, 99 .d_ioctl = npf_dev_ioctl,
99 .d_stop = nostop, 100 .d_stop = nostop,
100 .d_tty = notty, 101 .d_tty = notty,
101 .d_poll = npf_dev_poll, 102 .d_poll = npf_dev_poll,
102 .d_mmap = nommap, 103 .d_mmap = nommap,
103 .d_kqfilter = nokqfilter, 104 .d_kqfilter = nokqfilter,
104 .d_discard = nodiscard, 105 .d_discard = nodiscard,
105 .d_flag = D_OTHER | D_MPSAFE 106 .d_flag = D_OTHER | D_MPSAFE
106}; 107};
107 108
108static const char * npf_ifop_getname(ifnet_t *); 109static const char * npf_ifop_getname(ifnet_t *);
109static ifnet_t * npf_ifop_lookup(const char *); 110static ifnet_t * npf_ifop_lookup(const char *);
110static void npf_ifop_flush(void *); 111static void npf_ifop_flush(void *);
111static void * npf_ifop_getmeta(const ifnet_t *); 112static void * npf_ifop_getmeta(const ifnet_t *);
112static void npf_ifop_setmeta(ifnet_t *, void *); 113static void npf_ifop_setmeta(ifnet_t *, void *);
113 114
114static const unsigned nworkers = 1; 115static const unsigned nworkers = 1;
115 116
116static bool pfil_registered = false; 117static bool pfil_registered = false;
117static pfil_head_t * npf_ph_if = NULL; 118static pfil_head_t * npf_ph_if = NULL;
118static pfil_head_t * npf_ph_inet = NULL; 119static pfil_head_t * npf_ph_inet = NULL;
119static pfil_head_t * npf_ph_inet6 = NULL; 120static pfil_head_t * npf_ph_inet6 = NULL;
120 121
121static const npf_ifops_t kern_ifops = { 122static const npf_ifops_t kern_ifops = {
122 .getname = npf_ifop_getname, 123 .getname = npf_ifop_getname,
123 .lookup = npf_ifop_lookup, 124 .lookup = npf_ifop_lookup,
124 .flush = npf_ifop_flush, 125 .flush = npf_ifop_flush,
125 .getmeta = npf_ifop_getmeta, 126 .getmeta = npf_ifop_getmeta,
126 .setmeta = npf_ifop_setmeta, 127 .setmeta = npf_ifop_setmeta,
127}; 128};
128 129
129static int 130static int
130npf_fini(void) 131npf_fini(void)
131{ 132{
132 npf_t *npf = npf_getkernctx(); 133 npf_t *npf = npf_getkernctx();
133 134
134 /* At first, detach device and remove pfil hooks. */ 135 /* At first, detach device and remove pfil hooks. */
135#ifdef _MODULE 136#ifdef _MODULE
136 devsw_detach(NULL, &npf_cdevsw); 137 devsw_detach(NULL, &npf_cdevsw);
137#endif 138#endif
138 npf_pfil_unregister(true); 139 npf_pfil_unregister(true);
139 npf_destroy(npf); 140 npf_destroy(npf);
140 npf_sysfini(); 141 npf_sysfini();
141 return 0; 142 return 0;
142} 143}
143 144
144static int 145static int
145npf_init(void) 146npf_init(void)
146{ 147{
147 npf_t *npf; 148 npf_t *npf;
148 int error = 0; 149 int error = 0;
149 150
150 error = npf_sysinit(nworkers); 151 error = npf_sysinit(nworkers);
151 if (error) 152 if (error)
152 return error; 153 return error;
153 npf = npf_create(0, NULL, &kern_ifops); 154 npf = npf_create(0, NULL, &kern_ifops);
154 npf_setkernctx(npf); 155 npf_setkernctx(npf);
155 npf_pfil_register(true); 156 npf_pfil_register(true);
156 157
157#ifdef _MODULE 158#ifdef _MODULE
158 devmajor_t bmajor = NODEVMAJOR, cmajor = NODEVMAJOR; 159 devmajor_t bmajor = NODEVMAJOR, cmajor = NODEVMAJOR;
159 160
160 /* Attach /dev/npf device. */ 161 /* Attach /dev/npf device. */
161 error = devsw_attach("npf", NULL, &bmajor, &npf_cdevsw, &cmajor); 162 error = devsw_attach("npf", NULL, &bmajor, &npf_cdevsw, &cmajor);
162 if (error) { 163 if (error) {
163 /* It will call devsw_detach(), which is safe. */ 164 /* It will call devsw_detach(), which is safe. */
164 (void)npf_fini(); 165 (void)npf_fini();
165 } 166 }
166#endif 167#endif
167 return error; 168 return error;
168} 169}
169 170
170 171
171/* 172/*
172 * Module interface. 173 * Module interface.
173 */ 174 */
174static int 175static int
175npf_modcmd(modcmd_t cmd, void *arg) 176npf_modcmd(modcmd_t cmd, void *arg)
176{ 177{
177 switch (cmd) { 178 switch (cmd) {
178 case MODULE_CMD_INIT: 179 case MODULE_CMD_INIT:
179 return npf_init(); 180 return npf_init();
180 case MODULE_CMD_FINI: 181 case MODULE_CMD_FINI:
181 return npf_fini(); 182 return npf_fini();
182 case MODULE_CMD_AUTOUNLOAD: 183 case MODULE_CMD_AUTOUNLOAD:
183 if (npf_autounload_p()) { 184 if (npf_autounload_p()) {
184 return EBUSY; 185 return EBUSY;
185 } 186 }
186 break; 187 break;
187 default: 188 default:
188 return ENOTTY; 189 return ENOTTY;
189 } 190 }
190 return 0; 191 return 0;
191} 192}
192 193
193void 194void
194npfattach(int nunits) 195npfattach(int nunits)
195{ 196{
196 /* Nothing */ 197 /* Nothing */
197} 198}
198 199
199static int 200static int
200npf_dev_open(dev_t dev, int flag, int mode, lwp_t *l) 201npf_dev_open(dev_t dev, int flag, int mode, lwp_t *l)
201{ 202{
202 /* Available only for super-user. */ 203 /* Available only for super-user. */
203 if (kauth_authorize_network(l->l_cred, KAUTH_NETWORK_FIREWALL, 204 if (kauth_authorize_network(l->l_cred, KAUTH_NETWORK_FIREWALL,
204 KAUTH_REQ_NETWORK_FIREWALL_FW, NULL, NULL, NULL)) { 205 KAUTH_REQ_NETWORK_FIREWALL_FW, NULL, NULL, NULL)) {
205 return EPERM; 206 return EPERM;
206 } 207 }
207 return 0; 208 return 0;
208} 209}
209 210
210static int 211static int
211npf_dev_close(dev_t dev, int flag, int mode, lwp_t *l) 212npf_dev_close(dev_t dev, int flag, int mode, lwp_t *l)
212{ 213{
213 return 0; 214 return 0;
214} 215}
215 216
216static int 217static int
217npf_stats_export(npf_t *npf, void *data) 218npf_stats_export(npf_t *npf, void *data)
218{ 219{
219 uint64_t *fullst, *uptr = *(uint64_t **)data; 220 uint64_t *fullst, *uptr = *(uint64_t **)data;
220 int error; 221 int error;
221 222
222 fullst = kmem_alloc(NPF_STATS_SIZE, KM_SLEEP); 223 fullst = kmem_alloc(NPF_STATS_SIZE, KM_SLEEP);
223 npf_stats(npf, fullst); /* will zero the buffer */ 224 npf_stats(npf, fullst); /* will zero the buffer */
224 error = copyout(fullst, uptr, NPF_STATS_SIZE); 225 error = copyout(fullst, uptr, NPF_STATS_SIZE);
225 kmem_free(fullst, NPF_STATS_SIZE); 226 kmem_free(fullst, NPF_STATS_SIZE);
226 return error; 227 return error;
227} 228}
228 229
229static int 230static int
230npf_dev_ioctl(dev_t dev, u_long cmd, void *data, int flag, lwp_t *l) 231npf_dev_ioctl(dev_t dev, u_long cmd, void *data, int flag, lwp_t *l)
231{ 232{
232 npf_t *npf = npf_getkernctx(); 233 npf_t *npf = npf_getkernctx();
233 int error; 234 int error;
234 235
235 /* Available only for super-user. */ 236 /* Available only for super-user. */
236 if (kauth_authorize_network(l->l_cred, KAUTH_NETWORK_FIREWALL, 237 if (kauth_authorize_network(l->l_cred, KAUTH_NETWORK_FIREWALL,
237 KAUTH_REQ_NETWORK_FIREWALL_FW, NULL, NULL, NULL)) { 238 KAUTH_REQ_NETWORK_FIREWALL_FW, NULL, NULL, NULL)) {
238 return EPERM; 239 return EPERM;
239 } 240 }
240 241
241 switch (cmd) { 242 switch (cmd) {
242 case IOC_NPF_TABLE: 243 case IOC_NPF_TABLE:
243 error = npfctl_table(npf, data); 244 error = npfctl_table(npf, data);
244 break; 245 break;
245 case IOC_NPF_RULE: 246 case IOC_NPF_RULE:
246 error = npfctl_rule(npf, cmd, data); 247 error = npfctl_rule(npf, cmd, data);
247 break; 248 break;
248 case IOC_NPF_STATS: 249 case IOC_NPF_STATS:
249 error = npf_stats_export(npf, data); 250 error = npf_stats_export(npf, data);
250 break; 251 break;
251 case IOC_NPF_SAVE: 252 case IOC_NPF_SAVE:
252 error = npfctl_save(npf, cmd, data); 253 error = npfctl_save(npf, cmd, data);
253 break; 254 break;
254 case IOC_NPF_SWITCH: 255 case IOC_NPF_SWITCH:
255 error = npfctl_switch(data); 256 error = npfctl_switch(data);
256 break; 257 break;
257 case IOC_NPF_LOAD: 258 case IOC_NPF_LOAD:
258 error = npfctl_load(npf, cmd, data); 259 error = npfctl_load(npf, cmd, data);
259 break; 260 break;
260 case IOC_NPF_CONN_LOOKUP: 261 case IOC_NPF_CONN_LOOKUP:
261 error = npfctl_conn_lookup(npf, cmd, data); 262 error = npfctl_conn_lookup(npf, cmd, data);
262 break; 263 break;
263 case IOC_NPF_VERSION: 264 case IOC_NPF_VERSION:
264 *(int *)data = NPF_VERSION; 265 *(int *)data = NPF_VERSION;
265 error = 0; 266 error = 0;
266 break; 267 break;
267 default: 268 default:
268 error = ENOTTY; 269 error = ENOTTY;
269 break; 270 break;
270 } 271 }
271 return error; 272 return error;
272} 273}
273 274
274static int 275static int
275npf_dev_poll(dev_t dev, int events, lwp_t *l) 276npf_dev_poll(dev_t dev, int events, lwp_t *l)
276{ 277{
277 return ENOTSUP; 278 return ENOTSUP;
278} 279}
279 280
280static int 281static int
281npf_dev_read(dev_t dev, struct uio *uio, int flag) 282npf_dev_read(dev_t dev, struct uio *uio, int flag)
282{ 283{
283 return ENOTSUP; 284 return ENOTSUP;
284} 285}
285 286
286bool 287bool
287npf_autounload_p(void) 288npf_autounload_p(void)
288{ 289{
289 npf_t *npf = npf_getkernctx(); 290 npf_t *npf = npf_getkernctx();
290 return !npf_pfil_registered_p() && npf_default_pass(npf); 291 return !npf_pfil_registered_p() && npf_default_pass(npf);
291} 292}
292 293
293/* 294/*
294 * Interface operations. 295 * Interface operations.
295 */ 296 */
296 297
297static const char * 298static const char *
298npf_ifop_getname(ifnet_t *ifp) 299npf_ifop_getname(ifnet_t *ifp)
299{ 300{
300 return ifp->if_xname; 301 return ifp->if_xname;
301} 302}
302 303
303static ifnet_t * 304static ifnet_t *
304npf_ifop_lookup(const char *name) 305npf_ifop_lookup(const char *name)
305{ 306{
306 return ifunit(name); 307 return ifunit(name);
307} 308}
308 309
309static void 310static void
310npf_ifop_flush(void *arg) 311npf_ifop_flush(void *arg)
311{ 312{
312 ifnet_t *ifp; 313 ifnet_t *ifp;
313 314
314 KERNEL_LOCK(1, NULL); 315 KERNEL_LOCK(1, NULL);
315 IFNET_LOCK(); 316 IFNET_LOCK();
316 IFNET_WRITER_FOREACH(ifp) { 317 IFNET_WRITER_FOREACH(ifp) {
317 ifp->if_pf_kif = arg; 318 ifp->if_pf_kif = arg;
318 } 319 }
319 IFNET_UNLOCK(); 320 IFNET_UNLOCK();
320 KERNEL_UNLOCK_ONE(NULL); 321 KERNEL_UNLOCK_ONE(NULL);
321} 322}
322 323
323static void * 324static void *
324npf_ifop_getmeta(const ifnet_t *ifp) 325npf_ifop_getmeta(const ifnet_t *ifp)
325{ 326{
326 return ifp->if_pf_kif; 327 return ifp->if_pf_kif;
327} 328}
328 329
329static void 330static void
330npf_ifop_setmeta(ifnet_t *ifp, void *arg) 331npf_ifop_setmeta(ifnet_t *ifp, void *arg)
331{ 332{
332 ifp->if_pf_kif = arg; 333 ifp->if_pf_kif = arg;
333} 334}
334 335
335#ifdef _KERNEL 336#ifdef _KERNEL
336 337
337/* 338/*
338 * Wrapper of the main packet handler to pass the kernel NPF context. 339 * Wrapper of the main packet handler to pass the kernel NPF context.
339 */ 340 */
340static int 341static int
341npfkern_packet_handler(void *arg, struct mbuf **mp, ifnet_t *ifp, int di) 342npfkern_packet_handler(void *arg, struct mbuf **mp, ifnet_t *ifp, int di)
342{ 343{
343 npf_t *npf = npf_getkernctx(); 344 npf_t *npf = npf_getkernctx();
344 return npf_packet_handler(npf, mp, ifp, di); 345 return npf_packet_handler(npf, mp, ifp, di);
345} 346}
346 347
347/* 348/*
348 * npf_ifhook: hook handling interface changes. 349 * npf_ifhook: hook handling interface changes.
349 */ 350 */
350static void 351static void
351npf_ifhook(void *arg, unsigned long cmd, void *arg2) 352npf_ifhook(void *arg, unsigned long cmd, void *arg2)
352{ 353{
353 npf_t *npf = npf_getkernctx(); 354 npf_t *npf = npf_getkernctx();
354 ifnet_t *ifp = arg2; 355 ifnet_t *ifp = arg2;
355 356
356 switch (cmd) { 357 switch (cmd) {
357 case PFIL_IFNET_ATTACH: 358 case PFIL_IFNET_ATTACH:
358 npf_ifmap_attach(npf, ifp); 359 npf_ifmap_attach(npf, ifp);
359 npf_ifaddr_sync(npf, ifp); 360 npf_ifaddr_sync(npf, ifp);
360 break; 361 break;
361 case PFIL_IFNET_DETACH: 362 case PFIL_IFNET_DETACH:
362 npf_ifmap_detach(npf, ifp); 363 npf_ifmap_detach(npf, ifp);
363 npf_ifaddr_flush(npf, ifp); 364 npf_ifaddr_flush(npf, ifp);
364 break; 365 break;
365 } 366 }
366} 367}
367 368
368static void 369static void
369npf_ifaddrhook(void *arg, u_long cmd, void *arg2) 370npf_ifaddrhook(void *arg, u_long cmd, void *arg2)
370{ 371{
371 npf_t *npf = npf_getkernctx(); 372 npf_t *npf = npf_getkernctx();
372 struct ifaddr *ifa = arg2; 373 struct ifaddr *ifa = arg2;
373 374
374 switch (cmd) { 375 switch (cmd) {
375 case SIOCSIFADDR: 376 case SIOCSIFADDR:
376 case SIOCAIFADDR: 377 case SIOCAIFADDR:
377 case SIOCDIFADDR: 378 case SIOCDIFADDR:
378#ifdef INET6 379#ifdef INET6
379 case SIOCSIFADDR_IN6: 380 case SIOCSIFADDR_IN6:
380 case SIOCAIFADDR_IN6: 381 case SIOCAIFADDR_IN6:
381 case SIOCDIFADDR_IN6: 382 case SIOCDIFADDR_IN6:
382#endif 383#endif
383 break; 384 break;
384 default: 385 default:
385 return; 386 return;
386 } 387 }
387 npf_ifaddr_sync(npf, ifa->ifa_ifp); 388 npf_ifaddr_sync(npf, ifa->ifa_ifp);
388} 389}
389 390
390/* 391/*
391 * npf_pfil_register: register pfil(9) hooks. 392 * npf_pfil_register: register pfil(9) hooks.
392 */ 393 */
393int 394int
394npf_pfil_register(bool init) 395npf_pfil_register(bool init)
395{ 396{
396 npf_t *npf = npf_getkernctx(); 397 npf_t *npf = npf_getkernctx();
397 int error = 0; 398 int error = 0;
398 399
 400#ifndef NET_MPSAFE
399 mutex_enter(softnet_lock); 401 mutex_enter(softnet_lock);
400 KERNEL_LOCK(1, NULL); 402 KERNEL_LOCK(1, NULL);
 403#endif
401 404
402 /* Init: interface re-config and attach/detach hook. */ 405 /* Init: interface re-config and attach/detach hook. */
403 if (!npf_ph_if) { 406 if (!npf_ph_if) {
404 npf_ph_if = pfil_head_get(PFIL_TYPE_IFNET, 0); 407 npf_ph_if = pfil_head_get(PFIL_TYPE_IFNET, 0);
405 if (!npf_ph_if) { 408 if (!npf_ph_if) {
406 error = ENOENT; 409 error = ENOENT;
407 goto out; 410 goto out;
408 } 411 }
409 412
410 error = pfil_add_ihook(npf_ifhook, NULL, 413 error = pfil_add_ihook(npf_ifhook, NULL,
411 PFIL_IFNET, npf_ph_if); 414 PFIL_IFNET, npf_ph_if);
412 KASSERT(error == 0); 415 KASSERT(error == 0);
413 416
414 error = pfil_add_ihook(npf_ifaddrhook, NULL, 417 error = pfil_add_ihook(npf_ifaddrhook, NULL,
415 PFIL_IFADDR, npf_ph_if); 418 PFIL_IFADDR, npf_ph_if);
416 KASSERT(error == 0); 419 KASSERT(error == 0);
417 } 420 }
418 if (init) { 421 if (init) {
419 goto out; 422 goto out;
420 } 423 }
421 424
422 /* Check if pfil hooks are not already registered. */ 425 /* Check if pfil hooks are not already registered. */
423 if (pfil_registered) { 426 if (pfil_registered) {
424 error = EEXIST; 427 error = EEXIST;
425 goto out; 428 goto out;
426 } 429 }
427 430
428 /* Capture points of the activity in the IP layer. */ 431 /* Capture points of the activity in the IP layer. */
429 npf_ph_inet = pfil_head_get(PFIL_TYPE_AF, (void *)AF_INET); 432 npf_ph_inet = pfil_head_get(PFIL_TYPE_AF, (void *)AF_INET);
430 npf_ph_inet6 = pfil_head_get(PFIL_TYPE_AF, (void *)AF_INET6); 433 npf_ph_inet6 = pfil_head_get(PFIL_TYPE_AF, (void *)AF_INET6);
431 if (!npf_ph_inet && !npf_ph_inet6) { 434 if (!npf_ph_inet && !npf_ph_inet6) {
432 error = ENOENT; 435 error = ENOENT;
433 goto out; 436 goto out;
434 } 437 }
435 438
436 /* Packet IN/OUT handlers for IP layer. */ 439 /* Packet IN/OUT handlers for IP layer. */
437 if (npf_ph_inet) { 440 if (npf_ph_inet) {
438 error = pfil_add_hook(npfkern_packet_handler, npf, 441 error = pfil_add_hook(npfkern_packet_handler, npf,
439 PFIL_ALL, npf_ph_inet); 442 PFIL_ALL, npf_ph_inet);
440 KASSERT(error == 0); 443 KASSERT(error == 0);
441 } 444 }
442 if (npf_ph_inet6) { 445 if (npf_ph_inet6) {
443 error = pfil_add_hook(npfkern_packet_handler, npf, 446 error = pfil_add_hook(npfkern_packet_handler, npf,
444 PFIL_ALL, npf_ph_inet6); 447 PFIL_ALL, npf_ph_inet6);
445 KASSERT(error == 0); 448 KASSERT(error == 0);
446 } 449 }
447 450
448 /* 451 /*
449 * It is necessary to re-sync all/any interface address tables, 452 * It is necessary to re-sync all/any interface address tables,
450 * since we did not listen for any changes. 453 * since we did not listen for any changes.
451 */ 454 */
452 npf_ifaddr_syncall(npf); 455 npf_ifaddr_syncall(npf);
453 pfil_registered = true; 456 pfil_registered = true;
454out: 457out:
 458#ifndef NET_MPSAFE
455 KERNEL_UNLOCK_ONE(NULL); 459 KERNEL_UNLOCK_ONE(NULL);
456 mutex_exit(softnet_lock); 460 mutex_exit(softnet_lock);
 461#endif
457 462
458 return error; 463 return error;
459} 464}
460 465
461/* 466/*
462 * npf_pfil_unregister: unregister pfil(9) hooks. 467 * npf_pfil_unregister: unregister pfil(9) hooks.
463 */ 468 */
464void 469void
465npf_pfil_unregister(bool fini) 470npf_pfil_unregister(bool fini)
466{ 471{
467 npf_t *npf = npf_getkernctx(); 472 npf_t *npf = npf_getkernctx();
468 473
 474#ifndef NET_MPSAFE
469 mutex_enter(softnet_lock); 475 mutex_enter(softnet_lock);
470 KERNEL_LOCK(1, NULL); 476 KERNEL_LOCK(1, NULL);
 477#endif
471 478
472 if (fini && npf_ph_if) { 479 if (fini && npf_ph_if) {
473 (void)pfil_remove_ihook(npf_ifhook, NULL, 480 (void)pfil_remove_ihook(npf_ifhook, NULL,
474 PFIL_IFNET, npf_ph_if); 481 PFIL_IFNET, npf_ph_if);
475 (void)pfil_remove_ihook(npf_ifaddrhook, NULL, 482 (void)pfil_remove_ihook(npf_ifaddrhook, NULL,
476 PFIL_IFADDR, npf_ph_if); 483 PFIL_IFADDR, npf_ph_if);
477 } 484 }
478 if (npf_ph_inet) { 485 if (npf_ph_inet) {
479 (void)pfil_remove_hook(npfkern_packet_handler, npf, 486 (void)pfil_remove_hook(npfkern_packet_handler, npf,
480 PFIL_ALL, npf_ph_inet); 487 PFIL_ALL, npf_ph_inet);
481 } 488 }
482 if (npf_ph_inet6) { 489 if (npf_ph_inet6) {
483 (void)pfil_remove_hook(npfkern_packet_handler, npf, 490 (void)pfil_remove_hook(npfkern_packet_handler, npf,
484 PFIL_ALL, npf_ph_inet6); 491 PFIL_ALL, npf_ph_inet6);
485 } 492 }
486 pfil_registered = false; 493 pfil_registered = false;
487 494
 495#ifndef NET_MPSAFE
488 KERNEL_UNLOCK_ONE(NULL); 496 KERNEL_UNLOCK_ONE(NULL);
489 mutex_exit(softnet_lock); 497 mutex_exit(softnet_lock);
 498#endif
490} 499}
491 500
492bool 501bool
493npf_pfil_registered_p(void) 502npf_pfil_registered_p(void)
494{ 503{
495 return pfil_registered; 504 return pfil_registered;
496} 505}
497#endif 506#endif