Annotation of XNU/bsd/netinet/fil.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * The contents of this file constitute Original Code as defined in and
        !             7:  * are subject to the Apple Public Source License Version 1.1 (the
        !             8:  * "License").  You may not use this file except in compliance with the
        !             9:  * License.  Please obtain a copy of the License at
        !            10:  * http://www.apple.com/publicsource and read it before using this file.
        !            11:  * 
        !            12:  * This Original Code and all software distributed under the License are
        !            13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            17:  * License for the specific language governing rights and limitations
        !            18:  * under the License.
        !            19:  * 
        !            20:  * @APPLE_LICENSE_HEADER_END@
        !            21:  */
        !            22: /*
        !            23:  * Copyright (C) 1993-1997 by Darren Reed.
        !            24:  *
        !            25:  * Redistribution and use in source and binary forms are permitted
        !            26:  * provided that this notice is preserved and due credit is given
        !            27:  * to the original author and the contributors.
        !            28:  */
        !            29: #if !defined(lint)
        !            30: /* static const char sccsid[] = "@(#)fil.c     1.36 6/5/96 (C) 1993-1996 Darren Reed"; */
        !            31: #endif
        !            32: 
        !            33: #include "opt_ipfilter.h"
        !            34: 
        !            35: #include <sys/errno.h>
        !            36: #include <sys/types.h>
        !            37: #include <sys/param.h>
        !            38: #include <sys/time.h>
        !            39: #include <sys/file.h>
        !            40: #if !defined(__FreeBSD__)
        !            41: # include <sys/ioctl.h>
        !            42: #endif
        !            43: 
        !            44: # include <sys/systm.h>
        !            45: 
        !            46: #include <sys/uio.h>
        !            47: #if !defined(__SVR4) && !defined(__svr4__)
        !            48: # ifndef linux
        !            49: #  include <sys/mbuf.h>
        !            50: # endif
        !            51: #else
        !            52: # include <sys/byteorder.h>
        !            53: # include <sys/dditypes.h>
        !            54: # include <sys/stream.h>
        !            55: #endif
        !            56: #if defined(__FreeBSD__)
        !            57: # include <sys/malloc.h>
        !            58: #endif
        !            59: #ifndef linux
        !            60: # include <sys/protosw.h>
        !            61: # include <sys/socket.h>
        !            62: #endif
        !            63: #include <net/if.h>
        !            64: #ifdef sun
        !            65: # include <net/af.h>
        !            66: #endif
        !            67: #include <net/route.h>
        !            68: #include <netinet/in.h>
        !            69: #include <netinet/in_systm.h>
        !            70: #include <netinet/ip.h>
        !            71: #ifndef linux
        !            72: # include <netinet/ip_var.h>
        !            73: #endif
        !            74: #include <netinet/tcp.h>
        !            75: #include <netinet/udp.h>
        !            76: #include <netinet/ip_icmp.h>
        !            77: #include "netinet/ip_compat.h"
        !            78: #include <netinet/tcpip.h>
        !            79: #include "netinet/ip_fil.h"
        !            80: #include "netinet/ip_proxy.h"
        !            81: #include "netinet/ip_nat.h"
        !            82: #include "netinet/ip_frag.h"
        !            83: #include "netinet/ip_state.h"
        !            84: #include "netinet/ip_auth.h"
        !            85: #ifndef        MIN
        !            86: #define        MIN(a,b)        (((a)<(b))?(a):(b))
        !            87: #endif
        !            88: 
        !            89: #ifndef        KERNEL
        !            90: # include "ipf.h"
        !            91: # include "ipt.h"
        !            92: extern int     opts;
        !            93: 
        !            94: # define       FR_IFVERBOSE(ex,second,verb_pr) if (ex) { verbose verb_pr; \
        !            95:                                                          second; }
        !            96: # define       FR_IFDEBUG(ex,second,verb_pr)   if (ex) { debug verb_pr; \
        !            97:                                                          second; }
        !            98: # define       FR_VERBOSE(verb_pr)                     verbose verb_pr
        !            99: # define       FR_DEBUG(verb_pr)                       debug verb_pr
        !           100: # define       SEND_RESET(ip, qif, if, m)              send_reset(ip, if)
        !           101: # define       IPLLOG(a, c, d, e)              ipllog()
        !           102: #  define      FR_NEWAUTH(m, fi, ip, qif)      fr_newauth((mb_t *)m, fi, ip)
        !           103: # if SOLARIS
        !           104: #  define      ICMP_ERROR(b, ip, t, c, if, src)        icmp_error(ip)
        !           105: # else
        !           106: #  define      ICMP_ERROR(b, ip, t, c, if, src)        icmp_error(b, ip, if)
        !           107: # endif
        !           108: #else /* #ifndef KERNEL */
        !           109: # define       FR_IFVERBOSE(ex,second,verb_pr) ;
        !           110: # define       FR_IFDEBUG(ex,second,verb_pr)   ;
        !           111: # define       FR_VERBOSE(verb_pr)
        !           112: # define       FR_DEBUG(verb_pr)
        !           113: # define       IPLLOG(a, c, d, e)              ipflog(a, c, d, e)
        !           114: # if SOLARIS || defined(__sgi)
        !           115: extern kmutex_t        ipf_mutex, ipf_auth;
        !           116: # endif
        !           117: # if SOLARIS
        !           118: #  define      FR_NEWAUTH(m, fi, ip, qif)      fr_newauth((mb_t *)m, fi, \
        !           119:                                                           ip, qif)
        !           120: #  define      SEND_RESET(ip, qif, if)         send_reset(ip, qif)
        !           121: #  define      ICMP_ERROR(b, ip, t, c, if, src) \
        !           122:                        icmp_error(ip, t, c, if, src)
        !           123: # else /* SOLARIS */
        !           124: #  define      FR_NEWAUTH(m, fi, ip, qif)      fr_newauth((mb_t *)m, fi, ip)
        !           125: #  ifdef linux
        !           126: #   define     SEND_RESET(ip, qif, if)         send_reset((tcpiphdr_t *)ip,\
        !           127:                                                           ifp)
        !           128: #  else
        !           129: #   define     SEND_RESET(ip, qif, if)         send_reset((tcpiphdr_t *)ip)
        !           130: #  endif
        !           131: #  ifdef __sgi
        !           132: #   define     ICMP_ERROR(b, ip, t, c, if, src) \
        !           133:                        icmp_error(b, t, c, if, src, if)
        !           134: #  else
        !           135: #   if BSD < 199103
        !           136: #    ifdef linux
        !           137: #     define   ICMP_ERROR(b, ip, t, c, if, src)        icmp_send(b,t,c,0,if)
        !           138: #    else
        !           139: #     define   ICMP_ERROR(b, ip, t, c, if, src) \
        !           140:                        icmp_error(mtod(b, ip_t *), t, c, if, src)
        !           141: #    endif /* linux */
        !           142: #   else
        !           143: #    define    ICMP_ERROR(b, ip, t, c, if, src) \
        !           144:                        icmp_error(b, t, c, (src).s_addr, if)
        !           145: #   endif /* BSD < 199103 */
        !           146: #  endif /* __sgi */
        !           147: # endif /* SOLARIS || __sgi */
        !           148: #endif /* KERNEL */
        !           149: 
        !           150: 
        !           151: struct filterstats frstats[2] = {{0,0,0,0,0},{0,0,0,0,0}};
        !           152: struct frentry *ipfilter[2][2] = { { NULL, NULL }, { NULL, NULL } },
        !           153:                *ipacct[2][2] = { { NULL, NULL }, { NULL, NULL } };
        !           154: struct frgroup *ipfgroups[3][2];
        !           155: int    fr_flags = IPF_LOGGING, fr_active = 0;
        !           156: #if defined(IPFILTER_DEFAULT_BLOCK)
        !           157: int    fr_pass = FR_NOMATCH|FR_BLOCK;
        !           158: #else
        !           159: int    fr_pass = (IPF_DEFAULT_PASS|FR_NOMATCH);
        !           160: #endif
        !           161: 
        !           162: fr_info_t      frcache[2];
        !           163: 
        !           164: static void    fr_makefrip __P((int, ip_t *, fr_info_t *));
        !           165: static int     fr_tcpudpchk __P((frentry_t *, fr_info_t *));
        !           166: static int     frflushlist __P((int, int, int *, frentry_t *, frentry_t **));
        !           167: 
        !           168: 
        !           169: /*
        !           170:  * bit values for identifying presence of individual IP options
        !           171:  */
        !           172: static struct  optlist ipopts[20] = {
        !           173:        { IPOPT_NOP,    0x000001 },
        !           174:        { IPOPT_RR,     0x000002 },
        !           175:        { IPOPT_ZSU,    0x000004 },
        !           176:        { IPOPT_MTUP,   0x000008 },
        !           177:        { IPOPT_MTUR,   0x000010 },
        !           178:        { IPOPT_ENCODE, 0x000020 },
        !           179:        { IPOPT_TS,     0x000040 },
        !           180:        { IPOPT_TR,     0x000080 },
        !           181:        { IPOPT_SECURITY, 0x000100 },
        !           182:        { IPOPT_LSRR,   0x000200 },
        !           183:        { IPOPT_E_SEC,  0x000400 },
        !           184:        { IPOPT_CIPSO,  0x000800 },
        !           185:        { IPOPT_SATID,  0x001000 },
        !           186:        { IPOPT_SSRR,   0x002000 },
        !           187:        { IPOPT_ADDEXT, 0x004000 },
        !           188:        { IPOPT_VISA,   0x008000 },
        !           189:        { IPOPT_IMITD,  0x010000 },
        !           190:        { IPOPT_EIP,    0x020000 },
        !           191:        { IPOPT_FINN,   0x040000 },
        !           192:        { 0,            0x000000 }
        !           193: };
        !           194: 
        !           195: /*
        !           196:  * bit values for identifying presence of individual IP security options
        !           197:  */
        !           198: static struct  optlist secopt[8] = {
        !           199:        { IPSO_CLASS_RES4,      0x01 },
        !           200:        { IPSO_CLASS_TOPS,      0x02 },
        !           201:        { IPSO_CLASS_SECR,      0x04 },
        !           202:        { IPSO_CLASS_RES3,      0x08 },
        !           203:        { IPSO_CLASS_CONF,      0x10 },
        !           204:        { IPSO_CLASS_UNCL,      0x20 },
        !           205:        { IPSO_CLASS_RES2,      0x40 },
        !           206:        { IPSO_CLASS_RES1,      0x80 }
        !           207: };
        !           208: 
        !           209: 
        !           210: /*
        !           211:  * compact the IP header into a structure which contains just the info.
        !           212:  * which is useful for comparing IP headers with.
        !           213:  */
        !           214: static void    fr_makefrip(hlen, ip, fin)
        !           215: int hlen;
        !           216: ip_t *ip;
        !           217: fr_info_t *fin;
        !           218: {
        !           219:        struct optlist *op;
        !           220:        tcphdr_t *tcp;
        !           221:        icmphdr_t *icmp;
        !           222:        fr_ip_t *fi = &fin->fin_fi;
        !           223:        u_short optmsk = 0, secmsk = 0, auth = 0;
        !           224:        int i, mv, ol, off;
        !           225:        u_char *s, opt;
        !           226: 
        !           227:        fin->fin_fr = NULL;
        !           228:        fin->fin_tcpf = 0;
        !           229:        fin->fin_data[0] = 0;
        !           230:        fin->fin_data[1] = 0;
        !           231:        fin->fin_rule = -1;
        !           232:        fin->fin_group = -1;
        !           233:        fin->fin_id = ip->ip_id;
        !           234: #ifdef KERNEL
        !           235:        fin->fin_icode = ipl_unreach;
        !           236: #endif
        !           237:        fi->fi_v = ip->ip_v;
        !           238:        fi->fi_tos = ip->ip_tos;
        !           239:        fin->fin_hlen = hlen;
        !           240:        fin->fin_dlen = ip->ip_len - hlen;
        !           241:        tcp = (tcphdr_t *)((char *)ip + hlen);
        !           242:        icmp = (icmphdr_t *)tcp;
        !           243:        fin->fin_dp = (void *)tcp;
        !           244:        (*(((u_short *)fi) + 1)) = (*(((u_short *)ip) + 4));
        !           245:        (*(((u_32_t *)fi) + 1)) = (*(((u_32_t *)ip) + 3));
        !           246:        (*(((u_32_t *)fi) + 2)) = (*(((u_32_t *)ip) + 4));
        !           247: 
        !           248:        fi->fi_fl = (hlen > sizeof(ip_t)) ? FI_OPTIONS : 0;
        !           249:        off = (ip->ip_off & 0x1fff) << 3;
        !           250:        if (ip->ip_off & 0x3fff)
        !           251:                fi->fi_fl |= FI_FRAG;
        !           252:        switch (ip->ip_p)
        !           253:        {
        !           254:        case IPPROTO_ICMP :
        !           255:        {
        !           256:                int minicmpsz = sizeof(struct icmp);
        !           257: 
        !           258:                if (!off && ip->ip_len > ICMP_MINLEN + hlen &&
        !           259:                    (icmp->icmp_type == ICMP_ECHOREPLY ||
        !           260:                     icmp->icmp_type == ICMP_UNREACH))
        !           261:                        minicmpsz = ICMP_MINLEN;
        !           262:                if ((!(ip->ip_len >= hlen + minicmpsz) && !off) ||
        !           263:                    (off && off < sizeof(struct icmp)))
        !           264:                        fi->fi_fl |= FI_SHORT;
        !           265:                if (fin->fin_dlen > 1)
        !           266:                        fin->fin_data[0] = *(u_short *)tcp;
        !           267:                break;
        !           268:        }
        !           269:        case IPPROTO_TCP :
        !           270:                fi->fi_fl |= FI_TCPUDP;
        !           271:                if ((!IPMINLEN(ip, tcphdr) && !off) ||
        !           272:                    (off && off < sizeof(struct tcphdr)))
        !           273:                        fi->fi_fl |= FI_SHORT;
        !           274:                if (!(fi->fi_fl & FI_SHORT) && !off)
        !           275:                        fin->fin_tcpf = tcp->th_flags;
        !           276:                goto getports;
        !           277:        case IPPROTO_UDP :
        !           278:                fi->fi_fl |= FI_TCPUDP;
        !           279:                if ((!IPMINLEN(ip, udphdr) && !off) ||
        !           280:                    (off && off < sizeof(struct udphdr)))
        !           281:                        fi->fi_fl |= FI_SHORT;
        !           282: getports:
        !           283:                if (!off && (fin->fin_dlen > 3)) {
        !           284:                        fin->fin_data[0] = ntohs(tcp->th_sport);
        !           285:                        fin->fin_data[1] = ntohs(tcp->th_dport);
        !           286:                }
        !           287:                break;
        !           288:        default :
        !           289:                break;
        !           290:        }
        !           291: 
        !           292: 
        !           293:        for (s = (u_char *)(ip + 1), hlen -= sizeof(*ip); hlen; ) {
        !           294:                if (!(opt = *s))
        !           295:                        break;
        !           296:                ol = (opt == IPOPT_NOP) ? 1 : (int)*(s+1);
        !           297:                if (opt > 1 && (ol < 2 || ol > hlen))
        !           298:                        break;
        !           299:                for (i = 9, mv = 4; mv >= 0; ) {
        !           300:                        op = ipopts + i;
        !           301:                        if (opt == (u_char)op->ol_val) {
        !           302:                                optmsk |= op->ol_bit;
        !           303:                                if (opt == IPOPT_SECURITY) {
        !           304:                                        struct optlist *sp;
        !           305:                                        u_char  sec;
        !           306:                                        int j, m;
        !           307: 
        !           308:                                        sec = *(s + 2); /* classification */
        !           309:                                        for (j = 3, m = 2; m >= 0; ) {
        !           310:                                                sp = secopt + j;
        !           311:                                                if (sec == sp->ol_val) {
        !           312:                                                        secmsk |= sp->ol_bit;
        !           313:                                                        auth = *(s + 3);
        !           314:                                                        auth *= 256;
        !           315:                                                        auth += *(s + 4);
        !           316:                                                        break;
        !           317:                                                }
        !           318:                                                if (sec < sp->ol_val)
        !           319:                                                        j -= m--;
        !           320:                                                else
        !           321:                                                        j += m--;
        !           322:                                        }
        !           323:                                }
        !           324:                                break;
        !           325:                        }
        !           326:                        if (opt < op->ol_val)
        !           327:                                i -= mv--;
        !           328:                        else
        !           329:                                i += mv--;
        !           330:                }
        !           331:                hlen -= ol;
        !           332:                s += ol;
        !           333:        }
        !           334:        if (auth && !(auth & 0x0100))
        !           335:                auth &= 0xff00;
        !           336:        fi->fi_optmsk = optmsk;
        !           337:        fi->fi_secmsk = secmsk;
        !           338:        fi->fi_auth = auth;
        !           339: }
        !           340: 
        !           341: 
        !           342: /*
        !           343:  * check an IP packet for TCP/UDP characteristics such as ports and flags.
        !           344:  */
        !           345: static int fr_tcpudpchk(fr, fin)
        !           346: frentry_t *fr;
        !           347: fr_info_t *fin;
        !           348: {
        !           349:        register u_short po, tup;
        !           350:        register char i;
        !           351:        register int err = 1;
        !           352: 
        !           353:        /*
        !           354:         * Both ports should *always* be in the first fragment.
        !           355:         * So far, I cannot find any cases where they can not be.
        !           356:         *
        !           357:         * compare destination ports
        !           358:         */
        !           359:        if ((i = (int)fr->fr_dcmp)) {
        !           360:                po = fr->fr_dport;
        !           361:                tup = fin->fin_data[1];
        !           362:                /*
        !           363:                 * Do opposite test to that required and
        !           364:                 * continue if that succeeds.
        !           365:                 */
        !           366:                if (!--i && tup != po) /* EQUAL */
        !           367:                        err = 0;
        !           368:                else if (!--i && tup == po) /* NOTEQUAL */
        !           369:                        err = 0;
        !           370:                else if (!--i && tup >= po) /* LESSTHAN */
        !           371:                        err = 0;
        !           372:                else if (!--i && tup <= po) /* GREATERTHAN */
        !           373:                        err = 0;
        !           374:                else if (!--i && tup > po) /* LT or EQ */
        !           375:                        err = 0;
        !           376:                else if (!--i && tup < po) /* GT or EQ */
        !           377:                        err = 0;
        !           378:                else if (!--i &&           /* Out of range */
        !           379:                         (tup >= po && tup <= fr->fr_dtop))
        !           380:                        err = 0;
        !           381:                else if (!--i &&           /* In range */
        !           382:                         (tup <= po || tup >= fr->fr_dtop))
        !           383:                        err = 0;
        !           384:        }
        !           385:        /*
        !           386:         * compare source ports
        !           387:         */
        !           388:        if (err && (i = (int)fr->fr_scmp)) {
        !           389:                po = fr->fr_sport;
        !           390:                tup = fin->fin_data[0];
        !           391:                if (!--i && tup != po)
        !           392:                        err = 0;
        !           393:                else if (!--i && tup == po)
        !           394:                        err = 0;
        !           395:                else if (!--i && tup >= po)
        !           396:                        err = 0;
        !           397:                else if (!--i && tup <= po)
        !           398:                        err = 0;
        !           399:                else if (!--i && tup > po)
        !           400:                        err = 0;
        !           401:                else if (!--i && tup < po)
        !           402:                        err = 0;
        !           403:                else if (!--i &&           /* Out of range */
        !           404:                         (tup >= po && tup <= fr->fr_stop))
        !           405:                        err = 0;
        !           406:                else if (!--i &&           /* In range */
        !           407:                         (tup <= po || tup >= fr->fr_stop))
        !           408:                        err = 0;
        !           409:        }
        !           410: 
        !           411:        /*
        !           412:         * If we don't have all the TCP/UDP header, then how can we
        !           413:         * expect to do any sort of match on it ?  If we were looking for
        !           414:         * TCP flags, then NO match.  If not, then match (which should
        !           415:         * satisfy the "short" class too).
        !           416:         */
        !           417:        if (err && (fin->fin_fi.fi_p == IPPROTO_TCP)) {
        !           418:                if (fin->fin_fi.fi_fl & FI_SHORT)
        !           419:                        return !(fr->fr_tcpf | fr->fr_tcpfm);
        !           420:                /*
        !           421:                 * Match the flags ?  If not, abort this match.
        !           422:                 */
        !           423:                if (fr->fr_tcpf &&
        !           424:                    fr->fr_tcpf != (fin->fin_tcpf & fr->fr_tcpfm)) {
        !           425:                        FR_DEBUG(("f. %#x & %#x != %#x\n", fin->fin_tcpf,
        !           426:                                 fr->fr_tcpfm, fr->fr_tcpf));
        !           427:                        err = 0;
        !           428:                }
        !           429:        }
        !           430:        return err;
        !           431: }
        !           432: 
        !           433: /*
        !           434:  * Check the input/output list of rules for a match and result.
        !           435:  * Could be per interface, but this gets real nasty when you don't have
        !           436:  * kernel sauce.
        !           437:  */
        !           438: int fr_scanlist(pass, ip, fin, m)
        !           439: int pass;
        !           440: ip_t *ip;
        !           441: register fr_info_t *fin;
        !           442: void *m;
        !           443: {
        !           444:        register struct frentry *fr;
        !           445:        register fr_ip_t *fi = &fin->fin_fi;
        !           446:        int rulen, portcmp = 0, off, skip = 0;
        !           447: 
        !           448:        fr = fin->fin_fr;
        !           449:        fin->fin_fr = NULL;
        !           450:        fin->fin_rule = 0;
        !           451:        fin->fin_group = 0;
        !           452:        off = ip->ip_off & 0x1fff;
        !           453:        pass |= (fi->fi_fl << 24);
        !           454: 
        !           455:         if ((fi->fi_fl & FI_TCPUDP) && (fin->fin_dlen > 3) && !off)
        !           456:                portcmp = 1;
        !           457: 
        !           458:        for (rulen = 0; fr; fr = fr->fr_next, rulen++) {
        !           459:                if (skip) {
        !           460:                        skip--;
        !           461:                        continue;
        !           462:                }
        !           463:                /*
        !           464:                 * In all checks below, a null (zero) value in the
        !           465:                 * filter struture is taken to mean a wildcard.
        !           466:                 *
        !           467:                 * check that we are working for the right interface
        !           468:                 */
        !           469: #ifdef KERNEL
        !           470:                if (fr->fr_ifa && fr->fr_ifa != fin->fin_ifp)
        !           471:                        continue;
        !           472: #else
        !           473:                if (opts & (OPT_VERBOSE|OPT_DEBUG))
        !           474:                        printf("\n");
        !           475:                FR_VERBOSE(("%c", (pass & FR_PASS) ? 'p' : 
        !           476:                                  (pass & FR_AUTH) ? 'a' : 'b'));
        !           477:                if (fr->fr_ifa && fr->fr_ifa != fin->fin_ifp)
        !           478:                        continue;
        !           479:                FR_VERBOSE((":i"));
        !           480: #endif
        !           481:                {
        !           482:                        register u_32_t *ld, *lm, *lip;
        !           483:                        register int i;
        !           484: 
        !           485:                        lip = (u_32_t *)fi;
        !           486:                        lm = (u_32_t *)&fr->fr_mip;
        !           487:                        ld = (u_32_t *)&fr->fr_ip;
        !           488:                        i = ((lip[0] & lm[0]) != ld[0]);
        !           489:                        FR_IFDEBUG(i,continue,("0. %#08x & %#08x != %#08x\n",
        !           490:                                   lip[0], lm[0], ld[0]));
        !           491:                        i |= ((lip[1] & lm[1]) != ld[1]) << 21;
        !           492:                        FR_IFDEBUG(i,continue,("1. %#08x & %#08x != %#08x\n",
        !           493:                                   lip[1], lm[1], ld[1]));
        !           494:                        i |= ((lip[2] & lm[2]) != ld[2]) << 22;
        !           495:                        FR_IFDEBUG(i,continue,("2. %#08x & %#08x != %#08x\n",
        !           496:                                   lip[2], lm[2], ld[2]));
        !           497:                        i |= ((lip[3] & lm[3]) != ld[3]);
        !           498:                        FR_IFDEBUG(i,continue,("3. %#08x & %#08x != %#08x\n",
        !           499:                                   lip[3], lm[3], ld[3]));
        !           500:                        i |= ((lip[4] & lm[4]) != ld[4]);
        !           501:                        FR_IFDEBUG(i,continue,("4. %#08x & %#08x != %#08x\n",
        !           502:                                   lip[4], lm[4], ld[4]));
        !           503:                        i ^= (fi->fi_fl & (FR_NOTSRCIP|FR_NOTDSTIP));
        !           504:                        if (i)
        !           505:                                continue;
        !           506:                }
        !           507: 
        !           508:                /*
        !           509:                 * If a fragment, then only the first has what we're looking
        !           510:                 * for here...
        !           511:                 */
        !           512:                if (!portcmp && (fr->fr_dcmp || fr->fr_scmp || fr->fr_tcpf ||
        !           513:                                 fr->fr_tcpfm))
        !           514:                        continue;
        !           515:                if (fi->fi_fl & FI_TCPUDP) {
        !           516:                        if (!fr_tcpudpchk(fr, fin))
        !           517:                                continue;
        !           518:                } else if (fr->fr_icmpm || fr->fr_icmp) {
        !           519:                        if ((fi->fi_p != IPPROTO_ICMP) || off ||
        !           520:                            (fin->fin_dlen < 2))
        !           521:                                continue;
        !           522:                        if ((fin->fin_data[0] & fr->fr_icmpm) != fr->fr_icmp) {
        !           523:                                FR_DEBUG(("i. %#x & %#x != %#x\n",
        !           524:                                         fin->fin_data[0], fr->fr_icmpm,
        !           525:                                         fr->fr_icmp));
        !           526:                                continue;
        !           527:                        }
        !           528:                }
        !           529:                FR_VERBOSE(("*"));
        !           530:                /*
        !           531:                 * Just log this packet...
        !           532:                 */
        !           533:                if (!(skip = fr->fr_skip))
        !           534:                        pass = fr->fr_flags;
        !           535:                if ((pass & FR_CALLNOW) && fr->fr_func)
        !           536:                        pass = (*fr->fr_func)(pass, ip, fin);
        !           537: #if  IPFILTER_LOG
        !           538:                if ((pass & FR_LOGMASK) == FR_LOG) {
        !           539:                        if (!IPLLOG(fr->fr_flags, ip, fin, m))
        !           540:                                frstats[fin->fin_out].fr_skip++;
        !           541:                        frstats[fin->fin_out].fr_pkl++;
        !           542:                }
        !           543: #endif /* IPFILTER_LOG */
        !           544:                FR_DEBUG(("pass %#x\n", pass));
        !           545:                fr->fr_hits++;
        !           546:                if (pass & FR_ACCOUNT)
        !           547:                        fr->fr_bytes += (U_QUAD_T)ip->ip_len;
        !           548:                else
        !           549:                        fin->fin_icode = fr->fr_icode;
        !           550:                fin->fin_rule = rulen;
        !           551:                fin->fin_group = fr->fr_group;
        !           552:                fin->fin_fr = fr;
        !           553:                if (fr->fr_grp) {
        !           554:                        fin->fin_fr = fr->fr_grp;
        !           555:                        pass = fr_scanlist(pass, ip, fin, m);
        !           556:                        if (fin->fin_fr == NULL) {
        !           557:                                fin->fin_rule = rulen;
        !           558:                                fin->fin_group = fr->fr_group;
        !           559:                                fin->fin_fr = fr;
        !           560:                        }
        !           561:                }
        !           562:                if (pass & FR_QUICK)
        !           563:                        break;
        !           564:        }
        !           565:        return pass;
        !           566: }
        !           567: 
        !           568: 
        !           569: /*
        !           570:  * frcheck - filter check
        !           571:  * check using source and destination addresses/pors in a packet whether
        !           572:  * or not to pass it on or not.
        !           573:  */
        !           574: int fr_check(ip, hlen, ifp, out
        !           575: #if defined(KERNEL) && SOLARIS
        !           576: , qif, mp)
        !           577: qif_t *qif;
        !           578: #else
        !           579: , mp)
        !           580: #endif
        !           581: mb_t **mp;
        !           582: ip_t *ip;
        !           583: int hlen;
        !           584: void *ifp;
        !           585: int out;
        !           586: {
        !           587:        /*
        !           588:         * The above is really bad, but short of writing a diff
        !           589:         */
        !           590:        fr_info_t frinfo, *fc;
        !           591:        register fr_info_t *fin = &frinfo;
        !           592:        frentry_t *fr = NULL;
        !           593:        int pass, changed, apass, error = EHOSTUNREACH;
        !           594: #if !SOLARIS || !defined(KERNEL)
        !           595:        register mb_t *m = *mp;
        !           596: #endif
        !           597: 
        !           598: #if    KERNEL
        !           599:        mb_t *mc = NULL;
        !           600: # if !defined(__SVR4) && !defined(__svr4__)
        !           601: #  ifdef __sgi
        !           602:        char hbuf[(0xf << 2) + sizeof(struct icmp) + sizeof(ip_t) + 8];
        !           603: #  endif
        !           604:        int up;
        !           605: 
        !           606: #if M_CANFASTFWD
        !           607:        /*
        !           608:         * XXX For now, IP Filter and fast-forwarding of cached flows
        !           609:         * XXX are mutually exclusive.  Eventually, IP Filter should
        !           610:         * XXX get a "can-fast-forward" filter rule.
        !           611:         */
        !           612:        m->m_flags &= ~M_CANFASTFWD;
        !           613: #endif /* M_CANFASTFWD */
        !           614: 
        !           615:        if ((ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP ||
        !           616:             ip->ip_p == IPPROTO_ICMP)) {
        !           617:                int plen = 0;
        !           618: 
        !           619:                switch(ip->ip_p)
        !           620:                {
        !           621:                case IPPROTO_TCP:
        !           622:                        plen = sizeof(tcphdr_t);
        !           623:                        break;
        !           624:                case IPPROTO_UDP:
        !           625:                        plen = sizeof(udphdr_t);
        !           626:                        break;
        !           627:                case IPPROTO_ICMP:
        !           628:                        /* 96 - enough for complete ICMP error IP header */
        !           629:                        plen = sizeof(struct icmp) + sizeof(ip_t) + 8;
        !           630:                        break;
        !           631:                }
        !           632:                up = MIN(hlen + plen, ip->ip_len);
        !           633: 
        !           634:                if (up > m->m_len) {
        !           635: #ifdef __sgi /* Under IRIX, avoid m_pullup as it makes ping <hostname> panic */
        !           636:                        if ((up > sizeof(hbuf)) || (m_length(m) < up)) {
        !           637:                                frstats[out].fr_pull[1]++;
        !           638:                                return -1;
        !           639:                        }
        !           640:                        m_copydata(m, 0, up, hbuf);
        !           641:                        frstats[out].fr_pull[0]++;
        !           642:                        ip = (ip_t *)hbuf;
        !           643: #else
        !           644: # ifndef linux
        !           645:                        if ((*mp = m_pullup(m, up)) == 0) {
        !           646:                                frstats[out].fr_pull[1]++;
        !           647:                                return -1;
        !           648:                        } else {
        !           649:                                frstats[out].fr_pull[0]++;
        !           650:                                m = *mp;
        !           651:                                ip = mtod(m, ip_t *);
        !           652:                        }
        !           653: # endif
        !           654: #endif
        !           655:                } else
        !           656:                        up = 0;
        !           657:        } else
        !           658:                up = 0;
        !           659: # endif
        !           660: # if SOLARIS
        !           661:        mb_t *m = qif->qf_m;
        !           662: # endif
        !           663: #endif
        !           664:        fr_makefrip(hlen, ip, fin);
        !           665:        fin->fin_ifp = ifp;
        !           666:        fin->fin_out = out;
        !           667:        fin->fin_mp = mp;
        !           668: 
        !           669:        MUTEX_ENTER(&ipf_mutex);
        !           670: 
        !           671:        /*
        !           672:         * Check auth now.  This, combined with the check below to see if apass
        !           673:         * is 0 is to ensure that we don't count the packet twice, which can
        !           674:         * otherwise occur when we reprocess it.  As it is, we only count it
        !           675:         * after it has no auth. table matchup.  This also stops NAT from
        !           676:         * occuring until after the packet has been auth'd.
        !           677:         */
        !           678:        apass = fr_checkauth(ip, fin);
        !           679: 
        !           680:        if (!out) {
        !           681:                changed = ip_natin(ip, hlen, fin);
        !           682:                if (!apass && (fin->fin_fr = ipacct[0][fr_active]) &&
        !           683:                    (FR_SCANLIST(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT))
        !           684:                        frstats[0].fr_acct++;
        !           685:        }
        !           686: 
        !           687:        if (apass || (!(pass = ipfr_knownfrag(ip, fin)) &&
        !           688:            !(pass = fr_checkstate(ip, fin)))) {
        !           689:                /*
        !           690:                 * If a packet is found in the auth table, then skip checking
        !           691:                 * the access lists for permission but we do need to consider
        !           692:                 * the result as if it were from the ACL's.
        !           693:                 */
        !           694:                if (!apass) {
        !           695:                        fc = frcache + out;
        !           696:                        if (!bcmp((char *)fin, (char *)fc, FI_CSIZE)) {
        !           697:                                /*
        !           698:                                 * copy cached data so we can unlock the mutex
        !           699:                                 * earlier.
        !           700:                                 */
        !           701:                                bcopy((char *)fc, (char *)fin, FI_COPYSIZE);
        !           702:                                frstats[out].fr_chit++;
        !           703:                                if ((fr = fin->fin_fr)) {
        !           704:                                        fr->fr_hits++;
        !           705:                                        pass = fr->fr_flags;
        !           706:                                } else
        !           707:                                        pass = fr_pass;
        !           708:                        } else {
        !           709:                                pass = fr_pass;
        !           710:                                if ((fin->fin_fr = ipfilter[out][fr_active]))
        !           711:                                        pass = FR_SCANLIST(fr_pass, ip, fin, m);
        !           712:                                bcopy((char *)fin, (char *)fc, FI_COPYSIZE);
        !           713:                                if (pass & FR_NOMATCH)
        !           714:                                        frstats[out].fr_nom++;
        !           715:                        }
        !           716:                        fr = fin->fin_fr;
        !           717:                } else
        !           718:                        pass = apass;
        !           719: 
        !           720:                /*
        !           721:                 * If we fail to add a packet to the authorization queue,
        !           722:                 * then we drop the packet later.  However, if it was added
        !           723:                 * then pretend we've dropped it already.
        !           724:                 */
        !           725:                if ((pass & FR_AUTH))
        !           726:                        if (FR_NEWAUTH(m, fin, ip, qif) != 0)
        !           727: #ifdef KERNEL
        !           728:                                m = *mp = NULL;
        !           729: #else
        !           730:                                ;
        !           731: #endif
        !           732: 
        !           733:                if (pass & FR_PREAUTH) {
        !           734:                        MUTEX_ENTER(&ipf_auth);
        !           735:                        if ((fin->fin_fr = ipauth) &&
        !           736:                            (pass = FR_SCANLIST(0, ip, fin, m)))
        !           737:                                fr_authstats.fas_hits++;
        !           738:                        else
        !           739:                                fr_authstats.fas_miss++;
        !           740:                        MUTEX_EXIT(&ipf_auth);
        !           741:                }
        !           742: 
        !           743:                if (pass & FR_KEEPFRAG) {
        !           744:                        if (fin->fin_fi.fi_fl & FI_FRAG) {
        !           745:                                if (ipfr_newfrag(ip, fin, pass) == -1)
        !           746:                                        frstats[out].fr_bnfr++;
        !           747:                                else
        !           748:                                        frstats[out].fr_nfr++;
        !           749:                        } else
        !           750:                                frstats[out].fr_cfr++;
        !           751:                }
        !           752:                if (pass & FR_KEEPSTATE) {
        !           753:                        if (fr_addstate(ip, fin, pass) == -1)
        !           754:                                frstats[out].fr_bads++;
        !           755:                        else
        !           756:                                frstats[out].fr_ads++;
        !           757:                }
        !           758:        }
        !           759: 
        !           760:        if (fr && fr->fr_func && !(pass & FR_CALLNOW))
        !           761:                pass = (*fr->fr_func)(pass, ip, fin);
        !           762: 
        !           763:        /*
        !           764:         * Only count/translate packets which will be passed on, out the
        !           765:         * interface.
        !           766:         */
        !           767:        if (out && (pass & FR_PASS)) {
        !           768:                if ((fin->fin_fr = ipacct[1][fr_active]) &&
        !           769:                    (FR_SCANLIST(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT))
        !           770:                        frstats[1].fr_acct++;
        !           771:                fin->fin_fr = NULL;
        !           772:                changed = ip_natout(ip, hlen, fin);
        !           773:        }
        !           774:        fin->fin_fr = fr;
        !           775:        MUTEX_EXIT(&ipf_mutex);
        !           776: 
        !           777: #if    IPFILTER_LOG
        !           778:        if ((fr_flags & FF_LOGGING) || (pass & FR_LOGMASK)) {
        !           779:                if ((fr_flags & FF_LOGNOMATCH) && (pass & FR_NOMATCH)) {
        !           780:                        pass |= FF_LOGNOMATCH;
        !           781:                        frstats[out].fr_npkl++;
        !           782:                        goto logit;
        !           783:                } else if (((pass & FR_LOGMASK) == FR_LOGP) ||
        !           784:                    ((pass & FR_PASS) && (fr_flags & FF_LOGPASS))) {
        !           785:                        if ((pass & FR_LOGMASK) != FR_LOGP)
        !           786:                                pass |= FF_LOGPASS;
        !           787:                        frstats[out].fr_ppkl++;
        !           788:                        goto logit;
        !           789:                } else if (((pass & FR_LOGMASK) == FR_LOGB) ||
        !           790:                           ((pass & FR_BLOCK) && (fr_flags & FF_LOGBLOCK))) {
        !           791:                        if ((pass & FR_LOGMASK) != FR_LOGB)
        !           792:                                pass |= FF_LOGBLOCK;
        !           793:                        frstats[out].fr_bpkl++;
        !           794: logit:
        !           795:                        if (!IPLLOG(pass, ip, fin, m)) {
        !           796:                                frstats[out].fr_skip++;
        !           797:                                if ((pass & (FR_PASS|FR_LOGORBLOCK)) ==
        !           798:                                    (FR_PASS|FR_LOGORBLOCK))
        !           799:                                        pass ^= FR_PASS|FR_BLOCK;
        !           800:                        }
        !           801:                }
        !           802:        }
        !           803: #endif /* IPFILTER_LOG */
        !           804: #ifdef KERNEL
        !           805:        /*
        !           806:         * Only allow FR_DUP to work if a rule matched - it makes no sense to
        !           807:         * set FR_DUP as a "default" as there are no instructions about where
        !           808:         * to send the packet.
        !           809:         */
        !           810:        if (fr && (pass & FR_DUP))
        !           811: # if   SOLARIS
        !           812:                mc = dupmsg(m);
        !           813: # else
        !           814: #  ifndef linux
        !           815:                mc = m_copy(m, 0, M_COPYALL);
        !           816: #  else
        !           817:                ;
        !           818: #  endif
        !           819: # endif
        !           820: #endif
        !           821:        if (pass & FR_PASS)
        !           822:                frstats[out].fr_pass++;
        !           823:        else if (pass & FR_BLOCK) {
        !           824:                frstats[out].fr_block++;
        !           825:                /*
        !           826:                 * Should we return an ICMP packet to indicate error
        !           827:                 * status passing through the packet filter ?
        !           828:                 * WARNING: ICMP error packets AND TCP RST packets should
        !           829:                 * ONLY be sent in repsonse to incoming packets.  Sending them
        !           830:                 * in response to outbound packets can result in a panic on
        !           831:                 * some operating systems.
        !           832:                 */
        !           833:                if (!out) {
        !           834: #ifdef KERNEL
        !           835:                        if (pass & FR_RETICMP) {
        !           836: # if SOLARIS
        !           837:                                ICMP_ERROR(q, ip, ICMP_UNREACH, fin->fin_icode,
        !           838:                                           qif, ip->ip_src);
        !           839: # else
        !           840:                                ICMP_ERROR(m, ip, ICMP_UNREACH, fin->fin_icode,
        !           841:                                           ifp, ip->ip_src);
        !           842:                                m = *mp = NULL; /* freed by icmp_error() */
        !           843: # endif
        !           844: 
        !           845:                                frstats[0].fr_ret++;
        !           846:                        } else if ((pass & FR_RETRST) &&
        !           847:                                   !(fin->fin_fi.fi_fl & FI_SHORT)) {
        !           848:                                if (SEND_RESET(ip, qif, ifp) == 0)
        !           849:                                        frstats[1].fr_ret++;
        !           850:                        }
        !           851: #else
        !           852:                        if (pass & FR_RETICMP) {
        !           853:                                verbose("- ICMP unreachable sent\n");
        !           854:                                frstats[0].fr_ret++;
        !           855:                        } else if ((pass & FR_RETRST) &&
        !           856:                                   !(fin->fin_fi.fi_fl & FI_SHORT)) {
        !           857:                                verbose("- TCP RST sent\n");
        !           858:                                frstats[1].fr_ret++;
        !           859:                        }
        !           860: #endif
        !           861:                } else {
        !           862:                        if (pass & FR_RETRST)
        !           863:                                error = ECONNRESET;
        !           864:                }
        !           865:        }
        !           866: 
        !           867:        /*
        !           868:         * If we didn't drop off the bottom of the list of rules (and thus
        !           869:         * the 'current' rule fr is not NULL), then we may have some extra
        !           870:         * instructions about what to do with a packet.
        !           871:         * Once we're finished return to our caller, freeing the packet if
        !           872:         * we are dropping it (* BSD ONLY *).
        !           873:         */
        !           874: #if defined(KERNEL)
        !           875: # if !SOLARIS
        !           876: #  if !defined(linux)
        !           877:        if (fr) {
        !           878:                frdest_t *fdp = &fr->fr_tif;
        !           879: 
        !           880:                if ((pass & FR_FASTROUTE) ||
        !           881:                    (fdp->fd_ifp && fdp->fd_ifp != (struct ifnet *)-1)) {
        !           882:                        ipfr_fastroute(m, fin, fdp);
        !           883:                        m = *mp = NULL;
        !           884:                }
        !           885:                if (mc)
        !           886:                        ipfr_fastroute(mc, fin, &fr->fr_dif);
        !           887:        }
        !           888:        if (!(pass & FR_PASS) && m)
        !           889:                m_freem(m);
        !           890: #   ifdef __sgi
        !           891:        else if (changed && up && m)
        !           892:                m_copyback(m, 0, up, hbuf);
        !           893: #   endif
        !           894: #  endif /* !linux */
        !           895:        return (pass & FR_PASS) ? 0 : error;
        !           896: # else /* !SOLARIS */
        !           897:        if (fr) {
        !           898:                frdest_t *fdp = &fr->fr_tif;
        !           899: 
        !           900:                if ((pass & FR_FASTROUTE) ||
        !           901:                    (fdp->fd_ifp && fdp->fd_ifp != (struct ifnet *)-1)) {
        !           902:                        ipfr_fastroute(qif, ip, m, mp, fin, fdp);
        !           903:                        m = *mp = NULL;
        !           904:                }
        !           905:                if (mc)
        !           906:                        ipfr_fastroute(qif, ip, mc, mp, fin, &fr->fr_dif);
        !           907:        }
        !           908:        return (pass & FR_PASS) ? changed : error;
        !           909: # endif /* !SOLARIS */
        !           910: #else /* KERNEL */
        !           911:        if (pass & FR_NOMATCH)
        !           912:                return 1;
        !           913:        if (pass & FR_PASS)
        !           914:                return 0;
        !           915:        if (pass & FR_AUTH)
        !           916:                return -2;
        !           917:        return -1;
        !           918: #endif /* KERNEL */
        !           919: }
        !           920: 
        !           921: 
        !           922: /*
        !           923:  * ipf_cksum
        !           924:  * addr should be 16bit aligned and len is in bytes.
        !           925:  * length is in bytes
        !           926:  */
        !           927: u_short ipf_cksum(addr, len)
        !           928: register u_short *addr;
        !           929: register int len;
        !           930: {
        !           931:        register u_32_t sum = 0;
        !           932: 
        !           933:        for (sum = 0; len > 1; len -= 2)
        !           934:                sum += *addr++;
        !           935: 
        !           936:        /* mop up an odd byte, if necessary */
        !           937:        if (len == 1)
        !           938:                sum += *(u_char *)addr;
        !           939: 
        !           940:        /*
        !           941:         * add back carry outs from top 16 bits to low 16 bits
        !           942:         */
        !           943:        sum = (sum >> 16) + (sum & 0xffff);     /* add hi 16 to low 16 */
        !           944:        sum += (sum >> 16);                     /* add carry */
        !           945:        return (u_short)(~sum);
        !           946: }
        !           947: 
        !           948: 
        !           949: /*
        !           950:  * NB: This function assumes we've pullup'd enough for all of the IP header
        !           951:  * and the TCP header.  We also assume that data blocks aren't allocated in
        !           952:  * odd sizes.
        !           953:  */
        !           954: u_short fr_tcpsum(m, ip, tcp, len)
        !           955: mb_t *m;
        !           956: ip_t *ip;
        !           957: tcphdr_t *tcp;
        !           958: int len;
        !           959: {
        !           960:        union {
        !           961:                u_char  c[2];
        !           962:                u_short s;
        !           963:        } bytes;
        !           964:        u_32_t sum;
        !           965:        u_short *sp;
        !           966: # if SOLARIS || defined(__sgi)
        !           967:        int add, hlen;
        !           968: # endif
        !           969: 
        !           970: # if SOLARIS
        !           971:        /* skip any leading M_PROTOs */
        !           972:        while(m && (MTYPE(m) != M_DATA))
        !           973:                m = m->b_cont;
        !           974:        PANIC((!m),("fr_tcpsum: no M_DATA"));
        !           975: # endif
        !           976: 
        !           977:        /*
        !           978:         * Add up IP Header portion
        !           979:         */
        !           980:        bytes.c[0] = 0;
        !           981:        bytes.c[1] = IPPROTO_TCP;
        !           982:        len -= (ip->ip_hl << 2);
        !           983:        sum = bytes.s;
        !           984:        sum += htons((u_short)len);
        !           985:        sp = (u_short *)&ip->ip_src;
        !           986:        sum += *sp++;
        !           987:        sum += *sp++;
        !           988:        sum += *sp++;
        !           989:        sum += *sp++;
        !           990:        if (sp != (u_short *)tcp)
        !           991:                sp = (u_short *)tcp;
        !           992:        sum += *sp++;
        !           993:        sum += *sp++;
        !           994:        sum += *sp++;
        !           995:        sum += *sp++;
        !           996:        sum += *sp++;
        !           997:        sum += *sp++;
        !           998:        sum += *sp++;
        !           999:        sum += *sp;
        !          1000:        sp += 2;        /* Skip over checksum */
        !          1001:        sum += *sp++;
        !          1002: 
        !          1003: #if SOLARIS
        !          1004:        /*
        !          1005:         * In case we had to copy the IP & TCP header out of mblks,
        !          1006:         * skip over the mblk bits which are the header
        !          1007:         */
        !          1008:        if ((caddr_t)ip != (caddr_t)m->b_rptr) {
        !          1009:                hlen = (caddr_t)sp - (caddr_t)ip;
        !          1010:                while (hlen) {
        !          1011:                        add = MIN(hlen, m->b_wptr - m->b_rptr);
        !          1012:                        sp = (u_short *)((caddr_t)m->b_rptr + add);
        !          1013:                        hlen -= add;
        !          1014:                        if ((caddr_t)sp >= (caddr_t)m->b_wptr) {
        !          1015:                                m = m->b_cont;
        !          1016:                                PANIC((!m),("fr_tcpsum: not enough data"));
        !          1017:                                if (!hlen)
        !          1018:                                        sp = (u_short *)m->b_rptr;
        !          1019:                        }
        !          1020:                }
        !          1021:        }
        !          1022: #endif
        !          1023: #ifdef __sgi
        !          1024:        /*
        !          1025:         * In case we had to copy the IP & TCP header out of mbufs,
        !          1026:         * skip over the mbuf bits which are the header
        !          1027:         */
        !          1028:        if ((caddr_t)ip != mtod(m, caddr_t)) {
        !          1029:                hlen = (caddr_t)sp - (caddr_t)ip;
        !          1030:                while (hlen) {
        !          1031:                        add = MIN(hlen, m->m_len);
        !          1032:                        sp = (u_short *)(mtod(m, caddr_t) + add);
        !          1033:                        hlen -= add;
        !          1034:                        if (add >= m->m_len) {
        !          1035:                                m = m->m_next;
        !          1036:                                PANIC((!m),("fr_tcpsum: not enough data"));
        !          1037:                                if (!hlen)
        !          1038:                                        sp = mtod(m, u_short *);
        !          1039:                        }
        !          1040:                }
        !          1041:        }
        !          1042: #endif
        !          1043: 
        !          1044:        if (!(len -= sizeof(*tcp)))
        !          1045:                goto nodata;
        !          1046:        while (len > 0) {
        !          1047: #if SOLARIS
        !          1048:                while ((caddr_t)sp >= (caddr_t)m->b_wptr) {
        !          1049:                        m = m->b_cont;
        !          1050:                        PANIC((!m),("fr_tcpsum: not enough data"));
        !          1051:                        sp = (u_short *)m->b_rptr;
        !          1052:                }
        !          1053: #else
        !          1054:                while (((caddr_t)sp - mtod(m, caddr_t)) >= m->m_len)
        !          1055:                {
        !          1056:                        m = m->m_next;
        !          1057:                        PANIC((!m),("fr_tcpsum: not enough data"));
        !          1058:                        sp = mtod(m, u_short *);
        !          1059:                }
        !          1060: #endif /* SOLARIS */
        !          1061:                if (len < 2)
        !          1062:                        break;
        !          1063:                if((u_32_t)sp & 1) {
        !          1064:                        bcopy((char *)sp++, (char *)&bytes.s, sizeof(bytes.s));
        !          1065:                        sum += bytes.s;
        !          1066:                } else
        !          1067:                        sum += *sp++;
        !          1068:                len -= 2;
        !          1069:        }
        !          1070:        if (len) {
        !          1071:                bytes.c[1] = 0;
        !          1072:                bytes.c[0] = *(u_char *)sp;
        !          1073:                sum += bytes.s;
        !          1074:        }
        !          1075: nodata:
        !          1076:        sum = (sum >> 16) + (sum & 0xffff);
        !          1077:        sum += (sum >> 16);
        !          1078:        sum = (u_short)((~sum) & 0xffff);
        !          1079:        return sum;
        !          1080: }
        !          1081: 
        !          1082: 
        !          1083: #if defined(KERNEL) && ( ((BSD < 199306) && !SOLARIS) || defined(__sgi) )
        !          1084: /*
        !          1085:  * Copyright (c) 1982, 1986, 1988, 1991, 1993
        !          1086:  *     The Regents of the University of California.  All rights reserved.
        !          1087:  *
        !          1088:  * Redistribution and use in source and binary forms, with or without
        !          1089:  * modification, are permitted provided that the following conditions
        !          1090:  * are met:
        !          1091:  * 1. Redistributions of source code must retain the above copyright
        !          1092:  *    notice, this list of conditions and the following disclaimer.
        !          1093:  * 2. Redistributions in binary form must reproduce the above copyright
        !          1094:  *    notice, this list of conditions and the following disclaimer in the
        !          1095:  *    documentation and/or other materials provided with the distribution.
        !          1096:  * 3. All advertising materials mentioning features or use of this software
        !          1097:  *    must display the following acknowledgement:
        !          1098:  *     This product includes software developed by the University of
        !          1099:  *     California, Berkeley and its contributors.
        !          1100:  * 4. Neither the name of the University nor the names of its contributors
        !          1101:  *    may be used to endorse or promote products derived from this software
        !          1102:  *    without specific prior written permission.
        !          1103:  *
        !          1104:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !          1105:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !          1106:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !          1107:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !          1108:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !          1109:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !          1110:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !          1111:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !          1112:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !          1113:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !          1114:  * SUCH DAMAGE.
        !          1115:  *
        !          1116:  *     @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94
        !          1117:  */
        !          1118: /*
        !          1119:  * Copy data from an mbuf chain starting "off" bytes from the beginning,
        !          1120:  * continuing for "len" bytes, into the indicated buffer.
        !          1121:  */
        !          1122: void
        !          1123: m_copydata(m, off, len, cp)
        !          1124:        register mb_t *m;
        !          1125:        register int off;
        !          1126:        register int len;
        !          1127:        caddr_t cp;
        !          1128: {
        !          1129:        register unsigned count;
        !          1130: 
        !          1131:        if (off < 0 || len < 0)
        !          1132:                panic("m_copydata");
        !          1133:        while (off > 0) {
        !          1134:                if (m == 0)
        !          1135:                        panic("m_copydata");
        !          1136:                if (off < m->m_len)
        !          1137:                        break;
        !          1138:                off -= m->m_len;
        !          1139:                m = m->m_next;
        !          1140:        }
        !          1141:        while (len > 0) {
        !          1142:                if (m == 0)
        !          1143:                        panic("m_copydata");
        !          1144:                count = MIN(m->m_len - off, len);
        !          1145:                bcopy(mtod(m, caddr_t) + off, cp, count);
        !          1146:                len -= count;
        !          1147:                cp += count;
        !          1148:                off = 0;
        !          1149:                m = m->m_next;
        !          1150:        }
        !          1151: }
        !          1152: 
        !          1153: 
        !          1154: # ifndef linux
        !          1155: /*
        !          1156:  * Copy data from a buffer back into the indicated mbuf chain,
        !          1157:  * starting "off" bytes from the beginning, extending the mbuf
        !          1158:  * chain if necessary.
        !          1159:  */
        !          1160: void
        !          1161: m_copyback(m0, off, len, cp)
        !          1162:        struct  mbuf *m0;
        !          1163:        register int off;
        !          1164:        register int len;
        !          1165:        caddr_t cp;
        !          1166: {
        !          1167:        register int mlen;
        !          1168:        register struct mbuf *m = m0, *n;
        !          1169:        int totlen = 0;
        !          1170: 
        !          1171:        if (m0 == 0)
        !          1172:                return;
        !          1173:        while (off > (mlen = m->m_len)) {
        !          1174:                off -= mlen;
        !          1175:                totlen += mlen;
        !          1176:                if (m->m_next == 0) {
        !          1177:                        n = m_getclr(M_DONTWAIT, m->m_type);
        !          1178:                        if (n == 0)
        !          1179:                                goto out;
        !          1180:                        n->m_len = min(MLEN, len + off);
        !          1181:                        m->m_next = n;
        !          1182:                }
        !          1183:                m = m->m_next;
        !          1184:        }
        !          1185:        while (len > 0) {
        !          1186:                mlen = min (m->m_len - off, len);
        !          1187:                bcopy(cp, off + mtod(m, caddr_t), (unsigned)mlen);
        !          1188:                cp += mlen;
        !          1189:                len -= mlen;
        !          1190:                mlen += off;
        !          1191:                off = 0;
        !          1192:                totlen += mlen;
        !          1193:                if (len == 0)
        !          1194:                        break;
        !          1195:                if (m->m_next == 0) {
        !          1196:                        n = m_get(M_DONTWAIT, m->m_type);
        !          1197:                        if (n == 0)
        !          1198:                                break;
        !          1199:                        n->m_len = min(MLEN, len);
        !          1200:                        m->m_next = n;
        !          1201:                }
        !          1202:                m = m->m_next;
        !          1203:        }
        !          1204: out:
        !          1205: #if 0
        !          1206:        if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen))
        !          1207:                m->m_pkthdr.len = totlen;
        !          1208: #endif
        !          1209:        return;
        !          1210: }
        !          1211: # endif /* linux */
        !          1212: #endif /* (KERNEL) && ( ((BSD < 199306) && !SOLARIS) || __sgi) */
        !          1213: 
        !          1214: 
        !          1215: frgroup_t *fr_findgroup(num, flags, which, set, fgpp)
        !          1216: u_short num;
        !          1217: u_32_t flags;
        !          1218: int which, set;
        !          1219: frgroup_t ***fgpp;
        !          1220: {
        !          1221:        frgroup_t *fg, **fgp;
        !          1222: 
        !          1223:        if (which == IPL_LOGAUTH)
        !          1224:                fgp = &ipfgroups[2][set];
        !          1225:        else if (flags & FR_ACCOUNT)
        !          1226:                fgp = &ipfgroups[1][set];
        !          1227:        else if (flags & (FR_OUTQUE|FR_INQUE))
        !          1228:                fgp = &ipfgroups[0][set];
        !          1229:        else
        !          1230:                return NULL;
        !          1231: 
        !          1232:        while ((fg = *fgp))
        !          1233:                if (fg->fg_num == num)
        !          1234:                        break;
        !          1235:                else
        !          1236:                        fgp = &fg->fg_next;
        !          1237:        if (fgpp)
        !          1238:                *fgpp = fgp;
        !          1239:        return fg;
        !          1240: }
        !          1241: 
        !          1242: 
        !          1243: frgroup_t *fr_addgroup(num, fp, which, set)
        !          1244: u_short num;
        !          1245: frentry_t *fp;
        !          1246: int which, set;
        !          1247: {
        !          1248:        frgroup_t *fg, **fgp;
        !          1249: 
        !          1250:        if ((fg = fr_findgroup(num, fp->fr_flags, which, set, &fgp)))
        !          1251:                return fg;
        !          1252: 
        !          1253:        KMALLOC(fg, frgroup_t *, sizeof(*fg));
        !          1254:        if (fg) {
        !          1255:                fg->fg_num = num;
        !          1256:                fg->fg_next = *fgp;
        !          1257:                fg->fg_head = fp;
        !          1258:                fg->fg_start = &fp->fr_grp;
        !          1259:                *fgp = fg;
        !          1260:        }
        !          1261:        return fg;
        !          1262: }
        !          1263: 
        !          1264: 
        !          1265: void fr_delgroup(num, flags, which, set)
        !          1266: u_short num;
        !          1267: u_32_t flags;
        !          1268: int which, set;
        !          1269: {
        !          1270:        frgroup_t *fg, **fgp;
        !          1271:  
        !          1272:        if (!(fg = fr_findgroup(num, flags, which, set, &fgp)))
        !          1273:                return;
        !          1274:  
        !          1275:        *fgp = fg->fg_next;
        !          1276:        KFREE(fg);
        !          1277: }
        !          1278: 
        !          1279: 
        !          1280: 
        !          1281: /*
        !          1282:  * recursively flush rules from the list, descending groups as they are
        !          1283:  * encountered.  if a rule is the head of a group and it has lost all its
        !          1284:  * group members, then also delete the group reference.
        !          1285:  */
        !          1286: static int frflushlist(set, unit, nfreedp, list, listp)
        !          1287: int set, unit, *nfreedp;
        !          1288: frentry_t *list, **listp;
        !          1289: {
        !          1290:        register frentry_t *fp = list, *fpn;
        !          1291:        register int freed = 0;
        !          1292: 
        !          1293:        while (fp) {
        !          1294:                fpn = fp->fr_next;
        !          1295:                if (fp->fr_grp) {
        !          1296:                        fp->fr_ref -= frflushlist(set, unit, nfreedp,
        !          1297:                                                  fp->fr_grp, &fp->fr_grp);
        !          1298:                }
        !          1299: 
        !          1300:                if (fp->fr_ref == 1) {
        !          1301:                        if (fp->fr_grhead)
        !          1302:                                fr_delgroup(fp->fr_grhead, fp->fr_flags, unit,
        !          1303:                                            set);
        !          1304:                        KFREE(fp);
        !          1305:                        *listp = fpn;
        !          1306:                        freed++;
        !          1307:                }
        !          1308:                fp = fpn;
        !          1309:        }
        !          1310:        *nfreedp += freed;
        !          1311:        return freed;
        !          1312: }
        !          1313: 
        !          1314: 
        !          1315: void frflush(unit, result)
        !          1316: int unit;
        !          1317: int *result;
        !          1318: {
        !          1319:        int flags = *result, flushed = 0, set = fr_active;
        !          1320: 
        !          1321:        bzero((char *)frcache, sizeof(frcache[0]) * 2);
        !          1322: 
        !          1323:        if (flags & FR_INACTIVE)
        !          1324:                set = 1 - set;
        !          1325: 
        !          1326:        if (unit == IPL_LOGIPF) {
        !          1327:                if (flags & FR_OUTQUE) {
        !          1328:                        (void) frflushlist(set, unit, &flushed,
        !          1329:                                           ipfilter[1][set],
        !          1330:                                           &ipfilter[1][set]);
        !          1331:                        (void) frflushlist(set, unit, &flushed,
        !          1332:                                           ipacct[1][set], &ipacct[1][set]);
        !          1333:                }
        !          1334:                if (flags & FR_INQUE) {
        !          1335:                        (void) frflushlist(set, unit, &flushed,
        !          1336:                                           ipfilter[0][set],
        !          1337:                                           &ipfilter[0][set]);
        !          1338:                        (void) frflushlist(set, unit, &flushed,
        !          1339:                                           ipacct[0][set], &ipacct[0][set]);
        !          1340:                }
        !          1341:        }
        !          1342: 
        !          1343:        *result = flushed;
        !          1344: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.