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