VirtualBox

Changeset 22020 in vbox for trunk/src


Ignore:
Timestamp:
Aug 6, 2009 10:37:24 AM (15 years ago)
Author:
vboxsync
Message:

NAT: 1st stage of delayed port forwarding

Location:
trunk/src/VBox/Devices/Network
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Network/DrvNAT.cpp

    r21659 r22020  
    691691static int drvNATConstructRedir(unsigned iInstance, PDRVNAT pThis, PCFGMNODE pCfgHandle, RTIPV4ADDR Network)
    692692{
     693     RTMAC Mac;
     694     memset(&Mac, 0, sizeof(RTMAC)); /*can't get MAC here */
    693695    /*
    694696     * Enumerate redirections.
     
    741743        struct in_addr BindIP;
    742744        GETIP_DEF(rc, pThis, pNode, BindIP, INADDR_ANY);
    743         if (slirp_redir(pThis->pNATState, fUDP, BindIP, iHostPort, GuestIP, iGuestPort) < 0)
     745        if (slirp_redir(pThis->pNATState, fUDP, BindIP, iHostPort, GuestIP, iGuestPort, Mac.au8) < 0)
    744746            return PDMDrvHlpVMSetError(pThis->pDrvIns, VERR_NAT_REDIR_SETUP, RT_SRC_POS,
    745747                                       N_("NAT#%d: configuration error: failed to set up "
  • trunk/src/VBox/Devices/Network/slirp/ip_output.c

    r22013 r22020  
    5050{
    5151    int i;
    52    /* @todo (r - vasily) to quick ramp up on routing rails
     52   /* @todo (vasily) to quick ramp up on routing rails
    5353    * we use information from DHCP server leasings, this
    5454    * code couldn't detect any changes in network topology
  • trunk/src/VBox/Devices/Network/slirp/libslirp.h

    r21004 r22020  
    5858int slirp_redir(PNATState pData, int is_udp, struct in_addr host_addr,
    5959                int host_port, struct in_addr guest_addr,
    60                 int guest_port);
     60                int guest_port, const uint8_t *);
    6161int slirp_add_exec(PNATState pData, int do_pty, const char *args, int addr_low_byte,
    6262                   int guest_port);
  • trunk/src/VBox/Devices/Network/slirp/slirp.c

    r22014 r22020  
    189189#define LOG_NAT_SOCK(so, proto, winevent, r_fdset, w_fdset, x_fdset) DO_LOG_NAT_SOCK((so), proto, (winevent), r_fdset, w_fdset, x_fdset)
    190190
     191static void acivate_port_forwarding(PNATState, struct ethhdr *);
     192static in_addr_t find_guest_ip(PNATState, uint8_t *);
     193
    191194static const uint8_t special_ethaddr[6] =
    192195{
     
    14441447    m->m_len = pkt_len ;
    14451448    memcpy(m->m_data, pkt, pkt_len);
     1449   
     1450    if (pData->port_forwarding_activated == 0)
     1451        acivate_port_forwarding(pData, mtod(m, struct ethhdr *));
    14461452
    14471453    proto = ntohs(*(uint16_t *)(pkt + 12));
     
    15101516#endif
    15111517    eh->h_proto = htons(eth_proto);
    1512 #if 0
    1513     slirp_output(pData->pvUser, m, mtod(m, uint8_t *), m->m_len);
    1514 #else
    15151518    memcpy(buf, mtod(m, uint8_t *), m->m_len);
    15161519    slirp_output(pData->pvUser, NULL, buf, m->m_len);
     
    15181521    STAM_PROFILE_STOP(&pData->StatIF_encap, a);
    15191522    m_free(pData, m);
    1520 #endif
    1521 }
    1522 
     1523}
     1524
     1525/**
     1526 * Still we're using dhcp server leasing to map ether to IP
     1527 * @todo  see rt_lookup_in_cache
     1528 */
     1529static in_addr_t find_guest_ip(PNATState pData, uint8_t *eth_addr)
     1530{
     1531    int i;
     1532    if (memcmp(eth_addr, zerro_ethaddr, ETH_ALEN) == 0
     1533        || memcmp(eth_addr, broadcast_ethaddr, ETH_ALEN) == 0)
     1534        goto done;
     1535    for (i = 0; i < NB_ADDR; i++)
     1536    {
     1537        if (   bootp_clients[i].allocated
     1538            && memcmp(bootp_clients[i].macaddr, eth_addr, ETH_ALEN) == 0)
     1539            return bootp_clients[i].addr.s_addr;
     1540    }
     1541done:
     1542    return INADDR_ANY;
     1543}
     1544
     1545/**
     1546 * We need check if we've activated port forwarding
     1547 * for specific machine ... that of course relates to
     1548 * service mode
     1549 * @todo finish this for service case
     1550 */
     1551static void acivate_port_forwarding(PNATState pData, struct ethhdr *ethdr)
     1552{
     1553    struct port_forward_rule *rule = NULL;
     1554   
     1555    pData->port_forwarding_activated = 1;
     1556    /* check mac here */
     1557    LIST_FOREACH(rule, &pData->port_forward_rule_head, list)
     1558    {
     1559        struct socket *so;
     1560        struct alias_link *link;
     1561        struct libalias *lib;
     1562        int flags;
     1563        struct sockaddr sa;
     1564        struct sockaddr_in *psin;
     1565        socklen_t socketlen;
     1566        struct in_addr alias;
     1567        int rc;
     1568        in_addr_t guest_addr; /* need to understand if we already give address to guest */
     1569
     1570        if (rule->activated)
     1571            continue; /*already activated */
     1572#ifdef VBOX_WITH_NAT_SERVICE
     1573        if (memcmp(rule->mac_address, ethdr->h_source, ETH_ALEN) != 0)
     1574            continue; /*not right mac, @todo: it'd be better do the list port forwarding per mac */
     1575        guest_addr = find_guest_ip(pData, ethdr->h_source);
     1576#else
     1577        if (memcmp(client_ethaddr, ethdr->h_source, ETH_ALEN) != 0)
     1578            continue;
     1579        guest_addr = find_guest_ip(pData, ethdr->h_source);
     1580        Assert(rule->guest_addr.s_addr == guest_addr);
     1581#endif
     1582        if (guest_addr == INADDR_ANY)
     1583        {
     1584            /* the address wasn't granted */
     1585            pData->port_forwarding_activated = 0;
     1586            return;
     1587        }
     1588
     1589        LogRel(("NAT: set redirect %s hp:%d gp:%d\n", (rule->proto == IPPROTO_UDP?"UDP":"TCP"),
     1590            rule->host_port, rule->guest_port));
     1591        if (rule->proto == IPPROTO_UDP)
     1592        {
     1593            so = udp_listen(pData, rule->bind_ip.s_addr, htons(rule->host_port), guest_addr,
     1594                            htons(rule->guest_port), 0);
     1595        }
     1596        else
     1597        {
     1598            so = solisten(pData, rule->bind_ip.s_addr, htons(rule->host_port), guest_addr,
     1599                          htons(rule->guest_port), 0);
     1600        }
     1601        if (so == NULL)
     1602        {   
     1603            LogRel(("NAT: failed redirect %s hp:%d gp:%d\n", (rule->proto == IPPROTO_UDP?"UDP":"TCP"),
     1604                rule->host_port, rule->guest_port));
     1605            goto remove_port_forwarding;
     1606        }
     1607
     1608        psin = (struct sockaddr_in *)&sa;
     1609        psin->sin_family = AF_INET;
     1610        psin->sin_port = 0;
     1611        psin->sin_addr.s_addr = INADDR_ANY;
     1612        socketlen = sizeof(struct sockaddr);
     1613
     1614        rc = getsockname(so->s, &sa, &socketlen);
     1615        if (rc < 0 || sa.sa_family != AF_INET)
     1616        {
     1617            LogRel(("NAT: failed redirect %s hp:%d gp:%d\n", (rule->proto == IPPROTO_UDP?"UDP":"TCP"),
     1618                rule->host_port, rule->guest_port));
     1619            goto remove_port_forwarding;
     1620        }
     1621
     1622        psin = (struct sockaddr_in *)&sa;
     1623
     1624        lib = LibAliasInit(pData, NULL);
     1625        flags = LibAliasSetMode(lib, 0, 0);
     1626        flags |= PKT_ALIAS_LOG; /* set logging */
     1627        flags |= PKT_ALIAS_REVERSE; /* set logging */
     1628        flags = LibAliasSetMode(lib, flags, ~0);
     1629
     1630        alias.s_addr =  htonl(ntohl(guest_addr) | CTL_ALIAS);
     1631        link = LibAliasRedirectPort(lib, psin->sin_addr, htons(rule->host_port),
     1632            alias, htons(rule->guest_port),
     1633            special_addr,  -1, /* not very clear for now*/
     1634            rule->proto);
     1635        if (link == NULL)
     1636        {
     1637            LogRel(("NAT: failed redirect %s hp:%d gp:%d\n", (rule->proto == IPPROTO_UDP?"UDP":"TCP"),
     1638                rule->host_port, rule->guest_port));
     1639            goto remove_port_forwarding;
     1640        }
     1641        so->so_la = lib;
     1642        rule->activated = 1;
     1643        continue;
     1644    remove_port_forwarding:
     1645        LIST_REMOVE(rule, list);
     1646        RTMemFree(rule);
     1647    }
     1648}
     1649
     1650/**
     1651 * Changes in 3.1 instead of opening new socket do the following:
     1652 * gain more information:
     1653 *  1. bind IP
     1654 *  2. host port
     1655 *  3. guest port
     1656 *  4. proto
     1657 *  5. guest MAC address
     1658 * the guest's MAC address is rather important for service, but we easily
     1659 * could get it from VM configuration in DrvNAT or Service, the idea is activating
     1660 * corresponding port-forwarding
     1661 */
    15231662int slirp_redir(PNATState pData, int is_udp, struct in_addr host_addr, int host_port,
    1524                 struct in_addr guest_addr, int guest_port)
    1525 {
    1526     struct socket *so;
    1527     struct alias_link *link;
    1528     struct libalias *lib;
    1529     int flags;
    1530     struct sockaddr sa;
    1531     struct sockaddr_in *psin;
    1532     socklen_t socketlen;
    1533     struct in_addr alias;
    1534     int rc;
    1535 
    1536     Log2(("NAT: set redirect %s hp:%d gp:%d\n", (is_udp?"UDP":"TCP"), host_port, guest_port));
    1537     if (is_udp)
    1538     {
    1539         so = udp_listen(pData, host_addr.s_addr, htons(host_port), guest_addr.s_addr,
    1540                         htons(guest_port), 0);
    1541     }
    1542     else
    1543     {
    1544         so = solisten(pData, host_addr.s_addr, htons(host_port), guest_addr.s_addr,
    1545                       htons(guest_port), 0);
    1546     }
    1547     if (so == NULL)
    1548     {   
    1549         return -1;
    1550     }
    1551 
    1552     psin = (struct sockaddr_in *)&sa;
    1553     psin->sin_family = AF_INET;
    1554     psin->sin_port = 0;
    1555     psin->sin_addr.s_addr = INADDR_ANY;
    1556     socketlen = sizeof(struct sockaddr);
    1557 
    1558     rc = getsockname(so->s, &sa, &socketlen);
    1559     if (rc < 0 || sa.sa_family != AF_INET)
    1560     {
    1561         Log(("NAT: can't get socket's name\n"));
     1663                struct in_addr guest_addr, int guest_port, const uint8_t *ethaddr)
     1664{
     1665    struct port_forward_rule *rule = NULL;
     1666    Assert(memcmp(ethaddr, zerro_ethaddr, ETH_ALEN) == 0);
     1667    rule = RTMemAllocZ(sizeof(struct port_forward_rule));
     1668    if (rule == NULL)
    15621669        return 1;
    1563     }
    1564 
    1565     psin = (struct sockaddr_in *)&sa;
    1566 
    1567 #if 1
    1568     lib = LibAliasInit(pData, NULL);
    1569     flags = LibAliasSetMode(lib, 0, 0);
    1570     flags |= PKT_ALIAS_LOG; /* set logging */
    1571     flags |= PKT_ALIAS_REVERSE; /* set logging */
    1572     flags = LibAliasSetMode(lib, flags, ~0);
    1573 #else
    1574     lib = LIST_FIRST(&instancehead);
    1575 #endif
    1576 
    1577     alias.s_addr =  htonl(ntohl(guest_addr.s_addr) | CTL_ALIAS);
    1578     link = LibAliasRedirectPort(lib, psin->sin_addr, htons(host_port),
    1579         alias, htons(guest_port),
    1580         special_addr,  -1, /* not very clear for now*/
    1581         (is_udp ? IPPROTO_UDP : IPPROTO_TCP));
    1582     if (link == NULL)
    1583     {
    1584         Log(("NAT: can't create redirect\n"));
    1585         return 1;
    1586     }
    1587     so->so_la = lib;
    1588 
     1670    rule->proto = (is_udp ? IPPROTO_UDP : IPPROTO_TCP);
     1671    rule->host_port = host_port;
     1672    rule->guest_port = guest_port;
     1673#ifndef VBOX_WITH_NAT_SERVICE
     1674    rule->guest_addr.s_addr = guest_addr.s_addr;
     1675#endif
     1676    rule->bind_ip.s_addr = host_addr.s_addr;
     1677    memcmp(rule->mac_address, ethaddr, ETH_ALEN);
     1678    /* @todo add mac address */
     1679    LIST_INSERT_HEAD(&pData->port_forward_rule_head, rule, list);
    15891680    return 0;
    15901681}
     
    15991690void slirp_set_ethaddr(PNATState pData, const uint8_t *ethaddr)
    16001691{
    1601 #ifndef VBOX_WITHOUT_SLIRP_CLIENT_ETHER
     1692#ifndef VBOX_WITH_NAT_SERVICE
    16021693    memcpy(client_ethaddr, ethaddr, ETH_ALEN);
    16031694#endif
  • trunk/src/VBox/Devices/Network/slirp/slirp_state.h

    r22013 r22020  
    7171};
    7272TAILQ_HEAD(dns_list_head, dns_entry);
     73
     74struct port_forward_rule
     75{
     76    uint16_t proto;
     77    uint16_t host_port;
     78    uint16_t guest_port;
     79#ifndef VBOX_WITH_NAT_SERVICE
     80    struct in_addr guest_addr;
     81#endif
     82    struct in_addr bind_ip;
     83    uint8_t mac_address[6]; /*need ETH_ALEN here */
     84    int activated;
     85    LIST_ENTRY(port_forward_rule) list;
     86};
     87LIST_HEAD(port_forward_rule_list, port_forward_rule);
    7388
    7489/** Main state/configuration structure for slirp NAT. */
     
    130145    uint8_t client_ethaddr[6];
    131146#else
     147# ifndef VBOX_WITH_NAT_SERVICE
     148    uint8_t client_ethaddr[6];
     149# endif
    132150    const uint8_t *slirp_ethaddr;
    133151#endif
     
    229247    struct libalias *proxy_alias;
    230248    LIST_HEAD(handler_chain, proto_handler) handler_chain;
     249    struct port_forward_rule_list port_forward_rule_head;
     250    int port_forwarding_activated;
    231251
    232252#define PROFILE_COUNTER(name, dsc)     STAMPROFILE Stat ## name
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette