Annotation of XNU/bsd/netinet/ip_auth.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) 1997 by Darren Reed & Guido van Rooij.
                     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: #define __FreeBSD_version 300000       /* just a hack - no <sys/osreldate.h> */
                     31: 
                     32: #if !defined(KERNEL)
                     33: # include <stdlib.h>
                     34: # include <string.h>
                     35: #endif
                     36: #include <sys/errno.h>
                     37: #include <sys/types.h>
                     38: #include <sys/param.h>
                     39: #include <sys/time.h>
                     40: #include <sys/file.h>
                     41: #if defined(KERNEL) && (__FreeBSD_version >= 220000)
                     42: # include <sys/filio.h>
                     43: # include <sys/fcntl.h>
                     44: #else
                     45: # include <sys/ioctl.h>
                     46: #endif
                     47: #include <sys/uio.h>
                     48: #ifndef linux
                     49: # include <sys/protosw.h>
                     50: #endif
                     51: #include <sys/socket.h>
                     52: #if defined(KERNEL) 
                     53: # include <sys/systm.h>
                     54: #endif
                     55: #if !defined(__SVR4) && !defined(__svr4__)
                     56: # ifndef linux
                     57: #  include <sys/mbuf.h>
                     58: # endif
                     59: #else
                     60: # include <sys/filio.h>
                     61: # include <sys/byteorder.h>
                     62: # include <sys/dditypes.h>
                     63: # include <sys/stream.h>
                     64: # include <sys/kmem.h>
                     65: #endif
                     66: #if defined(KERNEL) && (__FreeBSD_version >= 300000)
                     67: # include <sys/malloc.h>
                     68: #endif
                     69: #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(bsdi)
                     70: # include <kern/cpu_number.h>
                     71: #endif
                     72: #include <net/if.h>
                     73: #ifdef sun
                     74: #include <net/af.h>
                     75: #endif
                     76: #if !defined(KERNEL) && (__FreeBSD_version >= 300000)
                     77: # include <net/if_var.h>
                     78: #endif
                     79: #include <net/route.h>
                     80: #include <netinet/in.h>
                     81: #include <netinet/in_systm.h>
                     82: #include <netinet/ip.h>
                     83: #ifndef        KERNEL
                     84: #define        KERNEL
                     85: #define        NOT_KERNEL
                     86: #endif
                     87: #ifndef linux
                     88: # include <netinet/ip_var.h>
                     89: #endif
                     90: #ifdef NOT_KERNEL
                     91: #undef KERNEL
                     92: #endif
                     93: #ifdef __sgi
                     94: # ifdef IFF_DRVRLOCK /* IRIX6 */
                     95: #include <sys/hashing.h>
                     96: # endif
                     97: #endif
                     98: #include <netinet/tcp.h>
                     99: #if defined(__sgi) && !defined(IFF_DRVRLOCK) /* IRIX < 6 */
                    100: extern struct ifqueue   ipintrq;                /* ip packet input queue */
                    101: #else
                    102: # ifndef linux
                    103: #  include <netinet/in_var.h>
                    104: #  include <netinet/tcp_fsm.h>
                    105: # endif
                    106: #endif
                    107: #include <netinet/udp.h>
                    108: #include <netinet/ip_icmp.h>
                    109: #include "netinet/ip_compat.h"
                    110: #include <netinet/tcpip.h>
                    111: #include "netinet/ip_fil.h"
                    112: #include "netinet/ip_auth.h"
                    113: #if !SOLARIS && !defined(linux)
                    114: # include <net/netisr.h>
                    115: # ifdef __FreeBSD__
                    116: #  include <machine/cpufunc.h>
                    117: # endif
                    118: #endif
                    119: 
                    120: 
                    121: #if (SOLARIS || defined(__sgi)) && defined(_KERNEL)
                    122: extern kmutex_t ipf_auth;
                    123: # if SOLARIS
                    124: extern kcondvar_t ipfauthwait;
                    125: # endif
                    126: #endif
                    127: #ifdef linux
                    128: static struct wait_queue *ipfauthwait = NULL;
                    129: #endif
                    130: 
                    131: int    fr_authsize = FR_NUMAUTH;
                    132: int    fr_authused = 0;
                    133: int    fr_defaultauthage = 600;
                    134: fr_authstat_t  fr_authstats;
                    135: static frauth_t fr_auth[FR_NUMAUTH];
                    136: mb_t   *fr_authpkts[FR_NUMAUTH];
                    137: static int     fr_authstart = 0, fr_authend = 0, fr_authnext = 0;
                    138: static frauthent_t     *fae_list = NULL;
                    139: frentry_t      *ipauth = NULL;
                    140: 
                    141: 
                    142: /*
                    143:  * Check if a packet has authorization.  If the packet is found to match an
                    144:  * authorization result and that would result in a feedback loop (i.e. it
                    145:  * will end up returning FR_AUTH) then return FR_BLOCK instead.
                    146:  */
                    147: int fr_checkauth(ip, fin)
                    148: ip_t *ip;
                    149: fr_info_t *fin;
                    150: {
                    151:        u_short id = ip->ip_id;
                    152:        u_32_t pass;
                    153:        int i;
                    154: 
                    155:        MUTEX_ENTER(&ipf_auth);
                    156:        for (i = fr_authstart; i != fr_authend; ) {
                    157:                /*
                    158:                 * index becomes -2 only after an SIOCAUTHW.  Check this in
                    159:                 * case the same packet gets sent again and it hasn't yet been
                    160:                 * auth'd.
                    161:                 */
                    162:                if ((fr_auth[i].fra_index == -2) &&
                    163:                    (id == fr_auth[i].fra_info.fin_id) &&
                    164:                    !bcmp((char *)fin,(char *)&fr_auth[i].fra_info,FI_CSIZE)) {
                    165:                        /*
                    166:                         * Avoid feedback loop.
                    167:                         */
                    168:                        if (!(pass = fr_auth[i].fra_pass) || (pass & FR_AUTH))
                    169:                                pass = FR_BLOCK;
                    170:                        fr_authstats.fas_hits++;
                    171:                        fr_auth[i].fra_index = -1;
                    172:                        fr_authused--;
                    173:                        if (i == fr_authstart) {
                    174:                                while (fr_auth[i].fra_index == -1) {
                    175:                                        i++;
                    176:                                        if (i == FR_NUMAUTH)
                    177:                                                i = 0;
                    178:                                        fr_authstart = i;
                    179:                                        if (i == fr_authend)
                    180:                                                break;
                    181:                                }
                    182:                                if (fr_authstart == fr_authend) {
                    183:                                        fr_authnext = 0;
                    184:                                        fr_authstart = fr_authend = 0;
                    185:                                }
                    186:                        }
                    187:                        MUTEX_EXIT(&ipf_auth);
                    188:                        return pass;
                    189:                }
                    190:                i++;
                    191:                if (i == FR_NUMAUTH)
                    192:                        i = 0;
                    193:        }
                    194:        fr_authstats.fas_miss++;
                    195:        MUTEX_EXIT(&ipf_auth);
                    196:        return 0;
                    197: }
                    198: 
                    199: 
                    200: /*
                    201:  * Check if we have room in the auth array to hold details for another packet.
                    202:  * If we do, store it and wake up any user programs which are waiting to
                    203:  * hear about these events.
                    204:  */
                    205: int fr_newauth(m, fin, ip
                    206: #if defined(_KERNEL) && SOLARIS
                    207: , qif)
                    208: qif_t *qif;
                    209: #else
                    210: )
                    211: #endif
                    212: mb_t *m;
                    213: fr_info_t *fin;
                    214: ip_t *ip;
                    215: {
                    216:        int i;
                    217: 
                    218:        MUTEX_ENTER(&ipf_auth);
                    219:        if ((fr_authstart > fr_authend) && (fr_authstart - fr_authend == -1)) {
                    220:                fr_authstats.fas_nospace++;
                    221:                MUTEX_EXIT(&ipf_auth);
                    222:                return 0;
                    223:        }
                    224:        if (fr_authend - fr_authstart == FR_NUMAUTH - 1) {
                    225:                fr_authstats.fas_nospace++;
                    226:                MUTEX_EXIT(&ipf_auth);
                    227:                return 0;
                    228:        }
                    229: 
                    230:        fr_authstats.fas_added++;
                    231:        fr_authused++;
                    232:        i = fr_authend++;
                    233:        if (fr_authend == FR_NUMAUTH)
                    234:                fr_authend = 0;
                    235:        MUTEX_EXIT(&ipf_auth);
                    236:        fr_auth[i].fra_index = i;
                    237:        fr_auth[i].fra_pass = 0;
                    238:        fr_auth[i].fra_age = fr_defaultauthage;
                    239:        bcopy((char *)fin, (char *)&fr_auth[i].fra_info, sizeof(*fin));
                    240: #if !defined(sparc) && !defined(m68k)
                    241:        /*
                    242:         * No need to copyback here as we want to undo the changes, not keep
                    243:         * them.
                    244:         */
                    245: # if SOLARIS && defined(KERNEL)
                    246:        if (ip == (ip_t *)m->b_rptr)
                    247: # endif
                    248:        {
                    249:                register u_short bo;
                    250: 
                    251:                bo = ip->ip_len;
                    252:                ip->ip_len = htons(bo);
                    253: # if !SOLARIS  /* 4.4BSD converts this ip_input.c, but I don't in solaris.c */
                    254:                bo = ip->ip_id;
                    255:                ip->ip_id = htons(bo);
                    256: # endif
                    257:                bo = ip->ip_off;
                    258:                ip->ip_off = htons(bo);
                    259:        }
                    260: #endif
                    261: #if SOLARIS && defined(KERNEL)
                    262:        m->b_rptr -= qif->qf_off;
                    263:        fr_authpkts[i] = *(mblk_t **)fin->fin_mp;
                    264:        fr_auth[i].fra_q = qif->qf_q;
                    265:        cv_signal(&ipfauthwait);
                    266: #else
                    267:        fr_authpkts[i] = m;
                    268: # if defined(linux) && defined(KERNEL)
                    269:        wake_up_interruptible(&ipfauthwait);
                    270: # else
                    271:        WAKEUP(&fr_authnext);
                    272: # endif
                    273: #endif
                    274:        return 1;
                    275: }
                    276: 
                    277: 
                    278: int fr_auth_ioctl(data, cmd, fr, frptr)
                    279: caddr_t data;
                    280: #if defined(__NetBSD__) || defined(__OpenBSD__) || (__FreeBSD_version >= 300003)
                    281: u_long cmd;
                    282: #else
                    283: int cmd;
                    284: #endif
                    285: frentry_t *fr, **frptr;
                    286: {
                    287:        mb_t *m;
                    288: #if defined(KERNEL)
                    289: # if !SOLARIS
                    290:        struct ifqueue *ifq;
                    291:        int s;
                    292: # endif
                    293: #endif
                    294:        frauth_t auth, *au = &auth;
                    295:        frauthent_t *fae, **faep;
                    296:        int i, error = 0;
                    297: 
                    298:        switch (cmd)
                    299:        {
                    300:        case SIOCINIFR :
                    301:        case SIOCRMIFR :
                    302:        case SIOCADIFR :
                    303:                error = EINVAL;
                    304:                break;
                    305:        case SIOCINAFR :
                    306:        case SIOCRMAFR :
                    307:        case SIOCADAFR :
                    308:                for (faep = &fae_list; (fae = *faep); )
                    309:                        if (&fae->fae_fr == fr)
                    310:                                break;
                    311:                        else
                    312:                                faep = &fae->fae_next;
                    313:                if (cmd == SIOCRMAFR) {
                    314:                        if (!fae)
                    315:                                error = ESRCH;
                    316:                        else {
                    317:                                *faep = fae->fae_next;
                    318:                                *frptr = fr->fr_next;
                    319:                                KFREE(fae);
                    320:                        }
                    321:                } else {
                    322:                        KMALLOC(fae, frauthent_t *, sizeof(*fae));
                    323:                        if (fae != NULL) {
                    324:                                IRCOPY((char *)data, (char *)&fae->fae_fr,
                    325:                                       sizeof(fae->fae_fr));
                    326:                                if (!fae->fae_age)
                    327:                                        fae->fae_age = fr_defaultauthage;
                    328:                                fae->fae_fr.fr_hits = 0;
                    329:                                fae->fae_fr.fr_next = *frptr;
                    330:                                *frptr = &fae->fae_fr;
                    331:                                fae->fae_next = *faep;
                    332:                                *faep = fae;
                    333:                        } else
                    334:                                error = ENOMEM;
                    335:                }
                    336:                break;
                    337:        case SIOCATHST:
                    338:                IWCOPY((char *)&fr_authstats, data, sizeof(fr_authstats));
                    339:                break;
                    340:        case SIOCAUTHW:
                    341: fr_authioctlloop:
                    342:                MUTEX_ENTER(&ipf_auth);
                    343:                if ((fr_authnext != fr_authend) && fr_authpkts[fr_authnext]) {
                    344:                        IWCOPY((char *)&fr_auth[fr_authnext++], data,
                    345:                               sizeof(fr_info_t));
                    346:                        if (fr_authnext == FR_NUMAUTH)
                    347:                                fr_authnext = 0;
                    348:                        MUTEX_EXIT(&ipf_auth);
                    349:                        return 0;
                    350:                }
                    351: #ifdef KERNEL
                    352: # if   SOLARIS
                    353:                if (!cv_wait_sig(&ipfauthwait, &ipf_auth)) {
                    354:                        mutex_exit(&ipf_auth);
                    355:                        return EINTR;
                    356:                }
                    357: # else
                    358: #  ifdef linux
                    359:                interruptible_sleep_on(&ipfauthwait);
                    360:                if (current->signal & ~current->blocked)
                    361:                        error = -EINTR;
                    362: #  else
                    363:                error = SLEEP(&fr_authnext, "fr_authnext");
                    364: # endif
                    365: # endif
                    366: #endif
                    367:                MUTEX_EXIT(&ipf_auth);
                    368:                if (!error)
                    369:                        goto fr_authioctlloop;
                    370:                break;
                    371:        case SIOCAUTHR:
                    372:                IRCOPY(data, (caddr_t)&auth, sizeof(auth));
                    373:                MUTEX_ENTER(&ipf_auth);
                    374:                i = au->fra_index;
                    375:                if ((i < 0) || (i > FR_NUMAUTH) ||
                    376:                    (fr_auth[i].fra_info.fin_id != au->fra_info.fin_id)) {
                    377:                        MUTEX_EXIT(&ipf_auth);
                    378:                        return EINVAL;
                    379:                }
                    380:                m = fr_authpkts[i];
                    381:                fr_auth[i].fra_index = -2;
                    382:                fr_auth[i].fra_pass = au->fra_pass;
                    383:                fr_authpkts[i] = NULL;
                    384: #ifdef KERNEL
                    385:                MUTEX_EXIT(&ipf_auth);
                    386:                SPL_NET(s);
                    387: # ifndef linux
                    388:                if (m && au->fra_info.fin_out) {
                    389: #  if SOLARIS
                    390:                        error = fr_qout(fr_auth[i].fra_q, m);
                    391: #  else /* SOLARIS */
                    392:                        error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL);
                    393: #  endif /* SOLARIS */
                    394:                        if (error)
                    395:                                fr_authstats.fas_sendfail++;
                    396:                        else
                    397:                                fr_authstats.fas_sendok++;
                    398:                } else if (m) {
                    399: # if SOLARIS
                    400:                        error = fr_qin(fr_auth[i].fra_q, m);
                    401: # else /* SOLARIS */
                    402:                        ifq = &ipintrq;
                    403:                        if (IF_QFULL(ifq)) {
                    404:                                IF_DROP(ifq);
                    405:                                m_freem(m);
                    406:                                error = ENOBUFS;
                    407:                        } else {
                    408:                                IF_ENQUEUE(ifq, m);
                    409:                                schednetisr(NETISR_IP);
                    410:                        }
                    411: # endif /* SOLARIS */
                    412:                        if (error)
                    413:                                fr_authstats.fas_quefail++;
                    414:                        else
                    415:                                fr_authstats.fas_queok++;
                    416:                } else
                    417:                        error = EINVAL;
                    418: # endif
                    419: # if SOLARIS
                    420:                if (error)
                    421:                        error = EINVAL;
                    422: # else
                    423:                /*
                    424:                 * If we experience an error which will result in the packet
                    425:                 * not being processed, make sure we advance to the next one.
                    426:                 */ 
                    427:                if (error == ENOBUFS) {
                    428:                        fr_authused--;
                    429:                        fr_auth[i].fra_index = -1;
                    430:                        fr_auth[i].fra_pass = 0;
                    431:                        if (i == fr_authstart) {
                    432:                                while (fr_auth[i].fra_index == -1) {
                    433:                                        i++;
                    434:                                        if (i == FR_NUMAUTH)
                    435:                                                i = 0;
                    436:                                        fr_authstart = i;
                    437:                                        if (i == fr_authend)
                    438:                                                break;
                    439:                                }
                    440:                                if (fr_authstart == fr_authend) {
                    441:                                        fr_authnext = 0;
                    442:                                        fr_authstart = fr_authend = 0;
                    443:                                }
                    444:                        }
                    445:                }
                    446: # endif
                    447:                SPL_X(s);
                    448: #endif /* KERNEL */
                    449:                break;
                    450:        default :
                    451:                error = EINVAL;
                    452:                break;
                    453:        }
                    454:        return error;
                    455: }
                    456: 
                    457: 
                    458: #ifdef KERNEL
                    459: /*
                    460:  * Free all network buffer memory used to keep saved packets.
                    461:  */
                    462: void fr_authunload()
                    463: {
                    464:        register int i;
                    465:        register frauthent_t *fae, **faep;
                    466:        mb_t *m;
                    467: 
                    468:        MUTEX_ENTER(&ipf_auth);
                    469:        for (i = 0; i < FR_NUMAUTH; i++) {
                    470:                if ((m = fr_authpkts[i])) {
                    471:                        FREE_MB_T(m);
                    472:                        fr_authpkts[i] = NULL;
                    473:                        fr_auth[i].fra_index = -1;
                    474:                }
                    475:        }
                    476: 
                    477: 
                    478:        for (faep = &fae_list; (fae = *faep); ) {
                    479:                *faep = fae->fae_next;
                    480:                KFREE(fae);
                    481:        }
                    482:        MUTEX_EXIT(&ipf_auth);
                    483: }
                    484: 
                    485: 
                    486: /*
                    487:  * Slowly expire held auth records.  Timeouts are set
                    488:  * in expectation of this being called twice per second.
                    489:  */
                    490: void fr_authexpire()
                    491: {
                    492:        register int i;
                    493:        register frauth_t *fra;
                    494:        register frauthent_t *fae, **faep;
                    495:        mb_t *m;
                    496: #if !SOLARIS
                    497:        int s;
                    498: #endif
                    499: 
                    500:        SPL_NET(s);
                    501:        MUTEX_ENTER(&ipf_auth);
                    502:        for (i = 0, fra = fr_auth; i < FR_NUMAUTH; i++, fra++) {
                    503:                if ((!--fra->fra_age) && (m = fr_authpkts[i])) {
                    504:                        FREE_MB_T(m);
                    505:                        fr_authpkts[i] = NULL;
                    506:                        fr_auth[i].fra_index = -1;
                    507:                        fr_authstats.fas_expire++;
                    508:                        fr_authused--;
                    509:                }
                    510:        }
                    511: 
                    512:        for (faep = &fae_list; (fae = *faep); ) {
                    513:                if (!--fra->fra_age) {
                    514:                        *faep = fae->fae_next;
                    515:                        KFREE(fae);
                    516:                        fr_authstats.fas_expire++;
                    517:                } else
                    518:                        faep = &fae->fae_next;
                    519:        }
                    520:        MUTEX_EXIT(&ipf_auth);
                    521:        SPL_X(s);
                    522: }
                    523: #endif

unix.superglobalmegacorp.com

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