"Fossies" - the Fresh Open Source Software Archive

Member "openlitespeed-1.6.6/src/adns/adns.cpp" (22 Jan 2020, 11093 Bytes) of package /linux/www/openlitespeed-1.6.6.src.tgz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "adns.cpp" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.6.4_vs_1.6.5.

    1 /*
    2  * Copyright 2002 Lite Speed Technologies Inc, All Rights Reserved.
    3  * LITE SPEED PROPRIETARY/CONFIDENTIAL.
    4  */
    5 
    6 #include "adns.h"
    7 
    8 #include <log4cxx/logger.h>
    9 #include <shm/lsshmhash.h>
   10 #include <util/datetime.h>
   11 
   12 #include <udns.h>
   13 
   14 #include <sys/socket.h>
   15 #include <netinet/in.h>
   16 #include <arpa/inet.h>
   17 #include <netdb.h>
   18 #include <stdio.h>
   19 #include <stdlib.h>
   20 #include <string.h>
   21 #include <sys/time.h>
   22 #include <sys/types.h>
   23 #include <unistd.h>
   24 
   25 #define DNS_CACHE_TTL           3600
   26 #define DNS_CACHE_NOTFOUND_TTL  300
   27 
   28 static int s_inited = 0;
   29 
   30 
   31 LS_SINGLETON(Adns);
   32 
   33 
   34 Adns::Adns()
   35     : m_pCtx( NULL )
   36     , m_iCounter(0)
   37     , m_iPendingEvt(0)
   38     , m_pShmHash(NULL)
   39     , m_tmLastTrim(0)
   40 {
   41 }
   42 
   43 
   44 Adns::~Adns()
   45 {
   46     shutdown();
   47     s_inited = 0;
   48 }
   49 
   50 
   51 void Adns::trimCache()
   52 {
   53     if (!m_pShmHash)
   54         return;
   55     if (DateTime::s_curTime - m_tmLastTrim > 60)
   56     {
   57         m_tmLastTrim = DateTime::s_curTime;
   58         m_pShmHash->lock();
   59         m_pShmHash->trim(DateTime::s_curTime - DNS_CACHE_TTL, NULL, 0);
   60         m_pShmHash->unlock();
   61     }
   62 }
   63 
   64 
   65 const char *Adns::getCacheValue( const char * pName, int nameLen, int &valLen )
   66 {
   67     if (!m_pShmHash)
   68         return NULL;
   69     const char *ret = NULL;
   70     LsShmHash::iteroffset iterOff;
   71     ls_strpair_t parms;
   72     ls_str_set(&parms.key, (char *)pName, nameLen);
   73     m_pShmHash->lock();
   74     iterOff = m_pShmHash->findIterator(&parms);
   75     if (iterOff.m_iOffset != 0)
   76     {
   77         LsShmHash::iterator iter = m_pShmHash->offset2iterator(iterOff);
   78         valLen = iter->getValLen();
   79         if (valLen == 0)
   80         {
   81             ret = "";
   82             if (iter->getLruLasttime() < DateTime::s_curTime
   83                                             - DNS_CACHE_NOTFOUND_TTL)
   84             {
   85                 m_pShmHash->eraseIterator(iterOff);
   86                 ret = NULL;
   87             }
   88         }
   89         ret = (char *)iter->getVal();
   90     }
   91     m_pShmHash->unlock();
   92     return ret;
   93 }
   94 
   95 
   96 int Adns::deleteCache()
   97 {
   98     return LsShm::deleteFile("adns_cache", NULL);
   99 }
  100 
  101 
  102 int Adns::init()
  103 {
  104     if (!s_inited)
  105     {
  106         if (dns_init(NULL, 1) < 0)
  107             return -1;
  108         s_inited = 1;
  109         dns_set_opt(NULL, DNS_OPT_NTRIES, 1);
  110     }
  111     if ( m_pCtx )
  112         return 0;
  113     m_pCtx = dns_new( NULL );
  114     if ( !m_pCtx )
  115         return -1;
  116     if ( dns_open( m_pCtx ) < 0 )
  117         return -1;
  118     setfd( dns_sock( m_pCtx ) );
  119 
  120     return 0;
  121 }
  122 
  123 
  124 int Adns::initShm(int uid, int gid)
  125 {
  126     if ( m_pShmHash )
  127         return 0;
  128     if ((m_pShmHash = LsShmHash::open(
  129         "adns_cache", "dns_cache", 1000, LSSHM_FLAG_LRU)) != NULL)
  130     {
  131         m_pShmHash->getPool()->getShm()->chperm(uid, gid, 0600);
  132         m_pShmHash->disableAutoLock();
  133     }
  134     return 0;
  135 }
  136 
  137 int Adns::shutdown()
  138 {
  139       dns_close( m_pCtx );
  140 //    if ( m_pCtx )
  141 //    {
  142 //        dns_free( m_pCtx );
  143 //        m_pCtx = NULL;
  144 //    }
  145     return 0;
  146 }
  147 
  148 
  149 void Adns::printLookupError(struct dns_ctx *ctx, AdnsReq *pAdnsReq)
  150 {
  151     const char *pError;
  152     switch(dns_status(ctx))
  153     {
  154     case DNS_E_TEMPFAIL:
  155         pError = "DNS_E_TEMPFAIL";
  156         break;
  157     case DNS_E_PROTOCOL:
  158         pError = "DNS_E_PROTOCOL";
  159         break;
  160     case DNS_E_NXDOMAIN:
  161         pError = "DNS_E_NXDOMAIN";
  162         break;
  163     case DNS_E_NODATA:
  164         pError = "DNS_E_NODATA";
  165         break;
  166     case DNS_E_NOMEM:
  167         pError = "DNS_E_NOMEM";
  168         break;
  169     case DNS_E_BADQUERY:
  170         pError = "DNS_E_BADQUERY";
  171         break;
  172     default:
  173         pError = "Unknown status";
  174         break;
  175     }
  176     LS_DBG_L("[DNSLOOKUP] (%s), "
  177             "AdnsReq Dump: Type %d, Name %s, Arg %p, Start time %ld",
  178              pError, pAdnsReq->type, pAdnsReq->name, pAdnsReq->arg,
  179              pAdnsReq->start_time);
  180 }
  181 
  182 
  183 void Adns::release(AdnsReq *pReq)
  184 {
  185     if (!pReq)
  186         return;
  187     if (--pReq->ref_count == 0)
  188     {
  189         //fprintf(stderr, "release AdnsReq %p\n", pReq); 
  190         delete pReq;
  191     }
  192 }
  193 
  194 
  195 int Adns::setResult(const struct sockaddr *result,
  196                      const void *ip, int len)
  197 {
  198     if (!result || !ip)
  199         return -1;
  200     void *dest = NULL;
  201     if (result->sa_family == PF_INET)
  202     {
  203         if (len == sizeof(in_addr))
  204             dest = &((sockaddr_in *)result)->sin_addr;
  205     }
  206     else
  207     {
  208         if (len == sizeof(in6_addr))
  209             dest = &((sockaddr_in6 *)result)->sin6_addr;
  210     }
  211     if (dest)
  212     {
  213         memmove(dest, ip, len);
  214         return 0;
  215     }
  216     return -1;
  217 }
  218 
  219 
  220 void Adns::getHostByNameCb(struct dns_ctx *ctx, void *rr_unknown, void *param)
  221 {
  222     AdnsReq *pAdnsReq = (AdnsReq *)param;
  223 
  224     char *sIp= (char *)"";
  225     int ipLen = 0;
  226     if (rr_unknown)
  227     {
  228         if (pAdnsReq->type != PF_INET6)
  229         {
  230             struct dns_rr_a4 * rr = (struct dns_rr_a4 *)rr_unknown;
  231             sIp = (char *)rr->dnsa4_addr;
  232             ipLen = sizeof(in_addr);
  233         }
  234         else
  235         {
  236             struct dns_rr_a6 * rr = (struct dns_rr_a6 *)rr_unknown;
  237             sIp = (char *)rr->dnsa6_addr;
  238             ipLen = sizeof(in6_addr);
  239         }
  240     }
  241     else if (LS_LOG_ENABLED(log4cxx::Level::DBG_LESS))
  242         printLookupError(ctx, pAdnsReq);
  243 
  244     LsShmHash *pCache = Adns::getInstance().getShmHash();
  245     if (pCache)
  246     {
  247         pCache->lock();
  248         pCache->insert(pAdnsReq->name, strlen(pAdnsReq->name), sIp, ipLen);
  249         pCache->unlock();
  250     }
  251     if (pAdnsReq->cb && pAdnsReq->arg)
  252         pAdnsReq->cb(pAdnsReq->arg, ipLen, sIp);
  253 
  254     if (rr_unknown)
  255         free(rr_unknown);
  256     release(pAdnsReq);
  257 }
  258 
  259 
  260 void Adns::getHostByAddrCb(struct dns_ctx *ctx, struct dns_rr_ptr *rr, void *param)
  261 {
  262     AdnsReq *pAdnsReq = (AdnsReq *)param;
  263 
  264     int nameLen;
  265     if (pAdnsReq->type != PF_INET6)
  266         nameLen = sizeof(in_addr);
  267     else
  268         nameLen = sizeof(in6_addr);
  269 
  270     char achBuf[4096];
  271     char *p = (char *)"";
  272     int n = 0;
  273     if (rr)
  274     {
  275         if ( rr->dnsptr_nrr == 1 )
  276         {
  277             p = rr->dnsptr_ptr[0];
  278             n = strlen(rr->dnsptr_ptr[0]);
  279         }
  280         else
  281         {
  282             p = achBuf;
  283             for(int i = 0; i < rr->dnsptr_nrr; ++i)
  284             {
  285                 n += lsnprintf(achBuf + n, 4096 - n, "%s,", rr->dnsptr_ptr[i]);
  286             }
  287             achBuf[n -1] = 0;
  288         }
  289     }
  290 
  291     LsShmHash *pCache = Adns::getInstance().getShmHash();
  292     if (pCache)
  293     {
  294         pCache->lock();
  295         pCache->insert(pAdnsReq->name, nameLen, p, n);
  296         pCache->unlock();
  297     }
  298     if (pAdnsReq->cb && pAdnsReq->arg)
  299         pAdnsReq->cb(pAdnsReq->arg, n, p);
  300     //else
  301     //    fprintf(stderr, "AdnsReq %p for %s skip callback, cb: %p, arg: %p\n", 
  302     //            pAdnsReq, pAdnsReq->name, pAdnsReq->cb, pAdnsReq->arg); 
  303 
  304     if (rr)
  305         free(rr);
  306     release(pAdnsReq);
  307 }
  308 
  309 
  310 char *Adns::getCacheName(const char *pName, int type)
  311 {
  312     int len = strlen(pName);
  313     char *nameWithVer = (char *)malloc(len + 4);
  314     memcpy(nameWithVer, pName, len);
  315     memcpy(nameWithVer + len, (type != PF_INET6 ? "_v4" : "_v6"), 3);
  316     nameWithVer[len + 3] = 0x00;
  317     return nameWithVer;
  318 }
  319 
  320 
  321 const char *Adns::getHostByNameInCache( const char * pName, int &length, int type )
  322 {
  323     char *nameWithVer = getCacheName(pName, type);
  324     const char *ret = getCacheValue(nameWithVer, strlen(nameWithVer), length);
  325     free(nameWithVer);
  326     return ret;
  327 }
  328 
  329 
  330 AdnsReq *Adns::getHostByName(const char * pName, int type, 
  331                              lookup_pf cb, void *arg)
  332 {
  333     dns_query * pQuery;
  334     init();
  335     AdnsReq *pAdnsReq = new AdnsReq;
  336     if (!pAdnsReq)
  337         return NULL;
  338     //fprintf(stderr, "AdnsReq %p created for getHostByName %s\n", 
  339     //        pAdnsReq, pName); 
  340     pAdnsReq->type = type;
  341     pAdnsReq->name = getCacheName(pName, type);
  342     pAdnsReq->cb = cb;
  343     pAdnsReq->arg = arg;
  344     pAdnsReq->start_time = DateTime::s_curTime;
  345     if (type != PF_INET6)
  346         pQuery = dns_submit_a4( m_pCtx, pName, DNS_NOSRCH, (addrLookupCbV4)getHostByNameCb, pAdnsReq);
  347     else
  348         pQuery = dns_submit_a6( m_pCtx, pName, DNS_NOSRCH, (addrLookupCbV6)getHostByNameCb, pAdnsReq);
  349     if (pQuery == NULL)
  350     {
  351         delete pAdnsReq;
  352         pAdnsReq = NULL;
  353     }
  354     else
  355         m_iPendingEvt = 1;
  356     return pAdnsReq;
  357 }
  358 
  359 
  360 static void *getInAddr(const struct sockaddr * pAddr, int& length)
  361 {
  362     switch( pAddr->sa_family )
  363     {
  364     case AF_INET6:
  365         length = sizeof(in6_addr);
  366         return &(((sockaddr_in6 *)pAddr)->sin6_addr);
  367     case AF_INET:
  368     default:
  369         length = sizeof(in_addr);
  370         return &(((sockaddr_in *)pAddr)->sin_addr);
  371     }
  372 }
  373 
  374 
  375 const char *Adns::getHostByAddrInCache(const struct sockaddr * pAddr, int &length )
  376 {
  377     int keyLen;
  378     const char *key = (const char *)getInAddr(pAddr, keyLen);
  379     const char *ret = getCacheValue(key, keyLen, length);
  380     return ret;
  381 }
  382 
  383 
  384 AdnsReq * Adns::getHostByAddr(const struct sockaddr * pAddr, void *arg, lookup_pf cb)
  385 {
  386     dns_query * pQuery;
  387     init();
  388     AdnsReq *pAdnsReq = new AdnsReq;
  389     if (!pAdnsReq)
  390         return NULL;
  391 
  392     //fprintf(stderr, "AdnsReq %p created for getHostByAddr\n", pAdnsReq); 
  393     int type = pAddr->sa_family;
  394     pAdnsReq->type = type;
  395     int length;
  396     char *pName= (char *)getInAddr(pAddr, length);
  397     pAdnsReq->name = (char *)malloc(length); //No NULL terminate
  398     memcpy(pAdnsReq->name, pName, length);
  399     pAdnsReq->cb = cb;
  400     pAdnsReq->arg = arg;
  401     pAdnsReq->start_time = DateTime::s_curTime;
  402 
  403     if (type != PF_INET6)
  404         pQuery = dns_submit_a4ptr( m_pCtx, (in_addr *)pName, getHostByAddrCb, pAdnsReq);
  405     else
  406         pQuery = dns_submit_a6ptr( m_pCtx, (in6_addr *)pName, getHostByAddrCb, pAdnsReq);
  407     if (pQuery == NULL)
  408     {
  409         delete pAdnsReq;
  410         pAdnsReq = NULL;
  411     }
  412     else
  413         m_iPendingEvt = 1;
  414     return pAdnsReq;
  415 }
  416 
  417 
  418 int Adns::handleEvents( short events )
  419 {
  420     if ( events & POLLIN )
  421         dns_ioevent( m_pCtx, DateTime::s_curTime );
  422 
  423     return 0;
  424 }
  425 
  426 
  427 int Adns::onTimer()
  428 {
  429     if (++m_iCounter >= 10)
  430     {
  431         m_iCounter = 0;
  432         checkDnsEvents();
  433     }
  434     return 0;
  435 }
  436 
  437 
  438 void Adns::setTimeOut(int tmSec)
  439 {
  440     dns_set_opt(m_pCtx, DNS_OPT_TIMEOUT, tmSec);
  441 }
  442 
  443 
  444 void Adns::checkDnsEvents()
  445 {
  446     dns_timeouts( m_pCtx, -1, DateTime::s_curTime );
  447 }
  448 
  449 
  450 int Adns::getHostByNameSync(const char *pName, in_addr_t *addr)
  451 {
  452     struct dns_rr_a4 *rr;
  453     if (!s_inited)
  454     {
  455         if (dns_init(NULL, 1) < 0)
  456             return -1;
  457         s_inited = 1;
  458         dns_set_opt(NULL, DNS_OPT_NTRIES, 1);
  459 
  460     }
  461     rr = dns_resolve_a4(NULL, pName, DNS_NOSRCH);
  462     if (rr)
  463     {
  464         if (rr->dnsa4_nrr > 0)
  465             memmove(addr, &rr->dnsa4_addr[0], 4);
  466         free(rr);
  467         return 0;
  468     }
  469     return -1;
  470 }
  471 
  472 int Adns::getHostByNameV6Sync(const char *pName, in6_addr *addr)
  473 {
  474     struct dns_rr_a6 *rr;
  475     if (!s_inited)
  476     {
  477         if (dns_init(NULL, 1) < 0)
  478             return -1;
  479         s_inited = 1;
  480         dns_set_opt(NULL, DNS_OPT_NTRIES, 1);
  481     }
  482     rr = dns_resolve_a6(NULL, pName, DNS_NOSRCH);
  483     if (rr)
  484     {
  485         if (rr->dnsa6_nrr > 0)
  486             memmove(addr, &rr->dnsa6_addr[0], 16);
  487         free(rr);
  488         return 0;
  489     }
  490     return -1;
  491 }