diff options
Diffstat (limited to 'usr/src/common/ipf/solaris.c')
| -rw-r--r-- | usr/src/common/ipf/solaris.c | 1122 |
1 files changed, 0 insertions, 1122 deletions
diff --git a/usr/src/common/ipf/solaris.c b/usr/src/common/ipf/solaris.c deleted file mode 100644 index f4ac8ff761..0000000000 --- a/usr/src/common/ipf/solaris.c +++ /dev/null @@ -1,1122 +0,0 @@ -/* - * 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 "%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 "ip_compat.h" -#include "ipl.h" -#include "ip_fil.h" -#include "ip_nat.h" -#include "ip_frag.h" -#include "ip_auth.h" -#include "ip_state.h" -#if SOLARIS2 >= 10 -#include "pfild.h" -#endif - - -extern struct filterstats frstats[]; -extern ipfrwlock_t ipf_mutex, ipf_nat, ipf_global; -extern ipfmutex_t ipf_rw, ipf_timeoutlock; -extern int fr_running; -extern int fr_flags; -#ifdef IPFILTER_SYNC -extern int iplwrite __P((dev_t, struct uio *, cred_t *)); -#endif - -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, qif_t *, mblk_t **)); -static char *ipf_devfiles[] = { IPL_NAME, IPNAT_NAME, IPSTATE_NAME, - IPAUTH_NAME, IPSYNC_NAME, IPSCAN_NAME, - IPLOOKUP_NAME, NULL }; - - -#if SOLARIS2 >= 7 -void fr_slowtimer __P((void *)); -timeout_id_t fr_timer_id; -static timeout_id_t synctimeoutid = 0; -#else -void fr_slowtimer __P((void)); -int fr_timer_id; -static int synctimeoutid = 0; -#endif - -#ifndef IRE_ILL_CN -#ifdef IPFDEBUG -void printire __P((ire_t *)); -#endif -#endif - -static struct cb_ops ipf_cb_ops = { - iplopen, - iplclose, - nodev, /* strategy */ - nodev, /* print */ - nodev, /* dump */ - iplread, -#ifdef IPFILTER_SYNC - iplwrite, /* write */ -#else - nodev, /* write */ -#endif - 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 status; - - /* - * Initialize mutex's - */ - RWLOCK_INIT(&ipf_global, "ipf filter load/unload mutex"); - RWLOCK_INIT(&ipf_mutex, "ipf filter rwlock"); - ipf_kstat_init(); - status = mod_install(&modlink1); - if (status != 0) { - RW_DESTROY(&ipf_mutex); - RW_DESTROY(&ipf_global); - ipf_kstat_fini(); - } - - return status; -} - - -int _fini(void) -{ - int status; - - status = mod_remove(&modlink1); - if (status != 0) - return status; - ipf_kstat_fini(); - RW_DESTROY(&ipf_mutex); - RW_DESTROY(&ipf_global); - return status; -} - - -int _info(modinfop) -struct modinfo *modinfop; -{ - int status; - - status = mod_info(&modlink1, modinfop); - return status; -} - - -#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 - - - 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; - - if (pfilinterface != PFIL_INTERFACE) { -#ifdef IPFDEBUG - cmn_err(CE_NOTE, "pfilinterface(%d) != %d", - pfilinterface, PFIL_INTERFACE); -#endif - return DDI_FAILURE; - } - - if (ddi_prop_update_int(DDI_DEV_T_NONE, dip, DDI_NO_AUTODETACH, - 1) != DDI_PROP_SUCCESS) { -#ifdef IPFDEBUG - cmn_err(CE_WARN, "!updating %s failed", - DDI_NO_AUTODETACH); -#endif - return DDI_FAILURE; - } - - 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); - return DDI_FAILURE; - } - } - - ipf_dev_info = dip; - /* - * Lock people out while we set things up. - */ - WRITE_ENTER(&ipf_global); - if ((fr_running != 0) || (iplattach() == -1)) { - RWLOCK_EXIT(&ipf_global); -#ifdef IPFDEBUG - cmn_err(CE_NOTE, "IP Filter: iplattach() failed"); -#endif - goto attach_failed; - } - - if (pfil_add_hook(fr_check, PFIL_IN|PFIL_OUT, &pfh_inet4)) { - RWLOCK_EXIT(&ipf_global); - goto attach_failed; - } - -#ifdef USE_INET6 - if (pfil_add_hook(fr_check, PFIL_IN|PFIL_OUT, &pfh_inet6)) { - RWLOCK_EXIT(&ipf_global); - goto attach_failed; - } -#endif - - if (pfil_add_hook(fr_qifsync, PFIL_IN|PFIL_OUT, &pfh_sync)) { - RWLOCK_EXIT(&ipf_global); - goto attach_failed; - } - - 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: - return DDI_FAILURE; - } - -attach_failed: -#ifdef IPFDEBUG - cmn_err(CE_NOTE, "IP Filter: failed to attach"); -#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_running == -2 || fr_running == 0) { -#ifdef IPFDEBUG - cmn_err(CE_NOTE, "IP Filter: not yet attached " - "or already detached"); -#endif - 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; - - (void) pfil_remove_hook(fr_check, PFIL_IN|PFIL_OUT, &pfh_inet4); -#ifdef USE_INET6 - (void) pfil_remove_hook(fr_check, PFIL_IN|PFIL_OUT, &pfh_inet6); -#endif - (void) pfil_remove_hook(fr_qifsync, PFIL_IN|PFIL_OUT, &pfh_sync); - - 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) { -#ifdef IPFDEBUG - cmn_err(CE_CONT, "IP Filter: still attached (%d)\n", i); -#endif - return DDI_FAILURE; - } - - WRITE_ENTER(&ipf_global); - if (!ipldetach()) { - RWLOCK_EXIT(&ipf_global); -#ifdef IPFDEBUG - cmn_err(CE_CONT, "!%s detached.\n", ipfilter_version); -#endif - return (DDI_SUCCESS); - } - RWLOCK_EXIT(&ipf_global); -#ifdef IPFDEBUG - cmn_err(CE_NOTE, "IP Filter: ipldetach() failed"); -#endif - break; - default: - return DDI_FAILURE; - } -#ifdef IPFDEBUG - cmn_err(CE_NOTE, "IP Filter: failed to detach"); -#endif - 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; -qif_t *qif; -mblk_t **mp; -{ - - frsync(); - /* - * Resync. any NAT `connections' using this interface and its IP #. - */ - fr_natsync(il); - fr_statesync(il); - return 0; -} - - -/* - * look for bad consistancies between the list of interfaces the filter knows - * about and those which are currently configured. - */ -int ipfsync() -{ - qif_t *qf; - - frsync(); - /* - * Resync. any NAT `connections' using this interface and its IP #. - */ - qf = NULL; - while (qif_walk(&qf)) - (void) fr_qifsync(NULL, 0, (void *)qf->qf_ill, -1, qf, NULL); - return 0; -} - -#ifndef IRE_ILL_CN -#ifdef IPFDEBUG -void printire(ire) -ire_t *ire; -{ - printf("ire: ll_hdr_mp %p rfq %p stq %p src_addr %x max_frag %d\n", -# if SOLARIS2 >= 8 - NULL, -# else - ire->ire_ll_hdr_mp, -# endif - ire->ire_rfq, ire->ire_stq, - ire->ire_src_addr, ire->ire_max_frag); - printf("ire: mask %x addr %x gateway_addr %x type %d\n", - ire->ire_mask, ire->ire_addr, ire->ire_gateway_addr, - ire->ire_type); - printf("ire: ll_hdr_length %d ll_hdr_saved_mp %p\n", - ire->ire_ll_hdr_length, -# if SOLARIS2 >= 8 - NULL -# else - ire->ire_ll_hdr_saved_mp -# endif - ); - -} -#endif -#endif /* IRE_ILL_CN */ - -/* - * Function: fr_fastroute - * Returns: 0: success; - * -1: failed - * Parameters: - * mb: the message block where ip head starts - * mpp: the pointer to the pointer of the orignal - * packet message - * fin: packet information - * fdp: destination interface information - * if it is NULL, no interface information provided. - * - * This function is for fastroute/to/dup-to rules. It calls - * pfil_make_lay2_packet to search route, make lay-2 header - * ,and identify output queue for the IP packet. - * The destination address depends on the following conditions: - * 1: for fastroute rule, fdp is passed in as NULL, so the - * destination address is the IP Packet's destination address - * 2: for to/dup-to rule, if an ip address is specified after - * the interface name, this address is the as destination - * address. Otherwise IP Packet's destination address is used - */ -int fr_fastroute(mb, mpp, fin, fdp) -mblk_t *mb, **mpp; -fr_info_t *fin; -frdest_t *fdp; -{ -#ifndef IRE_ILL_CN - ire_t *ir, *dir; - struct in_addr dst; - ill_t *ifp; - u_char *s; - size_t hlen = 0; - frdest_t fd; -#else - void *target = NULL; - char *ifname = NULL; - s_ill_t *ifp; -#endif - queue_t *q = NULL; - mblk_t *mp = NULL; - frentry_t *fr = fin->fin_fr; - qif_t *qf; - ip_t *ip; -#ifndef sparc - u_short __iplen, __ipoff; -#endif -#ifndef IRE_ILL_CN -#ifdef USE_INET6 - ip6_t *ip6 = (ip6_t *)fin->fin_ip; -#endif -#endif - ip = fin->fin_ip; - qf = fin->fin_qif; - - /* - * If this is a duplicate mblk then we want ip to point at that - * data, not the original, if and only if it is already pointing at - * the current mblk data. - * - * Otherwise, if it's not a duplicate, and we're not already pointing - * at the current mblk data, then we want to ensure that the data - * points at ip. - */ - - if ((ip == (ip_t *)qf->qf_m->b_rptr) && (qf->qf_m != mb)) { - ip = (ip_t *)mb->b_rptr; - } else if ((qf->qf_m == mb) && (ip != (ip_t *)qf->qf_m->b_rptr)) { - qf->qf_m->b_rptr = (uchar_t *)ip; - qf->qf_off = 0; - } - - /* - * If there is another M_PROTO, we don't want it - */ - if (*mpp != mb) { - mp = unlinkb(*mpp); - freeb(*mpp); - *mpp = mp; - } - - - /* - * In case we're here due to "to <if>" being used with - * "keep state", check that we're going in the correct - * direction. - */ - if (fdp != NULL) { - if ((fr != NULL) && (fdp->fd_ifp != NULL) && - (fin->fin_rev != 0) && (fdp == &fr->fr_tif)) - goto bad_fastroute; - } - -#ifndef IRE_ILL_CN - if (!fdp) { - ipif_t *ipif; - - ifp = fin->fin_ifp; - ipif = ifp->ill_ipif; - if (!ipif) - goto bad_fastroute; -#if SOLARIS2 > 5 - ir = ire_ctable_lookup(ipif->ipif_local_addr, 0, IRE_LOCAL, - NULL, NULL, MATCH_IRE_TYPE); -#else - ir = ire_lookup_myaddr(ipif->ipif_local_addr); -#endif - if (!ir) - ir = (ire_t *)-1; - - fd.fd_ifp = (struct ifnet *)ir; - fd.fd_ip = ip->ip_dst; - fdp = &fd; - } - - ir = (ire_t *)fdp->fd_ifp; - - if (fdp->fd_ip.s_addr) - dst = fdp->fd_ip; - else - dst.s_addr = fin->fin_fi.fi_daddr; - -#if SOLARIS2 >= 6 - if (fin->fin_v == 4) { - dir = ire_route_lookup(dst.s_addr, 0xffffffff, 0, 0, NULL, - NULL, NULL, MATCH_IRE_DSTONLY| - MATCH_IRE_DEFAULT|MATCH_IRE_RECURSIVE); - } -#ifdef USE_INET6 - else if (fin->fin_v == 6) { - dir = ire_route_lookup_v6(&ip6->ip6_dst, NULL, 0, 0, - NULL, NULL, NULL, MATCH_IRE_DSTONLY| - MATCH_IRE_DEFAULT|MATCH_IRE_RECURSIVE); - } -#endif -#else - dir = ire_lookup(dst.s_addr); -#endif -#if SOLARIS2 < 8 - if (dir) - if (!dir->ire_ll_hdr_mp || !dir->ire_ll_hdr_length) - dir = NULL; -#else - if (dir) - if (!dir->ire_fp_mp || !dir->ire_dlureq_mp) - dir = NULL; -#endif - - if (!ir) - ir = dir; - - if (!ir || !dir) - goto bad_fastroute; - -#if SOLARIS2 < 8 - mp = dir->ire_ll_hdr_mp; - hlen = dir->ire_ll_hdr_length; -#else - mp = dir->ire_fp_mp; - hlen = mp ? mp->b_wptr - mp->b_rptr : 0; - if (mp == NULL) - mp = dir->ire_dlureq_mp; -#endif - if (mp != NULL) { - s = mb->b_rptr; - if ( -#if SOLARIS2 >= 6 - (dohwcksum && - ifp->ill_ick.ick_magic == ICK_M_CTL_MAGIC) || -#endif - (hlen && (s - mb->b_datap->db_base) >= hlen)) { - s -= hlen; - mb->b_rptr = (u_char *)s; - bcopy((char *)mp->b_rptr, (char *)s, hlen); - } else { - mblk_t *mp2; - - mp2 = copyb(mp); - if (!mp2) - goto bad_fastroute; - linkb(mp2, mb); - mb = mp2; - } - } - - if (ir->ire_stq) - q = ir->ire_stq; - else if (ir->ire_rfq) - q = WR(ir->ire_rfq); - if (q) - q = q->q_next; - if (!q) - goto bad_fastroute; - - ifp = ire_to_ill(ir); - if (ifp == NULL) - goto bad_fastroute; - - fin->fin_ifp = ifp; -#else /* IRE_ILL_CN */ - if (fin->fin_v == 4) { - if (fdp && (fdp->fd_ip.s_addr != 0)) - target = &fdp->fd_ip; - } -#ifdef USE_INET6 - else if (fin->fin_v == 6) { - if (fdp && !IN6_IS_ADDR_UNSPECIFIED(&fdp->fd_ip6.in6)) - target = &fdp->fd_ip6.in6; - } -#endif - else - goto bad_fastroute; - - if (fdp && fdp->fd_ifname[0] != 0) - ifname = fdp->fd_ifname; - - mp = pfil_make_dl_packet(mb, ip, target, ifname, &q); - if (mp == NULL) - { - goto bad_fastroute; - } - mb = mp; - /* - * Determine the s_ill_t we're going out on - */ - ifp = ((qif_t *)(q->q_ptr))->qf_ill; -#endif /* IRE_ILL_CN */ - - mb->b_queue = q; - *mpp = mb; - - if (fin->fin_out == 0) { - void *saveifp; - u_32_t pass; - - saveifp = fin->fin_ifp; - fin->fin_ifp = ifp; - (void)fr_acctpkt(fin, &pass); - fin->fin_fr = NULL; - if (!fr || !(fr->fr_flags & FR_RETMASK)) - (void) fr_checkstate(fin, &pass); - (void) fr_checknatout(fin, NULL); - fin->fin_ifp = saveifp; - } -#ifndef sparc - if (fin->fin_v == 4) { - __iplen = (u_short)ip->ip_len, - __ipoff = (u_short)ip->ip_off; - - ip->ip_len = htons(__iplen); - ip->ip_off = htons(__ipoff); - } -#endif - -#ifndef IRE_ILL_CN -#if SOLARIS2 >= 6 - if ((p == IPPROTO_TCP) && dohwcksum && - (ifp->ill_ick.ick_magic == ICK_M_CTL_MAGIC)) { - tcphdr_t *tcp; - u_32_t t; - - tcp = (tcphdr_t *)((char *)ip + fin->fin_hlen); - t = ip->ip_src.s_addr; - t += ip->ip_dst.s_addr; - t += 30; - t = (t & 0xffff) + (t >> 16); - tcp->th_sum = t & 0xffff; - } -#endif - RWLOCK_EXIT(&ipf_global); - putnext(q, mb); - READ_ENTER(&ipf_global); -#else /* IRE_ILL_CN */ - pfil_send_dl_packet(q, mb); -#endif /* IRE_ILL_CN */ - fr_frouteok[0]++; - return 0; -bad_fastroute: - freemsg(mb); - fr_frouteok[1]++; - return -1; -} - -#if SOLARIS2 >= 10 -/* - * Function: addrset_match_v4 - * Returns: boolean_t - * Parameters: addr - the IP address of interest - * setp - pointer to an address set (generated by pfild) - * - * Support function for fr_verifysrc used on Solaris 10 and later. - * Try to match an IPv4 address against an address set. - * Returns true iff the specified address is a member of the set. - * Note that addr is passed in network byte order; we convert it to host byte - * order for searching the table. - */ -static boolean_t addrset_match_v4(setp, addr) -struct pfil_ifaddrset *setp; -struct in_addr addr; -{ - uint32_t haddr = ntohl(addr.s_addr); - unsigned int low, high, mid; - struct pfil_v4span *spans = (struct pfil_v4span *)(setp + 1); - - /* binary search */ - low = 0; - high = setp->nspans; - while (low < high) { - mid = (high + low) / 2; - if (haddr > spans[mid].last) - low = mid + 1; - else if (haddr < spans[mid].first) - high = mid; - else - return B_TRUE; - } - return B_FALSE; -} - -/* - * Function: addrset_match_v6 - * Returns: boolean_t - * Parameters: addr - the IP address of interest - * setp - pointer to an address set (generated by pfild) - * - * Support function for fr_verifysrc used on Solaris 10 and later. - * Try to match an IPv6 address against an address set. - * Returns true iff the specified address is a member of the set. - */ -static boolean_t addrset_match_v6(setp, addr) -struct pfil_ifaddrset *setp; -struct in6_addr addr; -{ - unsigned int low, high, mid; - struct pfil_v6span *spans = (struct pfil_v6span *)(setp + 1); - - /* binary search */ - low = 0; - high = setp->nspans; - while (low < high) { - mid = (high + low) / 2; - if (IP6_GT(&addr, &spans[mid].last)) - low = mid + 1; - else if (IP6_LT(&addr, &spans[mid].first)) - high = mid; - else - return B_TRUE; - } - return B_FALSE; -} -#endif - -/* - * Function: fr_verifysrc - * Returns: int (really boolean) - * Parameters: fin - packet information - * - * Check whether the packet has a valid source address for the interface on - * which the packet arrived, implementing the "fr_chksrc" feature. - * Returns true iff the packet's source address is valid. - * Pre-Solaris 10, we call into the routing code to make the determination. - * On Solaris 10 and later, we have a valid address set from pfild to check - * against. - */ -int fr_verifysrc(fin) -fr_info_t *fin; -{ -#if SOLARIS2 >= 10 - qif_t *qf = fin->fin_qif; - struct pfil_ifaddrset *setp; - - if (qf->qf_addrset == NULL) { - /* Warn here? pfild might not be running. */ - return 0; - } - - setp = (struct pfil_ifaddrset *)qf->qf_addrset->b_rptr; - if (!setp) - return 0; - - if (fin->fin_v == IPVERSION && setp->af == AF_INET) { - if (qf->qf_addrset->b_wptr - qf->qf_addrset->b_rptr < - sizeof (*setp) + setp->nspans * sizeof (struct pfil_v4span)) - return 0; /* malformed set */ - - return addrset_match_v4(setp, fin->fin_src); - } else if (fin->fin_v == IPV6_VERSION && setp->af == AF_INET6) { - if (qf->qf_addrset->b_wptr - qf->qf_addrset->b_rptr < - sizeof (*setp) + setp->nspans * sizeof (struct pfil_v6span)) - return 0; /* malformed set */ - - return addrset_match_v6(setp, fin->fin_src6); - } else - return 0; - -#else - ire_t *ir, *dir; - -#if SOLARIS2 >= 6 - dir = ire_route_lookup(fin->fin_saddr, 0xffffffff, 0, 0, NULL, - NULL, NULL, MATCH_IRE_DSTONLY|MATCH_IRE_DEFAULT| - MATCH_IRE_RECURSIVE); -#else - dir = ire_lookup(fin->fin_saddr); -#endif - - if (!dir) - return 0; - return (ire_to_ill(dir) == fin->fin_ifp); -#endif /* SOLARIS2 >= 10 */ -} - - -#if (SOLARIS2 < 7) -void fr_slowtimer() -#else -/*ARGSUSED*/ -void fr_slowtimer __P((void *ptr)) -#endif -{ - - WRITE_ENTER(&ipf_global); - if (fr_running <= 0) { - if (fr_running == -1) - fr_timer_id = timeout(fr_slowtimer, NULL, - drv_usectohz(500000)); - else - fr_timer_id = NULL; - RWLOCK_EXIT(&ipf_global); - return; - } - MUTEX_DOWNGRADE(&ipf_global); - - fr_fragexpire(); - fr_timeoutstate(); - fr_natexpire(); - fr_authexpire(); - fr_ticks++; - if (fr_running == -1 || fr_running == 1) - fr_timer_id = timeout(fr_slowtimer, NULL, drv_usectohz(500000)); - else - fr_timer_id = NULL; - RWLOCK_EXIT(&ipf_global); -} |
