VirtualBox

Changeset 59167 in vbox


Ignore:
Timestamp:
Dec 17, 2015 2:42:48 AM (9 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
104757
Message:

NAT: Teach host resolver reverse lookups (in-addr.arpa PTR records).
Not yet hooked up with HostResolverMappings extradata.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Network/slirp/hostres.c

    r59159 r59167  
    108108static int verify_header(PNATState pData, struct mbuf **pMBuf);
    109109static struct mbuf *respond(PNATState pData, struct mbuf *m, struct response *res);
    110 struct mbuf *resolve(PNATState pData, struct mbuf *m, struct response *res, size_t qname, uint16_t qtype);
     110struct mbuf *resolve(PNATState pData, struct mbuf *m, struct response *res,
     111                     uint16_t qtype, size_t qname);
     112struct mbuf *resolve_reverse(PNATState pData, struct mbuf *m, struct response *res,
     113                             uint16_t qtype, size_t qname, struct in_addr addr);
    111114struct mbuf *refuse(PNATState pData, struct mbuf *m, unsigned int rcode);
    112115static ssize_t append_a(struct response *res, const char *name, struct in_addr addr);
    113116static ssize_t append_cname(struct response *res, const char *name, const char *cname);
     117static ssize_t append_ptr(struct response *res, const char *inaddrname, const char *name);
     118static ssize_t append_name_rr(struct response *res, const char *question, int type, const char *answer);
    114119static ssize_t append_rrhdr(struct response *res, const char *name, uint16_t type, uint32_t ttl);
    115120static ssize_t append_name(struct response *res, const char *name);
     
    120125static ssize_t check_space(struct response *res, size_t size);
    121126
     127static int get_in_addr_arpa(struct in_addr *paddr, struct label *root);
     128static int labelstrcmp(struct label *l, const char *s);
    122129static void strnlabels(char *namebuf, size_t nbuflen, const uint8_t *msg, size_t off);
    123130
     
    282289    size_t qname;
    283290    uint16_t qtype, qclass;
     291    struct in_addr in_addr_arpa;
    284292    struct label *l;
    285293
     
    400408    if (   qtype != Type_A
    401409        && qtype != Type_CNAME
     410        && qtype != Type_PTR
    402411        && qtype != Type_ANY)
    403412    {
     
    406415    }
    407416
    408     return resolve(pData, m, res, qname, qtype);
     417    /*
     418     * Check for IN-ADDR.ARPA.  Use the fact that res->labels at this
     419     * point contains only the qname, so we have easy top-down access
     420     * to its components.
     421     */
     422    if (get_in_addr_arpa(&in_addr_arpa, res->labels))
     423        return resolve_reverse(pData, m, res, qtype, qname, in_addr_arpa);
     424    else
     425        return resolve(pData, m, res, qtype, qname);
    409426}
    410427
     
    412429struct mbuf *
    413430resolve(PNATState pData, struct mbuf *m, struct response *res,
    414         size_t qname, uint16_t qtype)
     431        uint16_t qtype, size_t qname)
    415432{
    416433    struct dnsmsg_header *pHdr;
     
    429446    strnlabels(name, sizeof(name), res->buf, qname);
    430447    LogDbg(("NAT: hostres: qname=\"%s\"\n", name));
     448
     449    if (qtype != Type_A && qtype != Type_CNAME && qtype != Type_ANY)
     450    {
     451        goto out; /* NB: RCode_NoError without an answer, not RCode_NXDomain */
     452    }
     453
    431454
    432455    h = gethostbyname(name);
     
    551574
    552575
     576struct mbuf *
     577resolve_reverse(PNATState pData, struct mbuf *m, struct response *res,
     578                uint16_t qtype, size_t qname, struct in_addr in_addr_arpa)
     579{
     580    struct dnsmsg_header *pHdr;
     581    struct hostent *h;
     582    size_t oend;
     583    size_t nanswers;
     584    ssize_t nbytes;
     585    int i;
     586
     587    pHdr = (struct dnsmsg_header *)res->buf;
     588    nanswers = 0;
     589    oend = res->end;
     590
     591    LogDbg(("NAT: hostres: %RTnaipv4\n", in_addr_arpa.s_addr));
     592
     593    if (qtype != Type_PTR && qtype != Type_ANY)
     594    {
     595        /* can't answer CNAME to PTR queries using gethostby* */
     596        goto out; /* NB: RCode_NoError without an answer, not RCode_NXDomain */
     597    }
     598
     599    /* XXX: TODO: apply HostResolverMappings */
     600    h = gethostbyaddr(&in_addr_arpa, sizeof(struct in_addr), AF_INET);
     601    if (h == NULL)
     602    {
     603        /* LogErr: h_errno */
     604        return refuse(pData, m, RCode_NXDomain);
     605    }
     606
     607    if (h->h_name != NULL)
     608    {
     609        char name[DNS_MAX_NAME_LEN+1];
     610        strnlabels(name, sizeof(name), res->buf, qname);
     611
     612        LogDbg(("NAT: hostres: %s PTR %s\n", name, h->h_name));
     613        nbytes = append_ptr(res, name, h->h_name);
     614        if (nbytes > 0)
     615        {
     616            ++nanswers;
     617        }
     618        else
     619        {
     620            LogErr(("NAT: hostres: failed to add %s PTR %s\n",
     621                    name, h->h_name));
     622            if (nbytes < 0)
     623                return refuse(pData, m, RCode_ServFail);
     624            else
     625            {
     626                pHdr->tc = 1;
     627                goto out;
     628            }
     629        }
     630    }
     631
     632  out:
     633    if (nanswers > 0)
     634    {
     635        int ok = m_append(pData, m, res->end - oend, (caddr_t)&res->buf[oend]);
     636        if (!ok)
     637        {
     638            /* XXX: this may fail part way: restore old lenght, clear TC? */
     639            return refuse(pData, m, RCode_ServFail);
     640        }
     641        pHdr->ancount = RT_H2N_U16(nanswers);
     642    }
     643    memcpy(mtod(m, char *), res->buf, sizeof(struct dnsmsg_header));
     644    return m;
     645}
     646
     647
    553648
    554649#define APPEND_PROLOGUE()                       \
     
    601696append_cname(struct response *res, const char *name, const char *cname)
    602697{
     698    return append_name_rr(res, name, Type_CNAME, cname);
     699}
     700
     701
     702/*
     703 * PTR RR - rfc1035#section-3.3.12
     704 */
     705static ssize_t
     706append_ptr(struct response *res, const char *inaddrname, const char *name)
     707{
     708    return append_name_rr(res, inaddrname, Type_PTR, name);
     709}
     710
     711
     712static ssize_t
     713append_name_rr(struct response *res, const char *question,
     714               int type, const char *answer)
     715{
    603716    size_t rdlpos;
    604717    uint16_t rdlength;
     
    606719    APPEND_PROLOGUE();
    607720
    608     CHECKED( append_rrhdr(res, name, Type_CNAME, 3600) );
     721    CHECKED( append_rrhdr(res, question, type, 3600) );
    609722
    610723    rdlpos = res->end;
    611724    CHECKED( append_u16(res, 0) ); /* RDLENGTH placeholder */
    612725
    613     CHECKED( append_name(res, cname) );
     726    CHECKED( append_name(res, answer) );
    614727
    615728    rdlength = RT_H2N_U16(nbytes);
     
    851964
    852965    return size;
     966}
     967
     968
     969static int
     970get_in_addr_arpa(struct in_addr *paddr, struct label *root)
     971{
     972    RTNETADDRIPV4 addr;
     973    struct label *l;
     974    int i;
     975
     976    l = root;
     977    if (l == NULL || labelstrcmp(l, "arpa") != 0)
     978        return 0;
     979
     980    l = l->children;
     981    if (l == NULL || labelstrcmp(l, "in-addr") != 0)
     982        return 0;
     983
     984    for (i = 0; i < 4; ++i)
     985    {
     986        char buf[4];
     987        size_t llen;
     988        int rc;
     989        uint8_t octet;
     990
     991        l = l->children;
     992        if (l == NULL)
     993            return 0;
     994
     995        llen = l->buf[l->off];
     996        Assert((llen & DNS_LABEL_PTR) == 0);
     997
     998        /* valid octet values are at most 3 digits */
     999        if (llen > 3)
     1000            return 0;
     1001
     1002        /* copy to avoid dealing with trailing bytes */
     1003        memcpy(buf, &l->buf[l->off + 1], llen);
     1004        buf[llen] = '\0';
     1005
     1006        rc = RTStrToUInt8Full(buf, 10, &octet);
     1007        if (rc != VINF_SUCCESS)
     1008            return 0;
     1009
     1010        addr.au8[i] = octet;
     1011    }
     1012
     1013    if (l->children != NULL)
     1014        return 0;               /* too many components */
     1015
     1016    if (paddr != NULL)
     1017        paddr->s_addr = addr.u;
     1018
     1019    return 1;
     1020}
     1021
     1022
     1023/*
     1024 * Compare label with string.
     1025 */
     1026static int
     1027labelstrcmp(struct label *l, const char *s)
     1028{
     1029    size_t llen;
     1030
     1031    llen = l->buf[l->off];
     1032    Assert((llen & DNS_LABEL_PTR) == 0);
     1033
     1034    return RTStrNICmp((char *)&l->buf[l->off + 1], s, llen);
    8531035}
    8541036
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