solaris.c revision 3448:aaf16568054b
1/*
2 * Copyright (C) 1993-2001, 2003 by Darren Reed.
3 *
4 * See the IPFILTER.LICENCE file for details on licencing.
5 *
6 * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
7 * Use is subject to license terms.
8 */
9/* #pragma ident   "@(#)solaris.c	1.12 6/5/96 (C) 1995 Darren Reed"*/
10#pragma ident "@(#)$Id: solaris.c,v 2.73.2.6 2005/07/13 21:40:47 darrenr Exp $"
11
12#pragma ident	"%Z%%M%	%I%	%E% SMI"
13
14#include <sys/systm.h>
15#include <sys/types.h>
16#include <sys/param.h>
17#include <sys/errno.h>
18#include <sys/uio.h>
19#include <sys/buf.h>
20#include <sys/modctl.h>
21#include <sys/open.h>
22#include <sys/kmem.h>
23#include <sys/conf.h>
24#include <sys/cmn_err.h>
25#include <sys/stat.h>
26#include <sys/cred.h>
27#include <sys/dditypes.h>
28#include <sys/poll.h>
29#include <sys/autoconf.h>
30#include <sys/byteorder.h>
31#include <sys/socket.h>
32#include <sys/dlpi.h>
33#include <sys/stropts.h>
34#include <sys/kstat.h>
35#include <sys/sockio.h>
36#include <sys/neti.h>
37#include <sys/hook.h>
38#include <net/if.h>
39#if SOLARIS2 >= 6
40# include <net/if_types.h>
41#endif
42#include <sys/netstack.h>
43#include <net/af.h>
44#include <net/route.h>
45#include <netinet/in.h>
46#include <netinet/in_systm.h>
47#include <netinet/if_ether.h>
48#include <netinet/ip.h>
49#include <netinet/ip_var.h>
50#include <netinet/tcp.h>
51#include <netinet/udp.h>
52#include <netinet/tcpip.h>
53#include <netinet/ip_icmp.h>
54#include <sys/ddi.h>
55#include <sys/sunddi.h>
56#include "netinet/ip_compat.h"
57#include "netinet/ipl.h"
58#include "netinet/ip_fil.h"
59#include "netinet/ip_nat.h"
60#include "netinet/ip_frag.h"
61#include "netinet/ip_auth.h"
62#include "netinet/ip_state.h"
63#include "netinet/ipf_stack.h"
64
65extern	int	iplwrite __P((dev_t, struct uio *, cred_t *));
66
67static	int	ipf_getinfo __P((dev_info_t *, ddi_info_cmd_t,
68				 void *, void **));
69#if SOLARIS2 < 10
70static	int	ipf_identify __P((dev_info_t *));
71#endif
72static	int	ipf_attach __P((dev_info_t *, ddi_attach_cmd_t));
73static	int	ipf_detach __P((dev_info_t *, ddi_detach_cmd_t));
74static	int	ipf_property_g_update __P((dev_info_t *));
75static	char	*ipf_devfiles[] = { IPL_NAME, IPNAT_NAME, IPSTATE_NAME,
76				    IPAUTH_NAME, IPSYNC_NAME, IPSCAN_NAME,
77				    IPLOOKUP_NAME, NULL };
78
79
80static struct cb_ops ipf_cb_ops = {
81	iplopen,
82	iplclose,
83	nodev,		/* strategy */
84	nodev,		/* print */
85	nodev,		/* dump */
86	iplread,
87	iplwrite,	/* write */
88	iplioctl,	/* ioctl */
89	nodev,		/* devmap */
90	nodev,		/* mmap */
91	nodev,		/* segmap */
92	nochpoll,	/* poll */
93	ddi_prop_op,
94	NULL,
95	D_MTSAFE,
96#if SOLARIS2 > 4
97	CB_REV,
98	nodev,		/* aread */
99	nodev,		/* awrite */
100#endif
101};
102
103static struct dev_ops ipf_ops = {
104	DEVO_REV,
105	0,
106	ipf_getinfo,
107#if SOLARIS2 >= 10
108	nulldev,
109#else
110	ipf_identify,
111#endif
112	nulldev,
113	ipf_attach,
114	ipf_detach,
115	nodev,		/* reset */
116	&ipf_cb_ops,
117	(struct bus_ops *)0
118};
119
120extern struct mod_ops mod_driverops;
121static struct modldrv iplmod = {
122	&mod_driverops, IPL_VERSION, &ipf_ops };
123static struct modlinkage modlink1 = { MODREV_1, &iplmod, NULL };
124
125#if SOLARIS2 >= 6
126static	size_t	hdrsizes[57][2] = {
127	{ 0, 0 },
128	{ IFT_OTHER, 0 },
129	{ IFT_1822, 0 },
130	{ IFT_HDH1822, 0 },
131	{ IFT_X25DDN, 0 },
132	{ IFT_X25, 0 },
133	{ IFT_ETHER, 14 },
134	{ IFT_ISO88023, 0 },
135	{ IFT_ISO88024, 0 },
136	{ IFT_ISO88025, 0 },
137	{ IFT_ISO88026, 0 },
138	{ IFT_STARLAN, 0 },
139	{ IFT_P10, 0 },
140	{ IFT_P80, 0 },
141	{ IFT_HY, 0 },
142	{ IFT_FDDI, 24 },
143	{ IFT_LAPB, 0 },
144	{ IFT_SDLC, 0 },
145	{ IFT_T1, 0 },
146	{ IFT_CEPT, 0 },
147	{ IFT_ISDNBASIC, 0 },
148	{ IFT_ISDNPRIMARY, 0 },
149	{ IFT_PTPSERIAL, 0 },
150	{ IFT_PPP, 0 },
151	{ IFT_LOOP, 0 },
152	{ IFT_EON, 0 },
153	{ IFT_XETHER, 0 },
154	{ IFT_NSIP, 0 },
155	{ IFT_SLIP, 0 },
156	{ IFT_ULTRA, 0 },
157	{ IFT_DS3, 0 },
158	{ IFT_SIP, 0 },
159	{ IFT_FRELAY, 0 },
160	{ IFT_RS232, 0 },
161	{ IFT_PARA, 0 },
162	{ IFT_ARCNET, 0 },
163	{ IFT_ARCNETPLUS, 0 },
164	{ IFT_ATM, 0 },
165	{ IFT_MIOX25, 0 },
166	{ IFT_SONET, 0 },
167	{ IFT_X25PLE, 0 },
168	{ IFT_ISO88022LLC, 0 },
169	{ IFT_LOCALTALK, 0 },
170	{ IFT_SMDSDXI, 0 },
171	{ IFT_FRELAYDCE, 0 },
172	{ IFT_V35, 0 },
173	{ IFT_HSSI, 0 },
174	{ IFT_HIPPI, 0 },
175	{ IFT_MODEM, 0 },
176	{ IFT_AAL5, 0 },
177	{ IFT_SONETPATH, 0 },
178	{ IFT_SONETVT, 0 },
179	{ IFT_SMDSICIP, 0 },
180	{ IFT_PROPVIRTUAL, 0 },
181	{ IFT_PROPMUX, 0 },
182};
183#endif /* SOLARIS2 >= 6 */
184
185dev_info_t *ipf_dev_info = NULL;
186
187static const filter_kstats_t ipf_kstat_tmp = {
188	{ "pass",			KSTAT_DATA_ULONG },
189	{ "block",			KSTAT_DATA_ULONG },
190	{ "nomatch",			KSTAT_DATA_ULONG },
191	{ "short",			KSTAT_DATA_ULONG },
192	{ "pass, logged",		KSTAT_DATA_ULONG },
193	{ "block, logged",		KSTAT_DATA_ULONG },
194	{ "nomatch, logged",		KSTAT_DATA_ULONG },
195	{ "logged",			KSTAT_DATA_ULONG },
196	{ "skip",			KSTAT_DATA_ULONG },
197	{ "return sent",		KSTAT_DATA_ULONG },
198	{ "acct",			KSTAT_DATA_ULONG },
199	{ "bad frag state alloc",	KSTAT_DATA_ULONG },
200	{ "new frag state kept",	KSTAT_DATA_ULONG },
201	{ "new frag state compl. pkt",	KSTAT_DATA_ULONG },
202	{ "bad pkt state alloc",	KSTAT_DATA_ULONG },
203	{ "new pkt kept state",		KSTAT_DATA_ULONG },
204	{ "cachehit",			KSTAT_DATA_ULONG },
205	{ "tcp cksum bad",		KSTAT_DATA_ULONG },
206	{{ "pullup ok",			KSTAT_DATA_ULONG },
207	{ "pullup nok",			KSTAT_DATA_ULONG }},
208	{ "src != route",		KSTAT_DATA_ULONG },
209	{ "ttl invalid",		KSTAT_DATA_ULONG },
210	{ "bad ip pkt",			KSTAT_DATA_ULONG },
211	{ "ipv6 pkt",			KSTAT_DATA_ULONG },
212	{ "dropped:pps ceiling",	KSTAT_DATA_ULONG },
213	{ "ip upd. fail",		KSTAT_DATA_ULONG }
214};
215
216
217static int	ipf_kstat_update(kstat_t *ksp, int rwflag);
218
219static void
220ipf_kstat_init(ipf_stack_t *ifs, netstackid_t stackid)
221{
222	int 	i;
223
224	for (i = 0; i < 2; i++) {
225		ifs->ifs_kstatp[i] = kstat_create_netstack("ipf", 0,
226			(i==0)?"inbound":"outbound",
227			"net",
228			KSTAT_TYPE_NAMED,
229			sizeof (filter_kstats_t) / sizeof (kstat_named_t),
230			0, stackid);
231		if (ifs->ifs_kstatp[i] != NULL) {
232			bcopy(&ipf_kstat_tmp, ifs->ifs_kstatp[i]->ks_data,
233				sizeof (filter_kstats_t));
234			ifs->ifs_kstatp[i]->ks_update = ipf_kstat_update;
235			ifs->ifs_kstatp[i]->ks_private = &ifs->ifs_frstats[i];
236			kstat_install(ifs->ifs_kstatp[i]);
237		}
238	}
239
240#ifdef	IPFDEBUG
241	cmn_err(CE_NOTE, "IP Filter: ipf_kstat_init() installed 0x%x, 0x%x",
242		ifs->ifs_kstatp[0], ifs->ifs_kstatp[1]);
243#endif
244}
245
246static void
247ipf_kstat_fini(ipf_stack_t *ifs, netstackid_t stackid)
248{
249	int i;
250
251	for (i = 0; i < 2; i++) {
252		if (ifs->ifs_kstatp[i] != NULL) {
253			kstat_delete_netstack(ifs->ifs_kstatp[i], stackid);
254			ifs->ifs_kstatp[i] = NULL;
255		}
256	}
257}
258
259static int
260ipf_kstat_update(kstat_t *ksp, int rwflag)
261{
262	filter_kstats_t	*fkp;
263	filterstats_t	*fsp;
264
265	if (ksp == NULL || ksp->ks_data == NULL)
266		return (EIO);
267
268	if (rwflag == KSTAT_WRITE)
269		return (EACCES);
270
271	fkp = ksp->ks_data;
272	fsp = ksp->ks_private;
273
274	fkp->fks_pass.value.ul		= fsp->fr_pass;
275	fkp->fks_block.value.ul		= fsp->fr_block;
276	fkp->fks_nom.value.ul		= fsp->fr_nom;
277	fkp->fks_short.value.ul		= fsp->fr_short;
278	fkp->fks_ppkl.value.ul		= fsp->fr_ppkl;
279	fkp->fks_bpkl.value.ul		= fsp->fr_bpkl;
280	fkp->fks_npkl.value.ul		= fsp->fr_npkl;
281	fkp->fks_pkl.value.ul		= fsp->fr_pkl;
282	fkp->fks_skip.value.ul		= fsp->fr_skip;
283	fkp->fks_ret.value.ul		= fsp->fr_ret;
284	fkp->fks_acct.value.ul		= fsp->fr_acct;
285	fkp->fks_bnfr.value.ul		= fsp->fr_bnfr;
286	fkp->fks_nfr.value.ul		= fsp->fr_nfr;
287	fkp->fks_cfr.value.ul		= fsp->fr_cfr;
288	fkp->fks_bads.value.ul		= fsp->fr_bads;
289	fkp->fks_ads.value.ul		= fsp->fr_ads;
290	fkp->fks_chit.value.ul		= fsp->fr_chit;
291	fkp->fks_tcpbad.value.ul 	= fsp->fr_tcpbad;
292	fkp->fks_pull[0].value.ul 	= fsp->fr_pull[0];
293	fkp->fks_pull[1].value.ul 	= fsp->fr_pull[1];
294	fkp->fks_badsrc.value.ul 	= fsp->fr_badsrc;
295	fkp->fks_badttl.value.ul 	= fsp->fr_badttl;
296	fkp->fks_bad.value.ul		= fsp->fr_bad;
297	fkp->fks_ipv6.value.ul		= fsp->fr_ipv6;
298	fkp->fks_ppshit.value.ul 	= fsp->fr_ppshit;
299	fkp->fks_ipud.value.ul		= fsp->fr_ipud;
300
301	return (0);
302}
303
304int _init()
305{
306	int ipfinst;
307
308	ipfinst = mod_install(&modlink1);
309#ifdef	IPFDEBUG
310	cmn_err(CE_NOTE, "IP Filter: _init() = %d", ipfinst);
311#endif
312	return ipfinst;
313}
314
315
316int _fini(void)
317{
318	int ipfinst;
319
320	ipfinst = mod_remove(&modlink1);
321#ifdef	IPFDEBUG
322	cmn_err(CE_NOTE, "IP Filter: _fini() = %d", ipfinst);
323#endif
324	return ipfinst;
325}
326
327
328int _info(modinfop)
329struct modinfo *modinfop;
330{
331	int ipfinst;
332
333	ipfinst = mod_info(&modlink1, modinfop);
334#ifdef	IPFDEBUG
335	cmn_err(CE_NOTE, "IP Filter: _info(%x) = %x", modinfop, ipfinst);
336#endif
337	return ipfinst;
338}
339
340
341#if SOLARIS2 < 10
342static int ipf_identify(dip)
343dev_info_t *dip;
344{
345# ifdef	IPFDEBUG
346	cmn_err(CE_NOTE, "IP Filter: ipf_identify(%x)", dip);
347# endif
348	if (strcmp(ddi_get_name(dip), "ipf") == 0)
349		return (DDI_IDENTIFIED);
350	return (DDI_NOT_IDENTIFIED);
351}
352#endif
353
354/*
355 * Initialize things for IPF for each stack instance
356 */
357static void *
358ipf_stack_init(netstackid_t stackid, netstack_t *ns)
359{
360	ipf_stack_t	*ifs;
361
362#ifdef NS_DEBUG
363	(void) printf("ipf_stack_init(%d)\n", stackid);
364#endif
365
366	KMALLOCS(ifs, ipf_stack_t *, sizeof (*ifs));
367	bzero(ifs, sizeof (*ifs));
368
369	ifs->ifs_netstack = ns;
370
371	ifs->ifs_hook4_physical_in	= B_FALSE;
372	ifs->ifs_hook4_physical_out	= B_FALSE;
373	ifs->ifs_hook4_nic_events	= B_FALSE;
374	ifs->ifs_hook4_loopback_in	= B_FALSE;
375	ifs->ifs_hook4_loopback_out	= B_FALSE;
376	ifs->ifs_hook6_physical_in	= B_FALSE;
377	ifs->ifs_hook6_physical_out	= B_FALSE;
378	ifs->ifs_hook6_nic_events	= B_FALSE;
379	ifs->ifs_hook6_loopback_in	= B_FALSE;
380	ifs->ifs_hook6_loopback_out	= B_FALSE;
381
382	/*
383	 * Initialize mutex's
384	 */
385	RWLOCK_INIT(&ifs->ifs_ipf_global, "ipf filter load/unload mutex");
386	RWLOCK_INIT(&ifs->ifs_ipf_mutex, "ipf filter rwlock");
387	RWLOCK_INIT(&ifs->ifs_ipf_frcache, "ipf cache rwlock");
388#ifdef KERNEL
389	ipf_kstat_init(ifs, stackid);
390#endif
391
392	/*
393	 * Lock people out while we set things up.
394	 */
395	WRITE_ENTER(&ifs->ifs_ipf_global);
396	ipftuneable_alloc(ifs);
397	ifs->ifs_fr_timer_id = timeout(fr_slowtimer, (void *)ifs,
398	    drv_usectohz(500000));
399
400	RWLOCK_EXIT(&ifs->ifs_ipf_global);
401
402	cmn_err(CE_CONT, "!%s, running.\n", ipfilter_version);
403	return (ifs);
404}
405
406static int ipf_detach_check_zone(ipf_stack_t *ifs)
407{
408	/*
409	 * Make sure we're the only one's modifying things.  With
410	 * this lock others should just fall out of the loop.
411	 */
412	READ_ENTER(&ifs->ifs_ipf_global);
413	if (ifs->ifs_fr_running == 1) {
414		RWLOCK_EXIT(&ifs->ifs_ipf_global);
415		return (-1);
416	}
417
418	/*
419	 * Make sure there is no active filter rule.
420	 */
421	if (ifs->ifs_ipfilter[0][ifs->ifs_fr_active] ||
422	    ifs->ifs_ipfilter[1][ifs->ifs_fr_active] ||
423	    ifs->ifs_ipfilter6[0][ifs->ifs_fr_active] ||
424	    ifs->ifs_ipfilter6[1][ifs->ifs_fr_active]) {
425		RWLOCK_EXIT(&ifs->ifs_ipf_global);
426		return (-1);
427	}
428
429	RWLOCK_EXIT(&ifs->ifs_ipf_global);
430
431	return (0);
432}
433
434static int ipf_detach_check_all()
435{
436	netstack_handle_t nh;
437	netstack_t *ns;
438	int ret;
439
440	netstack_next_init(&nh);
441	while ((ns = netstack_next(&nh)) != NULL) {
442		ret = ipf_detach_check_zone(ns->netstack_ipf);
443		netstack_rele(ns);
444		if (ret != 0) {
445			netstack_next_fini(&nh);
446			return (-1);
447		}
448	}
449
450	netstack_next_fini(&nh);
451	return (0);
452}
453
454/*
455 * Destroy things for ipf for one stack.
456 */
457/* ARGSUSED */
458static void
459ipf_stack_fini(netstackid_t stackid, void *arg)
460{
461	ipf_stack_t *ifs = (ipf_stack_t *)arg;
462
463#ifdef NS_DEBUG
464	(void) printf("ipf_stack_destroy(%p, stackid %d)\n",
465	    (void *)ifs, stackid);
466#endif
467
468	/*
469	 * Make sure we're the only one's modifying things.  With
470	 * this lock others should just fall out of the loop.
471	 */
472	WRITE_ENTER(&ifs->ifs_ipf_global);
473	if (ifs->ifs_fr_running == -2) {
474		RWLOCK_EXIT(&ifs->ifs_ipf_global);
475		return;
476	}
477	ifs->ifs_fr_running = -2;
478	RWLOCK_EXIT(&ifs->ifs_ipf_global);
479
480#ifdef KERNEL
481	ipf_kstat_fini(ifs, stackid);
482#endif
483	if (ifs->ifs_fr_timer_id != 0) {
484		(void) untimeout(ifs->ifs_fr_timer_id);
485		ifs->ifs_fr_timer_id = 0;
486	}
487
488	WRITE_ENTER(&ifs->ifs_ipf_global);
489	if (ipldetach(ifs) != 0) {
490		printf("ipf_stack_fini: ipldetach failed\n");
491	}
492
493	ipftuneable_free(ifs);
494
495	RWLOCK_EXIT(&ifs->ifs_ipf_global);
496	RW_DESTROY(&ifs->ifs_ipf_mutex);
497	RW_DESTROY(&ifs->ifs_ipf_frcache);
498	RW_DESTROY(&ifs->ifs_ipf_global);
499
500	KFREE(ifs);
501}
502
503static int ipf_attach(dip, cmd)
504dev_info_t *dip;
505ddi_attach_cmd_t cmd;
506{
507	char *s;
508	int i;
509	int instance;
510
511#ifdef	IPFDEBUG
512	cmn_err(CE_NOTE, "IP Filter: ipf_attach(%x,%x)", dip, cmd);
513#endif
514
515	switch (cmd)
516	{
517	case DDI_ATTACH:
518		instance = ddi_get_instance(dip);
519		/* Only one instance of ipf (instance 0) can be attached. */
520		if (instance > 0)
521			return DDI_FAILURE;
522
523#ifdef	IPFDEBUG
524		cmn_err(CE_NOTE, "IP Filter: attach ipf instance %d", instance);
525#endif
526
527		(void) ipf_property_g_update(dip);
528
529		for (i = 0; ((s = ipf_devfiles[i]) != NULL); i++) {
530			s = strrchr(s, '/');
531			if (s == NULL)
532				continue;
533			s++;
534			if (ddi_create_minor_node(dip, s, S_IFCHR, i,
535						  DDI_PSEUDO, 0) ==
536			    DDI_FAILURE) {
537				ddi_remove_minor_node(dip, NULL);
538				goto attach_failed;
539			}
540		}
541
542		ipf_dev_info = dip;
543		netstack_register(NS_IPF, ipf_stack_init, NULL,
544		    ipf_stack_fini);
545		return DDI_SUCCESS;
546		/* NOTREACHED */
547	default:
548		break;
549	}
550
551attach_failed:
552	ddi_prop_remove_all(dip);
553	return DDI_FAILURE;
554}
555
556
557static int ipf_detach(dip, cmd)
558dev_info_t *dip;
559ddi_detach_cmd_t cmd;
560{
561	int i;
562
563#ifdef	IPFDEBUG
564	cmn_err(CE_NOTE, "IP Filter: ipf_detach(%x,%x)", dip, cmd);
565#endif
566	switch (cmd) {
567	case DDI_DETACH:
568		if (ipf_detach_check_all() != 0)
569			return DDI_FAILURE;
570
571		/* Undo what we did in ipf_attach, freeing resources
572		 * and removing things we installed.  The system
573		 * framework guarantees we are not active with this devinfo
574		 * node in any other entry points at this time.
575		 */
576		ddi_prop_remove_all(dip);
577		i = ddi_get_instance(dip);
578		ddi_remove_minor_node(dip, NULL);
579		if (i > 0) {
580			cmn_err(CE_CONT, "IP Filter: still attached (%d)\n", i);
581			return DDI_FAILURE;
582		}
583
584		netstack_unregister(NS_IPF);
585		return DDI_SUCCESS;
586		/* NOTREACHED */
587	default:
588		break;
589	}
590	cmn_err(CE_NOTE, "IP Filter: failed to detach\n");
591	return DDI_FAILURE;
592}
593
594
595/*ARGSUSED*/
596static int ipf_getinfo(dip, infocmd, arg, result)
597dev_info_t *dip;
598ddi_info_cmd_t infocmd;
599void *arg, **result;
600{
601	int error;
602
603	error = DDI_FAILURE;
604#ifdef	IPFDEBUG
605	cmn_err(CE_NOTE, "IP Filter: ipf_getinfo(%x,%x,%x)", dip, infocmd, arg);
606#endif
607	switch (infocmd) {
608	case DDI_INFO_DEVT2DEVINFO:
609		*result = ipf_dev_info;
610		error = DDI_SUCCESS;
611		break;
612	case DDI_INFO_DEVT2INSTANCE:
613		*result = (void *)0;
614		error = DDI_SUCCESS;
615		break;
616	default:
617		break;
618	}
619	return (error);
620}
621
622
623/*
624 * Fetch configuration file values that have been entered into the ipf.conf
625 * driver file.
626 */
627static int ipf_property_g_update(dip)
628dev_info_t *dip;
629{
630#ifdef DDI_NO_AUTODETACH
631	if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
632				DDI_NO_AUTODETACH, 1) != DDI_PROP_SUCCESS) {
633		cmn_err(CE_WARN, "!updating DDI_NO_AUTODETACH failed");
634		return DDI_FAILURE;
635	}
636#else
637	if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
638				"ddi-no-autodetach", 1) != DDI_PROP_SUCCESS) {
639		cmn_err(CE_WARN, "!updating ddi-no-autodetach failed");
640		return DDI_FAILURE;
641	}
642#endif
643
644	return DDI_SUCCESS;
645}
646
647int ipf_property_update(dip, ifs)
648dev_info_t *dip;
649ipf_stack_t *ifs;
650{
651	ipftuneable_t *ipft;
652	int64_t *i64p;
653	char *name;
654	u_int one;
655	int *i32p;
656	int err;
657
658	for (ipft = ifs->ifs_ipf_tuneables; (name = ipft->ipft_name) != NULL; ipft++) {
659		one = 1;
660		switch (ipft->ipft_sz)
661		{
662		case 4 :
663			i32p = NULL;
664			err = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip,
665							0, name, &i32p, &one);
666			if (err == DDI_PROP_NOT_FOUND)
667				continue;
668#ifdef	IPFDEBUG
669			cmn_err(CE_CONT, "IP Filter: lookup_int(%s) = %d\n",
670				name, err);
671#endif
672			if (err != DDI_PROP_SUCCESS)
673				return err;
674			if (*i32p >= ipft->ipft_min && *i32p <= ipft->ipft_max)
675				*ipft->ipft_pint = *i32p;
676			else
677				err = DDI_PROP_CANNOT_DECODE;
678			ddi_prop_free(i32p);
679			break;
680
681#if SOLARIS2 > 8
682		case 8 :
683			i64p = NULL;
684			err = ddi_prop_lookup_int64_array(DDI_DEV_T_ANY, dip,
685							  0, name, &i64p, &one);
686			if (err == DDI_PROP_NOT_FOUND)
687				continue;
688# ifdef	IPFDEBUG
689			cmn_err(CE_CONT, "IP Filter: lookup_int64(%s) = %d\n",
690				name, err);
691# endif
692			if (err != DDI_PROP_SUCCESS)
693				return err;
694			if (*i64p >= ipft->ipft_min && *i64p <= ipft->ipft_max)
695				*ipft->ipft_pint = *i64p;
696			else
697				err = DDI_PROP_CANNOT_DECODE;
698			ddi_prop_free(i64p);
699			break;
700#endif
701		default :
702			break;
703		}
704		if (err != DDI_SUCCESS)
705			break;
706	}
707	return err;
708}
709