Annotation of XNU/bsd/netinet/ip_proxy.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.
                     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.