VirtualBox

Changeset 45324 in vbox


Ignore:
Timestamp:
Apr 4, 2013 5:11:47 AM (12 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
84732
Message:

NAT/dnsproxy: this one big.

  1. reduced fragmentation of code of VBOX/!VBOX blocks + lines between logicall blocks.
  2. next nameserver done on the same socket
File:
1 edited

Legend:

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

    r45261 r45324  
    129129    /* be paranoid */
    130130    AssertPtrReturnVoid(arg);
     131   
    131132    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   
    133134    if (de == NULL)
    134135    {
     
    140141    else
    141142    {
    142         /* Note: so will be deleted after we create new one (so1)
    143          * to make attempt on the next server.
    144          */
    145143        struct ip *ip;
    146144        struct udphdr *udp;
    147145        int iphlen;
    148         struct socket *so1 = socreate();
    149146        struct mbuf *m = NULL;
    150147        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       
    165149        m = slirpDnsMbufAlloc(pData);
    166150        if (m == NULL)
    167151        {
    168152            LogRel(("NAT: Can't allocate mbuf\n"));
    169             udp_detach(pData, so1);
    170153            goto socket_clean_up;
    171154        }
     
    187170        udp->uh_dport = ntohs(53);
    188171        udp->uh_sport = so->so_lport;
     172
    189173        memcpy(data, req->byte, req->nbyte); /* coping initial req */
    190174
    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 */
    196176        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;
    201183    }
    202184 
     
    263245        return;
    264246    }
    265 #else
    266     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 #endif
    278247
    279248    /* check for minimum dns packet length */
     
    284253    }
    285254
    286 #ifndef VBOX
    287255    /* allocate new request */
    288256    if ((req = calloc(1, sizeof(struct request))) == NULL) {
     
    295263    memcpy(&req->client, &fromaddr, sizeof(struct sockaddr_in));
    296264    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)
    301354    {
    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        {
    303360            LogRel(("calloc failed\n"));
    304361            ++dropped_queries;
    305362            return;
    306363        }
    307     }
    308 
    309     /* fill the request structure */
    310     if (so->so_timeout_arg == NULL)
    311     {
     364
    312365        req->id = QUERYID;
    313366        memcpy(&req->client, &fromaddr, sizeof(struct sockaddr_in));
     
    319372            RTMemFree(req);
    320373            if (fail_counter == 0)
    321                 LogRel(("NAT/dnsproxy: Empty DNS entry (suppressed 100 times)\n"));
     374              LogRel(("NAT/dnsproxy: Empty DNS entry (suppressed 100 times)\n"));
    322375            else
    323                 fail_counter = (fail_counter == 100 ? 0 : fail_counter + 1);
     376              fail_counter = (fail_counter == 100 ? 0 : fail_counter + 1);
    324377            return;
    325378
     
    333386    else
    334387    {
    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
    353391    req->recursion = 0;
     392       
    354393    DPRINTF(("External query RD=%d\n", RD(buf)));
     394       
    355395    if (retransmit == 0)
    356396        hash_add_request(pData, req);
    357 #endif
     397
    358398
    359399    /* overwrite the original query id */
    360400    memcpy(&buf[0], &req->id, 2);
    361401
    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 */
    420443}
    421444
     
    451474        return;
    452475    }
    453 #else
    454     char *buf;
    455     int byte;
    456     struct request *query = NULL;
    457     byte = m->m_len;
    458     buf = mtod(m, char *);
    459 #endif
    460476
    461477    /* check for minimum dns packet length */
     
    467483
    468484    /* find corresponding query */
    469 #ifdef VBOX
    470     if ((query = hash_find_request(pData, *((unsigned short *)buf))) == NULL) {
    471         ++late_answers;
    472         /* Probably, this request wasn't serviced by
    473          * 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 #else
    481485    if ((query = hash_find_request(pData, *((unsigned short *)&buf))) == NULL) {
    482486        ++late_answers;
     
    484488    }
    485489    event_del(&query->timeout);
    486 #endif
     490
    487491    hash_remove_request(pData, query);
    488492
     
    490494    memcpy(&buf[0], &query->clientid, 2);
    491495
    492 #ifndef VBOX
    493     /* Slirp: will send mbuf to guest by itself */
    494     /* send answer back to querying host */
    495496    if (sendto(sock_query, buf, (unsigned int)byte, 0,
    496497                (struct sockaddr *)&query->client,
     
    498499        LogRel(("sendto failed: %s\n", strerror(errno)));
    499500        ++dropped_answers;
    500     } else
     501    }
     502    else
    501503        ++answered_queries;
    502504
    503505    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
    505547    ++answered_queries;
    506548
    507549    RTMemFree(query);
    508 #endif
     550#endif /* VBOX */
    509551}
    510552
     553
     554#ifdef VBOX
     555int
     556dnsproxy_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 */
    511568/* main -- dnsproxy main function
    512569 */
    513 #ifndef VBOX
    514570int
    515571main(int argc, char *argv[])
     
    671727
    672728}
    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.

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