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