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