VirtualBox

source: vbox/trunk/src/VBox/Devices/Network/slirp/ip_output.c@ 5380

Last change on this file since 5380 was 1076, checked in by vboxsync, 18 years ago

Removed tons of ifdef VBOX conditionals to make slirp readable again

  • Property svn:eol-style set to native
File size: 5.5 KB
Line 
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
48/*
49 * IP output. The packet in mbuf chain m contains a skeletal IP
50 * header (with len, off, ttl, proto, tos, src, dst).
51 * The mbuf chain containing the packet will be freed.
52 * The mbuf opt, if present, will not be freed.
53 */
54int
55ip_output(PNATState pData, struct socket *so, struct mbuf *m0)
56{
57 register struct ip *ip;
58 register struct mbuf *m = m0;
59 register int hlen = sizeof(struct ip );
60 int len, off, 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_currid++);
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(pData, 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 < (u_int16_t)ip->ip_len; off += len) {
133 register struct ip *mhip;
134 m = m_get(pData);
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 - (u_int16_t)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);
182sendorfree:
183 for (m = m0; m; m = m0) {
184 m0 = m->m_nextpkt;
185 m->m_nextpkt = 0;
186 if (error == 0)
187 if_output(pData, so, m);
188 else
189 m_freem(pData, m);
190 }
191
192 if (error == 0)
193 ipstat.ips_fragmented++;
194 }
195
196done:
197 return (error);
198
199bad:
200 m_freem(pData, m0);
201 goto done;
202}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette