- Timestamp:
- Nov 25, 2014 10:49:59 PM (10 years ago)
- Location:
- trunk/src/VBox/Devices/Network
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/DrvNAT.cpp
r52976 r53399 833 833 DWORD dwEvent = WSAWaitForMultipleEvents(nFDs, phEvents, FALSE, 834 834 slirp_get_timeout_ms(pThis->pNATState), 835 FALSE);835 /* :fAlertable */ TRUE); 836 836 if ( (dwEvent < WSA_WAIT_EVENT_0 || dwEvent > WSA_WAIT_EVENT_0 + nFDs - 1) 837 && dwEvent != WSA_WAIT_TIMEOUT )837 && dwEvent != WSA_WAIT_TIMEOUT && dwEvent != WSA_WAIT_IO_COMPLETION) 838 838 { 839 839 int error = WSAGetLastError(); … … 845 845 { 846 846 /* only check for slow/fast timers */ 847 slirp_select_poll(pThis->pNATState, /* fTimeout=*/true , /*fIcmp=*/false);847 slirp_select_poll(pThis->pNATState, /* fTimeout=*/true); 848 848 continue; 849 849 } 850 850 /* poll the sockets in any case */ 851 851 Log2(("%s: poll\n", __FUNCTION__)); 852 slirp_select_poll(pThis->pNATState, /* fTimeout=*/false , /* fIcmp=*/(dwEvent == WSA_WAIT_EVENT_0));852 slirp_select_poll(pThis->pNATState, /* fTimeout=*/false); 853 853 /* process _all_ outstanding requests but don't wait */ 854 854 RTReqQueueProcess(pThis->hSlirpReqQueue, 0); -
trunk/src/VBox/Devices/Network/slirp/ip_icmp.c
r53309 r53399 56 56 #include "slirp.h" 57 57 #include "ip_icmp.h" 58 #ifdef RT_OS_WINDOWS59 # include <Icmpapi.h>60 # include <Iphlpapi.h>61 # include <iprt/ldr.h>62 #endif63 58 64 59 /* The message sent when emulating PING */ … … 97 92 pData->icmp_socket.so_type = IPPROTO_ICMP; 98 93 pData->icmp_socket.so_state = SS_ISFCONNECTED; 94 95 #ifndef RT_OS_WINDOWS 99 96 if (iIcmpCacheLimit < 0) 100 97 { … … 103 100 } 104 101 pData->iIcmpCacheLimit = iIcmpCacheLimit; 105 #ifndef RT_OS_WINDOWS106 102 # ifndef RT_OS_DARWIN 107 103 pData->icmp_socket.s = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP); … … 118 114 NSOCK_INC(); 119 115 116 LIST_INIT(&pData->icmp_msg_head); 117 120 118 #else /* RT_OS_WINDOWS */ 121 119 if (icmpwin_init(pData) != 0) … … 123 121 #endif /* RT_OS_WINDOWS */ 124 122 125 LIST_INIT(&pData->icmp_msg_head);126 123 return 0; 127 124 } … … 133 130 icmp_finit(PNATState pData) 134 131 { 135 icmp_cache_clean(pData, -1);136 132 #ifdef RT_OS_WINDOWS 137 133 icmpwin_finit(pData); 138 134 #else 135 icmp_cache_clean(pData, -1); 139 136 closesocket(pData->icmp_socket.s); 140 137 #endif 141 138 } 142 139 140 #if !defined(RT_OS_WINDOWS) 143 141 /* 144 142 * ip here is ip header + 64bytes readed from ICMP packet … … 339 337 return 0; 340 338 } 339 #endif /* !RT_OS_WINDOWS */ 341 340 342 341 /* … … 350 349 uint8_t icmp_type; 351 350 void *icp_buf = NULL; 352 int status;353 351 uint32_t dst; 354 #if !defined(RT_OS_WINDOWS)355 int ttl;356 #endif357 352 358 353 /* int code; */ … … 409 404 goto done; 410 405 } 411 else 406 407 #ifdef RT_OS_WINDOWS 408 { 409 icmpwin_ping(pData, m, hlen); 410 break; /* free mbuf */ 411 } 412 #else 412 413 { 413 414 struct icmp *icp; 414 415 struct sockaddr_in addr; 415 #ifdef RT_OS_WINDOWS 416 IP_OPTION_INFORMATION ipopt; 417 int error; 418 #endif 416 417 /* XXX: FIXME: this is bogus, see CTL_CHECKs above */ 419 418 addr.sin_family = AF_INET; 420 419 if ((ip->ip_dst.s_addr & RT_H2N_U32(pData->netmask)) == pData->special_addr.s_addr) … … 447 446 icp = (struct icmp *)(mtod(m, char *) + hlen); 448 447 449 #ifndef RT_OS_WINDOWS450 448 if (pData->icmp_socket.s != -1) 451 449 { 450 static bool fIcmpSocketErrorReported; 451 int ttl; 452 int status; 452 453 ssize_t rc; 453 static bool fIcmpSocketErrorReported; 454 454 455 ttl = ip->ip_ttl; 455 456 Log(("NAT/ICMP: try to set TTL(%d)\n", ttl)); … … 478 479 icmp_error(pData, m, ICMP_UNREACH, ICMP_UNREACH_NET, 0, strerror(errno)); 479 480 } 480 #else /* RT_OS_WINDOWS */ 481 pData->icmp_socket.so_laddr.s_addr = ip->ip_src.s_addr; /* XXX: hack*/ 482 pData->icmp_socket.so_icmp_id = icp->icmp_id; 483 pData->icmp_socket.so_icmp_seq = icp->icmp_seq; 484 memset(&ipopt, 0, sizeof(IP_OPTION_INFORMATION)); 485 ipopt.Ttl = ip->ip_ttl; 486 status = IcmpSendEcho2(pData->icmp_socket.sh /*=handle*/, 487 pData->phEvents[VBOX_ICMP_EVENT_INDEX] /*=Event*/, 488 NULL /*=ApcRoutine*/, 489 NULL /*=ApcContext*/, 490 addr.sin_addr.s_addr /*=DestinationAddress*/, 491 icp->icmp_data /*=RequestData*/, 492 icmplen - ICMP_MINLEN /*=RequestSize*/, 493 &ipopt /*=RequestOptions*/, 494 pData->pvIcmpBuffer /*=ReplyBuffer*/, 495 pData->cbIcmpBuffer /*=ReplySize*/, 496 1 /*=Timeout in ms*/); 497 error = GetLastError(); 498 if ( status != 0 499 || error == ERROR_IO_PENDING) 500 { 501 /* no error! */ 502 m->m_so = &pData->icmp_socket; 503 icmp_attach(pData, m); 504 /* don't let m_freem at the end free atached buffer */ 505 goto done; 506 } 507 Log(("NAT: Error (%d) occurred while sending ICMP (", error)); 508 switch (error) 509 { 510 case ERROR_INVALID_PARAMETER: 511 Log(("icmp_socket:%lx is invalid)\n", pData->icmp_socket.s)); 512 break; 513 case ERROR_NOT_SUPPORTED: 514 Log(("operation is unsupported)\n")); 515 break; 516 case ERROR_NOT_ENOUGH_MEMORY: 517 Log(("OOM!!!)\n")); 518 break; 519 case IP_BUF_TOO_SMALL: 520 Log(("Buffer too small)\n")); 521 break; 522 default: 523 Log(("Other error!!!)\n")); 524 break; 525 } 526 #endif /* RT_OS_WINDOWS */ 527 } /* if ip->ip_dst.s_addr == alias_addr.s_addr */ 481 } 482 #endif /* !RT_OS_WINDOWS */ 528 483 break; 529 484 case ICMP_UNREACH: -
trunk/src/VBox/Devices/Network/slirp/ip_icmp.h
r53350 r53399 208 208 void icmpwin_finit (PNATState); 209 209 void icmpwin_ping(PNATState, struct mbuf *, int); 210 void icmpwin_process(PNATState); 210 211 #endif 211 212 -
trunk/src/VBox/Devices/Network/slirp/ip_icmpwin.c
r53381 r53399 41 41 PNATState pData; 42 42 43 TAILQ_ENTRY(pong) queue_entry; 44 43 45 struct ip reqiph; 44 46 struct icmp_echo reqicmph; … … 53 55 54 56 static void icmpwin_callback(struct pong *pong); 57 static void icmpwin_pong(struct pong *pong); 55 58 56 59 static struct mbuf *icmpwin_get_error(struct pong *pong, int type, int code); … … 91 94 } 92 95 96 TAILQ_INIT(&pData->pongs_expected); 97 TAILQ_INIT(&pData->pongs_received); 98 93 99 pData->icmp_socket.sh = IcmpCreateFile(); 94 100 pData->phEvents[VBOX_ICMP_EVENT_INDEX] = CreateEvent(NULL, FALSE, FALSE, NULL); 95 pData->cbIcmpBuffer = sizeof(ICMP_ECHO_REPLY) * 10;96 pData->pvIcmpBuffer = RTMemAlloc(pData->cbIcmpBuffer);97 101 98 102 return 0; … … 104 108 { 105 109 IcmpCloseHandle(pData->icmp_socket.sh); 106 RTMemFree(pData->pvIcmpBuffer); 110 111 while (!TAILQ_EMPTY(&pData->pongs_received)) { 112 struct pong *pong = TAILQ_FIRST(&pData->pongs_received); 113 TAILQ_REMOVE(&pData->pongs_received, pong, queue_entry); 114 RTMemFree(pong); 115 } 116 117 /* this should be empty */ 118 while (!TAILQ_EMPTY(&pData->pongs_expected)) { 119 struct pong *pong = TAILQ_FIRST(&pData->pongs_expected); 120 TAILQ_REMOVE(&pData->pongs_expected, pong, queue_entry); 121 pong->pData = NULL; 122 } 107 123 } 108 124 … … 115 131 { 116 132 struct ip *ip = mtod(m, struct ip *); 117 size_t reqsize ;133 size_t reqsize, pongsize; 118 134 uint8_t ttl; 119 135 size_t bufsize; … … 137 153 bufsize += 16; /* whatever that is; empirically at least XP needs it */ 138 154 139 pong = RTMemAlloc(RT_OFFSETOF(struct pong, buf) + bufsize); 155 pongsize = RT_OFFSETOF(struct pong, buf) + bufsize; 156 if (pData->cbIcmpPending + pongsize > 1024 * 1024) 157 return; 158 159 pong = RTMemAlloc(pongsize); 140 160 if (RT_UNLIKELY(pong == NULL)) 141 161 return; … … 209 229 else /* success */ 210 230 { 211 Log2(("NAT: pong %p for ping %RTnaipv4 id 0x%04x seq %d len % d\n",231 Log2(("NAT: pong %p for ping %RTnaipv4 id 0x%04x seq %d len %zu (%zu)\n", 212 232 pong, dst, 213 233 RT_N2H_U16(pong->reqicmph.icmp_echo_id), 214 234 RT_N2H_U16(pong->reqicmph.icmp_echo_seq), 215 reqsize)); 235 pongsize, reqsize)); 236 237 pData->cbIcmpPending += pongsize; 238 TAILQ_INSERT_TAIL(&pData->pongs_expected, pong, queue_entry); 216 239 pong = NULL; /* callback owns it now */ 217 240 } … … 226 249 { 227 250 struct pong *pong = (struct pong *)ctx; 228 229 251 if (pong != NULL) 230 {231 252 icmpwin_callback(pong); 232 RTMemFree(pong);233 }234 253 } 235 254 … … 239 258 { 240 259 struct pong *pong = (struct pong *)ctx; 241 242 260 if (pong != NULL) 243 {244 261 icmpwin_callback(pong); 245 RTMemFree(pong);246 }247 262 } 248 263 … … 251 266 * Actual callback code for IcmpSendEcho2(). OS version specific 252 267 * trampoline will free "pong" argument for us. 268 * 269 * Since async callback can be called anytime the thread is alertable, 270 * it's not safe to do any processing here. Instead queue it and 271 * notify the main loop. 253 272 */ 254 273 static void 255 274 icmpwin_callback(struct pong *pong) 275 { 276 PNATState pData = pong->pData; 277 278 if (pData == NULL) 279 { 280 RTMemFree(pong); 281 return; 282 } 283 284 #ifdef DEBUG 285 { 286 struct pong *expected, *already; 287 288 TAILQ_FOREACH(expected, &pData->pongs_expected, queue_entry) 289 { 290 if (expected == pong) 291 break; 292 } 293 Assert(expected); 294 295 TAILQ_FOREACH(already, &pData->pongs_received, queue_entry) 296 { 297 if (already == pong) 298 break; 299 } 300 Assert(!already); 301 } 302 #endif 303 304 TAILQ_REMOVE(&pData->pongs_expected, pong, queue_entry); 305 TAILQ_INSERT_TAIL(&pData->pongs_received, pong, queue_entry); 306 307 WSASetEvent(pData->phEvents[VBOX_ICMP_EVENT_INDEX]); 308 } 309 310 311 void 312 icmpwin_process(PNATState pData) 313 { 314 struct pong_tailq pongs; 315 316 if (TAILQ_EMPTY(&pData->pongs_received)) 317 return; 318 319 TAILQ_INIT(&pongs); 320 TAILQ_CONCAT(&pongs, &pData->pongs_received, queue_entry); 321 322 while (!TAILQ_EMPTY(&pongs)) { 323 struct pong *pong = TAILQ_FIRST(&pongs); 324 size_t sz; 325 326 sz = RT_OFFSETOF(struct pong, buf) + pong->bufsize; 327 Assert(pData->cbIcmpPending >= sz); 328 pData->cbIcmpPending -= sz; 329 330 icmpwin_pong(pong); 331 332 TAILQ_REMOVE(&pongs, pong, queue_entry); 333 RTMemFree(pong); 334 } 335 } 336 337 338 void 339 icmpwin_pong(struct pong *pong) 256 340 { 257 341 PNATState pData; -
trunk/src/VBox/Devices/Network/slirp/libslirp.h
r50949 r53399 56 56 void slirp_select_fill(PNATState pData, int *pndfs); 57 57 58 void slirp_select_poll(PNATState pData, int fTimeout , int fIcmp);58 void slirp_select_poll(PNATState pData, int fTimeout); 59 59 #else /* RT_OS_WINDOWS */ 60 60 void slirp_select_fill(PNATState pData, int *pnfds, struct pollfd *polls); -
trunk/src/VBox/Devices/Network/slirp/slirp.c
r53338 r53399 892 892 893 893 #if defined(RT_OS_WINDOWS) 894 void slirp_select_poll(PNATState pData, int fTimeout , int fIcmp)894 void slirp_select_poll(PNATState pData, int fTimeout) 895 895 #else /* RT_OS_WINDOWS */ 896 896 void slirp_select_poll(PNATState pData, struct pollfd *polls, int ndfs) … … 942 942 goto done; 943 943 #if defined(RT_OS_WINDOWS) 944 /*XXX: before renaming please make see define 945 * fIcmp in slirp_state.h 946 */ 947 if (fIcmp) 948 sorecvfrom(pData, &pData->icmp_socket); 944 icmpwin_process(pData); 949 945 #else 950 946 if ( (pData->icmp_socket.s != -1) -
trunk/src/VBox/Devices/Network/slirp/slirp_state.h
r53382 r53399 96 96 97 97 98 #ifdef RT_OS_WINDOWS 99 struct pong; 100 TAILQ_HEAD(pong_tailq, pong); 101 #endif 98 102 99 103 /* forward declaration */ … … 199 203 200 204 struct socket icmp_socket; 205 # if !defined(RT_OS_WINDOWS) 201 206 struct icmp_storage icmp_msg_head; 202 207 int cIcmpCacheSize; 203 208 int iIcmpCacheLimit; 204 # ifdef RT_OS_WINDOWS 205 void *pvIcmpBuffer; 206 uint32_t cbIcmpBuffer; 209 # else 210 struct pong_tailq pongs_expected; 211 struct pong_tailq pongs_received; 212 size_t cbIcmpPending; 207 213 # endif 214 208 215 #if defined(RT_OS_WINDOWS) 209 216 # define VBOX_SOCKET_EVENT (pData->phEvents[VBOX_SOCKET_EVENT_INDEX]) -
trunk/src/VBox/Devices/Network/slirp/socket.c
r53310 r53399 128 128 } 129 129 #endif /* !VBOX_WITH_NAT_SEND2HOME */ 130 131 #if !defined(RT_OS_WINDOWS) 130 132 static void send_icmp_to_guest(PNATState, char *, size_t, const struct sockaddr_in *); 131 #ifdef RT_OS_WINDOWS132 static void sorecvfrom_icmp_win(PNATState, struct socket *);133 #else /* RT_OS_WINDOWS */134 133 static void sorecvfrom_icmp_unix(PNATState, struct socket *); 135 134 #endif /* !RT_OS_WINDOWS */ … … 811 810 { 812 811 LogFlowFunc(("sorecvfrom: so = %lx\n", (long)so)); 813 812 813 #ifdef RT_OS_WINDOWS 814 /* ping is handled with ICMP API in ip_icmpwin.c */ 815 Assert(so->so_type == IPPROTO_UDP); 816 #else 814 817 if (so->so_type == IPPROTO_ICMP) 815 818 { 816 819 /* This is a "ping" reply */ 817 #ifdef RT_OS_WINDOWS818 sorecvfrom_icmp_win(pData, so);819 #else /* RT_OS_WINDOWS */820 820 sorecvfrom_icmp_unix(pData, so); 821 udp_detach(pData, so); 822 } 823 else 821 824 #endif /* !RT_OS_WINDOWS */ 822 udp_detach(pData, so);823 }824 else825 825 { 826 826 static uint8_t au8Buf[64 * 1024]; … … 1272 1272 } 1273 1273 1274 #if !defined(RT_OS_WINDOWS) 1274 1275 static void 1275 1276 send_icmp_to_guest(PNATState pData, char *buff, size_t len, const struct sockaddr_in *addr) … … 1442 1443 } 1443 1444 1444 #ifdef RT_OS_WINDOWS1445 static void1446 sorecvfrom_icmp_win(PNATState pData, struct socket *so)1447 {1448 int len;1449 int i;1450 struct ip *ip;1451 struct mbuf *m;1452 struct icmp *icp;1453 struct icmp_msg *icm;1454 struct ip *ip_broken; /* ICMP returns header + 64 bit of packet */1455 uint32_t src;1456 ICMP_ECHO_REPLY *icr;1457 int hlen = 0;1458 int nbytes = 0;1459 u_char code = ~0;1460 int out_len;1461 int size;1462 1463 len = IcmpParseReplies(pData->pvIcmpBuffer, pData->cbIcmpBuffer);1464 if (len < 0)1465 {1466 LogRel(("NAT: Error (%d) occurred on ICMP receiving\n", GetLastError()));1467 return;1468 }1469 if (len == 0)1470 return; /* no error */1471 1472 icr = (ICMP_ECHO_REPLY *)pData->pvIcmpBuffer;1473 for (i = 0; i < len; ++i)1474 {1475 LogFunc(("icr[%d] Data:%p, DataSize:%d\n",1476 i, icr[i].Data, icr[i].DataSize));1477 switch(icr[i].Status)1478 {1479 case IP_DEST_HOST_UNREACHABLE:1480 code = (code != ~0 ? code : ICMP_UNREACH_HOST);1481 case IP_DEST_NET_UNREACHABLE:1482 code = (code != ~0 ? code : ICMP_UNREACH_NET);1483 case IP_DEST_PROT_UNREACHABLE:1484 code = (code != ~0 ? code : ICMP_UNREACH_PROTOCOL);1485 /* UNREACH error inject here */1486 case IP_DEST_PORT_UNREACHABLE:1487 code = (code != ~0 ? code : ICMP_UNREACH_PORT);1488 icmp_error(pData, so->so_m, ICMP_UNREACH, code, 0, "Error occurred!!!");1489 so->so_m = NULL;1490 break;1491 case IP_SUCCESS: /* echo replied */1492 out_len = ETH_HLEN + sizeof(struct ip) + 8;1493 size;1494 size = MCLBYTES;1495 if (out_len < MSIZE)1496 size = MCLBYTES;1497 else if (out_len < MCLBYTES)1498 size = MCLBYTES;1499 else if (out_len < MJUM9BYTES)1500 size = MJUM9BYTES;1501 else if (out_len < MJUM16BYTES)1502 size = MJUM16BYTES;1503 else1504 AssertMsgFailed(("Unsupported size"));1505 1506 m = m_getjcl(pData, M_NOWAIT, MT_HEADER, M_PKTHDR, size);1507 LogFunc(("m_getjcl returns m: %p\n", m));1508 if (m == NULL)1509 return;1510 m->m_len = 0;1511 m->m_data += if_maxlinkhdr;1512 m->m_pkthdr.header = mtod(m, void *);1513 1514 ip = mtod(m, struct ip *);1515 ip->ip_src.s_addr = icr[i].Address;1516 ip->ip_p = IPPROTO_ICMP;1517 ip->ip_dst.s_addr = so->so_laddr.s_addr; /*XXX: still the hack*/1518 ip->ip_hl = sizeof(struct ip) >> 2; /* requiered for icmp_reflect, no IP options */1519 ip->ip_ttl = icr[i].Options.Ttl;1520 1521 icp = (struct icmp *)&ip[1]; /* no options */1522 icp->icmp_type = ICMP_ECHOREPLY;1523 icp->icmp_code = 0;1524 icp->icmp_id = so->so_icmp_id;1525 icp->icmp_seq = so->so_icmp_seq;1526 1527 icm = icmp_find_original_mbuf(pData, ip);1528 if (icm)1529 {1530 /* on this branch we don't need stored variant */1531 m_freem(pData, icm->im_m);1532 LIST_REMOVE(icm, im_list);1533 pData->cIcmpCacheSize--;1534 RTMemFree(icm);1535 }1536 1537 1538 hlen = (ip->ip_hl << 2);1539 Assert((hlen >= sizeof(struct ip)));1540 1541 m->m_data += hlen + ICMP_MINLEN;1542 if (!RT_VALID_PTR(icr[i].Data))1543 {1544 m_freem(pData, m);1545 break;1546 }1547 m_copyback(pData, m, 0, icr[i].DataSize, icr[i].Data);1548 m->m_data -= hlen + ICMP_MINLEN;1549 m->m_len += hlen + ICMP_MINLEN;1550 1551 1552 ip->ip_len = m_length(m, NULL);1553 Assert((ip->ip_len == hlen + ICMP_MINLEN + icr[i].DataSize));1554 1555 icmp_reflect(pData, m);1556 break;1557 case IP_TTL_EXPIRED_TRANSIT: /* TTL expired */1558 1559 ip_broken = icr[i].Data;1560 icm = icmp_find_original_mbuf(pData, ip_broken);1561 if (icm == NULL) {1562 Log(("ICMP: can't find original package (first double word %x)\n", *(uint32_t *)ip_broken));1563 return;1564 }1565 m = icm->im_m;1566 ip = mtod(m, struct ip *);1567 Assert(((ip_broken->ip_hl >> 2) >= sizeof(struct ip)));1568 ip->ip_ttl = icr[i].Options.Ttl;1569 src = ip->ip_src.s_addr;1570 ip->ip_dst.s_addr = src;1571 ip->ip_dst.s_addr = icr[i].Address;1572 1573 hlen = (ip->ip_hl << 2);1574 icp = (struct icmp *)((char *)ip + hlen);1575 ip_broken->ip_src.s_addr = src; /*it packet sent from host not from guest*/1576 1577 m->m_len = (ip_broken->ip_hl << 2) + 64;1578 m->m_pkthdr.header = mtod(m, void *);1579 m_copyback(pData, m, ip->ip_hl >> 2, icr[i].DataSize, icr[i].Data);1580 icmp_reflect(pData, m);1581 /* Here is different situation from Unix world, where we can receive icmp in response on TCP/UDP */1582 LIST_REMOVE(icm, im_list);1583 pData->cIcmpCacheSize--;1584 RTMemFree(icm);1585 break;1586 default:1587 Log(("ICMP(default): message with Status: %x was received from %x\n", icr[i].Status, icr[i].Address));1588 break;1589 }1590 }1591 }1592 #else /* !RT_OS_WINDOWS */1593 1445 static void sorecvfrom_icmp_unix(PNATState pData, struct socket *so) 1594 1446 {
Note:
See TracChangeset
for help on using the changeset viewer.