Changeset 57784 in vbox for trunk/src/VBox/Devices/Network/slirp
- Timestamp:
- Sep 16, 2015 3:36:31 PM (9 years ago)
- Location:
- trunk/src/VBox/Devices/Network/slirp
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/slirp/bootp.c
r57181 r57784 363 363 364 364 dhcp_create_msg(pData, bp, m, DHCPACK); 365 slirp_update_guest_addr_guess(pData, bc->addr.s_addr, "DHCP ACK"); 365 366 offReply = dhcp_do_ack_offer(pData, m, bc, fDhcpRequest); 366 367 return offReply; -
trunk/src/VBox/Devices/Network/slirp/libslirp.h
r56292 r57784 63 63 64 64 void slirp_input(PNATState pData, struct mbuf *m, size_t cbBuf); 65 void slirp_set_ethaddr_and_activate_port_forwarding(PNATState pData, const uint8_t *ethaddr, uint32_t GuestIP);66 65 67 66 /* you must provide the following functions: */ … … 73 72 void slirp_post_sent(PNATState pData, void *pvArg); 74 73 74 void slirp_update_guest_addr_guess(PNATState pData, uint32_t guess, const char *msg); 75 75 76 int slirp_add_redirect(PNATState pData, int is_udp, struct in_addr host_addr, 76 77 int host_port, struct in_addr guest_addr, 77 int guest_port , const uint8_t *);78 int guest_port); 78 79 int slirp_remove_redirect(PNATState pData, int is_udp, struct in_addr host_addr, 79 80 int host_port, struct in_addr guest_addr, -
trunk/src/VBox/Devices/Network/slirp/slirp.c
r57739 r57784 261 261 DO_LOG_NAT_SOCK((so), proto, (winevent), r_fdset, w_fdset, x_fdset) 262 262 263 static void activate_port_forwarding(PNATState, const uint8_t *pEther);264 265 263 static const uint8_t special_ethaddr[6] = 266 264 { … … 477 475 if (!pData->fUseHostResolverPermanent) 478 476 slirpInitializeDnsSettings(pData); 479 480 if (LIST_EMPTY(&pData->arp_cache))481 return;482 483 LIST_FOREACH(ac, &pData->arp_cache, list)484 {485 activate_port_forwarding(pData, ac->ether);486 }487 477 } 488 478 … … 498 488 499 489 slirpReleaseDnsSettings(pData); 500 501 /*502 * Clear the active state of port-forwarding rules to force503 * re-setup on restoration of communications.504 */505 LIST_FOREACH(rule, &pData->port_forward_rule_head, list)506 {507 rule->activated = 0;508 }509 pData->cRedirectionsActive = 0;510 490 511 491 link_up = 0; … … 1319 1299 if_encap(pData, ETH_P_ARP, pMbufResponse, ETH_ENCAP_URG); 1320 1300 } 1301 1321 1302 /** 1322 1303 * @note This function will free m! … … 1341 1322 || CTL_CHECK(ip4TargetAddress, CTL_ALIAS) 1342 1323 || CTL_CHECK(ip4TargetAddress, CTL_TFTP)) 1324 { 1325 slirp_update_guest_addr_guess(pData, *(uint32_t *)pARPHeader->ar_sip, "arp request"); 1343 1326 arp_output(pData, pEtherHeader->h_source, pARPHeader, ip4TargetAddress); 1327 break; 1328 } 1344 1329 1345 1330 /* Gratuitous ARP */ 1346 if ( *(uint32_t *)pARPHeader->ar_sip == *(uint32_t *)pARPHeader->ar_tip 1347 && memcmp(pARPHeader->ar_tha, broadcast_ethaddr, ETH_ALEN) == 0 1331 if ( *(uint32_t *)pARPHeader->ar_sip == *(uint32_t *)pARPHeader->ar_tip 1332 && ( memcmp(pARPHeader->ar_tha, zerro_ethaddr, ETH_ALEN) == 0 1333 || memcmp(pARPHeader->ar_tha, broadcast_ethaddr, ETH_ALEN) == 0) 1348 1334 && memcmp(pEtherHeader->h_dest, broadcast_ethaddr, ETH_ALEN) == 0) 1349 1335 { 1350 /* We've received an announce about address assignment, 1351 * let's do an ARP cache update 1352 */ 1353 static bool fGratuitousArpReported; 1354 if (!fGratuitousArpReported) 1355 { 1356 LogRel(("NAT: Gratuitous ARP [IP:%RTnaipv4, ether:%RTmac]\n", 1357 *(uint32_t *)pARPHeader->ar_sip, pARPHeader->ar_sha)); 1358 fGratuitousArpReported = true; 1359 } 1336 LogRel2(("NAT: gratuitous ARP from %RTnaipv4 at %RTmac\n", 1337 *(uint32_t *)pARPHeader->ar_sip, pARPHeader->ar_sha)); 1338 slirp_update_guest_addr_guess(pData, *(uint32_t *)pARPHeader->ar_sip, "gratuitous arp"); 1360 1339 slirp_arp_cache_update_or_add(pData, *(uint32_t *)pARPHeader->ar_sip, &pARPHeader->ar_sha[0]); 1361 1340 } … … 1428 1407 break; 1429 1408 } 1430 1431 if (pData->cRedirectionsActive != pData->cRedirectionsStored)1432 activate_port_forwarding(pData, au8Ether);1433 1409 } 1434 1410 … … 1498 1474 } 1499 1475 1500 /** 1501 * Still we're using dhcp server leasing to map ether to IP 1502 * @todo see rt_lookup_in_cache 1503 */ 1504 static uint32_t find_guest_ip(PNATState pData, const uint8_t *eth_addr) 1505 { 1506 uint32_t ip = INADDR_ANY; 1507 int rc; 1508 1509 if (eth_addr == NULL) 1510 return INADDR_ANY; 1511 1512 if ( memcmp(eth_addr, zerro_ethaddr, ETH_ALEN) == 0 1513 || memcmp(eth_addr, broadcast_ethaddr, ETH_ALEN) == 0) 1514 return INADDR_ANY; 1515 1516 rc = slirp_arp_lookup_ip_by_ether(pData, eth_addr, &ip); 1517 if (RT_SUCCESS(rc)) 1518 return ip; 1519 1520 bootp_cache_lookup_ip_by_ether(pData, eth_addr, &ip); 1521 /* ignore return code, ip will be set to INADDR_ANY on error */ 1522 return ip; 1523 } 1524 1525 /** 1526 * We need check if we've activated port forwarding 1527 * for specific machine ... that of course relates to 1528 * service mode 1529 * @todo finish this for service case 1530 */ 1531 static void activate_port_forwarding(PNATState pData, const uint8_t *h_source) 1532 { 1533 struct port_forward_rule *rule, *tmp; 1534 const uint8_t *pu8EthSource = h_source; 1535 1536 /* check mac here */ 1537 LIST_FOREACH_SAFE(rule, &pData->port_forward_rule_head, list, tmp) 1538 { 1539 struct socket *so; 1540 struct sockaddr sa; 1541 struct sockaddr_in *psin; 1542 socklen_t socketlen; 1543 int rc; 1544 uint32_t guest_addr; /* need to understand if we already give address to guest */ 1545 1546 if (rule->activated) 1547 continue; 1548 1549 guest_addr = find_guest_ip(pData, pu8EthSource); 1550 if (guest_addr == INADDR_ANY) 1551 { 1552 /* the address wasn't granted */ 1553 return; 1554 } 1555 1556 if ( rule->guest_addr.s_addr != guest_addr 1557 && rule->guest_addr.s_addr != INADDR_ANY) 1558 continue; 1559 if (rule->guest_addr.s_addr == INADDR_ANY) 1560 rule->guest_addr.s_addr = guest_addr; 1561 1562 LogRel(("NAT: set redirect %s host %RTnaipv4:%d => guest %RTnaipv4:%d\n", 1476 1477 void 1478 slirp_update_guest_addr_guess(PNATState pData, uint32_t guess, const char *msg) 1479 { 1480 Assert(msg != NULL); 1481 1482 if (pData->guest_addr_guess.s_addr == guess) 1483 { 1484 LogRel2(("NAT: guest address guess %RTnaipv4 re-confirmed by %s\n", 1485 pData->guest_addr_guess.s_addr, msg)); 1486 return; 1487 } 1488 1489 if (pData->guest_addr_guess.s_addr == INADDR_ANY) 1490 { 1491 pData->guest_addr_guess.s_addr = guess; 1492 LogRel(("NAT: guest address guess set to %RTnaipv4 by %s\n", 1493 pData->guest_addr_guess.s_addr, msg)); 1494 return; 1495 } 1496 else 1497 { 1498 LogRel(("NAT: guest address guess changed from %RTnaipv4 to %RTnaipv4 by %s\n", 1499 pData->guest_addr_guess.s_addr, guess, msg)); 1500 pData->guest_addr_guess.s_addr = guess; 1501 return; 1502 } 1503 } 1504 1505 1506 static struct port_forward_rule * 1507 slirp_find_redirect(PNATState pData, 1508 int is_udp, 1509 struct in_addr host_addr, int host_port, 1510 struct in_addr guest_addr, int guest_port) 1511 { 1512 struct port_forward_rule *rule; 1513 uint16_t proto = (is_udp ? IPPROTO_UDP : IPPROTO_TCP); 1514 1515 LIST_FOREACH(rule, &pData->port_forward_rule_head, list) 1516 { 1517 if ( rule->proto == proto 1518 && rule->host_port == host_port 1519 && rule->bind_ip.s_addr == host_addr.s_addr 1520 && rule->guest_port == guest_port 1521 && rule->guest_addr.s_addr == guest_addr.s_addr) 1522 { 1523 return rule; 1524 } 1525 } 1526 1527 return NULL; 1528 } 1529 1530 1531 int slirp_add_redirect(PNATState pData, int is_udp, struct in_addr host_addr, int host_port, 1532 struct in_addr guest_addr, int guest_port) 1533 { 1534 struct port_forward_rule *rule; 1535 1536 rule = slirp_find_redirect(pData, is_udp, host_addr, host_port, guest_addr, guest_port); 1537 if (rule != NULL) /* rule has been already registered */ 1538 { 1539 /* XXX: this shouldn't happen */ 1540 return 0; 1541 } 1542 1543 rule = RTMemAllocZ(sizeof(struct port_forward_rule)); 1544 if (rule == NULL) 1545 return 1; 1546 1547 rule->proto = (is_udp ? IPPROTO_UDP : IPPROTO_TCP); 1548 rule->bind_ip.s_addr = host_addr.s_addr; 1549 rule->host_port = host_port; 1550 rule->guest_addr.s_addr = guest_addr.s_addr; 1551 rule->guest_port = guest_port; 1552 1553 if (rule->proto == IPPROTO_UDP) 1554 rule->so = udp_listen(pData, rule->bind_ip.s_addr, RT_H2N_U16(rule->host_port), 1555 rule->guest_addr.s_addr, RT_H2N_U16(rule->guest_port), 0); 1556 else 1557 rule->so = solisten(pData, rule->bind_ip.s_addr, RT_H2N_U16(rule->host_port), 1558 rule->guest_addr.s_addr, RT_H2N_U16(rule->guest_port), 0); 1559 1560 if (rule->so == NULL) 1561 { 1562 LogRel(("NAT: failed to redirect %s %RTnaipv4:%d -> %RTnaipv4:%d\n", 1563 1563 rule->proto == IPPROTO_UDP ? "UDP" : "TCP", 1564 1564 rule->bind_ip.s_addr, rule->host_port, 1565 1565 guest_addr, rule->guest_port)); 1566 1567 if (rule->proto == IPPROTO_UDP)1568 so = udp_listen(pData, rule->bind_ip.s_addr, RT_H2N_U16(rule->host_port), guest_addr,1569 RT_H2N_U16(rule->guest_port), 0);1570 else1571 so = solisten(pData, rule->bind_ip.s_addr, RT_H2N_U16(rule->host_port), guest_addr,1572 RT_H2N_U16(rule->guest_port), 0);1573 1574 if (so == NULL)1575 goto remove_port_forwarding;1576 1577 psin = (struct sockaddr_in *)&sa;1578 psin->sin_family = AF_INET;1579 psin->sin_port = 0;1580 psin->sin_addr.s_addr = INADDR_ANY;1581 socketlen = sizeof(struct sockaddr);1582 1583 rc = getsockname(so->s, &sa, &socketlen);1584 if (rc < 0 || sa.sa_family != AF_INET)1585 goto remove_port_forwarding;1586 1587 rule->activated = 1;1588 rule->so = so;1589 pData->cRedirectionsActive++;1590 continue;1591 1592 remove_port_forwarding:1593 LogRel(("NAT: failed to redirect %s %RTnaipv4:%d => %RTnaipv4:%d\n",1594 (rule->proto == IPPROTO_UDP ? "UDP" : "TCP"),1595 rule->bind_ip.s_addr, rule->host_port,1596 guest_addr, rule->guest_port));1597 LIST_REMOVE(rule, list);1598 pData->cRedirectionsStored--;1599 1566 RTMemFree(rule); 1600 }1601 }1602 1603 /**1604 * Changes in 3.1 instead of opening new socket do the following:1605 * gain more information:1606 * 1. bind IP1607 * 2. host port1608 * 3. guest port1609 * 4. proto1610 * 5. guest MAC address1611 * the guest's MAC address is rather important for service, but we easily1612 * could get it from VM configuration in DrvNAT or Service, the idea is activating1613 * corresponding port-forwarding1614 */1615 int slirp_add_redirect(PNATState pData, int is_udp, struct in_addr host_addr, int host_port,1616 struct in_addr guest_addr, int guest_port, const uint8_t *ethaddr)1617 {1618 struct port_forward_rule *rule = NULL;1619 LIST_FOREACH(rule, &pData->port_forward_rule_head, list)1620 {1621 if ( rule->proto == (is_udp ? IPPROTO_UDP : IPPROTO_TCP)1622 && rule->host_port == host_port1623 && rule->bind_ip.s_addr == host_addr.s_addr1624 && rule->guest_port == guest_port1625 && rule->guest_addr.s_addr == guest_addr.s_addr1626 )1627 return 0; /* rule has been already registered */1628 }1629 1630 rule = RTMemAllocZ(sizeof(struct port_forward_rule));1631 if (rule == NULL)1632 1567 return 1; 1633 1634 rule->proto = (is_udp ? IPPROTO_UDP : IPPROTO_TCP); 1635 rule->host_port = host_port; 1636 rule->guest_port = guest_port; 1637 rule->guest_addr.s_addr = guest_addr.s_addr; 1638 rule->bind_ip.s_addr = host_addr.s_addr; 1568 } 1569 1570 LogRel(("NAT: set redirect %s %RTnaipv4:%d -> %RTnaipv4:%d\n", 1571 rule->proto == IPPROTO_UDP ? "UDP" : "TCP", 1572 rule->bind_ip.s_addr, rule->host_port, 1573 guest_addr, rule->guest_port)); 1574 1639 1575 LIST_INSERT_HEAD(&pData->port_forward_rule_head, rule, list); 1640 pData->cRedirectionsStored++;1641 /* activate port-forwarding if guest has already got assigned IP */1642 if ( ethaddr1643 && memcmp(ethaddr, zerro_ethaddr, ETH_ALEN))1644 activate_port_forwarding(pData, ethaddr);1645 1576 return 0; 1646 1577 } 1578 1647 1579 1648 1580 int slirp_remove_redirect(PNATState pData, int is_udp, struct in_addr host_addr, int host_port, 1649 1581 struct in_addr guest_addr, int guest_port) 1650 1582 { 1651 struct port_forward_rule *rule = NULL; 1652 LIST_FOREACH(rule, &pData->port_forward_rule_head, list) 1653 { 1654 if ( rule->proto == (is_udp ? IPPROTO_UDP : IPPROTO_TCP) 1655 && rule->host_port == host_port 1656 && rule->guest_port == guest_port 1657 && rule->bind_ip.s_addr == host_addr.s_addr 1658 && rule->guest_addr.s_addr == guest_addr.s_addr 1659 && rule->activated) 1660 { 1661 LogRel(("NAT: remove redirect %s host %RTnaipv4:%d => guest %RTnaipv4:%d\n", 1662 rule->proto == IPPROTO_UDP ? "UDP" : "TCP", 1663 rule->bind_ip.s_addr, rule->host_port, 1664 guest_addr.s_addr, rule->guest_port)); 1665 1666 if (is_udp) 1667 udp_detach(pData, rule->so); 1668 else 1669 tcp_close(pData, sototcpcb(rule->so)); 1670 LIST_REMOVE(rule, list); 1671 RTMemFree(rule); 1672 pData->cRedirectionsStored--; 1673 break; 1674 } 1675 1676 } 1583 struct port_forward_rule *rule; 1584 1585 rule = slirp_find_redirect(pData, is_udp, host_addr, host_port, guest_addr, guest_port); 1586 if (rule == NULL) 1587 { 1588 LogRel(("NAT: unable to find redirect %s %RTnaipv4:%d -> %RTnaipv4:%d\n", 1589 rule->proto == IPPROTO_UDP ? "UDP" : "TCP", 1590 rule->bind_ip.s_addr, rule->host_port, 1591 guest_addr.s_addr, rule->guest_port)); 1592 return 0; 1593 } 1594 1595 LogRel(("NAT: remove redirect %s %RTnaipv4:%d -> %RTnaipv4:%d\n", 1596 rule->proto == IPPROTO_UDP ? "UDP" : "TCP", 1597 rule->bind_ip.s_addr, rule->host_port, 1598 guest_addr.s_addr, rule->guest_port)); 1599 1600 if (rule->so != NULL) 1601 { 1602 if (is_udp) 1603 udp_detach(pData, rule->so); 1604 else 1605 tcp_close(pData, sototcpcb(rule->so)); 1606 } 1607 1608 LIST_REMOVE(rule, list); 1609 RTMemFree(rule); 1677 1610 return 0; 1678 1611 } 1679 1612 1680 void slirp_set_ethaddr_and_activate_port_forwarding(PNATState pData, const uint8_t *ethaddr, uint32_t GuestIP)1681 {1682 memcpy(client_ethaddr, ethaddr, ETH_ALEN);1683 if (GuestIP != INADDR_ANY)1684 {1685 slirp_arp_cache_update_or_add(pData, GuestIP, ethaddr);1686 activate_port_forwarding(pData, ethaddr);1687 }1688 }1689 1613 1690 1614 #if defined(RT_OS_WINDOWS) -
trunk/src/VBox/Devices/Network/slirp/slirp_state.h
r57739 r57784 139 139 struct in_addr alias_addr; 140 140 struct in_addr special_addr; 141 struct in_addr guest_addr_guess; 141 142 142 143 int tcp_rcvspace; … … 298 299 RTCRITSECTRW CsRwHandlerChain; 299 300 struct port_forward_rule_list port_forward_rule_head; 300 int cRedirectionsActive;301 int cRedirectionsStored;302 301 struct arp_cache_head arp_cache; 303 302 /* libalis modules' handlers*/ -
trunk/src/VBox/Devices/Network/slirp/tcp_subr.c
r56292 r57784 477 477 LogFlowFunc(("ENTER: inso = %R[natsock]\n", inso)); 478 478 479 if ( inso->so_laddr.s_addr == INADDR_ANY /* delayed port-forwarding? */ 480 && pData->guest_addr_guess.s_addr == INADDR_ANY) 481 { 482 LogRel2(("NAT: port-forward: guest address unknown for %R[natsock]\n", inso)); 483 closesocket(accept(inso->s, NULL, NULL)); 484 if (inso->so_state & SS_FACCEPTONCE) 485 tcp_close(pData, sototcpcb(inso)); 486 return; 487 } 488 479 489 /* 480 490 * If it's an SS_ACCEPTONCE socket, no need to socreate() … … 503 513 } 504 514 515 if (so->so_laddr.s_addr == INADDR_ANY) 516 { 517 LogRel2(("NAT: port-forward: using %RTnaipv4 for %R[natsock]\n", 518 pData->guest_addr_guess.s_addr, inso)); 519 so->so_laddr = pData->guest_addr_guess; 520 } 521 505 522 (void) tcp_mss(pData, sototcpcb(so), 0); 506 523 -
trunk/src/VBox/Devices/Network/slirp/udp.c
r57738 r57784 464 464 so, (long)m, addr->sin_addr.s_addr)); 465 465 466 if (so->so_laddr.s_addr == INADDR_ANY) 467 { 468 if (pData->guest_addr_guess.s_addr != INADDR_ANY) 469 { 470 LogRel2(("NAT: port-forward: using %RTnaipv4 for %R[natsock]\n", 471 pData->guest_addr_guess.s_addr, so)); 472 so->so_laddr = pData->guest_addr_guess; 473 } 474 else 475 { 476 LogRel2(("NAT: port-forward: guest address unknown for %R[natsock]\n", so)); 477 m_freem(pData, m); 478 return 0; 479 } 480 } 481 466 482 saddr = *addr; 467 483 if ((so->so_faddr.s_addr & RT_H2N_U32(pData->netmask)) == pData->special_addr.s_addr)
Note:
See TracChangeset
for help on using the changeset viewer.