Annotation of libwww/Library/src/HTDNS.c, revision 2.18

2.1       frystyk     1: /*                                                                     HTDNS.c
                      2: **     DOMAIN NAME SERVICE MANAGER
                      3: **
                      4: **     (c) COPYRIGHT MIT 1995.
                      5: **     Please first read the full copyright statement in the file COPYRIGH.
                      6: **
                      7: **     This object manages a cache of hosts we have looked up vis DNS.
                      8: **     The object contains the necessary parts from hostent. For Internet host
                      9: **     hostent->h_addr_list is not an array of char pointers but an array of 
                     10: **     pointers of type in_addr.
                     11: **
                     12: **     13 Sep 95  HFN  Spawned from HTTCP.c and rewritten
                     13: */
                     14: 
                     15: /* Library include files */
                     16: #include "tcp.h"
                     17: #include "HTUtils.h"
                     18: #include "HTString.h"
                     19: #include "HTAtom.h"
                     20: #include "HTList.h"
                     21: #include "HTParse.h"
                     22: #include "HTAlert.h"
                     23: #include "HTError.h"
                     24: #include "HTNetMan.h"
                     25: #include "HTDNS.h"                                      /* Implemented here */
                     26: 
                     27: #define TCP_TIMEOUT            3600L           /* Default TCP timeout i 1 h */
                     28: #define DNS_TIMEOUT            172800L       /* Default DNS timeout is 48 h */
                     29: #define HASH_SIZE              67
                     30: 
                     31: /* Type definitions and global variables etc. local to this module */
                     32: struct _HTdns {
                     33:     char *             hostname;               /* name of host + maybe port */
                     34:     time_t             ntime;                              /* Creation time */
                     35: 
                     36:     char *             server;                              /* Server class */
                     37:     int                version;                           /* Server version */
                     38:     HTTCPType          type;                             /* Connection type */
                     39: 
2.12      frystyk    40:     int                active;                  /* Semaphor on Socket usage */
2.1       frystyk    41:     time_t             expires;                      /* Socket expires time */
2.11      frystyk    42:     SOCKET             sockfd;                     /* Persistent connection */
2.1       frystyk    43: 
                     44:     int                        addrlength;            /* Length of address in bytes */
                     45:     int                        homes;         /* Number of IP addresses on the host */
                     46:     char **            addrlist;      /* List of addresses from name server */
                     47:     double *           weight;                    /* Weight on each address */
                     48: };
                     49: 
2.2       frystyk    50: PRIVATE HTList **CacheTable = NULL;
                     51: PRIVATE HTList *PersSock = NULL;              /* List of persistent sockets */
                     52: PRIVATE time_t DNSTimeout = DNS_TIMEOUT;          /* Timeout on DNS entries */
                     53: PRIVATE time_t TCPTimeout = TCP_TIMEOUT;          /* Timeout on TCP sockets */
