VirtualBox

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

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

Big change to make slirp fully instantiatable (replace all global
variables with local ones, passing a reference to the state/config
structure to all places which are interested). You can now have as many
cards in the guest configured for NAT networking as you want.

  • Property svn:eol-style set to native
File size: 6.1 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#ifndef VBOX
48u_int16_t ip_id;
49#endif /* !VBOX */
50
51/*
52 * IP output. The packet in mbuf chain m contains a skeletal IP
53 * header (with len, off, ttl, proto, tos, src, dst).
54 * The mbuf chain containing the packet will be freed.
55 * The mbuf opt, if present, will not be freed.
56 */
57int
58#ifdef VBOX
59ip_output(PNATState pData, struct socket *so, struct mbuf *m0)
60#else /* !VBOX */
61ip_output(so, m0)
62 struct socket *so;
63 struct mbuf *m0;
64#endif /* !VBOX */
65{
66 register struct ip *ip;
67 register struct mbuf *m = m0;
68 register int hlen = sizeof(struct ip );
69 int len, off, error = 0;
70
71 DEBUG_CALL("ip_output");
72 DEBUG_ARG("so = %lx", (long)so);
73 DEBUG_ARG("m0 = %lx", (long)m0);
74
75 /* We do no options */
76/* if (opt) {
77 * m = ip_insertoptions(m, opt, &len);
78 * hlen = len;
79 * }
80 */
81 ip = mtod(m, struct ip *);
82 /*
83 * Fill in IP header.
84 */
85 ip->ip_v = IPVERSION;
86 ip->ip_off &= IP_DF;
87#ifdef VBOX
88 ip->ip_id = htons(ip_currid++);
89#else /* !VBOX */
90 ip->ip_id = htons(ip_id++);
91#endif /* !VBOX */
92 ip->ip_hl = hlen >> 2;
93 ipstat.ips_localout++;
94
95 /*
96 * Verify that we have any chance at all of being able to queue
97 * the packet or packet fragments
98 */
99 /* XXX Hmmm... */
100/* if (if_queued > if_thresh && towrite <= 0) {
101 * error = ENOBUFS;
102 * goto bad;
103 * }
104 */
105
106 /*
107 * If small enough for interface, can just send directly.
108 */
109 if ((u_int16_t)ip->ip_len <= if_mtu) {
110 ip->ip_len = htons((u_int16_t)ip->ip_len);
111 ip->ip_off = htons((u_int16_t)ip->ip_off);
112 ip->ip_sum = 0;
113 ip->ip_sum = cksum(m, hlen);
114
115#ifdef VBOX
116 if_output(pData, so, m);
117#else /* !VBOX */
118 if_output(so, m);
119#endif /* !VBOX */
120 goto done;
121 }
122
123 /*
124 * Too large for interface; fragment if possible.
125 * Must be able to put at least 8 bytes per fragment.
126 */
127 if (ip->ip_off & IP_DF) {
128 error = -1;
129 ipstat.ips_cantfrag++;
130 goto bad;
131 }
132
133 len = (if_mtu - hlen) &~ 7; /* ip databytes per packet */
134 if (len < 8) {
135 error = -1;
136 goto bad;
137 }
138
139 {
140 int mhlen, firstlen = len;
141 struct mbuf **mnext = &m->m_nextpkt;
142
143 /*
144 * Loop through length of segment after first fragment,
145 * make new header and copy data of each part and link onto chain.
146 */
147 m0 = m;
148 mhlen = sizeof (struct ip);
149 for (off = hlen + len; off < (u_int16_t)ip->ip_len; off += len) {
150 register struct ip *mhip;
151#ifdef VBOX
152 m = m_get(pData);
153#else /* !VBOX */
154 m = m_get();
155#endif /* !VBOX */
156 if (m == 0) {
157 error = -1;
158 ipstat.ips_odropped++;
159 goto sendorfree;
160 }
161 m->m_data += if_maxlinkhdr;
162 mhip = mtod(m, struct ip *);
163 *mhip = *ip;
164
165 /* No options */
166/* if (hlen > sizeof (struct ip)) {
167 * mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip);
168 * mhip->ip_hl = mhlen >> 2;
169 * }
170 */
171 m->m_len = mhlen;
172 mhip->ip_off = ((off - hlen) >> 3) + (ip->ip_off & ~IP_MF);
173 if (ip->ip_off & IP_MF)
174 mhip->ip_off |= IP_MF;
175 if (off + len >= (u_int16_t)ip->ip_len)
176 len = (u_int16_t)ip->ip_len - off;
177 else
178 mhip->ip_off |= IP_MF;
179 mhip->ip_len = htons((u_int16_t)(len + mhlen));
180
181 if (m_copy(m, m0, off, len) < 0) {
182 error = -1;
183 goto sendorfree;
184 }
185
186 mhip->ip_off = htons((u_int16_t)mhip->ip_off);
187 mhip->ip_sum = 0;
188 mhip->ip_sum = cksum(m, mhlen);
189 *mnext = m;
190 mnext = &m->m_nextpkt;
191 ipstat.ips_ofragments++;
192 }
193 /*
194 * Update first fragment by trimming what's been copied out
195 * and updating header, then send each fragment (in order).
196 */
197 m = m0;
198 m_adj(m, hlen + firstlen - (u_int16_t)ip->ip_len);
199 ip->ip_len = htons((u_int16_t)m->m_len);
200 ip->ip_off = htons((u_int16_t)(ip->ip_off | IP_MF));
201 ip->ip_sum = 0;
202 ip->ip_sum = cksum(m, hlen);
203sendorfree:
204 for (m = m0; m; m = m0) {
205 m0 = m->m_nextpkt;
206 m->m_nextpkt = 0;
207 if (error == 0)
208#ifdef VBOX
209 if_output(pData, so, m);
210#else /* !VBOX */
211 if_output(so, m);
212#endif /* !VBOX */
213 else
214#ifdef VBOX
215 m_freem(pData, m);
216#else /* !VBOX */
217 m_freem(m);
218#endif /* !VBOX */
219 }
220
221 if (error == 0)
222 ipstat.ips_fragmented++;
223 }
224
225done:
226 return (error);
227
228bad:
229#ifdef VBOX
230 m_freem(pData, m0);
231#else /* !VBOX */
232 m_freem(m0);
233#endif /* !VBOX */
234 goto done;
235}
Note: See TracBrowser for help on using the repository browser.

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