1255332Scy/* $FreeBSD$ */
2255332Scy
3255332Scy/*
4255332Scy * Copyright (C) 2012 by Darren Reed.
5255332Scy *
6255332Scy * See the IPFILTER.LICENCE file for details on licencing.
7255332Scy */
8255332Scy
9255332Scy
10255332Scy#include <sys/param.h>
11255332Scy#include <sys/systm.h>
12255332Scy#include <sys/kernel.h>
13255332Scy#include <sys/module.h>
14255332Scy#include <sys/conf.h>
15255332Scy#include <sys/socket.h>
16255332Scy#include <sys/sysctl.h>
17255332Scy#include <sys/select.h>
18255332Scy#if __FreeBSD_version >= 500000
19255332Scy# include <sys/selinfo.h>
20255332Scy#endif
21255332Scy#include <net/if.h>
22255332Scy#include <netinet/in_systm.h>
23255332Scy#include <netinet/in.h>
24255332Scy
25255332Scy
26255332Scy#include "netinet/ipl.h"
27255332Scy#include "netinet/ip_compat.h"
28255332Scy#include "netinet/ip_fil.h"
29255332Scy#include "netinet/ip_state.h"
30255332Scy#include "netinet/ip_nat.h"
31255332Scy#include "netinet/ip_auth.h"
32255332Scy#include "netinet/ip_frag.h"
33255332Scy#include "netinet/ip_sync.h"
34255332Scy
35255332Scyextern ipf_main_softc_t ipfmain;
36255332Scy
37255332Scy#if __FreeBSD_version >= 502116
38255332Scystatic struct cdev *ipf_devs[IPL_LOGSIZE];
39255332Scy#else
40255332Scystatic dev_t ipf_devs[IPL_LOGSIZE];
41255332Scy#endif
42255332Scy
43255332Scy#if 0
44255332Scystatic int sysctl_ipf_int ( SYSCTL_HANDLER_ARGS );
45255332Scy#endif
46255332Scystatic int ipf_modload(void);
47255332Scystatic int ipf_modunload(void);
48255332Scy
49255332Scy#if (__FreeBSD_version >= 500024)
50255332Scy# if (__FreeBSD_version >= 502116)
51255332Scystatic	int	ipfopen __P((struct cdev*, int, int, struct thread *));
52255332Scystatic	int	ipfclose __P((struct cdev*, int, int, struct thread *));
53255332Scy# else
54255332Scystatic	int	ipfopen __P((dev_t, int, int, struct thread *));
55255332Scystatic	int	ipfclose __P((dev_t, int, int, struct thread *));
56255332Scy# endif /* __FreeBSD_version >= 502116 */
57255332Scy#else
58255332Scystatic	int	ipfopen __P((dev_t, int, int, struct proc *));
59255332Scystatic	int	ipfclose __P((dev_t, int, int, struct proc *));
60255332Scy#endif
61255332Scy#if (__FreeBSD_version >= 502116)
62255332Scystatic	int	ipfread __P((struct cdev*, struct uio *, int));
63255332Scystatic	int	ipfwrite __P((struct cdev*, struct uio *, int));
64255332Scy#else
65255332Scystatic	int	ipfread __P((dev_t, struct uio *, int));
66255332Scystatic	int	ipfwrite __P((dev_t, struct uio *, int));
67255332Scy#endif /* __FreeBSD_version >= 502116 */
68255332Scy
69255332Scy
70255332Scy
71255332ScySYSCTL_DECL(_net_inet);
72255332Scy#define SYSCTL_IPF(parent, nbr, name, access, ptr, val, descr) \
73255332Scy	SYSCTL_OID(parent, nbr, name, CTLTYPE_INT|access, \
74255332Scy		   ptr, val, sysctl_ipf_int, "I", descr);
75255332Scy#define	CTLFLAG_OFF	0x00800000	/* IPFilter must be disabled */
76255332Scy#define	CTLFLAG_RWO	(CTLFLAG_RW|CTLFLAG_OFF)
77255332ScySYSCTL_NODE(_net_inet, OID_AUTO, ipf, CTLFLAG_RW, 0, "IPF");
78255332Scy#if 0
79255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_flags, CTLFLAG_RW, &ipf_flags, 0, "");
80255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_pass, CTLFLAG_RW, &ipf_pass, 0, "");
81255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_active, CTLFLAG_RD, &ipf_active, 0, "");
82255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpidletimeout, CTLFLAG_RWO,
83255332Scy	   &ipf_tcpidletimeout, 0, "");
84255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcphalfclosed, CTLFLAG_RWO,
85255332Scy	   &ipf_tcphalfclosed, 0, "");
86255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpclosewait, CTLFLAG_RWO,
87255332Scy	   &ipf_tcpclosewait, 0, "");
88255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcplastack, CTLFLAG_RWO,
89255332Scy	   &ipf_tcplastack, 0, "");
90255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcptimeout, CTLFLAG_RWO,
91255332Scy	   &ipf_tcptimeout, 0, "");
92255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpclosed, CTLFLAG_RWO,
93255332Scy	   &ipf_tcpclosed, 0, "");
94255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_udptimeout, CTLFLAG_RWO,
95255332Scy	   &ipf_udptimeout, 0, "");
96255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_udpacktimeout, CTLFLAG_RWO,
97255332Scy	   &ipf_udpacktimeout, 0, "");
98255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_icmptimeout, CTLFLAG_RWO,
99255332Scy	   &ipf_icmptimeout, 0, "");
100255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_defnatage, CTLFLAG_RWO,
101255332Scy	   &ipf_nat_defage, 0, "");
102255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_ipfrttl, CTLFLAG_RW,
103255332Scy	   &ipf_ipfrttl, 0, "");
104255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_running, CTLFLAG_RD,
105255332Scy	   &ipf_running, 0, "");
106255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_statesize, CTLFLAG_RWO,
107255332Scy	   &ipf_state_size, 0, "");
108255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_statemax, CTLFLAG_RWO,
109255332Scy	   &ipf_state_max, 0, "");
110255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_nattable_sz, CTLFLAG_RWO,
111255332Scy	   &ipf_nat_table_sz, 0, "");
112255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_natrules_sz, CTLFLAG_RWO,
113255332Scy	   &ipf_nat_maprules_sz, 0, "");
114255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_rdrrules_sz, CTLFLAG_RWO,
115255332Scy	   &ipf_nat_rdrrules_sz, 0, "");
116255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_hostmap_sz, CTLFLAG_RWO,
117255332Scy	   &ipf_nat_hostmap_sz, 0, "");
118255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_authsize, CTLFLAG_RWO,
119255332Scy	   &ipf_auth_size, 0, "");
120255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_authused, CTLFLAG_RD,
121255332Scy	   &ipf_auth_used, 0, "");
122255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_defaultauthage, CTLFLAG_RW,
123255332Scy	   &ipf_auth_defaultage, 0, "");
124255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_chksrc, CTLFLAG_RW, &ipf_chksrc, 0, "");
125255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_minttl, CTLFLAG_RW, &ipf_minttl, 0, "");
126255332Scy#endif
127255332Scy
128255332Scy#define CDEV_MAJOR 79
129255332Scy#include <sys/poll.h>
130255332Scy#if __FreeBSD_version >= 500043
131255332Scy# include <sys/select.h>
132255332Scystatic int ipfpoll(struct cdev *dev, int events, struct thread *td);
133255332Scy
134255332Scystatic struct cdevsw ipf_cdevsw = {
135255332Scy#if __FreeBSD_version >= 502103
136255332Scy	.d_version =	D_VERSION,
137255332Scy	.d_flags =	0,	/* D_NEEDGIANT - Should be SMP safe */
138255332Scy#endif
139255332Scy	.d_open =	ipfopen,
140255332Scy	.d_close =	ipfclose,
141255332Scy	.d_read =	ipfread,
142255332Scy	.d_write =	ipfwrite,
143255332Scy	.d_ioctl =	ipfioctl,
144255332Scy	.d_poll =	ipfpoll,
145255332Scy	.d_name =	"ipf",
146255332Scy#if __FreeBSD_version < 600000
147255332Scy	.d_maj =	CDEV_MAJOR,
148255332Scy#endif
149255332Scy};
150255332Scy#else
151255332Scystatic int ipfpoll(dev_t dev, int events, struct proc *td);
152255332Scy
153255332Scystatic struct cdevsw ipf_cdevsw = {
154255332Scy	/* open */	ipfopen,
155255332Scy	/* close */	ipfclose,
156255332Scy	/* read */	ipfread,
157255332Scy	/* write */	ipfwrite,
158255332Scy	/* ioctl */	ipfioctl,
159255332Scy	/* poll */	ipfpoll,
160255332Scy	/* mmap */	nommap,
161255332Scy	/* strategy */	nostrategy,
162255332Scy	/* name */	"ipf",
163255332Scy	/* maj */	CDEV_MAJOR,
164255332Scy	/* dump */	nodump,
165255332Scy	/* psize */	nopsize,
166255332Scy	/* flags */	0,
167255332Scy# if (__FreeBSD_version < 500043)
168255332Scy	/* bmaj */	-1,
169255332Scy# endif
170255332Scy# if (__FreeBSD_version >= 430000)
171255332Scy	/* kqfilter */	NULL
172255332Scy# endif
173255332Scy};
174255332Scy#endif
175255332Scy
176255332Scystatic char *ipf_devfiles[] = {	IPL_NAME, IPNAT_NAME, IPSTATE_NAME, IPAUTH_NAME,
177255332Scy				IPSYNC_NAME, IPSCAN_NAME, IPLOOKUP_NAME, NULL };
178255332Scy
179255332Scy
180255332Scystatic int
181255332Scyipfilter_modevent(module_t mod, int type, void *unused)
182255332Scy{
183255332Scy	int error = 0;
184255332Scy
185255332Scy	switch (type)
186255332Scy	{
187255332Scy	case MOD_LOAD :
188255332Scy		error = ipf_modload();
189255332Scy		break;
190255332Scy
191255332Scy	case MOD_UNLOAD :
192255332Scy		error = ipf_modunload();
193255332Scy		break;
194255332Scy	default:
195255332Scy		error = EINVAL;
196255332Scy		break;
197255332Scy	}
198255332Scy	return error;
199255332Scy}
200255332Scy
201255332Scy
202255332Scystatic int
203255332Scyipf_modload()
204255332Scy{
205255332Scy	char *defpass, *c, *str;
206255332Scy	int i, j, error;
207255332Scy
208255332Scy	if (ipf_load_all() != 0)
209255332Scy		return EIO;
210255332Scy
211255332Scy	if (ipf_create_all(&ipfmain) == NULL)
212255332Scy		return EIO;
213255332Scy
214255332Scy	error = ipfattach(&ipfmain);
215255332Scy	if (error)
216255332Scy		return error;
217255332Scy
218255332Scy	for (i = 0; i < IPL_LOGSIZE; i++)
219255332Scy		ipf_devs[i] = NULL;
220255332Scy
221255332Scy	for (i = 0; (str = ipf_devfiles[i]); i++) {
222255332Scy		c = NULL;
223255332Scy		for(j = strlen(str); j > 0; j--)
224255332Scy			if (str[j] == '/') {
225255332Scy				c = str + j + 1;
226255332Scy				break;
227255332Scy			}
228255332Scy		if (!c)
229255332Scy			c = str;
230255332Scy		ipf_devs[i] = make_dev(&ipf_cdevsw, i, 0, 0, 0600, c);
231255332Scy	}
232255332Scy
233255332Scy	error = ipf_pfil_hook();
234255332Scy	if (error != 0)
235255332Scy		return error;
236255332Scy	ipf_event_reg();
237255332Scy
238255332Scy	if (FR_ISPASS(ipfmain.ipf_pass))
239255332Scy		defpass = "pass";
240255332Scy	else if (FR_ISBLOCK(ipfmain.ipf_pass))
241255332Scy		defpass = "block";
242255332Scy	else
243255332Scy		defpass = "no-match -> block";
244255332Scy
245255332Scy	printf("%s initialized.  Default = %s all, Logging = %s%s\n",
246255332Scy		ipfilter_version, defpass,
247255332Scy#ifdef IPFILTER_LOG
248255332Scy		"enabled",
249255332Scy#else
250255332Scy		"disabled",
251255332Scy#endif
252255332Scy#ifdef IPFILTER_COMPILED
253255332Scy		" (COMPILED)"
254255332Scy#else
255255332Scy		""
256255332Scy#endif
257255332Scy		);
258255332Scy	return 0;
259255332Scy}
260255332Scy
261255332Scy
262255332Scystatic int
263255332Scyipf_modunload()
264255332Scy{
265255332Scy	int error, i;
266255332Scy
267255332Scy	if (ipfmain.ipf_refcnt)
268255332Scy		return EBUSY;
269255332Scy
270255332Scy	error = ipf_pfil_unhook();
271255332Scy	if (error != 0)
272255332Scy		return error;
273255332Scy
274255332Scy	if (ipfmain.ipf_running >= 0) {
275255332Scy		error = ipfdetach(&ipfmain);
276255332Scy		if (error != 0)
277255332Scy			return error;
278255332Scy
279255332Scy		ipf_destroy_all(&ipfmain);
280255332Scy		ipf_unload_all();
281255332Scy	} else
282255332Scy		error = 0;
283255332Scy
284255332Scy	ipfmain.ipf_running = -2;
285255332Scy
286255332Scy	for (i = 0; ipf_devfiles[i]; i++) {
287255332Scy		if (ipf_devs[i] != NULL)
288255332Scy			destroy_dev(ipf_devs[i]);
289255332Scy	}
290255332Scy
291255332Scy	printf("%s unloaded\n", ipfilter_version);
292255332Scy
293255332Scy	return error;
294255332Scy}
295255332Scy
296255332Scy
297255332Scystatic moduledata_t ipfiltermod = {
298255332Scy	"ipfilter",
299255332Scy	ipfilter_modevent,
300255332Scy	0
301255332Scy};
302255332Scy
303255332Scy
304255332ScyDECLARE_MODULE(ipfilter, ipfiltermod, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY);
305255332Scy#ifdef	MODULE_VERSION
306255332ScyMODULE_VERSION(ipfilter, 1);
307255332Scy#endif
308255332Scy
309255332Scy
310255332Scy#if 0
311255332Scy#ifdef SYSCTL_IPF
312255332Scyint
313255332Scysysctl_ipf_int ( SYSCTL_HANDLER_ARGS )
314255332Scy{
315255332Scy	int error = 0;
316255332Scy
317255332Scy	if (arg1)
318255332Scy		error = SYSCTL_OUT(req, arg1, sizeof(int));
319255332Scy	else
320255332Scy		error = SYSCTL_OUT(req, &arg2, sizeof(int));
321255332Scy
322255332Scy	if (error || !req->newptr)
323255332Scy		return (error);
324255332Scy
325255332Scy	if (!arg1)
326255332Scy		error = EPERM;
327255332Scy	else {
328255332Scy		if ((oidp->oid_kind & CTLFLAG_OFF) && (ipfmain.ipf_running > 0))
329255332Scy			error = EBUSY;
330255332Scy		else
331255332Scy			error = SYSCTL_IN(req, arg1, sizeof(int));
332255332Scy	}
333255332Scy	return (error);
334255332Scy}
335255332Scy#endif
336255332Scy#endif
337255332Scy
338255332Scy
339255332Scystatic int
340255332Scy#if __FreeBSD_version >= 500043
341255332Scyipfpoll(struct cdev *dev, int events, struct thread *td)
342255332Scy#else
343255332Scyipfpoll(dev_t dev, int events, struct proc *td)
344255332Scy#endif
345255332Scy{
346255332Scy	u_int unit = GET_MINOR(dev);
347255332Scy	int revents;
348255332Scy
349255332Scy	if (unit < 0 || unit > IPL_LOGMAX)
350255332Scy		return 0;
351255332Scy
352255332Scy	revents = 0;
353255332Scy
354255332Scy	switch (unit)
355255332Scy	{
356255332Scy	case IPL_LOGIPF :
357255332Scy	case IPL_LOGNAT :
358255332Scy	case IPL_LOGSTATE :
359255332Scy#ifdef IPFILTER_LOG
360255332Scy		if ((events & (POLLIN | POLLRDNORM)) && ipf_log_canread(&ipfmain, unit))
361255332Scy			revents |= events & (POLLIN | POLLRDNORM);
362255332Scy#endif
363255332Scy		break;
364255332Scy	case IPL_LOGAUTH :
365255332Scy		if ((events & (POLLIN | POLLRDNORM)) && ipf_auth_waiting(&ipfmain))
366255332Scy			revents |= events & (POLLIN | POLLRDNORM);
367255332Scy		break;
368255332Scy	case IPL_LOGSYNC :
369255332Scy		if ((events & (POLLIN | POLLRDNORM)) && ipf_sync_canread(&ipfmain))
370255332Scy			revents |= events & (POLLIN | POLLRDNORM);
371255332Scy		if ((events & (POLLOUT | POLLWRNORM)) && ipf_sync_canwrite(&ipfmain))
372255332Scy			revents |= events & (POLLOUT | POLLWRNORM);
373255332Scy		break;
374255332Scy	case IPL_LOGSCAN :
375255332Scy	case IPL_LOGLOOKUP :
376255332Scy	default :
377255332Scy		break;
378255332Scy	}
379255332Scy
380255332Scy	if ((revents == 0) && ((events & (POLLIN|POLLRDNORM)) != 0))
381255332Scy		selrecord(td, &ipfmain.ipf_selwait[unit]);
382255332Scy
383255332Scy	return revents;
384255332Scy}
385255332Scy
386255332Scy
387255332Scy/*
388255332Scy * routines below for saving IP headers to buffer
389255332Scy */
390255332Scystatic int ipfopen(dev, flags
391255332Scy#if ((BSD >= 199506) || (__FreeBSD_version >= 220000))
392255332Scy, devtype, p)
393255332Scy	int devtype;
394255332Scy# if (__FreeBSD_version >= 500024)
395255332Scy	struct thread *p;
396255332Scy# else
397255332Scy	struct proc *p;
398255332Scy# endif /* __FreeBSD_version >= 500024 */
399255332Scy#else
400255332Scy)
401255332Scy#endif
402255332Scy#if (__FreeBSD_version >= 502116)
403255332Scy	struct cdev *dev;
404255332Scy#else
405255332Scy	dev_t dev;
406255332Scy#endif
407255332Scy	int flags;
408255332Scy{
409255332Scy	u_int unit = GET_MINOR(dev);
410255332Scy	int error;
411255332Scy
412255332Scy	if (IPL_LOGMAX < unit)
413255332Scy		error = ENXIO;
414255332Scy	else {
415255332Scy		switch (unit)
416255332Scy		{
417255332Scy		case IPL_LOGIPF :
418255332Scy		case IPL_LOGNAT :
419255332Scy		case IPL_LOGSTATE :
420255332Scy		case IPL_LOGAUTH :
421255332Scy		case IPL_LOGLOOKUP :
422255332Scy		case IPL_LOGSYNC :
423255332Scy#ifdef IPFILTER_SCAN
424255332Scy		case IPL_LOGSCAN :
425255332Scy#endif
426255332Scy			error = 0;
427255332Scy			break;
428255332Scy		default :
429255332Scy			error = ENXIO;
430255332Scy			break;
431255332Scy		}
432255332Scy	}
433255332Scy	return error;
434255332Scy}
435255332Scy
436255332Scy
437255332Scystatic int ipfclose(dev, flags
438255332Scy#if ((BSD >= 199506) || (__FreeBSD_version >= 220000))
439255332Scy, devtype, p)
440255332Scy	int devtype;
441255332Scy# if (__FreeBSD_version >= 500024)
442255332Scy	struct thread *p;
443255332Scy# else
444255332Scy	struct proc *p;
445255332Scy# endif /* __FreeBSD_version >= 500024 */
446255332Scy#else
447255332Scy)
448255332Scy#endif
449255332Scy#if (__FreeBSD_version >= 502116)
450255332Scy	struct cdev *dev;
451255332Scy#else
452255332Scy	dev_t dev;
453255332Scy#endif
454255332Scy	int flags;
455255332Scy{
456255332Scy	u_int	unit = GET_MINOR(dev);
457255332Scy
458255332Scy	if (IPL_LOGMAX < unit)
459255332Scy		unit = ENXIO;
460255332Scy	else
461255332Scy		unit = 0;
462255332Scy	return unit;
463255332Scy}
464255332Scy
465255332Scy/*
466255332Scy * ipfread/ipflog
467255332Scy * both of these must operate with at least splnet() lest they be
468255332Scy * called during packet processing and cause an inconsistancy to appear in
469255332Scy * the filter lists.
470255332Scy */
471255332Scy#if (BSD >= 199306)
472255332Scystatic int ipfread(dev, uio, ioflag)
473255332Scy	int ioflag;
474255332Scy#else
475255332Scystatic int ipfread(dev, uio)
476255332Scy#endif
477255332Scy#if (__FreeBSD_version >= 502116)
478255332Scy	struct cdev *dev;
479255332Scy#else
480255332Scy	dev_t dev;
481255332Scy#endif
482255332Scy	struct uio *uio;
483255332Scy{
484255332Scy	u_int	unit = GET_MINOR(dev);
485255332Scy
486255332Scy	if (unit < 0)
487255332Scy		return ENXIO;
488255332Scy
489255332Scy	if (ipfmain.ipf_running < 1)
490255332Scy		return EIO;
491255332Scy
492255332Scy	if (unit == IPL_LOGSYNC)
493255332Scy		return ipf_sync_read(&ipfmain, uio);
494255332Scy
495255332Scy#ifdef IPFILTER_LOG
496255332Scy	return ipf_log_read(&ipfmain, unit, uio);
497255332Scy#else
498255332Scy	return ENXIO;
499255332Scy#endif
500255332Scy}
501255332Scy
502255332Scy
503255332Scy/*
504255332Scy * ipfwrite
505255332Scy * both of these must operate with at least splnet() lest they be
506255332Scy * called during packet processing and cause an inconsistancy to appear in
507255332Scy * the filter lists.
508255332Scy */
509255332Scy#if (BSD >= 199306)
510255332Scystatic int ipfwrite(dev, uio, ioflag)
511255332Scy	int ioflag;
512255332Scy#else
513255332Scystatic int ipfwrite(dev, uio)
514255332Scy#endif
515255332Scy#if (__FreeBSD_version >= 502116)
516255332Scy	struct cdev *dev;
517255332Scy#else
518255332Scy	dev_t dev;
519255332Scy#endif
520255332Scy	struct uio *uio;
521255332Scy{
522255332Scy
523255332Scy	if (ipfmain.ipf_running < 1)
524255332Scy		return EIO;
525255332Scy
526255332Scy	if (GET_MINOR(dev) == IPL_LOGSYNC)
527255332Scy		return ipf_sync_write(&ipfmain, uio);
528255332Scy	return ENXIO;
529255332Scy}
530