VirtualBox

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

Last change on this file since 41455 was 41455, checked in by vboxsync, 13 years ago

NAT: Don't spend time on connections with uninitiolized template.

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