Annotation of XNU/bsd/netinet/ip_proxy.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: #if !defined(lint)
        !            30: #endif
        !            31: 
        !            32: #if defined(__FreeBSD__) && defined(KERNEL) && !defined(_KERNEL)
        !            33: # define       _KERNEL
        !            34: #endif
        !            35: 
        !            36: #if !defined(_KERNEL) && !defined(KERNEL)
        !            37: # include <stdio.h>
        !            38: # include <string.h>
        !            39: # include <stdlib.h>
        !            40: #endif
        !            41: #include <sys/errno.h>
        !            42: #include <sys/types.h>
        !            43: #include <sys/param.h>
        !            44: #include <sys/time.h>
        !            45: #include <sys/file.h>
        !            46: #if !defined(__FreeBSD__)
        !            47: # include <sys/ioctl.h>
        !            48: #endif
        !            49: #include <sys/fcntl.h>
        !            50: #include <sys/uio.h>
        !            51: #ifndef        linux
        !            52: # include <sys/protosw.h>
        !            53: #endif
        !            54: #include <sys/socket.h>
        !            55: #if defined(_KERNEL)
        !            56: # if !defined(linux)
        !            57: #  include <sys/systm.h>
        !            58: # else
        !            59: #  include <linux/string.h>
        !            60: # endif
        !            61: #endif
        !            62: #if !defined(__SVR4) && !defined(__svr4__)
        !            63: # ifndef linux
        !            64: #  include <sys/mbuf.h>
        !            65: # endif
        !            66: #else
        !            67: # include <sys/byteorder.h>
        !            68: # include <sys/dditypes.h>
        !            69: # include <sys/stream.h>
        !            70: # include <sys/kmem.h>
        !            71: #endif
        !            72: #if __FreeBSD__ > 2
        !            73: # include <sys/queue.h>
        !            74: # include <sys/malloc.h>
        !            75: #endif
        !            76: #include <net/if.h>
        !            77: #ifdef sun
        !            78: # include <net/af.h>
        !            79: #endif
        !            80: #include <net/route.h>
        !            81: #include <netinet/in.h>
        !            82: #include <netinet/in_systm.h>
        !            83: #include <netinet/ip.h>
        !            84: #ifndef linux
        !            85: # include <netinet/ip_var.h>
        !            86: #endif
        !            87: #include <netinet/tcp.h>
        !            88: #include <netinet/udp.h>
        !            89: #include <netinet/ip_icmp.h>
        !            90: #include "netinet/ip_compat.h"
        !            91: #include <netinet/tcpip.h>
        !            92: #include "netinet/ip_fil.h"
        !            93: #include "netinet/ip_proxy.h"
        !            94: #include "netinet/ip_nat.h"
        !            95: #include "netinet/ip_state.h"
        !            96: 
        !            97: #ifndef MIN
        !            98: #define MIN(a,b)        (((a)<(b))?(a):(b))
        !            99: #endif
        !           100: 
        !           101: static ap_session_t *ap_find __P((ip_t *, tcphdr_t *));
        !           102: static ap_session_t *ap_new_session __P((aproxy_t *, ip_t *, tcphdr_t *,
        !           103:                                         fr_info_t *, nat_t *));
        !           104: 
        !           105: static int ap_matchsrcdst __P((ap_session_t *aps, struct in_addr src,
        !           106:                               struct in_addr dst, void *tcp, u_short sport,
        !           107:                               u_short dport));
        !           108: 
        !           109: #define        AP_SESS_SIZE    53
        !           110: 
        !           111: #if defined(_KERNEL) && !defined(linux)
        !           112: #include "netinet/ip_ftp_pxy.c"
        !           113: #endif
        !           114: 
        !           115: ap_session_t   *ap_sess_tab[AP_SESS_SIZE];
        !           116: aproxy_t       ap_proxies[] = {
        !           117: #if    IPF_FTP_PROXY
        !           118:        { "ftp", (char)IPPROTO_TCP, 0, 0, ippr_ftp_init, ippr_ftp_in, ippr_ftp_out },
        !           119: #endif
        !           120:        { "", '\0', 0, 0, NULL, NULL }
        !           121: };
        !           122: 
        !           123: 
        !           124: int ap_ok(ip, tcp, nat)
        !           125: ip_t *ip;
        !           126: tcphdr_t *tcp;
        !           127: ipnat_t *nat;
        !           128: {
        !           129:        aproxy_t *apr = nat->in_apr;
        !           130:        u_short dport = nat->in_dport;
        !           131: 
        !           132:        if (!apr || (apr && (apr->apr_flags & APR_DELETE)) ||
        !           133:            (ip->ip_p != apr->apr_p))
        !           134:                return 0;
        !           135:        if ((tcp && (tcp->th_dport != dport)) || (!tcp && dport))
        !           136:                return 0;
        !           137:        return 1;
        !           138: }
        !           139: 
        !           140: 
        !           141: static int
        !           142: ap_matchsrcdst(aps, src, dst, tcp, sport, dport)
        !           143: ap_session_t *aps;
        !           144: struct in_addr src, dst;
        !           145: void *tcp;
        !           146: u_short sport, dport;
        !           147: {
        !           148:        if (aps->aps_dst.s_addr == dst.s_addr) {
        !           149:                if ((aps->aps_src.s_addr == src.s_addr) &&
        !           150:                    (!tcp || (sport == aps->aps_sport) &&
        !           151:                     (dport == aps->aps_dport)))
        !           152:                        return 1;
        !           153:        } else if (aps->aps_dst.s_addr == src.s_addr) {
        !           154:                if ((aps->aps_src.s_addr == dst.s_addr) &&
        !           155:                    (!tcp || (sport == aps->aps_dport) &&
        !           156:                     (dport == aps->aps_sport)))
        !           157:                        return 1;
        !           158:        }
        !           159:        return 0;
        !           160: }
        !           161: 
        !           162: 
        !           163: static ap_session_t *ap_find(ip, tcp)
        !           164: ip_t *ip;
        !           165: tcphdr_t *tcp;
        !           166: {
        !           167:        register u_char p = ip->ip_p;
        !           168:        register ap_session_t *aps;
        !           169:        register u_short sp, dp;
        !           170:        register u_long hv;
        !           171:        struct in_addr src, dst;
        !           172: 
        !           173:        src = ip->ip_src, dst = ip->ip_dst;
        !           174:        sp = dp = 0;                    /* XXX gcc -Wunitialized */
        !           175: 
        !           176:        hv = ip->ip_src.s_addr ^ ip->ip_dst.s_addr;
        !           177:        hv *= 651733;
        !           178:        if (tcp) {
        !           179:                sp = tcp->th_sport;
        !           180:                dp = tcp->th_dport;
        !           181:                hv ^= (sp + dp);
        !           182:                hv *= 5;
        !           183:        }
        !           184:        hv %= AP_SESS_SIZE;
        !           185: 
        !           186:        for (aps = ap_sess_tab[hv]; aps; aps = aps->aps_next)
        !           187:                if ((aps->aps_p == p) &&
        !           188:                    ap_matchsrcdst(aps, src, dst, tcp, sp, dp))
        !           189:                        break;
        !           190:        return aps;
        !           191: }
        !           192: 
        !           193: 
        !           194: /*
        !           195:  * Allocate a new application proxy structure and fill it in with the
        !           196:  * relevant details.  call the init function once complete, prior to
        !           197:  * returning.
        !           198:  */
        !           199: static ap_session_t *ap_new_session(apr, ip, tcp, fin, nat)
        !           200: aproxy_t *apr;
        !           201: ip_t *ip;
        !           202: tcphdr_t *tcp;
        !           203: fr_info_t *fin;
        !           204: nat_t *nat;
        !           205: {
        !           206:        register ap_session_t *aps;
        !           207:        u_short dport;
        !           208:        u_long hv;
        !           209: 
        !           210:        if (!apr || (apr && (apr->apr_flags & APR_DELETE)) ||
        !           211:            (ip->ip_p != apr->apr_p))
        !           212:                return NULL;
        !           213:        dport = nat->nat_ptr->in_dport;
        !           214:        if ((tcp && (tcp->th_dport != dport)) || (!tcp && dport))
        !           215:                return NULL;
        !           216: 
        !           217:        hv = ip->ip_src.s_addr ^ ip->ip_dst.s_addr;
        !           218:        hv *= 651733;
        !           219:        if (tcp) {
        !           220:                hv ^= (tcp->th_sport + tcp->th_dport);
        !           221:                hv *= 5;
        !           222:        }
        !           223:        hv %= AP_SESS_SIZE;
        !           224: 
        !           225:        KMALLOC(aps, ap_session_t *, sizeof(*aps));
        !           226:        if (!aps)
        !           227:                return NULL;
        !           228:        bzero((char *)aps, sizeof(*aps));
        !           229:        aps->aps_apr = apr;
        !           230:        aps->aps_src = ip->ip_src;
        !           231:        aps->aps_dst = ip->ip_dst;
        !           232:        aps->aps_p = ip->ip_p;
        !           233:        aps->aps_tout = 1200;   /* XXX */
        !           234:        if (tcp) {
        !           235:                aps->aps_sport = tcp->th_sport;
        !           236:                aps->aps_dport = tcp->th_dport;
        !           237:        }
        !           238:        aps->aps_data = NULL;
        !           239:        aps->aps_psiz = 0;
        !           240:        aps->aps_next = ap_sess_tab[hv];
        !           241:        ap_sess_tab[hv] = aps;
        !           242:        (void) (*apr->apr_init)(fin, ip, tcp, aps, nat);
        !           243:        return aps;
        !           244: }
        !           245: 
        !           246: 
        !           247: /*
        !           248:  * check to see if a packet should be passed through an active proxy routine
        !           249:  * if one has been setup for it.
        !           250:  */
        !           251: int ap_check(ip, tcp, fin, nat)
        !           252: ip_t *ip;
        !           253: tcphdr_t *tcp;
        !           254: fr_info_t *fin;
        !           255: nat_t *nat;
        !           256: {
        !           257:        ap_session_t *aps;
        !           258:        aproxy_t *apr;
        !           259:        int err;
        !           260: 
        !           261:        if (!(fin->fin_fi.fi_fl & FI_TCPUDP))
        !           262:                tcp = NULL;
        !           263: 
        !           264:        if ((aps = ap_find(ip, tcp)) ||
        !           265:            (aps = ap_new_session(nat->nat_ptr->in_apr, ip, tcp, fin, nat))) {
        !           266:                if (ip->ip_p == IPPROTO_TCP) {
        !           267:                        /*
        !           268:                         * verify that the checksum is correct.  If not, then
        !           269:                         * don't do anything with this packet.
        !           270:                         */
        !           271:                        if (tcp->th_sum != fr_tcpsum(*(mb_t **)fin->fin_mp,
        !           272:                                                     ip, tcp, ip->ip_len)) {
        !           273:                                frstats[fin->fin_out].fr_tcpbad++;
        !           274:                                return -1;
        !           275:                        }
        !           276:                        fr_tcp_age(&aps->aps_tout, aps->aps_state, ip, fin,
        !           277:                                   tcp->th_sport == aps->aps_sport);
        !           278:                }
        !           279: 
        !           280:                apr = aps->aps_apr;
        !           281:                err = 0;
        !           282:                if (fin->fin_out) {
        !           283:                        if (apr->apr_outpkt)
        !           284:                                err = (*apr->apr_outpkt)(fin, ip, tcp,
        !           285:                                                         aps, nat);
        !           286:                } else {
        !           287:                        if (apr->apr_inpkt)
        !           288:                                err = (*apr->apr_inpkt)(fin, ip, tcp,
        !           289:                                                        aps, nat);
        !           290:                }
        !           291:                if (err == 2) {
        !           292:                        tcp->th_sum = fr_tcpsum(*(mb_t **)fin->fin_mp, ip,
        !           293:                                                tcp, ip->ip_len);
        !           294:                        err = 0;
        !           295:                }
        !           296:                return err;
        !           297:        }
        !           298:        return -1;
        !           299: }
        !           300: 
        !           301: 
        !           302: aproxy_t *ap_match(pr, name)
        !           303: u_char pr;
        !           304: char *name;
        !           305: {
        !           306:        aproxy_t *ap;
        !           307: 
        !           308:        for (ap = ap_proxies; ap->apr_p; ap++)
        !           309:                if ((ap->apr_p == pr) &&
        !           310:                    !strncmp(name, ap->apr_label, sizeof(ap->apr_label))) {
        !           311:                        ap->apr_ref++;
        !           312:                        return ap;
        !           313:                }
        !           314:        return NULL;
        !           315: }
        !           316: 
        !           317: 
        !           318: void ap_free(ap)
        !           319: aproxy_t *ap;
        !           320: {
        !           321:        ap->apr_ref--;
        !           322: }
        !           323: 
        !           324: 
        !           325: void aps_free(aps)
        !           326: ap_session_t *aps;
        !           327: {
        !           328:        if (aps->aps_data && aps->aps_psiz)
        !           329:                KFREES(aps->aps_data, aps->aps_psiz);
        !           330:        KFREE(aps);
        !           331: }
        !           332: 
        !           333: 
        !           334: void ap_unload()
        !           335: {
        !           336:        ap_session_t *aps;
        !           337:        int i;
        !           338: 
        !           339:        for (i = 0; i < AP_SESS_SIZE; i++)
        !           340:                while ((aps = ap_sess_tab[i])) {
        !           341:                        ap_sess_tab[i] = aps->aps_next;
        !           342:                        aps_free(aps);
        !           343:                }
        !           344: }
        !           345: 
        !           346: 
        !           347: void ap_expire()
        !           348: {
        !           349:        ap_session_t *aps, **apsp;
        !           350:        int i;
        !           351: 
        !           352:        for (i = 0; i < AP_SESS_SIZE; i++)
        !           353:                for (apsp = &ap_sess_tab[i]; (aps = *apsp); ) {
        !           354:                        aps->aps_tout--;
        !           355:                        if (!aps->aps_tout) {
        !           356:                                ap_sess_tab[i] = aps->aps_next;
        !           357:                                aps_free(aps);
        !           358:                                *apsp = aps->aps_next;
        !           359:                        } else
        !           360:                                apsp = &aps->aps_next;
        !           361:                }
        !           362: }

unix.superglobalmegacorp.com

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