VirtualBox

source: vbox/trunk/src/VBox/Devices/Network/slirp/socket.c@ 63121

Last change on this file since 63121 was 63121, checked in by vboxsync, 8 years ago

warnings

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 41.3 KB
Line 
1/* $Id: socket.c 63121 2016-08-07 03:16:53Z vboxsync $ */
2/** @file
3 * NAT - socket handling.
4 */
5
6/*
7 * Copyright (C) 2006-2016 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18/*
19 * This code is based on:
20 *
21 * Copyright (c) 1995 Danny Gasparovski.
22 *
23 * Please read the file COPYRIGHT for the
24 * terms and conditions of the copyright.
25 */
26
27#include <slirp.h>
28#include "ip_icmp.h"
29#include "main.h"
30#ifdef __sun__
31#include <sys/filio.h>
32#endif
33#include <VBox/vmm/pdmdrv.h>
34#if defined (RT_OS_WINDOWS)
35#include <iprt/win/iphlpapi.h>
36#include <icmpapi.h>
37#endif
38
39#if defined(DECLARE_IOVEC) && defined(RT_OS_WINDOWS)
40AssertCompileMembersSameSizeAndOffset(struct iovec, iov_base, WSABUF, buf);
41AssertCompileMembersSameSizeAndOffset(struct iovec, iov_len, WSABUF, len);
42#endif
43
44#ifdef VBOX_WITH_NAT_UDP_SOCKET_CLONE
45/**
46 *
47 */
48struct socket * soCloneUDPSocketWithForegnAddr(PNATState pData, bool fBindSocket, struct socket *pSo, uint32_t u32ForeignAddr)
49{
50 struct socket *pNewSocket = NULL;
51 LogFlowFunc(("Enter: fBindSocket:%RTbool, so:%R[natsock], u32ForeignAddr:%RTnaipv4\n", fBindSocket, pSo, u32ForeignAddr));
52 pNewSocket = socreate();
53 if (!pNewSocket)
54 {
55 LogFunc(("Can't create socket\n"));
56 LogFlowFunc(("Leave: NULL\n"));
57 return NULL;
58 }
59 if (fBindSocket)
60 {
61 if (udp_attach(pData, pNewSocket, 0) <= 0)
62 {
63 sofree(pData, pNewSocket);
64 LogFunc(("Can't attach fresh created socket\n"));
65 return NULL;
66 }
67 }
68 else
69 {
70 pNewSocket->so_cloneOf = (struct socket *)pSo;
71 pNewSocket->s = pSo->s;
72 insque(pData, pNewSocket, &udb);
73 }
74 pNewSocket->so_laddr = pSo->so_laddr;
75 pNewSocket->so_lport = pSo->so_lport;
76 pNewSocket->so_faddr.s_addr = u32ForeignAddr;
77 pNewSocket->so_fport = pSo->so_fport;
78 pSo->so_cCloneCounter++;
79 LogFlowFunc(("Leave: %R[natsock]\n", pNewSocket));
80 return pNewSocket;
81}
82
83struct socket *soLookUpClonedUDPSocket(PNATState pData, const struct socket *pcSo, uint32_t u32ForeignAddress)
84{
85 struct socket *pSoClone = NULL;
86 LogFlowFunc(("Enter: pcSo:%R[natsock], u32ForeignAddress:%RTnaipv4\n", pcSo, u32ForeignAddress));
87 for (pSoClone = udb.so_next; pSoClone != &udb; pSoClone = pSoClone->so_next)
88 {
89 if ( pSoClone->so_cloneOf
90 && pSoClone->so_cloneOf == pcSo
91 && pSoClone->so_lport == pcSo->so_lport
92 && pSoClone->so_fport == pcSo->so_fport
93 && pSoClone->so_laddr.s_addr == pcSo->so_laddr.s_addr
94 && pSoClone->so_faddr.s_addr == u32ForeignAddress)
95 goto done;
96 }
97 pSoClone = NULL;
98done:
99 LogFlowFunc(("Leave: pSoClone: %R[natsock]\n", pSoClone));
100 return pSoClone;
101}
102#endif
103
104#ifdef VBOX_WITH_NAT_SEND2HOME
105DECLINLINE(bool) slirpSend2Home(PNATState pData, struct socket *pSo, const void *pvBuf, uint32_t cbBuf, int iFlags)
106{
107 int idxAddr;
108 int ret = 0;
109 bool fSendDone = false;
110 LogFlowFunc(("Enter pSo:%R[natsock] pvBuf: %p, cbBuf: %d, iFlags: %d\n", pSo, pvBuf, cbBuf, iFlags));
111 for (idxAddr = 0; idxAddr < pData->cInHomeAddressSize; ++idxAddr)
112 {
113
114 struct socket *pNewSocket = soCloneUDPSocketWithForegnAddr(pData, pSo, pData->pInSockAddrHomeAddress[idxAddr].sin_addr);
115 AssertReturn((pNewSocket, false));
116 pData->pInSockAddrHomeAddress[idxAddr].sin_port = pSo->so_fport;
117 /* @todo: more verbose on errors,
118 * @note: we shouldn't care if this send fail or not (we're in broadcast).
119 */
120 LogFunc(("send %d bytes to %RTnaipv4 from %R[natsock]\n", cbBuf, pData->pInSockAddrHomeAddress[idxAddr].sin_addr.s_addr, pNewSocket));
121 ret = sendto(pNewSocket->s, pvBuf, cbBuf, iFlags, (struct sockaddr *)&pData->pInSockAddrHomeAddress[idxAddr], sizeof(struct sockaddr_in));
122 if (ret < 0)
123 LogFunc(("Failed to send %d bytes to %RTnaipv4\n", cbBuf, pData->pInSockAddrHomeAddress[idxAddr].sin_addr.s_addr));
124 fSendDone |= ret > 0;
125 }
126 LogFlowFunc(("Leave %RTbool\n", fSendDone));
127 return fSendDone;
128}
129#endif /* !VBOX_WITH_NAT_SEND2HOME */
130
131#if !defined(RT_OS_WINDOWS)
132static void send_icmp_to_guest(PNATState, char *, size_t, const struct sockaddr_in *);
133static void sorecvfrom_icmp_unix(PNATState, struct socket *);
134#endif /* !RT_OS_WINDOWS */
135
136void
137so_init(void)
138{
139}
140
141struct socket *
142solookup(struct socket *head, struct in_addr laddr,
143 u_int lport, struct in_addr faddr, u_int fport)
144{
145 struct socket *so;
146
147 for (so = head->so_next; so != head; so = so->so_next)
148 {
149 if ( so->so_lport == lport
150 && so->so_laddr.s_addr == laddr.s_addr
151 && so->so_faddr.s_addr == faddr.s_addr
152 && so->so_fport == fport)
153 return so;
154 }
155
156 return (struct socket *)NULL;
157}
158
159/*
160 * Create a new socket, initialise the fields
161 * It is the responsibility of the caller to
162 * insque() it into the correct linked-list
163 */
164struct socket *
165socreate(void)
166{
167 struct socket *so;
168
169 so = (struct socket *)RTMemAllocZ(sizeof(struct socket));
170 if (so)
171 {
172 so->so_state = SS_NOFDREF;
173 so->s = -1;
174#if !defined(RT_OS_WINDOWS)
175 so->so_poll_index = -1;
176#endif
177 }
178 return so;
179}
180
181/*
182 * remque and free a socket, clobber cache
183 */
184void
185sofree(PNATState pData, struct socket *so)
186{
187 LogFlowFunc(("ENTER:%R[natsock]\n", so));
188 /*
189 * We should not remove socket when polling routine do the polling
190 * instead we mark it for deletion.
191 */
192 if (so->fUnderPolling)
193 {
194 so->fShouldBeRemoved = 1;
195 LogFlowFunc(("LEAVE:%R[natsock] postponed deletion\n", so));
196 return;
197 }
198 /**
199 * Check that we don't freeng socket with tcbcb
200 */
201 Assert(!sototcpcb(so));
202 /* udp checks */
203 Assert(!so->so_timeout);
204 Assert(!so->so_timeout_arg);
205 if (so == tcp_last_so)
206 tcp_last_so = &tcb;
207 else if (so == udp_last_so)
208 udp_last_so = &udb;
209
210 /* check if mbuf haven't been already freed */
211 if (so->so_m != NULL)
212 {
213 m_freem(pData, so->so_m);
214 so->so_m = NULL;
215 }
216
217 if (so->so_ohdr != NULL)
218 {
219 RTMemFree(so->so_ohdr);
220 so->so_ohdr = NULL;
221 }
222
223 if (so->so_next && so->so_prev)
224 {
225 remque(pData, so); /* crashes if so is not in a queue */
226 NSOCK_DEC();
227 }
228
229 RTMemFree(so);
230 LogFlowFuncLeave();
231}
232
233/*
234 * Read from so's socket into sb_snd, updating all relevant sbuf fields
235 * NOTE: This will only be called if it is select()ed for reading, so
236 * a read() of 0 (or less) means it's disconnected
237 */
238int
239soread(PNATState pData, struct socket *so)
240{
241 int n, nn, lss, total;
242 struct sbuf *sb = &so->so_snd;
243 u_int len = sb->sb_datalen - sb->sb_cc;
244 struct iovec iov[2];
245 int mss = so->so_tcpcb->t_maxseg;
246
247 STAM_PROFILE_START(&pData->StatIOread, a);
248 STAM_COUNTER_RESET(&pData->StatIORead_in_1);
249 STAM_COUNTER_RESET(&pData->StatIORead_in_2);
250
251 QSOCKET_LOCK(tcb);
252 SOCKET_LOCK(so);
253 QSOCKET_UNLOCK(tcb);
254
255 LogFlow(("soread: so = %R[natsock]\n", so));
256 Log2(("%s: so = %R[natsock] so->so_snd = %R[sbuf]\n", RT_GCC_EXTENSION __PRETTY_FUNCTION__, so, sb));
257
258 /*
259 * No need to check if there's enough room to read.
260 * soread wouldn't have been called if there weren't
261 */
262
263 len = sb->sb_datalen - sb->sb_cc;
264
265 iov[0].iov_base = sb->sb_wptr;
266 iov[1].iov_base = 0;
267 iov[1].iov_len = 0;
268 if (sb->sb_wptr < sb->sb_rptr)
269 {
270 iov[0].iov_len = sb->sb_rptr - sb->sb_wptr;
271 /* Should never succeed, but... */
272 if (iov[0].iov_len > len)
273 iov[0].iov_len = len;
274 if (iov[0].iov_len > mss)
275 iov[0].iov_len -= iov[0].iov_len%mss;
276 n = 1;
277 }
278 else
279 {
280 iov[0].iov_len = (sb->sb_data + sb->sb_datalen) - sb->sb_wptr;
281 /* Should never succeed, but... */
282 if (iov[0].iov_len > len)
283 iov[0].iov_len = len;
284 len -= iov[0].iov_len;
285 if (len)
286 {
287 iov[1].iov_base = sb->sb_data;
288 iov[1].iov_len = sb->sb_rptr - sb->sb_data;
289 if (iov[1].iov_len > len)
290 iov[1].iov_len = len;
291 total = iov[0].iov_len + iov[1].iov_len;
292 if (total > mss)
293 {
294 lss = total % mss;
295 if (iov[1].iov_len > lss)
296 {
297 iov[1].iov_len -= lss;
298 n = 2;
299 }
300 else
301 {
302 lss -= iov[1].iov_len;
303 iov[0].iov_len -= lss;
304 n = 1;
305 }
306 }
307 else
308 n = 2;
309 }
310 else
311 {
312 if (iov[0].iov_len > mss)
313 iov[0].iov_len -= iov[0].iov_len%mss;
314 n = 1;
315 }
316 }
317
318#ifdef HAVE_READV
319 nn = readv(so->s, (struct iovec *)iov, n);
320#else
321 nn = recv(so->s, iov[0].iov_base, iov[0].iov_len, (so->so_tcpcb->t_force? MSG_OOB:0));
322#endif
323 Log2(("%s: read(1) nn = %d bytes\n", RT_GCC_EXTENSION __PRETTY_FUNCTION__, nn));
324 Log2(("%s: so = %R[natsock] so->so_snd = %R[sbuf]\n", RT_GCC_EXTENSION __PRETTY_FUNCTION__, so, sb));
325 if (nn <= 0)
326 {
327 /*
328 * Special case for WSAEnumNetworkEvents: If we receive 0 bytes that
329 * _could_ mean that the connection is closed. But we will receive an
330 * FD_CLOSE event later if the connection was _really_ closed. With
331 * www.youtube.com I see this very often. Closing the socket too early
332 * would be dangerous.
333 */
334 int status;
335 unsigned long pending = 0;
336 status = ioctlsocket(so->s, FIONREAD, &pending);
337 if (status < 0)
338 Log(("NAT:%s: error in WSAIoctl: %d\n", RT_GCC_EXTENSION __PRETTY_FUNCTION__, errno));
339 if (nn == 0 && (pending != 0))
340 {
341 SOCKET_UNLOCK(so);
342 STAM_PROFILE_STOP(&pData->StatIOread, a);
343 return 0;
344 }
345 if ( nn < 0
346 && soIgnorableErrorCode(errno))
347 {
348 SOCKET_UNLOCK(so);
349 STAM_PROFILE_STOP(&pData->StatIOread, a);
350 return 0;
351 }
352 else
353 {
354 int fUninitiolizedTemplate = 0;
355 fUninitiolizedTemplate = RT_BOOL(( sototcpcb(so)
356 && ( sototcpcb(so)->t_template.ti_src.s_addr == INADDR_ANY
357 || sototcpcb(so)->t_template.ti_dst.s_addr == INADDR_ANY)));
358 /* nn == 0 means peer has performed an orderly shutdown */
359 Log2(("%s: disconnected, nn = %d, errno = %d (%s)\n",
360 RT_GCC_EXTENSION __PRETTY_FUNCTION__, nn, errno, strerror(errno)));
361 sofcantrcvmore(so);
362 if (!fUninitiolizedTemplate)
363 tcp_sockclosed(pData, sototcpcb(so));
364 else
365 tcp_drop(pData, sototcpcb(so), errno);
366 SOCKET_UNLOCK(so);
367 STAM_PROFILE_STOP(&pData->StatIOread, a);
368 return -1;
369 }
370 }
371 STAM_STATS(
372 if (n == 1)
373 {
374 STAM_COUNTER_INC(&pData->StatIORead_in_1);
375 STAM_COUNTER_ADD(&pData->StatIORead_in_1_bytes, nn);
376 }
377 else
378 {
379 STAM_COUNTER_INC(&pData->StatIORead_in_2);
380 STAM_COUNTER_ADD(&pData->StatIORead_in_2_1st_bytes, nn);
381 }
382 );
383
384#ifndef HAVE_READV
385 /*
386 * If there was no error, try and read the second time round
387 * We read again if n = 2 (ie, there's another part of the buffer)
388 * and we read as much as we could in the first read
389 * We don't test for <= 0 this time, because there legitimately
390 * might not be any more data (since the socket is non-blocking),
391 * a close will be detected on next iteration.
392 * A return of -1 wont (shouldn't) happen, since it didn't happen above
393 */
394 if (n == 2 && (unsigned)nn == iov[0].iov_len)
395 {
396 int ret;
397 ret = recv(so->s, iov[1].iov_base, iov[1].iov_len, 0);
398 if (ret > 0)
399 nn += ret;
400 STAM_STATS(
401 if (ret > 0)
402 {
403 STAM_COUNTER_INC(&pData->StatIORead_in_2);
404 STAM_COUNTER_ADD(&pData->StatIORead_in_2_2nd_bytes, ret);
405 }
406 );
407 }
408
409 Log2(("%s: read(2) nn = %d bytes\n", RT_GCC_EXTENSION __PRETTY_FUNCTION__, nn));
410#endif
411
412 /* Update fields */
413 sb->sb_cc += nn;
414 sb->sb_wptr += nn;
415 Log2(("%s: update so_snd (readed nn = %d) %R[sbuf]\n", RT_GCC_EXTENSION __PRETTY_FUNCTION__, nn, sb));
416 if (sb->sb_wptr >= (sb->sb_data + sb->sb_datalen))
417 {
418 sb->sb_wptr -= sb->sb_datalen;
419 Log2(("%s: alter sb_wptr so_snd = %R[sbuf]\n", RT_GCC_EXTENSION __PRETTY_FUNCTION__, sb));
420 }
421 STAM_PROFILE_STOP(&pData->StatIOread, a);
422 SOCKET_UNLOCK(so);
423 return nn;
424}
425
426/*
427 * Get urgent data
428 *
429 * When the socket is created, we set it SO_OOBINLINE,
430 * so when OOB data arrives, we soread() it and everything
431 * in the send buffer is sent as urgent data
432 */
433void
434sorecvoob(PNATState pData, struct socket *so)
435{
436 struct tcpcb *tp = sototcpcb(so);
437 ssize_t ret;
438
439 LogFlowFunc(("sorecvoob: so = %R[natsock]\n", so));
440
441 /*
442 * We take a guess at how much urgent data has arrived.
443 * In most situations, when urgent data arrives, the next
444 * read() should get all the urgent data. This guess will
445 * be wrong however if more data arrives just after the
446 * urgent data, or the read() doesn't return all the
447 * urgent data.
448 */
449 ret = soread(pData, so);
450 if (RT_LIKELY(ret > 0))
451 {
452 tp->snd_up = tp->snd_una + SBUF_LEN(&so->so_snd);
453 tp->t_force = 1;
454 tcp_output(pData, tp);
455 tp->t_force = 0;
456 }
457}
458
459/*
460 * Send urgent data
461 * There's a lot duplicated code here, but...
462 */
463int
464sosendoob(struct socket *so)
465{
466 struct sbuf *sb = &so->so_rcv;
467 char buff[2048]; /* XXX Shouldn't be sending more oob data than this */
468
469 int n, len;
470
471 LogFlowFunc(("sosendoob so = %R[natsock]\n", so));
472
473 if (so->so_urgc > sizeof(buff))
474 so->so_urgc = sizeof(buff); /* XXX */
475
476 if (sb->sb_rptr < sb->sb_wptr)
477 {
478 /* We can send it directly */
479 n = send(so->s, sb->sb_rptr, so->so_urgc, (MSG_OOB)); /* |MSG_DONTWAIT)); */
480 so->so_urgc -= n;
481
482 Log2((" --- sent %d bytes urgent data, %d urgent bytes left\n",
483 n, so->so_urgc));
484 }
485 else
486 {
487 /*
488 * Since there's no sendv or sendtov like writev,
489 * we must copy all data to a linear buffer then
490 * send it all
491 */
492 len = (sb->sb_data + sb->sb_datalen) - sb->sb_rptr;
493 if (len > so->so_urgc)
494 len = so->so_urgc;
495 memcpy(buff, sb->sb_rptr, len);
496 so->so_urgc -= len;
497 if (so->so_urgc)
498 {
499 n = sb->sb_wptr - sb->sb_data;
500 if (n > so->so_urgc)
501 n = so->so_urgc;
502 memcpy(buff + len, sb->sb_data, n);
503 so->so_urgc -= n;
504 len += n;
505 }
506 n = send(so->s, buff, len, (MSG_OOB)); /* |MSG_DONTWAIT)); */
507#ifdef DEBUG
508 if (n != len)
509 Log(("Didn't send all data urgently XXXXX\n"));
510#endif
511 Log2((" ---2 sent %d bytes urgent data, %d urgent bytes left\n",
512 n, so->so_urgc));
513 }
514
515 sb->sb_cc -= n;
516 sb->sb_rptr += n;
517 if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen))
518 sb->sb_rptr -= sb->sb_datalen;
519
520 return n;
521}
522
523/*
524 * Write data from so_rcv to so's socket,
525 * updating all sbuf field as necessary
526 */
527int
528sowrite(PNATState pData, struct socket *so)
529{
530 int n, nn;
531 struct sbuf *sb = &so->so_rcv;
532 u_int len = sb->sb_cc;
533 struct iovec iov[2];
534
535 STAM_PROFILE_START(&pData->StatIOwrite, a);
536 STAM_COUNTER_RESET(&pData->StatIOWrite_in_1);
537 STAM_COUNTER_RESET(&pData->StatIOWrite_in_1_bytes);
538 STAM_COUNTER_RESET(&pData->StatIOWrite_in_2);
539 STAM_COUNTER_RESET(&pData->StatIOWrite_in_2_1st_bytes);
540 STAM_COUNTER_RESET(&pData->StatIOWrite_in_2_2nd_bytes);
541 STAM_COUNTER_RESET(&pData->StatIOWrite_no_w);
542 STAM_COUNTER_RESET(&pData->StatIOWrite_rest);
543 STAM_COUNTER_RESET(&pData->StatIOWrite_rest_bytes);
544 LogFlowFunc(("so = %R[natsock]\n", so));
545 Log2(("%s: so = %R[natsock] so->so_rcv = %R[sbuf]\n", RT_GCC_EXTENSION __PRETTY_FUNCTION__, so, sb));
546 QSOCKET_LOCK(tcb);
547 SOCKET_LOCK(so);
548 QSOCKET_UNLOCK(tcb);
549 if (so->so_urgc)
550 {
551 sosendoob(so);
552 if (sb->sb_cc == 0)
553 {
554 SOCKET_UNLOCK(so);
555 STAM_PROFILE_STOP(&pData->StatIOwrite, a);
556 return 0;
557 }
558 }
559
560 /*
561 * No need to check if there's something to write,
562 * sowrite wouldn't have been called otherwise
563 */
564
565 len = sb->sb_cc;
566
567 iov[0].iov_base = sb->sb_rptr;
568 iov[1].iov_base = 0;
569 iov[1].iov_len = 0;
570 if (sb->sb_rptr < sb->sb_wptr)
571 {
572 iov[0].iov_len = sb->sb_wptr - sb->sb_rptr;
573 /* Should never succeed, but... */
574 if (iov[0].iov_len > len)
575 iov[0].iov_len = len;
576 n = 1;
577 }
578 else
579 {
580 iov[0].iov_len = (sb->sb_data + sb->sb_datalen) - sb->sb_rptr;
581 if (iov[0].iov_len > len)
582 iov[0].iov_len = len;
583 len -= iov[0].iov_len;
584 if (len)
585 {
586 iov[1].iov_base = sb->sb_data;
587 iov[1].iov_len = sb->sb_wptr - sb->sb_data;
588 if (iov[1].iov_len > len)
589 iov[1].iov_len = len;
590 n = 2;
591 }
592 else
593 n = 1;
594 }
595 STAM_STATS({
596 if (n == 1)
597 {
598 STAM_COUNTER_INC(&pData->StatIOWrite_in_1);
599 STAM_COUNTER_ADD(&pData->StatIOWrite_in_1_bytes, iov[0].iov_len);
600 }
601 else
602 {
603 STAM_COUNTER_INC(&pData->StatIOWrite_in_2);
604 STAM_COUNTER_ADD(&pData->StatIOWrite_in_2_1st_bytes, iov[0].iov_len);
605 STAM_COUNTER_ADD(&pData->StatIOWrite_in_2_2nd_bytes, iov[1].iov_len);
606 }
607 });
608 /* Check if there's urgent data to send, and if so, send it */
609#ifdef HAVE_READV
610 nn = writev(so->s, (const struct iovec *)iov, n);
611#else
612 nn = send(so->s, iov[0].iov_base, iov[0].iov_len, 0);
613#endif
614 Log2(("%s: wrote(1) nn = %d bytes\n", RT_GCC_EXTENSION __PRETTY_FUNCTION__, nn));
615 /* This should never happen, but people tell me it does *shrug* */
616 if ( nn < 0
617 && soIgnorableErrorCode(errno))
618 {
619 SOCKET_UNLOCK(so);
620 STAM_PROFILE_STOP(&pData->StatIOwrite, a);
621 return 0;
622 }
623
624 if (nn < 0 || (nn == 0 && iov[0].iov_len > 0))
625 {
626 Log2(("%s: disconnected, so->so_state = %x, errno = %d\n",
627 RT_GCC_EXTENSION __PRETTY_FUNCTION__, so->so_state, errno));
628 sofcantsendmore(so);
629 tcp_sockclosed(pData, sototcpcb(so));
630 SOCKET_UNLOCK(so);
631 STAM_PROFILE_STOP(&pData->StatIOwrite, a);
632 return -1;
633 }
634
635#ifndef HAVE_READV
636 if (n == 2 && (unsigned)nn == iov[0].iov_len)
637 {
638 int ret;
639 ret = send(so->s, iov[1].iov_base, iov[1].iov_len, 0);
640 if (ret > 0)
641 nn += ret;
642# ifdef VBOX_WITH_STATISTICS
643 if (ret > 0 && ret != (ssize_t)iov[1].iov_len)
644 {
645 STAM_COUNTER_INC(&pData->StatIOWrite_rest);
646 STAM_COUNTER_ADD(&pData->StatIOWrite_rest_bytes, (iov[1].iov_len - ret));
647 }
648#endif
649 }
650 Log2(("%s: wrote(2) nn = %d bytes\n", RT_GCC_EXTENSION __PRETTY_FUNCTION__, nn));
651#endif
652
653 /* Update sbuf */
654 sb->sb_cc -= nn;
655 sb->sb_rptr += nn;
656 Log2(("%s: update so_rcv (written nn = %d) %R[sbuf]\n", RT_GCC_EXTENSION __PRETTY_FUNCTION__, nn, sb));
657 if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen))
658 {
659 sb->sb_rptr -= sb->sb_datalen;
660 Log2(("%s: alter sb_rptr of so_rcv %R[sbuf]\n", RT_GCC_EXTENSION __PRETTY_FUNCTION__, sb));
661 }
662
663 /*
664 * If in DRAIN mode, and there's no more data, set
665 * it CANTSENDMORE
666 */
667 if ((so->so_state & SS_FWDRAIN) && sb->sb_cc == 0)
668 sofcantsendmore(so);
669
670 SOCKET_UNLOCK(so);
671 STAM_PROFILE_STOP(&pData->StatIOwrite, a);
672 return nn;
673}
674
675/*
676 * recvfrom() a UDP socket
677 */
678void
679sorecvfrom(PNATState pData, struct socket *so)
680{
681 LogFlowFunc(("sorecvfrom: so = %p\n", so));
682
683#ifdef RT_OS_WINDOWS
684 /* ping is handled with ICMP API in ip_icmpwin.c */
685 Assert(so->so_type == IPPROTO_UDP);
686#else
687 if (so->so_type == IPPROTO_ICMP)
688 {
689 /* This is a "ping" reply */
690 sorecvfrom_icmp_unix(pData, so);
691 udp_detach(pData, so);
692 }
693 else
694#endif /* !RT_OS_WINDOWS */
695 {
696 static char achBuf[64 * 1024];
697
698 /* A "normal" UDP packet */
699 struct sockaddr_in addr;
700 socklen_t addrlen = sizeof(struct sockaddr_in);
701 struct iovec iov[2];
702 ssize_t nread;
703 struct mbuf *m;
704
705 QSOCKET_LOCK(udb);
706 SOCKET_LOCK(so);
707 QSOCKET_UNLOCK(udb);
708
709 m = m_getjcl(pData, M_NOWAIT, MT_HEADER, M_PKTHDR, slirp_size(pData));
710 if (m == NULL)
711 {
712 SOCKET_UNLOCK(so);
713 return;
714 }
715
716 m->m_data += ETH_HLEN;
717 m->m_pkthdr.header = mtod(m, void *);
718
719 m->m_data += sizeof(struct udpiphdr);
720
721 /* small packets will fit without copying */
722 iov[0].iov_base = mtod(m, char *);
723 iov[0].iov_len = M_TRAILINGSPACE(m);
724
725 /* large packets will spill into a temp buffer */
726 iov[1].iov_base = achBuf;
727 iov[1].iov_len = sizeof(achBuf);
728
729#if !defined(RT_OS_WINDOWS)
730 {
731 struct msghdr mh;
732 memset(&mh, 0, sizeof(mh));
733
734 mh.msg_iov = iov;
735 mh.msg_iovlen = 2;
736 mh.msg_name = &addr;
737 mh.msg_namelen = addrlen;
738
739 nread = recvmsg(so->s, &mh, 0);
740 }
741#else /* RT_OS_WINDOWS */
742 {
743 DWORD nbytes; /* NB: can't use nread b/c of different size */
744 DWORD flags = 0;
745 int status;
746 AssertCompile(sizeof(WSABUF) == sizeof(struct iovec));
747 AssertCompileMembersSameSizeAndOffset(WSABUF, len, struct iovec, iov_len);
748 AssertCompileMembersSameSizeAndOffset(WSABUF, buf, struct iovec, iov_base);
749 status = WSARecvFrom(so->s, (WSABUF *)&iov[0], 2, &nbytes, &flags,
750 (struct sockaddr *)&addr, &addrlen,
751 NULL, NULL);
752 if (status != SOCKET_ERROR)
753 nread = nbytes;
754 else
755 nread = -1;
756 }
757#endif
758 if (nread >= 0)
759 {
760 if (nread <= iov[0].iov_len)
761 m->m_len = nread;
762 else
763 {
764 m->m_len = iov[0].iov_len;
765 m_append(pData, m, nread - iov[0].iov_len, iov[1].iov_base);
766 }
767 Assert(m_length(m, NULL) == (size_t)nread);
768
769 /*
770 * Hack: domain name lookup will be used the most for UDP,
771 * and since they'll only be used once there's no need
772 * for the 4 minute (or whatever) timeout... So we time them
773 * out much quicker (10 seconds for now...)
774 */
775 if (so->so_expire)
776 {
777 if (so->so_fport != RT_H2N_U16_C(53))
778 so->so_expire = curtime + SO_EXPIRE;
779 }
780
781 /*
782 * DNS proxy requests are forwarded to the real resolver,
783 * but its socket's so_faddr is that of the DNS proxy
784 * itself.
785 *
786 * last argument should be changed if Slirp will inject IP attributes
787 */
788 if ( pData->fUseDnsProxy
789 && so->so_fport == RT_H2N_U16_C(53)
790 && CTL_CHECK(so->so_faddr.s_addr, CTL_DNS))
791 dnsproxy_answer(pData, so, m);
792
793 /* packets definetly will be fragmented, could confuse receiver peer. */
794 if (nread > if_mtu)
795 m->m_flags |= M_SKIP_FIREWALL;
796
797 /*
798 * If this packet was destined for CTL_ADDR,
799 * make it look like that's where it came from, done by udp_output
800 */
801 udp_output(pData, so, m, &addr);
802 }
803 else
804 {
805 m_freem(pData, m);
806
807 if (!soIgnorableErrorCode(errno))
808 {
809 u_char code;
810 if (errno == EHOSTUNREACH)
811 code = ICMP_UNREACH_HOST;
812 else if (errno == ENETUNREACH)
813 code = ICMP_UNREACH_NET;
814 else
815 code = ICMP_UNREACH_PORT;
816
817 Log2((" rx error, tx icmp ICMP_UNREACH:%i\n", code));
818 icmp_error(pData, so->so_m, ICMP_UNREACH, code, 0, strerror(errno));
819 so->so_m = NULL;
820 }
821 }
822
823 SOCKET_UNLOCK(so);
824 }
825}
826
827/*
828 * sendto() a socket
829 */
830int
831sosendto(PNATState pData, struct socket *so, struct mbuf *m)
832{
833 int ret;
834 struct sockaddr_in *paddr;
835 struct sockaddr addr;
836#if 0
837 struct sockaddr_in host_addr;
838#endif
839 caddr_t buf = 0;
840 int mlen;
841
842 LogFlowFunc(("sosendto: so = %R[natsock], m = %p\n", so, m));
843
844 memset(&addr, 0, sizeof(struct sockaddr));
845#ifdef RT_OS_DARWIN
846 addr.sa_len = sizeof(struct sockaddr_in);
847#endif
848 paddr = (struct sockaddr_in *)&addr;
849 paddr->sin_family = AF_INET;
850 if ((so->so_faddr.s_addr & RT_H2N_U32(pData->netmask)) == pData->special_addr.s_addr)
851 {
852 /* It's an alias */
853 uint32_t last_byte = RT_N2H_U32(so->so_faddr.s_addr) & ~pData->netmask;
854 switch(last_byte)
855 {
856#if 0
857 /* handle this case at 'default:' */
858 case CTL_BROADCAST:
859 addr.sin_addr.s_addr = INADDR_BROADCAST;
860 /* Send the packet to host to fully emulate broadcast */
861 /** @todo r=klaus: on Linux host this causes the host to receive
862 * the packet twice for some reason. And I cannot find any place
863 * in the man pages which states that sending a broadcast does not
864 * reach the host itself. */
865 host_addr.sin_family = AF_INET;
866 host_addr.sin_port = so->so_fport;
867 host_addr.sin_addr = our_addr;
868 sendto(so->s, m->m_data, m->m_len, 0,
869 (struct sockaddr *)&host_addr, sizeof (struct sockaddr));
870 break;
871#endif
872 case CTL_DNS:
873 case CTL_ALIAS:
874 default:
875 if (last_byte == ~pData->netmask)
876 paddr->sin_addr.s_addr = INADDR_BROADCAST;
877 else
878 paddr->sin_addr = loopback_addr;
879 break;
880 }
881 }
882 else
883 paddr->sin_addr = so->so_faddr;
884 paddr->sin_port = so->so_fport;
885
886 Log2((" sendto()ing, addr.sin_port=%d, addr.sin_addr.s_addr=%.16s\n",
887 RT_N2H_U16(paddr->sin_port), inet_ntoa(paddr->sin_addr)));
888
889 /* Don't care what port we get */
890 /*
891 * > nmap -sV -T4 -O -A -v -PU3483 255.255.255.255
892 * generates bodyless messages, annoying memmory management system.
893 */
894 mlen = m_length(m, NULL);
895 if (mlen > 0)
896 {
897 buf = RTMemAlloc(mlen);
898 if (buf == NULL)
899 {
900 return -1;
901 }
902 m_copydata(m, 0, mlen, buf);
903 }
904 ret = sendto(so->s, buf, mlen, 0,
905 (struct sockaddr *)&addr, sizeof (struct sockaddr));
906#ifdef VBOX_WITH_NAT_SEND2HOME
907 if (slirpIsWideCasting(pData, so->so_faddr.s_addr))
908 {
909 slirpSend2Home(pData, so, buf, mlen, 0);
910 }
911#endif
912 if (buf)
913 RTMemFree(buf);
914 if (ret < 0)
915 {
916 Log2(("UDP: sendto fails (%s)\n", strerror(errno)));
917 return -1;
918 }
919
920 /*
921 * Kill the socket if there's no reply in 4 minutes,
922 * but only if it's an expirable socket
923 */
924 if (so->so_expire)
925 so->so_expire = curtime + SO_EXPIRE;
926 so->so_state = SS_ISFCONNECTED; /* So that it gets select()ed */
927 return 0;
928}
929
930/*
931 * XXX This should really be tcp_listen
932 */
933struct socket *
934solisten(PNATState pData, u_int32_t bind_addr, u_int port, u_int32_t laddr, u_int lport, int flags)
935{
936 struct sockaddr_in addr;
937 struct socket *so;
938 socklen_t addrlen = sizeof(addr);
939 int s, opt = 1;
940 int status;
941
942 LogFlowFunc(("solisten: port = %d, laddr = %x, lport = %d, flags = %x\n", port, laddr, lport, flags));
943
944 if ((so = socreate()) == NULL)
945 {
946 /* RTMemFree(so); Not sofree() ??? free(NULL) == NOP */
947 return NULL;
948 }
949
950 /* Don't tcp_attach... we don't need so_snd nor so_rcv */
951 if ((so->so_tcpcb = tcp_newtcpcb(pData, so)) == NULL)
952 {
953 RTMemFree(so);
954 return NULL;
955 }
956
957 SOCKET_LOCK_CREATE(so);
958 SOCKET_LOCK(so);
959 QSOCKET_LOCK(tcb);
960 insque(pData, so,&tcb);
961 NSOCK_INC();
962 QSOCKET_UNLOCK(tcb);
963
964 /*
965 * SS_FACCEPTONCE sockets must time out.
966 */
967 if (flags & SS_FACCEPTONCE)
968 so->so_tcpcb->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT*2;
969
970 so->so_state = (SS_FACCEPTCONN|flags);
971 so->so_lport = lport; /* Kept in network format */
972 so->so_laddr.s_addr = laddr; /* Ditto */
973
974 memset(&addr, 0, sizeof(addr));
975#ifdef RT_OS_DARWIN
976 addr.sin_len = sizeof(addr);
977#endif
978 addr.sin_family = AF_INET;
979 addr.sin_addr.s_addr = bind_addr;
980 addr.sin_port = port;
981
982 /**
983 * changing listen(,1->SOMAXCONN) shouldn't be harmful for NAT's TCP/IP stack,
984 * kernel will choose the optimal value for requests queue length.
985 * @note: MSDN recommends low (2-4) values for bluetooth networking devices.
986 */
987 if ( ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0)
988 || (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,(char *)&opt, sizeof(int)) < 0)
989 || (bind(s,(struct sockaddr *)&addr, sizeof(addr)) < 0)
990 || (listen(s, pData->soMaxConn) < 0))
991 {
992#ifdef RT_OS_WINDOWS
993 int tmperrno = WSAGetLastError(); /* Don't clobber the real reason we failed */
994 closesocket(s);
995 QSOCKET_LOCK(tcb);
996 sofree(pData, so);
997 QSOCKET_UNLOCK(tcb);
998 /* Restore the real errno */
999 WSASetLastError(tmperrno);
1000#else
1001 int tmperrno = errno; /* Don't clobber the real reason we failed */
1002 close(s);
1003 if (sototcpcb(so))
1004 tcp_close(pData, sototcpcb(so));
1005 else
1006 sofree(pData, so);
1007 /* Restore the real errno */
1008 errno = tmperrno;
1009#endif
1010 return NULL;
1011 }
1012 fd_nonblock(s);
1013 setsockopt(s, SOL_SOCKET, SO_OOBINLINE,(char *)&opt, sizeof(int));
1014
1015 getsockname(s,(struct sockaddr *)&addr,&addrlen);
1016 so->so_fport = addr.sin_port;
1017 /* set socket buffers */
1018 opt = pData->socket_rcv;
1019 status = setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&opt, sizeof(int));
1020 if (status < 0)
1021 {
1022 LogRel(("NAT: Error(%d) while setting RCV capacity to (%d)\n", errno, opt));
1023 goto no_sockopt;
1024 }
1025 opt = pData->socket_snd;
1026 status = setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *)&opt, sizeof(int));
1027 if (status < 0)
1028 {
1029 LogRel(("NAT: Error(%d) while setting SND capacity to (%d)\n", errno, opt));
1030 goto no_sockopt;
1031 }
1032no_sockopt:
1033 if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr)
1034 so->so_faddr = alias_addr;
1035 else
1036 so->so_faddr = addr.sin_addr;
1037
1038 so->s = s;
1039 SOCKET_UNLOCK(so);
1040 return so;
1041}
1042
1043/*
1044 * Data is available in so_rcv
1045 * Just write() the data to the socket
1046 * XXX not yet...
1047 * @todo do we really need this function, what it's intended to do?
1048 */
1049void
1050sorwakeup(struct socket *so)
1051{
1052 NOREF(so);
1053#if 0
1054 sowrite(so);
1055 FD_CLR(so->s,&writefds);
1056#endif
1057}
1058
1059/*
1060 * Data has been freed in so_snd
1061 * We have room for a read() if we want to
1062 * For now, don't read, it'll be done in the main loop
1063 */
1064void
1065sowwakeup(struct socket *so)
1066{
1067 NOREF(so);
1068}
1069
1070/*
1071 * Various session state calls
1072 * XXX Should be #define's
1073 * The socket state stuff needs work, these often get call 2 or 3
1074 * times each when only 1 was needed
1075 */
1076void
1077soisfconnecting(struct socket *so)
1078{
1079 so->so_state &= ~(SS_NOFDREF|SS_ISFCONNECTED|SS_FCANTRCVMORE|
1080 SS_FCANTSENDMORE|SS_FWDRAIN);
1081 so->so_state |= SS_ISFCONNECTING; /* Clobber other states */
1082}
1083
1084void
1085soisfconnected(struct socket *so)
1086{
1087 LogFlowFunc(("ENTER: so:%R[natsock]\n", so));
1088 so->so_state &= ~(SS_ISFCONNECTING|SS_FWDRAIN|SS_NOFDREF);
1089 so->so_state |= SS_ISFCONNECTED; /* Clobber other states */
1090 LogFlowFunc(("LEAVE: so:%R[natsock]\n", so));
1091}
1092
1093void
1094sofcantrcvmore(struct socket *so)
1095{
1096 LogFlowFunc(("ENTER: so:%R[natsock]\n", so));
1097 if ((so->so_state & SS_NOFDREF) == 0)
1098 {
1099 shutdown(so->s, 0);
1100 }
1101 so->so_state &= ~(SS_ISFCONNECTING);
1102 if (so->so_state & SS_FCANTSENDMORE)
1103 so->so_state = SS_NOFDREF; /* Don't select it */
1104 /* XXX close() here as well? */
1105 else
1106 so->so_state |= SS_FCANTRCVMORE;
1107 LogFlowFuncLeave();
1108}
1109
1110void
1111sofcantsendmore(struct socket *so)
1112{
1113 LogFlowFunc(("ENTER: so:%R[natsock]\n", so));
1114 if ((so->so_state & SS_NOFDREF) == 0)
1115 shutdown(so->s, 1); /* send FIN to fhost */
1116
1117 so->so_state &= ~(SS_ISFCONNECTING);
1118 if (so->so_state & SS_FCANTRCVMORE)
1119 so->so_state = SS_NOFDREF; /* as above */
1120 else
1121 so->so_state |= SS_FCANTSENDMORE;
1122 LogFlowFuncLeave();
1123}
1124
1125void
1126soisfdisconnected(struct socket *so)
1127{
1128 NOREF(so);
1129#if 0
1130 so->so_state &= ~(SS_ISFCONNECTING|SS_ISFCONNECTED);
1131 close(so->s);
1132 so->so_state = SS_ISFDISCONNECTED;
1133 /*
1134 * XXX Do nothing ... ?
1135 */
1136#endif
1137}
1138
1139/*
1140 * Set write drain mode
1141 * Set CANTSENDMORE once all data has been write()n
1142 */
1143void
1144sofwdrain(struct socket *so)
1145{
1146 if (SBUF_LEN(&so->so_rcv))
1147 so->so_state |= SS_FWDRAIN;
1148 else
1149 sofcantsendmore(so);
1150}
1151
1152#if !defined(RT_OS_WINDOWS)
1153static void
1154send_icmp_to_guest(PNATState pData, char *buff, size_t len, const struct sockaddr_in *addr)
1155{
1156 struct ip *ip;
1157 uint32_t dst, src;
1158 char ip_copy[256];
1159 struct icmp *icp;
1160 int old_ip_len = 0;
1161 int hlen, original_hlen = 0;
1162 struct mbuf *m;
1163 struct icmp_msg *icm;
1164 uint8_t proto;
1165 int type = 0;
1166
1167 ip = (struct ip *)buff;
1168 /* Fix ip->ip_len to contain the total packet length including the header
1169 * in _host_ byte order for all OSes. On Darwin, that value already is in
1170 * host byte order. Solaris and Darwin report only the payload. */
1171#ifndef RT_OS_DARWIN
1172 ip->ip_len = RT_N2H_U16(ip->ip_len);
1173#endif
1174 hlen = (ip->ip_hl << 2);
1175#if defined(RT_OS_SOLARIS) || defined(RT_OS_DARWIN)
1176 ip->ip_len += hlen;
1177#endif
1178 if (ip->ip_len < hlen + ICMP_MINLEN)
1179 {
1180 Log(("send_icmp_to_guest: ICMP header is too small to understand which type/subtype of the datagram\n"));
1181 return;
1182 }
1183 icp = (struct icmp *)((char *)ip + hlen);
1184
1185 Log(("ICMP:received msg(t:%d, c:%d)\n", icp->icmp_type, icp->icmp_code));
1186 if ( icp->icmp_type != ICMP_ECHOREPLY
1187 && icp->icmp_type != ICMP_TIMXCEED
1188 && icp->icmp_type != ICMP_UNREACH)
1189 {
1190 return;
1191 }
1192
1193 /*
1194 * ICMP_ECHOREPLY, ICMP_TIMXCEED, ICMP_UNREACH minimal header size is
1195 * ICMP_ECHOREPLY assuming data 0
1196 * icmp_{type(8), code(8), cksum(16),identifier(16),seqnum(16)}
1197 */
1198 if (ip->ip_len < hlen + 8)
1199 {
1200 Log(("send_icmp_to_guest: NAT accept ICMP_{ECHOREPLY, TIMXCEED, UNREACH} the minimum size is 64 (see rfc792)\n"));
1201 return;
1202 }
1203
1204 type = icp->icmp_type;
1205 if ( type == ICMP_TIMXCEED
1206 || type == ICMP_UNREACH)
1207 {
1208 /*
1209 * ICMP_TIMXCEED, ICMP_UNREACH minimal header size is
1210 * icmp_{type(8), code(8), cksum(16),unused(32)} + IP header + 64 bit of original datagram
1211 */
1212 if (ip->ip_len < hlen + 2*8 + sizeof(struct ip))
1213 {
1214 Log(("send_icmp_to_guest: NAT accept ICMP_{TIMXCEED, UNREACH} the minimum size of ipheader + 64 bit of data (see rfc792)\n"));
1215 return;
1216 }
1217 ip = &icp->icmp_ip;
1218 }
1219
1220 icm = icmp_find_original_mbuf(pData, ip);
1221 if (icm == NULL)
1222 {
1223 Log(("NAT: Can't find the corresponding packet for the received ICMP\n"));
1224 return;
1225 }
1226
1227 m = icm->im_m;
1228 if (!m)
1229 {
1230 LogFunc(("%R[natsock] hasn't stored it's mbuf on sent\n", icm->im_so));
1231 goto done;
1232 }
1233
1234 src = addr->sin_addr.s_addr;
1235 if (type == ICMP_ECHOREPLY)
1236 {
1237 struct ip *ip0 = mtod(m, struct ip *);
1238 struct icmp *icp0 = (struct icmp *)((char *)ip0 + (ip0->ip_hl << 2));
1239 if (icp0->icmp_type != ICMP_ECHO)
1240 {
1241 Log(("NAT: we haven't found echo for this reply\n"));
1242 goto done;
1243 }
1244 /*
1245 * while combining buffer to send (see ip_icmp.c) we control ICMP header only,
1246 * IP header combined by OS network stack, our local copy of IP header contians values
1247 * in host byte order so no byte order conversion is required. IP headers fields are converting
1248 * in ip_output0 routine only.
1249 */
1250 if ( (ip->ip_len - hlen)
1251 != (ip0->ip_len - (ip0->ip_hl << 2)))
1252 {
1253 Log(("NAT: ECHO(%d) lenght doesn't match ECHOREPLY(%d)\n",
1254 (ip->ip_len - hlen), (ip0->ip_len - (ip0->ip_hl << 2))));
1255 goto done;
1256 }
1257 }
1258
1259 /* ip points on origianal ip header */
1260 ip = mtod(m, struct ip *);
1261 proto = ip->ip_p;
1262 /* Now ip is pointing on header we've sent from guest */
1263 if ( icp->icmp_type == ICMP_TIMXCEED
1264 || icp->icmp_type == ICMP_UNREACH)
1265 {
1266 old_ip_len = (ip->ip_hl << 2) + 64;
1267 if (old_ip_len > sizeof(ip_copy))
1268 old_ip_len = sizeof(ip_copy);
1269 memcpy(ip_copy, ip, old_ip_len);
1270 }
1271
1272 /* source address from original IP packet*/
1273 dst = ip->ip_src.s_addr;
1274
1275 /* overide ther tail of old packet */
1276 ip = mtod(m, struct ip *); /* ip is from mbuf we've overrided */
1277 original_hlen = ip->ip_hl << 2;
1278 /* saves original ip header and options */
1279 m_copyback(pData, m, original_hlen, len - hlen, buff + hlen);
1280 ip->ip_len = m_length(m, NULL);
1281 ip->ip_p = IPPROTO_ICMP; /* the original package could be whatever, but we're response via ICMP*/
1282
1283 icp = (struct icmp *)((char *)ip + (ip->ip_hl << 2));
1284 type = icp->icmp_type;
1285 if ( type == ICMP_TIMXCEED
1286 || type == ICMP_UNREACH)
1287 {
1288 /* according RFC 793 error messages required copy of initial IP header + 64 bit */
1289 memcpy(&icp->icmp_ip, ip_copy, old_ip_len);
1290
1291 /* undo byte order conversions done in ip_input() */
1292 HTONS(icp->icmp_ip.ip_len);
1293 HTONS(icp->icmp_ip.ip_id);
1294 HTONS(icp->icmp_ip.ip_off);
1295
1296 ip->ip_tos = ((ip->ip_tos & 0x1E) | 0xC0); /* high priority for errors */
1297 }
1298
1299 ip->ip_src.s_addr = src;
1300 ip->ip_dst.s_addr = dst;
1301 icmp_reflect(pData, m);
1302 /* m was freed */
1303 icm->im_m = NULL;
1304
1305 done:
1306 icmp_msg_delete(pData, icm);
1307}
1308
1309static void sorecvfrom_icmp_unix(PNATState pData, struct socket *so)
1310{
1311 struct sockaddr_in addr;
1312 socklen_t addrlen = sizeof(struct sockaddr_in);
1313 struct ip ip;
1314 char *buff;
1315 int len = 0;
1316
1317 /* 1- step: read the ip header */
1318 len = recvfrom(so->s, &ip, sizeof(struct ip), MSG_PEEK,
1319 (struct sockaddr *)&addr, &addrlen);
1320 if ( len < 0
1321 && ( soIgnorableErrorCode(errno)
1322 || errno == ENOTCONN))
1323 {
1324 Log(("sorecvfrom_icmp_unix: 1 - step can't read IP datagramm (would block)\n"));
1325 return;
1326 }
1327
1328 if ( len < sizeof(struct ip)
1329 || len < 0
1330 || len == 0)
1331 {
1332 u_char code;
1333 code = ICMP_UNREACH_PORT;
1334
1335 if (errno == EHOSTUNREACH)
1336 code = ICMP_UNREACH_HOST;
1337 else if (errno == ENETUNREACH)
1338 code = ICMP_UNREACH_NET;
1339
1340 LogRel(("NAT: UDP ICMP rx errno=%d (%s)\n", errno, strerror(errno)));
1341 icmp_error(pData, so->so_m, ICMP_UNREACH, code, 0, strerror(errno));
1342 so->so_m = NULL;
1343 Log(("sorecvfrom_icmp_unix: 1 - step can't read IP datagramm\n"));
1344 return;
1345 }
1346 /* basic check of IP header */
1347 if ( ip.ip_v != IPVERSION
1348# ifndef RT_OS_DARWIN
1349 || ip.ip_p != IPPROTO_ICMP
1350# endif
1351 )
1352 {
1353 Log(("sorecvfrom_icmp_unix: 1 - step IP isn't IPv4\n"));
1354 return;
1355 }
1356# ifndef RT_OS_DARWIN
1357 /* Darwin reports the IP length already in host byte order. */
1358 ip.ip_len = RT_N2H_U16(ip.ip_len);
1359# endif
1360# if defined(RT_OS_SOLARIS) || defined(RT_OS_DARWIN)
1361 /* Solaris and Darwin report the payload only */
1362 ip.ip_len += (ip.ip_hl << 2);
1363# endif
1364 /* Note: ip->ip_len in host byte order (all OS) */
1365 len = ip.ip_len;
1366 buff = RTMemAlloc(len);
1367 if (buff == NULL)
1368 {
1369 Log(("sorecvfrom_icmp_unix: 1 - step can't allocate enought room for datagram\n"));
1370 return;
1371 }
1372 /* 2 - step: we're reading rest of the datagramm to the buffer */
1373 addrlen = sizeof(struct sockaddr_in);
1374 memset(&addr, 0, addrlen);
1375 len = recvfrom(so->s, buff, len, 0,
1376 (struct sockaddr *)&addr, &addrlen);
1377 if ( len < 0
1378 && ( soIgnorableErrorCode(errno)
1379 || errno == ENOTCONN))
1380 {
1381 Log(("sorecvfrom_icmp_unix: 2 - step can't read IP body (would block expected:%d)\n",
1382 ip.ip_len));
1383 RTMemFree(buff);
1384 return;
1385 }
1386 if ( len < 0
1387 || len == 0)
1388 {
1389 Log(("sorecvfrom_icmp_unix: 2 - step read of the rest of datagramm is fallen (errno:%d, len:%d expected: %d)\n",
1390 errno, len, (ip.ip_len - sizeof(struct ip))));
1391 RTMemFree(buff);
1392 return;
1393 }
1394 /* len is modified in 2nd read, when the rest of the datagramm was read */
1395 send_icmp_to_guest(pData, buff, len, &addr);
1396 RTMemFree(buff);
1397}
1398#endif /* !RT_OS_WINDOWS */
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