summaryrefslogtreecommitdiffstats
path: root/contrib/ipfilter/solaris.c
diff options
context:
space:
mode:
authorcy <cy@FreeBSD.org>2013-07-19 05:41:57 +0000
committercy <cy@FreeBSD.org>2013-07-19 05:41:57 +0000
commit672af8808c0e7c15f330b401482f9271c2eb3fa6 (patch)
tree225b5acf68c01bc6a260b386c2b2dbf4fa2839e3 /contrib/ipfilter/solaris.c
parent71e82d94e82560b20789833f60056506de34de8b (diff)
downloadFreeBSD-src-672af8808c0e7c15f330b401482f9271c2eb3fa6.zip
FreeBSD-src-672af8808c0e7c15f330b401482f9271c2eb3fa6.tar.gz
As per the developers handbook (5.3.1 step 1), prepare the vendor trees for
import of new ipfilter vendor sources by flattening them. To keep the tags consistent with dist, the tags are also flattened. Approved by: glebius (Mentor)
Diffstat (limited to 'contrib/ipfilter/solaris.c')
-rw-r--r--contrib/ipfilter/solaris.c2131
1 files changed, 0 insertions, 2131 deletions
diff --git a/contrib/ipfilter/solaris.c b/contrib/ipfilter/solaris.c
deleted file mode 100644
index aa139d3..0000000
--- a/contrib/ipfilter/solaris.c
+++ /dev/null
@@ -1,2131 +0,0 @@
-/*
- * Copyright (C) 1993-2002 by Darren Reed.
- *
- * See the IPFILTER.LICENCE file for details on licencing.
- */
-/* #pragma ident "@(#)solaris.c 1.12 6/5/96 (C) 1995 Darren Reed"*/
-#pragma ident "@(#)$Id: solaris.c,v 2.15.2.30 2002/04/23 14:57:51 darrenr Exp $"
-
-#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/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_state.h"
-
-
-char _depends_on[] = "drv/ip";
-
-
-void solipdrvattach __P((void));
-int solipdrvdetach __P((void));
-
-void solattach __P((void));
-int soldetach __P((void));
-
-extern struct filterstats frstats[];
-extern KRWLOCK_T ipf_mutex, ipfs_mutex, ipf_nat, ipf_solaris;
-extern kmutex_t ipf_rw;
-extern int fr_running;
-extern int fr_flags;
-
-extern ipnat_t *nat_list;
-
-static qif_t *qif_head = NULL;
-static int ipf_getinfo __P((dev_info_t *, ddi_info_cmd_t,
- void *, void **));
-static int ipf_probe __P((dev_info_t *));
-static int ipf_identify __P((dev_info_t *));
-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 qif_t *qif_from_queue __P((queue_t *));
-static void fr_donotip __P((int, qif_t *, queue_t *, mblk_t *,
- mblk_t *, ip_t *, size_t));
-static char *ipf_devfiles[] = { IPL_NAME, IPL_NAT, IPL_STATE, IPL_AUTH,
- NULL };
-static int (*ipf_ip_inp) __P((queue_t *, mblk_t *)) = NULL;
-
-
-#if SOLARIS2 >= 7
-extern void ipfr_slowtimer __P((void *));
-timeout_id_t ipfr_timer_id;
-static timeout_id_t synctimeoutid = 0;
-#else
-extern void ipfr_slowtimer __P((void));
-int ipfr_timer_id;
-static int synctimeoutid = 0;
-#endif
-int ipf_debug = 0;
-int ipf_debug_verbose = 0;
-
-/* #undef IPFDEBUG 1 */
-/* #undef IPFDEBUG_VERBOSE 1 */
-#ifdef IPFDEBUG
-void printire __P((ire_t *));
-#endif
-#define isdigit(x) ((x) >= '0' && (x) <= '9')
-
-static int fr_precheck __P((mblk_t **, queue_t *, qif_t *, int));
-
-
-static struct cb_ops ipf_cb_ops = {
- iplopen,
- iplclose,
- nodev, /* strategy */
- nodev, /* print */
- nodev, /* dump */
- iplread,
- nodev, /* 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,
- ipf_identify,
- ipf_probe,
- 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, 14 }, /* 14 for ire0 ?? */
- { IFT_HDH1822, 0 },
- { IFT_X25DDN, 0 },
- { IFT_X25, 0 },
- { IFT_ETHER, 14 },
- { IFT_ISO88023, 14 },
- { 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;
-
-
-int _init()
-{
- int ipfinst;
-
- ipfinst = mod_install(&modlink1);
-#ifdef IPFDEBUG
- if (ipf_debug)
- cmn_err(CE_NOTE, "IP Filter: _init() = %d", ipfinst);
-#endif
- return ipfinst;
-}
-
-
-int _fini(void)
-{
- int ipfinst;
-
- ipfinst = mod_remove(&modlink1);
-#ifdef IPFDEBUG
- if (ipf_debug)
- cmn_err(CE_NOTE, "IP Filter: _fini() = %d", ipfinst);
-#endif
- return ipfinst;
-}
-
-
-int _info(modinfop)
-struct modinfo *modinfop;
-{
- int ipfinst;
-
- ipfinst = mod_info(&modlink1, modinfop);
-#ifdef IPFDEBUG
- if (ipf_debug)
- cmn_err(CE_NOTE, "IP Filter: _info(%x) = %x",
- modinfop, ipfinst);
-#endif
- if (fr_running > 0)
- ipfsync();
- return ipfinst;
-}
-
-
-static int ipf_probe(dip)
-dev_info_t *dip;
-{
- if (fr_running < 0)
- return DDI_PROBE_FAILURE;
-#ifdef IPFDEBUG
- if (ipf_debug)
- cmn_err(CE_NOTE, "IP Filter: ipf_probe(%x)", dip);
-#endif
- return DDI_PROBE_SUCCESS;
-}
-
-
-static int ipf_identify(dip)
-dev_info_t *dip;
-{
-#ifdef IPFDEBUG
- if (ipf_debug)
- 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);
-}
-
-
-static void ipf_ire_walk(ire, arg)
-ire_t *ire;
-void *arg;
-{
- qif_t *qif = arg;
-
- if ((ire->ire_type == IRE_CACHE) &&
-#if SOLARIS2 >= 6
- (ire->ire_ipif != NULL) &&
- (ire->ire_ipif->ipif_ill == qif->qf_ill)
-#else
- (ire_to_ill(ire) == qif->qf_ill)
-#endif
- ) {
-#if SOLARIS2 >= 8
- mblk_t *m = ire->ire_fp_mp;
-#else
- mblk_t *m = ire->ire_ll_hdr_mp;
-#endif
- if (m != NULL)
- qif->qf_hl = m->b_wptr - m->b_rptr;
- }
-}
-
-
-static int ipf_attach(dip, cmd)
-dev_info_t *dip;
-ddi_attach_cmd_t cmd;
-{
-#ifdef IPFDEBUG
- int instance;
-
- if (ipf_debug)
- cmn_err(CE_NOTE, "IP Filter: ipf_attach(%x,%x)", dip, cmd);
-#endif
- switch (cmd) {
- case DDI_ATTACH:
- if (fr_running < 0)
- break;
-#ifdef IPFDEBUG
- instance = ddi_get_instance(dip);
-
- if (ipf_debug)
- cmn_err(CE_NOTE, "IP Filter: attach ipf instance %d", instance);
-#endif
- if (ddi_create_minor_node(dip, "ipf", S_IFCHR, IPL_LOGIPF,
- DDI_PSEUDO, 0) == DDI_FAILURE) {
- ddi_remove_minor_node(dip, NULL);
- goto attach_failed;
- }
- if (ddi_create_minor_node(dip, "ipnat", S_IFCHR, IPL_LOGNAT,
- DDI_PSEUDO, 0) == DDI_FAILURE) {
- ddi_remove_minor_node(dip, NULL);
- goto attach_failed;
- }
- if (ddi_create_minor_node(dip, "ipstate", S_IFCHR,IPL_LOGSTATE,
- DDI_PSEUDO, 0) == DDI_FAILURE) {
- ddi_remove_minor_node(dip, NULL);
- goto attach_failed;
- }
- if (ddi_create_minor_node(dip, "ipauth", S_IFCHR, IPL_LOGAUTH,
- DDI_PSEUDO, 0) == DDI_FAILURE) {
- ddi_remove_minor_node(dip, NULL);
- goto attach_failed;
- }
- ipf_dev_info = dip;
- sync();
- /*
- * Initialize mutex's
- */
- if (iplattach() == -1)
- goto attach_failed;
- /*
- * Lock people out while we set things up.
- */
- WRITE_ENTER(&ipf_solaris);
- solattach();
- solipdrvattach();
- RWLOCK_EXIT(&ipf_solaris);
- cmn_err(CE_CONT, "%s, attaching complete.\n",
- ipfilter_version);
- sync();
- if (fr_running == 0)
- fr_running = 1;
- if (ipfr_timer_id == 0)
- ipfr_timer_id = timeout(ipfr_slowtimer, NULL,
- drv_usectohz(500000));
- if (fr_running == 1)
- return DDI_SUCCESS;
-#if SOLARIS2 >= 8
- case DDI_RESUME :
- case DDI_PM_RESUME :
- if (ipfr_timer_id == 0)
- ipfr_timer_id = timeout(ipfr_slowtimer, NULL,
- drv_usectohz(500000));
- return DDI_SUCCESS;
-#endif
- default:
- return DDI_FAILURE;
- }
-
-attach_failed:
- cmn_err(CE_NOTE, "IP Filter: failed to attach\n");
- /*
- * 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
- if (ipf_debug)
- cmn_err(CE_NOTE, "IP Filter: ipf_detach(%x,%x)", dip, cmd);
-#endif
- switch (cmd) {
- case DDI_DETACH:
- if (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.
- */
- mutex_enter(&ipf_rw);
- if (ipfr_timer_id != 0) {
- untimeout(ipfr_timer_id);
- ipfr_timer_id = 0;
- }
- mutex_exit(&ipf_rw);
- WRITE_ENTER(&ipf_solaris);
- mutex_enter(&ipf_rw);
- if (fr_running <= 0) {
- mutex_exit(&ipf_rw);
- return DDI_FAILURE;
- }
- fr_running = -1;
- mutex_exit(&ipf_rw);
- /* NOTE: ipf_solaris rwlock is released in ipldetach */
-
- /*
- * 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);
- sync();
- i = solipdrvdetach();
- if (i > 0) {
- cmn_err(CE_CONT, "IP Filter: still attached (%d)\n", i);
- return DDI_FAILURE;
- }
- if (!soldetach()) {
- cmn_err(CE_CONT, "%s detached\n", ipfilter_version);
- return (DDI_SUCCESS);
- }
-#if SOLARIS2 >= 8
- case DDI_SUSPEND :
- case DDI_PM_SUSPEND :
- if (ipfr_timer_id != 0) {
- untimeout(ipfr_timer_id);
- ipfr_timer_id = 0;
- }
- if (synctimeoutid) {
- untimeout(synctimeoutid);
- synctimeoutid = 0;
- }
- return DDI_SUCCESS;
-#endif
- default:
- return (DDI_FAILURE);
- }
- return DDI_FAILURE;
-}
-
-
-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
- if (ipf_debug)
- 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 *)getminor((dev_t) arg);
- error = DDI_SUCCESS;
- break;
- default:
- break;
- }
- return (error);
-}
-
-/*
- * find the filter structure setup for this queue
- */
-static qif_t *qif_from_queue(q)
-queue_t *q;
-{
- qif_t *qif;
-
- for (qif = qif_head; qif; qif = qif->qf_next)
- if ((qif->qf_iptr == q->q_ptr) || (qif->qf_optr == q->q_ptr))
- break;
- return qif;
-}
-
-
-/*
- * OK, this is pretty scrappy code, but then it's essentially just here for
- * debug purposes and that's it. Packets should not normally come through
- * here, and if they do, well, we would like to see as much information as
- * possible about them and what they claim to hold.
- */
-void fr_donotip(out, qif, q, m, mt, ip, off)
-int out;
-qif_t *qif;
-queue_t *q;
-mblk_t *m, *mt;
-ip_t *ip;
-size_t off;
-{
- u_char *s, outb[256], *t;
- int i;
-
- outb[0] = '\0';
- outb[1] = '\0';
- outb[2] = '\0';
- outb[3] = '\0';
- s = ip ? (u_char *)ip : outb;
- if (!ip && (m == mt) && m->b_cont && (MTYPE(m) != M_DATA))
- m = m->b_cont;
-
- cmn_err(CE_CONT, " !IP %s:%d %d %p %p %p %d %p/%d %p/%d %p %d %d %p\n",
- qif ? qif->qf_name : "?", out, qif ? qif->qf_hl : -1, q,
- q ? q->q_ptr : NULL, q ? q->q_qinfo : NULL,
- mt->b_wptr - mt->b_rptr, m, MTYPE(m), mt, MTYPE(mt), m->b_rptr,
- m->b_wptr - m->b_rptr, off, ip);
- cmn_err(CE_CONT, "%02x%02x%02x%02x\n", *s, *(s+1), *(s+2), *(s+3));
- while (m != mt) {
- i = 0;
- t = outb;
- s = mt->b_rptr;
- sprintf((char *)t, "%d:", MTYPE(mt));
- t += strlen((char *)t);
- for (; (i < 100) && (s < mt->b_wptr); i++) {
- sprintf((char *)t, "%02x%s", *s++,
- ((i & 3) == 3) ? " " : "");
- t += ((i & 3) == 3) ? 3 : 2;
- }
- *t++ = '\n';
- *t = '\0';
- cmn_err(CE_CONT, "%s", outb);
- mt = mt->b_cont;
- }
- i = 0;
- t = outb;
- s = m->b_rptr;
- sprintf((char *)t, "%d:", MTYPE(m));
- t += strlen((char *)t);
- for (; (i < 100) && (s < m->b_wptr); i++) {
- sprintf((char *)t, "%02x%s", *s++, ((i & 3) == 3) ? " " : "");
- t += ((i & 3) == 3) ? 3 : 2;
- }
- *t++ = '\n';
- *t = '\0';
- cmn_err(CE_CONT, "%s", outb);
-}
-
-
-/*
- * find the first data mblk, if present, in the chain we're processing. Also
- * make a few sanity checks to try prevent the filter from causing a panic -
- * none of the nice IP sanity checks (including checksumming) should have been
- * done yet (for incoming packets) - dangerous!
- */
-static int fr_precheck(mp, q, qif, out)
-mblk_t **mp;
-queue_t *q;
-qif_t *qif;
-int out;
-{
- register mblk_t *m, *mt = *mp;
- register ip_t *ip;
- size_t hlen, len, off, off2, mlen, iphlen, plen, woff;
- int err, synced = 0, sap, p, realigned = 0, multi = 0;
- u_char *bp;
-#if SOLARIS2 >= 8
- ip6_t *ip6;
-#endif
-#ifndef sparc
- u_short __ipoff;
-#endif
-tryagain:
- ip = NULL;
- m = NULL;
- /*
- * If there is only M_DATA for a packet going out, then any header
- * information (which would otherwise appear in an M_PROTO mblk before
- * the M_DATA) is prepended before the IP header. We need to set the
- * offset to account for this. - see MMM
- */
- off = (out) ? qif->qf_hl : 0;
-
- /*
- * If the message protocol block indicates that there isn't a data
- * block following it, just return back.
- */
- bp = (u_char *)ALIGN32(mt->b_rptr);
- if (MTYPE(mt) == M_PROTO || MTYPE(mt) == M_PCPROTO) {
- dl_unitdata_ind_t *dl = (dl_unitdata_ind_t *)bp;
- if (dl->dl_primitive == DL_UNITDATA_IND) {
- multi = dl->dl_group_address;
- m = mt->b_cont;
- /*
- * This is a complete kludge to try and work around
- * some bizarre packets which drop through into
- * fr_donotip.
- */
- if (m && multi && ((*((u_char *)m->b_rptr) == 0x0) &&
- ((*((u_char *)m->b_rptr + 2) == 0x45)))) {
- ip = (ip_t *)(m->b_rptr + 2);
- off = 2;
- } else
- off = 0;
- } else if (dl->dl_primitive != DL_UNITDATA_REQ) {
- ip = (ip_t *)dl;
- if ((ip->ip_v == IPVERSION) &&
- (ip->ip_hl == (sizeof(*ip) >> 2)) &&
- (ntohs(ip->ip_len) == mt->b_wptr - mt->b_rptr)) {
- off = 0;
- m = mt;
- } else {
- frstats[out].fr_notdata++;
- return 0;
- }
- }
- }
-
- /*
- * Find the first data block, count the data blocks in this chain and
- * the total amount of data.
- */
- if (ip == NULL)
- for (m = mt; m && (MTYPE(m) != M_DATA); m = m->b_cont)
- off = 0; /* Any non-M_DATA cancels the offset */
-
- if (!m) {
- frstats[out].fr_nodata++;
- return 0; /* No data blocks */
- }
-
- ip = (ip_t *)(m->b_rptr + off); /* MMM */
-
- /*
- * We might have a 1st data block which is really M_PROTO, i.e. it is
- * only big enough for the link layer header
- */
- while ((u_char *)ip >= m->b_wptr) {
- len = (u_char *)ip - m->b_wptr;
- m = m->b_cont;
- if (m == NULL)
- return 0; /* not enough data for IP */
- ip = (ip_t *)(m->b_rptr + len);
- }
- off = (u_char *)ip - m->b_rptr;
- if (off != 0)
- m->b_rptr = (u_char *)ip;
-
- len = m->b_wptr - m->b_rptr;
- if (m->b_wptr < m->b_rptr) {
- cmn_err(CE_NOTE, "!IP Filter: Bad packet: wptr %p < rptr %p",
- m->b_wptr, m->b_rptr);
- frstats[out].fr_bad++;
- return -1;
- }
-
- mlen = msgdsize(m);
- sap = qif->qf_ill->ill_sap;
-
- if (sap == 0x800) {
- u_short tlen;
-
- hlen = sizeof(*ip);
-
- /* XXX - might not be aligned (from ppp?) */
- ((char *)&tlen)[0] = ((char *)&ip->ip_len)[0];
- ((char *)&tlen)[1] = ((char *)&ip->ip_len)[1];
-
- plen = ntohs(tlen);
-
- sap = 0;
- }
-#if SOLARIS2 >= 8
- else if (sap == IP6_DL_SAP) {
- u_short tlen;
-
- hlen = sizeof(ip6_t);
- ip6 = (ip6_t *)ip;
- /* XXX - might not be aligned (from ppp?) */
- ((char *)&tlen)[0] = ((char *)&ip6->ip6_plen)[0];
- ((char *)&tlen)[1] = ((char *)&ip6->ip6_plen)[1];
- plen = ntohs(tlen);
- if (!plen)
- return -1; /* Jumbo gram */
- plen += sizeof(*ip6);
- }
-#endif
- else {
- plen = 0;
- hlen = 0;
- sap = -1;
- }
-
- /*
- * Ok, the IP header isn't on a 32bit aligned address so junk it.
- */
- if (((u_long)ip & 0x3) || (plen > mlen) || (len < hlen) ||
- (sap == -1)) {
- mblk_t *m1, *m2;
- u_char *s, c;
- int v;
-
- /*
- * Junk using pullupmsg - it's next to useless.
- */
-fixalign:
- if (off)
- m->b_rptr -= off;
- c = *(u_char *)ip;
- c >>= 4;
- if (c != 4
-#if SOLARIS2 >= 8
- && c != 6
-#endif
- ) {
- frstats[out].fr_notip++;
- return (fr_flags & FF_BLOCKNONIP) ? -1 : 0;
- }
-
- if (realigned)
- return -1;
- realigned = 1;
- off2 = (size_t)((u_long)ip & 0x3);
- if (off2)
- off2 = 4 - off2;
- len = msgdsize(m);
- m2 = allocb(len + off2, BPRI_HI);
- if (m2 == NULL) {
- frstats[out].fr_pull[1]++;
- return -1;
- }
-
- MTYPE(m2) = M_DATA;
- if (m->b_rptr != (u_char *)ip)
- m2->b_rptr += off2;
- m2->b_wptr = m2->b_rptr + len;
- m1 = m;
- s = (u_char *)m->b_rptr;
- for (bp = m2->b_rptr; m1 && (bp < m2->b_wptr); bp += len) {
- len = MIN(m1->b_wptr - s, m2->b_wptr - bp);
- bcopy(s, bp, len);
- m1 = m1->b_cont;
- if (m1)
- s = m1->b_rptr;
- }
-
- if (mt != m && mt->b_cont == m && !off) {
- /*
- * check if the buffer we're changing is chained in-
- * between other buffers and unlink/relink as required.
- */
- (void) unlinkb(mt); /* should return 'm' */
- m1 = unlinkb(m);
- if (m1)
- linkb(m2, m1);
- freemsg(m);
- linkb(mt, m2);
- } else {
- if (m == mt) {
- m1 = unlinkb(mt);
- if (m1)
- linkb(m2, m1);
- }
- freemsg(mt);
- *mp = m2;
- mt = m2;
- }
-
- frstats[out].fr_pull[0]++;
- synced = 1;
- off = 0;
- goto tryagain;
- }
-
- if (((sap == 0) && (ip->ip_v != IP_VERSION))
-#if SOLARIS2 >= 8
- || ((sap == IP6_DL_SAP) && ((ip6->ip6_vfc >> 4) != 6))
-#endif
- ) {
- m->b_rptr -= off;
- return -2;
- }
-
-#ifndef sparc
-# if SOLARIS2 >= 8
- if (sap == IP6_DL_SAP) {
- ip6->ip6_plen = plen - sizeof(*ip6);
- } else {
-# endif
- __ipoff = (u_short)ip->ip_off;
-
- ip->ip_len = plen;
- ip->ip_off = ntohs(__ipoff);
-# if SOLARIS2 >= 8
- }
-# endif
-#endif
- if (sap == 0)
- iphlen = ip->ip_hl << 2;
-#if SOLARIS2 >= 8
- else if (sap == IP6_DL_SAP)
- iphlen = sizeof(ip6_t);
-#endif
-
- if ((
-#if SOLARIS2 >= 8
- (sap == IP6_DL_SAP) && (mlen < plen)) ||
- ((sap == 0) &&
-#endif
- ((iphlen < hlen) || (iphlen > plen) || (mlen < plen)))) {
- /*
- * Bad IP packet or not enough data/data length mismatches
- */
-#ifndef sparc
-# if SOLARIS2 >= 8
- if (sap == IP6_DL_SAP) {
- ip6->ip6_plen = htons(plen - sizeof(*ip6));
- } else {
-# endif
- __ipoff = (u_short)ip->ip_off;
-
- ip->ip_len = htons(plen);
- ip->ip_off = htons(__ipoff);
-# if SOLARIS2 >= 8
- }
-# endif
-#endif
- m->b_rptr -= off;
- frstats[out].fr_bad++;
- return -1;
- }
-
- /*
- * Make hlen the total size of the IP header plus TCP/UDP/ICMP header
- * (if it is one of these three).
- */
- if (sap == 0)
- p = ip->ip_p;
-#if SOLARIS2 >= 8
- else if (sap == IP6_DL_SAP)
- p = ip6->ip6_nxt;
-
- if ((sap == IP6_DL_SAP) || ((ip->ip_off & IP_OFFMASK) == 0))
-#else
- if ((ip->ip_off & IP_OFFMASK) == 0)
-#endif
- switch (p)
- {
- case IPPROTO_TCP :
- hlen += sizeof(tcphdr_t);
- break;
- case IPPROTO_UDP :
- hlen += sizeof(udphdr_t);
- break;
- case IPPROTO_ICMP :
- /* 76 bytes is enough for a complete ICMP error. */
- hlen += 76 + sizeof(icmphdr_t);
- break;
- default :
- break;
- }
-
- woff = 0;
- if (hlen > mlen) {
- hlen = mlen;
- } else if (m->b_wptr - m->b_rptr > plen) {
- woff = m->b_wptr - m->b_rptr - plen;
- m->b_wptr -= woff;
- }
-
- /*
- * If we don't have enough data in the mblk or we haven't yet copied
- * enough (above), then copy some more.
- */
- if ((hlen > len)) {
- if (!pullupmsg(m, (int)hlen)) {
- cmn_err(CE_NOTE, "pullupmsg failed");
- frstats[out].fr_pull[1]++;
- return -1;
- }
- frstats[out].fr_pull[0]++;
- ip = (ip_t *)ALIGN32(m->b_rptr);
- }
- qif->qf_m = m;
- qif->qf_q = q;
- qif->qf_off = off;
- qif->qf_len = len;
- err = fr_check(ip, iphlen, qif->qf_ill, out, qif, mp);
- if (err == 2) {
- goto fixalign;
- }
- /*
- * Copy back the ip header data if it was changed, we haven't yet
- * freed the message and we aren't going to drop the packet.
- * BUT only do this if there were no changes to the buffer, else
- * we can't be sure that the ip pointer is still correct!
- */
- if (*mp != NULL) {
- if (*mp == mt) {
- m->b_wptr += woff;
- m->b_rptr -= off;
-#ifndef sparc
-# if SOLARIS2 >= 8
- if (sap == IP6_DL_SAP) {
- ip6->ip6_plen = htons(plen - sizeof(*ip6));
- } else {
-# endif
- __ipoff = (u_short)ip->ip_off;
- /*
- * plen is useless because of NAT.
- */
- ip->ip_len = htons(ip->ip_len);
- ip->ip_off = htons(__ipoff);
-# if SOLARIS2 >= 8
- }
-# endif
-#endif
- } else
- cmn_err(CE_NOTE,
- "!IP Filter: *mp %p mt %p %s", *mp, mt,
- "mblk changed, cannot revert ip_len, ip_off");
- }
- return err;
-}
-
-
-/*
- * Only called for M_IOCACK messages
- */
-void fr_qif_update(qif, mp)
-qif_t *qif;
-mblk_t *mp;
-{
- struct iocblk *iocp;
-
- if (!qif || !mp)
- return;
- iocp = (struct iocblk *)mp->b_rptr;
- if (mp->b_cont && (iocp->ioc_cmd == DL_IOC_HDR_INFO)) {
- mp = mp->b_cont;
- if (MTYPE(mp) == M_PROTO && mp->b_cont) {
- mp = mp->b_cont;
- if (MTYPE(mp) == M_DATA) {
- qif->qf_hl = mp->b_wptr - mp->b_rptr;
- }
- }
- }
-}
-
-
-int fr_qin(q, mb)
-queue_t *q;
-mblk_t *mb;
-{
- int (*pnext) __P((queue_t *, mblk_t *)), type, synced = 0, err = 0;
- qif_t qf, *qif;
-
-#ifdef IPFDEBUG_VERBOSE
- if (ipf_debug_verbose)
- cmn_err(CE_CONT,
- "fr_qin(%lx,%lx) ptr %lx type 0x%x ref %d len %d\n",
- q, q->q_ptr, mb, MTYPE(mb), mb->b_datap->db_ref,
- msgdsize(mb));
-#endif
-
- /*
- * IPFilter is still in the packet path but not enabled. Drop whatever
- * it is that has come through.
- */
- if (fr_running <= 0) {
- mb->b_prev = NULL;
- freemsg(mb);
- return 0;
- }
-
- type = MTYPE(mb);
-
- /*
- * If a mblk has more than one reference, make a copy, filter that and
- * free a reference to the original.
- */
- if (mb->b_datap->db_ref > 1) {
- mblk_t *m1;
-
- m1 = copymsg(mb);
- if (!m1) {
- frstats[0].fr_drop++;
- mb->b_prev = NULL;
- freemsg(mb);
- return 0;
- }
- mb->b_prev = NULL;
- freemsg(mb);
- mb = m1;
- frstats[0].fr_copy++;
- }
-
- READ_ENTER(&ipf_solaris);
-again:
- if (fr_running <= 0) {
- mb->b_prev = NULL;
- freemsg(mb);
- RWLOCK_EXIT(&ipf_solaris);
- return 0;
- }
- READ_ENTER(&ipfs_mutex);
- if (!(qif = qif_from_queue(q))) {
- for (qif = qif_head; qif; qif = qif->qf_next)
- if (&qif->qf_rqinit == q->q_qinfo && qif->qf_rqinfo &&
- qif->qf_rqinfo->qi_putp) {
- pnext = qif->qf_rqinfo->qi_putp;
- frstats[0].fr_notip++;
- RWLOCK_EXIT(&ipfs_mutex);
- if (!synced) {
- ipfsync();
- synced = 1;
- goto again;
- }
- RWLOCK_EXIT(&ipf_solaris);
- /* fr_donotip(0, NULL, q, mb, mb, NULL, 0); */
- return (*pnext)(q, mb);
- }
- RWLOCK_EXIT(&ipfs_mutex);
- if (!synced) {
- ipfsync();
- synced = 1;
- goto again;
- }
- cmn_err(CE_WARN,
- "!IP Filter: dropped: fr_qin(%x,%x): type %x qif %x",
- q, mb, type, qif);
- cmn_err(CE_CONT,
- "!IP Filter: info %x next %x ptr %x fsrv %x bsrv %x\n",
- q->q_qinfo, q->q_next, q->q_ptr, q->q_nfsrv,
- q->q_nbsrv);
- cmn_err(CE_CONT, "!IP Filter: info: putp %x srvp %x info %x\n",
- q->q_qinfo->qi_putp, q->q_qinfo->qi_srvp,
-#if SOLARIS > 3
- q->q_qinfo->qi_infop
-#else
- 0
-#endif
- );
- frstats[0].fr_drop++;
- mb->b_prev = NULL;
- freemsg(mb);
- RWLOCK_EXIT(&ipf_solaris);
- return 0;
- }
-
- qif->qf_incnt++;
- pnext = qif->qf_rqinfo->qi_putp;
- if (type == M_IOCACK)
- fr_qif_update(qif, mb);
- bcopy((char *)qif, (char *)&qf, sizeof(qf));
- if (datamsg(type) || (type == M_BREAK))
- err = fr_precheck(&mb, q, &qf, 0);
-
- RWLOCK_EXIT(&ipfs_mutex);
-
- if ((err == 0) && (mb != NULL)) {
- if (pnext) {
- RWLOCK_EXIT(&ipf_solaris);
- return (*pnext)(q, mb);
- }
-
- cmn_err(CE_WARN,
- "!IP Filter: inp NULL: qif %x %s q %x info %x",
- qif, qf.qf_name, q, q->q_qinfo);
- }
-
- if (err == -2) {
- if (synced == 0) {
- ipfsync();
- synced = 1;
- goto again;
- }
- frstats[0].fr_notip++;
- if (!(fr_flags & FF_BLOCKNONIP) && (pnext != NULL)) {
- RWLOCK_EXIT(&ipf_solaris);
- return (*pnext)(q, mb);
- }
- }
-
-
- if (mb) {
- mb->b_prev = NULL;
- freemsg(mb);
- }
- RWLOCK_EXIT(&ipf_solaris);
- return 1;
-}
-
-
-int fr_qout(q, mb)
-queue_t *q;
-mblk_t *mb;
-{
- int (*pnext) __P((queue_t *, mblk_t *)), type, synced = 0, err = 0;
- qif_t qf, *qif;
-
-#ifdef IPFDEBUG_VERBOSE
- if (ipf_debug_verbose)
- cmn_err(CE_CONT,
- "fr_qout(%lx,%lx) ptr %lx type 0x%x ref %d len %d\n",
- q, q->q_ptr, mb, MTYPE(mb), mb->b_datap->db_ref,
- msgdsize(mb));
-#endif
-
- if (fr_running <= 0) {
- mb->b_prev = NULL;
- freemsg(mb);
- return 0;
- }
-
- type = MTYPE(mb);
-
-#if SOLARIS2 >= 6
- if ((!dohwcksum || mb->b_ick_flag != ICK_VALID) &&
- (mb->b_datap->db_ref > 1))
-#else
- if (mb->b_datap->db_ref > 1)
-#endif
- {
- mblk_t *m1;
-
- m1 = copymsg(mb);
- if (!m1) {
- frstats[1].fr_drop++;
- mb->b_prev = NULL;
- freemsg(mb);
- return 0;
- }
- mb->b_prev = NULL;
- freemsg(mb);
- mb = m1;
- frstats[1].fr_copy++;
- }
-
- READ_ENTER(&ipf_solaris);
-again:
- if (fr_running <= 0) {
- mb->b_prev = NULL;
- freemsg(mb);
- RWLOCK_EXIT(&ipf_solaris);
- return 0;
- }
- READ_ENTER(&ipfs_mutex);
- if (!(qif = qif_from_queue(q))) {
- for (qif = qif_head; qif; qif = qif->qf_next)
- if (&qif->qf_wqinit == q->q_qinfo && qif->qf_wqinfo &&
- qif->qf_wqinfo->qi_putp) {
- pnext = qif->qf_wqinfo->qi_putp;
- RWLOCK_EXIT(&ipfs_mutex);
- frstats[1].fr_notip++;
- if (!synced) {
- ipfsync();
- synced = 1;
- goto again;
- }
- /* fr_donotip(1, NULL, q, mb, mb, NULL, 0); */
- RWLOCK_EXIT(&ipf_solaris);
- return (*pnext)(q, mb);
- }
- RWLOCK_EXIT(&ipfs_mutex);
- if (!synced) {
- ipfsync();
- synced = 1;
- goto again;
- }
- cmn_err(CE_WARN,
- "!IP Filter: dropped: fr_qout(%x,%x): type %x: qif %x",
- q, mb, type, qif);
- cmn_err(CE_CONT,
- "!IP Filter: info %x next %x ptr %x fsrv %x bsrv %x\n",
- q->q_qinfo, q->q_next, q->q_ptr, q->q_nfsrv,
- q->q_nbsrv);
- cmn_err(CE_CONT, "!IP Filter: info: putp %x srvp %x info %x\n",
- q->q_qinfo->qi_putp, q->q_qinfo->qi_srvp,
-#if SOLARIS > 3
- q->q_qinfo->qi_infop
-#else
- 0
-#endif
- );
- if (q->q_nfsrv)
- cmn_err(CE_CONT,
- "!IP Filter: nfsrv: info %x next %x ptr %x\n",
- q->q_nfsrv->q_qinfo, q->q_nfsrv->q_next,
- q->q_nfsrv->q_ptr);
- if (q->q_nbsrv)
- cmn_err(CE_CONT,
- "!IP Filter: nbsrv: info %x next %x ptr %x\n",
- q->q_nbsrv->q_qinfo, q->q_nbsrv->q_next,
- q->q_nbsrv->q_ptr);
- frstats[1].fr_drop++;
- mb->b_prev = NULL;
- freemsg(mb);
- RWLOCK_EXIT(&ipf_solaris);
- return 0;
- }
-
- qif->qf_outcnt++;
- pnext = qif->qf_wqinfo->qi_putp;
- if (type == M_IOCACK)
- fr_qif_update(qif, mb);
- bcopy((char *)qif, (char *)&qf, sizeof(qf));
- if (datamsg(type) || (type == M_BREAK))
- err = fr_precheck(&mb, q, &qf, 1);
-
- RWLOCK_EXIT(&ipfs_mutex);
-
- if ((err == 0) && (mb != NULL)) {
- if (pnext) {
- RWLOCK_EXIT(&ipf_solaris);
- return (*pnext)(q, mb);
- }
-
- cmn_err(CE_WARN,
- "!IP Filter: outp NULL: qif %x %s q %x info %x",
- qif, qf.qf_name, q, q->q_qinfo);
- }
-
- if (err == -2) {
- if (synced == 0) {
- ipfsync();
- synced = 1;
- goto again;
- }
- frstats[1].fr_notip++;
- if (!(fr_flags & FF_BLOCKNONIP) && (pnext != NULL)) {
- RWLOCK_EXIT(&ipf_solaris);
- return (*pnext)(q, mb);
- }
- }
-
- if (mb) {
- mb->b_prev = NULL;
- freemsg(mb);
- }
- RWLOCK_EXIT(&ipf_solaris);
- return 1;
-}
-
-
-void ipf_synctimeout(arg)
-void *arg;
-{
- if (fr_running < 0)
- return;
- READ_ENTER(&ipf_solaris);
- ipfsync();
- WRITE_ENTER(&ipfs_mutex);
- synctimeoutid = 0;
- RWLOCK_EXIT(&ipfs_mutex);
- RWLOCK_EXIT(&ipf_solaris);
-}
-
-
-static int ipf_ip_qin(q, mb)
-queue_t *q;
-mblk_t *mb;
-{
- struct iocblk *ioc;
- int ret;
-
- if (fr_running <= 0) {
- mb->b_prev = NULL;
- freemsg(mb);
- return 0;
- }
-
- if (MTYPE(mb) != M_IOCTL)
- return (*ipf_ip_inp)(q, mb);
-
- READ_ENTER(&ipf_solaris);
- if (fr_running <= 0) {
- RWLOCK_EXIT(&ipf_solaris);
- mb->b_prev = NULL;
- freemsg(mb);
- return 0;
- }
- ioc = (struct iocblk *)mb->b_rptr;
-
- switch (ioc->ioc_cmd)
- {
- case DL_IOC_HDR_INFO:
- fr_qif_update(qif_from_queue(q), mb);
- break;
- case I_LINK:
- case I_UNLINK:
- case SIOCSIFADDR:
- case SIOCSIFFLAGS:
-#ifdef IPFDEBUG
- if (ipf_debug)
- cmn_err(CE_NOTE,
- "IP Filter: ipf_ip_qin() M_IOCTL type=0x%x",
- ioc->ioc_cmd);
-#endif
- WRITE_ENTER(&ipfs_mutex);
- if (synctimeoutid == 0) {
- synctimeoutid = timeout(ipf_synctimeout,
- NULL,
- drv_usectohz(1000000) /*1 sec*/
- );
- }
- RWLOCK_EXIT(&ipfs_mutex);
- break;
- default:
- break;
- }
- RWLOCK_EXIT(&ipf_solaris);
- return (*ipf_ip_inp)(q, mb);
-}
-
-static int ipdrvattcnt = 0;
-extern struct streamtab ipinfo;
-
-void solipdrvattach()
-{
-#ifdef IPFDEBUG
- if (ipf_debug)
- cmn_err(CE_NOTE, "IP Filter: solipdrvattach() %d ipinfo=0x%lx",
- ipdrvattcnt, &ipinfo);
-#endif
-
- if (++ipdrvattcnt == 1) {
- if (ipf_ip_inp == NULL) {
- ipf_ip_inp = ipinfo.st_wrinit->qi_putp;
- ipinfo.st_wrinit->qi_putp = ipf_ip_qin;
- }
- }
-}
-
-int solipdrvdetach()
-{
-#ifdef IPFDEBUG
- if (ipf_debug)
- cmn_err(CE_NOTE, "IP Filter: solipdrvdetach() %d ipinfo=0x%lx",
- ipdrvattcnt, &ipinfo);
-#endif
-
- WRITE_ENTER(&ipfs_mutex);
- if (--ipdrvattcnt <= 0) {
- if (ipf_ip_inp && (ipinfo.st_wrinit->qi_putp == ipf_ip_qin)) {
- ipinfo.st_wrinit->qi_putp = ipf_ip_inp;
- ipf_ip_inp = NULL;
- }
- if (synctimeoutid) {
- untimeout(synctimeoutid);
- synctimeoutid = 0;
- }
- }
- RWLOCK_EXIT(&ipfs_mutex);
- return ipdrvattcnt;
-}
-
-/*
- * attach the packet filter to each interface that is defined as having an
- * IP address associated with it and save some of the info. for that struct
- * so we're not out of date as soon as the ill disappears - but we must sync
- * to be correct!
- */
-void solattach()
-{
- queue_t *in, *out;
- struct frentry *f;
- qif_t *qif, *qf2;
- ipnat_t *np;
- size_t len;
- ill_t *il;
-
- for (il = ill_g_head; il; il = il->ill_next) {
- in = il->ill_rq;
- if (!in || !il->ill_wq)
- continue;
-
- out = il->ill_wq->q_next;
-
- WRITE_ENTER(&ipfs_mutex);
- /*
- * Look for entry already setup for this device
- */
- for (qif = qif_head; qif; qif = qif->qf_next)
- if (qif->qf_iptr == in->q_ptr &&
- qif->qf_optr == out->q_ptr)
- break;
- if (qif) {
- RWLOCK_EXIT(&ipfs_mutex);
- continue;
- }
-#ifdef IPFDEBUGX
- if (ipf_debug)
- cmn_err(CE_NOTE,
- "IP Filter: il %x ipt %x opt %x ipu %x opu %x i %x/%x",
- il, in->q_ptr, out->q_ptr, in->q_qinfo->qi_putp,
- out->q_qinfo->qi_putp, out->q_qinfo, in->q_qinfo);
-#endif
- KMALLOC(qif, qif_t *);
- if (!qif) {
- cmn_err(CE_WARN,
- "IP Filter: malloc(%d) for qif_t failed",
- sizeof(qif_t));
- RWLOCK_EXIT(&ipfs_mutex);
- continue;
- }
-
- if (in->q_qinfo->qi_putp == fr_qin) {
- for (qf2 = qif_head; qf2; qf2 = qf2->qf_next)
- if (&qf2->qf_rqinit == in->q_qinfo) {
- qif->qf_rqinfo = qf2->qf_rqinfo;
- break;
- }
- if (!qf2) {
-#ifdef IPFDEBUGX
- if (ipf_debug)
- cmn_err(CE_WARN,
- "IP Filter: rq:%s put %x qi %x",
- il->ill_name, in->q_qinfo->qi_putp,
- in->q_qinfo);
-#endif
- RWLOCK_EXIT(&ipfs_mutex);
- KFREE(qif);
- continue;
- }
- } else
- qif->qf_rqinfo = in->q_qinfo;
-
- if (out->q_qinfo->qi_putp == fr_qout) {
- for (qf2 = qif_head; qf2; qf2 = qf2->qf_next)
- if (&qf2->qf_wqinit == out->q_qinfo) {
- qif->qf_wqinfo = qf2->qf_wqinfo;
- break;
- }
- if (!qf2) {
-#ifdef IPFDEBUGX
- if (ipf_debug)
- cmn_err(CE_WARN,
- "IP Filter: wq:%s put %x qi %x",
- il->ill_name, out->q_qinfo->qi_putp,
- out->q_qinfo);
-#endif
- RWLOCK_EXIT(&ipfs_mutex);
- KFREE(qif);
- continue;
- }
- } else
- qif->qf_wqinfo = out->q_qinfo;
-
- qif->qf_ill = il;
- qif->qf_in = in;
- qif->qf_out = out;
- qif->qf_iptr = in->q_ptr;
- qif->qf_optr = out->q_ptr;
-#if SOLARIS2 < 8
- qif->qf_hl = il->ill_hdr_length;
-#else
- {
- ire_t *ire;
- mblk_t *m;
-
- qif->qf_hl = 0;
- qif->qf_sap = il->ill_sap;
-# if 0
- /*
- * Can't seem to lookup a route for the IP address on the
- * interface itself.
- */
- ire = ire_route_lookup(il->ill_ipif->ipif_lcl_addr, 0xffffffff,
- 0, 0, NULL, NULL, NULL,
- MATCH_IRE_DSTONLY|MATCH_IRE_RECURSIVE);
- if ((ire != NULL) && (m = ire->ire_fp_mp))
- qif->qf_hl = m->b_wptr - m->b_rptr;
-# endif
- if ((qif->qf_hl == 0) && (il->ill_type > 0) &&
- (il->ill_type < 0x37) &&
- (hdrsizes[il->ill_type][0] == il->ill_type))
- qif->qf_hl = hdrsizes[il->ill_type][1];
-
- /* DREADFUL VLAN HACK - JUST HERE TO CHECK IT WORKS */
- if (il->ill_type == IFT_ETHER &&
- il->ill_name[0] == 'c' && il->ill_name[1] == 'e' &&
- isdigit(il->ill_name[2]) && il->ill_name_length >= 6) {
- cmn_err(CE_NOTE, "VLAN HACK ENABLED");
- qif->qf_hl += 4;
- }
- /* DREADFUL VLAN HACK - JUST HERE TO CHECK IT WORKS */
-
- if (qif->qf_hl == 0 && il->ill_type != IFT_OTHER)
- cmn_err(CE_WARN,
- "Unknown layer 2 header size for %s type %d",
- il->ill_name, il->ill_type);
- }
-
- /*
- * XXX Awful hack for PPP; fix when PPP/snoop fixed.
- */
- if (il->ill_type == IFT_ETHER && !il->ill_bcast_addr_length)
- qif->qf_hl = 0;
-#endif
- strncpy(qif->qf_name, il->ill_name, sizeof(qif->qf_name));
- qif->qf_name[sizeof(qif->qf_name) - 1] = '\0';
-
- qif->qf_next = qif_head;
- qif_head = qif;
-
- /*
- * Activate any rules directly associated with this interface
- */
- WRITE_ENTER(&ipf_mutex);
- for (f = ipfilter[0][fr_active]; f; f = f->fr_next) {
- if ((f->fr_ifa == (struct ifnet *)-1)) {
- len = strlen(f->fr_ifname) + 1;
- if ((len != 0) &&
- (len == (size_t)il->ill_name_length) &&
- !strncmp(il->ill_name, f->fr_ifname, len))
- f->fr_ifa = il;
- }
- }
- for (f = ipfilter[1][fr_active]; f; f = f->fr_next) {
- if ((f->fr_ifa == (struct ifnet *)-1)) {
- len = strlen(f->fr_ifname) + 1;
- if ((len != 0) &&
- (len == (size_t)il->ill_name_length) &&
- !strncmp(il->ill_name, f->fr_ifname, len))
- f->fr_ifa = il;
- }
- }
-#if SOLARIS2 >= 8
- for (f = ipfilter6[0][fr_active]; f; f = f->fr_next) {
- if ((f->fr_ifa == (struct ifnet *)-1)) {
- len = strlen(f->fr_ifname) + 1;
- if ((len != 0) &&
- (len == (size_t)il->ill_name_length) &&
- !strncmp(il->ill_name, f->fr_ifname, len))
- f->fr_ifa = il;
- }
- }
- for (f = ipfilter6[1][fr_active]; f; f = f->fr_next) {
- if ((f->fr_ifa == (struct ifnet *)-1)) {
- len = strlen(f->fr_ifname) + 1;
- if ((len != 0) &&
- (len == (size_t)il->ill_name_length) &&
- !strncmp(il->ill_name, f->fr_ifname, len))
- f->fr_ifa = il;
- }
- }
-#endif
- RWLOCK_EXIT(&ipf_mutex);
- WRITE_ENTER(&ipf_nat);
- for (np = nat_list; np; np = np->in_next) {
- if ((np->in_ifp == (struct ifnet *)-1)) {
- len = strlen(np->in_ifname) + 1;
- if ((len != 0) &&
- (len == (size_t)il->ill_name_length) &&
- !strncmp(il->ill_name, np->in_ifname, len))
- np->in_ifp = il;
- }
- }
- RWLOCK_EXIT(&ipf_nat);
-
- bcopy((caddr_t)qif->qf_rqinfo, (caddr_t)&qif->qf_rqinit,
- sizeof(struct qinit));
- qif->qf_rqinit.qi_putp = fr_qin;
-#ifdef IPFDEBUG
- if (ipf_debug)
- cmn_err(CE_NOTE,
- "IP Filter: solattach: in queue(%lx)->q_qinfo FROM %lx TO %lx",
- in, in->q_qinfo, &qif->qf_rqinit);
-#endif
- in->q_qinfo = &qif->qf_rqinit;
-
- bcopy((caddr_t)qif->qf_wqinfo, (caddr_t)&qif->qf_wqinit,
- sizeof(struct qinit));
- qif->qf_wqinit.qi_putp = fr_qout;
-#ifdef IPFDEBUG
- if (ipf_debug)
- cmn_err(CE_NOTE,
- "IP Filter: solattach: out queue(%lx)->q_qinfo FROM %lx TO %lx",
- out, out->q_qinfo, &qif->qf_wqinit);
-#endif
- out->q_qinfo = &qif->qf_wqinit;
-
- ire_walk(ipf_ire_walk, (char *)qif);
- RWLOCK_EXIT(&ipfs_mutex);
- cmn_err(CE_CONT, "IP Filter: attach to [%s,%d] - %s\n",
- qif->qf_name, il->ill_ppa,
-#if SOLARIS2 >= 8
- il->ill_isv6 ? "IPv6" : "IPv4"
-#else
- "IPv4"
-#endif
- );
- }
- if (!qif_head)
- cmn_err(CE_CONT, "IP Filter: not attached to any interfaces\n");
- return;
-}
-
-
-/*
- * look for bad consistancies between the list of interfaces the filter knows
- * about and those which are currently configured.
- */
-int ipfsync()
-{
- register struct frentry *f;
- register ipnat_t *np;
- register qif_t *qif, **qp;
- register ill_t *il;
- queue_t *in, *out;
-
- WRITE_ENTER(&ipfs_mutex);
- for (qp = &qif_head; (qif = *qp); ) {
- for (il = ill_g_head; il; il = il->ill_next)
- if ((qif->qf_ill == il) &&
- !strcmp(qif->qf_name, il->ill_name)) {
-#if SOLARIS2 < 8
- mblk_t *m = il->ill_hdr_mp;
-
- qif->qf_hl = il->ill_hdr_length;
- if (m && qif->qf_hl != (m->b_wptr - m->b_rptr))
- cmn_err(CE_NOTE,
- "IP Filter: ILL Header Length Mismatch\n");
-#endif
- break;
- }
- if (il) {
- qp = &qif->qf_next;
- continue;
- }
- cmn_err(CE_CONT, "IP Filter: detaching [%s] - %s\n",
- qif->qf_name,
-#if SOLARIS2 >= 8
- (qif->qf_sap == IP6_DL_SAP) ? "IPv6" : "IPv4"
-#else
- "IPv4"
-#endif
- );
- *qp = qif->qf_next;
-
- /*
- * Disable any rules directly associated with this interface
- */
- WRITE_ENTER(&ipf_nat);
- for (np = nat_list; np; np = np->in_next)
- if (np->in_ifp == (void *)qif->qf_ill)
- np->in_ifp = (struct ifnet *)-1;
- RWLOCK_EXIT(&ipf_nat);
- WRITE_ENTER(&ipf_mutex);
- for (f = ipfilter[0][fr_active]; f; f = f->fr_next)
- if (f->fr_ifa == (void *)qif->qf_ill)
- f->fr_ifa = (struct ifnet *)-1;
- for (f = ipfilter[1][fr_active]; f; f = f->fr_next)
- if (f->fr_ifa == (void *)qif->qf_ill)
- f->fr_ifa = (struct ifnet *)-1;
-#if SOLARIS2 >= 8
- for (f = ipfilter6[0][fr_active]; f; f = f->fr_next)
- if (f->fr_ifa == (void *)qif->qf_ill)
- f->fr_ifa = (struct ifnet *)-1;
- for (f = ipfilter6[1][fr_active]; f; f = f->fr_next)
- if (f->fr_ifa == (void *)qif->qf_ill)
- f->fr_ifa = (struct ifnet *)-1;
-#endif
-
-#if 0 /* XXX */
- /*
- * As well as the ill disappearing when a device is unplumb'd,
- * it also appears that the associated queue structures also
- * disappear - at least in the case of ppp, which is the most
- * volatile here. Thanks to Greg for finding this problem.
- */
- /*
- * Restore q_qinfo pointers in interface queues
- */
- out = qif->qf_out;
- in = qif->qf_in;
- if (in) {
-# ifdef IPFDEBUG
- if (ipf_debug)
- cmn_err(CE_NOTE,
- "IP Filter: ipfsync: in queue(%lx)->q_qinfo FROM %lx TO %lx",
- in, in->q_qinfo, qif->qf_rqinfo);
-# endif
- in->q_qinfo = qif->qf_rqinfo;
- }
- if (out) {
-# ifdef IPFDEBUG
- if (ipf_debug)
- cmn_err(CE_NOTE,
- "IP Filter: ipfsync: out queue(%lx)->q_qinfo FROM %lx TO %lx",
- out, out->q_qinfo, qif->qf_wqinfo);
-# endif
- out->q_qinfo = qif->qf_wqinfo;
- }
-#endif /* XXX */
- RWLOCK_EXIT(&ipf_mutex);
- KFREE(qif);
- qif = *qp;
- }
- RWLOCK_EXIT(&ipfs_mutex);
- solattach();
-
- frsync();
- /*
- * Resync. any NAT `connections' using this interface and its IP #.
- */
- for (il = ill_g_head; il; il = il->ill_next) {
- ip_natsync((void *)il);
- ip_statesync((void *)il);
- }
- return 0;
-}
-
-
-/*
- * unhook the IP filter from all defined interfaces with IP addresses
- */
-int soldetach()
-{
- queue_t *in, *out;
- qif_t *qif, **qp;
- ill_t *il;
-
- WRITE_ENTER(&ipfs_mutex);
- /*
- * Make two passes, first get rid of all the unknown devices, next
- * unlink known devices.
- */
- for (qp = &qif_head; (qif = *qp); ) {
- for (il = ill_g_head; il; il = il->ill_next)
- if (qif->qf_ill == il)
- break;
- if (il) {
- qp = &qif->qf_next;
- continue;
- }
- cmn_err(CE_CONT, "IP Filter: removing [%s]\n", qif->qf_name);
- *qp = qif->qf_next;
- KFREE(qif);
- }
-
- while ((qif = qif_head)) {
- qif_head = qif->qf_next;
- for (il = ill_g_head; il; il = il->ill_next)
- if (qif->qf_ill == il)
- break;
- if (il) {
- in = qif->qf_in;
- out = qif->qf_out;
- cmn_err(CE_CONT, "IP Filter: detaching [%s,%d] - %s\n",
- qif->qf_name, il->ill_ppa,
-#if SOLARIS2 >= 8
- (qif->qf_sap == IP6_DL_SAP) ? "IPv6" : "IPv4"
-#else
- "IPv4"
-#endif
- );
-
-#ifdef IPFDEBUG
- if (ipf_debug)
- cmn_err(CE_NOTE,
- "IP Filter: soldetach: in queue(%lx)->q_qinfo FROM %lx TO %lx",
- in, in->q_qinfo, qif->qf_rqinfo);
-#endif
- in->q_qinfo = qif->qf_rqinfo;
-
- /*
- * and the write queue...
- */
-#ifdef IPFDEBUG
- if (ipf_debug)
- cmn_err(CE_NOTE,
- "IP Filter: soldetach: out queue(%lx)->q_qinfo FROM %lx TO %lx",
- out, out->q_qinfo, qif->qf_wqinfo);
-#endif
- out->q_qinfo = qif->qf_wqinfo;
- }
- KFREE(qif);
- }
- RWLOCK_EXIT(&ipfs_mutex);
- return ipldetach();
-}
-
-
-#ifdef IPFDEBUG
-void printire(ire)
-ire_t *ire;
-{
- if (!ipf_debug)
- return;
- 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
-
-
-int ipfr_fastroute(ip, mb, mpp, fin, fdp)
-ip_t *ip;
-mblk_t *mb, **mpp;
-fr_info_t *fin;
-frdest_t *fdp;
-{
-#ifdef USE_INET6
- ip6_t *ip6 = (ip6_t *)ip;
-#endif
- ire_t *ir, *dir, *gw;
- struct in_addr dst;
- queue_t *q = NULL;
- mblk_t *mp = NULL;
- size_t hlen = 0;
- frentry_t *fr;
- frdest_t fd;
- ill_t *ifp;
- u_char *s;
- qif_t *qf;
- int p;
-
-#ifndef sparc
- u_short __iplen, __ipoff;
-#endif
- 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.
- */
- if ((ip == (ip_t *)qf->qf_m->b_rptr) && (qf->qf_m != mb))
- ip = (ip_t *)mb->b_rptr;
-
- /*
- * If there is another M_PROTO, we don't want it
- */
- if (*mpp != mb) {
- mp = *mpp;
- (void) unlinkb(mp);
- mp = (*mpp)->b_cont;
- (*mpp)->b_cont = NULL;
- (*mpp)->b_prev = NULL;
- freemsg(*mpp);
- *mpp = mp;
- }
-
- 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
- gw = NULL;
- if (fin->fin_v == 4) {
- p = ip->ip_p;
- dir = ire_route_lookup(dst.s_addr, 0xffffffff, 0, 0, NULL,
- &gw, NULL, MATCH_IRE_DSTONLY|
- MATCH_IRE_DEFAULT|MATCH_IRE_RECURSIVE);
- }
-# ifdef USE_INET6
- else if (fin->fin_v == 6) {
- p = ip6->ip6_nxt;
- dir = ire_route_lookup_v6(&ip6->ip6_dst, NULL, 0, 0,
- NULL, &gw, 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) {
- ifp = ire_to_ill(ir);
- if (ifp == NULL)
- goto bad_fastroute;
- fr = fin->fin_fr;
-
- /*
- * In case we're here due to "to <if>" being used with
- * "keep state", check that we're going in the correct
- * direction.
- */
- if ((fr != NULL) && (fdp->fd_ifp != NULL) &&
- (fin->fin_rev != 0) && (fdp == &fr->fr_tif))
- return 1;
-
- fin->fin_ifp = ifp;
- if (fin->fin_out == 0) {
- fin->fin_fr = ipacct[1][fr_active];
- if ((fin->fin_fr != NULL) &&
- (fr_scanlist(FR_NOMATCH, ip, fin, mb)&FR_ACCOUNT)){
- ATOMIC_INCL(frstats[1].fr_acct);
- }
- fin->fin_fr = NULL;
- if (!fr || !(fr->fr_flags & FR_RETMASK))
- (void) fr_checkstate(ip, fin);
- (void) ip_natout(ip, fin);
- }
-#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
-
-#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;
- 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;
- }
- }
- *mpp = mb;
-
- if (ir->ire_stq)
- q = ir->ire_stq;
- else if (ir->ire_rfq)
- q = WR(ir->ire_rfq);
- if (q) {
- mb->b_prev = NULL;
- mb->b_queue = q;
- RWLOCK_EXIT(&ipfs_mutex);
- RWLOCK_EXIT(&ipf_solaris);
-#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
- putnext(q, mb);
- READ_ENTER(&ipf_solaris);
- READ_ENTER(&ipfs_mutex);
- ipl_frouteok[0]++;
- *mpp = NULL;
- return 0;
- }
- }
-bad_fastroute:
- mb->b_prev = NULL;
- freemsg(mb);
- ipl_frouteok[1]++;
- *mpp = NULL;
- return -1;
-}
-
-
-void copyout_mblk(m, off, len, buf)
-mblk_t *m;
-size_t off, len;
-char *buf;
-{
- u_char *s, *bp = (u_char *)buf;
- size_t mlen, olen, clen;
-
- for (; m && len; m = m->b_cont) {
- if (MTYPE(m) != M_DATA)
- continue;
- s = m->b_rptr;
- mlen = m->b_wptr - s;
- olen = MIN(off, mlen);
- if ((olen == mlen) || (olen < off)) {
- off -= olen;
- continue;
- } else if (olen) {
- off -= olen;
- s += olen;
- mlen -= olen;
- }
- clen = MIN(mlen, len);
- bcopy(s, bp, clen);
- len -= clen;
- bp += clen;
- }
-}
-
-
-void copyin_mblk(m, off, len, buf)
-mblk_t *m;
-size_t off, len;
-char *buf;
-{
- u_char *s, *bp = (u_char *)buf;
- size_t mlen, olen, clen;
-
- for (; m && len; m = m->b_cont) {
- if (MTYPE(m) != M_DATA)
- continue;
- s = m->b_rptr;
- mlen = m->b_wptr - s;
- olen = MIN(off, mlen);
- if ((olen == mlen) || (olen < off)) {
- off -= olen;
- continue;
- } else if (olen) {
- off -= olen;
- s += olen;
- mlen -= olen;
- }
- clen = MIN(mlen, len);
- bcopy(bp, s, clen);
- len -= clen;
- bp += clen;
- }
-}
-
-
-int fr_verifysrc(ipa, ifp)
-struct in_addr ipa;
-void *ifp;
-{
- ire_t *ir, *dir, *gw;
-
-#if SOLARIS2 >= 6
- dir = ire_route_lookup(ipa.s_addr, 0xffffffff, 0, 0, NULL, &gw, NULL,
- MATCH_IRE_DSTONLY|MATCH_IRE_DEFAULT|
- MATCH_IRE_RECURSIVE);
-#else
- dir = ire_lookup(ipa.s_addr);
-#endif
-
- if (!dir)
- return 0;
- return (ire_to_ill(dir) == ifp);
-}
OpenPOWER on IntegriCloud