|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1986, 1988, 1990, 1993
3: * The Regents of the University of California. All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: * 3. Neither the name of the University nor the names of its contributors
14: * may be used to endorse or promote products derived from this software
15: * without specific prior written permission.
16: *
17: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27: * SUCH DAMAGE.
28: *
29: * @(#)ip_output.c 8.3 (Berkeley) 1/21/94
30: * ip_output.c,v 1.9 1994/11/16 10:17:10 jkh Exp
31: */
32:
33: /*
34: * Changes and additions relating to SLiRP are
35: * Copyright (c) 1995 Danny Gasparovski.
36: *
37: * Please read the file COPYRIGHT for the
38: * terms and conditions of the copyright.
39: */
40:
41: #include <slirp.h>
42:
43: u_int16_t ip_id;
44:
45: /*
46: * IP output. The packet in mbuf chain m contains a skeletal IP
47: * header (with len, off, ttl, proto, tos, src, dst).
48: * The mbuf chain containing the packet will be freed.
49: * The mbuf opt, if present, will not be freed.
50: */
51: int
52: ip_output(so, m0)
53: struct socket *so;
54: struct mbuf *m0;
55: {
56: register struct ip *ip;
57: register struct mbuf *m = m0;
58: register u_int hlen = sizeof(struct ip);
59: u_int len, off;
60: int error = 0;
61:
62: DEBUG_CALL("ip_output");
63: DEBUG_ARG("so = %lx", (long)so);
64: DEBUG_ARG("m0 = %lx", (long)m0);
65:
66: /* We do no options */
67: /* if (opt) {
68: * m = ip_insertoptions(m, opt, &len);
69: * hlen = len;
70: * }
71: */
72: ip = mtod(m, struct ip *);
73: /*
74: * Fill in IP header.
75: */
76: ip->ip_v = IPVERSION;
77: ip->ip_off &= IP_DF;
78: ip->ip_id = htons(ip_id++);
79: ip->ip_hl = hlen >> 2;
80: ipstat.ips_localout++;
81:
82: /*
83: * Verify that we have any chance at all of being able to queue
84: * the packet or packet fragments
85: */
86: /* XXX Hmmm... */
87: /* if (if_queued > if_thresh && towrite <= 0) {
88: * error = ENOBUFS;
89: * goto bad;
90: * }
91: */
92:
93: /*
94: * If small enough for interface, can just send directly.
95: */
96: if ((u_int16_t)ip->ip_len <= if_mtu) {
97: ip->ip_len = htons((u_int16_t)ip->ip_len);
98: ip->ip_off = htons((u_int16_t)ip->ip_off);
99: ip->ip_sum = 0;
100: ip->ip_sum = cksum(m, hlen);
101:
102: if_output(so, m);
103: goto done;
104: }
105:
106: /*
107: * Too large for interface; fragment if possible.
108: * Must be able to put at least 8 bytes per fragment.
109: */
110: if (ip->ip_off & IP_DF) {
111: error = -1;
112: ipstat.ips_cantfrag++;
113: goto bad;
114: }
115:
116: len = (if_mtu - hlen) &~ 7; /* ip databytes per packet */
117: if (len < 8) {
118: error = -1;
119: goto bad;
120: }
121:
122: {
123: int mhlen, firstlen = len;
124: struct mbuf **mnext = &m->m_nextpkt;
125:
126: /*
127: * Loop through length of segment after first fragment,
128: * make new header and copy data of each part and link onto chain.
129: */
130: m0 = m;
131: mhlen = sizeof (struct ip);
132: for (off = hlen + len; off < ip->ip_len; off += len) {
133: register struct ip *mhip;
134: m = m_get();
135: if (m == 0) {
136: error = -1;
137: ipstat.ips_odropped++;
138: goto sendorfree;
139: }
140: m->m_data += if_maxlinkhdr;
141: mhip = mtod(m, struct ip *);
142: *mhip = *ip;
143:
144: /* No options */
145: /* if (hlen > sizeof (struct ip)) {
146: * mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip);
147: * mhip->ip_hl = mhlen >> 2;
148: * }
149: */
150: m->m_len = mhlen;
151: mhip->ip_off = ((off - hlen) >> 3) + (ip->ip_off & ~IP_MF);
152: if (ip->ip_off & IP_MF)
153: mhip->ip_off |= IP_MF;
154: if (off + len >= (u_int16_t)ip->ip_len)
155: len = (u_int16_t)ip->ip_len - off;
156: else
157: mhip->ip_off |= IP_MF;
158: mhip->ip_len = htons((u_int16_t)(len + mhlen));
159:
160: if (m_copy(m, m0, off, len) < 0) {
161: error = -1;
162: goto sendorfree;
163: }
164:
165: mhip->ip_off = htons((u_int16_t)mhip->ip_off);
166: mhip->ip_sum = 0;
167: mhip->ip_sum = cksum(m, mhlen);
168: *mnext = m;
169: mnext = &m->m_nextpkt;
170: ipstat.ips_ofragments++;
171: }
172: /*
173: * Update first fragment by trimming what's been copied out
174: * and updating header, then send each fragment (in order).
175: */
176: m = m0;
177: m_adj(m, hlen + firstlen - ip->ip_len);
178: ip->ip_len = htons((u_int16_t)m->m_len);
179: ip->ip_off = htons((u_int16_t)(ip->ip_off | IP_MF));
180: ip->ip_sum = 0;
181: ip->ip_sum = cksum(m, hlen);
182: sendorfree:
183: for (m = m0; m; m = m0) {
184: m0 = m->m_nextpkt;
185: m->m_nextpkt = 0;
186: if (error == 0)
187: if_output(so, m);
188: else
189: m_freem(m);
190: }
191:
192: if (error == 0)
193: ipstat.ips_fragmented++;
194: }
195:
196: done:
197: return (error);
198:
199: bad:
200: m_freem(m0);
201: goto done;
202: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.