Пример #1
0
int VBoxNetDhcp::hostDnsServers(const ComHostPtr& host,
                                const RTNETADDRIPV4& networkid,
                                const AddressToOffsetMapping& mapping,
                                AddressList& servers)
{
    ComBstrArray strs;

    HRESULT hrc = host->COMGETTER(NameServers)(ComSafeArrayAsOutParam(strs));
    if (FAILED(hrc))
        return VERR_NOT_FOUND;

    /*
     * Recent fashion is to run dnsmasq on 127.0.1.1 which we
     * currently can't map.  If that's the only nameserver we've got,
     * we need to use DNS proxy for VMs to reach it.
     */
    bool fUnmappedLoopback = false;

    for (size_t i = 0; i < strs.size(); ++i)
    {
        RTNETADDRIPV4 addr;
        int rc;

        rc = RTNetStrToIPv4Addr(com::Utf8Str(strs[i]).c_str(), &addr);
        if (RT_FAILURE(rc))
            continue;

        if (addr.au8[0] == 127)
        {
            AddressToOffsetMapping::const_iterator remap(mapping.find(addr));

            if (remap != mapping.end())
            {
                int offset = remap->second;
                addr.u = RT_H2N_U32(RT_N2H_U32(networkid.u) + offset);
            }
            else
            {
                fUnmappedLoopback = true;
                continue;
            }
        }

        servers.push_back(addr);
    }

    if (servers.empty() && fUnmappedLoopback)
    {
        RTNETADDRIPV4 proxy;

        proxy.u = networkid.u | RT_H2N_U32_C(1U);
        servers.push_back(proxy);
    }

    return VINF_SUCCESS;
}
Пример #2
0
int VBoxNetDhcp::initNoMain()
{
    CmdParameterIterator it;

    RTNETADDRIPV4 address = getIpv4Address();
    RTNETADDRIPV4 netmask = getIpv4Netmask();
    RTNETADDRIPV4 networkId;
    networkId.u = address.u & netmask.u;

    RTNETADDRIPV4 UpperAddress;
    RTNETADDRIPV4 LowerAddress = networkId;
    UpperAddress.u = RT_H2N_U32(RT_N2H_U32(LowerAddress.u) | RT_N2H_U32(netmask.u));

    for (it = CmdParameterll.begin(); it != CmdParameterll.end(); ++it)
    {
        switch(it->Key)
        {
            case 'l':
                RTNetStrToIPv4Addr(it->strValue.c_str(), &LowerAddress);
                break;

            case 'u':
                RTNetStrToIPv4Addr(it->strValue.c_str(), &UpperAddress);
                break;
            case 'b':
                break;

        }
    }

    ConfigurationManager *confManager = ConfigurationManager::getConfigurationManager();
    AssertPtrReturn(confManager, VERR_INTERNAL_ERROR);
    confManager->addNetwork(unconst(g_RootConfig),
                            networkId,
                            netmask,
                            LowerAddress,
                            UpperAddress);

    return VINF_SUCCESS;
}
bool Lease::fromXML(const xml::ElementNode *node)
{
    com::Utf8Str mac;
    bool valueExists = node->getAttributeValue(tagXMLLeaseAttributeMac.c_str(), mac);
    if (!valueExists) return false;
    int rc = RTNetStrToMacAddr(mac.c_str(), &m->m_mac);
    if (RT_FAILURE(rc)) return false;

    com::Utf8Str network;
    valueExists = node->getAttributeValue(tagXMLLeaseAttributeNetwork.c_str(), network);
    if (!valueExists) return false;
    rc = RTNetStrToIPv4Addr(network.c_str(), &m->m_network);
    if (RT_FAILURE(rc)) return false;

    /* Address */
    const xml::ElementNode *address = node->findChildElement(tagXMLLeaseAddress.c_str());
    if (!address) return false;
    com::Utf8Str addressValue;
    valueExists = address->getAttributeValue(tagXMLAddressAttributeValue.c_str(), addressValue);
    if (!valueExists) return false;
    rc = RTNetStrToIPv4Addr(addressValue.c_str(), &m->m_address);

    /* Time */
    const xml::ElementNode *time = node->findChildElement(tagXMLLeaseTime.c_str());
    if (!time) return false;

    valueExists = time->getAttributeValue(tagXMLTimeAttributeIssued.c_str(),
                                          &m->u64TimestampLeasingStarted);
    if (!valueExists) return false;
    m->fBinding = false;

    valueExists = time->getAttributeValue(tagXMLTimeAttributeExpiration.c_str(),
                                          &m->u32LeaseExpirationPeriod);
    if (!valueExists) return false;

    m->fHasLease = true;
    return true;
}
Пример #4
0
static inline int configGetBoundryAddress(const ComDhcpServerPtr& dhcp, bool fUpperBoundry, RTNETADDRIPV4& boundryAddress)
{
    boundryAddress.u = INADDR_ANY;

    HRESULT hrc;
    com::Bstr strAddress;
    if (fUpperBoundry)
        hrc = dhcp->COMGETTER(UpperIP)(strAddress.asOutParam());
    else
        hrc = dhcp->COMGETTER(LowerIP)(strAddress.asOutParam());
    AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);

    return RTNetStrToIPv4Addr(com::Utf8Str(strAddress).c_str(), &boundryAddress);
}
Пример #5
0
int localMappings(const ComNatPtr& nat, AddressToOffsetMapping& mapping)
{
    mapping.clear();

    ComBstrArray strs;
    size_t cStrs;
    HRESULT hrc = nat->COMGETTER(LocalMappings)(ComSafeArrayAsOutParam(strs));
    if (   SUCCEEDED(hrc)
            && (cStrs = strs.size()))
    {
        for (size_t i = 0; i < cStrs; ++i)
        {
            char szAddr[17];
            RTNETADDRIPV4 ip4addr;
            char *pszTerm;
            uint32_t u32Off;
            com::Utf8Str strLo2Off(strs[i]);
            const char *pszLo2Off = strLo2Off.c_str();

            RT_ZERO(szAddr);

            pszTerm = RTStrStr(pszLo2Off, "=");

            if (   pszTerm
                    && (pszTerm - pszLo2Off) <= INET_ADDRSTRLEN)
            {
                memcpy(szAddr, pszLo2Off, (pszTerm - pszLo2Off));
                int rc = RTNetStrToIPv4Addr(szAddr, &ip4addr);
                if (RT_SUCCESS(rc))
                {
                    u32Off = RTStrToUInt32(pszTerm + 1);
                    if (u32Off != 0)
                        mapping.insert(
                            AddressToOffsetMapping::value_type(ip4addr, u32Off));
                }
            }
        }
    }
    else
        return VERR_NOT_FOUND;

    return VINF_SUCCESS;
}
Пример #6
0
/**
 * @note: const dropped here, because of map<K,V>::operator[] which isn't const, map<K,V>::at() has const
 * variant but it's C++11.
 */
