Annotation of XNU/bsd/netinet/fil.c, revision 1.1.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.