2.1       frystyk    54: 
                     55: /* ------------------------------------------------------------------------- */
                     56: 
                     57: PRIVATE void free_object (HTdns * me)
                     58: {
                     59:     if (me) {
2.17      frystyk    60:        HT_FREE(me->hostname);
                     61:        HT_FREE(me->server);
2.12      frystyk    62:        if (me->sockfd != INVSOC && me->active <= 0) {
2.1       frystyk    63:            NETCLOSE(me->sockfd);
2.2       frystyk    64:            HTEvent_UnRegister(me->sockfd, (SockOps) FD_ALL);
                     65:            HTList_removeObject(PersSock, me);
                     66:        }
2.1       frystyk    67:        if (*me->addrlist)
2.17      frystyk    68:            HT_FREE(*me->addrlist);
                     69:        HT_FREE(me->addrlist);
                     70:        HT_FREE(me->weight);
                     71:        HT_FREE(me);
2.1       frystyk    72:     }
                     73: }
                     74: 
                     75: PRIVATE BOOL delete_object (HTList * list, HTdns *me)
                     76: {
                     77:     if (PROT_TRACE)
2.18    ! eric       78:        HTTrace("DNS Delete.. object %p from list %p\n", me, list);
2.1       frystyk    79:     HTList_removeObject(list, (void *) me);
                     80:     free_object(me);
                     81:     return YES;
                     82: }
                     83: 
                     84: /*     HTDNS_setTimeout
                     85: **     ----------------
                     86: **     Set the cache timeout for DNS entries. Default is DNS_TIMEOUT
                     87: */
                     88: PUBLIC void HTDNS_setTimeout (time_t timeout)
                     89: {
                     90:     DNSTimeout = timeout;
                     91: }
                     92: 
                     93: /*     HTDNS_timeout
                     94: **     -------------
                     95: **     Get the cache timeout 
                     96: */
                     97: PUBLIC time_t HTDNS_timeout (time_t timeout)
                     98: {
                     99:     return DNSTimeout;
                    100: }
                    101: 
                    102: /*     HTDNS_setSockTimeout
                    103: **     --------------------
                    104: **     Set the cache timeout for DNS entries. Default is DNS_TIMEOUT
                    105: */
                    106: PUBLIC void HTDNS_setSockTimeout (time_t timeout)
                    107: {
                    108:     TCPTimeout = timeout;
                    109: }
                    110: 
                    111: /*     HTDNS_sockTimeout
                    112: **     -----------------
                    113: **     Get the cache timeout 
                    114: */
                    115: PUBLIC time_t HTDNS_sockTimeout (time_t timeout)
                    116: {
                    117:     return TCPTimeout;
                    118: }
                    119: 
                    120: /*     HTDNS_serverClass
                    121: **     -----------------
                    122: */
                    123: PUBLIC char *HTDNS_serverClass (HTdns *dns)
                    124: {
                    125:      return dns ? dns->server : NULL;
                    126: }
                    127: 
2.4       frystyk   128: PUBLIC void HTDNS_setServerClass (HTdns * dns, char *s_class)
2.1       frystyk   129: {
2.4       frystyk   130:     if (dns && s_class) StrAllocCopy(dns->server, s_class);
2.1       frystyk   131: }
                    132: 
                    133: /*     HTDNS_serverVersion
                    134: **     -------------------
                    135: */
                    136: PUBLIC int HTDNS_serverVersion (HTdns *dns)
                    137: {
                    138:      return dns ? dns->version : 0;
                    139: }
                    140: 
2.5       frystyk   141: PUBLIC void HTDNS_setServerVersion (HTdns * dns, int version)
2.1       frystyk   142: {
2.5       frystyk   143:     if (dns) dns->version = version;
                    144: }
                    145: 
                    146: /*     HTDNS_connection
                    147: **     ----------------
                    148: */
                    149: PUBLIC HTTCPType HTDNS_connection (HTdns *dns)
                    150: {
2.7       frystyk   151:      return dns ? dns->type : HT_TCP_PLAIN;
2.5       frystyk   152: }
                    153: 
                    154: PUBLIC void HTDNS_setConnection (HTdns * dns, HTTCPType type)
                    155: {
                    156:     if (dns) dns->type = type;
2.1       frystyk   157: }
                    158: 
                    159: /*     Persistent Connections
                    160: **     ----------------------
                    161: */
2.11      frystyk   162: PUBLIC SOCKET HTDNS_socket(HTdns *dns)
2.1       frystyk   163: {
                    164:     return dns ? dns->sockfd : INVSOC;
                    165: }
                    166: 
2.2       frystyk   167: /*
                    168: **     We don't want more than MaxSockets-2 connections to be persistent in
                    169: **     order to avoid deadlock.
                    170: */
