summaryrefslogtreecommitdiff
path: root/usr/src/common/ipf/solaris.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/common/ipf/solaris.c')
-rw-r--r--usr/src/common/ipf/solaris.c1122
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);
-}