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

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

unix.superglobalmegacorp.com

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