xref: /titanic_50/usr/src/uts/common/inet/ipf/solaris.c (revision dfb96a4f56fb431b915bc67e5d9d5c8d4f4f6679)
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 
65 extern	int	iplwrite __P((dev_t, struct uio *, cred_t *));
66 
67 static	int	ipf_getinfo __P((dev_info_t *, ddi_info_cmd_t,
68 				 void *, void **));
69 #if SOLARIS2 < 10
70 static	int	ipf_identify __P((dev_info_t *));
71 #endif
72 static	int	ipf_attach __P((dev_info_t *, ddi_attach_cmd_t));
73 static	int	ipf_detach __P((dev_info_t *, ddi_detach_cmd_t));
74 static	int	ipf_property_g_update __P((dev_info_t *));
75 static	char	*ipf_devfiles[] = { IPL_NAME, IPNAT_NAME, IPSTATE_NAME,
76 				    IPAUTH_NAME, IPSYNC_NAME, IPSCAN_NAME,
77 				    IPLOOKUP_NAME, NULL };
78 
79 
80 static 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 
103 static 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 
120 extern struct mod_ops mod_driverops;
121 static struct modldrv iplmod = {
122 	&mod_driverops, IPL_VERSION, &ipf_ops };
123 static struct modlinkage modlink1 = { MODREV_1, &iplmod, NULL };
124 
125 #if SOLARIS2 >= 6
126 static	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 
185 dev_info_t *ipf_dev_info = NULL;
186 
187 static 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 
217 static int	ipf_kstat_update(kstat_t *ksp, int rwflag);
218 
219 static void
220 ipf_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 
246 static void
247 ipf_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 
259 static int
260 ipf_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 
304 int _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 
316 int _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 
328 int _info(modinfop)
329 struct 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
342 static int ipf_identify(dip)
343 dev_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  */
357 static void *
358 ipf_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 	/* Limit to global stack */
403 	if (stackid == GLOBAL_NETSTACKID)
404 		cmn_err(CE_CONT, "!%s, running.\n", ipfilter_version);
405 
406 	return (ifs);
407 }
408 
409 static int ipf_detach_check_zone(ipf_stack_t *ifs)
410 {
411 	/*
412 	 * Make sure we're the only one's modifying things.  With
413 	 * this lock others should just fall out of the loop.
414 	 */
415 	READ_ENTER(&ifs->ifs_ipf_global);
416 	if (ifs->ifs_fr_running == 1) {
417 		RWLOCK_EXIT(&ifs->ifs_ipf_global);
418 		return (-1);
419 	}
420 
421 	/*
422 	 * Make sure there is no active filter rule.
423 	 */
424 	if (ifs->ifs_ipfilter[0][ifs->ifs_fr_active] ||
425 	    ifs->ifs_ipfilter[1][ifs->ifs_fr_active] ||
426 	    ifs->ifs_ipfilter6[0][ifs->ifs_fr_active] ||
427 	    ifs->ifs_ipfilter6[1][ifs->ifs_fr_active]) {
428 		RWLOCK_EXIT(&ifs->ifs_ipf_global);
429 		return (-1);
430 	}
431 
432 	RWLOCK_EXIT(&ifs->ifs_ipf_global);
433 
434 	return (0);
435 }
436 
437 static int ipf_detach_check_all()
438 {
439 	netstack_handle_t nh;
440 	netstack_t *ns;
441 	int ret;
442 
443 	netstack_next_init(&nh);
444 	while ((ns = netstack_next(&nh)) != NULL) {
445 		ret = ipf_detach_check_zone(ns->netstack_ipf);
446 		netstack_rele(ns);
447 		if (ret != 0) {
448 			netstack_next_fini(&nh);
449 			return (-1);
450 		}
451 	}
452 
453 	netstack_next_fini(&nh);
454 	return (0);
455 }
456 
457 /*
458  * Destroy things for ipf for one stack.
459  */
460 /* ARGSUSED */
461 static void
462 ipf_stack_fini(netstackid_t stackid, void *arg)
463 {
464 	ipf_stack_t *ifs = (ipf_stack_t *)arg;
465 
466 #ifdef NS_DEBUG
467 	(void) printf("ipf_stack_destroy(%p, stackid %d)\n",
468 	    (void *)ifs, stackid);
469 #endif
470 
471 	/*
472 	 * Make sure we're the only one's modifying things.  With
473 	 * this lock others should just fall out of the loop.
474 	 */
475 	WRITE_ENTER(&ifs->ifs_ipf_global);
476 	if (ifs->ifs_fr_running == -2) {
477 		RWLOCK_EXIT(&ifs->ifs_ipf_global);
478 		return;
479 	}
480 	ifs->ifs_fr_running = -2;
481 	RWLOCK_EXIT(&ifs->ifs_ipf_global);
482 
483 #ifdef KERNEL
484 	ipf_kstat_fini(ifs, stackid);
485 #endif
486 	if (ifs->ifs_fr_timer_id != 0) {
487 		(void) untimeout(ifs->ifs_fr_timer_id);
488 		ifs->ifs_fr_timer_id = 0;
489 	}
490 
491 	WRITE_ENTER(&ifs->ifs_ipf_global);
492 	if (ipldetach(ifs) != 0) {
493 		printf("ipf_stack_fini: ipldetach failed\n");
494 	}
495 
496 	ipftuneable_free(ifs);
497 
498 	RWLOCK_EXIT(&ifs->ifs_ipf_global);
499 	RW_DESTROY(&ifs->ifs_ipf_mutex);
500 	RW_DESTROY(&ifs->ifs_ipf_frcache);
501 	RW_DESTROY(&ifs->ifs_ipf_global);
502 
503 	KFREE(ifs);
504 }
505 
506 static int ipf_attach(dip, cmd)
507 dev_info_t *dip;
508 ddi_attach_cmd_t cmd;
509 {
510 	char *s;
511 	int i;
512 	int instance;
513 
514 #ifdef	IPFDEBUG
515 	cmn_err(CE_NOTE, "IP Filter: ipf_attach(%x,%x)", dip, cmd);
516 #endif
517 
518 	switch (cmd)
519 	{
520 	case DDI_ATTACH:
521 		instance = ddi_get_instance(dip);
522 		/* Only one instance of ipf (instance 0) can be attached. */
523 		if (instance > 0)
524 			return DDI_FAILURE;
525 
526 #ifdef	IPFDEBUG
527 		cmn_err(CE_NOTE, "IP Filter: attach ipf instance %d", instance);
528 #endif
529 
530 		(void) ipf_property_g_update(dip);
531 
532 		for (i = 0; ((s = ipf_devfiles[i]) != NULL); i++) {
533 			s = strrchr(s, '/');
534 			if (s == NULL)
535 				continue;
536 			s++;
537 			if (ddi_create_minor_node(dip, s, S_IFCHR, i,
538 						  DDI_PSEUDO, 0) ==
539 			    DDI_FAILURE) {
540 				ddi_remove_minor_node(dip, NULL);
541 				goto attach_failed;
542 			}
543 		}
544 
545 		ipf_dev_info = dip;
546 		netstack_register(NS_IPF, ipf_stack_init, NULL,
547 		    ipf_stack_fini);
548 		return DDI_SUCCESS;
549 		/* NOTREACHED */
550 	default:
551 		break;
552 	}
553 
554 attach_failed:
555 	ddi_prop_remove_all(dip);
556 	return DDI_FAILURE;
557 }
558 
559 
560 static int ipf_detach(dip, cmd)
561 dev_info_t *dip;
562 ddi_detach_cmd_t cmd;
563 {
564 	int i;
565 
566 #ifdef	IPFDEBUG
567 	cmn_err(CE_NOTE, "IP Filter: ipf_detach(%x,%x)", dip, cmd);
568 #endif
569 	switch (cmd) {
570 	case DDI_DETACH:
571 		if (ipf_detach_check_all() != 0)
572 			return DDI_FAILURE;
573 
574 		/* Undo what we did in ipf_attach, freeing resources
575 		 * and removing things we installed.  The system
576 		 * framework guarantees we are not active with this devinfo
577 		 * node in any other entry points at this time.
578 		 */
579 		ddi_prop_remove_all(dip);
580 		i = ddi_get_instance(dip);
581 		ddi_remove_minor_node(dip, NULL);
582 		if (i > 0) {
583 			cmn_err(CE_CONT, "IP Filter: still attached (%d)\n", i);
584 			return DDI_FAILURE;
585 		}
586 
587 		netstack_unregister(NS_IPF);
588 		return DDI_SUCCESS;
589 		/* NOTREACHED */
590 	default:
591 		break;
592 	}
593 	cmn_err(CE_NOTE, "IP Filter: failed to detach\n");
594 	return DDI_FAILURE;
595 }
596 
597 
598 /*ARGSUSED*/
599 static int ipf_getinfo(dip, infocmd, arg, result)
600 dev_info_t *dip;
601 ddi_info_cmd_t infocmd;
602 void *arg, **result;
603 {
604 	int error;
605 
606 	error = DDI_FAILURE;
607 #ifdef	IPFDEBUG
608 	cmn_err(CE_NOTE, "IP Filter: ipf_getinfo(%x,%x,%x)", dip, infocmd, arg);
609 #endif
610 	switch (infocmd) {
611 	case DDI_INFO_DEVT2DEVINFO:
612 		*result = ipf_dev_info;
613 		error = DDI_SUCCESS;
614 		break;
615 	case DDI_INFO_DEVT2INSTANCE:
616 		*result = (void *)0;
617 		error = DDI_SUCCESS;
618 		break;
619 	default:
620 		break;
621 	}
622 	return (error);
623 }
624 
625 
626 /*
627  * Fetch configuration file values that have been entered into the ipf.conf
628  * driver file.
629  */
630 static int ipf_property_g_update(dip)
631 dev_info_t *dip;
632 {
633 #ifdef DDI_NO_AUTODETACH
634 	if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
635 				DDI_NO_AUTODETACH, 1) != DDI_PROP_SUCCESS) {
636 		cmn_err(CE_WARN, "!updating DDI_NO_AUTODETACH failed");
637 		return DDI_FAILURE;
638 	}
639 #else
640 	if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
641 				"ddi-no-autodetach", 1) != DDI_PROP_SUCCESS) {
642 		cmn_err(CE_WARN, "!updating ddi-no-autodetach failed");
643 		return DDI_FAILURE;
644 	}
645 #endif
646 
647 	return DDI_SUCCESS;
648 }
649 
650 int ipf_property_update(dip, ifs)
651 dev_info_t *dip;
652 ipf_stack_t *ifs;
653 {
654 	ipftuneable_t *ipft;
655 	int64_t *i64p;
656 	char *name;
657 	u_int one;
658 	int *i32p;
659 	int err;
660 
661 	for (ipft = ifs->ifs_ipf_tuneables; (name = ipft->ipft_name) != NULL; ipft++) {
662 		one = 1;
663 		switch (ipft->ipft_sz)
664 		{
665 		case 4 :
666 			i32p = NULL;
667 			err = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip,
668 							0, name, &i32p, &one);
669 			if (err == DDI_PROP_NOT_FOUND)
670 				continue;
671 #ifdef	IPFDEBUG
672 			cmn_err(CE_CONT, "IP Filter: lookup_int(%s) = %d\n",
673 				name, err);
674 #endif
675 			if (err != DDI_PROP_SUCCESS)
676 				return err;
677 			if (*i32p >= ipft->ipft_min && *i32p <= ipft->ipft_max)
678 				*ipft->ipft_pint = *i32p;
679 			else
680 				err = DDI_PROP_CANNOT_DECODE;
681 			ddi_prop_free(i32p);
682 			break;
683 
684 #if SOLARIS2 > 8
685 		case 8 :
686 			i64p = NULL;
687 			err = ddi_prop_lookup_int64_array(DDI_DEV_T_ANY, dip,
688 							  0, name, &i64p, &one);
689 			if (err == DDI_PROP_NOT_FOUND)
690 				continue;
691 # ifdef	IPFDEBUG
692 			cmn_err(CE_CONT, "IP Filter: lookup_int64(%s) = %d\n",
693 				name, err);
694 # endif
695 			if (err != DDI_PROP_SUCCESS)
696 				return err;
697 			if (*i64p >= ipft->ipft_min && *i64p <= ipft->ipft_max)
698 				*ipft->ipft_pint = *i64p;
699 			else
700 				err = DDI_PROP_CANNOT_DECODE;
701 			ddi_prop_free(i64p);
702 			break;
703 #endif
704 		default :
705 			break;
706 		}
707 		if (err != DDI_SUCCESS)
708 			break;
709 	}
710 	return err;
711 }
712