Annotation of XNU/bsd/netinet/ip_log.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) 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:  */
        !            30: #include "opt_ipfilter.h"
        !            31: 
        !            32: #if    IPFILTER_LOG
        !            33: # ifndef SOLARIS
        !            34: #  define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
        !            35: # endif
        !            36: 
        !            37: # if defined(KERNEL) && !defined(_KERNEL)
        !            38: #  define       _KERNEL
        !            39: # endif
        !            40: # ifdef  __FreeBSD__
        !            41: #  if defined(_KERNEL) && !defined(IPFILTER_LKM)
        !            42: #   define __FreeBSD_version 300000    /* this will do as a hack */
        !            43: #  else
        !            44: #   include <osreldate.h>
        !            45: #  endif
        !            46: # endif
        !            47: # ifndef _KERNEL
        !            48: #  include <stdio.h>
        !            49: #  include <string.h>
        !            50: #  include <stdlib.h>
        !            51: #  include <ctype.h>
        !            52: # endif
        !            53: # include <sys/errno.h>
        !            54: # include <sys/types.h>
        !            55: # include <sys/param.h>
        !            56: # include <sys/file.h>
        !            57: # if __FreeBSD_version >= 220000 && defined(_KERNEL)
        !            58: #  include <sys/fcntl.h>
        !            59: #  include <sys/filio.h>
        !            60: # else
        !            61: #  include <sys/ioctl.h>
        !            62: # endif
        !            63: # include <sys/time.h>
        !            64: # if defined(_KERNEL) && !defined(linux)
        !            65: #  include <sys/systm.h>
        !            66: # endif
        !            67: # include <sys/uio.h>
        !            68: # if !SOLARIS
        !            69: #  if (NetBSD > 199609) || (OpenBSD > 199603) || defined(__FreeBSD__)
        !            70: #   include <sys/dirent.h>
        !            71: #  else
        !            72: #   include <sys/dir.h>
        !            73: #  endif
        !            74: #  ifndef linux
        !            75: #   include <sys/mbuf.h>
        !            76: #  endif
        !            77: # else
        !            78: #  include <sys/filio.h>
        !            79: #  include <sys/cred.h>
        !            80: #  include <sys/ddi.h>
        !            81: #  include <sys/sunddi.h>
        !            82: #  include <sys/ksynch.h>
        !            83: #  include <sys/kmem.h>
        !            84: #  include <sys/mkdev.h>
        !            85: #  include <sys/dditypes.h>
        !            86: #  include <sys/cmn_err.h>
        !            87: # endif
        !            88: # ifndef linux
        !            89: #  include <sys/protosw.h>
        !            90: # endif
        !            91: # include <sys/socket.h>
        !            92: 
        !            93: # include <net/if.h>
        !            94: # ifdef sun
        !            95: #  include <net/af.h>
        !            96: # endif
        !            97: # if __FreeBSD_version >= 300000
        !            98: #  include <sys/malloc.h>
        !            99: #  include <machine/random.h>
        !           100: # endif
        !           101: # include <net/route.h>
        !           102: # include <netinet/in.h>
        !           103: # ifdef __sgi
        !           104: #  include <sys/ddi.h>
        !           105: #  ifdef IFF_DRVRLOCK /* IRIX6 */
        !           106: #   include <sys/hashing.h>
        !           107: #  endif
        !           108: # endif
        !           109: # if !defined(linux) && !(defined(__sgi) && !defined(IFF_DRVRLOCK)) /*IRIX<6*/
        !           110: #  include <netinet/in_var.h>
        !           111: # endif
        !           112: # include <netinet/in_systm.h>
        !           113: # include <netinet/ip.h>
        !           114: # include <netinet/tcp.h>
        !           115: # include <netinet/udp.h>
        !           116: # include <netinet/ip_icmp.h>
        !           117: # ifndef linux
        !           118: #  include <netinet/ip_var.h>
        !           119: # endif
        !           120: # ifndef _KERNEL
        !           121: #  include <syslog.h>
        !           122: # endif
        !           123: # include "netinet/ip_compat.h"
        !           124: # include <netinet/tcpip.h>
        !           125: # include "netinet/ip_fil.h"
        !           126: # include "netinet/ip_proxy.h"
        !           127: # include "netinet/ip_nat.h"
        !           128: # include "netinet/ip_frag.h"
        !           129: # include "netinet/ip_state.h"
        !           130: # include "netinet/ip_auth.h"
        !           131: # ifndef MIN
        !           132: #  define      MIN(a,b)        (((a)<(b))?(a):(b))
        !           133: # endif
        !           134: 
        !           135: 
        !           136: # if SOLARIS || defined(__sgi)
        !           137: extern kmutex_t        ipl_mutex;
        !           138: #  if SOLARIS
        !           139: extern kcondvar_t      iplwait;
        !           140: #  endif
        !           141: # endif
        !           142: 
        !           143: iplog_t        **iplh[IPL_LOGMAX+1], *iplt[IPL_LOGMAX+1];
        !           144: int    iplused[IPL_LOGMAX+1];
        !           145: static u_long  iplcrc[IPL_LOGMAX+1];
        !           146: static u_long  iplcrcinit;
        !           147: #ifdef linux
        !           148: static struct wait_queue *iplwait[IPL_LOGMAX+1];
        !           149: #endif
        !           150: 
        !           151: 
        !           152: /*
        !           153:  * Initialise log buffers & pointers.  Also iniialised the CRC to a local
        !           154:  * secret for use in calculating the "last log checksum".
        !           155:  */
        !           156: void ipflog_init()
        !           157: {
        !           158:        int     i;
        !           159: 
        !           160:        for (i = IPL_LOGMAX; i >= 0; i--) {
        !           161:                iplt[i] = NULL;
        !           162:                iplh[i] = &iplt[i];
        !           163:                iplused[i] = 0;
        !           164:        }
        !           165: # if defined(__FreeBSD__) &&  __FreeBSD_version >= 300000
        !           166:        read_random(&iplcrcinit, sizeof iplcrcinit);
        !           167: # else
        !           168:        {
        !           169:                struct timeval tv;
        !           170: 
        !           171: #if BSD >= 199306 || defined(__FreeBSD__) || defined(__sgi)
        !           172:                microtime(&tv);
        !           173: # else
        !           174:                uniqtime(&tv);
        !           175: # endif
        !           176:                iplcrcinit = tv.tv_sec ^ (tv.tv_usec << 8) ^ tv.tv_usec;
        !           177:        }
        !           178: # endif
        !           179: }
        !           180: 
        !           181: 
        !           182: /*
        !           183:  * ipflog
        !           184:  * Create a log record for a packet given that it has been triggered by a
        !           185:  * rule (or the default setting).  Calculate the transport protocol header
        !           186:  * size using predetermined size of a couple of popular protocols and thus
        !           187:  * how much data to copy into the log, including part of the data body if
        !           188:  * requested.
        !           189:  */
        !           190: int ipflog(flags, ip, fin, m)
        !           191: u_int flags;
        !           192: ip_t *ip;
        !           193: fr_info_t *fin;
        !           194: mb_t *m;
        !           195: {
        !           196:        ipflog_t ipfl;
        !           197:        register int mlen, hlen;
        !           198:        u_long crc;
        !           199:        size_t sizes[2];
        !           200:        void *ptrs[2];
        !           201:        int types[2];
        !           202: # if SOLARIS
        !           203:        ill_t *ifp = fin->fin_ifp;
        !           204: # else
        !           205:        struct ifnet *ifp = fin->fin_ifp;
        !           206: # endif
        !           207: 
        !           208:        /*
        !           209:         * calculate header size.
        !           210:         */
        !           211:        hlen = fin->fin_hlen;
        !           212:        if (ip->ip_p == IPPROTO_TCP)
        !           213:                hlen += MIN(sizeof(tcphdr_t), fin->fin_dlen);
        !           214:        else if (ip->ip_p == IPPROTO_UDP)
        !           215:                hlen += MIN(sizeof(udphdr_t), fin->fin_dlen);
        !           216:        else if (ip->ip_p == IPPROTO_ICMP) {
        !           217:                struct  icmp    *icmp = (struct icmp *)((char *)ip + hlen);
        !           218:  
        !           219:                /*
        !           220:                 * For ICMP, if the packet is an error packet, also include
        !           221:                 * the information about the packet which caused the error.
        !           222:                 */
        !           223:                switch (icmp->icmp_type)
        !           224:                {
        !           225:                case ICMP_UNREACH :
        !           226:                case ICMP_SOURCEQUENCH :
        !           227:                case ICMP_REDIRECT :
        !           228:                case ICMP_TIMXCEED :
        !           229:                case ICMP_PARAMPROB :
        !           230:                        hlen += MIN(sizeof(struct icmp) + 8, fin->fin_dlen);
        !           231:                        break;
        !           232:                default :
        !           233:                        hlen += MIN(sizeof(struct icmp), fin->fin_dlen);
        !           234:                        break;
        !           235:                }
        !           236:        }
        !           237:        /*
        !           238:         * Get the interface number and name to which this packet is
        !           239:         * currently associated.
        !           240:         */
        !           241: # if SOLARIS
        !           242:        ipfl.fl_unit = (u_char)ifp->ill_ppa;
        !           243:        bcopy(ifp->ill_name, ipfl.fl_ifname, MIN(ifp->ill_name_length, 4));
        !           244:        mlen = (flags & FR_LOGBODY) ? MIN(msgdsize(m) - hlen, 128) : 0;
        !           245: # else
        !           246: #  if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603)) || \
        !           247:        (defined(OpenBSD) && (OpenBSD >= 199603))
        !           248:        strncpy(ipfl.fl_ifname, ifp->if_xname, IFNAMSIZ);
        !           249: #  else
        !           250: #   ifndef linux
        !           251:        ipfl.fl_unit = (u_char)ifp->if_unit;
        !           252: #   endif
        !           253:        if ((ipfl.fl_ifname[0] = ifp->if_name[0]))
        !           254:                if ((ipfl.fl_ifname[1] = ifp->if_name[1]))
        !           255:                        if ((ipfl.fl_ifname[2] = ifp->if_name[2]))
        !           256:                                ipfl.fl_ifname[3] = ifp->if_name[3];
        !           257: #  endif
        !           258:        mlen = (flags & FR_LOGBODY) ? MIN(ip->ip_len - hlen, 128) : 0;
        !           259: # endif
        !           260:        ipfl.fl_plen = (u_char)mlen;
        !           261:        ipfl.fl_hlen = (u_char)hlen;
        !           262:        ipfl.fl_rule = fin->fin_rule;
        !           263:        ipfl.fl_group = fin->fin_group;
        !           264:        ipfl.fl_flags = flags;
        !           265:        ptrs[0] = (void *)&ipfl;
        !           266:        sizes[0] = sizeof(ipfl);
        !           267:        types[0] = 0;
        !           268: #if SOLARIS
        !           269:        /*
        !           270:         * Are we copied from the mblk or an aligned array ?
        !           271:         */
        !           272:        if (ip == (ip_t *)m->b_rptr) {
        !           273:                ptrs[1] = m;
        !           274:                sizes[1] = hlen + mlen;
        !           275:                types[1] = 1;
        !           276:        } else {
        !           277:                ptrs[1] = ip;
        !           278:                sizes[1] = hlen + mlen;
        !           279:                types[1] = 0;
        !           280:        }
        !           281: #else
        !           282:        ptrs[1] = m;
        !           283:        sizes[1] = hlen + mlen;
        !           284:        types[1] = 1;
        !           285: #endif
        !           286:        crc = (ipf_cksum((u_short *)fin, FI_CSIZE) << 8) + iplcrcinit;
        !           287:        return ipllog(IPL_LOGIPF, crc, ptrs, sizes, types, 2);
        !           288: }
        !           289: 
        !           290: 
        !           291: /*
        !           292:  * ipllog
        !           293:  */
        !           294: int ipllog(dev, crc, items, itemsz, types, cnt)
        !           295: int dev;
        !           296: u_long crc;
        !           297: void **items;
        !           298: size_t *itemsz;
        !           299: int *types, cnt;
        !           300: {
        !           301:        iplog_t *ipl;
        !           302:        caddr_t buf, s;
        !           303:        int len, i;
        !           304:  
        !           305:        /*
        !           306:         * Check to see if this log record has a CRC which matches the last
        !           307:         * record logged.  If it does, just up the count on the previous one
        !           308:         * rather than create a new one.
        !           309:         */
        !           310:        if (crc) {
        !           311:                MUTEX_ENTER(&ipl_mutex);
        !           312:                if ((iplcrc[dev] == crc) && *iplh[dev]) {
        !           313:                        (*iplh[dev])->ipl_count++;
        !           314:                        MUTEX_EXIT(&ipl_mutex);
        !           315:                        return 1;
        !           316:                }
        !           317:                iplcrc[dev] = crc;
        !           318:                MUTEX_EXIT(&ipl_mutex);
        !           319:        }
        !           320: 
        !           321:        /*
        !           322:         * Get the total amount of data to be logged.
        !           323:         */
        !           324:        for (i = 0, len = sizeof(iplog_t); i < cnt; i++)
        !           325:                len += itemsz[i];
        !           326: 
        !           327:        /*
        !           328:         * check that we have space to record this information and can
        !           329:         * allocate that much.
        !           330:         */
        !           331:        KMALLOC(buf, caddr_t, len);
        !           332:        if (!buf)
        !           333:                return 0;
        !           334:        MUTEX_ENTER(&ipl_mutex);
        !           335:        if ((iplused[dev] + len) > IPLLOGSIZE) {
        !           336:                MUTEX_EXIT(&ipl_mutex);
        !           337:                KFREES(buf, len);
        !           338:                return 0;
        !           339:        }
        !           340:        iplused[dev] += len;
        !           341:        MUTEX_EXIT(&ipl_mutex);
        !           342: 
        !           343:        /*
        !           344:         * advance the log pointer to the next empty record and deduct the
        !           345:         * amount of space we're going to use.
        !           346:         */
        !           347:        ipl = (iplog_t *)buf;
        !           348:        ipl->ipl_magic = IPL_MAGIC;
        !           349:        ipl->ipl_count = 1;
        !           350:        ipl->ipl_next = NULL;
        !           351:        ipl->ipl_dsize = len;
        !           352: # if SOLARIS || defined(sun) || defined(linux)
        !           353:        uniqtime((struct timeval *)&ipl->ipl_sec);
        !           354: # else
        !           355: #  if BSD >= 199306 || defined(__FreeBSD__) || defined(__sgi)
        !           356:        microtime((struct timeval *)&ipl->ipl_sec);
        !           357: #  endif
        !           358: # endif
        !           359: 
        !           360:        /*
        !           361:         * Loop through all the items to be logged, copying each one to the
        !           362:         * buffer.  Use bcopy for normal data or the mb_t copyout routine.
        !           363:         */
        !           364:        for (i = 0, s = buf + sizeof(*ipl); i < cnt; i++) {
        !           365:                if (types[i] == 0)
        !           366:                        bcopy(items[i], s, itemsz[i]);
        !           367:                else if (types[i] == 1) {
        !           368: # if SOLARIS
        !           369:                        copyout_mblk(items[i], 0, itemsz[i], s);
        !           370: # else
        !           371:                        m_copydata(items[i], 0, itemsz[i], s);
        !           372: # endif
        !           373:                }
        !           374:                s += itemsz[i];
        !           375:        }
        !           376:        MUTEX_ENTER(&ipl_mutex);
        !           377:        *iplh[dev] = ipl;
        !           378:        iplh[dev] = &ipl->ipl_next;
        !           379: # if SOLARIS
        !           380:        cv_signal(&iplwait);
        !           381:        mutex_exit(&ipl_mutex);
        !           382: # else
        !           383:        MUTEX_EXIT(&ipl_mutex);
        !           384: #  ifdef linux
        !           385:        wake_up_interruptible(&iplwait[dev]);
        !           386: #  else
        !           387:        wakeup(&iplh[dev]);
        !           388: #  endif
        !           389: # endif
        !           390:        return 1;
        !           391: }
        !           392: 
        !           393: 
        !           394: int ipflog_read(unit, uio)
        !           395: int unit;
        !           396: struct uio *uio;
        !           397: {
        !           398:        iplog_t *ipl;
        !           399:        int error = 0, dlen, copied;
        !           400: # if defined(_KERNEL) && !SOLARIS
        !           401:        int s;
        !           402: # endif
        !           403: 
        !           404:        /*
        !           405:         * Sanity checks.  Make sure the minor # is valid and we're copying
        !           406:         * a valid chunk of data.
        !           407:         */
        !           408:        if ((IPL_LOGMAX < unit) || (unit < 0))
        !           409:                return ENXIO;
        !           410:        if (!uio->uio_resid)
        !           411:                return 0;
        !           412:        if ((uio->uio_resid < sizeof(iplog_t)) ||
        !           413:            (uio->uio_resid > IPLLOGSIZE))
        !           414:                return EINVAL;
        !           415:  
        !           416:        /*
        !           417:         * Lock the log so we can snapshot the variables.  Wait for a signal
        !           418:         * if the log is empty.
        !           419:         */
        !           420:        SPL_NET(s);
        !           421:        MUTEX_ENTER(&ipl_mutex);
        !           422: 
        !           423:        while (!iplused[unit] || !iplt[unit]) {
        !           424: # if SOLARIS && defined(_KERNEL)
        !           425:                if (!cv_wait_sig(&iplwait, &ipl_mutex)) {
        !           426:                        MUTEX_EXIT(&ipl_mutex);
        !           427:                        return EINTR;
        !           428:                }
        !           429: # else
        !           430: #  ifdef linux
        !           431:                interruptible_sleep_on(&iplwait[unit]);
        !           432:                if (current->signal & ~current->blocked)
        !           433:                        return -EINTR;
        !           434: #  else
        !           435:                MUTEX_EXIT(&ipl_mutex);
        !           436:                SPL_X(s);
        !           437:                error = SLEEP(&iplh[unit], "ipl sleep");
        !           438:                if (error)
        !           439:                        return error;
        !           440:                SPL_NET(s);
        !           441:                MUTEX_ENTER(&ipl_mutex);
        !           442: #  endif /* linux */
        !           443: # endif /* SOLARIS */
        !           444:        }
        !           445: 
        !           446: # if BSD >= 199306 || defined(__FreeBSD__)
        !           447:        uio->uio_rw = UIO_READ;
        !           448: # endif
        !           449: 
        !           450:        for (copied = 0; (ipl = iplt[unit]); copied += dlen) {
        !           451:                dlen = ipl->ipl_dsize;
        !           452:                if (dlen + sizeof(iplog_t) > uio->uio_resid)
        !           453:                        break;
        !           454:                /*
        !           455:                 * Don't hold the mutex over the uiomove call.
        !           456:                 */
        !           457:                iplt[unit] = ipl->ipl_next;
        !           458:                MUTEX_EXIT(&ipl_mutex);
        !           459:                SPL_X(s);
        !           460:                error = UIOMOVE((caddr_t)ipl, ipl->ipl_dsize, UIO_READ, uio);
        !           461:                KFREES((caddr_t)ipl, ipl->ipl_dsize);
        !           462:                if (error)
        !           463:                        break;
        !           464:                SPL_NET(s);
        !           465:                MUTEX_ENTER(&ipl_mutex);
        !           466:                iplused[unit] -= dlen;
        !           467:        }
        !           468:        if (!ipl) {
        !           469:                iplused[unit] = 0;
        !           470:                iplh[unit] = &iplt[unit];
        !           471:        }
        !           472: 
        !           473:        if (!error) {
        !           474:                MUTEX_EXIT(&ipl_mutex);
        !           475:                SPL_X(s);
        !           476:        }
        !           477: #ifdef         linux
        !           478:        if (!error)
        !           479:                return copied;
        !           480:        return -error;
        !           481: #else
        !           482:        return error;
        !           483: #endif
        !           484: }
        !           485: 
        !           486: 
        !           487: int ipflog_clear(unit)
        !           488: int unit;
        !           489: {
        !           490:        iplog_t *ipl;
        !           491:        int used;
        !           492: 
        !           493:        while ((ipl = iplt[unit])) {
        !           494:                iplt[unit] = ipl->ipl_next;
        !           495:                KFREES((caddr_t)ipl, ipl->ipl_dsize);
        !           496:        }
        !           497:        iplh[unit] = &iplt[unit];
        !           498:        used = iplused[unit];
        !           499:        iplused[unit] = 0;
        !           500:        iplcrc[unit] = 0;
        !           501:        return used;
        !           502: }
        !           503: #endif /* IPFILTER_LOG */

unix.superglobalmegacorp.com

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