12393Syz155240 /* 22393Syz155240 * Copyright (C) 1993-2001, 2003 by Darren Reed. 32393Syz155240 * 42393Syz155240 * See the IPFILTER.LICENCE file for details on licencing. 52393Syz155240 * 62393Syz155240 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 72393Syz155240 * Use is subject to license terms. 82393Syz155240 */ 92393Syz155240 /* #pragma ident "@(#)solaris.c 1.12 6/5/96 (C) 1995 Darren Reed"*/ 102393Syz155240 #pragma ident "@(#)$Id: solaris.c,v 2.73.2.6 2005/07/13 21:40:47 darrenr Exp $" 112393Syz155240 122393Syz155240 #pragma ident "%Z%%M% %I% %E% SMI" 132393Syz155240 142393Syz155240 #include <sys/systm.h> 152393Syz155240 #include <sys/types.h> 162393Syz155240 #include <sys/param.h> 172393Syz155240 #include <sys/errno.h> 182393Syz155240 #include <sys/uio.h> 192393Syz155240 #include <sys/buf.h> 202393Syz155240 #include <sys/modctl.h> 212393Syz155240 #include <sys/open.h> 222393Syz155240 #include <sys/kmem.h> 232393Syz155240 #include <sys/conf.h> 242393Syz155240 #include <sys/cmn_err.h> 252393Syz155240 #include <sys/stat.h> 262393Syz155240 #include <sys/cred.h> 272393Syz155240 #include <sys/dditypes.h> 282393Syz155240 #include <sys/poll.h> 292393Syz155240 #include <sys/autoconf.h> 302393Syz155240 #include <sys/byteorder.h> 312393Syz155240 #include <sys/socket.h> 322393Syz155240 #include <sys/dlpi.h> 332393Syz155240 #include <sys/stropts.h> 342393Syz155240 #include <sys/kstat.h> 352393Syz155240 #include <sys/sockio.h> 36*2958Sdr146992 #include <sys/neti.h> 37*2958Sdr146992 #include <sys/hook.h> 382393Syz155240 #include <net/if.h> 392393Syz155240 #if SOLARIS2 >= 6 402393Syz155240 # include <net/if_types.h> 412393Syz155240 #endif 422393Syz155240 #include <net/af.h> 432393Syz155240 #include <net/route.h> 442393Syz155240 #include <netinet/in.h> 452393Syz155240 #include <netinet/in_systm.h> 462393Syz155240 #include <netinet/if_ether.h> 472393Syz155240 #include <netinet/ip.h> 482393Syz155240 #include <netinet/ip_var.h> 492393Syz155240 #include <netinet/tcp.h> 502393Syz155240 #include <netinet/udp.h> 512393Syz155240 #include <netinet/tcpip.h> 522393Syz155240 #include <netinet/ip_icmp.h> 532393Syz155240 #include <sys/ddi.h> 542393Syz155240 #include <sys/sunddi.h> 552393Syz155240 #include "netinet/ip_compat.h" 562393Syz155240 #include "netinet/ipl.h" 572393Syz155240 #include "netinet/ip_fil.h" 582393Syz155240 #include "netinet/ip_nat.h" 592393Syz155240 #include "netinet/ip_frag.h" 602393Syz155240 #include "netinet/ip_auth.h" 612393Syz155240 #include "netinet/ip_state.h" 622393Syz155240 632393Syz155240 extern struct filterstats frstats[]; 642393Syz155240 extern int fr_running; 652393Syz155240 extern int fr_flags; 662393Syz155240 extern int iplwrite __P((dev_t, struct uio *, cred_t *)); 672393Syz155240 682393Syz155240 extern ipnat_t *nat_list; 692393Syz155240 702393Syz155240 static int ipf_getinfo __P((dev_info_t *, ddi_info_cmd_t, 712393Syz155240 void *, void **)); 722393Syz155240 #if SOLARIS2 < 10 732393Syz155240 static int ipf_identify __P((dev_info_t *)); 742393Syz155240 #endif 752393Syz155240 static int ipf_attach __P((dev_info_t *, ddi_attach_cmd_t)); 762393Syz155240 static int ipf_detach __P((dev_info_t *, ddi_detach_cmd_t)); 772393Syz155240 static int ipf_property_update __P((dev_info_t *)); 782393Syz155240 static char *ipf_devfiles[] = { IPL_NAME, IPNAT_NAME, IPSTATE_NAME, 792393Syz155240 IPAUTH_NAME, IPSYNC_NAME, IPSCAN_NAME, 802393Syz155240 IPLOOKUP_NAME, NULL }; 812393Syz155240 822393Syz155240 832393Syz155240 #if SOLARIS2 >= 7 842393Syz155240 extern timeout_id_t fr_timer_id; 852393Syz155240 #else 862393Syz155240 extern int fr_timer_id; 872393Syz155240 #endif 882393Syz155240 892393Syz155240 static struct cb_ops ipf_cb_ops = { 902393Syz155240 iplopen, 912393Syz155240 iplclose, 922393Syz155240 nodev, /* strategy */ 932393Syz155240 nodev, /* print */ 942393Syz155240 nodev, /* dump */ 952393Syz155240 iplread, 962393Syz155240 iplwrite, /* write */ 972393Syz155240 iplioctl, /* ioctl */ 982393Syz155240 nodev, /* devmap */ 992393Syz155240 nodev, /* mmap */ 1002393Syz155240 nodev, /* segmap */ 1012393Syz155240 nochpoll, /* poll */ 1022393Syz155240 ddi_prop_op, 1032393Syz155240 NULL, 1042393Syz155240 D_MTSAFE, 1052393Syz155240 #if SOLARIS2 > 4 1062393Syz155240 CB_REV, 1072393Syz155240 nodev, /* aread */ 1082393Syz155240 nodev, /* awrite */ 1092393Syz155240 #endif 1102393Syz155240 }; 1112393Syz155240 1122393Syz155240 static struct dev_ops ipf_ops = { 1132393Syz155240 DEVO_REV, 1142393Syz155240 0, 1152393Syz155240 ipf_getinfo, 1162393Syz155240 #if SOLARIS2 >= 10 1172393Syz155240 nulldev, 1182393Syz155240 #else 1192393Syz155240 ipf_identify, 1202393Syz155240 #endif 1212393Syz155240 nulldev, 1222393Syz155240 ipf_attach, 1232393Syz155240 ipf_detach, 1242393Syz155240 nodev, /* reset */ 1252393Syz155240 &ipf_cb_ops, 1262393Syz155240 (struct bus_ops *)0 1272393Syz155240 }; 1282393Syz155240 1292393Syz155240 extern struct mod_ops mod_driverops; 1302393Syz155240 static struct modldrv iplmod = { 1312393Syz155240 &mod_driverops, IPL_VERSION, &ipf_ops }; 1322393Syz155240 static struct modlinkage modlink1 = { MODREV_1, &iplmod, NULL }; 1332393Syz155240 1342393Syz155240 #if SOLARIS2 >= 6 1352393Syz155240 static size_t hdrsizes[57][2] = { 1362393Syz155240 { 0, 0 }, 1372393Syz155240 { IFT_OTHER, 0 }, 1382393Syz155240 { IFT_1822, 0 }, 1392393Syz155240 { IFT_HDH1822, 0 }, 1402393Syz155240 { IFT_X25DDN, 0 }, 1412393Syz155240 { IFT_X25, 0 }, 1422393Syz155240 { IFT_ETHER, 14 }, 1432393Syz155240 { IFT_ISO88023, 0 }, 1442393Syz155240 { IFT_ISO88024, 0 }, 1452393Syz155240 { IFT_ISO88025, 0 }, 1462393Syz155240 { IFT_ISO88026, 0 }, 1472393Syz155240 { IFT_STARLAN, 0 }, 1482393Syz155240 { IFT_P10, 0 }, 1492393Syz155240 { IFT_P80, 0 }, 1502393Syz155240 { IFT_HY, 0 }, 1512393Syz155240 { IFT_FDDI, 24 }, 1522393Syz155240 { IFT_LAPB, 0 }, 1532393Syz155240 { IFT_SDLC, 0 }, 1542393Syz155240 { IFT_T1, 0 }, 1552393Syz155240 { IFT_CEPT, 0 }, 1562393Syz155240 { IFT_ISDNBASIC, 0 }, 1572393Syz155240 { IFT_ISDNPRIMARY, 0 }, 1582393Syz155240 { IFT_PTPSERIAL, 0 }, 1592393Syz155240 { IFT_PPP, 0 }, 1602393Syz155240 { IFT_LOOP, 0 }, 1612393Syz155240 { IFT_EON, 0 }, 1622393Syz155240 { IFT_XETHER, 0 }, 1632393Syz155240 { IFT_NSIP, 0 }, 1642393Syz155240 { IFT_SLIP, 0 }, 1652393Syz155240 { IFT_ULTRA, 0 }, 1662393Syz155240 { IFT_DS3, 0 }, 1672393Syz155240 { IFT_SIP, 0 }, 1682393Syz155240 { IFT_FRELAY, 0 }, 1692393Syz155240 { IFT_RS232, 0 }, 1702393Syz155240 { IFT_PARA, 0 }, 1712393Syz155240 { IFT_ARCNET, 0 }, 1722393Syz155240 { IFT_ARCNETPLUS, 0 }, 1732393Syz155240 { IFT_ATM, 0 }, 1742393Syz155240 { IFT_MIOX25, 0 }, 1752393Syz155240 { IFT_SONET, 0 }, 1762393Syz155240 { IFT_X25PLE, 0 }, 1772393Syz155240 { IFT_ISO88022LLC, 0 }, 1782393Syz155240 { IFT_LOCALTALK, 0 }, 1792393Syz155240 { IFT_SMDSDXI, 0 }, 1802393Syz155240 { IFT_FRELAYDCE, 0 }, 1812393Syz155240 { IFT_V35, 0 }, 1822393Syz155240 { IFT_HSSI, 0 }, 1832393Syz155240 { IFT_HIPPI, 0 }, 1842393Syz155240 { IFT_MODEM, 0 }, 1852393Syz155240 { IFT_AAL5, 0 }, 1862393Syz155240 { IFT_SONETPATH, 0 }, 1872393Syz155240 { IFT_SONETVT, 0 }, 1882393Syz155240 { IFT_SMDSICIP, 0 }, 1892393Syz155240 { IFT_PROPVIRTUAL, 0 }, 1902393Syz155240 { IFT_PROPMUX, 0 }, 1912393Syz155240 }; 1922393Syz155240 #endif /* SOLARIS2 >= 6 */ 1932393Syz155240 1942393Syz155240 static dev_info_t *ipf_dev_info = NULL; 1952393Syz155240 1962393Syz155240 static const filter_kstats_t ipf_kstat_tmp = { 1972393Syz155240 { "pass", KSTAT_DATA_ULONG }, 1982393Syz155240 { "block", KSTAT_DATA_ULONG }, 1992393Syz155240 { "nomatch", KSTAT_DATA_ULONG }, 2002393Syz155240 { "short", KSTAT_DATA_ULONG }, 2012393Syz155240 { "pass, logged", KSTAT_DATA_ULONG }, 2022393Syz155240 { "block, logged", KSTAT_DATA_ULONG }, 2032393Syz155240 { "nomatch, logged", KSTAT_DATA_ULONG }, 2042393Syz155240 { "logged", KSTAT_DATA_ULONG }, 2052393Syz155240 { "skip", KSTAT_DATA_ULONG }, 2062393Syz155240 { "return sent", KSTAT_DATA_ULONG }, 2072393Syz155240 { "acct", KSTAT_DATA_ULONG }, 2082393Syz155240 { "bad frag state alloc", KSTAT_DATA_ULONG }, 2092393Syz155240 { "new frag state kept", KSTAT_DATA_ULONG }, 2102393Syz155240 { "new frag state compl. pkt", KSTAT_DATA_ULONG }, 2112393Syz155240 { "bad pkt state alloc", KSTAT_DATA_ULONG }, 2122393Syz155240 { "new pkt kept state", KSTAT_DATA_ULONG }, 2132393Syz155240 { "cachehit", KSTAT_DATA_ULONG }, 2142393Syz155240 { "tcp cksum bad", KSTAT_DATA_ULONG }, 2152393Syz155240 {{ "pullup ok", KSTAT_DATA_ULONG }, 2162393Syz155240 { "pullup nok", KSTAT_DATA_ULONG }}, 2172393Syz155240 { "src != route", KSTAT_DATA_ULONG }, 2182393Syz155240 { "ttl invalid", KSTAT_DATA_ULONG }, 2192393Syz155240 { "bad ip pkt", KSTAT_DATA_ULONG }, 2202393Syz155240 { "ipv6 pkt", KSTAT_DATA_ULONG }, 2212393Syz155240 { "dropped:pps ceiling", KSTAT_DATA_ULONG }, 2222393Syz155240 { "ip upd. fail", KSTAT_DATA_ULONG } 2232393Syz155240 }; 2242393Syz155240 225*2958Sdr146992 net_data_t ipf_ipv4; 226*2958Sdr146992 net_data_t ipf_ipv6; 227*2958Sdr146992 2282393Syz155240 kstat_t *ipf_kstatp[2] = {NULL, NULL}; 2292393Syz155240 static int ipf_kstat_update(kstat_t *ksp, int rwflag); 2302393Syz155240 2312393Syz155240 static void 2322393Syz155240 ipf_kstat_init(void) 2332393Syz155240 { 2342393Syz155240 int i; 2352393Syz155240 2362393Syz155240 for (i = 0; i < 2; i++) { 2372393Syz155240 ipf_kstatp[i] = kstat_create("ipf", 0, 2382393Syz155240 (i==0)?"inbound":"outbound", 2392393Syz155240 "net", 2402393Syz155240 KSTAT_TYPE_NAMED, 2412393Syz155240 sizeof (filter_kstats_t) / sizeof (kstat_named_t), 2422393Syz155240 0); 2432393Syz155240 if (ipf_kstatp[i] != NULL) { 2442393Syz155240 bcopy(&ipf_kstat_tmp, ipf_kstatp[i]->ks_data, 2452393Syz155240 sizeof (filter_kstats_t)); 2462393Syz155240 ipf_kstatp[i]->ks_update = ipf_kstat_update; 2472393Syz155240 ipf_kstatp[i]->ks_private = &frstats[i]; 2482393Syz155240 kstat_install(ipf_kstatp[i]); 2492393Syz155240 } 2502393Syz155240 } 2512393Syz155240 2522393Syz155240 #ifdef IPFDEBUG 2532393Syz155240 cmn_err(CE_NOTE, "IP Filter: ipf_kstat_init() installed 0x%x, 0x%x", 2542393Syz155240 ipf_kstatp[0], ipf_kstatp[1]); 2552393Syz155240 #endif 2562393Syz155240 } 2572393Syz155240 2582393Syz155240 static void 2592393Syz155240 ipf_kstat_fini(void) 2602393Syz155240 { 2612393Syz155240 int i; 2622393Syz155240 for (i = 0; i < 2; i++) { 2632393Syz155240 if (ipf_kstatp[i] != NULL) { 2642393Syz155240 kstat_delete(ipf_kstatp[i]); 2652393Syz155240 ipf_kstatp[i] = NULL; 2662393Syz155240 } 2672393Syz155240 } 2682393Syz155240 } 2692393Syz155240 2702393Syz155240 static int 2712393Syz155240 ipf_kstat_update(kstat_t *ksp, int rwflag) 2722393Syz155240 { 2732393Syz155240 filter_kstats_t *fkp; 2742393Syz155240 filterstats_t *fsp; 2752393Syz155240 2762393Syz155240 if (rwflag == KSTAT_WRITE) 2772393Syz155240 return (EACCES); 2782393Syz155240 2792393Syz155240 fkp = ksp->ks_data; 2802393Syz155240 fsp = ksp->ks_private; 2812393Syz155240 2822393Syz155240 fkp->fks_pass.value.ul = fsp->fr_pass; 2832393Syz155240 fkp->fks_block.value.ul = fsp->fr_block; 2842393Syz155240 fkp->fks_nom.value.ul = fsp->fr_nom; 2852393Syz155240 fkp->fks_short.value.ul = fsp->fr_short; 2862393Syz155240 fkp->fks_ppkl.value.ul = fsp->fr_ppkl; 2872393Syz155240 fkp->fks_bpkl.value.ul = fsp->fr_bpkl; 2882393Syz155240 fkp->fks_npkl.value.ul = fsp->fr_npkl; 2892393Syz155240 fkp->fks_pkl.value.ul = fsp->fr_pkl; 2902393Syz155240 fkp->fks_skip.value.ul = fsp->fr_skip; 2912393Syz155240 fkp->fks_ret.value.ul = fsp->fr_ret; 2922393Syz155240 fkp->fks_acct.value.ul = fsp->fr_acct; 2932393Syz155240 fkp->fks_bnfr.value.ul = fsp->fr_bnfr; 2942393Syz155240 fkp->fks_nfr.value.ul = fsp->fr_nfr; 2952393Syz155240 fkp->fks_cfr.value.ul = fsp->fr_cfr; 2962393Syz155240 fkp->fks_bads.value.ul = fsp->fr_bads; 2972393Syz155240 fkp->fks_ads.value.ul = fsp->fr_ads; 2982393Syz155240 fkp->fks_chit.value.ul = fsp->fr_chit; 2992393Syz155240 fkp->fks_tcpbad.value.ul = fsp->fr_tcpbad; 3002393Syz155240 fkp->fks_pull[0].value.ul = fsp->fr_pull[0]; 3012393Syz155240 fkp->fks_pull[1].value.ul = fsp->fr_pull[1]; 3022393Syz155240 fkp->fks_badsrc.value.ul = fsp->fr_badsrc; 3032393Syz155240 fkp->fks_badttl.value.ul = fsp->fr_badttl; 3042393Syz155240 fkp->fks_bad.value.ul = fsp->fr_bad; 3052393Syz155240 fkp->fks_ipv6.value.ul = fsp->fr_ipv6; 3062393Syz155240 fkp->fks_ppshit.value.ul = fsp->fr_ppshit; 3072393Syz155240 fkp->fks_ipud.value.ul = fsp->fr_ipud; 3082393Syz155240 3092393Syz155240 return (0); 3102393Syz155240 } 3112393Syz155240 3122393Syz155240 int _init() 3132393Syz155240 { 3142393Syz155240 int ipfinst; 3152393Syz155240 3162393Syz155240 ipf_kstat_init(); 317*2958Sdr146992 3182393Syz155240 ipfinst = mod_install(&modlink1); 319*2958Sdr146992 3202393Syz155240 if (ipfinst != 0) 3212393Syz155240 ipf_kstat_fini(); 3222393Syz155240 #ifdef IPFDEBUG 3232393Syz155240 cmn_err(CE_NOTE, "IP Filter: _init() = %d", ipfinst); 3242393Syz155240 #endif 3252393Syz155240 return ipfinst; 3262393Syz155240 } 3272393Syz155240 3282393Syz155240 3292393Syz155240 int _fini(void) 3302393Syz155240 { 3312393Syz155240 int ipfinst; 3322393Syz155240 3332393Syz155240 ipfinst = mod_remove(&modlink1); 3342393Syz155240 #ifdef IPFDEBUG 3352393Syz155240 cmn_err(CE_NOTE, "IP Filter: _fini() = %d", ipfinst); 3362393Syz155240 #endif 3372393Syz155240 if (ipfinst == 0) 3382393Syz155240 ipf_kstat_fini(); 339*2958Sdr146992 3402393Syz155240 return ipfinst; 3412393Syz155240 } 3422393Syz155240 3432393Syz155240 3442393Syz155240 int _info(modinfop) 3452393Syz155240 struct modinfo *modinfop; 3462393Syz155240 { 3472393Syz155240 int ipfinst; 3482393Syz155240 3492393Syz155240 ipfinst = mod_info(&modlink1, modinfop); 3502393Syz155240 #ifdef IPFDEBUG 3512393Syz155240 cmn_err(CE_NOTE, "IP Filter: _info(%x) = %x", modinfop, ipfinst); 3522393Syz155240 #endif 3532393Syz155240 return ipfinst; 3542393Syz155240 } 3552393Syz155240 3562393Syz155240 3572393Syz155240 #if SOLARIS2 < 10 3582393Syz155240 static int ipf_identify(dip) 3592393Syz155240 dev_info_t *dip; 3602393Syz155240 { 3612393Syz155240 # ifdef IPFDEBUG 3622393Syz155240 cmn_err(CE_NOTE, "IP Filter: ipf_identify(%x)", dip); 3632393Syz155240 # endif 3642393Syz155240 if (strcmp(ddi_get_name(dip), "ipf") == 0) 3652393Syz155240 return (DDI_IDENTIFIED); 3662393Syz155240 return (DDI_NOT_IDENTIFIED); 3672393Syz155240 } 3682393Syz155240 #endif 3692393Syz155240 3702393Syz155240 3712393Syz155240 static int ipf_attach(dip, cmd) 3722393Syz155240 dev_info_t *dip; 3732393Syz155240 ddi_attach_cmd_t cmd; 3742393Syz155240 { 3752393Syz155240 char *s; 3762393Syz155240 int i; 3772393Syz155240 int instance; 3782393Syz155240 3792393Syz155240 #ifdef IPFDEBUG 3802393Syz155240 cmn_err(CE_NOTE, "IP Filter: ipf_attach(%x,%x)", dip, cmd); 3812393Syz155240 #endif 3822393Syz155240 3832393Syz155240 switch (cmd) 3842393Syz155240 { 3852393Syz155240 case DDI_ATTACH: 3862393Syz155240 instance = ddi_get_instance(dip); 3872393Syz155240 /* Only one instance of ipf (instance 0) can be attached. */ 3882393Syz155240 if (instance > 0) 3892393Syz155240 return DDI_FAILURE; 3902393Syz155240 if (fr_running != 0) 3912393Syz155240 return DDI_FAILURE; 3922393Syz155240 3932393Syz155240 #ifdef IPFDEBUG 3942393Syz155240 cmn_err(CE_NOTE, "IP Filter: attach ipf instance %d", instance); 3952393Syz155240 #endif 3962393Syz155240 3972393Syz155240 (void) ipf_property_update(dip); 3982393Syz155240 3992393Syz155240 for (i = 0; ((s = ipf_devfiles[i]) != NULL); i++) { 4002393Syz155240 s = strrchr(s, '/'); 4012393Syz155240 if (s == NULL) 4022393Syz155240 continue; 4032393Syz155240 s++; 4042393Syz155240 if (ddi_create_minor_node(dip, s, S_IFCHR, i, 4052393Syz155240 DDI_PSEUDO, 0) == 4062393Syz155240 DDI_FAILURE) { 4072393Syz155240 ddi_remove_minor_node(dip, NULL); 4082393Syz155240 goto attach_failed; 4092393Syz155240 } 4102393Syz155240 } 4112393Syz155240 4122393Syz155240 ipf_dev_info = dip; 4132393Syz155240 /* 4142393Syz155240 * Initialize mutex's 4152393Syz155240 */ 4162393Syz155240 RWLOCK_INIT(&ipf_global, "ipf filter load/unload mutex"); 4172393Syz155240 RWLOCK_INIT(&ipf_mutex, "ipf filter rwlock"); 4182393Syz155240 RWLOCK_INIT(&ipf_frcache, "ipf cache rwlock"); 4192393Syz155240 4202393Syz155240 /* 4212393Syz155240 * Lock people out while we set things up. 4222393Syz155240 */ 4232393Syz155240 WRITE_ENTER(&ipf_global); 4242393Syz155240 if ((fr_running != 0) || (iplattach() == -1)) { 4252393Syz155240 RWLOCK_EXIT(&ipf_global); 4262393Syz155240 goto attach_failed; 4272393Syz155240 } 4282393Syz155240 4292393Syz155240 fr_timer_id = timeout(fr_slowtimer, NULL, 4302393Syz155240 drv_usectohz(500000)); 4312393Syz155240 4322393Syz155240 fr_running = 1; 4332393Syz155240 4342393Syz155240 RWLOCK_EXIT(&ipf_global); 4352393Syz155240 4362393Syz155240 cmn_err(CE_CONT, "!%s, running.\n", ipfilter_version); 4372393Syz155240 4382393Syz155240 return DDI_SUCCESS; 4392393Syz155240 /* NOTREACHED */ 4402393Syz155240 default: 4412393Syz155240 break; 4422393Syz155240 } 4432393Syz155240 4442393Syz155240 attach_failed: 4452393Syz155240 #ifdef IPFDEBUG 4462393Syz155240 cmn_err(CE_NOTE, "IP Filter: failed to attach\n"); 4472393Syz155240 #endif 4482393Syz155240 /* 4492393Syz155240 * Use our own detach routine to toss 4502393Syz155240 * away any stuff we allocated above. 4512393Syz155240 */ 4522393Syz155240 (void) ipf_detach(dip, DDI_DETACH); 4532393Syz155240 return DDI_FAILURE; 4542393Syz155240 } 4552393Syz155240 4562393Syz155240 4572393Syz155240 static int ipf_detach(dip, cmd) 4582393Syz155240 dev_info_t *dip; 4592393Syz155240 ddi_detach_cmd_t cmd; 4602393Syz155240 { 4612393Syz155240 int i; 4622393Syz155240 4632393Syz155240 #ifdef IPFDEBUG 4642393Syz155240 cmn_err(CE_NOTE, "IP Filter: ipf_detach(%x,%x)", dip, cmd); 4652393Syz155240 #endif 4662393Syz155240 switch (cmd) { 4672393Syz155240 case DDI_DETACH: 4682393Syz155240 if (fr_refcnt != 0) 4692393Syz155240 return DDI_FAILURE; 4702393Syz155240 471*2958Sdr146992 if (fr_running == -2) 4722393Syz155240 break; 4732393Syz155240 /* 4742393Syz155240 * Make sure we're the only one's modifying things. With 4752393Syz155240 * this lock others should just fall out of the loop. 4762393Syz155240 */ 4772393Syz155240 WRITE_ENTER(&ipf_global); 4782393Syz155240 if (fr_running <= 0) { 4792393Syz155240 RWLOCK_EXIT(&ipf_global); 4802393Syz155240 return DDI_FAILURE; 4812393Syz155240 } 482*2958Sdr146992 /* 483*2958Sdr146992 * Make sure there is no active filter rule. 484*2958Sdr146992 */ 485*2958Sdr146992 if (ipfilter[0][fr_active] || ipfilter[1][fr_active] || 486*2958Sdr146992 ipfilter6[0][fr_active] || ipfilter6[1][fr_active]) { 487*2958Sdr146992 RWLOCK_EXIT(&ipf_global); 488*2958Sdr146992 return DDI_FAILURE; 489*2958Sdr146992 } 4902393Syz155240 fr_running = -2; 4912393Syz155240 4922393Syz155240 RWLOCK_EXIT(&ipf_global); 4932393Syz155240 4942393Syz155240 if (fr_timer_id != 0) { 4952393Syz155240 (void) untimeout(fr_timer_id); 4962393Syz155240 fr_timer_id = 0; 4972393Syz155240 } 4982393Syz155240 4992393Syz155240 /* 5002393Syz155240 * Undo what we did in ipf_attach, freeing resources 5012393Syz155240 * and removing things we installed. The system 5022393Syz155240 * framework guarantees we are not active with this devinfo 5032393Syz155240 * node in any other entry points at this time. 5042393Syz155240 */ 5052393Syz155240 ddi_prop_remove_all(dip); 5062393Syz155240 i = ddi_get_instance(dip); 5072393Syz155240 ddi_remove_minor_node(dip, NULL); 5082393Syz155240 if (i > 0) { 5092393Syz155240 cmn_err(CE_CONT, "IP Filter: still attached (%d)\n", i); 5102393Syz155240 return DDI_FAILURE; 5112393Syz155240 } 5122393Syz155240 5132393Syz155240 WRITE_ENTER(&ipf_global); 5142393Syz155240 if (!ipldetach()) { 5152393Syz155240 RWLOCK_EXIT(&ipf_global); 5162393Syz155240 RW_DESTROY(&ipf_mutex); 5172393Syz155240 RW_DESTROY(&ipf_frcache); 5182393Syz155240 RW_DESTROY(&ipf_global); 5192393Syz155240 cmn_err(CE_CONT, "!%s detached.\n", ipfilter_version); 5202393Syz155240 return (DDI_SUCCESS); 5212393Syz155240 } 5222393Syz155240 RWLOCK_EXIT(&ipf_global); 5232393Syz155240 break; 5242393Syz155240 default: 5252393Syz155240 break; 5262393Syz155240 } 5272393Syz155240 cmn_err(CE_NOTE, "IP Filter: failed to detach\n"); 5282393Syz155240 return DDI_FAILURE; 5292393Syz155240 } 5302393Syz155240 5312393Syz155240 5322393Syz155240 /*ARGSUSED*/ 5332393Syz155240 static int ipf_getinfo(dip, infocmd, arg, result) 5342393Syz155240 dev_info_t *dip; 5352393Syz155240 ddi_info_cmd_t infocmd; 5362393Syz155240 void *arg, **result; 5372393Syz155240 { 5382393Syz155240 int error; 5392393Syz155240 5402393Syz155240 if (fr_running <= 0) 5412393Syz155240 return DDI_FAILURE; 5422393Syz155240 error = DDI_FAILURE; 5432393Syz155240 #ifdef IPFDEBUG 5442393Syz155240 cmn_err(CE_NOTE, "IP Filter: ipf_getinfo(%x,%x,%x)", dip, infocmd, arg); 5452393Syz155240 #endif 5462393Syz155240 switch (infocmd) { 5472393Syz155240 case DDI_INFO_DEVT2DEVINFO: 5482393Syz155240 *result = ipf_dev_info; 5492393Syz155240 error = DDI_SUCCESS; 5502393Syz155240 break; 5512393Syz155240 case DDI_INFO_DEVT2INSTANCE: 5522393Syz155240 *result = (void *)0; 5532393Syz155240 error = DDI_SUCCESS; 5542393Syz155240 break; 5552393Syz155240 default: 5562393Syz155240 break; 5572393Syz155240 } 5582393Syz155240 return (error); 5592393Syz155240 } 5602393Syz155240 5612393Syz155240 5622393Syz155240 /* 5632393Syz155240 * Fetch configuration file values that have been entered into the ipf.conf 5642393Syz155240 * driver file. 5652393Syz155240 */ 5662393Syz155240 static int ipf_property_update(dip) 5672393Syz155240 dev_info_t *dip; 5682393Syz155240 { 5692393Syz155240 ipftuneable_t *ipft; 5702393Syz155240 int64_t *i64p; 5712393Syz155240 char *name; 5722393Syz155240 u_int one; 5732393Syz155240 int *i32p; 5742393Syz155240 int err; 5752393Syz155240 5762393Syz155240 #ifdef DDI_NO_AUTODETACH 5772393Syz155240 if (ddi_prop_update_int(DDI_DEV_T_NONE, dip, 5782393Syz155240 DDI_NO_AUTODETACH, 1) != DDI_PROP_SUCCESS) { 5792393Syz155240 cmn_err(CE_WARN, "!updating DDI_NO_AUTODETACH failed"); 5802393Syz155240 return DDI_FAILURE; 5812393Syz155240 } 5822393Syz155240 #else 5832393Syz155240 if (ddi_prop_update_int(DDI_DEV_T_NONE, dip, 5842393Syz155240 "ddi-no-autodetach", 1) != DDI_PROP_SUCCESS) { 5852393Syz155240 cmn_err(CE_WARN, "!updating ddi-no-autodetach failed"); 5862393Syz155240 return DDI_FAILURE; 5872393Syz155240 } 5882393Syz155240 #endif 5892393Syz155240 5902393Syz155240 err = DDI_SUCCESS; 5912393Syz155240 ipft = ipf_tuneables; 5922393Syz155240 for (ipft = ipf_tuneables; (name = ipft->ipft_name) != NULL; ipft++) { 5932393Syz155240 one = 1; 5942393Syz155240 switch (ipft->ipft_sz) 5952393Syz155240 { 5962393Syz155240 case 4 : 5972393Syz155240 i32p = NULL; 5982393Syz155240 err = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 5992393Syz155240 0, name, &i32p, &one); 6002393Syz155240 if (err == DDI_PROP_NOT_FOUND) 6012393Syz155240 continue; 6022393Syz155240 #ifdef IPFDEBUG 6032393Syz155240 cmn_err(CE_CONT, "IP Filter: lookup_int(%s) = %d\n", 6042393Syz155240 name, err); 6052393Syz155240 #endif 6062393Syz155240 if (err != DDI_PROP_SUCCESS) 6072393Syz155240 return err; 6082393Syz155240 if (*i32p >= ipft->ipft_min && *i32p <= ipft->ipft_max) 6092393Syz155240 *ipft->ipft_pint = *i32p; 6102393Syz155240 else 6112393Syz155240 err = DDI_PROP_CANNOT_DECODE; 6122393Syz155240 ddi_prop_free(i32p); 6132393Syz155240 break; 6142393Syz155240 6152393Syz155240 #if SOLARIS2 > 8 6162393Syz155240 case 8 : 6172393Syz155240 i64p = NULL; 6182393Syz155240 err = ddi_prop_lookup_int64_array(DDI_DEV_T_ANY, dip, 6192393Syz155240 0, name, &i64p, &one); 6202393Syz155240 if (err == DDI_PROP_NOT_FOUND) 6212393Syz155240 continue; 6222393Syz155240 # ifdef IPFDEBUG 6232393Syz155240 cmn_err(CE_CONT, "IP Filter: lookup_int64(%s) = %d\n", 6242393Syz155240 name, err); 6252393Syz155240 # endif 6262393Syz155240 if (err != DDI_PROP_SUCCESS) 6272393Syz155240 return err; 6282393Syz155240 if (*i64p >= ipft->ipft_min && *i64p <= ipft->ipft_max) 6292393Syz155240 *ipft->ipft_pint = *i64p; 6302393Syz155240 else 6312393Syz155240 err = DDI_PROP_CANNOT_DECODE; 6322393Syz155240 ddi_prop_free(i64p); 6332393Syz155240 break; 6342393Syz155240 #endif 6352393Syz155240 6362393Syz155240 default : 6372393Syz155240 break; 6382393Syz155240 } 6392393Syz155240 if (err != DDI_SUCCESS) 6402393Syz155240 break; 6412393Syz155240 } 6422393Syz155240 6432393Syz155240 return err; 6442393Syz155240 } 645