|
|
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 int hlen = sizeof(struct ip );
59: int len, off, error = 0;
60:
61: DEBUG_CALL("ip_output");
62: DEBUG_ARG("so = %lx", (long)so);
63: DEBUG_ARG("m0 = %lx", (long)m0);
64:
65: /* We do no options */
66: /* if (opt) {
67: * m = ip_insertoptions(m, opt, &len);
68: * hlen = len;
69: * }
70: */
71: ip = mtod(m, struct ip *);
72: /*
73: * Fill in IP header.
74: */
75: ip->ip_v = IPVERSION;
76: ip->ip_off &= IP_DF;
77: ip->ip_id = htons(ip_id++);
78: ip->ip_hl = hlen >> 2;
79: ipstat.ips_localout++;
80:
81: /*
82: * Verify that we have any chance at all of being able to queue
83: * the packet or packet fragments
84: */
85: /* XXX Hmmm... */
86: /* if (if_queued > if_thresh && towrite <= 0) {
87: * error = ENOBUFS;
88: * goto bad;
89: * }
90: */
91:
92: /*
93: * If small enough for interface, can just send directly.
94: */
95: if ((u_int16_t)ip->ip_len <= if_mtu) {
96: ip->ip_len = htons((u_int16_t)ip->ip_len);
97: ip->ip_off = htons((u_int16_t)ip->ip_off);
98: ip->ip_sum = 0;
99: ip->ip_sum = cksum(m, hlen);
100:
101: if_output(so, m);
102: goto done;
103: }
104:
105: /*
106: * Too large for interface; fragment if possible.
107: * Must be able to put at least 8 bytes per fragment.
108: */
109: if (ip->ip_off & IP_DF) {
110: error = -1;
111: ipstat.ips_cantfrag++;
112: goto bad;
113: }
114:
115: len = (if_mtu - hlen) &~ 7; /* ip databytes per packet */
116: if (len < 8) {
117: error = -1;
118: goto bad;
119: }
120:
121: {
122: int mhlen, firstlen = len;
123: struct mbuf **mnext = &m->m_nextpkt;
124:
125: /*
126: * Loop through length of segment after first fragment,
127: * make new header and copy data of each part and link onto chain.
128: */
129: m0 = m;
130: mhlen = sizeof (struct ip);
131: for (off = hlen + len; off < (u_int16_t)ip->ip_len; off += len) {
132: register struct ip *mhip;
133: m = m_get();
134: if (m == 0) {
135: error = -1;
136: ipstat.ips_odropped++;
137: goto sendorfree;
138: }
139: m->m_data += if_maxlinkhdr;
140: mhip = mtod(m, struct ip *);
141: *mhip = *ip;
142:
143: /* No options */
144: /* if (hlen > sizeof (struct ip)) {
145: * mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip);
146: * mhip->ip_hl = mhlen >> 2;
147: * }
148: */
149: m->m_len = mhlen;
150: mhip->ip_off = ((off - hlen) >> 3) + (ip->ip_off & ~IP_MF);
151: if (ip->ip_off & IP_MF)
152: mhip->ip_off |= IP_MF;
153: if (off + len >= (u_int16_t)ip->ip_len)
154: len = (u_int16_t)ip->ip_len - off;
155: else
156: mhip->ip_off |= IP_MF;
157: mhip->ip_len = htons((u_int16_t)(len + mhlen));
158:
159: if (m_copy(m, m0, off, len) < 0) {
160: error = -1;
161: goto sendorfree;
162: }
163:
164: mhip->ip_off = htons((u_int16_t)mhip->ip_off);
165: mhip->ip_sum = 0;
166: mhip->ip_sum = cksum(m, mhlen);
167: *mnext = m;
168: mnext = &m->m_nextpkt;
169: ipstat.ips_ofragments++;
170: }
171: /*
172: * Update first fragment by trimming what's been copied out
173: * and updating header, then send each fragment (in order).
174: */
175: m = m0;
176: m_adj(m, hlen + firstlen - (u_int16_t)ip->ip_len);
177: ip->ip_len = htons((u_int16_t)m->m_len);
178: ip->ip_off = htons((u_int16_t)(ip->ip_off | IP_MF));
179: ip->ip_sum = 0;
180: ip->ip_sum = cksum(m, hlen);
181: sendorfree:
182: for (m = m0; m; m = m0) {
183: m0 = m->m_nextpkt;
184: m->m_nextpkt = 0;
185: if (error == 0)
186: if_output(so, m);
187: else
188: m_freem(m);
189: }
190:
191: if (error == 0)
192: ipstat.ips_fragmented++;
193: }
194:
195: done:
196: return (error);
197:
198: bad:
199: m_freem(m0);
200: goto done;
201: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.