Changeset 45324 in vbox
- Timestamp:
- Apr 4, 2013 5:11:47 AM (12 years ago)
- svn:sync-xref-src-repo-rev:
- 84732
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/slirp/dnsproxy/dnsproxy.c
r45261 r45324 129 129 /* be paranoid */ 130 130 AssertPtrReturnVoid(arg); 131 131 132 de = TAILQ_PREV(req->dns_server, dns_list_head, de_list); 132 /* here we should check if we reached the end of the DNS server list */133 133 134 if (de == NULL) 134 135 { … … 140 141 else 141 142 { 142 /* Note: so will be deleted after we create new one (so1)143 * to make attempt on the next server.144 */145 143 struct ip *ip; 146 144 struct udphdr *udp; 147 145 int iphlen; 148 struct socket *so1 = socreate();149 146 struct mbuf *m = NULL; 150 147 char *data; 151 152 if (so1 == NULL) 153 { 154 LogRel(("NAT: can't create DNS socket\n")); 155 goto socket_clean_up; 156 } 157 158 if(udp_attach(pData, so1) == -1) 159 { 160 LogRel(("NAT: can't attach udp socket\n")); 161 sofree(pData, so1); 162 goto socket_clean_up; 163 } 164 148 165 149 m = slirpDnsMbufAlloc(pData); 166 150 if (m == NULL) 167 151 { 168 152 LogRel(("NAT: Can't allocate mbuf\n")); 169 udp_detach(pData, so1);170 153 goto socket_clean_up; 171 154 } … … 187 170 udp->uh_dport = ntohs(53); 188 171 udp->uh_sport = so->so_lport; 172 189 173 memcpy(data, req->byte, req->nbyte); /* coping initial req */ 190 174 191 so1->so_laddr = so->so_laddr; 192 so1->so_lport = so->so_lport; 193 so1->so_faddr = so->so_faddr; 194 so1->so_fport = so->so_fport; 195 175 /* req points to so->so_timeout_arg */ 196 176 req->dns_server = de; 197 so1->so_timeout_arg = req; 198 so1->so_timeout = timeout; 199 200 dnsproxy_query(pData, so1, m, iphlen); 177 178 /* expiration will be bumped in dnsproxy_query */ 179 180 dnsproxy_query(pData, so, m, iphlen); 181 /* should we free so->so_m ? */ 182 return; 201 183 } 202 184 … … 263 245 return; 264 246 } 265 #else266 ip = mtod(m, struct ip *);267 udp = (struct udphdr *)(m->m_data + iphlen);268 269 fromaddr.sin_addr.s_addr = ip->ip_src.s_addr;270 fromaddr.sin_port = udp->uh_sport;271 fromaddr.sin_family = AF_INET;272 273 iphlen += sizeof (struct udphdr);274 byte = m->m_len - iphlen; /* size of IP header + udp header size */275 /* the validness of ip and udp header has been already checked so we shouldn't care if */276 buf = m->m_data + iphlen;277 #endif278 247 279 248 /* check for minimum dns packet length */ … … 284 253 } 285 254 286 #ifndef VBOX287 255 /* allocate new request */ 288 256 if ((req = calloc(1, sizeof(struct request))) == NULL) { … … 295 263 memcpy(&req->client, &fromaddr, sizeof(struct sockaddr_in)); 296 264 memcpy(&req->clientid, &buf[0], 2); 297 #else 298 /* allocate new request */ 299 req = so->so_timeout_arg; /* in slirp we might re-send the query*/ 300 if (req == NULL) 265 266 /* where is this query coming from? */ 267 if (is_internal(pData, fromaddr.sin_addr)) { 268 req->recursion = RD(buf); 269 DPRINTF(("Internal query RD=%d\n", req->recursion)); 270 } else { 271 /* no recursion for foreigners */ 272 req->recursion = 0; 273 DPRINTF(("External query RD=%d\n", RD(buf))); 274 } 275 276 /* insert it into the hash table */ 277 hash_add_request(pData, req); 278 279 /* overwrite the original query id */ 280 memcpy(&buf[0], &req->id, 2); 281 282 if (req->recursion) { 283 284 /* recursive queries timeout in 90s */ 285 event_set(&req->timeout, -1, 0, timeout, req); 286 tv.tv_sec=recursive_timeout; tv.tv_usec=0; 287 event_add(&req->timeout, &tv); 288 289 /* send it to our recursive server */ 290 if ((byte = sendto(sock_answer, buf, (unsigned int)byte, 0, 291 (struct sockaddr *)&recursive_addr, 292 sizeof(struct sockaddr_in))) == -1) { 293 LogRel(("sendto failed: %s\n", strerror(errno))); 294 ++dropped_queries; 295 return; 296 } 297 298 ++recursive_queries; 299 300 } else { 301 302 /* authoritative queries timeout in 10s */ 303 event_set(&req->timeout, -1, 0, timeout, req); 304 tv.tv_sec=authoritative_timeout; tv.tv_usec=0; 305 event_add(&req->timeout, &tv); 306 307 /* send it to our authoritative server */ 308 if ((byte = sendto(sock_answer, buf, (unsigned int)byte, 0, 309 (struct sockaddr *)&authoritative_addr, 310 sizeof(struct sockaddr_in))) == -1) { 311 LogRel(("sendto failed: %s\n", strerror(errno))); 312 ++dropped_queries; 313 return; 314 } 315 ++authoritative_queries; 316 } 317 318 #else /* VBOX */ 319 AssertPtr(pData); 320 321 /* m->m_data points to IP header */ 322 #if 0 323 /* XXX: for some reason it make gdb ill, 324 * it good to have this assert here with assumption above. 325 */ 326 M_ASSERTPKTHDR(m); 327 #endif 328 329 ip = mtod(m, struct ip *); 330 udp = (struct udphdr *)(m->m_data + iphlen); 331 332 fromaddr.sin_addr.s_addr = ip->ip_src.s_addr; 333 fromaddr.sin_port = udp->uh_sport; 334 fromaddr.sin_family = AF_INET; 335 336 /* iphlen equals to lenght of ip header */ 337 Assert(iphlen == sizeof(struct ip)); 338 iphlen += sizeof (struct udphdr); 339 340 byte = m->m_len - iphlen; 341 buf = m->m_data + iphlen; 342 343 /* check for minimum dns packet length */ 344 if (byte < 12) { 345 LogRel(("query too short from %RTnaipv4\n", fromaddr.sin_addr)); 346 ++dropped_queries; 347 return; 348 } 349 350 351 req = so->so_timeout_arg; 352 353 if (!req) 301 354 { 302 if ((req = RTMemAllocZ(sizeof(struct request) + byte)) == NULL) { 355 356 Assert(!so->so_timeout_arg); 357 358 if ((req = RTMemAllocZ(sizeof(struct request) + byte)) == NULL) 359 { 303 360 LogRel(("calloc failed\n")); 304 361 ++dropped_queries; 305 362 return; 306 363 } 307 } 308 309 /* fill the request structure */ 310 if (so->so_timeout_arg == NULL) 311 { 364 312 365 req->id = QUERYID; 313 366 memcpy(&req->client, &fromaddr, sizeof(struct sockaddr_in)); … … 319 372 RTMemFree(req); 320 373 if (fail_counter == 0) 321 374 LogRel(("NAT/dnsproxy: Empty DNS entry (suppressed 100 times)\n")); 322 375 else 323 376 fail_counter = (fail_counter == 100 ? 0 : fail_counter + 1); 324 377 return; 325 378 … … 333 386 else 334 387 { 335 retransmit = 1; 336 } 337 #endif 338 339 #ifndef VBOX 340 /* where is this query coming from? */ 341 if (is_internal(pData, fromaddr.sin_addr)) { 342 req->recursion = RD(buf); 343 DPRINTF(("Internal query RD=%d\n", req->recursion)); 344 } else { 345 /* no recursion for foreigners */ 346 req->recursion = 0; 347 DPRINTF(("External query RD=%d\n", RD(buf))); 348 } 349 350 /* insert it into the hash table */ 351 hash_add_request(pData, req); 352 #else 388 retransmit = 1; 389 } 390 353 391 req->recursion = 0; 392 354 393 DPRINTF(("External query RD=%d\n", RD(buf))); 394 355 395 if (retransmit == 0) 356 396 hash_add_request(pData, req); 357 #endif 397 358 398 359 399 /* overwrite the original query id */ 360 400 memcpy(&buf[0], &req->id, 2); 361 401 362 #ifndef VBOX 363 if (req->recursion) { 364 365 /* recursive queries timeout in 90s */ 366 event_set(&req->timeout, -1, 0, timeout, req); 367 tv.tv_sec=recursive_timeout; tv.tv_usec=0; 368 event_add(&req->timeout, &tv); 369 370 /* send it to our recursive server */ 371 if ((byte = sendto(sock_answer, buf, (unsigned int)byte, 0, 372 (struct sockaddr *)&recursive_addr, 373 sizeof(struct sockaddr_in))) == -1) { 374 LogRel(("sendto failed: %s\n", strerror(errno))); 375 ++dropped_queries; 376 return; 377 } 378 379 ++recursive_queries; 380 381 } else { 382 383 /* authoritative queries timeout in 10s */ 384 event_set(&req->timeout, -1, 0, timeout, req); 385 tv.tv_sec=authoritative_timeout; tv.tv_usec=0; 386 event_add(&req->timeout, &tv); 387 388 /* send it to our authoritative server */ 389 if ((byte = sendto(sock_answer, buf, (unsigned int)byte, 0, 390 (struct sockaddr *)&authoritative_addr, 391 sizeof(struct sockaddr_in))) == -1) { 392 LogRel(("sendto failed: %s\n", strerror(errno))); 393 ++dropped_queries; 394 return; 395 } 396 397 #else 398 so->so_expire = curtime + recursive_timeout * 1000; /* let's slirp to care about expiration */ 399 memset(&addr, 0, sizeof(struct sockaddr_in)); 400 addr.sin_family = AF_INET; 401 addr.sin_addr.s_addr = req->dns_server->de_addr.s_addr; 402 addr.sin_port = htons(53); 403 so->so_expire = curtime + recursive_timeout * 1000; /* let's slirp to care about expiration */ 404 /* send it to our authoritative server */ 405 Log2(("NAT: request will be sent to %RTnaipv4 on %R[natsock]\n", addr.sin_addr, so)); 406 if ((byte = sendto(so->s, buf, (unsigned int)byte, 0, 407 (struct sockaddr *)&addr, 408 sizeof(struct sockaddr_in))) == -1) { 409 LogRel(("sendto failed: %s\n", strerror(errno))); 410 ++dropped_queries; 411 return; 412 } 413 so->so_state = SS_ISFCONNECTED; /* now it's selected */ 414 Log2(("NAT: request was sent to %RTnaipv4 on %R[natsock]\n", addr.sin_addr, so)); 415 #endif 416 ++authoritative_queries; 417 #ifndef VBOX 418 } 419 #endif 402 /* let's slirp to care about expiration */ 403 so->so_expire = curtime + recursive_timeout * 1000; 404 405 memset(&addr, 0, sizeof(struct sockaddr_in)); 406 addr.sin_family = AF_INET; 407 addr.sin_addr.s_addr = req->dns_server->de_addr.s_addr; 408 addr.sin_port = htons(53); 409 410 /* send it to our authoritative server */ 411 Log2(("NAT: request will be sent to %RTnaipv4 on %R[natsock]\n", addr.sin_addr, so)); 412 413 byte = sendto(so->s, buf, (unsigned int)byte, 0, 414 (struct sockaddr *)&addr, 415 sizeof(struct sockaddr_in)); 416 if (byte == -1) 417 { 418 /* XXX: is it really enough? */ 419 LogRel(("sendto failed: %s\n", strerror(errno))); 420 ++dropped_queries; 421 return; 422 } 423 424 so->so_state = SS_ISFCONNECTED; /* now it's selected */ 425 Log2(("NAT: request was sent to %RTnaipv4 on %R[natsock]\n", addr.sin_addr, so)); 426 427 ++authoritative_queries; 428 429 # if 0 430 /* XXX: this stuff for _debugging_ only, 431 * first enforce guest to send next request 432 * and second for faster getting timeout callback 433 * other option is adding couple entries in resolv.conf with 434 * invalid nameservers. 435 * 436 * For testing purposes could be used 437 * namebench -S -q 10000 -m random or -m chunk 438 */ 439 /* RTThreadSleep(3000); */ 440 /* curtime += 300; */ 441 # endif 442 #endif /* VBOX */ 420 443 } 421 444 … … 451 474 return; 452 475 } 453 #else454 char *buf;455 int byte;456 struct request *query = NULL;457 byte = m->m_len;458 buf = mtod(m, char *);459 #endif460 476 461 477 /* check for minimum dns packet length */ … … 467 483 468 484 /* find corresponding query */ 469 #ifdef VBOX470 if ((query = hash_find_request(pData, *((unsigned short *)buf))) == NULL) {471 ++late_answers;472 /* Probably, this request wasn't serviced by473 * dnsproxy so we won't care about it here*/474 so->so_expire = curtime + SO_EXPIREFAST;475 Log2(("NAT: query wasn't found\n"));476 return;477 }478 so->so_timeout = NULL;479 so->so_timeout_arg = NULL;480 #else481 485 if ((query = hash_find_request(pData, *((unsigned short *)&buf))) == NULL) { 482 486 ++late_answers; … … 484 488 } 485 489 event_del(&query->timeout); 486 #endif 490 487 491 hash_remove_request(pData, query); 488 492 … … 490 494 memcpy(&buf[0], &query->clientid, 2); 491 495 492 #ifndef VBOX493 /* Slirp: will send mbuf to guest by itself */494 /* send answer back to querying host */495 496 if (sendto(sock_query, buf, (unsigned int)byte, 0, 496 497 (struct sockaddr *)&query->client, … … 498 499 LogRel(("sendto failed: %s\n", strerror(errno))); 499 500 ++dropped_answers; 500 } else 501 } 502 else 501 503 ++answered_queries; 502 504 503 505 free(query); 504 #else 506 #else /* VBOX */ 507 508 char *buf = NULL; 509 int byte = 0; 510 struct request *query = NULL; 511 512 AssertPtr(pData); 513 514 /* XXX: mbuf->data points to ??? */ 515 byte = m->m_len; 516 buf = mtod(m, char *); 517 518 /* check for minimum dns packet length */ 519 if (byte < 12) { 520 LogRel(("answer too short\n")); 521 ++dropped_answers; 522 return; 523 } 524 525 query = hash_find_request(pData, *((unsigned short *)buf)); 526 527 /* find corresponding query */ 528 if (query == NULL) 529 { 530 /* XXX: if we haven't found anything for this request ... 531 * What we are expecting later? 532 */ 533 ++late_answers; 534 so->so_expire = curtime + SO_EXPIREFAST; 535 Log2(("NAT: query wasn't found\n")); 536 return; 537 } 538 539 so->so_timeout = NULL; 540 so->so_timeout_arg = NULL; 541 542 hash_remove_request(pData, query); 543 544 /* restore original query id */ 545 memcpy(&buf[0], &query->clientid, 2); 546 505 547 ++answered_queries; 506 548 507 549 RTMemFree(query); 508 #endif 550 #endif /* VBOX */ 509 551 } 510 552 553 554 #ifdef VBOX 555 int 556 dnsproxy_init(PNATState pData) 557 { 558 /* globals initialization */ 559 authoritative_port = 53; 560 authoritative_timeout = 10; 561 recursive_port = 53; 562 recursive_timeout = 2; 563 stats_timeout = 3600; 564 dns_port = 53; 565 return 0; 566 } 567 #else /* !VBOX */ 511 568 /* main -- dnsproxy main function 512 569 */ 513 #ifndef VBOX514 570 int 515 571 main(int argc, char *argv[]) … … 671 727 672 728 } 673 #else 674 int 675 dnsproxy_init(PNATState pData) 676 { 677 /* globals initialization */ 678 authoritative_port = 53; 679 authoritative_timeout = 10; 680 recursive_port = 53; 681 recursive_timeout = 2; 682 stats_timeout = 3600; 683 dns_port = 53; 684 return 0; 685 } 686 #endif 729 #endif
Note:
See TracChangeset
for help on using the changeset viewer.