VirtualBox

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

Last change on this file since 21715 was 21715, checked in by vboxsync, 15 years ago

NAT: MSVC is C compiler, when compiling C files, thus profile counter
initializations leading to code like: int foo; foo = rdtsc(); can only be
used once (as code block starts, when setting value so no more var
declarations allowed). Maybe best approach would be to fix macroses to be
usable from C multiple times, just disabled for now.

  • Property svn:eol-style set to native
File size: 9.2 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#ifdef VBOX_WITH_SLIRP_ALIAS
47# include "alias.h"
48#endif
49
50#ifdef VBOX_WITHOUT_SLIRP_CLIENT_ETHER
51static const uint8_t* rt_lookup_in_cache(PNATState pData, uint32_t dst)
52{
53 int i;
54 /* @todo (r - vasily) to quick ramp up on routing rails
55 * we use information from DHCP server leasings, this
56 * code couldn't detect any changes in network topology
57 * and should be borrowed from other places
58 */
59 for (i = 0; i < NB_ADDR; i++)
60 {
61 if ( bootp_clients[i].allocated
62 && bootp_clients[i].addr.s_addr == dst)
63 return &bootp_clients[i].macaddr[0];
64 }
65
66 if (dst != 0)
67 return pData->slirp_ethaddr;
68
69 return NULL;
70}
71#endif
72
73/*
74 * IP output. The packet in mbuf chain m contains a skeletal IP
75 * header (with len, off, ttl, proto, tos, src, dst).
76 * The mbuf chain containing the packet will be freed.
77 * The mbuf opt, if present, will not be freed.
78 */
79int
80ip_output(PNATState pData, struct socket *so, struct mbuf *m0)
81{
82 register struct ip *ip;
83 register struct mbuf *m = m0;
84 register int hlen = sizeof(struct ip );
85 int len, off, error = 0;
86#ifdef VBOX_WITHOUT_SLIRP_CLIENT_ETHER
87 extern uint8_t zerro_ethaddr[ETH_ALEN];
88 struct ethhdr *eh = NULL;
89 const uint8_t *eth_dst = NULL;
90#endif
91 STAM_PROFILE_START(&pData->StatIP_output, a);
92#ifdef VBOX_WITH_SLIRP_ALIAS
93 //STAM_PROFILE_START(&pData->StatALIAS_output, b);
94#endif
95
96 DEBUG_CALL("ip_output");
97 DEBUG_ARG("so = %lx", (long)so);
98 DEBUG_ARG("m0 = %lx", (long)m0);
99 if(m->m_data != (MBUF_HEAD(m) + if_maxlinkhdr))
100 {
101 LogRel(("NAT: ethernet detects corruption of the packet"));
102 AssertMsgFailed(("!!Ethernet frame corrupted!!"));
103 }
104
105#if 0 /* We do no options */
106 if (opt)
107 {
108 m = ip_insertoptions(m, opt, &len);
109 hlen = len;
110 }
111#endif
112 ip = mtod(m, struct ip *);
113 /*
114 * Fill in IP header.
115 */
116 ip->ip_v = IPVERSION;
117 ip->ip_off &= IP_DF;
118 ip->ip_id = htons(ip_currid++);
119 ip->ip_hl = hlen >> 2;
120 ipstat.ips_localout++;
121
122 /*
123 * Verify that we have any chance at all of being able to queue
124 * the packet or packet fragments
125 */
126#if 0 /* XXX Hmmm... */
127 if (if_queued > if_thresh && towrite <= 0)
128 {
129 error = ENOBUFS;
130 goto bad;
131 }
132#endif
133#ifdef VBOX_WITHOUT_SLIRP_CLIENT_ETHER
134 /* Current TCP/IP stack hasn't routing information at
135 * all so we need to calculate destination ethernet address
136 */
137 eh = (struct ethhdr *)MBUF_HEAD(m);
138 if (memcmp(eh->h_source, zerro_ethaddr, ETH_ALEN) == 0)
139 eth_dst = rt_lookup_in_cache(pData, ip->ip_dst.s_addr);
140#endif
141
142 /*
143 * If small enough for interface, can just send directly.
144 */
145 if ((u_int16_t)ip->ip_len <= if_mtu)
146 {
147 ip->ip_len = htons((u_int16_t)ip->ip_len);
148 ip->ip_off = htons((u_int16_t)ip->ip_off);
149 ip->ip_sum = 0;
150 ip->ip_sum = cksum(m, hlen);
151#ifdef VBOX_WITHOUT_SLIRP_CLIENT_ETHER
152 if (eth_dst != NULL) {
153 memcpy(eh->h_source, eth_dst, ETH_ALEN);
154 }
155#endif
156#ifdef VBOX_WITH_SLIRP_ALIAS
157 {
158 int rc;
159 rc = LibAliasOut((m->m_la ? m->m_la : pData->proxy_alias),
160 mtod(m, char *), m->m_len);
161 Log2(("NAT: LibAlias return %d\n", rc));
162 //STAM_PROFILE_STOP(&pData->StatALIAS_output, b);
163 }
164#endif
165
166 if_output(pData, so, m);
167 goto done;
168 }
169
170 /*
171 * Too large for interface; fragment if possible.
172 * Must be able to put at least 8 bytes per fragment.
173 */
174 if (ip->ip_off & IP_DF)
175 {
176 error = -1;
177 ipstat.ips_cantfrag++;
178 goto bad;
179 }
180
181 len = (if_mtu - hlen) &~ 7; /* ip databytes per packet */
182 if (len < 8)
183 {
184 error = -1;
185 goto bad;
186 }
187
188 {
189 int mhlen, firstlen = len;
190 struct mbuf **mnext = &m->m_nextpkt;
191
192 /*
193 * Loop through length of segment after first fragment,
194 * make new header and copy data of each part and link onto chain.
195 */
196 m0 = m;
197 mhlen = sizeof (struct ip);
198 for (off = hlen + len; off < (u_int16_t)ip->ip_len; off += len)
199 {
200 register struct ip *mhip;
201 m = m_get(pData);
202 if (m == 0)
203 {
204 error = -1;
205 ipstat.ips_odropped++;
206 goto sendorfree;
207 }
208 m->m_data += if_maxlinkhdr;
209 mhip = mtod(m, struct ip *);
210 *mhip = *ip;
211#ifdef VBOX_WITHOUT_SLIRP_CLIENT_ETHER
212 /* we've calculated eth_dst for first packet */
213 eh = (struct ethhdr *)MBUF_HEAD(m);
214 if (eth_dst != NULL) {
215 memcpy(eh->h_source, eth_dst, ETH_ALEN);
216 }
217#endif
218
219#if 0 /* No options */
220 if (hlen > sizeof (struct ip))
221 {
222 mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip);
223 mhip->ip_hl = mhlen >> 2;
224 }
225#endif
226 m->m_len = mhlen;
227 mhip->ip_off = ((off - hlen) >> 3) + (ip->ip_off & ~IP_MF);
228 if (ip->ip_off & IP_MF)
229 mhip->ip_off |= IP_MF;
230 if (off + len >= (u_int16_t)ip->ip_len)
231 len = (u_int16_t)ip->ip_len - off;
232 else
233 mhip->ip_off |= IP_MF;
234 mhip->ip_len = htons((u_int16_t)(len + mhlen));
235
236 if (m_copy(m, m0, off, len) < 0)
237 {
238 error = -1;
239 goto sendorfree;
240 }
241
242 mhip->ip_off = htons((u_int16_t)mhip->ip_off);
243 mhip->ip_sum = 0;
244 mhip->ip_sum = cksum(m, mhlen);
245 *mnext = m;
246 mnext = &m->m_nextpkt;
247 ipstat.ips_ofragments++;
248 }
249 /*
250 * Update first fragment by trimming what's been copied out
251 * and updating header, then send each fragment (in order).
252 */
253 m = m0;
254 m_adj(m, hlen + firstlen - (u_int16_t)ip->ip_len);
255 ip->ip_len = htons((u_int16_t)m->m_len);
256 ip->ip_off = htons((u_int16_t)(ip->ip_off | IP_MF));
257 ip->ip_sum = 0;
258 ip->ip_sum = cksum(m, hlen);
259#ifdef VBOX_WITH_SLIRP_ALIAS
260 {
261 int rc;
262 rc = LibAliasOut((m->m_la ? m->m_la : pData->proxy_alias),
263 mtod(m, char *), m->m_len);
264 Log2(("NAT: LibAlias return %d\n", rc));
265 //STAM_PROFILE_STOP(&pData->StatALIAS_output, b);
266 }
267#endif
268
269sendorfree:
270 for (m = m0; m; m = m0)
271 {
272 m0 = m->m_nextpkt;
273 m->m_nextpkt = 0;
274 if (error == 0)
275 {
276#ifdef VBOX_WITH_SLIRP_ALIAS
277 {
278 int rc;
279 rc = LibAliasOut((m->m_la ? m->m_la : pData->proxy_alias),
280 mtod(m, char *), m->m_len);
281 Log2(("NAT: LibAlias return %d\n", rc));
282 }
283#endif
284 if_output(pData, so, m);
285 }
286 else
287 {
288 m_freem(pData, m);
289 }
290 }
291
292 if (error == 0)
293 ipstat.ips_fragmented++;
294 }
295
296done:
297 STAM_PROFILE_STOP(&pData->StatIP_output, a);
298 return (error);
299
300bad:
301 m_freem(pData, m0);
302 STAM_PROFILE_STOP(&pData->StatIP_output, a);
303 goto done;
304}
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