VirtualBox

source: vbox/trunk/src/VBox/Devices/Network/slirp/ip_icmp.c@ 16069

Last change on this file since 16069 was 15890, checked in by vboxsync, 16 years ago

NAT: 1. wo sync enhancement branch is still functional (was corrupted with using ICMP file handler in select(1))

  1. after sending send queue doesn't need to synchronize with NAT thread to free mbuf instead NAT queue used to call freeing slirp routine.
  2. no more copying on slirp to guest sent.


  • Property svn:eol-style set to native
File size: 21.4 KB
Line 
1/*
2 * Copyright (c) 1982, 1986, 1988, 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_icmp.c 8.2 (Berkeley) 1/4/94
34 * ip_icmp.c,v 1.7 1995/05/30 08:09:42 rgrimes Exp
35 */
36
37#include "slirp.h"
38#include "ip_icmp.h"
39#ifdef RT_OS_WINDOWS
40#include <Icmpapi.h>
41#include <Iphlpapi.h>
42#endif
43
44#ifdef RT_OS_WINDOWS
45# ifdef VBOX_WITH_SIMPLIFIED_SLIRP_SYNC
46# define ICMP_SEND_ECHO(event, routine, addr, data, datasize, ipopt) \
47 IcmpSendEcho2(pData->icmp_socket.sh, (event), NULL, NULL, (addr), (data), (datasize), \
48 (ipopt), pData->pvIcmpBuffer, pData->szIcmpBuffer, 1)
49# else /* VBOX_WITH_SIMPLIFIED_SLIRP_SYNC */
50# define ICMP_SEND_ECHO(event, routine, addr, data, datasize, ipopt) \
51 IcmpSendEcho2(pData->icmp_socket.sh, NULL, (FARPROC)(routine), (void *)pData, (addr), (data), (datasize), \
52 (ipopt), pData->pvIcmpBuffer, pData->szIcmpBuffer, 1)
53static void WINAPI notify_slirp(void *);
54# endif /* !VBOX_WITH_SIMPLIFIED_SLIRP_SYNC */
55#endif /* RT_OS_WINDOWS */
56
57/* The message sent when emulating PING */
58/* Be nice and tell them it's just a psuedo-ping packet */
59static const char icmp_ping_msg[] = "This is a psuedo-PING packet used by Slirp to emulate ICMP ECHO-REQUEST packets.\n";
60
61/* list of actions for icmp_error() on RX of an icmp message */
62static const int icmp_flush[19] =
63{
64/* ECHO REPLY (0) */ 0,
65 1,
66 1,
67/* DEST UNREACH (3) */ 1,
68/* SOURCE QUENCH (4)*/ 1,
69/* REDIRECT (5) */ 1,
70 1,
71 1,
72/* ECHO (8) */ 0,
73/* ROUTERADVERT (9) */ 1,
74/* ROUTERSOLICIT (10) */ 1,
75/* TIME EXCEEDED (11) */ 1,
76/* PARAMETER PROBLEM (12) */ 1,
77/* TIMESTAMP (13) */ 0,
78/* TIMESTAMP REPLY (14) */ 0,
79/* INFO (15) */ 0,
80/* INFO REPLY (16) */ 0,
81/* ADDR MASK (17) */ 0,
82/* ADDR MASK REPLY (18) */ 0
83};
84
85int
86icmp_init(PNATState pData)
87{
88 pData->icmp_socket.so_type = IPPROTO_ICMP;
89 pData->icmp_socket.so_state = SS_ISFCONNECTED;
90#ifndef RT_OS_WINDOWS
91# ifndef RT_OS_DARWIN
92 pData->icmp_socket.s = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP);
93# else /* !RT_OS_DARWIN */
94 pData->icmp_socket.s = socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP);
95# endif /* RT_OS_DARWIN */
96 if (pData->icmp_socket.s == -1)
97 {
98 int rc = RTErrConvertFromErrno(errno);
99 LogRel(("NAT: ICMP/ping not available (could open ICMP socket, error %Rrc)\n", rc));
100 return 1;
101 }
102#else /* RT_OS_WINDOWS */
103 pData->hmIcmpLibrary = LoadLibrary("Iphlpapi.dll");
104 if (pData->hmIcmpLibrary != NULL)
105 {
106 pData->pfIcmpParseReplies = (long (WINAPI *)(void *, long))
107 GetProcAddress(pData->hmIcmpLibrary, "IcmpParseReplies");
108 pData->pfIcmpCloseHandle = (BOOL (WINAPI *)(HANDLE))
109 GetProcAddress(pData->hmIcmpLibrary, "IcmpCloseHandle");
110 }
111 if (pData->pfIcmpParseReplies == NULL)
112 {
113 FreeLibrary(pData->hmIcmpLibrary);
114 pData->hmIcmpLibrary = LoadLibrary("Icmp.dll");
115 if (pData->hmIcmpLibrary == NULL)
116 {
117 LogRel(("NAT: Icmp.dll could not be loaded\n"));
118 return 1;
119 }
120 pData->pfIcmpParseReplies = (long (WINAPI *)(void *, long))
121 GetProcAddress(pData->hmIcmpLibrary, "IcmpParseReplies");
122 pData->pfIcmpCloseHandle = (BOOL (WINAPI *)(HANDLE))
123 GetProcAddress(pData->hmIcmpLibrary, "IcmpCloseHandle");
124 }
125 if (pData->pfIcmpParseReplies == NULL)
126 {
127 LogRel(("NAT: Can't find IcmpParseReplies symbol\n"));
128 FreeLibrary(pData->hmIcmpLibrary);
129 return 1;
130 }
131 if (pData->pfIcmpCloseHandle == NULL)
132 {
133 LogRel(("NAT: Can't find IcmpCloseHandle symbol\n"));
134 FreeLibrary(pData->hmIcmpLibrary);
135 return 1;
136 }
137 pData->icmp_socket.sh = IcmpCreateFile();
138# ifdef VBOX_WITH_SIMPLIFIED_SLIRP_SYNC
139 pData->phEvents[VBOX_ICMP_EVENT_INDEX] = CreateEvent(NULL, FALSE, FALSE, NULL);
140# endif /* VBOX_WITH_SIMPLIFIED_SLIRP_SYNC */
141 pData->szIcmpBuffer = sizeof(ICMP_ECHO_REPLY) * 10;
142 pData->pvIcmpBuffer = RTMemAlloc(pData->szIcmpBuffer);
143#endif /* RT_OS_WINDOWS */
144 LIST_INIT(&pData->icmp_msg_head);
145 return 0;
146}
147
148/*
149 * ip here is ip header + 64bytes readed from ICMP packet
150 */
151struct icmp_msg *
152icmp_find_original_mbuf(PNATState pData, struct ip *ip)
153{
154 struct mbuf *m0;
155 struct ip *ip0;
156 struct icmp *icp, *icp0;
157 struct icmp_msg *icm = NULL;
158 int found = 0;
159 struct udphdr *udp;
160 struct tcphdr *tcp;
161 struct socket *head_socket = NULL;
162 struct socket *last_socket = NULL;
163 struct socket *so = NULL;
164 struct in_addr laddr, faddr;
165 u_short lport, fport;
166
167 laddr.s_addr = ~0;
168 faddr.s_addr = ~0;
169
170 lport = ~0;
171 fport = ~0;
172
173
174 Log(("%s: processing (proto:%d)\n", __FUNCTION__, ip->ip_p));
175 switch (ip->ip_p)
176 {
177 case IPPROTO_ICMP:
178 icp = (struct icmp *)((char *)ip + (ip->ip_hl << 2));
179 LIST_FOREACH(icm, &pData->icmp_msg_head, im_list)
180 {
181 m0 = icm->im_m;
182 ip0 = mtod(m0, struct ip *);
183 AssertRelease(ip0->ip_p == IPPROTO_ICMP);
184 icp0 = (struct icmp *)((char *)ip0 + (ip0->ip_hl << 2));
185 if ( ( (icp->icmp_type != ICMP_ECHO && ip->ip_src.s_addr == ip0->ip_dst.s_addr)
186 || (icp->icmp_type == ICMP_ECHO && ip->ip_dst.s_addr == ip0->ip_dst.s_addr))
187 && icp->icmp_id == icp0->icmp_id
188 && icp->icmp_seq == icp0->icmp_seq)
189 {
190 found = 1;
191 break;
192 }
193 Log(("Have found nothing\n"));
194 }
195 break;
196
197 /*
198 * for TCP and UDP logic little bit reverted, we try to find the HOST socket
199 * from which the IP package has been sent.
200 */
201 case IPPROTO_UDP:
202 head_socket = &udb;
203 udp = (struct udphdr *)((char *)ip + (ip->ip_hl << 2));
204 faddr.s_addr = ip->ip_dst.s_addr;
205 fport = udp->uh_dport;
206 laddr.s_addr = ip->ip_src.s_addr;
207 lport = udp->uh_sport;
208 last_socket = udp_last_so;
209 /* fall through */
210
211 case IPPROTO_TCP:
212 if (head_socket == NULL)
213 {
214 tcp = (struct tcphdr *)((char *)ip + (ip->ip_hl << 2));
215 head_socket = &tcb; /* head_socket could be initialized with udb*/
216 faddr.s_addr = ip->ip_dst.s_addr;
217 fport = tcp->th_dport;
218 laddr.s_addr = ip->ip_src.s_addr;
219 lport = tcp->th_sport;
220 last_socket = tcp_last_so;
221 }
222 /* check last socket first */
223 if ( last_socket->so_faddr.s_addr == faddr.s_addr
224 && last_socket->so_fport == fport
225 && last_socket->so_hlport == lport)
226 {
227 found = 1;
228 so = last_socket;
229 goto sofound;
230 }
231 for (so = head_socket->so_prev; so != head_socket; so = so->so_prev)
232 {
233 /* Should be reaplaced by hash here */
234 Log(("trying:%R[natsock] against %R[IP4]:%d lport=%d hlport=%d\n", so, &faddr, fport, lport, so->so_hlport));
235 if ( so->so_faddr.s_addr == faddr.s_addr
236 && so->so_fport == fport
237 && so->so_hlport == lport)
238 {
239 found = 1;
240 break;
241 }
242 }
243 break;
244
245 default:
246 LogRel(("%s:ICMP: unsupported protocol(%d)\n", __FUNCTION__, ip->ip_p));
247 }
248 sofound:
249 if (found == 1 && icm == NULL)
250 {
251 icm = RTMemAlloc(sizeof(struct icmp_msg));
252 icm->im_m = so->so_m;
253 icm->im_so = so;
254 found = 1;
255 Log(("hit:%R[natsock]\n", so));
256 /*XXX: this storage not very long,
257 * better add flag if it should removed from lis
258 */
259 LIST_INSERT_HEAD(&pData->icmp_msg_head, icm, im_list);
260 return (icm);
261 }
262 if (found == 1)
263 return icm;
264
265 return NULL;
266}
267
268static int
269icmp_attach(PNATState pData, struct mbuf *m)
270{
271 struct icmp_msg *icm;
272 struct ip *ip;
273 ip = mtod(m, struct ip *);
274 Assert(ip->ip_p == IPPROTO_ICMP);
275 icm = RTMemAlloc(sizeof(struct icmp_msg));
276 icm->im_m = m;
277 LIST_INSERT_HEAD(&pData->icmp_msg_head, icm, im_list);
278 return 0;
279}
280
281/*
282 * Process a received ICMP message.
283 */
284void
285icmp_input(PNATState pData, struct mbuf *m, int hlen)
286{
287 register struct icmp *icp;
288 register struct ip *ip = mtod(m, struct ip *);
289 int icmplen = ip->ip_len;
290 int status;
291 uint32_t dst;
292#if !defined(RT_OS_WINDOWS)
293 int ttl;
294#endif
295
296 /* int code; */
297
298 DEBUG_CALL("icmp_input");
299 DEBUG_ARG("m = %lx", (long )m);
300 DEBUG_ARG("m_len = %d", m->m_len);
301
302 icmpstat.icps_received++;
303
304 /*
305 * Locate icmp structure in mbuf, and check
306 * that its not corrupted and of at least minimum length.
307 */
308 if (icmplen < ICMP_MINLEN)
309 {
310 /* min 8 bytes payload */
311 icmpstat.icps_tooshort++;
312freeit:
313 m_freem(pData, m);
314 goto end_error;
315 }
316
317 m->m_len -= hlen;
318 m->m_data += hlen;
319 icp = mtod(m, struct icmp *);
320 if (cksum(m, icmplen))
321 {
322 icmpstat.icps_checksum++;
323 goto freeit;
324 }
325 m->m_len += hlen;
326 m->m_data -= hlen;
327
328 /* icmpstat.icps_inhist[icp->icmp_type]++; */
329 /* code = icp->icmp_code; */
330
331 DEBUG_ARG("icmp_type = %d", icp->icmp_type);
332 switch (icp->icmp_type)
333 {
334 case ICMP_ECHO:
335 ip->ip_len += hlen; /* since ip_input subtracts this */
336 dst = ip->ip_dst.s_addr;
337 if (dst == alias_addr.s_addr)
338 {
339 icp->icmp_type = ICMP_ECHOREPLY;
340 ip->ip_dst.s_addr = ip->ip_src.s_addr;
341 ip->ip_src.s_addr = dst;
342 icmp_reflect(pData, m);
343 }
344 else
345 {
346 struct sockaddr_in addr;
347#ifdef RT_OS_WINDOWS
348 IP_OPTION_INFORMATION ipopt;
349 int error;
350#endif
351 addr.sin_family = AF_INET;
352 if ((ip->ip_dst.s_addr & htonl(pData->netmask)) == special_addr.s_addr)
353 {
354 /* It's an alias */
355 switch (ntohl(ip->ip_dst.s_addr) & ~pData->netmask)
356 {
357 case CTL_DNS:
358 addr.sin_addr = dns_addr;
359 break;
360 case CTL_ALIAS:
361 default:
362 addr.sin_addr = loopback_addr;
363 break;
364 }
365 }
366 else
367 addr.sin_addr.s_addr = ip->ip_dst.s_addr;
368#ifndef RT_OS_WINDOWS
369 if (pData->icmp_socket.s != -1)
370 {
371 icmp_attach(pData, m);
372 ttl = ip->ip_ttl;
373 Log(("NAT/ICMP: try to set TTL(%d)\n", ttl));
374 status = setsockopt(pData->icmp_socket.s, IPPROTO_IP, IP_TTL,
375 (void *)&ttl, sizeof(ttl));
376 if (status < 0)
377 LogRel(("NAT: Error (%s) occurred while setting TTL attribute of IP packet\n",
378 strerror(errno)));
379 if (sendto(pData->icmp_socket.s, icp, icmplen, 0,
380 (struct sockaddr *)&addr, sizeof(addr)) == -1)
381 {
382 DEBUG_MISC((dfd,"icmp_input udp sendto tx errno = %d-%s\n",
383 errno, strerror(errno)));
384 icmp_error(pData, m, ICMP_UNREACH,ICMP_UNREACH_NET, 0, strerror(errno));
385 m_free(pData, m);
386 }
387 }
388 else
389 {
390 /*
391 * We're freeing the ICMP message, which unable sent or process.
392 * That behavior described in rfc 793, we shouldn't notify sender about
393 * fail of processing it's ICMP packets
394 */
395 m_free(pData, m);
396 return;
397 }
398#else /* RT_OS_WINDOWS */
399 icmp_attach(pData, m);
400 pData->icmp_socket.so_laddr.s_addr = ip->ip_src.s_addr; /* XXX: hack*/
401 pData->icmp_socket.so_icmp_id = icp->icmp_id;
402 pData->icmp_socket.so_icmp_seq = icp->icmp_seq;
403 memset(&ipopt, 0, sizeof(IP_OPTION_INFORMATION));
404 ipopt.Ttl = ip->ip_ttl;
405 status = ICMP_SEND_ECHO(pData->phEvents[VBOX_ICMP_EVENT_INDEX], notify_slirp, addr.sin_addr.s_addr,
406 icp->icmp_data, icmplen - ICMP_MINLEN, &ipopt);
407 if (status == 0 && (error = GetLastError()) != ERROR_IO_PENDING)
408 {
409 error = GetLastError();
410 LogRel(("NAT: Error (%d) occurred while sending ICMP (", error));
411 switch (error)
412 {
413 case ERROR_INVALID_PARAMETER:
414 LogRel(("icmp_socket:%lx is invalid)\n", pData->icmp_socket.s));
415 break;
416 case ERROR_NOT_SUPPORTED:
417 LogRel(("operation is unsupported)\n"));
418 break;
419 case ERROR_NOT_ENOUGH_MEMORY:
420 LogRel(("OOM!!!)\n"));
421 break;
422 case IP_BUF_TOO_SMALL:
423 LogRel(("Buffer too small)\n"));
424 break;
425 default:
426 LogRel(("Other error!!!)\n"));
427 break;
428 }
429 }
430#endif /* RT_OS_WINDOWS */
431 } /* if ip->ip_dst.s_addr == alias_addr.s_addr */
432 break;
433 case ICMP_UNREACH:
434 /* XXX? report error? close socket? */
435 case ICMP_TIMXCEED:
436 case ICMP_PARAMPROB:
437 case ICMP_SOURCEQUENCH:
438 case ICMP_TSTAMP:
439 case ICMP_MASKREQ:
440 case ICMP_REDIRECT:
441 icmpstat.icps_notsupp++;
442 m_freem(pData, m);
443 break;
444
445 default:
446 icmpstat.icps_badtype++;
447 m_freem(pData, m);
448 } /* switch */
449
450end_error:
451 /* m is m_free()'d xor put in a socket xor or given to ip_send */
452 ;
453}
454
455
456/*
457 * Send an ICMP message in response to a situation
458 *
459 * RFC 1122: 3.2.2 MUST send at least the IP header and 8 bytes of header. MAY send more (we do).
460 * MUST NOT change this header information.
461 * MUST NOT reply to a multicast/broadcast IP address.
462 * MUST NOT reply to a multicast/broadcast MAC address.
463 * MUST reply to only the first fragment.
464 */
465/*
466 * Send ICMP_UNREACH back to the source regarding msrc.
467 * mbuf *msrc is used as a template, but is NOT m_free()'d.
468 * It is reported as the bad ip packet. The header should
469 * be fully correct and in host byte order.
470 * ICMP fragmentation is illegal. All machines must accept 576 bytes in one
471 * packet. The maximum payload is 576-20(ip hdr)-8(icmp hdr)=548
472 */
473
474#define ICMP_MAXDATALEN (IP_MSS-28)
475void icmp_error(PNATState pData, struct mbuf *msrc, u_char type, u_char code, int minsize, const char *message)
476{
477 unsigned hlen, shlen, s_ip_len;
478 register struct ip *ip;
479 register struct icmp *icp;
480 register struct mbuf *m;
481
482 DEBUG_CALL("icmp_error");
483 DEBUG_ARG("msrc = %lx", (long )msrc);
484 DEBUG_ARG("msrc_len = %d", msrc->m_len);
485
486 if (type!=ICMP_UNREACH && type!=ICMP_TIMXCEED)
487 goto end_error;
488
489 /* check msrc */
490 if (!msrc)
491 goto end_error;
492
493 ip = mtod(msrc, struct ip *);
494#if DEBUG
495 {
496 char bufa[20], bufb[20];
497 strcpy(bufa, inet_ntoa(ip->ip_src));
498 strcpy(bufb, inet_ntoa(ip->ip_dst));
499 DEBUG_MISC((dfd, " %.16s to %.16s\n", bufa, bufb));
500 }
501#endif
502 if (ip->ip_off & IP_OFFMASK)
503 goto end_error; /* Only reply to fragment 0 */
504
505 shlen = ip->ip_hl << 2;
506 s_ip_len = ip->ip_len;
507 if (ip->ip_p == IPPROTO_ICMP)
508 {
509 icp = (struct icmp *)((char *)ip + shlen);
510 /*
511 * Assume any unknown ICMP type is an error. This isn't
512 * specified by the RFC, but think about it..
513 */
514 if (icp->icmp_type>18 || icmp_flush[icp->icmp_type])
515 goto end_error;
516 }
517
518 /* make a copy */
519 if (!(m = m_get(pData)))
520 goto end_error; /* get mbuf */
521 {
522 int new_m_size;
523 m->m_data += if_maxlinkhdr;
524 new_m_size = sizeof(struct ip) + ICMP_MINLEN + msrc->m_len + ICMP_MAXDATALEN;
525 if (new_m_size>m->m_size)
526 m_inc(m, new_m_size);
527 }
528 memcpy(m->m_data, msrc->m_data, msrc->m_len);
529 m->m_len = msrc->m_len; /* copy msrc to m */
530
531 /* make the header of the reply packet */
532 ip = mtod(m, struct ip *);
533 hlen = sizeof(struct ip ); /* no options in reply */
534
535 /* fill in icmp */
536 m->m_data += hlen;
537 m->m_len -= hlen;
538
539 icp = mtod(m, struct icmp *);
540
541 if (minsize)
542 s_ip_len = shlen+ICMP_MINLEN; /* return header+8b only */
543 else if (s_ip_len > ICMP_MAXDATALEN) /* maximum size */
544 s_ip_len = ICMP_MAXDATALEN;
545
546 m->m_len = ICMP_MINLEN + s_ip_len; /* 8 bytes ICMP header */
547
548 /* min. size = 8+sizeof(struct ip)+8 */
549
550 icp->icmp_type = type;
551 icp->icmp_code = code;
552 icp->icmp_id = 0;
553 icp->icmp_seq = 0;
554
555 memcpy(&icp->icmp_ip, msrc->m_data, s_ip_len); /* report the ip packet */
556 HTONS(icp->icmp_ip.ip_len);
557 HTONS(icp->icmp_ip.ip_id);
558 HTONS(icp->icmp_ip.ip_off);
559
560#if DEBUG
561 if (message)
562 {
563 /* DEBUG : append message to ICMP packet */
564 int message_len;
565 char *cpnt;
566 message_len = strlen(message);
567 if (message_len > ICMP_MAXDATALEN)
568 message_len = ICMP_MAXDATALEN;
569 cpnt = (char *)m->m_data+m->m_len;
570 memcpy(cpnt, message, message_len);
571 m->m_len += message_len;
572 }
573#endif
574
575 icp->icmp_cksum = 0;
576 icp->icmp_cksum = cksum(m, m->m_len);
577
578 m->m_data -= hlen;
579 m->m_len += hlen;
580
581 /* fill in ip */
582 ip->ip_hl = hlen >> 2;
583 ip->ip_len = m->m_len;
584
585 ip->ip_tos = ((ip->ip_tos & 0x1E) | 0xC0); /* high priority for errors */
586
587 ip->ip_ttl = MAXTTL;
588 ip->ip_p = IPPROTO_ICMP;
589 ip->ip_dst = ip->ip_src; /* ip adresses */
590 ip->ip_src = alias_addr;
591
592 (void ) ip_output(pData, (struct socket *)NULL, m);
593
594 icmpstat.icps_reflect++;
595
596end_error:
597 ;
598}
599#undef ICMP_MAXDATALEN
600
601/*
602 * Reflect the ip packet back to the source
603 */
604void
605icmp_reflect(PNATState pData, struct mbuf *m)
606{
607 register struct ip *ip = mtod(m, struct ip *);
608 int hlen = ip->ip_hl << 2;
609 int optlen = hlen - sizeof(struct ip );
610 register struct icmp *icp;
611
612 /*
613 * Send an icmp packet back to the ip level,
614 * after supplying a checksum.
615 */
616 m->m_data += hlen;
617 m->m_len -= hlen;
618 icp = mtod(m, struct icmp *);
619
620 icp->icmp_cksum = 0;
621 icp->icmp_cksum = cksum(m, ip->ip_len - hlen);
622
623 m->m_data -= hlen;
624 m->m_len += hlen;
625
626 (void ) ip_output(pData, (struct socket *)NULL, m);
627
628 icmpstat.icps_reflect++;
629}
630#if defined(RT_OS_WINDOWS) && !defined(VBOX_WITH_SIMPLIFIED_SLIRP_SYNC)
631static void WINAPI
632notify_slirp(void *ctx)
633{
634 /* pData name is important see slirp_state.h */
635 PNATState pData = (PNATState)ctx;
636 fIcmp = 1;
637}
638#endif
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