2.11      frystyk   171: PUBLIC BOOL HTDNS_setSocket(HTdns *dns, SOCKET socket)
2.1       frystyk   172: {
2.2       frystyk   173:     if (!dns) return NO;
                    174:     if (!PersSock) PersSock = HTList_new();
                    175:     if (socket == INVSOC) {
                    176:        dns->sockfd = socket;
2.12      frystyk   177:        dns->active = 0;
                    178:        if (dns->active < 0) dns->active = 0;
2.2       frystyk   179:        dns->expires = 0;
                    180:        HTList_removeObject(PersSock, dns);
                    181:        return YES;
                    182:     } else if (HTList_count(PersSock) < HTNet_maxSocket()-2) {
2.1       frystyk   183:        dns->sockfd = socket;
2.12      frystyk   184:        if (dns->active <= 0) dns->active = 1;
2.1       frystyk   185:        dns->expires = time(NULL) + TCPTimeout;           /* Default timeout */
2.2       frystyk   186:        HTList_addObject(PersSock, dns);
                    187:        return YES;
2.15      frystyk   188:     } else {
                    189:        if (PROT_TRACE)
2.18    ! eric      190:            HTTrace("DNS Socket.. not room for persistent socket %d\n",
2.15      frystyk   191:                     socket);
2.1       frystyk   192:     }
2.12      frystyk   193:     if (PROT_TRACE)
2.18    ! eric      194:        HTTrace("DNS Socket.. semaphor is %d for soc %d\n",
2.12      frystyk   195:                 dns->active, dns->sockfd);
2.2       frystyk   196:     return NO;
2.1       frystyk   197: }
                    198: 
2.6       frystyk   199: PUBLIC int HTDNS_socketCount (void)
                    200: {
                    201:     return PersSock ? HTList_count(PersSock) : 0;
                    202: }
                    203: 
