Annotation of XNU/bsd/netinet/ip_ftp_pxy.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:  * Simple FTP transparent proxy for in-kernel use.  For use with the NAT
        !            24:  * code.
        !            25:  */
        !            26: 
        !            27: 
        !            28: #define        isdigit(x)      ((x) >= '0' && (x) <= '9')
        !            29: 
        !            30: #define        IPF_FTP_PROXY
        !            31: 
        !            32: #define        IPF_MINPORTLEN  18
        !            33: #define        IPF_MAXPORTLEN  30
        !            34: 
        !            35: 
        !            36: int ippr_ftp_init __P((fr_info_t *, ip_t *, tcphdr_t *,
        !            37:                       ap_session_t *, nat_t *));
        !            38: int ippr_ftp_in __P((fr_info_t *, ip_t *, tcphdr_t *,
        !            39:                       ap_session_t *, nat_t *));
        !            40: int ippr_ftp_out __P((fr_info_t *, ip_t *, tcphdr_t *,
        !            41:                       ap_session_t *, nat_t *));
        !            42: u_short ipf_ftp_atoi __P((char **));
        !            43: 
        !            44: 
        !            45: /*
        !            46:  * FTP application proxy initialization.
        !            47:  */
        !            48: int ippr_ftp_init(fin, ip, tcp, aps, nat)
        !            49: fr_info_t *fin;
        !            50: ip_t *ip;
        !            51: tcphdr_t *tcp;
        !            52: ap_session_t *aps;
        !            53: nat_t *nat;
        !            54: {
        !            55:        aps->aps_sport = tcp->th_sport;
        !            56:        aps->aps_dport = tcp->th_dport;
        !            57:        return 0;
        !            58: }
        !            59: 
        !            60: 
        !            61: int ippr_ftp_in(fin, ip, tcp, aps, nat)
        !            62: fr_info_t *fin;
        !            63: ip_t *ip;
        !            64: tcphdr_t *tcp;
        !            65: ap_session_t *aps;
        !            66: nat_t *nat;
        !            67: {
        !            68:        u_32_t  sum1, sum2;
        !            69:        short sel;
        !            70: 
        !            71:        if (tcp->th_sport == aps->aps_dport) {
        !            72:                sum2 = (u_32_t)ntohl(tcp->th_ack);
        !            73:                sel = aps->aps_sel;
        !            74:                if ((aps->aps_after[!sel] > aps->aps_after[sel]) &&
        !            75:                        (sum2 > aps->aps_after[!sel])) {
        !            76:                        sel = aps->aps_sel = !sel; /* switch to other set */
        !            77:                }
        !            78:                if (aps->aps_seqoff[sel] && (sum2 > aps->aps_after[sel])) {
        !            79:                        sum1 = (u_32_t)aps->aps_seqoff[sel];
        !            80:                        tcp->th_ack = htonl(sum2 - sum1);
        !            81:                        return 2;
        !            82:                }
        !            83:        }
        !            84:        return 0;
        !            85: }
        !            86: 
        !            87: 
        !            88: /*
        !            89:  * ipf_ftp_atoi - implement a version of atoi which processes numbers in
        !            90:  * pairs separated by commas (which are expected to be in the range 0 - 255),
        !            91:  * returning a 16 bit number combining either side of the , as the MSB and
        !            92:  * LSB.
        !            93:  */
        !            94: u_short ipf_ftp_atoi(ptr)
        !            95: char **ptr;
        !            96: {
        !            97:        register char *s = *ptr, c;
        !            98:        register u_char i = 0, j = 0;
        !            99: 
        !           100:        while ((c = *s++) && isdigit(c)) {
        !           101:                i *= 10;
        !           102:                i += c - '0';
        !           103:        }
        !           104:        if (c != ',') {
        !           105:                *ptr = NULL;
        !           106:                return 0;
        !           107:        }
        !           108:        while ((c = *s++) && isdigit(c)) {
        !           109:                j *= 10;
        !           110:                j += c - '0';
        !           111:        }
        !           112:        *ptr = s;
        !           113:        return (i << 8) | j;
        !           114: }
        !           115: 
        !           116: 
        !           117: int ippr_ftp_out(fin, ip, tcp, aps, nat)
        !           118: fr_info_t *fin;
        !           119: ip_t *ip;
        !           120: tcphdr_t *tcp;
        !           121: ap_session_t *aps;
        !           122: nat_t *nat;
        !           123: {
        !           124:        register u_32_t sum1, sum2;
        !           125:        char    newbuf[IPF_MAXPORTLEN+1];
        !           126:        char    portbuf[IPF_MAXPORTLEN+1], *s;
        !           127:        int     ch = 0, off = (ip->ip_hl << 2) + (tcp->th_off << 2);
        !           128:        u_int   a1, a2, a3, a4;
        !           129:        u_short a5, a6;
        !           130:        int     olen, dlen, nlen = 0, inc = 0;
        !           131:        tcphdr_t tcph, *tcp2 = &tcph;
        !           132:        void    *savep;
        !           133:        nat_t   *ipn;
        !           134:        struct  in_addr swip;
        !           135:        mb_t *m = *(mb_t **)fin->fin_mp;
        !           136: 
        !           137: #if    SOLARIS
        !           138:        mb_t *m1;
        !           139: 
        !           140:        /* skip any leading M_PROTOs */
        !           141:        while(m && (MTYPE(m) != M_DATA))
        !           142:                m = m->b_cont;
        !           143:        PANIC((!m),("ippr_ftp_out: no M_DATA"));
        !           144: 
        !           145:        dlen = msgdsize(m) - off;
        !           146:        bzero(portbuf, sizeof(portbuf));
        !           147:        copyout_mblk(m, off, MIN(sizeof(portbuf), dlen), portbuf);
        !           148: #else
        !           149:        dlen = mbufchainlen(m) - off;
        !           150:        bzero(portbuf, sizeof(portbuf));
        !           151:        m_copydata(m, off, MIN(sizeof(portbuf), dlen), portbuf);
        !           152: #endif
        !           153:        portbuf[IPF_MAXPORTLEN] = '\0';
        !           154: 
        !           155:        if ((dlen < IPF_MINPORTLEN) || strncmp(portbuf, "PORT ", 5))
        !           156:                goto adjust_seqack;
        !           157: 
        !           158:        /*
        !           159:         * Skip the PORT command + space
        !           160:         */
        !           161:        s = portbuf + 5;
        !           162:        /*
        !           163:         * Pick out the address components, two at a time.
        !           164:         */
        !           165:        (void) ipf_ftp_atoi(&s);
        !           166:        if (!s)
        !           167:                goto adjust_seqack;
        !           168:        (void) ipf_ftp_atoi(&s);
        !           169:        if (!s)
        !           170:                goto adjust_seqack;
        !           171:        a5 = ipf_ftp_atoi(&s);
        !           172:        if (!s)
        !           173:                goto adjust_seqack;
        !           174:        /*
        !           175:         * check for CR-LF at the end.
        !           176:         */
        !           177:        if (*s != '\n' || *(s - 1) != '\r')
        !           178:                goto adjust_seqack;
        !           179:        a6 = a5 & 0xff;
        !           180:        a5 >>= 8;
        !           181:        /*
        !           182:         * Calculate new address parts for PORT command
        !           183:         */
        !           184:        a1 = ntohl(ip->ip_src.s_addr);
        !           185:        a2 = (a1 >> 16) & 0xff;
        !           186:        a3 = (a1 >> 8) & 0xff;
        !           187:        a4 = a1 & 0xff;
        !           188:        a1 >>= 24;
        !           189:        olen = s - portbuf + 1;
        !           190:        (void) snprintf(newbuf, sizeof(newbuf), "PORT %d,%d,%d,%d,%d,%d\r\n",
        !           191:                a1, a2, a3, a4, a5, a6);
        !           192:        nlen = strlen(newbuf);
        !           193:        inc = nlen - olen;
        !           194: #if SOLARIS
        !           195:        for (m1 = m; m1->b_cont; m1 = m1->b_cont)
        !           196:                ;
        !           197:        if (inc > 0) {
        !           198:                mblk_t *nm;
        !           199: 
        !           200:                /* alloc enough to keep same trailer space for lower driver */
        !           201:                nm = allocb(nlen + m1->b_datap->db_lim - m1->b_wptr, BPRI_MED);
        !           202:                PANIC((!nm),("ippr_ftp_out: allocb failed"));
        !           203: 
        !           204:                nm->b_band = m1->b_band;
        !           205:                nm->b_wptr += nlen;
        !           206: 
        !           207:                m1->b_wptr -= olen;
        !           208:                PANIC((m1->b_wptr < m1->b_rptr),("ippr_ftp_out: cannot handle fragmented data block"));
        !           209: 
        !           210:                linkb(m1, nm);
        !           211:        } else {
        !           212:                m1->b_wptr += inc;
        !           213:        }
        !           214:        copyin_mblk(m, off, nlen, newbuf);
        !           215: #else
        !           216:        if (inc < 0)
        !           217:                m_adj(m, inc);
        !           218:        /* the mbuf chain will be extended if necessary by m_copyback() */
        !           219:        m_copyback(m, off, nlen, newbuf);
        !           220: #endif
        !           221:        if (inc) {
        !           222: #if SOLARIS || defined(__sgi)
        !           223:                sum1 = ip->ip_len;
        !           224:                sum2 = ip->ip_len + inc;
        !           225: 
        !           226:                /* Because ~1 == -2, We really need ~1 == -1 */
        !           227:                if (sum1 > sum2)
        !           228:                        sum2--;
        !           229:                sum2 -= sum1;
        !           230:                sum2 = (sum2 & 0xffff) + (sum2 >> 16);
        !           231: 
        !           232:                fix_outcksum(&ip->ip_sum, sum2);
        !           233: #endif
        !           234:                ip->ip_len += inc;
        !           235:        }
        !           236:        ch = 1;
        !           237: 
        !           238:        /*
        !           239:         * Add skeleton NAT entry for connection which will come back the
        !           240:         * other way.
        !           241:         */
        !           242:        savep = fin->fin_dp;
        !           243:        fin->fin_dp = (char *)tcp2;
        !           244:        bzero((char *)tcp2, sizeof(*tcp2));
        !           245:        tcp2->th_sport = htons(a5 << 8 | a6);
        !           246:        tcp2->th_dport = htons(20);
        !           247:        swip = ip->ip_src;
        !           248:        ip->ip_src = nat->nat_inip;
        !           249:        if ((ipn = nat_new(nat->nat_ptr, ip, fin, IPN_TCP, NAT_OUTBOUND)))
        !           250:                ipn->nat_age = fr_defnatage;
        !           251:        (void) fr_addstate(ip, fin, FR_INQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE);
        !           252:        ip->ip_src = swip;
        !           253:        fin->fin_dp = (char *)savep;
        !           254: 
        !           255: adjust_seqack:
        !           256:        if (tcp->th_dport == aps->aps_dport) {
        !           257:                sum2 = (u_32_t)ntohl(tcp->th_seq);
        !           258:                off = aps->aps_sel;
        !           259:                if ((aps->aps_after[!off] > aps->aps_after[off]) &&
        !           260:                        (sum2 > aps->aps_after[!off])) {
        !           261:                        off = aps->aps_sel = !off; /* switch to other set */
        !           262:                }
        !           263:                if (aps->aps_seqoff[off]) {
        !           264:                        sum1 = (u_32_t)aps->aps_after[off] -
        !           265:                               aps->aps_seqoff[off];
        !           266:                        if (sum2 > sum1) {
        !           267:                                sum1 = (u_32_t)aps->aps_seqoff[off];
        !           268:                                sum2 += sum1;
        !           269:                                tcp->th_seq = htonl(sum2);
        !           270:                                ch = 1;
        !           271:                        }
        !           272:                }
        !           273: 
        !           274:                if (inc && (sum2 > aps->aps_after[!off])) {
        !           275:                        aps->aps_after[!off] = sum2 + nlen - 1;
        !           276:                        aps->aps_seqoff[!off] = aps->aps_seqoff[off] + inc;
        !           277:                }
        !           278:        }
        !           279:        return ch ? 2 : 0;
        !           280: }

unix.superglobalmegacorp.com

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