|
|
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.
1.1.1.3 ! root 13: * 3. Neither the name of the University nor the names of its contributors
1.1 root 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:
1.1.1.2 root 45: /* Number of packets queued before we start sending
46: * (to prevent allocing too many mbufs) */
47: #define IF_THRESH 10
48:
1.1 root 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);
1.1.1.2 root 68:
1.1 root 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;
1.1.1.2 root 83: STAT(ipstat.ips_localout++);
1.1 root 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... */
1.1.1.2 root 90: /* if (if_queued > IF_THRESH && towrite <= 0) {
1.1 root 91: * error = ENOBUFS;
92: * goto bad;
93: * }
94: */
1.1.1.2 root 95:
1.1 root 96: /*
97: * If small enough for interface, can just send directly.
98: */
1.1.1.2 root 99: if ((u_int16_t)ip->ip_len <= IF_MTU) {
1.1 root 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;
1.1.1.2 root 115: STAT(ipstat.ips_cantfrag++);
1.1 root 116: goto bad;
117: }
1.1.1.2 root 118:
119: len = (IF_MTU - hlen) &~ 7; /* ip databytes per packet */
1.1 root 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;
1.1.1.2 root 140: STAT(ipstat.ips_odropped++);
1.1 root 141: goto sendorfree;
142: }
1.1.1.2 root 143: m->m_data += IF_MAXLINKHDR;
1.1 root 144: mhip = mtod(m, struct ip *);
145: *mhip = *ip;
1.1.1.2 root 146:
1.1 root 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;
1.1.1.2 root 159: else
1.1 root 160: mhip->ip_off |= IP_MF;
161: mhip->ip_len = htons((u_int16_t)(len + mhlen));
1.1.1.2 root 162:
1.1 root 163: if (m_copy(m, m0, off, len) < 0) {
164: error = -1;
165: goto sendorfree;
166: }
1.1.1.2 root 167:
1.1 root 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;
1.1.1.2 root 173: STAT(ipstat.ips_ofragments++);
1.1 root 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)
1.1.1.2 root 196: STAT(ipstat.ips_fragmented++);
1.1 root 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.