|
|
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.