2.1       frystyk   204: PUBLIC void HTDNS_clearActive (HTdns *dns)
                    205: {
2.2       frystyk   206:     if (dns) {
2.12      frystyk   207:        dns->active--;  
                    208:        if (dns->active < 0) dns->active = 0;
2.2       frystyk   209:        if (PROT_TRACE)
2.18    ! eric      210:            HTTrace("DNS Clear... semaphor is %d for soc %d\n",
2.12      frystyk   211:                     dns->active, dns->sockfd);
2.2       frystyk   212:     }
2.1       frystyk   213: }
                    214: 
                    215: /*     Persistent Connection Expiration
                    216: **     --------------------------------
2.2       frystyk   217: **     Should normally not be used. If, then use calendar time.
2.1       frystyk   218: */
                    219: PUBLIC void HTDNS_setSockExpires (HTdns * dns, time_t expires)
                    220: {
                    221:     if (dns) dns->expires = expires;
                    222: }
                    223: 
                    224: PUBLIC time_t HTDNS_sockExpires (HTdns * dns)
                    225: {
                    226:     return dns ? dns->expires : -1;
                    227: }
                    228: 
                    229: /*     HTDNS_add
                    230: **     ---------
                    231: **     Add an element to the cache of visited hosts. Note that this function
                    232: **     requires the system implemented structure hostent and not our own
                    233: **     host_info. The homes variable indicates the number of
                    234: **     IP addresses found. host is a host name possibly with a port number
                    235: **     returns address of new HTdns object
                    236: */
                    237: PRIVATE HTdns * HTDNS_add (HTList * list, struct hostent * element,
                    238:                           char *host, int *homes)
                    239: {
                    240:     HTdns *me;
                    241:     char *addr;
                    242:     char **index = element->h_addr_list;
                    243:     int cnt = 1;
                    244: 
                    245:     while(*index++) cnt++;
2.17      frystyk   246:     if ((me = (HTdns *) HT_CALLOC(1, sizeof(HTdns))) == NULL ||
                    247:        (me->addrlist = (char **) HT_CALLOC(1, cnt*sizeof(char*))) == NULL ||
                    248:        (addr = (char *) HT_CALLOC(1, cnt*element->h_length)) == NULL)
                    249:        HT_OUTOFMEM("HTDNS_add");
2.1       frystyk   250:     StrAllocCopy(me->hostname, host);
                    251:     me->ntime = time(NULL);
                    252:     me->sockfd = INVSOC;
                    253:     index = element->h_addr_list;
                    254:     cnt = 0;
                    255:     while (*index) {
                    256:        *(me->addrlist+cnt) = addr+cnt*element->h_length;
                    257:        memcpy((void *) *(me->addrlist+cnt++), *index++, element->h_length);
                    258:     }
                    259:     me->homes = cnt;
                    260:     *homes = cnt;
2.17      frystyk   261:     if ((me->weight = (double *) HT_CALLOC(me->homes, sizeof(double))) == NULL)
                    262:         HT_OUTOFMEM("HTDNS_add");
2.1       frystyk   263:     me->addrlength = element->h_length;
                    264:     if (PROT_TRACE)
2.18    ! eric      265:        HTTrace("DNS Add..... `%s\' with %d home(s) to %p\n",
2.1       frystyk   266:                host, *homes, list);
                    267:     HTList_addObject(list, (void *) me);
                    268:     return me;
                    269: }
                    270: 
                    271: 
                    272: /*     HTDNS_updateWeights
                    273: **     -------------------
                    274: **     This function calculates the weights of the different IP addresses
                    275: **     on a multi homed host. Each weight is calculated as
                    276: **
                    277: **             w(n+1) = w(n)*a + (1-a) * deltatime
                    278: **             a = exp(-1/Neff)
                    279: **             Neff is the effective number of samples used
                    280: **             deltatime is time spend on making a connection
                    281: **
                    282: **     A short window (low Neff) gives a high sensibility, but this is
                    283: **     required as we can't expect a lot of data to test on.
                    284: **     host is a host name possibly with port number. current is the index
                    285: **     returned by HTGetHostByName()
                    286: */
                    287: PUBLIC BOOL HTDNS_updateWeigths(HTdns *dns, int current, time_t deltatime)
                    288: {
                    289:     if (dns) {
                    290:        int cnt;
                    291:        CONST double passive = 0.9;       /* Factor for all passive IP_addrs */
                    292: #if 0
                    293:        CONST int Neff = 3;
                    294:        CONST double alpha = exp(-1.0/Neff);
                    295: #else
                    296:        CONST double alpha = 0.716531310574;    /* Doesn't need the math lib */
                    297: #endif
                    298:        for (cnt=0; cnt<dns->homes; cnt++) {
                    299:            if (cnt == current) {
                    300:                *(dns->weight+current) = *(dns->weight+current)*alpha + (1.0-alpha)*deltatime;
2.16      frystyk   301:                if (*(dns->weight+current) < 0.0) *(dns->weight+current) = 0.0;
2.1       frystyk   302:            } else {
                    303:                *(dns->weight+cnt) = *(dns->weight+cnt) * passive;
                    304:            }
                    305:            if (PROT_TRACE)
2.18    ! eric      306:                HTTrace("DNS Weigths. Home %d has weight %4.2f\n", cnt,
2.1       frystyk   307:                        *(dns->weight+cnt));
                    308:        }
                    309:        return YES;
                    310:     }
                    311:     if (PROT_TRACE)
2.18    ! eric      312:        HTTrace("DNS Weigths. Object %p not found'\n", dns);
2.1       frystyk   313:     return NO;
                    314: }
                    315: 
                    316: /*     HTDNS_delete
                    317: **     ------------
                    318: **     Remove an element from the cache
                    319: **     Host must be a host name possibly with a port number
                    320: */
                    321: PUBLIC BOOL HTDNS_delete (CONST char * host)
                    322: {
                    323:     HTList *list;
                    324:     int hash = 0;
                    325:     CONST char *ptr;
                    326:     if (!host || !CacheTable) return NO;
                    327:     for(ptr=host; *ptr; ptr++)
                    328:        hash = (int) ((hash * 3 + (*(unsigned char *) ptr)) % HASH_SIZE);
                    329:     if ((list = CacheTable[hash])) {    /* We have the list, find the entry */
                    330:        HTdns *pres;
                    331:        while ((pres = (HTdns *) HTList_nextObject(list))) {
                    332:            if (!strcmp(pres->hostname, host)) {
                    333:                delete_object(CacheTable[hash], pres);
                    334:                break;
                    335:            }
                    336:        }
                    337:     }
                    338:     return YES;
                    339: }
                    340: 
                    341: /*     HTDNS_deleteAll
                    342: **     ---------------
                    343: **     Destroys the cache completely
                    344: */
                    345: PUBLIC BOOL HTDNS_deleteAll (void)
                    346: {
                    347:     int cnt;
                    348:     HTList *cur;
                    349:     if (!CacheTable) return NO;
                    350:     for (cnt=0; cnt<HASH_SIZE; cnt++) {
                    351:        if ((cur = CacheTable[cnt])) { 
                    352:            HTdns *pres;
                    353:            while ((pres = (HTdns *) HTList_nextObject(cur)) != NULL)
                    354:                free_object(pres);
                    355:        }
                    356:        HTList_delete(CacheTable[cnt]);
                    357:        CacheTable[cnt] = NULL;
2.2       frystyk   358:     }
                    359:     if (PersSock) {                 /* Remove list of persistent connection */
                    360:        HTList_delete(PersSock);
                    361:        PersSock = NULL;
                    362:     }
                    363:     return YES;
                    364: }