int hostDnsServers(const ComHostPtr& host, const RTNETADDRIPV4& networkid,
                   /*const*/ AddressToOffsetMapping& mapping, AddressList& servers)
{
    servers.clear();

    ComBstrArray strs;
    if (SUCCEEDED(host->COMGETTER(NameServers)(ComSafeArrayAsOutParam(strs))))
    {
        RTNETADDRIPV4 addr;
        int rc;

        for (unsigned int i = 0; i < strs.size(); ++i)
        {
            rc = RTNetStrToIPv4Addr(com::Utf8Str(strs[i]).c_str(), &addr);
            if (RT_SUCCESS(rc))
            {
                if (addr.au8[0] == 127)
                {
                    /* XXX: here we want map<K,V>::at(const K& k) const */
                    if (mapping[addr] != 0)
                    {
                        addr.u = RT_H2N_U32(RT_N2H_U32(networkid.u)
                                            + mapping[addr]);
                    }
                    else
                        continue; /* XXX: Warning here (local mapping wasn't registered) */
                }

                servers.push_back(addr);
            }
        }
    }
    else
        return VERR_NOT_FOUND;

    return VINF_SUCCESS;
}
Пример #7
0
/** 
 * Main thread. Starts also the LWIP thread.
 */
int VBoxNetLwipNAT::init()
{
    LogFlowFuncEnter();

    /* virtualbox initialized in super class */
    int rc = ::VBoxNetBaseService::init();
    AssertRCReturn(rc, rc);

    std::string networkName = getNetworkName();
    rc = findNatNetwork(virtualbox, networkName, m_net);
    AssertRCReturn(rc, rc);

    ComEventTypeArray aNetEvents;
    aNetEvents.push_back(VBoxEventType_OnNATNetworkPortForward);
    aNetEvents.push_back(VBoxEventType_OnNATNetworkSetting);
    rc = createNatListener(m_listener, virtualbox, this, aNetEvents);
    AssertRCReturn(rc, rc);


    // resolver changes are reported on vbox but are retrieved from
    // host so stash a pointer for future lookups
    HRESULT hrc = virtualbox->COMGETTER(Host)(m_host.asOutParam());
    AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);

    ComEventTypeArray aVBoxEvents;
    aVBoxEvents.push_back(VBoxEventType_OnHostNameResolutionConfigurationChange);
    aVBoxEvents.push_back(VBoxEventType_OnNATNetworkStartStop);
    rc = createNatListener(m_vboxListener, virtualbox, this, aVBoxEvents);
    AssertRCReturn(rc, rc);

    BOOL fIPv6Enabled = FALSE;
    hrc = m_net->COMGETTER(IPv6Enabled)(&fIPv6Enabled);
    AssertComRCReturn(hrc, VERR_NOT_FOUND);

    BOOL fIPv6DefaultRoute = FALSE;
    if (fIPv6Enabled)
    {
        hrc = m_net->COMGETTER(AdvertiseDefaultIPv6RouteEnabled)(&fIPv6DefaultRoute);
        AssertComRCReturn(hrc, VERR_NOT_FOUND);
    }

    m_ProxyOptions.ipv6_enabled = fIPv6Enabled;
    m_ProxyOptions.ipv6_defroute = fIPv6DefaultRoute;


    com::Bstr bstrSourceIp4Key = com::BstrFmt("NAT/%s/SourceIp4", networkName.c_str());
    com::Bstr bstrSourceIpX;
    hrc = virtualbox->GetExtraData(bstrSourceIp4Key.raw(), bstrSourceIpX.asOutParam());
    if (SUCCEEDED(hrc))
    {
        RTNETADDRIPV4 addr;
        rc = RTNetStrToIPv4Addr(com::Utf8Str(bstrSourceIpX).c_str(), &addr);
        if (RT_SUCCESS(rc))
        {
            RT_ZERO(m_src4);

            m_src4.sin_addr.s_addr = addr.u;
            m_ProxyOptions.src4 = &m_src4;

            bstrSourceIpX.setNull();
        }
    }

    if (!fDontLoadRulesOnStartup)
    {
        fetchNatPortForwardRules(m_net, false, m_vecPortForwardRule4);
        fetchNatPortForwardRules(m_net, true, m_vecPortForwardRule6);
    } /* if (!fDontLoadRulesOnStartup) */

    AddressToOffsetMapping tmp;
    rc = localMappings(m_net, tmp);
    if (RT_SUCCESS(rc) && tmp.size() != 0)
    {
        unsigned long i = 0;
        for (AddressToOffsetMapping::iterator it = tmp.begin();
             it != tmp.end() && i < RT_ELEMENTS(m_lo2off);
             ++it, ++i)
        {
            ip4_addr_set_u32(&m_lo2off[i].loaddr, it->first.u);
            m_lo2off[i].off = it->second;
        }

        m_loOptDescriptor.lomap = m_lo2off;
        m_loOptDescriptor.num_lomap = i;
        m_ProxyOptions.lomap_desc = &m_loOptDescriptor;
    }

    com::Bstr bstr;
    hrc = virtualbox->COMGETTER(HomeFolder)(bstr.asOutParam());
    AssertComRCReturn(hrc, VERR_NOT_FOUND);
    if (!bstr.isEmpty())
    {
        com::Utf8Str strTftpRoot(com::Utf8StrFmt("%ls%c%s",
                                     bstr.raw(), RTPATH_DELIMITER, "TFTP"));
        char *pszStrTemp;       // avoid const char ** vs char **
        rc = RTStrUtf8ToCurrentCP(&pszStrTemp, strTftpRoot.c_str());
        AssertRC(rc);
        m_ProxyOptions.tftp_root = pszStrTemp;
    }

    m_ProxyOptions.nameservers = getHostNameservers();

    /* end of COM initialization */

    rc = g_pLwipNat->tryGoOnline();
    if (RT_FAILURE(rc))
        return rc;

    /* this starts LWIP thread */
    vboxLwipCoreInitialize(VBoxNetLwipNAT::onLwipTcpIpInit, this);

    LogFlowFuncLeaveRC(rc);
    return rc;
}
Пример #8
0
/* XXX: Having fIPv6 we might emprove adress verification comparing address length 
 * with INET[6]_ADDRLEN
 */
