|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.