2.1       frystyk   365: 
2.2       frystyk   366: /*     HTDNS_closeSocket
                    367: **     -----------------
                    368: **     This function is registered when the socket is idle so that we get
                    369: **     a notification if the socket closes at the other end. At this point
                    370: **     we can't use the request object as it might have been freed a long
                    371: **     time ago.
                    372: */
                    373: PUBLIC int HTDNS_closeSocket(SOCKET soc, HTRequest * request, SockOps ops)
                    374: {
                    375:     if (PROT_TRACE)
2.18    ! eric      376:        HTTrace("DNS Close... called with socket %d with ops %x\n",
2.2       frystyk   377:                soc, (unsigned) ops);
                    378:     if (ops == FD_READ && PersSock) {
                    379:        HTList *cur = PersSock;
                    380:        HTdns *pres;
                    381:        while ((pres = (HTdns *) HTList_nextObject(cur))) {
                    382:            if (pres->sockfd == soc) {
2.18    ! eric      383:                if (PROT_TRACE)HTTrace("DNS Close... socket %d\n",soc);
2.2       frystyk   384:                NETCLOSE(soc);
                    385:                HTDNS_setSocket(pres, INVSOC);
                    386:                break;
                    387:            }
                    388:        }
2.15      frystyk   389:        if (!pres)
2.18    ! eric      390:            if (PROT_TRACE)HTTrace("DNS Close... socket NOT FOUND!\n");
2.1       frystyk   391:     }
2.2       frystyk   392:     HTEvent_UnRegister(soc, (SockOps) FD_ALL);
                    393:     return HT_OK;
2.1       frystyk   394: }
                    395: 
                    396: /*     HTGetHostByName
                    397: **     ---------------
                    398: **     Resolve the host name using internal DNS cache. As we want to refer   
                    399: **     a specific host when timing the connection the weight function must
                    400: **     use the 'current' value as returned.
                    401: **     Host must be a host name possibly with a port number
                    402: **      Returns:
                    403: **             >0      Number of homes
                    404: **              0      Wait for persistent socket
                    405: **             -1      Error
                    406: */
                    407: PUBLIC int HTGetHostByName (HTNet *net, char *host)
                    408: {
                    409:     SockA *sin = &net->sock_addr;
                    410:     int homes = -1;
                    411:     HTList *list;                                  /* Current list in cache */
                    412:     HTdns *pres = NULL;
                    413:     if (!net || !host) {
                    414:        if (PROT_TRACE)
2.18    ! eric      415:            HTTrace("HostByName.. Bad argument\n");
2.1       frystyk   416:        return -1;
                    417:     }
                    418:     net->home = 0;
                    419:     
                    420:     /* Find a hash for this host */
                    421:     {
                    422:        int hash = 0;
                    423:        char *ptr;
                    424:        for(ptr=host; *ptr; ptr++)
                    425:            hash = (int) ((hash * 3 + (*(unsigned char *) ptr)) % HASH_SIZE);
                    426:        if (!CacheTable) {
2.17      frystyk   427:            if ((CacheTable = (HTList* *) HT_CALLOC(HASH_SIZE, sizeof(HTList *))) == NULL)
                    428:                HT_OUTOFMEM("HTDNS_init");
2.1       frystyk   429:        }
                    430:        if (!CacheTable[hash]) CacheTable[hash] = HTList_new();
                    431:        list = CacheTable[hash];
                    432:     }
                    433: 
                    434:     /* Search the cache */
                    435:     {
                    436:        HTList *cur = list;
                    437:        while ((pres = (HTdns *) HTList_nextObject(cur))) {
                    438:            if (!strcmp(pres->hostname, host)) {
                    439:                if (time(NULL) > pres->ntime + DNSTimeout) {
                    440:                    if (PROT_TRACE)
2.18    ! eric      441:                        HTTrace("HostByName.. Refreshing cache\n");
2.1       frystyk   442:                    delete_object(list, pres);
                    443:                    pres = NULL;
                    444:                }
                    445:                break;
                    446:            }
                    447:        }
                    448:     }
                    449:     if (pres) {
                    450:        if (PROT_TRACE)
2.18    ! eric      451:            HTTrace("HostByName.. '%s\' found in cache\n", host);
2.1       frystyk   452: 
                    453:        /* See if we have an open connection already */
                    454:        if (pres->sockfd != INVSOC) {
2.13      frystyk   455:            if (pres->active > 0) {                /* Warm connection in use */
2.2       frystyk   456:                net->sockfd = pres->sockfd;                 /* Assign always */
2.12      frystyk   457:                pres->active++;
                    458:                if (PROT_TRACE)
2.18    ! eric      459:                    HTTrace("HostByName.. semaphor is %d for soc %d\n",
2.12      frystyk   460:                             pres->active, pres->sockfd);
                    461:                if (pres->type == HT_TCP_PLAIN) {
2.1       frystyk   462:                    if (PROT_TRACE)
2.18    ! eric      463:                        HTTrace("HostByName.. waiting for socket %d\n",
2.12      frystyk   464:                                 pres->sockfd);
                    465:                    net->dns = pres;
2.1       frystyk   466:                    return 0;                   /* Wait for clear connection */
                    467:                }
                    468:            } else if (pres->expires < time(NULL)) {          /* Gotton cold */
                    469:                if (PROT_TRACE)
2.18    ! eric      470:                    HTTrace("HostByName.. Closing %d\n", pres->sockfd);
2.1       frystyk   471:                NETCLOSE(pres->sockfd);
2.2       frystyk   472:                HTEvent_UnRegister(pres->sockfd, (SockOps) FD_ALL);
                    473:                HTDNS_setSocket(pres, INVSOC);
                    474:            } else {                /* Warm connection is idle and ready :-) */
                    475:                HTEvent_UnRegister(pres->sockfd, (SockOps) FD_ALL);
2.12      frystyk   476:                pres->active = 1;
                    477:                if (PROT_TRACE)
2.18    ! eric      478:                    HTTrace("HostByName.. semaphor is %d for soc %d\n",
2.12      frystyk   479:                             pres->active, pres->sockfd);
2.1       frystyk   480:                net->sockfd = pres->sockfd;
                    481:            }
                    482:        }
                    483: 
                    484:        /*
                    485:        ** Find the best home. We still want to do this as we use it as a
                    486:        ** fall back for persistent connections
                    487:        */
                    488:        homes = pres->homes;
                    489:        if (pres->homes > 1) {
                    490:            int cnt = 0;
                    491:            double best_weight = 1e30;                        /* Pretty good */
                    492:            while (cnt < pres->homes) {
                    493:                if (*(pres->weight+cnt) < best_weight) {
                    494:                    best_weight = *(pres->weight+cnt);
                    495:                    net->home = cnt;
                    496:                }
                    497:                cnt++;
                    498:            }
                    499:        }
                    500:        net->dns = pres;
2.14      frystyk   501:        memcpy((void *) &sin->sin_addr, *(pres->addrlist+net->home),
                    502:               pres->addrlength);
2.1       frystyk   503:     } else {
                    504:        struct hostent *hostelement;                          /* see netdb.h */
                    505:        char *port = strchr(host, ':');
2.10      frystyk   506:        HTAlertCallback *cbf = HTAlert_find(HT_PROG_DNS);
2.1       frystyk   507: #ifdef HT_REENTRANT
                    508:        int thd_errno;
                    509:        char buffer[HOSTENT_MAX];
                    510:        struct hostent result;                        /* For gethostbyname_r */
                    511:        if (port) *port='\0';
2.10      frystyk   512:        if (cbf) (*cbf)(net->request, HT_PROG_DNS, HT_MSG_NULL,NULL,host,NULL);
2.1       frystyk   513:        hostelement = gethostbyname_r(host, &result, buffer,
                    514:                                      HOSTENT_MAX, &thd_errno);
                    515: #else
                    516:        if (port) *port='\0';
2.10      frystyk   517:        if (cbf) (*cbf)(net->request, HT_PROG_DNS, HT_MSG_NULL,NULL,host,NULL);
2.1       frystyk   518:        hostelement = gethostbyname(host);
                    519: #endif
                    520:        if (!hostelement) {
                    521:            if (PROT_TRACE)
2.18    ! eric      522:                HTTrace("HostByName.. Can't find node `%s'.\n", host);
2.1       frystyk   523:            return -1;
                    524:        }       
                    525:        if (port) *port=':';                              /* Put ':' back in */
                    526:        net->dns = HTDNS_add(list, hostelement, host, &homes);
2.14      frystyk   527:        memcpy((void *) &sin->sin_addr, *hostelement->h_addr_list,
                    528:               hostelement->h_length);
2.1       frystyk   529:     }
                    530:     return homes;
                    531: }
                    532: 
                    533: 
                    534: /*
                    535: **     Get host name of the machine on the other end of a socket.
                    536: **
                    537: */