int netPfStrToPf(const char *pcszStrPortForward, int fIPv6, PPORTFORWARDRULE pPfr)
{
    char *pszName;
    int  proto;
    char *pszHostAddr;
    char *pszGuestAddr;
    uint16_t u16HostPort;
    uint16_t u16GuestPort;
    bool fTcpProto = false;

    char *pszRawBegin = NULL; 
    char *pszRaw = NULL;
    int idxRaw = 0;
    int cbToken = 0;
    int cbRaw = 0;
    int rc = VINF_SUCCESS;

    AssertPtrReturn(pcszStrPortForward, VERR_INVALID_PARAMETER);
    AssertPtrReturn(pPfr, VERR_INVALID_PARAMETER);

    memset(pPfr, 0, sizeof(PORTFORWARDRULE));

    pszHostAddr = &pPfr->aszPfrHostAddr[0];
    pszGuestAddr = &pPfr->aszPfrGuestAddr[0];
    pszName = &pPfr->aszPfrName[0];

    cbRaw = strlen(pcszStrPortForward); 

    /* Minimal rule ":tcp:[]:0:[]:0" has got lenght 14 */
    AssertReturn(cbRaw > 14, VERR_INVALID_PARAMETER);
    
    pszRaw = RTStrDup(pcszStrPortForward);

    AssertPtrReturn(pszRaw, VERR_NO_MEMORY);

    pszRawBegin = pszRaw;

    /* name */
    if (pszRaw[idxRaw] == PF_FIELD_SEPARATOR) 
        idxRaw = 1; /* begin of the next segment */
    else
    {
        char *pszEndOfName = RTStrStr(pszRaw + 1, PF_STR_FIELD_SEPARATOR);
        if (!pszEndOfName)
            goto invalid_parameter;

        cbToken = (pszEndOfName) - pszRaw; /* don't take : into account */
        /* XXX it's unacceptable to have only name entry in PF */
        AssertReturn(cbToken < cbRaw, VERR_INVALID_PARAMETER);
        
        if (   cbToken < 0
            || (size_t)cbToken >= PF_NAMELEN)
            goto invalid_parameter;

        RTStrCopy(pszName, 
                  RT_MIN((size_t)cbToken + 1, PF_NAMELEN), 
                  pszRaw);
        pszRaw += cbToken; /* move to separator */
    }
    
    AssertReturn(pszRaw[0] == PF_FIELD_SEPARATOR, VERR_INVALID_PARAMETER);
    /* protocol */

    pszRaw++; /* skip separator */
    idxRaw = 0;
    
    cbRaw--;

    if (     ((    fTcpProto = (RTStrNICmp(pszRaw, "tcp", 3) == 0)
              ||  (RTStrNICmp(pszRaw, "udp", 3) == 0))
          && (pszRaw[3] == PF_FIELD_SEPARATOR)))
    {
        proto = (fTcpProto ? IPPROTO_TCP : IPPROTO_UDP);
        idxRaw = 3;
    }
    else
        goto invalid_parameter;
                    
    pszRaw += idxRaw;
    cbRaw -= idxRaw;
    idxRaw = 0;
                    
    idxRaw = netPfStrAddressPortPairParse(pszRaw, cbRaw, 
                                         pszHostAddr, INET6_ADDRSTRLEN,
                                         true, &u16HostPort);
    if (idxRaw < 0)
        return VERR_INVALID_PARAMETER;

    pszRaw += idxRaw;
    cbRaw -= idxRaw;

    Assert(pszRaw[0] == PF_FIELD_SEPARATOR);

    idxRaw = 0;

    idxRaw = netPfStrAddressPortPairParse(pszRaw, cbRaw, 
                                          pszGuestAddr, 
                                          INET6_ADDRSTRLEN,
                                          false,
                                          &u16GuestPort);

    if (idxRaw < 0)
        goto invalid_parameter;

    /* XXX: fill the rule */
    pPfr->fPfrIPv6 = fIPv6;
    pPfr->iPfrProto = proto;

    
    if (strlen(pszHostAddr))
    {
        if (!fIPv6)
            rc = RTNetStrToIPv4Addr(pszHostAddr, &pPfr->uPfrHostAddr.IPv4);
#if 0 /* No IPv6 yet */
        else
            rc = RTNetStrToIPv6Addr(pszHostAddr, &pPfr->uPfrHostAddr.IPv6);
#endif

        if (RT_FAILURE(rc))
            goto invalid_parameter;
    }
    
    pPfr->u16PfrHostPort = u16HostPort;

    if (strlen(pszGuestAddr))
    {
        if (!fIPv6)
            rc = RTNetStrToIPv4Addr(pszGuestAddr, &pPfr->uPfrGuestAddr.IPv4);       
#if 0
        else
            rc = RTNetStrToIPv6Addr(pszGuestAddr, &pPfr->uPfrGuestAddr.IPv6);
#endif
        if (RT_FAILURE(rc))
            goto invalid_parameter;
    }
    else
        goto invalid_parameter; /* guest address should be defined */
    
    pPfr->u16PfrGuestPort = u16GuestPort;
    
    Log(("name: %s\n"
         "proto: %d\n"
         "host address: %s\n"
         "host port: %d\n"
         "guest address: %s\n"
         "guest port:%d\n",
         pszName, proto,
         pszHostAddr, u16HostPort,
         pszGuestAddr, u16GuestPort));

    RTStrFree(pszRawBegin);
    return VINF_SUCCESS;
    
invalid_parameter:
    RTStrFree(pszRawBegin);
    if (pPfr)
        memset(pPfr, 0, sizeof(PORTFORWARDRULE));
    return VERR_INVALID_PARAMETER;
}
Пример #9
0
/**
 * Converts an stringified IPv4 address into the RTNETADDRIPV4 representation.
 *
 * @returns VINF_SUCCESS on success, VERR_GETOPT_INVALID_ARGUMENT_FORMAT on
 *          failure.
 *
 * @param   pszValue        The value to convert.
 * @param   pAddr           Where to store the result.
 */
