1ab25eeb5Syz155240 /* 2ab25eeb5Syz155240 * Copyright (C) 1993-2001, 2003 by Darren Reed. 3ab25eeb5Syz155240 * 4ab25eeb5Syz155240 * See the IPFILTER.LICENCE file for details on licencing. 5ab25eeb5Syz155240 * 614d3298eSAlexandr Nedvedicky * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 7ab25eeb5Syz155240 * Use is subject to license terms. 8*94bdecd9SRob Gulewich * 9*94bdecd9SRob Gulewich * Copyright (c) 2014, Joyent, Inc. All rights reserved. 10*94bdecd9SRob Gulewich */ 11*94bdecd9SRob Gulewich 12*94bdecd9SRob Gulewich /* 13*94bdecd9SRob Gulewich * ipfilter kernel module mutexes and locking: 14*94bdecd9SRob Gulewich * 15*94bdecd9SRob Gulewich * Enabling ipfilter creates a per-netstack ipf_stack_t object that is 16*94bdecd9SRob Gulewich * stored in the ipf_stacks list, which is protected by ipf_stack_lock. 17*94bdecd9SRob Gulewich * ipf_stack_t objects are accessed in three contexts: 18*94bdecd9SRob Gulewich * 19*94bdecd9SRob Gulewich * 1) administering that filter (eg: ioctls handled with iplioctl()) 20*94bdecd9SRob Gulewich * 2) reading log data (eg: iplread() / iplwrite()) 21*94bdecd9SRob Gulewich * 3) filtering packets (eg: ipf_hook4_* and ipf_hook6_* pfhooks 22*94bdecd9SRob Gulewich * functions) 23*94bdecd9SRob Gulewich * 24*94bdecd9SRob Gulewich * Each ipf_stack_t has a RW lock, ifs_ipf_global, protecting access to the 25*94bdecd9SRob Gulewich * whole structure. The structure also has locks protecting the various 26*94bdecd9SRob Gulewich * data structures used for filtering. The following guidelines should be 27*94bdecd9SRob Gulewich * followed for ipf_stack_t locks: 28*94bdecd9SRob Gulewich * 29*94bdecd9SRob Gulewich * - ipf_stack_lock must be held when accessing the ipf_stacks list 30*94bdecd9SRob Gulewich * - ipf_stack_lock should be held before acquiring ifs_ipf_global for 31*94bdecd9SRob Gulewich * a stack (the exception to this is ipf_stack_destroy(), which removes 32*94bdecd9SRob Gulewich * the ipf_stack_t from the list, then drops ipf_stack_lock before 33*94bdecd9SRob Gulewich * acquiring ifs_ipf_global) 34*94bdecd9SRob Gulewich * - ifs_ipf_global must be held when accessing an ipf_stack_t in that list: 35*94bdecd9SRob Gulewich * - The write lock is held only during stack creation / destruction 36*94bdecd9SRob Gulewich * - The read lock should be held for all other accesses 37*94bdecd9SRob Gulewich * - To alter the filtering data in the administrative context, one must: 38*94bdecd9SRob Gulewich * - acquire the read lock for ifs_ipf_global 39*94bdecd9SRob Gulewich * - then acquire the write lock for the data in question 40*94bdecd9SRob Gulewich * - In the filtering path, the read lock needs to be held for each type of 41*94bdecd9SRob Gulewich * filtering data used 42*94bdecd9SRob Gulewich * - ifs_ipf_global does not need to be held in the filtering path: 43*94bdecd9SRob Gulewich * - The filtering hooks don't need to modify the stack itself 44*94bdecd9SRob Gulewich * - The ipf_stack_t will not be destroyed until the hooks are unregistered. 45*94bdecd9SRob Gulewich * This requires a write lock on the hook, ensuring that no active hooks 46*94bdecd9SRob Gulewich * (eg: the filtering path) are running, and that the hooks won't be run 47*94bdecd9SRob Gulewich * afterward. 48*94bdecd9SRob Gulewich * 49*94bdecd9SRob Gulewich * Note that there is a deadlock possible when calling net_hook_register() 50*94bdecd9SRob Gulewich * or net_hook_unregister() with ifs_ipf_global held: see the comments in 51*94bdecd9SRob Gulewich * iplattach() and ipldetach() for details. 52ab25eeb5Syz155240 */ 53ab25eeb5Syz155240 54ab25eeb5Syz155240 #include <sys/systm.h> 55ab25eeb5Syz155240 #include <sys/types.h> 56ab25eeb5Syz155240 #include <sys/param.h> 57ab25eeb5Syz155240 #include <sys/errno.h> 58ab25eeb5Syz155240 #include <sys/uio.h> 59ab25eeb5Syz155240 #include <sys/buf.h> 60ab25eeb5Syz155240 #include <sys/modctl.h> 61ab25eeb5Syz155240 #include <sys/open.h> 62ab25eeb5Syz155240 #include <sys/kmem.h> 63ab25eeb5Syz155240 #include <sys/conf.h> 64ab25eeb5Syz155240 #include <sys/cmn_err.h> 65ab25eeb5Syz155240 #include <sys/stat.h> 66ab25eeb5Syz155240 #include <sys/cred.h> 67ab25eeb5Syz155240 #include <sys/dditypes.h> 68ab25eeb5Syz155240 #include <sys/poll.h> 69ab25eeb5Syz155240 #include <sys/autoconf.h> 70ab25eeb5Syz155240 #include <sys/byteorder.h> 71ab25eeb5Syz155240 #include <sys/socket.h> 72ab25eeb5Syz155240 #include <sys/dlpi.h> 73ab25eeb5Syz155240 #include <sys/stropts.h> 74ab25eeb5Syz155240 #include <sys/kstat.h> 75ab25eeb5Syz155240 #include <sys/sockio.h> 76381a2a9aSdr146992 #include <sys/neti.h> 77381a2a9aSdr146992 #include <sys/hook.h> 78ab25eeb5Syz155240 #include <net/if.h> 79ab25eeb5Syz155240 #if SOLARIS2 >= 6 80ab25eeb5Syz155240 #include <net/if_types.h> 81ab25eeb5Syz155240 #endif 82ab25eeb5Syz155240 #include <net/af.h> 83ab25eeb5Syz155240 #include <net/route.h> 84ab25eeb5Syz155240 #include <netinet/in.h> 85ab25eeb5Syz155240 #include <netinet/in_systm.h> 86ab25eeb5Syz155240 #include <netinet/if_ether.h> 87ab25eeb5Syz155240 #include <netinet/ip.h> 88ab25eeb5Syz155240 #include <netinet/ip_var.h> 89ab25eeb5Syz155240 #include <netinet/tcp.h> 90ab25eeb5Syz155240 #include <netinet/udp.h> 91ab25eeb5Syz155240 #include <netinet/tcpip.h> 92ab25eeb5Syz155240 #include <netinet/ip_icmp.h> 93ab25eeb5Syz155240 #include <sys/ddi.h> 94ab25eeb5Syz155240 #include <sys/sunddi.h> 95ab25eeb5Syz155240 #include "netinet/ip_compat.h" 96ab25eeb5Syz155240 #include "netinet/ipl.h" 97ab25eeb5Syz155240 #include "netinet/ip_fil.h" 98ab25eeb5Syz155240 #include "netinet/ip_nat.h" 99ab25eeb5Syz155240 #include "netinet/ip_frag.h" 100ab25eeb5Syz155240 #include "netinet/ip_auth.h" 101ab25eeb5Syz155240 #include "netinet/ip_state.h" 102f4b3ec61Sdh155122 #include "netinet/ipf_stack.h" 103ab25eeb5Syz155240 104ab25eeb5Syz155240 extern int iplwrite __P((dev_t, struct uio *, cred_t *)); 105ab25eeb5Syz155240 106ab25eeb5Syz155240 static int ipf_getinfo __P((dev_info_t *, ddi_info_cmd_t, 107ab25eeb5Syz155240 void *, void **)); 108ab25eeb5Syz155240 #if SOLARIS2 < 10 109ab25eeb5Syz155240 static int ipf_identify __P((dev_info_t *)); 110ab25eeb5Syz155240 #endif 111ab25eeb5Syz155240 static int ipf_attach __P((dev_info_t *, ddi_attach_cmd_t)); 112ab25eeb5Syz155240 static int ipf_detach __P((dev_info_t *, ddi_detach_cmd_t)); 1137ddc9b1aSDarren Reed static void *ipf_stack_create __P((const netid_t)); 1147ddc9b1aSDarren Reed static void ipf_stack_destroy __P((const netid_t, void *)); 1158ad74188SDarren Reed static void ipf_stack_shutdown __P((const netid_t, void *)); 116f4b3ec61Sdh155122 static int ipf_property_g_update __P((dev_info_t *)); 117ab25eeb5Syz155240 static char *ipf_devfiles[] = { IPL_NAME, IPNAT_NAME, IPSTATE_NAME, 118ab25eeb5Syz155240 IPAUTH_NAME, IPSYNC_NAME, IPSCAN_NAME, 119ab25eeb5Syz155240 IPLOOKUP_NAME, NULL }; 120*94bdecd9SRob Gulewich extern void *ipf_state; /* DDI state */ 121*94bdecd9SRob Gulewich extern vmem_t *ipf_minor; /* minor number arena */ 122ab25eeb5Syz155240 123ab25eeb5Syz155240 static struct cb_ops ipf_cb_ops = { 124ab25eeb5Syz155240 iplopen, 125ab25eeb5Syz155240 iplclose, 126ab25eeb5Syz155240 nodev, /* strategy */ 127ab25eeb5Syz155240 nodev, /* print */ 128ab25eeb5Syz155240 nodev, /* dump */ 129ab25eeb5Syz155240 iplread, 130ab25eeb5Syz155240 iplwrite, /* write */ 131ab25eeb5Syz155240 iplioctl, /* ioctl */ 132ab25eeb5Syz155240 nodev, /* devmap */ 133ab25eeb5Syz155240 nodev, /* mmap */ 134ab25eeb5Syz155240 nodev, /* segmap */ 135ab25eeb5Syz155240 nochpoll, /* poll */ 136ab25eeb5Syz155240 ddi_prop_op, 137ab25eeb5Syz155240 NULL, 138ab25eeb5Syz155240 D_MTSAFE, 139ab25eeb5Syz155240 #if SOLARIS2 > 4 140ab25eeb5Syz155240 CB_REV, 141ab25eeb5Syz155240 nodev, /* aread */ 142ab25eeb5Syz155240 nodev, /* awrite */ 143ab25eeb5Syz155240 #endif 144ab25eeb5Syz155240 }; 145ab25eeb5Syz155240 146ab25eeb5Syz155240 static struct dev_ops ipf_ops = { 147ab25eeb5Syz155240 DEVO_REV, 148ab25eeb5Syz155240 0, 149ab25eeb5Syz155240 ipf_getinfo, 150ab25eeb5Syz155240 #if SOLARIS2 >= 10 151ab25eeb5Syz155240 nulldev, 152ab25eeb5Syz155240 #else 153ab25eeb5Syz155240 ipf_identify, 154ab25eeb5Syz155240 #endif 155ab25eeb5Syz155240 nulldev, 156ab25eeb5Syz155240 ipf_attach, 157ab25eeb5Syz155240 ipf_detach, 158ab25eeb5Syz155240 nodev, /* reset */ 159ab25eeb5Syz155240 &ipf_cb_ops, 16019397407SSherry Moore (struct bus_ops *)0, 16119397407SSherry Moore NULL, 16219397407SSherry Moore ddi_quiesce_not_needed, /* quiesce */ 163ab25eeb5Syz155240 }; 164ab25eeb5Syz155240 1657ddc9b1aSDarren Reed 1667ddc9b1aSDarren Reed static net_instance_t *ipfncb = NULL; 1677ddc9b1aSDarren Reed static ipf_stack_t *ipf_stacks = NULL; 1687ddc9b1aSDarren Reed static kmutex_t ipf_stack_lock; 169ab25eeb5Syz155240 extern struct mod_ops mod_driverops; 170ab25eeb5Syz155240 static struct modldrv iplmod = { 171ab25eeb5Syz155240 &mod_driverops, IPL_VERSION, &ipf_ops }; 172ab25eeb5Syz155240 static struct modlinkage modlink1 = { MODREV_1, &iplmod, NULL }; 173ab25eeb5Syz155240 174ab25eeb5Syz155240 #if SOLARIS2 >= 6 175ab25eeb5Syz155240 static size_t hdrsizes[57][2] = { 176ab25eeb5Syz155240 { 0, 0 }, 177ab25eeb5Syz155240 { IFT_OTHER, 0 }, 178ab25eeb5Syz155240 { IFT_1822, 0 }, 179ab25eeb5Syz155240 { IFT_HDH1822, 0 }, 180ab25eeb5Syz155240 { IFT_X25DDN, 0 }, 181ab25eeb5Syz155240 { IFT_X25, 0 }, 182ab25eeb5Syz155240 { IFT_ETHER, 14 }, 183ab25eeb5Syz155240 { IFT_ISO88023, 0 }, 184ab25eeb5Syz155240 { IFT_ISO88024, 0 }, 185ab25eeb5Syz155240 { IFT_ISO88025, 0 }, 186ab25eeb5Syz155240 { IFT_ISO88026, 0 }, 187ab25eeb5Syz155240 { IFT_STARLAN, 0 }, 188ab25eeb5Syz155240 { IFT_P10, 0 }, 189ab25eeb5Syz155240 { IFT_P80, 0 }, 190ab25eeb5Syz155240 { IFT_HY, 0 }, 191ab25eeb5Syz155240 { IFT_FDDI, 24 }, 192ab25eeb5Syz155240 { IFT_LAPB, 0 }, 193ab25eeb5Syz155240 { IFT_SDLC, 0 }, 194ab25eeb5Syz155240 { IFT_T1, 0 }, 195ab25eeb5Syz155240 { IFT_CEPT, 0 }, 196ab25eeb5Syz155240 { IFT_ISDNBASIC, 0 }, 197ab25eeb5Syz155240 { IFT_ISDNPRIMARY, 0 }, 198ab25eeb5Syz155240 { IFT_PTPSERIAL, 0 }, 199ab25eeb5Syz155240 { IFT_PPP, 0 }, 200ab25eeb5Syz155240 { IFT_LOOP, 0 }, 201ab25eeb5Syz155240 { IFT_EON, 0 }, 202ab25eeb5Syz155240 { IFT_XETHER, 0 }, 203ab25eeb5Syz155240 { IFT_NSIP, 0 }, 204ab25eeb5Syz155240 { IFT_SLIP, 0 }, 205ab25eeb5Syz155240 { IFT_ULTRA, 0 }, 206ab25eeb5Syz155240 { IFT_DS3, 0 }, 207ab25eeb5Syz155240 { IFT_SIP, 0 }, 208ab25eeb5Syz155240 { IFT_FRELAY, 0 }, 209ab25eeb5Syz155240 { IFT_RS232, 0 }, 210ab25eeb5Syz155240 { IFT_PARA, 0 }, 211ab25eeb5Syz155240 { IFT_ARCNET, 0 }, 212ab25eeb5Syz155240 { IFT_ARCNETPLUS, 0 }, 213ab25eeb5Syz155240 { IFT_ATM, 0 }, 214ab25eeb5Syz155240 { IFT_MIOX25, 0 }, 215ab25eeb5Syz155240 { IFT_SONET, 0 }, 216ab25eeb5Syz155240 { IFT_X25PLE, 0 }, 217ab25eeb5Syz155240 { IFT_ISO88022LLC, 0 }, 218ab25eeb5Syz155240 { IFT_LOCALTALK, 0 }, 219ab25eeb5Syz155240 { IFT_SMDSDXI, 0 }, 220ab25eeb5Syz155240 { IFT_FRELAYDCE, 0 }, 221ab25eeb5Syz155240 { IFT_V35, 0 }, 222ab25eeb5Syz155240 { IFT_HSSI, 0 }, 223ab25eeb5Syz155240 { IFT_HIPPI, 0 }, 224ab25eeb5Syz155240 { IFT_MODEM, 0 }, 225ab25eeb5Syz155240 { IFT_AAL5, 0 }, 226ab25eeb5Syz155240 { IFT_SONETPATH, 0 }, 227ab25eeb5Syz155240 { IFT_SONETVT, 0 }, 228ab25eeb5Syz155240 { IFT_SMDSICIP, 0 }, 229ab25eeb5Syz155240 { IFT_PROPVIRTUAL, 0 }, 230ab25eeb5Syz155240 { IFT_PROPMUX, 0 }, 231ab25eeb5Syz155240 }; 232ab25eeb5Syz155240 #endif /* SOLARIS2 >= 6 */ 233ab25eeb5Syz155240 234f4b3ec61Sdh155122 dev_info_t *ipf_dev_info = NULL; 235ab25eeb5Syz155240 236ab25eeb5Syz155240 static const filter_kstats_t ipf_kstat_tmp = { 237ab25eeb5Syz155240 { "pass", KSTAT_DATA_ULONG }, 238ab25eeb5Syz155240 { "block", KSTAT_DATA_ULONG }, 239ab25eeb5Syz155240 { "nomatch", KSTAT_DATA_ULONG }, 240ab25eeb5Syz155240 { "short", KSTAT_DATA_ULONG }, 241ab25eeb5Syz155240 { "pass, logged", KSTAT_DATA_ULONG }, 242ab25eeb5Syz155240 { "block, logged", KSTAT_DATA_ULONG }, 243ab25eeb5Syz155240 { "nomatch, logged", KSTAT_DATA_ULONG }, 244ab25eeb5Syz155240 { "logged", KSTAT_DATA_ULONG }, 245ab25eeb5Syz155240 { "skip", KSTAT_DATA_ULONG }, 246ab25eeb5Syz155240 { "return sent", KSTAT_DATA_ULONG }, 247ab25eeb5Syz155240 { "acct", KSTAT_DATA_ULONG }, 248ab25eeb5Syz155240 { "bad frag state alloc", KSTAT_DATA_ULONG }, 249ab25eeb5Syz155240 { "new frag state kept", KSTAT_DATA_ULONG }, 250ab25eeb5Syz155240 { "new frag state compl. pkt", KSTAT_DATA_ULONG }, 251ab25eeb5Syz155240 { "bad pkt state alloc", KSTAT_DATA_ULONG }, 252ab25eeb5Syz155240 { "new pkt kept state", KSTAT_DATA_ULONG }, 253ab25eeb5Syz155240 { "cachehit", KSTAT_DATA_ULONG }, 254ab25eeb5Syz155240 { "tcp cksum bad", KSTAT_DATA_ULONG }, 255ab25eeb5Syz155240 {{ "pullup ok", KSTAT_DATA_ULONG }, 256ab25eeb5Syz155240 { "pullup nok", KSTAT_DATA_ULONG }}, 257ab25eeb5Syz155240 { "src != route", KSTAT_DATA_ULONG }, 258ab25eeb5Syz155240 { "ttl invalid", KSTAT_DATA_ULONG }, 259ab25eeb5Syz155240 { "bad ip pkt", KSTAT_DATA_ULONG }, 260ab25eeb5Syz155240 { "ipv6 pkt", KSTAT_DATA_ULONG }, 261ab25eeb5Syz155240 { "dropped:pps ceiling", KSTAT_DATA_ULONG }, 262ab25eeb5Syz155240 { "ip upd. fail", KSTAT_DATA_ULONG } 263ab25eeb5Syz155240 }; 264ab25eeb5Syz155240 265381a2a9aSdr146992 266ab25eeb5Syz155240 static int ipf_kstat_update(kstat_t *ksp, int rwflag); 267ab25eeb5Syz155240 268ab25eeb5Syz155240 static void 269*94bdecd9SRob Gulewich ipf_kstat_init(ipf_stack_t *ifs, boolean_t from_gz) 270ab25eeb5Syz155240 { 271*94bdecd9SRob Gulewich ifs->ifs_kstatp[0] = net_kstat_create(ifs->ifs_netid, 272*94bdecd9SRob Gulewich (from_gz ? "ipf_gz" : "ipf"), 273*94bdecd9SRob Gulewich 0, "inbound", "net", KSTAT_TYPE_NAMED, 2747ddc9b1aSDarren Reed sizeof (filter_kstats_t) / sizeof (kstat_named_t), 0); 2757ddc9b1aSDarren Reed if (ifs->ifs_kstatp[0] != NULL) { 2767ddc9b1aSDarren Reed bcopy(&ipf_kstat_tmp, ifs->ifs_kstatp[0]->ks_data, 277ab25eeb5Syz155240 sizeof (filter_kstats_t)); 2787ddc9b1aSDarren Reed ifs->ifs_kstatp[0]->ks_update = ipf_kstat_update; 2797ddc9b1aSDarren Reed ifs->ifs_kstatp[0]->ks_private = &ifs->ifs_frstats[0]; 2807ddc9b1aSDarren Reed kstat_install(ifs->ifs_kstatp[0]); 281ab25eeb5Syz155240 } 2827ddc9b1aSDarren Reed 283*94bdecd9SRob Gulewich ifs->ifs_kstatp[1] = net_kstat_create(ifs->ifs_netid, 284*94bdecd9SRob Gulewich (from_gz ? "ipf_gz" : "ipf"), 285*94bdecd9SRob Gulewich 0, "outbound", "net", KSTAT_TYPE_NAMED, 2867ddc9b1aSDarren Reed sizeof (filter_kstats_t) / sizeof (kstat_named_t), 0); 2877ddc9b1aSDarren Reed if (ifs->ifs_kstatp[1] != NULL) { 2887ddc9b1aSDarren Reed bcopy(&ipf_kstat_tmp, ifs->ifs_kstatp[1]->ks_data, 2897ddc9b1aSDarren Reed sizeof (filter_kstats_t)); 2907ddc9b1aSDarren Reed ifs->ifs_kstatp[1]->ks_update = ipf_kstat_update; 2917ddc9b1aSDarren Reed ifs->ifs_kstatp[1]->ks_private = &ifs->ifs_frstats[1]; 2927ddc9b1aSDarren Reed kstat_install(ifs->ifs_kstatp[1]); 293ab25eeb5Syz155240 } 294ab25eeb5Syz155240 295ab25eeb5Syz155240 #ifdef IPFDEBUG 2967ddc9b1aSDarren Reed cmn_err(CE_NOTE, "IP Filter: ipf_kstat_init(%p) installed %p, %p", 2977ddc9b1aSDarren Reed ifs, ifs->ifs_kstatp[0], ifs->ifs_kstatp[1]); 298ab25eeb5Syz155240 #endif 299ab25eeb5Syz155240 } 300ab25eeb5Syz155240 3017ddc9b1aSDarren Reed 302ab25eeb5Syz155240 static void 3037ddc9b1aSDarren Reed ipf_kstat_fini(ipf_stack_t *ifs) 304ab25eeb5Syz155240 { 305ab25eeb5Syz155240 int i; 306f4b3ec61Sdh155122 307ab25eeb5Syz155240 for (i = 0; i < 2; i++) { 308f4b3ec61Sdh155122 if (ifs->ifs_kstatp[i] != NULL) { 3097ddc9b1aSDarren Reed net_kstat_delete(ifs->ifs_netid, ifs->ifs_kstatp[i]); 310f4b3ec61Sdh155122 ifs->ifs_kstatp[i] = NULL; 311ab25eeb5Syz155240 } 312ab25eeb5Syz155240 } 313ab25eeb5Syz155240 } 314ab25eeb5Syz155240 3157ddc9b1aSDarren Reed 316ab25eeb5Syz155240 static int 317ab25eeb5Syz155240 ipf_kstat_update(kstat_t *ksp, int rwflag) 318ab25eeb5Syz155240 { 319ab25eeb5Syz155240 filter_kstats_t *fkp; 320ab25eeb5Syz155240 filterstats_t *fsp; 321ab25eeb5Syz155240 322f4b3ec61Sdh155122 if (ksp == NULL || ksp->ks_data == NULL) 323f4b3ec61Sdh155122 return (EIO); 324f4b3ec61Sdh155122 325ab25eeb5Syz155240 if (rwflag == KSTAT_WRITE) 326ab25eeb5Syz155240 return (EACCES); 327ab25eeb5Syz155240 328ab25eeb5Syz155240 fkp = ksp->ks_data; 329ab25eeb5Syz155240 fsp = ksp->ks_private; 330ab25eeb5Syz155240 331ab25eeb5Syz155240 fkp->fks_pass.value.ul = fsp->fr_pass; 332ab25eeb5Syz155240 fkp->fks_block.value.ul = fsp->fr_block; 333ab25eeb5Syz155240 fkp->fks_nom.value.ul = fsp->fr_nom; 334ab25eeb5Syz155240 fkp->fks_short.value.ul = fsp->fr_short; 335ab25eeb5Syz155240 fkp->fks_ppkl.value.ul = fsp->fr_ppkl; 336ab25eeb5Syz155240 fkp->fks_bpkl.value.ul = fsp->fr_bpkl; 337ab25eeb5Syz155240 fkp->fks_npkl.value.ul = fsp->fr_npkl; 338ab25eeb5Syz155240 fkp->fks_pkl.value.ul = fsp->fr_pkl; 339ab25eeb5Syz155240 fkp->fks_skip.value.ul = fsp->fr_skip; 340ab25eeb5Syz155240 fkp->fks_ret.value.ul = fsp->fr_ret; 341ab25eeb5Syz155240 fkp->fks_acct.value.ul = fsp->fr_acct; 342ab25eeb5Syz155240 fkp->fks_bnfr.value.ul = fsp->fr_bnfr; 343ab25eeb5Syz155240 fkp->fks_nfr.value.ul = fsp->fr_nfr; 344ab25eeb5Syz155240 fkp->fks_cfr.value.ul = fsp->fr_cfr; 345ab25eeb5Syz155240 fkp->fks_bads.value.ul = fsp->fr_bads; 346ab25eeb5Syz155240 fkp->fks_ads.value.ul = fsp->fr_ads; 347ab25eeb5Syz155240 fkp->fks_chit.value.ul = fsp->fr_chit; 348ab25eeb5Syz155240 fkp->fks_tcpbad.value.ul = fsp->fr_tcpbad; 349ab25eeb5Syz155240 fkp->fks_pull[0].value.ul = fsp->fr_pull[0]; 350ab25eeb5Syz155240 fkp->fks_pull[1].value.ul = fsp->fr_pull[1]; 351ab25eeb5Syz155240 fkp->fks_badsrc.value.ul = fsp->fr_badsrc; 352ab25eeb5Syz155240 fkp->fks_badttl.value.ul = fsp->fr_badttl; 353ab25eeb5Syz155240 fkp->fks_bad.value.ul = fsp->fr_bad; 354ab25eeb5Syz155240 fkp->fks_ipv6.value.ul = fsp->fr_ipv6; 355ab25eeb5Syz155240 fkp->fks_ppshit.value.ul = fsp->fr_ppshit; 356ab25eeb5Syz155240 fkp->fks_ipud.value.ul = fsp->fr_ipud; 357ab25eeb5Syz155240 358ab25eeb5Syz155240 return (0); 359ab25eeb5Syz155240 } 360ab25eeb5Syz155240 36119397407SSherry Moore int 36219397407SSherry Moore _init() 363ab25eeb5Syz155240 { 364ab25eeb5Syz155240 int ipfinst; 365ab25eeb5Syz155240 366ab25eeb5Syz155240 ipfinst = mod_install(&modlink1); 367ab25eeb5Syz155240 #ifdef IPFDEBUG 368ab25eeb5Syz155240 cmn_err(CE_NOTE, "IP Filter: _init() = %d", ipfinst); 369ab25eeb5Syz155240 #endif 3707ddc9b1aSDarren Reed mutex_init(&ipf_stack_lock, NULL, MUTEX_DRIVER, NULL); 37119397407SSherry Moore return (ipfinst); 372ab25eeb5Syz155240 } 373ab25eeb5Syz155240 374ab25eeb5Syz155240 37519397407SSherry Moore int 37619397407SSherry Moore _fini(void) 377ab25eeb5Syz155240 { 378ab25eeb5Syz155240 int ipfinst; 379ab25eeb5Syz155240 380ab25eeb5Syz155240 ipfinst = mod_remove(&modlink1); 381ab25eeb5Syz155240 #ifdef IPFDEBUG 382ab25eeb5Syz155240 cmn_err(CE_NOTE, "IP Filter: _fini() = %d", ipfinst); 383ab25eeb5Syz155240 #endif 38419397407SSherry Moore return (ipfinst); 385ab25eeb5Syz155240 } 386ab25eeb5Syz155240 387ab25eeb5Syz155240 38819397407SSherry Moore int 38919397407SSherry Moore _info(modinfop) 390ab25eeb5Syz155240 struct modinfo *modinfop; 391ab25eeb5Syz155240 { 392ab25eeb5Syz155240 int ipfinst; 393ab25eeb5Syz155240 394ab25eeb5Syz155240 ipfinst = mod_info(&modlink1, modinfop); 395ab25eeb5Syz155240 #ifdef IPFDEBUG 3967ddc9b1aSDarren Reed cmn_err(CE_NOTE, "IP Filter: _info(%p) = %d", modinfop, ipfinst); 397ab25eeb5Syz155240 #endif 39819397407SSherry Moore return (ipfinst); 399ab25eeb5Syz155240 } 400ab25eeb5Syz155240 401ab25eeb5Syz155240 402ab25eeb5Syz155240 #if SOLARIS2 < 10 403ab25eeb5Syz155240 static int ipf_identify(dip) 404ab25eeb5Syz155240 dev_info_t *dip; 405ab25eeb5Syz155240 { 406ab25eeb5Syz155240 #ifdef IPFDEBUG 4077ddc9b1aSDarren Reed cmn_err(CE_NOTE, "IP Filter: ipf_identify(%p)", dip); 408ab25eeb5Syz155240 #endif 409ab25eeb5Syz155240 if (strcmp(ddi_get_name(dip), "ipf") == 0) 410ab25eeb5Syz155240 return (DDI_IDENTIFIED); 411ab25eeb5Syz155240 return (DDI_NOT_IDENTIFIED); 412ab25eeb5Syz155240 } 413ab25eeb5Syz155240 #endif 414ab25eeb5Syz155240 415f4b3ec61Sdh155122 /* 416f4b3ec61Sdh155122 * Initialize things for IPF for each stack instance 417f4b3ec61Sdh155122 */ 418f4b3ec61Sdh155122 static void * 419*94bdecd9SRob Gulewich ipf_stack_create_one(const netid_t id, const zoneid_t zid, boolean_t from_gz, 420*94bdecd9SRob Gulewich ipf_stack_t *ifs_gz) 421f4b3ec61Sdh155122 { 422f4b3ec61Sdh155122 ipf_stack_t *ifs; 423f4b3ec61Sdh155122 4247ddc9b1aSDarren Reed #ifdef IPFDEBUG 425*94bdecd9SRob Gulewich cmn_err(CE_NOTE, "IP Filter:stack_create_one id=%d global=%d", id, 426*94bdecd9SRob Gulewich global); 427f4b3ec61Sdh155122 #endif 428f4b3ec61Sdh155122 4297ddc9b1aSDarren Reed ifs = (ipf_stack_t *)kmem_alloc(sizeof (*ifs), KM_SLEEP); 430f4b3ec61Sdh155122 bzero(ifs, sizeof (*ifs)); 431f4b3ec61Sdh155122 432f4b3ec61Sdh155122 ifs->ifs_hook4_physical_in = B_FALSE; 433f4b3ec61Sdh155122 ifs->ifs_hook4_physical_out = B_FALSE; 434f4b3ec61Sdh155122 ifs->ifs_hook4_nic_events = B_FALSE; 435f4b3ec61Sdh155122 ifs->ifs_hook4_loopback_in = B_FALSE; 436f4b3ec61Sdh155122 ifs->ifs_hook4_loopback_out = B_FALSE; 437f4b3ec61Sdh155122 ifs->ifs_hook6_physical_in = B_FALSE; 438f4b3ec61Sdh155122 ifs->ifs_hook6_physical_out = B_FALSE; 439f4b3ec61Sdh155122 ifs->ifs_hook6_nic_events = B_FALSE; 440f4b3ec61Sdh155122 ifs->ifs_hook6_loopback_in = B_FALSE; 441f4b3ec61Sdh155122 ifs->ifs_hook6_loopback_out = B_FALSE; 442f4b3ec61Sdh155122 443f4b3ec61Sdh155122 /* 444f4b3ec61Sdh155122 * Initialize mutex's 445f4b3ec61Sdh155122 */ 446f4b3ec61Sdh155122 RWLOCK_INIT(&ifs->ifs_ipf_global, "ipf filter load/unload mutex"); 447f4b3ec61Sdh155122 RWLOCK_INIT(&ifs->ifs_ipf_mutex, "ipf filter rwlock"); 44814d3298eSAlexandr Nedvedicky RWLOCK_INIT(&ifs->ifs_ipf_frcache, "ipf cache rwlock"); 4497ddc9b1aSDarren Reed ifs->ifs_netid = id; 450*94bdecd9SRob Gulewich ifs->ifs_zone = zid; 451*94bdecd9SRob Gulewich ifs->ifs_gz_controlled = from_gz; 452*94bdecd9SRob Gulewich ifs->ifs_gz_cont_ifs = ifs_gz; 453*94bdecd9SRob Gulewich 454*94bdecd9SRob Gulewich ipf_kstat_init(ifs, from_gz); 4557ddc9b1aSDarren Reed 4567ddc9b1aSDarren Reed #ifdef IPFDEBUG 4577ddc9b1aSDarren Reed cmn_err(CE_CONT, "IP Filter:stack_create zone=%d", ifs->ifs_zone); 458f4b3ec61Sdh155122 #endif 459f4b3ec61Sdh155122 460f4b3ec61Sdh155122 /* 461f4b3ec61Sdh155122 * Lock people out while we set things up. 462f4b3ec61Sdh155122 */ 463f4b3ec61Sdh155122 WRITE_ENTER(&ifs->ifs_ipf_global); 464f4b3ec61Sdh155122 ipftuneable_alloc(ifs); 465f4b3ec61Sdh155122 RWLOCK_EXIT(&ifs->ifs_ipf_global); 466f4b3ec61Sdh155122 46723f4867fSnordmark /* Limit to global stack */ 4687ddc9b1aSDarren Reed if (ifs->ifs_zone == GLOBAL_ZONEID) 469f4b3ec61Sdh155122 cmn_err(CE_CONT, "!%s, running.\n", ipfilter_version); 47023f4867fSnordmark 4717ddc9b1aSDarren Reed mutex_enter(&ipf_stack_lock); 4727ddc9b1aSDarren Reed if (ipf_stacks != NULL) 4737ddc9b1aSDarren Reed ipf_stacks->ifs_pnext = &ifs->ifs_next; 4747ddc9b1aSDarren Reed ifs->ifs_next = ipf_stacks; 4757ddc9b1aSDarren Reed ifs->ifs_pnext = &ipf_stacks; 4767ddc9b1aSDarren Reed ipf_stacks = ifs; 4777ddc9b1aSDarren Reed mutex_exit(&ipf_stack_lock); 4787ddc9b1aSDarren Reed 479f4b3ec61Sdh155122 return (ifs); 480f4b3ec61Sdh155122 } 481f4b3ec61Sdh155122 482*94bdecd9SRob Gulewich static void * 483*94bdecd9SRob Gulewich ipf_stack_create(const netid_t id) 484*94bdecd9SRob Gulewich { 485*94bdecd9SRob Gulewich ipf_stack_t *ifs = NULL; 486*94bdecd9SRob Gulewich zoneid_t zid = net_getzoneidbynetid(id); 4877ddc9b1aSDarren Reed 4887ddc9b1aSDarren Reed /* 489*94bdecd9SRob Gulewich * Create two ipfilter stacks for a zone - the first can only be 490*94bdecd9SRob Gulewich * controlled from the global zone, and the second is owned by 491*94bdecd9SRob Gulewich * the zone itself. There is no need to create a GZ-controlled 492*94bdecd9SRob Gulewich * stack for the global zone, since we're already in the global 493*94bdecd9SRob Gulewich * zone. See the "GZ-controlled and per-zone stacks" comment block in 494*94bdecd9SRob Gulewich * ip_fil_solaris.c for details. 495*94bdecd9SRob Gulewich */ 496*94bdecd9SRob Gulewich if (zid != GLOBAL_ZONEID) 497*94bdecd9SRob Gulewich ifs = ipf_stack_create_one(id, zid, B_TRUE, NULL); 498*94bdecd9SRob Gulewich 499*94bdecd9SRob Gulewich return (ipf_stack_create_one(id, zid, B_FALSE, ifs)); 500*94bdecd9SRob Gulewich } 501*94bdecd9SRob Gulewich 502*94bdecd9SRob Gulewich /* 503*94bdecd9SRob Gulewich * Find an ipfilter stack for the given zone. Return the GZ-controlled or 504*94bdecd9SRob Gulewich * per-zone stack if set by an earlier SIOCIPFZONESET ioctl call. See the 505*94bdecd9SRob Gulewich * "GZ-controlled and per-zone stacks" comment block in ip_fil_solaris.c for 506*94bdecd9SRob Gulewich * details. 507*94bdecd9SRob Gulewich * 508*94bdecd9SRob Gulewich * This function returns with the ipf_stack_t's ifs_ipf_global 509*94bdecd9SRob Gulewich * read lock held (if the stack is found). See the "ipfilter kernel module 510*94bdecd9SRob Gulewich * mutexes and locking" comment block at the top of this file. 5117ddc9b1aSDarren Reed */ 51219397407SSherry Moore ipf_stack_t * 513*94bdecd9SRob Gulewich ipf_find_stack(const zoneid_t orig_zone, ipf_devstate_t *isp) 5147ddc9b1aSDarren Reed { 5157ddc9b1aSDarren Reed ipf_stack_t *ifs; 516*94bdecd9SRob Gulewich boolean_t gz_stack; 517*94bdecd9SRob Gulewich zoneid_t zone; 518*94bdecd9SRob Gulewich 519*94bdecd9SRob Gulewich /* 520*94bdecd9SRob Gulewich * If we're in the GZ, determine if we're acting on a zone's stack, 521*94bdecd9SRob Gulewich * and whether or not that stack is the GZ-controlled or in-zone 522*94bdecd9SRob Gulewich * one. See the "GZ and per-zone stacks" note at the top of this 523*94bdecd9SRob Gulewich * file. 524*94bdecd9SRob Gulewich */ 525*94bdecd9SRob Gulewich if (orig_zone == GLOBAL_ZONEID && 526*94bdecd9SRob Gulewich (isp->ipfs_zoneid != IPFS_ZONE_UNSET)) { 527*94bdecd9SRob Gulewich /* Global zone, and we've set the zoneid for this fd already */ 528*94bdecd9SRob Gulewich 529*94bdecd9SRob Gulewich if (orig_zone == isp->ipfs_zoneid) { 530*94bdecd9SRob Gulewich /* There's only a per-zone stack for the GZ */ 531*94bdecd9SRob Gulewich gz_stack = B_FALSE; 532*94bdecd9SRob Gulewich } else { 533*94bdecd9SRob Gulewich gz_stack = isp->ipfs_gz; 534*94bdecd9SRob Gulewich } 535*94bdecd9SRob Gulewich 536*94bdecd9SRob Gulewich zone = isp->ipfs_zoneid; 537*94bdecd9SRob Gulewich } else { 538*94bdecd9SRob Gulewich /* 539*94bdecd9SRob Gulewich * Non-global zone or GZ without having set a zoneid: act on 540*94bdecd9SRob Gulewich * the per-zone stack of the zone that this ioctl originated 541*94bdecd9SRob Gulewich * from. 542*94bdecd9SRob Gulewich */ 543*94bdecd9SRob Gulewich gz_stack = B_FALSE; 544*94bdecd9SRob Gulewich zone = orig_zone; 545*94bdecd9SRob Gulewich } 5467ddc9b1aSDarren Reed 5477ddc9b1aSDarren Reed mutex_enter(&ipf_stack_lock); 5487ddc9b1aSDarren Reed for (ifs = ipf_stacks; ifs != NULL; ifs = ifs->ifs_next) { 549*94bdecd9SRob Gulewich if (ifs->ifs_zone == zone && ifs->ifs_gz_controlled == gz_stack) 5507ddc9b1aSDarren Reed break; 5517ddc9b1aSDarren Reed } 552*94bdecd9SRob Gulewich 553*94bdecd9SRob Gulewich if (ifs != NULL) { 554*94bdecd9SRob Gulewich READ_ENTER(&ifs->ifs_ipf_global); 555*94bdecd9SRob Gulewich } 5567ddc9b1aSDarren Reed mutex_exit(&ipf_stack_lock); 55719397407SSherry Moore return (ifs); 5587ddc9b1aSDarren Reed } 5597ddc9b1aSDarren Reed 560f4b3ec61Sdh155122 static int ipf_detach_check_zone(ipf_stack_t *ifs) 561f4b3ec61Sdh155122 { 562f4b3ec61Sdh155122 /* 563f4b3ec61Sdh155122 * Make sure we're the only one's modifying things. With 564f4b3ec61Sdh155122 * this lock others should just fall out of the loop. 565f4b3ec61Sdh155122 */ 566f4b3ec61Sdh155122 READ_ENTER(&ifs->ifs_ipf_global); 567f4b3ec61Sdh155122 if (ifs->ifs_fr_running == 1) { 568f4b3ec61Sdh155122 RWLOCK_EXIT(&ifs->ifs_ipf_global); 569f4b3ec61Sdh155122 return (-1); 570f4b3ec61Sdh155122 } 571f4b3ec61Sdh155122 572f4b3ec61Sdh155122 /* 573f4b3ec61Sdh155122 * Make sure there is no active filter rule. 574f4b3ec61Sdh155122 */ 575f4b3ec61Sdh155122 if (ifs->ifs_ipfilter[0][ifs->ifs_fr_active] || 576f4b3ec61Sdh155122 ifs->ifs_ipfilter[1][ifs->ifs_fr_active] || 577f4b3ec61Sdh155122 ifs->ifs_ipfilter6[0][ifs->ifs_fr_active] || 578f4b3ec61Sdh155122 ifs->ifs_ipfilter6[1][ifs->ifs_fr_active]) { 579f4b3ec61Sdh155122 RWLOCK_EXIT(&ifs->ifs_ipf_global); 580f4b3ec61Sdh155122 return (-1); 581f4b3ec61Sdh155122 } 582f4b3ec61Sdh155122 583f4b3ec61Sdh155122 RWLOCK_EXIT(&ifs->ifs_ipf_global); 584f4b3ec61Sdh155122 585f4b3ec61Sdh155122 return (0); 586f4b3ec61Sdh155122 } 587f4b3ec61Sdh155122 5887ddc9b1aSDarren Reed 589f4b3ec61Sdh155122 static int ipf_detach_check_all() 590f4b3ec61Sdh155122 { 5917ddc9b1aSDarren Reed ipf_stack_t *ifs; 592f4b3ec61Sdh155122 5937ddc9b1aSDarren Reed mutex_enter(&ipf_stack_lock); 5947ddc9b1aSDarren Reed for (ifs = ipf_stacks; ifs != NULL; ifs = ifs->ifs_next) 5957ddc9b1aSDarren Reed if (ipf_detach_check_zone(ifs) != 0) 5967ddc9b1aSDarren Reed break; 5977ddc9b1aSDarren Reed mutex_exit(&ipf_stack_lock); 5987ddc9b1aSDarren Reed return ((ifs == NULL) ? 0 : -1); 599f4b3ec61Sdh155122 } 600f4b3ec61Sdh155122 601f4b3ec61Sdh155122 602f4b3ec61Sdh155122 /* 603*94bdecd9SRob Gulewich * Remove ipf kstats for both the per-zone ipf stack and the 604*94bdecd9SRob Gulewich * GZ-controlled stack for the same zone, if it exists. 605f4b3ec61Sdh155122 */ 606f4b3ec61Sdh155122 /* ARGSUSED */ 607f4b3ec61Sdh155122 static void 6088ad74188SDarren Reed ipf_stack_shutdown(const netid_t id, void *arg) 6098ad74188SDarren Reed { 6108ad74188SDarren Reed ipf_stack_t *ifs = (ipf_stack_t *)arg; 6118ad74188SDarren Reed 612*94bdecd9SRob Gulewich /* 613*94bdecd9SRob Gulewich * The GZ-controlled stack 614*94bdecd9SRob Gulewich */ 615*94bdecd9SRob Gulewich if (ifs->ifs_gz_cont_ifs != NULL) 616*94bdecd9SRob Gulewich ipf_kstat_fini(ifs->ifs_gz_cont_ifs); 617*94bdecd9SRob Gulewich 618*94bdecd9SRob Gulewich /* 619*94bdecd9SRob Gulewich * The per-zone stack 620*94bdecd9SRob Gulewich */ 6218ad74188SDarren Reed ipf_kstat_fini(ifs); 6228ad74188SDarren Reed } 6238ad74188SDarren Reed 6248ad74188SDarren Reed 6258ad74188SDarren Reed /* 6268ad74188SDarren Reed * Destroy things for ipf for one stack. 6278ad74188SDarren Reed */ 6288ad74188SDarren Reed /* ARGSUSED */ 6298ad74188SDarren Reed static void 630*94bdecd9SRob Gulewich ipf_stack_destroy_one(const netid_t id, ipf_stack_t *ifs) 631f4b3ec61Sdh155122 { 6327ddc9b1aSDarren Reed timeout_id_t tid; 633f4b3ec61Sdh155122 6347ddc9b1aSDarren Reed #ifdef IPFDEBUG 635*94bdecd9SRob Gulewich (void) printf("ipf_stack_destroy_one(%p)\n", (void *)ifs); 636f4b3ec61Sdh155122 #endif 637f4b3ec61Sdh155122 638f4b3ec61Sdh155122 /* 639f4b3ec61Sdh155122 * Make sure we're the only one's modifying things. With 640f4b3ec61Sdh155122 * this lock others should just fall out of the loop. 641f4b3ec61Sdh155122 */ 642f4b3ec61Sdh155122 WRITE_ENTER(&ifs->ifs_ipf_global); 643f4b3ec61Sdh155122 if (ifs->ifs_fr_running == -2) { 644f4b3ec61Sdh155122 RWLOCK_EXIT(&ifs->ifs_ipf_global); 645f4b3ec61Sdh155122 return; 646f4b3ec61Sdh155122 } 647f4b3ec61Sdh155122 ifs->ifs_fr_running = -2; 6487ddc9b1aSDarren Reed tid = ifs->ifs_fr_timer_id; 6497ddc9b1aSDarren Reed ifs->ifs_fr_timer_id = NULL; 650f4b3ec61Sdh155122 RWLOCK_EXIT(&ifs->ifs_ipf_global); 651f4b3ec61Sdh155122 6527ddc9b1aSDarren Reed mutex_enter(&ipf_stack_lock); 6537ddc9b1aSDarren Reed if (ifs->ifs_next != NULL) 6547ddc9b1aSDarren Reed ifs->ifs_next->ifs_pnext = ifs->ifs_pnext; 6557ddc9b1aSDarren Reed *ifs->ifs_pnext = ifs->ifs_next; 6567ddc9b1aSDarren Reed mutex_exit(&ipf_stack_lock); 6577ddc9b1aSDarren Reed 6587ddc9b1aSDarren Reed if (tid != NULL) 6597ddc9b1aSDarren Reed (void) untimeout(tid); 660f4b3ec61Sdh155122 661f4b3ec61Sdh155122 WRITE_ENTER(&ifs->ifs_ipf_global); 662f4b3ec61Sdh155122 if (ipldetach(ifs) != 0) { 663*94bdecd9SRob Gulewich printf("ipf_stack_destroy_one: ipldetach failed\n"); 664f4b3ec61Sdh155122 } 665f4b3ec61Sdh155122 666f4b3ec61Sdh155122 ipftuneable_free(ifs); 667f4b3ec61Sdh155122 668f4b3ec61Sdh155122 RWLOCK_EXIT(&ifs->ifs_ipf_global); 669f4b3ec61Sdh155122 RW_DESTROY(&ifs->ifs_ipf_mutex); 67014d3298eSAlexandr Nedvedicky RW_DESTROY(&ifs->ifs_ipf_frcache); 671f4b3ec61Sdh155122 RW_DESTROY(&ifs->ifs_ipf_global); 672f4b3ec61Sdh155122 673f4b3ec61Sdh155122 KFREE(ifs); 674f4b3ec61Sdh155122 } 675ab25eeb5Syz155240 6767ddc9b1aSDarren Reed 677*94bdecd9SRob Gulewich /* 678*94bdecd9SRob Gulewich * Destroy things for ipf for both the per-zone ipf stack and the 679*94bdecd9SRob Gulewich * GZ-controlled stack for the same zone, if it exists. See the "GZ-controlled 680*94bdecd9SRob Gulewich * and per-zone stacks" comment block in ip_fil_solaris.c for details. 681*94bdecd9SRob Gulewich */ 682*94bdecd9SRob Gulewich /* ARGSUSED */ 683*94bdecd9SRob Gulewich static void 684*94bdecd9SRob Gulewich ipf_stack_destroy(const netid_t id, void *arg) 685*94bdecd9SRob Gulewich { 686*94bdecd9SRob Gulewich ipf_stack_t *ifs = (ipf_stack_t *)arg; 687*94bdecd9SRob Gulewich 688*94bdecd9SRob Gulewich /* 689*94bdecd9SRob Gulewich * The GZ-controlled stack 690*94bdecd9SRob Gulewich */ 691*94bdecd9SRob Gulewich if (ifs->ifs_gz_cont_ifs != NULL) 692*94bdecd9SRob Gulewich ipf_stack_destroy_one(id, ifs->ifs_gz_cont_ifs); 693*94bdecd9SRob Gulewich 694*94bdecd9SRob Gulewich /* 695*94bdecd9SRob Gulewich * The per-zone stack 696*94bdecd9SRob Gulewich */ 697*94bdecd9SRob Gulewich ipf_stack_destroy_one(id, ifs); 698*94bdecd9SRob Gulewich } 699*94bdecd9SRob Gulewich 700*94bdecd9SRob Gulewich 701ab25eeb5Syz155240 static int ipf_attach(dip, cmd) 702ab25eeb5Syz155240 dev_info_t *dip; 703ab25eeb5Syz155240 ddi_attach_cmd_t cmd; 704ab25eeb5Syz155240 { 705ab25eeb5Syz155240 char *s; 706ab25eeb5Syz155240 int i; 707ab25eeb5Syz155240 int instance; 708ab25eeb5Syz155240 709ab25eeb5Syz155240 #ifdef IPFDEBUG 7107ddc9b1aSDarren Reed cmn_err(CE_NOTE, "IP Filter: ipf_attach(%p,%x)", dip, cmd); 711ab25eeb5Syz155240 #endif 712ab25eeb5Syz155240 713ab25eeb5Syz155240 switch (cmd) 714ab25eeb5Syz155240 { 715ab25eeb5Syz155240 case DDI_ATTACH: 716ab25eeb5Syz155240 instance = ddi_get_instance(dip); 717ab25eeb5Syz155240 /* Only one instance of ipf (instance 0) can be attached. */ 718ab25eeb5Syz155240 if (instance > 0) 71919397407SSherry Moore return (DDI_FAILURE); 720ab25eeb5Syz155240 721ab25eeb5Syz155240 #ifdef IPFDEBUG 7227ddc9b1aSDarren Reed cmn_err(CE_CONT, "IP Filter: attach ipf instance %d", instance); 723ab25eeb5Syz155240 #endif 724ab25eeb5Syz155240 725f4b3ec61Sdh155122 (void) ipf_property_g_update(dip); 726ab25eeb5Syz155240 727*94bdecd9SRob Gulewich if (ddi_soft_state_init(&ipf_state, sizeof (ipf_devstate_t), 1) 728*94bdecd9SRob Gulewich != 0) { 729*94bdecd9SRob Gulewich ddi_prop_remove_all(dip); 730*94bdecd9SRob Gulewich return (DDI_FAILURE); 731*94bdecd9SRob Gulewich } 732*94bdecd9SRob Gulewich 733ab25eeb5Syz155240 for (i = 0; ((s = ipf_devfiles[i]) != NULL); i++) { 734ab25eeb5Syz155240 s = strrchr(s, '/'); 735ab25eeb5Syz155240 if (s == NULL) 736ab25eeb5Syz155240 continue; 737ab25eeb5Syz155240 s++; 738ab25eeb5Syz155240 if (ddi_create_minor_node(dip, s, S_IFCHR, i, 739*94bdecd9SRob Gulewich DDI_PSEUDO, 0) == DDI_FAILURE) 740ab25eeb5Syz155240 goto attach_failed; 741ab25eeb5Syz155240 } 742ab25eeb5Syz155240 743ab25eeb5Syz155240 ipf_dev_info = dip; 7447ddc9b1aSDarren Reed 7457ddc9b1aSDarren Reed ipfncb = net_instance_alloc(NETINFO_VERSION); 746*94bdecd9SRob Gulewich if (ipfncb == NULL) 747*94bdecd9SRob Gulewich goto attach_failed; 748*94bdecd9SRob Gulewich 7497ddc9b1aSDarren Reed ipfncb->nin_name = "ipf"; 7507ddc9b1aSDarren Reed ipfncb->nin_create = ipf_stack_create; 7517ddc9b1aSDarren Reed ipfncb->nin_destroy = ipf_stack_destroy; 7528ad74188SDarren Reed ipfncb->nin_shutdown = ipf_stack_shutdown; 753*94bdecd9SRob Gulewich if (net_instance_register(ipfncb) == DDI_FAILURE) { 754*94bdecd9SRob Gulewich net_instance_free(ipfncb); 755*94bdecd9SRob Gulewich goto attach_failed; 756*94bdecd9SRob Gulewich } 757*94bdecd9SRob Gulewich 758*94bdecd9SRob Gulewich ipf_minor = vmem_create("ipf_minor", (void *)1, UINT32_MAX - 1, 759*94bdecd9SRob Gulewich 1, NULL, NULL, NULL, 0, VM_SLEEP | VMC_IDENTIFIER); 7607ddc9b1aSDarren Reed 7617ddc9b1aSDarren Reed #ifdef IPFDEBUG 7627ddc9b1aSDarren Reed cmn_err(CE_CONT, "IP Filter:stack_create callback_reg=%d", i); 7637ddc9b1aSDarren Reed #endif 7647ddc9b1aSDarren Reed 76519397407SSherry Moore return (DDI_SUCCESS); 766ab25eeb5Syz155240 /* NOTREACHED */ 767ab25eeb5Syz155240 default: 768ab25eeb5Syz155240 break; 769ab25eeb5Syz155240 } 770ab25eeb5Syz155240 771ab25eeb5Syz155240 attach_failed: 772*94bdecd9SRob Gulewich ddi_remove_minor_node(dip, NULL); 773f4b3ec61Sdh155122 ddi_prop_remove_all(dip); 774*94bdecd9SRob Gulewich ddi_soft_state_fini(&ipf_state); 77519397407SSherry Moore return (DDI_FAILURE); 776ab25eeb5Syz155240 } 777ab25eeb5Syz155240 778ab25eeb5Syz155240 779ab25eeb5Syz155240 static int ipf_detach(dip, cmd) 780ab25eeb5Syz155240 dev_info_t *dip; 781ab25eeb5Syz155240 ddi_detach_cmd_t cmd; 782ab25eeb5Syz155240 { 783ab25eeb5Syz155240 int i; 784ab25eeb5Syz155240 785ab25eeb5Syz155240 #ifdef IPFDEBUG 7867ddc9b1aSDarren Reed cmn_err(CE_NOTE, "IP Filter: ipf_detach(%p,%x)", dip, cmd); 787ab25eeb5Syz155240 #endif 788ab25eeb5Syz155240 switch (cmd) { 789ab25eeb5Syz155240 case DDI_DETACH: 790f4b3ec61Sdh155122 if (ipf_detach_check_all() != 0) 79119397407SSherry Moore return (DDI_FAILURE); 792ab25eeb5Syz155240 79319397407SSherry Moore /* 79419397407SSherry Moore * Undo what we did in ipf_attach, freeing resources 795ab25eeb5Syz155240 * and removing things we installed. The system 796ab25eeb5Syz155240 * framework guarantees we are not active with this devinfo 797ab25eeb5Syz155240 * node in any other entry points at this time. 798ab25eeb5Syz155240 */ 799ab25eeb5Syz155240 ddi_prop_remove_all(dip); 800ab25eeb5Syz155240 i = ddi_get_instance(dip); 801ab25eeb5Syz155240 ddi_remove_minor_node(dip, NULL); 802ab25eeb5Syz155240 if (i > 0) { 803ab25eeb5Syz155240 cmn_err(CE_CONT, "IP Filter: still attached (%d)\n", i); 80419397407SSherry Moore return (DDI_FAILURE); 805ab25eeb5Syz155240 } 806ab25eeb5Syz155240 807*94bdecd9SRob Gulewich vmem_destroy(ipf_minor); 808*94bdecd9SRob Gulewich ddi_soft_state_fini(&ipf_state); 809*94bdecd9SRob Gulewich 8107ddc9b1aSDarren Reed (void) net_instance_unregister(ipfncb); 8117ddc9b1aSDarren Reed net_instance_free(ipfncb); 8127ddc9b1aSDarren Reed 81319397407SSherry Moore return (DDI_SUCCESS); 814f4b3ec61Sdh155122 /* NOTREACHED */ 815ab25eeb5Syz155240 default: 816ab25eeb5Syz155240 break; 817ab25eeb5Syz155240 } 818ab25eeb5Syz155240 cmn_err(CE_NOTE, "IP Filter: failed to detach\n"); 81919397407SSherry Moore return (DDI_FAILURE); 820ab25eeb5Syz155240 } 821ab25eeb5Syz155240 822ab25eeb5Syz155240 823ab25eeb5Syz155240 /*ARGSUSED*/ 824ab25eeb5Syz155240 static int ipf_getinfo(dip, infocmd, arg, result) 825ab25eeb5Syz155240 dev_info_t *dip; 826ab25eeb5Syz155240 ddi_info_cmd_t infocmd; 827ab25eeb5Syz155240 void *arg, **result; 828ab25eeb5Syz155240 { 829ab25eeb5Syz155240 int error; 830ab25eeb5Syz155240 831ab25eeb5Syz155240 error = DDI_FAILURE; 832ab25eeb5Syz155240 #ifdef IPFDEBUG 8337ddc9b1aSDarren Reed cmn_err(CE_NOTE, "IP Filter: ipf_getinfo(%p,%x,%p)", dip, infocmd, arg); 834ab25eeb5Syz155240 #endif 835ab25eeb5Syz155240 switch (infocmd) { 836ab25eeb5Syz155240 case DDI_INFO_DEVT2DEVINFO: 837ab25eeb5Syz155240 *result = ipf_dev_info; 838ab25eeb5Syz155240 error = DDI_SUCCESS; 839ab25eeb5Syz155240 break; 840ab25eeb5Syz155240 case DDI_INFO_DEVT2INSTANCE: 841ab25eeb5Syz155240 *result = (void *)0; 842ab25eeb5Syz155240 error = DDI_SUCCESS; 843ab25eeb5Syz155240 break; 844ab25eeb5Syz155240 default: 845ab25eeb5Syz155240 break; 846ab25eeb5Syz155240 } 847ab25eeb5Syz155240 return (error); 848ab25eeb5Syz155240 } 849ab25eeb5Syz155240 850ab25eeb5Syz155240 851ab25eeb5Syz155240 /* 852ab25eeb5Syz155240 * Fetch configuration file values that have been entered into the ipf.conf 853ab25eeb5Syz155240 * driver file. 854ab25eeb5Syz155240 */ 855f4b3ec61Sdh155122 static int ipf_property_g_update(dip) 856ab25eeb5Syz155240 dev_info_t *dip; 857ab25eeb5Syz155240 { 858ab25eeb5Syz155240 #ifdef DDI_NO_AUTODETACH 859ab25eeb5Syz155240 if (ddi_prop_update_int(DDI_DEV_T_NONE, dip, 860ab25eeb5Syz155240 DDI_NO_AUTODETACH, 1) != DDI_PROP_SUCCESS) { 861ab25eeb5Syz155240 cmn_err(CE_WARN, "!updating DDI_NO_AUTODETACH failed"); 86219397407SSherry Moore return (DDI_FAILURE); 863ab25eeb5Syz155240 } 864ab25eeb5Syz155240 #else 865ab25eeb5Syz155240 if (ddi_prop_update_int(DDI_DEV_T_NONE, dip, 866ab25eeb5Syz155240 "ddi-no-autodetach", 1) != DDI_PROP_SUCCESS) { 867ab25eeb5Syz155240 cmn_err(CE_WARN, "!updating ddi-no-autodetach failed"); 86819397407SSherry Moore return (DDI_FAILURE); 869ab25eeb5Syz155240 } 870ab25eeb5Syz155240 #endif 871ab25eeb5Syz155240 87219397407SSherry Moore return (DDI_SUCCESS); 873f4b3ec61Sdh155122 } 874f4b3ec61Sdh155122 87519397407SSherry Moore int 87619397407SSherry Moore ipf_property_update(dip, ifs) 877f4b3ec61Sdh155122 dev_info_t *dip; 878f4b3ec61Sdh155122 ipf_stack_t *ifs; 879f4b3ec61Sdh155122 { 880f4b3ec61Sdh155122 ipftuneable_t *ipft; 881f4b3ec61Sdh155122 char *name; 88219397407SSherry Moore uint_t one; 883f4b3ec61Sdh155122 int *i32p; 88440cdc2e8SAlexandr Nedvedicky int err, rv = 0; 885f4b3ec61Sdh155122 88640cdc2e8SAlexandr Nedvedicky for (ipft = ifs->ifs_ipf_tuneables; 88740cdc2e8SAlexandr Nedvedicky (name = ipft->ipft_name) != NULL; ipft++) { 888ab25eeb5Syz155240 one = 1; 889ab25eeb5Syz155240 i32p = NULL; 890ab25eeb5Syz155240 err = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 891ab25eeb5Syz155240 0, name, &i32p, &one); 892ab25eeb5Syz155240 if (err == DDI_PROP_NOT_FOUND) 893ab25eeb5Syz155240 continue; 894ab25eeb5Syz155240 #ifdef IPFDEBUG 895ab25eeb5Syz155240 cmn_err(CE_CONT, "IP Filter: lookup_int(%s) = %d\n", 896ab25eeb5Syz155240 name, err); 897ab25eeb5Syz155240 #endif 89840cdc2e8SAlexandr Nedvedicky if (err != DDI_PROP_SUCCESS) { 89940cdc2e8SAlexandr Nedvedicky rv = err; 900ab25eeb5Syz155240 continue; 901ab25eeb5Syz155240 } 90240cdc2e8SAlexandr Nedvedicky 90340cdc2e8SAlexandr Nedvedicky if (*i32p >= ipft->ipft_min && 90440cdc2e8SAlexandr Nedvedicky *i32p <= ipft->ipft_max) { 90540cdc2e8SAlexandr Nedvedicky if (ipft->ipft_sz == sizeof (uint32_t)) { 90640cdc2e8SAlexandr Nedvedicky *ipft->ipft_pint = *i32p; 90740cdc2e8SAlexandr Nedvedicky } else if (ipft->ipft_sz == sizeof (uint64_t)) { 90840cdc2e8SAlexandr Nedvedicky *ipft->ipft_plong = *i32p; 909ab25eeb5Syz155240 } 91040cdc2e8SAlexandr Nedvedicky } 91140cdc2e8SAlexandr Nedvedicky 91240cdc2e8SAlexandr Nedvedicky ddi_prop_free(i32p); 91340cdc2e8SAlexandr Nedvedicky } 91440cdc2e8SAlexandr Nedvedicky 91540cdc2e8SAlexandr Nedvedicky return (rv); 916ab25eeb5Syz155240 } 917