Annotation of researchv10no/sys/inet/ip_output.c, revision 1.1

1.1     ! root        1: #include "sys/param.h"
        !             2: #include "sys/stream.h"
        !             3: #include "sys/inet/in.h"
        !             4: #include "sys/inet/ip.h"
        !             5: #include "sys/inet/ip_var.h"
        !             6: 
        !             7: int ip_errors[8];
        !             8: 
        !             9: ip_output(m, opt, flags)
        !            10:        struct block *m;
        !            11:        struct block *opt;
        !            12:        int flags;
        !            13: {
        !            14:        register struct ip *ip = (struct ip *)(m->rptr);
        !            15:        register struct ipif *ifp;
        !            16:        int len, hlen = sizeof (struct ip), off;
        !            17:        in_addr dst;
        !            18:        struct ip_route_info info;
        !            19: 
        !            20:        if (opt)                                /* XXX */
        !            21:                (void) freeb(opt);              /* XXX */
        !            22:        /*
        !            23:         * Fill in IP header.
        !            24:         */
        !            25:        ip->ip_hl = hlen >> 2;
        !            26:        if ((flags & IP_FORWARDING) == 0) {
        !            27:                ip->ip_v = IPVERSION;
        !            28:                ip->ip_off &= IP_DF;
        !            29:                ip->ip_id = htons(ip_id++);
        !            30:        }
        !            31: 
        !            32:        dst = ip->ip_dst;
        !            33:        
        !            34:        /*
        !            35:         * If routing to interface only,
        !            36:         * short circuit routing lookup.
        !            37:         */
        !            38:        if (flags & IP_ROUTETOIF) {
        !            39:                ifp = ip_ifonnetof(dst);
        !            40:                if (ifp == 0)
        !            41:                        goto done;
        !            42:                goto gotif;
        !            43:        }
        !            44:        info = ip_route(dst);
        !            45:        if(info.ifp == 0){
        !            46:                ipstat.ips_route++;
        !            47:                goto done;
        !            48:        }
        !            49:        ifp = info.ifp;
        !            50:        dst = info.addr;
        !            51: 
        !            52: gotif:
        !            53: #ifndef notdef
        !            54:        /*
        !            55:         * If source address not specified yet, use address
        !            56:         * of outgoing interface.
        !            57:         */
        !            58:        if (in_lnaof(ip->ip_src) == INADDR_ANY)
        !            59:                ip->ip_src = ifp->thishost;
        !            60: #endif
        !            61: 
        !            62:        /*
        !            63:         * Look for broadcast address
        !            64:         * and verify user is allowed to send
        !            65:         * such a packet.
        !            66:         */
        !            67:        if (in_broadcast(ifp, dst)) {
        !            68:                /* don't allow broadcast messages to be fragmented */
        !            69:                if (ip->ip_len > ifp->mtu) {
        !            70:                        ip_errors[0]++;
        !            71:                        goto done;
        !            72:                }
        !            73:        }
        !            74: 
        !            75:        /*
        !            76:         * If small enough for interface, can just send directly.
        !            77:         */
        !            78:        if (ip->ip_len <= ifp->mtu) {
        !            79:                ip->ip_src = htonl(ip->ip_src);
        !            80:                ip->ip_dst = htonl(ip->ip_dst);
        !            81:                ip->ip_len = htons((u_short)ip->ip_len);
        !            82:                ip->ip_off = htons((u_short)ip->ip_off);
        !            83:                ip->ip_sum = 0;
        !            84:                ip->ip_sum = in_cksum(m, hlen);
        !            85:                ip_ldout(m, dst, ifp);
        !            86:                return;
        !            87:        }
        !            88:        ipstat.ips_fragout++;
        !            89: 
        !            90:        /*
        !            91:         * Too large for interface; fragment if possible.
        !            92:         * Must be able to put at least 8 bytes per fragment.
        !            93:         */
        !            94:        if (ip->ip_off & IP_DF)
        !            95:                goto done;
        !            96:        len = (ifp->mtu - hlen) &~ 7;
        !            97:        if (len < 8) {
        !            98:                ip_errors[1]++;
        !            99:                goto done;
        !           100:        }
        !           101: 
        !           102:        /*
        !           103:         * Discard IP header from logical block for b_copy's sake.
        !           104:         * Loop through length of segment, make a copy of each
        !           105:         * part and output.
        !           106:         */
        !           107:        m->rptr += sizeof (struct ip);
        !           108:        for (off = 0; off < ip->ip_len-hlen; off += len) {
        !           109:                struct block *mh = bp_get();
        !           110:                struct ip *mhip;
        !           111: 
        !           112:                if (mh == 0)
        !           113:                        goto done;
        !           114:                mh->next = 0;
        !           115:                mh->rptr = mh->lim - hlen;
        !           116:                mhip = (struct ip *)mh->rptr;
        !           117:                *mhip = *ip;
        !           118:                if (hlen > sizeof (struct ip)) {
        !           119:                        int olen = ip_optcopy(ip, mhip, off);
        !           120:                        mh->wptr = mh->rptr + sizeof (struct ip) + olen;
        !           121:                } else
        !           122:                        mh->wptr = mh->rptr + sizeof (struct ip);
        !           123:                mhip->ip_off = off >> 3;
        !           124: /* HOMER fix: */
        !           125:                if(ip->ip_off & IP_MF)
        !           126:                        mhip->ip_off |= IP_MF;
        !           127: /* :xif REMOH */
        !           128:                if (off + len >= ip->ip_len-hlen)
        !           129:                        len = mhip->ip_len = ip->ip_len - hlen - off;
        !           130:                else {
        !           131:                        mhip->ip_len = len;
        !           132:                        mhip->ip_off |= IP_MF;
        !           133:                }
        !           134:                mhip->ip_len += sizeof (struct ip);
        !           135:                mhip->ip_len = htons((u_short)mhip->ip_len);
        !           136:                mh->next = bp_copy(m, off, len);
        !           137:                if (mh->next == 0) {
        !           138:                        (void) freeb(mh);
        !           139:                        goto done;
        !           140:                }
        !           141:                mhip->ip_off = htons((u_short)mhip->ip_off);
        !           142:                mhip->ip_src = htonl(mhip->ip_src);
        !           143:                mhip->ip_dst = htonl(mhip->ip_dst);
        !           144:                mhip->ip_sum = 0;
        !           145:                mhip->ip_sum = in_cksum(mh, hlen);
        !           146:                if (ip_ldout(mh, dst, ifp))
        !           147:                        break;
        !           148:        }
        !           149: done:
        !           150:        bp_free(m);
        !           151: }
        !           152: 
        !           153: /*
        !           154:  * Copy options from ip to jp.
        !           155:  * If off is 0 all options are copied
        !           156:  * otherwise copy selectively.
        !           157:  */
        !           158: ip_optcopy(ip, jp, off)
        !           159:        struct ip *ip, *jp;
        !           160:        int off;
        !           161: {
        !           162:        register u_char *cp, *dp;
        !           163:        int opt, optlen, cnt;
        !           164: 
        !           165:        cp = (u_char *)(ip + 1);
        !           166:        dp = (u_char *)(jp + 1);
        !           167:        cnt = (ip->ip_hl << 2) - sizeof (struct ip);
        !           168:        for (; cnt > 0; cnt -= optlen, cp += optlen) {
        !           169:                opt = cp[0];
        !           170:                if (opt == IPOPT_EOL)
        !           171:                        break;
        !           172:                if (opt == IPOPT_NOP)
        !           173:                        optlen = 1;
        !           174:                else
        !           175:                        optlen = cp[1];
        !           176:                if (optlen > cnt)                       /* XXX */
        !           177:                        optlen = cnt;                   /* XXX */
        !           178:                if (off == 0 || IPOPT_COPIED(opt)) {
        !           179:                        bcopy((caddr_t)cp, (caddr_t)dp, (unsigned)optlen);
        !           180:                        dp += optlen;
        !           181:                }
        !           182:        }
        !           183:        for (optlen = dp - (u_char *)(jp+1); optlen & 0x3; optlen++)
        !           184:                *dp++ = IPOPT_EOL;
        !           185:        return (optlen);
        !           186: }

unix.superglobalmegacorp.com

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