static int rtgetoptConvertIPv4Addr(const char *pszValue, PRTNETADDRIPV4 pAddr)
{
    if (RT_FAILURE(RTNetStrToIPv4Addr(pszValue, pAddr)))
        return VERR_GETOPT_INVALID_ARGUMENT_FORMAT;
    return VINF_SUCCESS;
}
Пример #10
0
int VBoxNetDhcp::initWithMain()
{
    /* ok, here we should initiate instance of dhcp server
     * and listener for Dhcp configuration events
     */
    AssertRCReturn(virtualbox.isNull(), VERR_INTERNAL_ERROR);
    std::string networkName = getNetwork();

    int rc = findDhcpServer(virtualbox, networkName, m_DhcpServer);
    AssertRCReturn(rc, rc);

    rc = findNatNetwork(virtualbox, networkName, m_NATNetwork);
    AssertRCReturn(rc, rc);

    BOOL fNeedDhcpServer = isDhcpRequired(m_NATNetwork);
    if (!fNeedDhcpServer)
        return VERR_CANCELLED;

    RTNETADDRIPV4 gateway;
    com::Bstr strGateway;
    HRESULT hrc = m_NATNetwork->COMGETTER(Gateway)(strGateway.asOutParam());
    AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);
    RTNetStrToIPv4Addr(com::Utf8Str(strGateway).c_str(), &gateway);

    ConfigurationManager *confManager = ConfigurationManager::getConfigurationManager();
    AssertPtrReturn(confManager, VERR_INTERNAL_ERROR);
    confManager->addToAddressList(RTNET_DHCP_OPT_ROUTERS, gateway);

    rc = fetchAndUpdateDnsInfo();
    AssertMsgRCReturn(rc, ("Wasn't able to fetch Dns info"), rc);

    ComEventTypeArray aVBoxEvents;
    aVBoxEvents.push_back(VBoxEventType_OnHostNameResolutionConfigurationChange);
    rc = createNatListener(m_vboxListener, virtualbox, this, aVBoxEvents);
    AssertRCReturn(rc, rc);

    RTNETADDRIPV4 LowerAddress;
    rc = configGetBoundryAddress(m_DhcpServer, false, LowerAddress);
    AssertMsgRCReturn(rc, ("can't get lower boundrary adderss'"),rc);

    RTNETADDRIPV4 UpperAddress;
    rc = configGetBoundryAddress(m_DhcpServer, true, UpperAddress);
    AssertMsgRCReturn(rc, ("can't get upper boundrary adderss'"),rc);

    RTNETADDRIPV4 address = getIpv4Address();
    RTNETADDRIPV4 netmask = getIpv4Netmask();
    RTNETADDRIPV4 networkId = networkid(address, netmask);
    std::string name = std::string("default");

    confManager->addNetwork(unconst(g_RootConfig),
                            networkId,
                            netmask,
                            LowerAddress,
                            UpperAddress);

    com::Bstr bstr;
    hrc = virtualbox->COMGETTER(HomeFolder)(bstr.asOutParam());
    com::Utf8StrFmt strXmlLeaseFile("%ls%c%s.leases",
                                    bstr.raw(), RTPATH_DELIMITER, networkName.c_str());
    confManager->loadFromFile(strXmlLeaseFile);

    return VINF_SUCCESS;
}
Пример #11
0
/**
 * nameserverexpr ::= 'nameserver' ip+
 * @note: resolver(5) ip ::= (ipv4|ipv6)(.number)?
 */
