xref: /freebsd/sys/netpfil/ipfilter/netinet/mlfk_ipl.c (revision d9788eabffa4b67fc534685fc3d9b8e3334af196)
1 
2 /*
3  * Copyright (C) 2012 by Darren Reed.
4  * See the IPFILTER.LICENCE file for details on licencing.
5  */
6 
7 #if defined(KERNEL) || defined(_KERNEL)
8 # undef KERNEL
9 # undef _KERNEL
10 # define	KERNEL  1
11 # define	_KERNEL 1
12 #endif
13 
14 #include <sys/param.h>
15 #include <sys/systm.h>
16 #include <sys/kernel.h>
17 #include <sys/module.h>
18 #include <sys/conf.h>
19 #include <sys/socket.h>
20 #include <sys/sysctl.h>
21 #include <sys/select.h>
22 #ifdef __FreeBSD__
23 # include <sys/selinfo.h>
24 # include <sys/jail.h>
25 # ifdef _KERNEL
26 #  include <net/vnet.h>
27 # else
28 #  define CURVNET_SET(arg)
29 #  define CURVNET_RESTORE()
30 #  define	VNET_DEFINE(_t, _v)	_t _v
31 #  define	VNET_DECLARE(_t, _v)	extern _t _v
32 #  define	VNET(arg)	arg
33 # endif
34 #endif
35 #include <net/if.h>
36 #include <netinet/in_systm.h>
37 #include <netinet/in.h>
38 
39 
40 #include "netinet/ipl.h"
41 #include "netinet/ip_compat.h"
42 #include "netinet/ip_fil.h"
43 #include "netinet/ip_state.h"
44 #include "netinet/ip_nat.h"
45 #include "netinet/ip_auth.h"
46 #include "netinet/ip_frag.h"
47 #include "netinet/ip_sync.h"
48 
49 VNET_DECLARE(ipf_main_softc_t, ipfmain);
50 #define	V_ipfmain		VNET(ipfmain)
51 
52 #ifdef __FreeBSD__
53 static struct cdev *ipf_devs[IPL_LOGSIZE];
54 #else
55 static dev_t ipf_devs[IPL_LOGSIZE];
56 #endif
57 
58 static int sysctl_ipf_int ( SYSCTL_HANDLER_ARGS );
59 static int sysctl_ipf_int_nat ( SYSCTL_HANDLER_ARGS );
60 static int sysctl_ipf_int_state ( SYSCTL_HANDLER_ARGS );
61 static int sysctl_ipf_int_auth ( SYSCTL_HANDLER_ARGS );
62 static int sysctl_ipf_int_frag ( SYSCTL_HANDLER_ARGS );
63 static int ipf_modload(void);
64 static int ipf_modunload(void);
65 static int ipf_fbsd_sysctl_create(void);
66 static int ipf_fbsd_sysctl_destroy(void);
67 
68 #ifdef __FreeBSD__
69 static	int	ipfopen(struct cdev*, int, int, struct thread *);
70 static	int	ipfclose(struct cdev*, int, int, struct thread *);
71 static	int	ipfread(struct cdev*, struct uio *, int);
72 static	int	ipfwrite(struct cdev*, struct uio *, int);
73 #else
74 static	int	ipfopen(dev_t, int, int, struct proc *);
75 static	int	ipfclose(dev_t, int, int, struct proc *);
76 static	int	ipfread(dev_t, struct uio *, int);
77 static	int	ipfwrite(dev_t, struct uio *, int);
78 #endif
79 
80 #ifdef LARGE_NAT
81 #define IPF_LARGE_NAT	1
82 #else
83 #define IPF_LARGE_NAT	0
84 #endif
85 
86 SYSCTL_DECL(_net_inet);
87 #define SYSCTL_IPF(parent, nbr, name, access, ptr, val, descr) \
88     SYSCTL_OID(parent, nbr, name, \
89 	CTLTYPE_INT | CTLFLAG_VNET | CTLFLAG_MPSAFE | access, \
90 	ptr, val, sysctl_ipf_int, "I", descr)
91 #define SYSCTL_DYN_IPF_NAT(parent, nbr, name, access,ptr, val, descr) \
92     SYSCTL_ADD_OID(&ipf_clist, SYSCTL_STATIC_CHILDREN(parent), nbr, name, \
93 	CTLTYPE_INT | CTLFLAG_VNET | CTLFLAG_MPSAFE |access, \
94 	ptr, val, sysctl_ipf_int_nat, "I", descr)
95 #define SYSCTL_DYN_IPF_STATE(parent, nbr, name, access,ptr, val, descr) \
96     SYSCTL_ADD_OID(&ipf_clist, SYSCTL_STATIC_CHILDREN(parent), nbr, name, \
97 	CTLTYPE_INT | CTLFLAG_VNET | CTLFLAG_MPSAFE | access, \
98 	ptr, val, sysctl_ipf_int_state, "I", descr)
99 #define SYSCTL_DYN_IPF_FRAG(parent, nbr, name, access,ptr, val, descr) \
100     SYSCTL_ADD_OID(&ipf_clist, SYSCTL_STATIC_CHILDREN(parent), nbr, name, \
101 	CTLTYPE_INT | CTLFLAG_VNET | CTLFLAG_MPSAFE | access, \
102 	ptr, val, sysctl_ipf_int_frag, "I", descr)
103 #define SYSCTL_DYN_IPF_AUTH(parent, nbr, name, access,ptr, val, descr) \
104     SYSCTL_ADD_OID(&ipf_clist, SYSCTL_STATIC_CHILDREN(parent), nbr, name, \
105 	CTLTYPE_INT | CTLFLAG_VNET | CTLFLAG_MPSAFE | access, \
106 	ptr, val, sysctl_ipf_int_auth, "I", descr)
107 static struct sysctl_ctx_list ipf_clist;
108 #define	CTLFLAG_OFF	0x00800000	/* IPFilter must be disabled */
109 #define	CTLFLAG_RWO	(CTLFLAG_RW|CTLFLAG_OFF)
110 SYSCTL_NODE(_net_inet, OID_AUTO, ipf, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
111     "IPF");
112 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_flags, CTLFLAG_RW, &VNET_NAME(ipfmain.ipf_flags), 0, "IPF flags");
113 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_pass, CTLFLAG_RW, &VNET_NAME(ipfmain.ipf_pass), 0, "default pass/block");
114 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_active, CTLFLAG_RD, &VNET_NAME(ipfmain.ipf_active), 0, "IPF is active");
115 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpidletimeout, CTLFLAG_RWO,
116 	   &VNET_NAME(ipfmain.ipf_tcpidletimeout), 0, "TCP idle timeout in seconds");
117 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcphalfclosed, CTLFLAG_RWO,
118 	   &VNET_NAME(ipfmain.ipf_tcphalfclosed), 0, "timeout for half closed TCP sessions");
119 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpclosewait, CTLFLAG_RWO,
120 	   &VNET_NAME(ipfmain.ipf_tcpclosewait), 0, "timeout for TCP sessions in closewait status");
121 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcplastack, CTLFLAG_RWO,
122 	   &VNET_NAME(ipfmain.ipf_tcplastack), 0, "timeout for TCP sessions in last ack status");
123 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcptimeout, CTLFLAG_RWO,
124 	   &VNET_NAME(ipfmain.ipf_tcptimeout), 0, "");
125 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpclosed, CTLFLAG_RWO,
126 	   &VNET_NAME(ipfmain.ipf_tcpclosed), 0, "");
127 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_udptimeout, CTLFLAG_RWO,
128 	   &VNET_NAME(ipfmain.ipf_udptimeout), 0, "UDP timeout");
129 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_udpacktimeout, CTLFLAG_RWO,
130 	   &VNET_NAME(ipfmain.ipf_udpacktimeout), 0, "");
131 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_icmptimeout, CTLFLAG_RWO,
132 	   &VNET_NAME(ipfmain.ipf_icmptimeout), 0, "ICMP timeout");
133 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_running, CTLFLAG_RD,
134 	   &VNET_NAME(ipfmain.ipf_running), 0, "IPF is running");
135 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_chksrc, CTLFLAG_RW, &VNET_NAME(ipfmain.ipf_chksrc), 0, "");
136 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_minttl, CTLFLAG_RW, &VNET_NAME(ipfmain.ipf_minttl), 0, "");
137 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, large_nat, CTLFLAG_RDTUN | CTLFLAG_NOFETCH, &VNET_NAME(ipfmain.ipf_large_nat), 0, "large_nat");
138 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_max_namelen, CTLFLAG_RWTUN, &VNET_NAME(ipfmain.ipf_max_namelen), 0, "max_namelen");
139 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, jail_allowed, CTLFLAG_RWTUN, &VNET_NAME(ipfmain.ipf_jail_allowed), 0, "jail_allowed");
140 
141 #define CDEV_MAJOR 79
142 #include <sys/poll.h>
143 #ifdef __FreeBSD__
144 # include <sys/select.h>
145 static int ipfpoll(struct cdev *dev, int events, struct thread *td);
146 
147 static struct cdevsw ipf_cdevsw = {
148 	.d_version =	D_VERSION,
149 	.d_flags =	0,	/* D_NEEDGIANT - Should be SMP safe */
150 	.d_open =	ipfopen,
151 	.d_close =	ipfclose,
152 	.d_read =	ipfread,
153 	.d_write =	ipfwrite,
154 	.d_ioctl =	ipfioctl,
155 	.d_poll =	ipfpoll,
156 	.d_name =	"ipf",
157 };
158 #else
159 static int ipfpoll(dev_t dev, int events, struct proc *td);
160 
161 static struct cdevsw ipf_cdevsw = {
162 	/* open */	ipfopen,
163 	/* close */	ipfclose,
164 	/* read */	ipfread,
165 	/* write */	ipfwrite,
166 	/* ioctl */	ipfioctl,
167 	/* poll */	ipfpoll,
168 	/* mmap */	nommap,
169 	/* strategy */	nostrategy,
170 	/* name */	"ipf",
171 	/* maj */	CDEV_MAJOR,
172 	/* dump */	nodump,
173 	/* psize */	nopsize,
174 	/* flags */	0,
175 };
176 #endif
177 
178 static char *ipf_devfiles[] = {	IPL_NAME, IPNAT_NAME, IPSTATE_NAME, IPAUTH_NAME,
179 				IPSYNC_NAME, IPSCAN_NAME, IPLOOKUP_NAME, NULL };
180 
181 static int
ipfilter_modevent(module_t mod,int type,void * unused)182 ipfilter_modevent(module_t mod, int type, void *unused)
183 {
184 	int error = 0;
185 
186 	switch (type)
187 	{
188 	case MOD_LOAD :
189 		error = ipf_modload();
190 		break;
191 
192 	case MOD_UNLOAD :
193 		error = ipf_modunload();
194 		break;
195 	default:
196 		error = EINVAL;
197 		break;
198 	}
199 	return (error);
200 }
201 
202 
203 static void
vnet_ipf_init(void)204 vnet_ipf_init(void)
205 {
206 	char *defpass;
207 	int error;
208 
209 	if (ipf_create_all(&V_ipfmain) == NULL)
210 		return;
211 
212 	error = ipfattach(&V_ipfmain);
213 	if (error) {
214 		ipf_destroy_all(&V_ipfmain);
215 		return;
216 	}
217 
218 	if (FR_ISPASS(V_ipfmain.ipf_pass))
219 		defpass = "pass";
220 	else if (FR_ISBLOCK(V_ipfmain.ipf_pass))
221 		defpass = "block";
222 	else
223 		defpass = "no-match -> block";
224 
225 	if (IS_DEFAULT_VNET(curvnet)) {
226 	    printf("%s initialized.  Default = %s all, Logging = %s%s\n",
227 		ipfilter_version, defpass,
228 #ifdef IPFILTER_LOG
229 		"enabled",
230 #else
231 		"disabled",
232 #endif
233 #ifdef IPFILTER_COMPILED
234 		" (COMPILED)"
235 #else
236 		""
237 #endif
238 		);
239 	} else {
240 		(void)ipf_pfil_hook();
241 		ipf_event_reg();
242 	}
243 }
244 VNET_SYSINIT(vnet_ipf_init, SI_SUB_PROTO_FIREWALL, SI_ORDER_THIRD,
245     vnet_ipf_init, NULL);
246 
247 static int
ipf_modload(void)248 ipf_modload(void)
249 {
250 	char *c, *str;
251 	int i, j, error;
252 
253 	if (ipf_load_all() != 0)
254 		return (EIO);
255 
256 	if (ipf_fbsd_sysctl_create() != 0) {
257 		return (EIO);
258 	}
259 
260 	for (i = 0; i < IPL_LOGSIZE; i++)
261 		ipf_devs[i] = NULL;
262 	for (i = 0; (str = ipf_devfiles[i]); i++) {
263 		c = NULL;
264 		for(j = strlen(str); j > 0; j--)
265 			if (str[j] == '/') {
266 				c = str + j + 1;
267 				break;
268 			}
269 		if (!c)
270 			c = str;
271 		ipf_devs[i] = make_dev(&ipf_cdevsw, i, 0, 0, 0600, "%s", c);
272 	}
273 
274 	error = ipf_pfil_hook();
275 	if (error != 0)
276 		return (error);
277 	ipf_event_reg();
278 
279 	return (0);
280 }
281 
282 static void
vnet_ipf_uninit(void)283 vnet_ipf_uninit(void)
284 {
285 
286 	if (V_ipfmain.ipf_refcnt)
287 		return;
288 
289 	if (V_ipfmain.ipf_running >= 0) {
290 
291 		if (ipfdetach(&V_ipfmain) != 0)
292 			return;
293 
294 		V_ipfmain.ipf_running = -2;
295 
296 		ipf_destroy_all(&V_ipfmain);
297 		if (!IS_DEFAULT_VNET(curvnet)) {
298 			ipf_event_dereg();
299 			(void)ipf_pfil_unhook();
300 		}
301 	}
302 }
303 VNET_SYSUNINIT(vnet_ipf_uninit, SI_SUB_PROTO_FIREWALL, SI_ORDER_THIRD,
304     vnet_ipf_uninit, NULL);
305 
306 static int
ipf_modunload(void)307 ipf_modunload(void)
308 {
309 	int error, i;
310 
311 	ipf_event_dereg();
312 
313 	ipf_fbsd_sysctl_destroy();
314 
315 	error = ipf_pfil_unhook();
316 	if (error != 0)
317 		return (error);
318 
319 	for (i = 0; ipf_devfiles[i]; i++) {
320 		if (ipf_devs[i] != NULL)
321 			destroy_dev(ipf_devs[i]);
322 	}
323 
324 	ipf_unload_all();
325 
326 	printf("%s unloaded\n", ipfilter_version);
327 
328 	return (0);
329 }
330 
331 
332 static moduledata_t ipfiltermod = {
333 	"ipfilter",
334 	ipfilter_modevent,
335 	0
336 };
337 
338 
339 DECLARE_MODULE(ipfilter, ipfiltermod, SI_SUB_PROTO_FIREWALL, SI_ORDER_SECOND);
340 #ifdef	MODULE_VERSION
341 MODULE_VERSION(ipfilter, 1);
342 #endif
343 
344 
345 #ifdef SYSCTL_IPF
346 int
sysctl_ipf_int(SYSCTL_HANDLER_ARGS)347 sysctl_ipf_int ( SYSCTL_HANDLER_ARGS )
348 {
349 	int error = 0;
350 
351 	if (arg1)
352 		error = SYSCTL_OUT(req, arg1, sizeof(int));
353 	else
354 		error = SYSCTL_OUT(req, &arg2, sizeof(int));
355 
356 	if (error || !req->newptr)
357 		goto sysctl_error;
358 
359 	if (!arg1)
360 		error = EPERM;
361 	else {
362 		if ((oidp->oid_kind & CTLFLAG_OFF) && (V_ipfmain.ipf_running > 0))
363 			error = EBUSY;
364 		else
365 			error = SYSCTL_IN(req, arg1, sizeof(int));
366 	}
367 
368 sysctl_error:
369 	return (error);
370 }
371 
372 /*
373  * arg2 holds the offset of the relevant member in the virtualized
374  * ipfmain structure.
375  */
376 static int
sysctl_ipf_int_nat(SYSCTL_HANDLER_ARGS)377 sysctl_ipf_int_nat ( SYSCTL_HANDLER_ARGS )
378 {
379 	if (jailed_without_vnet(curthread->td_ucred))
380 		return (0);
381 
382 	ipf_nat_softc_t *nat_softc;
383 
384 	nat_softc = V_ipfmain.ipf_nat_soft;
385 	arg1 = (void *)((uintptr_t)nat_softc + (size_t)arg2);
386 
387 	return (sysctl_ipf_int(oidp, arg1, 0, req));
388 }
389 
390 static int
sysctl_ipf_int_state(SYSCTL_HANDLER_ARGS)391 sysctl_ipf_int_state ( SYSCTL_HANDLER_ARGS )
392 {
393 	if (jailed_without_vnet(curthread->td_ucred))
394 		return (0);
395 
396 	ipf_state_softc_t *state_softc;
397 
398 	state_softc = V_ipfmain.ipf_state_soft;
399 	arg1 = (void *)((uintptr_t)state_softc + (size_t)arg2);
400 
401 	return (sysctl_ipf_int(oidp, arg1, 0, req));
402 }
403 
404 static int
sysctl_ipf_int_auth(SYSCTL_HANDLER_ARGS)405 sysctl_ipf_int_auth ( SYSCTL_HANDLER_ARGS )
406 {
407 	if (jailed_without_vnet(curthread->td_ucred))
408 		return (0);
409 
410 	ipf_auth_softc_t *auth_softc;
411 
412 	auth_softc = V_ipfmain.ipf_auth_soft;
413 	arg1 = (void *)((uintptr_t)auth_softc + (size_t)arg2);
414 
415 	return (sysctl_ipf_int(oidp, arg1, 0, req));
416 }
417 
418 static int
sysctl_ipf_int_frag(SYSCTL_HANDLER_ARGS)419 sysctl_ipf_int_frag ( SYSCTL_HANDLER_ARGS )
420 {
421 	if (jailed_without_vnet(curthread->td_ucred))
422 		return (0);
423 
424 	ipf_frag_softc_t *frag_softc;
425 
426 	frag_softc = V_ipfmain.ipf_frag_soft;
427 	arg1 = (void *)((uintptr_t)frag_softc + (size_t)arg2);
428 
429 	return (sysctl_ipf_int(oidp, arg1, 0, req));
430 }
431 #endif
432 
433 
434 static int
435 #ifdef __FreeBSD__
ipfpoll(struct cdev * dev,int events,struct thread * td)436 ipfpoll(struct cdev *dev, int events, struct thread *td)
437 #else
438 ipfpoll(dev_t dev, int events, struct proc *td)
439 #endif
440 {
441 	int unit = GET_MINOR(dev);
442 	int revents;
443 
444 	if (unit < 0 || unit > IPL_LOGMAX)
445 		return (0);
446 
447 	revents = 0;
448 
449 	CURVNET_SET(TD_TO_VNET(td));
450 	switch (unit)
451 	{
452 	case IPL_LOGIPF :
453 	case IPL_LOGNAT :
454 	case IPL_LOGSTATE :
455 #ifdef IPFILTER_LOG
456 		if ((events & (POLLIN | POLLRDNORM)) && ipf_log_canread(&V_ipfmain, unit))
457 			revents |= events & (POLLIN | POLLRDNORM);
458 #endif
459 		break;
460 	case IPL_LOGAUTH :
461 		if ((events & (POLLIN | POLLRDNORM)) && ipf_auth_waiting(&V_ipfmain))
462 			revents |= events & (POLLIN | POLLRDNORM);
463 		break;
464 	case IPL_LOGSYNC :
465 		if ((events & (POLLIN | POLLRDNORM)) && ipf_sync_canread(&V_ipfmain))
466 			revents |= events & (POLLIN | POLLRDNORM);
467 		if ((events & (POLLOUT | POLLWRNORM)) && ipf_sync_canwrite(&V_ipfmain))
468 			revents |= events & (POLLOUT | POLLWRNORM);
469 		break;
470 	case IPL_LOGSCAN :
471 	case IPL_LOGLOOKUP :
472 	default :
473 		break;
474 	}
475 
476 	if ((revents == 0) && ((events & (POLLIN|POLLRDNORM)) != 0))
477 		selrecord(td, &V_ipfmain.ipf_selwait[unit]);
478 	CURVNET_RESTORE();
479 
480 	return (revents);
481 }
482 
483 
484 /*
485  * routines below for saving IP headers to buffer
486  */
487 static int
488 #ifdef __FreeBSD__
ipfopen(struct cdev * dev,int flags,int devtype,struct thread * p)489 ipfopen(struct cdev *dev, int flags, int devtype, struct thread *p)
490 #else
491 ipfopen(dev_t dev, int flags)
492 #endif
493 {
494 	int unit = GET_MINOR(dev);
495 	int error;
496 
497 	if (IPL_LOGMAX < unit)
498 		error = ENXIO;
499 	else {
500 		switch (unit)
501 		{
502 		case IPL_LOGIPF :
503 		case IPL_LOGNAT :
504 		case IPL_LOGSTATE :
505 		case IPL_LOGAUTH :
506 		case IPL_LOGLOOKUP :
507 		case IPL_LOGSYNC :
508 #ifdef IPFILTER_SCAN
509 		case IPL_LOGSCAN :
510 #endif
511 			error = 0;
512 			break;
513 		default :
514 			error = ENXIO;
515 			break;
516 		}
517 	}
518 	return (error);
519 }
520 
521 
522 static int
523 #ifdef __FreeBSD__
ipfclose(struct cdev * dev,int flags,int devtype,struct thread * p)524 ipfclose(struct cdev *dev, int flags, int devtype, struct thread *p)
525 #else
526 ipfclose(dev_t dev, int flags)
527 #endif
528 {
529 	int	unit = GET_MINOR(dev);
530 
531 	if (IPL_LOGMAX < unit)
532 		unit = ENXIO;
533 	else
534 		unit = 0;
535 	return (unit);
536 }
537 
538 /*
539  * ipfread/ipflog
540  * both of these must operate with at least splnet() lest they be
541  * called during packet processing and cause an inconsistency to appear in
542  * the filter lists.
543  */
544 #ifdef __FreeBSD__
ipfread(struct cdev * dev,struct uio * uio,int ioflag)545 static int ipfread(struct cdev *dev, struct uio *uio, int ioflag)
546 #else
547 static int ipfread(dev, uio, ioflag)
548 	int ioflag;
549 	dev_t dev;
550 	struct uio *uio;
551 #endif
552 {
553 	int error;
554 	int	unit = GET_MINOR(dev);
555 
556 	if (unit < 0)
557 		return (ENXIO);
558 
559 	CURVNET_SET(TD_TO_VNET(curthread));
560 	if (V_ipfmain.ipf_running < 1) {
561 		CURVNET_RESTORE();
562 		return (EIO);
563 	}
564 
565 	if (unit == IPL_LOGSYNC) {
566 		error = ipf_sync_read(&V_ipfmain, uio);
567 		CURVNET_RESTORE();
568 		return (error);
569 	}
570 
571 #ifdef IPFILTER_LOG
572 	error = ipf_log_read(&V_ipfmain, unit, uio);
573 #else
574 	error = ENXIO;
575 #endif
576 	CURVNET_RESTORE();
577 	return (error);
578 }
579 
580 
581 /*
582  * ipfwrite
583  * both of these must operate with at least splnet() lest they be
584  * called during packet processing and cause an inconsistency to appear in
585  * the filter lists.
586  */
587 #ifdef __FreeBSD__
ipfwrite(struct cdev * dev,struct uio * uio,int ioflag)588 static int ipfwrite(struct cdev *dev, struct uio *uio, int ioflag)
589 #else
590 static int ipfwrite(dev, uio, ioflag)
591 	int ioflag;
592 	dev_t dev;
593 	struct uio *uio;
594 #endif
595 {
596 	int error;
597 
598 	CURVNET_SET(TD_TO_VNET(curthread));
599 	if (V_ipfmain.ipf_running < 1) {
600 		CURVNET_RESTORE();
601 		return (EIO);
602 	}
603 
604 	if (GET_MINOR(dev) == IPL_LOGSYNC) {
605 		error = ipf_sync_write(&V_ipfmain, uio);
606 		CURVNET_RESTORE();
607 		return (error);
608 	}
609 	return (ENXIO);
610 }
611 
612 static int
ipf_fbsd_sysctl_create(void)613 ipf_fbsd_sysctl_create(void)
614 {
615 
616 	sysctl_ctx_init(&ipf_clist);
617 
618 	SYSCTL_DYN_IPF_NAT(_net_inet_ipf, OID_AUTO, "fr_defnatage", CTLFLAG_RWO,
619 	    NULL, offsetof(ipf_nat_softc_t, ipf_nat_defage), "");
620 	SYSCTL_DYN_IPF_STATE(_net_inet_ipf, OID_AUTO, "fr_statesize", CTLFLAG_RWO,
621 	    NULL, offsetof(ipf_state_softc_t, ipf_state_size), "");
622 	SYSCTL_DYN_IPF_STATE(_net_inet_ipf, OID_AUTO, "fr_statemax", CTLFLAG_RWO,
623 	    NULL, offsetof(ipf_state_softc_t, ipf_state_max), "");
624 	SYSCTL_DYN_IPF_NAT(_net_inet_ipf, OID_AUTO, "ipf_nattable_max", CTLFLAG_RWO,
625 	    NULL, offsetof(ipf_nat_softc_t, ipf_nat_table_max), "");
626 	SYSCTL_DYN_IPF_NAT(_net_inet_ipf, OID_AUTO, "ipf_nattable_sz", CTLFLAG_RWO,
627 	    NULL, offsetof(ipf_nat_softc_t, ipf_nat_table_sz), "");
628 	SYSCTL_DYN_IPF_NAT(_net_inet_ipf, OID_AUTO, "ipf_natrules_sz", CTLFLAG_RWO,
629 	    NULL, offsetof(ipf_nat_softc_t, ipf_nat_maprules_sz), "");
630 	SYSCTL_DYN_IPF_NAT(_net_inet_ipf, OID_AUTO, "ipf_rdrrules_sz", CTLFLAG_RWO,
631 	    NULL, offsetof(ipf_nat_softc_t, ipf_nat_rdrrules_sz), "");
632 	SYSCTL_DYN_IPF_NAT(_net_inet_ipf, OID_AUTO, "ipf_hostmap_sz", CTLFLAG_RWO,
633 	    NULL, offsetof(ipf_nat_softc_t, ipf_nat_hostmap_sz), "");
634 	SYSCTL_DYN_IPF_AUTH(_net_inet_ipf, OID_AUTO, "fr_authsize", CTLFLAG_RWO,
635 	    NULL, offsetof(ipf_auth_softc_t, ipf_auth_size), "");
636 	SYSCTL_DYN_IPF_AUTH(_net_inet_ipf, OID_AUTO, "fr_authused", CTLFLAG_RD,
637 	    NULL, offsetof(ipf_auth_softc_t, ipf_auth_used), "");
638 	SYSCTL_DYN_IPF_AUTH(_net_inet_ipf, OID_AUTO, "fr_defaultauthage", CTLFLAG_RW,
639 	    NULL, offsetof(ipf_auth_softc_t, ipf_auth_defaultage), "");
640 	SYSCTL_DYN_IPF_FRAG(_net_inet_ipf, OID_AUTO, "fr_ipfrttl", CTLFLAG_RW,
641 	    NULL, offsetof(ipf_frag_softc_t, ipfr_ttl), "");
642 	return (0);
643 }
644 
645 static int
ipf_fbsd_sysctl_destroy(void)646 ipf_fbsd_sysctl_destroy(void)
647 {
648 	if (sysctl_ctx_free(&ipf_clist)) {
649 		printf("sysctl_ctx_free failed");
650 		return (ENOTEMPTY);
651 	}
652 	return (0);
653 }
654