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