diff options
| author | yz155240 <none@none> | 2006-07-19 01:15:53 -0700 |
|---|---|---|
| committer | yz155240 <none@none> | 2006-07-19 01:15:53 -0700 |
| commit | ab25eeb551a4be927a4b6ae2cf8aff7ed17decb4 (patch) | |
| tree | 8f3a55a94fbaf0fdcbf3d0270606e4528a9dbb37 /usr/src/uts/common/inet/ipf/solaris.c | |
| parent | e32cd585e45b9f19db8e971dfa93046993fced0f (diff) | |
| download | illumos-joyent-ab25eeb551a4be927a4b6ae2cf8aff7ed17decb4.tar.gz | |
PSARC 2006/082 IP Filter Code Merge on ip_fil4.1.9
4912568 ipftest ipf ipfstat ipnat ippool need a non-name resolution flag
5040248 ipfs -W fails to save kernel state tables
5081834 syntax parser reports wrong error position and line number
5094575 keyword "netmask" is un-supported in ipnat.conf (4)
6181751 ipf parser fails on wrong subnet notations
6181773 ipf parser fails on wrong port ranges
6248745 ipnat drops packets if the IP header is not 32 bit aligned
6340621 RFE: IP Filter code merge on ip_fil4.1.9
6359805 ipf command incorrectly check options in rules and core dumps
6395837 ipnat tcpudp parsing is incomplete
6426469 IPFilter rejects IPv6 neighbour discovery packets
6447872 usr/src/common/ipf/ip_compat.h should not be CDDL
--HG--
rename : usr/src/common/ipf/bpf-ipf.h => usr/src/uts/common/inet/ipf/bpf-ipf.h
rename : usr/src/common/ipf/fil.c => usr/src/uts/common/inet/ipf/fil.c
rename : usr/src/common/ipf/ip_auth.c => usr/src/uts/common/inet/ipf/ip_auth.c
rename : usr/src/common/ipf/ip_fil_solaris.c => usr/src/uts/common/inet/ipf/ip_fil_solaris.c
rename : usr/src/common/ipf/ip_frag.c => usr/src/uts/common/inet/ipf/ip_frag.c
rename : usr/src/common/ipf/ip_htable.c => usr/src/uts/common/inet/ipf/ip_htable.c
rename : usr/src/common/ipf/ip_log.c => usr/src/uts/common/inet/ipf/ip_log.c
rename : usr/src/common/ipf/ip_lookup.c => usr/src/uts/common/inet/ipf/ip_lookup.c
rename : usr/src/common/ipf/ip_nat.c => usr/src/uts/common/inet/ipf/ip_nat.c
rename : usr/src/common/ipf/ip_pool.c => usr/src/uts/common/inet/ipf/ip_pool.c
rename : usr/src/common/ipf/ip_proxy.c => usr/src/uts/common/inet/ipf/ip_proxy.c
rename : usr/src/common/ipf/ip_state.c => usr/src/uts/common/inet/ipf/ip_state.c
rename : usr/src/common/ipf/ipf.h => usr/src/uts/common/inet/ipf/ipf.h
rename : usr/src/common/ipf/ipmon.h => usr/src/uts/common/inet/ipf/ipmon.h
rename : usr/src/common/ipf/ipt.h => usr/src/uts/common/inet/ipf/ipt.h
rename : usr/src/common/ipf/Makefile => usr/src/uts/common/inet/ipf/netinet/Makefile
rename : usr/src/common/ipf/ip_auth.h => usr/src/uts/common/inet/ipf/netinet/ip_auth.h
rename : usr/src/common/ipf/ip_compat.h => usr/src/uts/common/inet/ipf/netinet/ip_compat.h
rename : usr/src/common/ipf/ip_fil.h => usr/src/uts/common/inet/ipf/netinet/ip_fil.h
rename : usr/src/common/ipf/ip_frag.h => usr/src/uts/common/inet/ipf/netinet/ip_frag.h
rename : usr/src/common/ipf/ip_ftp_pxy.c => usr/src/uts/common/inet/ipf/netinet/ip_ftp_pxy.c
rename : usr/src/common/ipf/ip_h323_pxy.c => usr/src/uts/common/inet/ipf/netinet/ip_h323_pxy.c
rename : usr/src/common/ipf/ip_htable.h => usr/src/uts/common/inet/ipf/netinet/ip_htable.h
rename : usr/src/common/ipf/ip_ipsec_pxy.c => usr/src/uts/common/inet/ipf/netinet/ip_ipsec_pxy.c
rename : usr/src/common/ipf/ip_irc_pxy.c => usr/src/uts/common/inet/ipf/netinet/ip_irc_pxy.c
rename : usr/src/common/ipf/ip_lookup.h => usr/src/uts/common/inet/ipf/netinet/ip_lookup.h
rename : usr/src/common/ipf/ip_nat.h => usr/src/uts/common/inet/ipf/netinet/ip_nat.h
rename : usr/src/common/ipf/ip_netbios_pxy.c => usr/src/uts/common/inet/ipf/netinet/ip_netbios_pxy.c
rename : usr/src/common/ipf/ip_pool.h => usr/src/uts/common/inet/ipf/netinet/ip_pool.h
rename : usr/src/common/ipf/ip_proxy.h => usr/src/uts/common/inet/ipf/netinet/ip_proxy.h
rename : usr/src/common/ipf/ip_raudio_pxy.c => usr/src/uts/common/inet/ipf/netinet/ip_raudio_pxy.c
rename : usr/src/common/ipf/ip_rcmd_pxy.c => usr/src/uts/common/inet/ipf/netinet/ip_rcmd_pxy.c
rename : usr/src/common/ipf/ip_rpcb_pxy.c => usr/src/uts/common/inet/ipf/netinet/ip_rpcb_pxy.c
rename : usr/src/common/ipf/ip_state.h => usr/src/uts/common/inet/ipf/netinet/ip_state.h
rename : usr/src/common/ipf/ipl.h => usr/src/uts/common/inet/ipf/netinet/ipl.h
rename : usr/src/common/ipf/opts.h => usr/src/uts/common/inet/ipf/opts.h
rename : usr/src/common/ipf/radix.c => usr/src/uts/common/inet/ipf/radix.c
rename : usr/src/common/ipf/radix.h => usr/src/uts/common/inet/ipf/radix.h
rename : usr/src/common/ipf/solaris.c => usr/src/uts/common/inet/ipf/solaris.c
rename : usr/src/uts/common/inet/ipf/compat.h => usr/src/uts/common/inet/pfil/compat.h
rename : usr/src/uts/common/inet/ipf/misc.c => usr/src/uts/common/inet/pfil/misc.c
rename : usr/src/uts/common/inet/ipf/ndd.c => usr/src/uts/common/inet/pfil/ndd.c
rename : usr/src/uts/common/inet/ipf/os.h => usr/src/uts/common/inet/pfil/os.h
rename : usr/src/uts/common/inet/ipf/pfil.c => usr/src/uts/common/inet/pfil/pfil.c
rename : usr/src/uts/common/inet/ipf/pfil.conf => usr/src/uts/common/inet/pfil/pfil.conf
rename : usr/src/uts/common/inet/ipf/pfil.h => usr/src/uts/common/inet/pfil/pfil.h
rename : usr/src/common/ipf/pfild.h => usr/src/uts/common/inet/pfil/pfild.h
rename : usr/src/uts/common/inet/ipf/pfildrv.c => usr/src/uts/common/inet/pfil/pfildrv.c
rename : usr/src/uts/common/inet/ipf/pfilstream.c => usr/src/uts/common/inet/pfil/pfilstream.c
rename : usr/src/uts/common/inet/ipf/pkt.c => usr/src/uts/common/inet/pfil/pkt.c
rename : usr/src/uts/common/inet/ipf/qif.c => usr/src/uts/common/inet/pfil/qif.c
rename : usr/src/uts/common/inet/ipf/qif.h => usr/src/uts/common/inet/pfil/qif.h
Diffstat (limited to 'usr/src/uts/common/inet/ipf/solaris.c')
| -rw-r--r-- | usr/src/uts/common/inet/ipf/solaris.c | 696 |
1 files changed, 696 insertions, 0 deletions
diff --git a/usr/src/uts/common/inet/ipf/solaris.c b/usr/src/uts/common/inet/ipf/solaris.c new file mode 100644 index 0000000000..0c21d1f15f --- /dev/null +++ b/usr/src/uts/common/inet/ipf/solaris.c @@ -0,0 +1,696 @@ +/* + * Copyright (C) 1993-2001, 2003 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* #pragma ident "@(#)solaris.c 1.12 6/5/96 (C) 1995 Darren Reed"*/ +#pragma ident "@(#)$Id: solaris.c,v 2.73.2.6 2005/07/13 21:40:47 darrenr Exp $" + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <sys/systm.h> +#include <sys/types.h> +#include <sys/param.h> +#include <sys/errno.h> +#include <sys/uio.h> +#include <sys/buf.h> +#include <sys/modctl.h> +#include <sys/open.h> +#include <sys/kmem.h> +#include <sys/conf.h> +#include <sys/cmn_err.h> +#include <sys/stat.h> +#include <sys/cred.h> +#include <sys/dditypes.h> +#include <sys/stream.h> +#include <sys/poll.h> +#include <sys/autoconf.h> +#include <sys/byteorder.h> +#include <sys/socket.h> +#include <sys/dlpi.h> +#include <sys/stropts.h> +#include <sys/kstat.h> +#include <sys/sockio.h> +#include <net/if.h> +#if SOLARIS2 >= 6 +# include <net/if_types.h> +#endif +#include <net/af.h> +#include <net/route.h> +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/if_ether.h> +#include <netinet/ip.h> +#include <netinet/ip_var.h> +#include <netinet/tcp.h> +#include <netinet/udp.h> +#include <netinet/tcpip.h> +#include <netinet/ip_icmp.h> +#include <sys/ddi.h> +#include <sys/sunddi.h> +#include "netinet/ip_compat.h" +#include "netinet/ipl.h" +#include "netinet/ip_fil.h" +#include "netinet/ip_nat.h" +#include "netinet/ip_frag.h" +#include "netinet/ip_auth.h" +#include "netinet/ip_state.h" + + +extern struct filterstats frstats[]; +extern int fr_running; +extern int fr_flags; +extern int iplwrite __P((dev_t, struct uio *, cred_t *)); + +extern ipnat_t *nat_list; + +static int ipf_getinfo __P((dev_info_t *, ddi_info_cmd_t, + void *, void **)); +#if SOLARIS2 < 10 +static int ipf_identify __P((dev_info_t *)); +#endif +static int ipf_attach __P((dev_info_t *, ddi_attach_cmd_t)); +static int ipf_detach __P((dev_info_t *, ddi_detach_cmd_t)); +static int fr_qifsync __P((ip_t *, int, void *, int, void *, mblk_t **)); +static int ipf_property_update __P((dev_info_t *)); +static char *ipf_devfiles[] = { IPL_NAME, IPNAT_NAME, IPSTATE_NAME, + IPAUTH_NAME, IPSYNC_NAME, IPSCAN_NAME, + IPLOOKUP_NAME, NULL }; + + +#if SOLARIS2 >= 7 +extern timeout_id_t fr_timer_id; +#else +extern int fr_timer_id; +#endif + +static struct cb_ops ipf_cb_ops = { + iplopen, + iplclose, + nodev, /* strategy */ + nodev, /* print */ + nodev, /* dump */ + iplread, + iplwrite, /* write */ + iplioctl, /* ioctl */ + nodev, /* devmap */ + nodev, /* mmap */ + nodev, /* segmap */ + nochpoll, /* poll */ + ddi_prop_op, + NULL, + D_MTSAFE, +#if SOLARIS2 > 4 + CB_REV, + nodev, /* aread */ + nodev, /* awrite */ +#endif +}; + +static struct dev_ops ipf_ops = { + DEVO_REV, + 0, + ipf_getinfo, +#if SOLARIS2 >= 10 + nulldev, +#else + ipf_identify, +#endif + nulldev, + ipf_attach, + ipf_detach, + nodev, /* reset */ + &ipf_cb_ops, + (struct bus_ops *)0 +}; + +extern struct mod_ops mod_driverops; +static struct modldrv iplmod = { + &mod_driverops, IPL_VERSION, &ipf_ops }; +static struct modlinkage modlink1 = { MODREV_1, &iplmod, NULL }; + +#if SOLARIS2 >= 6 +static size_t hdrsizes[57][2] = { + { 0, 0 }, + { IFT_OTHER, 0 }, + { IFT_1822, 0 }, + { IFT_HDH1822, 0 }, + { IFT_X25DDN, 0 }, + { IFT_X25, 0 }, + { IFT_ETHER, 14 }, + { IFT_ISO88023, 0 }, + { IFT_ISO88024, 0 }, + { IFT_ISO88025, 0 }, + { IFT_ISO88026, 0 }, + { IFT_STARLAN, 0 }, + { IFT_P10, 0 }, + { IFT_P80, 0 }, + { IFT_HY, 0 }, + { IFT_FDDI, 24 }, + { IFT_LAPB, 0 }, + { IFT_SDLC, 0 }, + { IFT_T1, 0 }, + { IFT_CEPT, 0 }, + { IFT_ISDNBASIC, 0 }, + { IFT_ISDNPRIMARY, 0 }, + { IFT_PTPSERIAL, 0 }, + { IFT_PPP, 0 }, + { IFT_LOOP, 0 }, + { IFT_EON, 0 }, + { IFT_XETHER, 0 }, + { IFT_NSIP, 0 }, + { IFT_SLIP, 0 }, + { IFT_ULTRA, 0 }, + { IFT_DS3, 0 }, + { IFT_SIP, 0 }, + { IFT_FRELAY, 0 }, + { IFT_RS232, 0 }, + { IFT_PARA, 0 }, + { IFT_ARCNET, 0 }, + { IFT_ARCNETPLUS, 0 }, + { IFT_ATM, 0 }, + { IFT_MIOX25, 0 }, + { IFT_SONET, 0 }, + { IFT_X25PLE, 0 }, + { IFT_ISO88022LLC, 0 }, + { IFT_LOCALTALK, 0 }, + { IFT_SMDSDXI, 0 }, + { IFT_FRELAYDCE, 0 }, + { IFT_V35, 0 }, + { IFT_HSSI, 0 }, + { IFT_HIPPI, 0 }, + { IFT_MODEM, 0 }, + { IFT_AAL5, 0 }, + { IFT_SONETPATH, 0 }, + { IFT_SONETVT, 0 }, + { IFT_SMDSICIP, 0 }, + { IFT_PROPVIRTUAL, 0 }, + { IFT_PROPMUX, 0 }, +}; +#endif /* SOLARIS2 >= 6 */ + +static dev_info_t *ipf_dev_info = NULL; + +static const filter_kstats_t ipf_kstat_tmp = { + { "pass", KSTAT_DATA_ULONG }, + { "block", KSTAT_DATA_ULONG }, + { "nomatch", KSTAT_DATA_ULONG }, + { "short", KSTAT_DATA_ULONG }, + { "pass, logged", KSTAT_DATA_ULONG }, + { "block, logged", KSTAT_DATA_ULONG }, + { "nomatch, logged", KSTAT_DATA_ULONG }, + { "logged", KSTAT_DATA_ULONG }, + { "skip", KSTAT_DATA_ULONG }, + { "return sent", KSTAT_DATA_ULONG }, + { "acct", KSTAT_DATA_ULONG }, + { "bad frag state alloc", KSTAT_DATA_ULONG }, + { "new frag state kept", KSTAT_DATA_ULONG }, + { "new frag state compl. pkt", KSTAT_DATA_ULONG }, + { "bad pkt state alloc", KSTAT_DATA_ULONG }, + { "new pkt kept state", KSTAT_DATA_ULONG }, + { "cachehit", KSTAT_DATA_ULONG }, + { "tcp cksum bad", KSTAT_DATA_ULONG }, + {{ "pullup ok", KSTAT_DATA_ULONG }, + { "pullup nok", KSTAT_DATA_ULONG }}, + { "src != route", KSTAT_DATA_ULONG }, + { "ttl invalid", KSTAT_DATA_ULONG }, + { "bad ip pkt", KSTAT_DATA_ULONG }, + { "ipv6 pkt", KSTAT_DATA_ULONG }, + { "dropped:pps ceiling", KSTAT_DATA_ULONG }, + { "ip upd. fail", KSTAT_DATA_ULONG } +}; + +kstat_t *ipf_kstatp[2] = {NULL, NULL}; +static int ipf_kstat_update(kstat_t *ksp, int rwflag); + +static void +ipf_kstat_init(void) +{ + int i; + + for (i = 0; i < 2; i++) { + ipf_kstatp[i] = kstat_create("ipf", 0, + (i==0)?"inbound":"outbound", + "net", + KSTAT_TYPE_NAMED, + sizeof (filter_kstats_t) / sizeof (kstat_named_t), + 0); + if (ipf_kstatp[i] != NULL) { + bcopy(&ipf_kstat_tmp, ipf_kstatp[i]->ks_data, + sizeof (filter_kstats_t)); + ipf_kstatp[i]->ks_update = ipf_kstat_update; + ipf_kstatp[i]->ks_private = &frstats[i]; + kstat_install(ipf_kstatp[i]); + } + } + +#ifdef IPFDEBUG + cmn_err(CE_NOTE, "IP Filter: ipf_kstat_init() installed 0x%x, 0x%x", + ipf_kstatp[0], ipf_kstatp[1]); +#endif +} + +static void +ipf_kstat_fini(void) +{ + int i; + for (i = 0; i < 2; i++) { + if (ipf_kstatp[i] != NULL) { + kstat_delete(ipf_kstatp[i]); + ipf_kstatp[i] = NULL; + } + } +} + +static int +ipf_kstat_update(kstat_t *ksp, int rwflag) +{ + filter_kstats_t *fkp; + filterstats_t *fsp; + + if (rwflag == KSTAT_WRITE) + return (EACCES); + + fkp = ksp->ks_data; + fsp = ksp->ks_private; + + fkp->fks_pass.value.ul = fsp->fr_pass; + fkp->fks_block.value.ul = fsp->fr_block; + fkp->fks_nom.value.ul = fsp->fr_nom; + fkp->fks_short.value.ul = fsp->fr_short; + fkp->fks_ppkl.value.ul = fsp->fr_ppkl; + fkp->fks_bpkl.value.ul = fsp->fr_bpkl; + fkp->fks_npkl.value.ul = fsp->fr_npkl; + fkp->fks_pkl.value.ul = fsp->fr_pkl; + fkp->fks_skip.value.ul = fsp->fr_skip; + fkp->fks_ret.value.ul = fsp->fr_ret; + fkp->fks_acct.value.ul = fsp->fr_acct; + fkp->fks_bnfr.value.ul = fsp->fr_bnfr; + fkp->fks_nfr.value.ul = fsp->fr_nfr; + fkp->fks_cfr.value.ul = fsp->fr_cfr; + fkp->fks_bads.value.ul = fsp->fr_bads; + fkp->fks_ads.value.ul = fsp->fr_ads; + fkp->fks_chit.value.ul = fsp->fr_chit; + fkp->fks_tcpbad.value.ul = fsp->fr_tcpbad; + fkp->fks_pull[0].value.ul = fsp->fr_pull[0]; + fkp->fks_pull[1].value.ul = fsp->fr_pull[1]; + fkp->fks_badsrc.value.ul = fsp->fr_badsrc; + fkp->fks_badttl.value.ul = fsp->fr_badttl; + fkp->fks_bad.value.ul = fsp->fr_bad; + fkp->fks_ipv6.value.ul = fsp->fr_ipv6; + fkp->fks_ppshit.value.ul = fsp->fr_ppshit; + fkp->fks_ipud.value.ul = fsp->fr_ipud; + + return (0); +} + +int _init() +{ + int ipfinst; + + ipf_kstat_init(); + ipfinst = mod_install(&modlink1); + if (ipfinst != 0) + ipf_kstat_fini(); +#ifdef IPFDEBUG + cmn_err(CE_NOTE, "IP Filter: _init() = %d", ipfinst); +#endif + return ipfinst; +} + + +int _fini(void) +{ + int ipfinst; + + ipfinst = mod_remove(&modlink1); +#ifdef IPFDEBUG + cmn_err(CE_NOTE, "IP Filter: _fini() = %d", ipfinst); +#endif + if (ipfinst == 0) + ipf_kstat_fini(); + return ipfinst; +} + + +int _info(modinfop) +struct modinfo *modinfop; +{ + int ipfinst; + + ipfinst = mod_info(&modlink1, modinfop); +#ifdef IPFDEBUG + cmn_err(CE_NOTE, "IP Filter: _info(%x) = %x", modinfop, ipfinst); +#endif + return ipfinst; +} + + +#if SOLARIS2 < 10 +static int ipf_identify(dip) +dev_info_t *dip; +{ +# ifdef IPFDEBUG + cmn_err(CE_NOTE, "IP Filter: ipf_identify(%x)", dip); +# endif + if (strcmp(ddi_get_name(dip), "ipf") == 0) + return (DDI_IDENTIFIED); + return (DDI_NOT_IDENTIFIED); +} +#endif + + +static int ipf_attach(dip, cmd) +dev_info_t *dip; +ddi_attach_cmd_t cmd; +{ + char *s; + int i; + int instance; + +#ifdef IPFDEBUG + cmn_err(CE_NOTE, "IP Filter: ipf_attach(%x,%x)", dip, cmd); +#endif + + if ((pfilinterface != PFIL_INTERFACE) || (PFIL_INTERFACE < 2000000)) { + cmn_err(CE_NOTE, "pfilinterface(%d) != %d\n", pfilinterface, + PFIL_INTERFACE); + return EINVAL; + } + + switch (cmd) + { + case DDI_ATTACH: + instance = ddi_get_instance(dip); + /* Only one instance of ipf (instance 0) can be attached. */ + if (instance > 0) + return DDI_FAILURE; + if (fr_running != 0) + return DDI_FAILURE; + +#ifdef IPFDEBUG + cmn_err(CE_NOTE, "IP Filter: attach ipf instance %d", instance); +#endif + + (void) ipf_property_update(dip); + + for (i = 0; ((s = ipf_devfiles[i]) != NULL); i++) { + s = strrchr(s, '/'); + if (s == NULL) + continue; + s++; + if (ddi_create_minor_node(dip, s, S_IFCHR, i, + DDI_PSEUDO, 0) == + DDI_FAILURE) { + ddi_remove_minor_node(dip, NULL); + goto attach_failed; + } + } + + ipf_dev_info = dip; + /* + * Initialize mutex's + */ + RWLOCK_INIT(&ipf_global, "ipf filter load/unload mutex"); + RWLOCK_INIT(&ipf_mutex, "ipf filter rwlock"); + RWLOCK_INIT(&ipf_frcache, "ipf cache rwlock"); + + /* + * Lock people out while we set things up. + */ + WRITE_ENTER(&ipf_global); + if ((fr_running != 0) || (iplattach() == -1)) { + RWLOCK_EXIT(&ipf_global); + goto attach_failed; + } + + if (pfil_add_hook(fr_check, PFIL_IN|PFIL_OUT, &pfh_inet4)) + cmn_err(CE_WARN, "IP Filter: %s(pfh_inet4) failed", + "pfil_add_hook"); +#ifdef USE_INET6 + if (pfil_add_hook(fr_check, PFIL_IN|PFIL_OUT, &pfh_inet6)) + cmn_err(CE_WARN, "IP Filter: %s(pfh_inet6) failed", + "pfil_add_hook"); +#endif + if (pfil_add_hook(fr_qifsync, PFIL_IN|PFIL_OUT, &pfh_sync)) + cmn_err(CE_WARN, "IP Filter: %s(pfh_sync) failed", + "pfil_add_hook"); + + fr_timer_id = timeout(fr_slowtimer, NULL, + drv_usectohz(500000)); + + fr_running = 1; + + RWLOCK_EXIT(&ipf_global); + + cmn_err(CE_CONT, "!%s, running.\n", ipfilter_version); + + return DDI_SUCCESS; + /* NOTREACHED */ + default: + break; + } + +attach_failed: +#ifdef IPFDEBUG + cmn_err(CE_NOTE, "IP Filter: failed to attach\n"); +#endif + /* + * Use our own detach routine to toss + * away any stuff we allocated above. + */ + (void) ipf_detach(dip, DDI_DETACH); + return DDI_FAILURE; +} + + +static int ipf_detach(dip, cmd) +dev_info_t *dip; +ddi_detach_cmd_t cmd; +{ + int i; + +#ifdef IPFDEBUG + cmn_err(CE_NOTE, "IP Filter: ipf_detach(%x,%x)", dip, cmd); +#endif + switch (cmd) { + case DDI_DETACH: + if (fr_refcnt != 0) + return DDI_FAILURE; + + if (fr_running == -2 || fr_running == 0) + break; + /* + * Make sure we're the only one's modifying things. With + * this lock others should just fall out of the loop. + */ + WRITE_ENTER(&ipf_global); + if (fr_running <= 0) { + RWLOCK_EXIT(&ipf_global); + return DDI_FAILURE; + } + fr_running = -2; + + if (pfil_remove_hook(fr_check, PFIL_IN|PFIL_OUT, &pfh_inet4)) + cmn_err(CE_WARN, "IP Filter: %s(pfh_inet4) failed", + "pfil_remove_hook"); +#ifdef USE_INET6 + if (pfil_remove_hook(fr_check, PFIL_IN|PFIL_OUT, &pfh_inet6)) + cmn_err(CE_WARN, "IP Filter: %s(pfh_inet6) failed", + "pfil_add_hook"); +#endif + if (pfil_remove_hook(fr_qifsync, PFIL_IN|PFIL_OUT, &pfh_sync)) + cmn_err(CE_WARN, "IP Filter: %s(pfh_sync) failed", + "pfil_remove_hook"); + + RWLOCK_EXIT(&ipf_global); + + if (fr_timer_id != 0) { + (void) untimeout(fr_timer_id); + fr_timer_id = 0; + } + + /* + * Undo what we did in ipf_attach, freeing resources + * and removing things we installed. The system + * framework guarantees we are not active with this devinfo + * node in any other entry points at this time. + */ + ddi_prop_remove_all(dip); + i = ddi_get_instance(dip); + ddi_remove_minor_node(dip, NULL); + if (i > 0) { + cmn_err(CE_CONT, "IP Filter: still attached (%d)\n", i); + return DDI_FAILURE; + } + + WRITE_ENTER(&ipf_global); + if (!ipldetach()) { + RWLOCK_EXIT(&ipf_global); + RW_DESTROY(&ipf_mutex); + RW_DESTROY(&ipf_frcache); + RW_DESTROY(&ipf_global); + cmn_err(CE_CONT, "!%s detached.\n", ipfilter_version); + return (DDI_SUCCESS); + } + RWLOCK_EXIT(&ipf_global); + break; + default: + break; + } + cmn_err(CE_NOTE, "IP Filter: failed to detach\n"); + return DDI_FAILURE; +} + + +/*ARGSUSED*/ +static int ipf_getinfo(dip, infocmd, arg, result) +dev_info_t *dip; +ddi_info_cmd_t infocmd; +void *arg, **result; +{ + int error; + + if (fr_running <= 0) + return DDI_FAILURE; + error = DDI_FAILURE; +#ifdef IPFDEBUG + cmn_err(CE_NOTE, "IP Filter: ipf_getinfo(%x,%x,%x)", dip, infocmd, arg); +#endif + switch (infocmd) { + case DDI_INFO_DEVT2DEVINFO: + *result = ipf_dev_info; + error = DDI_SUCCESS; + break; + case DDI_INFO_DEVT2INSTANCE: + *result = (void *)0; + error = DDI_SUCCESS; + break; + default: + break; + } + return (error); +} + + +/* + * look for bad consistancies between the list of interfaces the filter knows + * about and those which are currently configured. + */ +/*ARGSUSED*/ +static int fr_qifsync(ip, hlen, il, out, qif, mp) +ip_t *ip; +int hlen; +void *il; +int out; +void *qif; +mblk_t **mp; +{ + + frsync(qif); + /* + * Resync. any NAT `connections' using this interface and its IP #. + */ + fr_natsync(qif); + fr_statesync(qif); + return 0; +} + + +/* + * look for bad consistancies between the list of interfaces the filter knows + * about and those which are currently configured. + */ +int ipfsync() +{ + frsync(NULL); + return 0; +} + + +/* + * Fetch configuration file values that have been entered into the ipf.conf + * driver file. + */ +static int ipf_property_update(dip) +dev_info_t *dip; +{ + ipftuneable_t *ipft; + int64_t *i64p; + char *name; + u_int one; + int *i32p; + int err; + +#ifdef DDI_NO_AUTODETACH + if (ddi_prop_update_int(DDI_DEV_T_NONE, dip, + DDI_NO_AUTODETACH, 1) != DDI_PROP_SUCCESS) { + cmn_err(CE_WARN, "!updating DDI_NO_AUTODETACH failed"); + return DDI_FAILURE; + } +#else + if (ddi_prop_update_int(DDI_DEV_T_NONE, dip, + "ddi-no-autodetach", 1) != DDI_PROP_SUCCESS) { + cmn_err(CE_WARN, "!updating ddi-no-autodetach failed"); + return DDI_FAILURE; + } +#endif + + err = DDI_SUCCESS; + ipft = ipf_tuneables; + for (ipft = ipf_tuneables; (name = ipft->ipft_name) != NULL; ipft++) { + one = 1; + switch (ipft->ipft_sz) + { + case 4 : + i32p = NULL; + err = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, + 0, name, &i32p, &one); + if (err == DDI_PROP_NOT_FOUND) + continue; +#ifdef IPFDEBUG + cmn_err(CE_CONT, "IP Filter: lookup_int(%s) = %d\n", + name, err); +#endif + if (err != DDI_PROP_SUCCESS) + return err; + if (*i32p >= ipft->ipft_min && *i32p <= ipft->ipft_max) + *ipft->ipft_pint = *i32p; + else + err = DDI_PROP_CANNOT_DECODE; + ddi_prop_free(i32p); + break; + +#if SOLARIS2 > 8 + case 8 : + i64p = NULL; + err = ddi_prop_lookup_int64_array(DDI_DEV_T_ANY, dip, + 0, name, &i64p, &one); + if (err == DDI_PROP_NOT_FOUND) + continue; +# ifdef IPFDEBUG + cmn_err(CE_CONT, "IP Filter: lookup_int64(%s) = %d\n", + name, err); +# endif + if (err != DDI_PROP_SUCCESS) + return err; + if (*i64p >= ipft->ipft_min && *i64p <= ipft->ipft_max) + *ipft->ipft_pint = *i64p; + else + err = DDI_PROP_CANNOT_DECODE; + ddi_prop_free(i64p); + break; +#endif + + default : + break; + } + if (err != DDI_SUCCESS) + break; + } + + return err; +} |