static enum RCP_TOKEN rcp_parse_nameserver(struct rcp_parser *parser)
{
    enum RCP_TOKEN tok = rcp_get_token(parser); /* eats 'nameserver' */

    if (  (   tok != tok_ipv4
           && tok != tok_ipv4_port
           && tok != tok_ipv6
           && tok != tok_ipv6_port)
        || tok == EOF)
        return tok_error;

    while (   tok == tok_ipv4
           || tok == tok_ipv4_port
           || tok == tok_ipv6
           || tok == tok_ipv6_port)
    {
        struct rcp_state *st;
        RTNETADDR *address;
        char *str_address;

        Assert(parser->rcpp_state);

        st = parser->rcpp_state;

        /* It's still valid resolv.conf file, just rest of the nameservers should be ignored */
        if (st->rcps_num_nameserver >= RCPS_MAX_NAMESERVERS)
            return rcp_get_token(parser);

        address = &st->rcps_nameserver[st->rcps_num_nameserver];
        str_address = &st->rcps_nameserver_str_buffer[st->rcps_num_nameserver * RCPS_IPVX_SIZE];
#ifdef RT_OS_DARWIN
        if (   tok == tok_ipv4_port
            || (   tok == tok_ipv6_port
                && (st->rcps_flags & RCPSF_IGNORE_IPV6) == 0))
        {
            char *ptr = &parser->rcpp_str_buffer[strlen(parser->rcpp_str_buffer)];
            while (*(--ptr) != '.');
            *ptr = '\0';
            address->uPort = RTStrToUInt16(ptr + 1);

            if (address->uPort == 0) return tok_error;
        }
#endif
        /**
         * if we on Darwin upper code will cut off port if it's.
         */
        if ((st->rcps_flags & RCPSF_NO_STR2IPCONV) != 0)
        {
            if (strlen(parser->rcpp_str_buffer) > RCPS_IPVX_SIZE)
                return tok_error;

            strcpy(str_address, parser->rcpp_str_buffer);

            st->rcps_str_nameserver[st->rcps_num_nameserver] = str_address;

            goto loop_prolog;
        }

        switch (tok)
        {
            case tok_ipv4:
            case tok_ipv4_port:
                {
                    int rc = RTNetStrToIPv4Addr(parser->rcpp_str_buffer, &address->uAddr.IPv4);
                    if (RT_FAILURE(rc)) return tok_error;

                    address->enmType = RTNETADDRTYPE_IPV4;
                }

                break;
            case tok_ipv6:
            case tok_ipv6_port:
                {
                    int rc;

                    if ((st->rcps_flags & RCPSF_IGNORE_IPV6) != 0)
                        return rcp_get_token(parser);

                    rc = inet_pton(AF_INET6, parser->rcpp_str_buffer,
                                       &address->uAddr.IPv6);
                    if (rc == -1)
                        return tok_error;

                    address->enmType = RTNETADDRTYPE_IPV6;
                }

                break;
            default: /* loop condition doesn't let enter enything */
                AssertMsgFailed(("shouldn't ever happen tok:%d, %s", tok,
                                 isprint(tok) ? parser->rcpp_str_buffer : "#"));
                break;
        }

    loop_prolog:
        st->rcps_num_nameserver++;
        tok = rcp_get_token(parser);
    }
    return tok;
}