VirtualBox

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

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

NAT: Slirp don't use ether address of guest anymore
instead it calculates ethernet address of destination
with lookup operation. Currently it's very simple looks
over send addresses via dhcp or assume destination in outer
network and gets Slirp's ethernet address.

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