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