2.9       frystyk   538: PUBLIC char * HTGetHostBySock (int soc)
2.1       frystyk   539: {
                    540:     struct sockaddr addr;
                    541:     int len = sizeof(struct sockaddr);
                    542:     struct in_addr *iaddr;
                    543:     char *name = NULL;
                    544:     struct hostent * phost;            /* Pointer to host -- See netdb.h */
                    545: #ifdef HT_REENTRANT
                    546:     int thd_errno;
                    547:     char buffer[HOSTENT_MAX];
                    548:     struct hostent result;                           /* For gethostbyaddr_r */
                    549: #endif
                    550: 
                    551: #ifdef DECNET  /* Decnet ain't got no damn name server 8#OO */
                    552:     return NULL;
                    553: #else
                    554:     if (getpeername(soc, &addr, &len) < 0)
                    555:        return NULL;
                    556:     iaddr = &(((struct sockaddr_in *)&addr)->sin_addr);
                    557: 
                    558: #ifdef HT_REENTRANT
                    559:     phost = gethostbyaddr_r((char *) iaddr, sizeof(struct in_addr), AF_INET,
                    560:                            &result, buffer, HOSTENT_MAX, &thd_errno);
                    561: #else
                    562:     phost = gethostbyaddr((char *) iaddr, sizeof(struct in_addr), AF_INET);
                    563: #endif
                    564:     if (!phost) {
                    565:        if (PROT_TRACE)
2.18    ! eric      566:            HTTrace("TCP......... Can't find internet node name for peer!!\n");
2.1       frystyk   567:        return NULL;
                    568:     }
                    569:     StrAllocCopy(name, phost->h_name);
2.18    ! eric      570:     if (PROT_TRACE) HTTrace("TCP......... Peer name is `%s'\n", name);
2.1       frystyk   571:     return name;
                    572: 
                    573: #endif /* not DECNET */
                    574: }

Webmaster