- Timestamp:
- Oct 23, 2013 4:53:22 AM (11 years ago)
- Location:
- trunk/src/VBox/NetworkServices/NAT
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/NetworkServices/NAT/Makefile.kmk
r49119 r49249 58 58 pxtcp.c \ 59 59 pxudp.c \ 60 pxdns.c \ 60 61 fwtcp.c \ 61 62 fwudp.c \ -
trunk/src/VBox/NetworkServices/NAT/VBoxNetLwipNAT.cpp
r49210 r49249 193 193 STDMETHOD(HandleEvent)(VBoxEventType_T aEventType, IEvent *pEvent); 194 194 195 const char **getHostNameservers(); 196 195 197 RTSEMEVENT hSemSVC; 196 198 /* Only for debug needs, by default NAT service should load rules from SVC … … 375 377 strHostAddr.setNull(); 376 378 strGuestAddr.setNull(); 379 break; 380 } 381 382 case VBoxEventType_OnHostNameResolutionConfigurationChange: 383 { 384 const char **ppcszNameServers = getHostNameservers(); 385 err_t error; 386 387 error = tcpip_callback_with_block(pxdns_set_nameservers, 388 ppcszNameServers, 389 /* :block */ 0); 390 if (error != ERR_OK && ppcszNameServers != NULL) 391 { 392 RTMemFree(ppcszNameServers); 393 } 377 394 break; 378 395 } … … 765 782 m_src6.sin6_len = sizeof(m_src6); 766 783 #endif 784 m_ProxyOptions.nameservers = NULL; 767 785 768 786 m_LwipNetIf.name[0] = 'N'; … … 1043 1061 } 1044 1062 1063 m_ProxyOptions.nameservers = getHostNameservers(); 1064 1045 1065 /* end of COM initialization */ 1046 1066 … … 1067 1087 LogFlowFuncLeaveRC(rc); 1068 1088 return rc; 1089 } 1090 1091 1092 const char **VBoxNetLwipNAT::getHostNameservers() 1093 { 1094 HRESULT hrc; 1095 1096 if (m_host.isNull()) 1097 { 1098 return NULL; 1099 } 1100 1101 com::SafeArray<BSTR> aNameServers; 1102 hrc = m_host->COMGETTER(NameServers)(ComSafeArrayAsOutParam(aNameServers)); 1103 if (FAILED(hrc)) 1104 { 1105 return NULL; 1106 } 1107 1108 const size_t cNameServers = aNameServers.size(); 1109 if (cNameServers == 0) 1110 { 1111 return NULL; 1112 } 1113 1114 const char **ppcszNameServers = 1115 (const char **)RTMemAllocZ(sizeof(char *) * (cNameServers + 1)); 1116 if (ppcszNameServers == NULL) 1117 { 1118 return NULL; 1119 } 1120 1121 size_t idxLast = 0; 1122 for (size_t i = 0; i < cNameServers; ++i) 1123 { 1124 com::Utf8Str strNameServer(aNameServers[i]); 1125 ppcszNameServers[idxLast] = RTStrDup(strNameServer.c_str()); 1126 if (ppcszNameServers[idxLast] != NULL) 1127 { 1128 ++idxLast; 1129 } 1130 } 1131 1132 if (idxLast == 0) 1133 { 1134 RTMemFree(ppcszNameServers); 1135 return NULL; 1136 } 1137 1138 return ppcszNameServers; 1069 1139 } 1070 1140 -
trunk/src/VBox/NetworkServices/NAT/proxy.c
r49016 r49249 35 35 static SOCKET proxy_create_socket(int, int); 36 36 37 volatile conststruct proxy_options *g_proxy_options;37 volatile struct proxy_options *g_proxy_options; 38 38 static sys_thread_t pollmgr_tid; 39 39 … … 46 46 */ 47 47 void 48 proxy_init(struct netif *proxy_netif, conststruct proxy_options *opts)48 proxy_init(struct netif *proxy_netif, struct proxy_options *opts) 49 49 { 50 50 int status; … … 83 83 84 84 portfwd_init(); 85 86 pxdns_init(proxy_netif); 85 87 86 88 pollmgr_tid = sys_thread_new("pollmgr_thread", -
trunk/src/VBox/NetworkServices/NAT/proxy.h
r49149 r49249 37 37 const struct sockaddr_in6 *src6; 38 38 const struct ip4_lomap_desc *lomap_desc; 39 const char **nameservers; 39 40 }; 40 41 41 extern volatile conststruct proxy_options *g_proxy_options;42 extern volatile struct proxy_options *g_proxy_options; 42 43 extern struct netif *g_proxy_netif; 43 44 44 void proxy_init(struct netif *, conststruct proxy_options *);45 void proxy_init(struct netif *, struct proxy_options *); 45 46 SOCKET proxy_connected_socket(int, int, ipX_addr_t *, u16_t); 46 47 SOCKET proxy_bound_socket(int, int, struct sockaddr *); … … 69 70 void pxudp_init(void); 70 71 72 /* pxdns.c */ 73 err_t pxdns_init(struct netif *); 74 void pxdns_set_nameservers(void *); 75 71 76 72 77 #if defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS) || defined(RT_OS_WINDOWS) -
trunk/src/VBox/NetworkServices/NAT/pxdns.c
r49016 r49249 34 34 * DEALINGS IN THE SOFTWARE. 35 35 */ 36 #include "winutils.h" 37 36 38 #include "proxy.h" 37 39 #include "proxy_pollmgr.h" … … 41 43 #include "lwip/udp.h" 42 44 45 #ifndef RT_OS_WINDOWS 43 46 #include <sys/poll.h> 44 47 #include <sys/socket.h> 45 48 #include <netinet/in.h> 49 #include <netdb.h> 50 #else 51 #include "winpoll.h" 52 #endif 46 53 47 54 #include <string.h> 55 56 57 union sockaddr_inet { 58 struct sockaddr sa; 59 struct sockaddr_in sin; 60 struct sockaddr_in6 sin6; 61 }; 48 62 49 63 … … 55 69 */ 56 70 struct pxdns { 57 struct pollmgr_handler pmhdl; 58 59 struct udp_pcb *pcb4; /* lwIP doesn't support listening for */ 60 struct udp_pcb *pcb6; /* both IPv4 and IPv6 on single pcb. */ 61 62 SOCKET sock; 71 SOCKET sock4; 72 SOCKET sock6; 73 74 struct pollmgr_handler pmhdl4; 75 struct pollmgr_handler pmhdl6; 76 77 struct udp_pcb *pcb4; 78 struct udp_pcb *pcb6; 79 80 size_t generation; 81 size_t nresolvers; 82 union sockaddr_inet *resolvers; 63 83 64 84 u16_t id; 65 66 /* XXX: TODO: support multiple, support IPv6 */67 struct sockaddr_in resolver_sin;68 socklen_t resolver_sinlen;69 85 70 86 sys_mutex_t lock; … … 92 108 93 109 /** 94 * XXX: TODO: to test rexmit code, rexmit to the same resolver 95 * multiple times; to be replaced with trying the next resolver. 96 */ 97 size_t rexmit_count; 110 * pxdns::generation used for this request 111 */ 112 size_t generation; 113 114 /** 115 * Current index into pxdns::resolvers 116 */ 117 size_t residx; 98 118 99 119 /** … … 142 162 }; 143 163 164 165 static void pxdns_create_resolver_sockaddrs(struct pxdns *pxdns, 166 const char **nameservers); 144 167 145 168 static void pxdns_recv4(void *arg, struct udp_pcb *pcb, struct pbuf *p, … … 176 199 LWIP_UNUSED_ARG(proxy_netif); 177 200 178 pxdns->pmhdl.callback = pxdns_pmgr_pump; 179 pxdns->pmhdl.data = (void *)pxdns; 180 pxdns->pmhdl.slot = -1; 201 pxdns->pmhdl4.callback = pxdns_pmgr_pump; 202 pxdns->pmhdl4.data = (void *)pxdns; 203 pxdns->pmhdl4.slot = -1; 204 205 pxdns->pmhdl6.callback = pxdns_pmgr_pump; 206 pxdns->pmhdl6.data = (void *)pxdns; 207 pxdns->pmhdl6.slot = -1; 181 208 182 209 pxdns->pcb4 = udp_new(); … … 197 224 } 198 225 199 error = udp_bind_ip6(pxdns->pcb 4, IP6_ADDR_ANY, 53);226 error = udp_bind_ip6(pxdns->pcb6, IP6_ADDR_ANY, 53); 200 227 if (error != ERR_OK) { 201 228 goto err_cleanup_pcb; … … 205 232 udp_recv_ip6(pxdns->pcb6, pxdns_recv6, pxdns); 206 233 207 pxdns->sock = socket(AF_INET, SOCK_DGRAM, 0);208 if (pxdns->sock == INVALID_SOCKET) {234 pxdns->sock4 = socket(AF_INET, SOCK_DGRAM, 0); 235 if (pxdns->sock4 == INVALID_SOCKET) { 209 236 goto err_cleanup_pcb; 210 237 } 211 238 212 /* XXX: TODO: support multiple, support IPv6 */ 213 pxdns->resolver_sin.sin_family = AF_INET; 214 pxdns->resolver_sin.sin_addr.s_addr = PP_HTONL(0x7f000001); /* XXX */ 215 pxdns->resolver_sin.sin_port = PP_HTONS(53); 216 #if HAVE_SA_LEN 217 pxdns->resolver_sin.sin_len = 218 #endif 219 pxdns->resolver_sinlen = sizeof(pxdns->resolver_sin); 239 pxdns->sock6 = socket(AF_INET6, SOCK_DGRAM, 0); 240 if (pxdns->sock6 == INVALID_SOCKET) { 241 /* it's ok if the host doesn't support IPv6 */ 242 /* XXX: TODO: log */ 243 } 244 245 pxdns->generation = 0; 246 pxdns->nresolvers = 0; 247 pxdns->resolvers = NULL; 248 pxdns_create_resolver_sockaddrs(pxdns, g_proxy_options->nameservers); 220 249 221 250 sys_mutex_new(&pxdns->lock); … … 223 252 pxdns->timeout_slot = 0; 224 253 225 /* XXX: assumes pollmgr thread is not running yet */ 226 pollmgr_add(&pxdns->pmhdl, pxdns->sock, POLLIN); 254 /* NB: assumes pollmgr thread is not running yet */ 255 pollmgr_add(&pxdns->pmhdl4, pxdns->sock4, POLLIN); 256 if (pxdns->sock6 != INVALID_SOCKET) { 257 pollmgr_add(&pxdns->pmhdl6, pxdns->sock6, POLLIN); 258 } 227 259 228 260 sys_timeout(1 * 1000, pxdns_timer, pxdns); … … 241 273 242 274 return error; 275 } 276 277 278 /** 279 * lwIP thread callback to set the new list of nameservers. 280 */ 281 void 282 pxdns_set_nameservers(void *arg) 283 { 284 const char **nameservers = (const char **)arg; 285 286 if (g_proxy_options->nameservers != NULL) { 287 RTMemFree(g_proxy_options->nameservers); 288 } 289 g_proxy_options->nameservers = nameservers; 290 291 pxdns_create_resolver_sockaddrs(&g_pxdns, nameservers); 292 } 293 294 295 /** 296 * Use this list of nameservers to resolve guest requests. 297 * 298 * Runs on lwIP thread, so no new queries or retramsmits compete with 299 * it for the use of the existing list of resolvers (to be replaced). 300 */ 301 static void 302 pxdns_create_resolver_sockaddrs(struct pxdns *pxdns, const char **nameservers) 303 { 304 /* 305 * XXX: TODO: Windows supports getaddrinfo(), including execution 306 * on older version of Windows where runtime tricks hide the gory 307 * compatibility details. 308 * 309 * http://msdn.microsoft.com/en-us/library/windows/desktop/ms738520%28v=vs.85%29.aspx 310 */ 311 #ifndef RT_OS_WINDOWS 312 struct addrinfo hints; 313 #endif 314 union sockaddr_inet *resolvers; 315 size_t nnames, nresolvers; 316 const char **p; 317 int status; 318 319 resolvers = NULL; 320 nresolvers = 0; 321 322 if (nameservers == NULL) { 323 goto update_resolvers; 324 } 325 326 nnames = 0; 327 for (p = nameservers; *p != NULL; ++p) { 328 ++nnames; 329 } 330 331 if (nnames == 0) { 332 goto update_resolvers; 333 } 334 335 resolvers = (union sockaddr_inet *)calloc(sizeof(resolvers[0]), nnames); 336 if (resolvers == NULL) { 337 nresolvers = 0; 338 goto update_resolvers; 339 } 340 341 #ifndef RT_OS_WINDOWS 342 memset(&hints, 0, sizeof(hints)); 343 hints.ai_family = AF_UNSPEC; 344 hints.ai_socktype = SOCK_DGRAM; 345 hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV; 346 347 for (p = nameservers; *p != NULL; ++p) { 348 const char *name = *p; 349 struct addrinfo *ai; 350 status = getaddrinfo(name, /* "domain" */ "53", &hints, &ai); 351 if (status != 0) { 352 /* XXX: log failed resolution */ 353 continue; 354 } 355 356 if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) { 357 /* XXX: log unsupported address family */ 358 freeaddrinfo(ai); 359 continue; 360 } 361 362 if (ai->ai_addrlen > sizeof(resolvers[nresolvers])) { 363 /* XXX: log */ 364 freeaddrinfo(ai); 365 continue; 366 } 367 368 if (ai->ai_family == AF_INET6 && pxdns->sock6 == INVALID_SOCKET) { 369 /* no IPv6 support on the host, can't use this resolver */ 370 freeaddrinfo(ai); 371 continue; 372 } 373 374 memcpy(&resolvers[nresolvers], ai->ai_addr, ai->ai_addrlen); 375 freeaddrinfo(ai); 376 ++nresolvers; 377 } 378 #endif /* RT_OS_WINDOWS */ 379 380 if (nresolvers == 0) { 381 if (resolvers != NULL) { 382 free(resolvers); 383 } 384 resolvers = NULL; 385 } 386 387 update_resolvers: 388 ++pxdns->generation; 389 if (pxdns->resolvers != NULL) { 390 free(pxdns->resolvers); 391 } 392 pxdns->resolvers = resolvers; 393 pxdns->nresolvers = nresolvers; 243 394 } 244 395 … … 447 598 int sent; 448 599 600 if (pxdns->nresolvers == 0) { 601 /* nothing we can do */ 602 pbuf_free(p); 603 return; 604 } 605 449 606 req = calloc(1, sizeof(struct request) - 1 + p->tot_len); 450 607 if (req == NULL) { 608 pbuf_free(p); 451 609 return; 452 610 } … … 466 624 memcpy(req->data, &req->id, sizeof(u16_t)); 467 625 468 /* XXX */ 469 req->rexmit_count = 1; 470 626 /* resolver to forward to */ 627 req->generation = pxdns->generation; 628 req->residx = 0; 629 630 /* prepare for relaying the reply back to guest */ 471 631 req->msg_reply.type = TCPIP_MSG_CALLBACK_STATIC; 472 632 req->msg_reply.sem = NULL; … … 480 640 481 641 sent = pxdns_forward_outbound(pxdns, req); 482 while(!sent) {642 if (!sent) { 483 643 sent = pxdns_rexmit(pxdns, req); 484 644 } … … 490 650 491 651 652 /** 653 * Forward request to the req::residx resolver in the pxdns::resolvers 654 * array of upstream resolvers. 655 * 656 * Returns 1 on success, 0 on failure. 657 */ 492 658 static int 493 659 pxdns_forward_outbound(struct pxdns *pxdns, struct request *req) 494 660 { 661 union sockaddr_inet *resolver; 495 662 ssize_t nsent; 496 663 497 DPRINTF2(("%s: req %p\n", __func__, (void *)req)); 498 499 nsent = sendto(pxdns->sock, req->data, req->size, 0, 500 (struct sockaddr *)&pxdns->resolver_sin, 501 pxdns->resolver_sinlen); 664 DPRINTF2(("%s: req %p: sending to resolver #%lu\n", 665 __func__, (void *)req, (unsigned long)req->residx)); 666 667 LWIP_ASSERT1(req->generation == pxdns->generation); 668 LWIP_ASSERT1(req->residx < pxdns->nresolvers); 669 resolver = &pxdns->resolvers[req->residx]; 670 671 if (resolver->sa.sa_family == AF_INET) { 672 nsent = sendto(pxdns->sock4, req->data, req->size, 0, 673 &resolver->sa, sizeof(resolver->sin)); 674 675 } 676 else if (resolver->sa.sa_family == AF_INET6) { 677 if (pxdns->sock6 != INVALID_SOCKET) { 678 nsent = sendto(pxdns->sock6, req->data, req->size, 0, 679 &resolver->sa, sizeof(resolver->sin6)); 680 } 681 else { 682 /* shouldn't happen, we should have weeded out IPv6 resolvers */ 683 return 0; 684 } 685 } 686 else { 687 /* shouldn't happen, we should have weeded out unsupported families */ 688 return 0; 689 } 502 690 503 691 if ((size_t)nsent == req->size) { … … 506 694 507 695 if (nsent < 0) { 508 perror("dnsproxy");509 } 510 else if ((size_t)nsent != req->size){511 DPRINTF (("%s: sent only %lu of %lu\n",512 __func__, (unsigned long)nsent, (unsigned long)req->size));696 DPRINTF2(("%s: send: errno %d\n", __func__, errno)); 697 } 698 else { 699 DPRINTF2(("%s: sent only %lu of %lu\n", 700 __func__, (unsigned long)nsent, (unsigned long)req->size)); 513 701 } 514 702 return 0; /* not sent, caller will retry as necessary */ … … 516 704 517 705 706 /** 707 * Forward request to the next resolver in the pxdns::resolvers array 708 * of upstream resolvers if there are any left. 709 */ 518 710 static int 519 711 pxdns_rexmit(struct pxdns *pxdns, struct request *req) 520 712 { 521 DPRINTF2(("%s: req %p: rexmit count %lu\n", 522 __func__, (void *)req, (unsigned long)req->rexmit_count)); 523 524 /* XXX: TODO: use the next resolver instead */ 525 if (req->rexmit_count == 0) { 713 int sent; 714 715 if (/* __predict_false */ req->generation != pxdns->generation) { 716 DPRINTF2(("%s: req %p: generation %lu != pxdns generation %lu\n", 717 __func__, (void *)req, 718 (unsigned long)req->generation, 719 (unsigned long)pxdns->generation)); 526 720 return 0; 527 721 } 528 --req->rexmit_count; 529 530 return pxdns_forward_outbound(pxdns, req); 722 723 LWIP_ASSERT1(req->residx < pxdns->nresolvers); 724 do { 725 if (++req->residx == pxdns->nresolvers) { 726 return 0; 727 } 728 729 sent = pxdns_forward_outbound(pxdns, req); 730 } while (!sent); 731 732 return 1; 531 733 } 532 734 … … 542 744 543 745 pxdns = (struct pxdns *)handler->data; 544 LWIP_ASSERT1(handler == &pxdns->pmhdl); 545 LWIP_ASSERT1(fd = pxdns->sock); 546 LWIP_UNUSED_ARG(fd); 746 LWIP_ASSERT1(handler == &pxdns->pmhdl4 || handler == &pxdns->pmhdl6); 747 LWIP_ASSERT1(fd == (handler == &pxdns->pmhdl4 ? pxdns->sock4 : pxdns->sock6)); 547 748 548 749 if (revents & ~(POLLIN|POLLERR)) { … … 556 757 int status; 557 758 558 status = getsockopt( pxdns->sock, SOL_SOCKET,759 status = getsockopt(fd, SOL_SOCKET, 559 760 SO_ERROR, &sockerr, &optlen); 560 761 if (status < 0) { 561 762 DPRINTF(("%s: sock %d: SO_ERROR failed with errno %d\n", 562 __func__, pxdns->sock, errno));763 __func__, fd, errno)); 563 764 } 564 765 else { 565 766 DPRINTF(("%s: sock %d: errno %d\n", 566 __func__, pxdns->sock, sockerr));767 __func__, fd, sockerr)); 567 768 } 568 769 } … … 573 774 574 775 575 nread = recv( pxdns->sock, pollmgr_udpbuf, sizeof(pollmgr_udpbuf), 0);776 nread = recv(fd, pollmgr_udpbuf, sizeof(pollmgr_udpbuf), 0); 576 777 if (nread < 0) { 577 778 perror(__func__); … … 585 786 return POLLIN; 586 787 } 788 789 /* XXX: shall we proxy back RCODE=Refused responses? */ 587 790 588 791 memcpy(&id, pollmgr_udpbuf, sizeof(id)); … … 594 797 } 595 798 596 DPRINTF2(("%s: reply for req=%p: client id %d ->id %d\n",597 __func__, (void *)req, req-> client_id, req->id));799 DPRINTF2(("%s: reply for req=%p: id %d -> client id %d\n", 800 __func__, (void *)req, req->id, req->client_id)); 598 801 599 802 req->reply = pbuf_alloc(PBUF_RAW, nread, PBUF_RAM); … … 629 832 ipX_2_ip(&req->client_addr), req->client_port); 630 833 if (error != ERR_OK) { 631 DPRINTF(("%s: udp_sendto err % d\n",834 DPRINTF(("%s: udp_sendto err %s\n", 632 835 __func__, proxy_lwip_strerr(error))); 633 836 }
Note:
See TracChangeset
for help on using the changeset viewer.