httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Dean Gaudet <dgau...@arctic.org>
Subject Re: [PATCH] more contrib: log-resolve.c
Date Sat, 23 Aug 1997 03:42:10 GMT
Uh, it helps if I include the code.

On Fri, 22 Aug 1997, Dean Gaudet wrote:

> Pierre-Yves, the fellow that got me started on the sysvsem code, submitted
> two other things to me at the same time.  Here's the first.

/*
 * LOG-RESOLVE
 * Pierre-Yves Kerembellec/VTCOM - 02/97
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
#include <resolv.h>
#include <netdb.h>
#include <db.h>

#ifndef INADDR_NONE
#define INADDR_NONE 0xffffffff
#endif

#ifndef res_init
int     res_init(void);
int     res_search(char *, int, int, unsigned char *, int);
int     dn_skipname(char *, char *);
int     dn_expand(char *, char *, char *, char *, int);
#endif

#define  VERSION            "1.1"
#define  NAME_SIZE          (256)
#define  LINE_SIZE          (8192)
#define  DEFAULTTTLVALID    (86400*7)
#define  DEFAULTTTLBOGUS    (86400)
#define  DEFAULTDNSTIMEOUT  (15)
#define  LEARNINGACTIVE     (1)
#define  LEARNINGPASSIVE    (2)

typedef struct {
  long  lCreationDate;
  long  lTTL;
  char  szName[NAME_SIZE];
 } CACHEENTRY;

int bEnd=0;

/* ========================================================================== */
/* Usage                                                                      */
/* ========================================================================== */
int Usage(int iStatus)
{
 fprintf(stderr,"\nUsage : log-resolve [options]\n\n");
 fprintf(stderr,"  -b[ogus-TTL] [value]      cache bogus entries TTL (default is %d secs)\n",DEFAULTTTLBOGUS);
 fprintf(stderr,"  -c[ache-file] [file]      specify cache file (default is none)\n");
 fprintf(stderr,"  -d[ump]                   dump cache content\n");
 fprintf(stderr,"  -D[NS-timeout] [value]    set DNS timeout (defaul is %d secs)\n",DEFAULTDNSTIMEOUT);
 fprintf(stderr,"  -f[etch] [IP address]     fetch a particular entry from the cache\n");
 fprintf(stderr,"  -h[elp]                   print this help screen\n");
 fprintf(stderr,"  -i[nfo]                   turn verbose mode on\n");
 fprintf(stderr,"  -l[earning-mode] [mode]   build-cache-only mode\n");
 fprintf(stderr,"  -q[uiet]                  turn quiet mode on\n");
 fprintf(stderr,"  -r[equest-limit] [value]  max DNS requests for this run (default is infinite)\n");
 fprintf(stderr,"  -t[ime-limit] [value]     max elapsed time for this run (default is infinite)\n");
 fprintf(stderr,"  -T[race]                  turn DNS trace on\n");
 fprintf(stderr,"  -v[alid-TTL] [value]      cache valid entries TTL (default is %d secs)\n",DEFAULTTTLVALID);
 fprintf(stderr,"  -z[ap-dns]                turn DNS requests off (use local cache only)\n");
 fprintf(stderr,"\n");
 return(iStatus);
}

/* ========================================================================== */
/* Resolve                                                                    */
/* ========================================================================== */
int Resolve(unsigned long lAddress, char *szName, int iMaxLength, 
            int lTimeout, int bDebug)
{
 static char szRequest[64],pAnswer[PACKETSZ],pBuffer[BUFSIZ+1],*pStart,*pEnd;
 struct in_addr stAddress;
 HEADER *pHeader;
 int    iLength,iBytes,iQDCount,iANCount,iType;

 if (lAddress==0 || szName==NULL || iMaxLength<=0)
     return(-1);
 *szName = 0;
 stAddress.s_addr = ntohl(lAddress);
 sprintf(szRequest,"%s.in-addr.arpa.",inet_ntoa(stAddress));
 if (!(_res.options & RES_INIT))
     res_init();
 _res.options = RES_RECURSE;
 if (bDebug)
     _res.options = RES_DEBUG;
 _res.retrans = lTimeout;
 _res.retry   = 1;
 iLength = res_search(szRequest,C_IN,T_PTR,pAnswer,sizeof(pAnswer));
 if (iLength<0)
     return(-2);
 pHeader = (HEADER *)pAnswer;
 pStart = pAnswer + sizeof(HEADER);
 pEnd   = pAnswer + iLength;
 iQDCount = ntohs(pHeader->qdcount);
 iANCount = ntohs(pHeader->ancount);
 if (iANCount==0)
     return(-3);
 while (iQDCount-->0) {
      iBytes = dn_skipname(pStart,pEnd);
      if (iBytes<0)
          return(-4);
      pStart += iBytes + QFIXEDSZ;
     }
 iBytes = dn_expand(pAnswer,pEnd,pStart,pBuffer,sizeof(pBuffer));
 if (iBytes<0)
     return(-5);
 pStart += iBytes;
 GETSHORT(iType,pStart);
 if (iType!=T_PTR)
     return(-6);
 pStart += (2*sizeof(short)) + sizeof(long);
 iBytes = dn_expand(pAnswer,pEnd,pStart,pBuffer,sizeof(pBuffer));
 if (iBytes<0)
     return(-7);
 if (iBytes>=iMaxLength)
     return(-8);
 memcpy(szName,pBuffer,iBytes);
 szName[iBytes] = 0;
 return(0);
}

/* ========================================================================== */
/* Main                                                                       */
/* ========================================================================== */
void Interrupt(int iSignal) 
{ 
 bEnd=1; 
 signal(SIGHUP,Interrupt);
 signal(SIGINT,Interrupt);
 signal(SIGQUIT,Interrupt);
 signal(SIGTERM,Interrupt);
}

int main(int argc, char **argv)
{
 unsigned   long lFetch,lAddress;
 long       lRequestLimit,lTimeLimit,lLines,lCacheHits,lCacheSaved,
            lCacheExpired,lDNSHits,lDNSBogus,lCurrent,lStart,lTTLValid,
            lTTLBogus,lDNSTimeout;
 struct     in_addr stAddress;
 struct     tm *pstTime;
 int        iStatus,iMode,bVerbose,bDump,bZapDNS,iLearningMode,bCacheValid,
            bDNSTrace;
 static     char szCacheFile[NAME_SIZE],szLine[LINE_SIZE],szAddress[LINE_SIZE],
            *pToken;
 DB         *pstCache;
 DBT        stKey,stData;
 CACHEENTRY stEntry,*pstEntry;

 /* set default values */
 bZapDNS = iLearningMode = bDump = bDNSTrace = 0;
 lLines = lCacheHits = lCacheSaved = lCacheExpired = lDNSHits = lDNSBogus = 0;
 lRequestLimit  = lTimeLimit = -1;
 bVerbose       = 1;
 lFetch         = INADDR_NONE;
 pstCache       = NULL;
 szCacheFile[0] = 0;
 lTTLValid      = DEFAULTTTLVALID;
 lTTLBogus      = DEFAULTTTLBOGUS;
 lDNSTimeout    = DEFAULTDNSTIMEOUT;

 /* parse command line arguments */
 argv++;
 while (*argv!=NULL) {
    if (**argv == '-') {
        if (!strncmp(*argv+1,"bogus-TTL",strlen(*argv+1))) {
            argv++;
            if (*argv==NULL)
                return(Usage(2));
            lTTLBogus = atol(*argv);
           }
        else if (!strncmp(*argv+1,"cache-file",strlen(*argv+1))) {
            argv++;
            if (*argv==NULL)
                return(Usage(2));
            strncpy(szCacheFile,*argv,sizeof(szCacheFile));
           }
        else if (!strncmp(*argv+1,"dump",strlen(*argv+1)))
            bDump = 1;
        else if (!strncmp(*argv+1,"DNS-timeout",strlen(*argv+1))) {
            argv++;
            if (*argv==NULL)
                return(Usage(2));
            lDNSTimeout = atol(*argv);
           }
        else if (!strncmp(*argv+1,"fetch",strlen(*argv+1))) {
            argv++;
            if (*argv==NULL)
                return(Usage(2));
            lFetch = inet_addr(*argv);
            if (lFetch==INADDR_NONE)
                return(Usage(2));
           }
        else if (!strncmp(*argv+1,"help",strlen(*argv+1)))
            return(Usage(0));
        else if (!strncmp(*argv+1,"info",strlen(*argv+1)))
            bVerbose = 2;
        else if (!strncmp(*argv+1,"learning-mode",strlen(*argv+1))) {
            argv++;
            if (*argv==NULL)
                return(Usage(2));
            if (!strcmp(*argv,"active"))
                iLearningMode = LEARNINGACTIVE;
            else if (!strcmp(*argv,"passive"))
                iLearningMode = LEARNINGPASSIVE;
            else
                return(Usage(2));
           }
        else if (!strncmp(*argv+1,"quiet",strlen(*argv+1)))
            bVerbose = 0;
        else if (!strncmp(*argv+1,"request-limit",strlen(*argv+1))) {
            argv++;
            if (*argv==NULL)
                return(Usage(2));
            lRequestLimit = atol(*argv);
           }
        else if (!strncmp(*argv+1,"time-limit",strlen(*argv+1))) {
            argv++;
            if (*argv==NULL)
                return(Usage(2));
            lTimeLimit = atol(*argv);
           }
        else if (!strncmp(*argv+1,"Trace",strlen(*argv+1)))
            bDNSTrace = 1;
        else if (!strncmp(*argv+1,"valid-TTL",strlen(*argv+1))) {
            argv++;
            if (*argv==NULL)
                return(Usage(2));
            lTTLValid = atol(*argv);
           }
        else if (!strncmp(*argv+1,"zap-dns",strlen(*argv+1)))
            bZapDNS = 1;
        else
            return(Usage(1));
       }
    argv++;
   }
 if ((bDump || lFetch!=INADDR_NONE) && szCacheFile[0]==0) {
     fprintf(stderr,"Dump or fetch option selected and no cache file specified - aborting\n");
     return(3);
    }
 if (iLearningMode && szCacheFile[0]==0) {
     fprintf(stderr,"Learning mode selected and no cache file specified - aborting\n");
     return(3);
    }
 if (iLearningMode==LEARNINGPASSIVE)
     bZapDNS=1;

 /* dump configuration on screen if verbose set */
 if (bVerbose) {
     fprintf(stderr,"LOG-RESOLVE v%s - PYK 02/97\n\n",VERSION);
     if (bVerbose>1) {
         fprintf(stderr,"Bogus entry TTL  : %ld secs\n",lTTLBogus);
         fprintf(stderr,"Cache file       : %s\n",
                 (szCacheFile[0]==0)?"none":szCacheFile);
         fprintf(stderr,"DNS timeout      : %ld secs\n",lDNSTimeout);
         fprintf(stderr,"Learning mode    : %s\n",
                 (iLearningMode==0)?"off":
                 (iLearningMode==LEARNINGACTIVE)?"active":"passive");
         fprintf(stderr,"Requests limit   : ");
         if (lRequestLimit<0)
             fprintf(stderr,"none\n");
         else
             fprintf(stderr,"%ld requests\n",lRequestLimit);
         fprintf(stderr,"Valid entry TTL  : %ld secs\n",lTTLValid);
         fprintf(stderr,"Time limit       : ");
         if (lTimeLimit<0)
             fprintf(stderr,"none\n");
         else
             fprintf(stderr,"%ld secs\n",lTimeLimit);
         fprintf(stderr,"DNS trace        : %s\n",
                 bDNSTrace?"on":"off");
         fprintf(stderr,"Zap DNS          : %s\n",
                 bZapDNS?"on":"off");
         fprintf(stderr,"\n");
        }
    }

 /* open cache if needed */
 umask(0);
 if (szCacheFile[0]!=0) {
     iMode = O_RDWR;
     if (access(szCacheFile,0)<0)
         iMode |= O_CREAT;
     pstCache = dbopen(szCacheFile,iMode,0644,DB_BTREE,NULL);
     if (pstCache==NULL) {
         fprintf(stderr,"Cannot open cache file '%s' - aborting\n",szCacheFile);
         return(4);
        }
    }

 /* fetch cache entry or dump cache if specified */
 if (lFetch!=INADDR_NONE || bDump) {
     if (bDump)
         iStatus = pstCache->seq(pstCache,&stKey,&stData,R_FIRST);
     else {
         stKey.data = &lFetch;
         stKey.size = sizeof(unsigned long);
         iStatus = pstCache->get(pstCache,&stKey,&stData,0);
        }
     while (iStatus==0) {
        pstEntry = (CACHEENTRY *)stData.data;
        memcpy(&stAddress.s_addr,stKey.data,sizeof(long));
        printf("%s %s",
               inet_ntoa(stAddress),
               pstEntry->szName);
        pstTime = localtime(&pstEntry->lCreationDate);
        printf(" %02d/%02d/%02d-%02d:%02d:%02d ",
               pstTime->tm_mday,
               pstTime->tm_mon+1,
               pstTime->tm_year,
               pstTime->tm_hour,
               pstTime->tm_min,
               pstTime->tm_sec);
        if (pstEntry->lTTL/86400>0) {
            printf("%ldj",pstEntry->lTTL/86400);
            pstEntry->lTTL = pstEntry->lTTL%86400;
           }
        if (pstEntry->lTTL/3600>0) {
            printf("%ldh",pstEntry->lTTL/3600);
            pstEntry->lTTL = pstEntry->lTTL%3600;
           }
        if (pstEntry->lTTL/60>0) {
            printf("%ldm",pstEntry->lTTL/60);
            pstEntry->lTTL = pstEntry->lTTL%60;
           }
        if (pstEntry->lTTL>0)
            printf("%lds",pstEntry->lTTL);
        printf("\n");
        if (bDump)
            iStatus = pstCache->seq(pstCache,&stKey,&stData,R_NEXT);
        else
            break;
       }
     return(0);
    }

 /* proceed to log resolving */
 signal(SIGHUP,Interrupt);
 signal(SIGINT,Interrupt);
 signal(SIGQUIT,Interrupt);
 signal(SIGTERM,Interrupt);
 time(&lStart);
 while (fgets(szLine,sizeof(szLine),stdin)!=NULL && !bEnd) {
    if ((pToken = strchr(szLine,' '))==NULL) {
        if ((pToken = strchr(szLine,'\t'))==NULL) {
            if (iLearningMode==0)
                printf("%s",szLine);
            continue;
           }
       }
    *pToken = 0;
    if ((lAddress = inet_addr(szLine))==INADDR_NONE) {
        if (iLearningMode==0)
            printf("%s %s",szLine,pToken+1);
        continue;
       }
    lLines++;
    time(&lCurrent);
    if (lTimeLimit>=0) {
        if (lCurrent-lStart>=lTimeLimit) {
            if (bVerbose>1 && !bZapDNS)
                fprintf(stderr,"Warning, time limit reached : desactivating DNS resolving\n");
            bZapDNS=1;
           }
       }
    if (bVerbose>1) {
        stAddress.s_addr = lAddress;
        sprintf(szAddress,"[%s]",inet_ntoa(stAddress));
        fprintf(stderr,"\rLines:%ld DNSHits:%ld CacheHits:%ld CacheSaved:%ld  %-17.17s ",
                lLines,lDNSHits,lCacheHits,lCacheSaved,szAddress);
       }
    memset(&stEntry,0,sizeof(CACHEENTRY));
    bCacheValid = 0;
    if (pstCache!=NULL) {
        if (iLearningMode!=LEARNINGPASSIVE) {
            stKey.data = &lAddress;
            stKey.size = sizeof(unsigned long);
            iStatus = pstCache->get(pstCache,&stKey,&stData,0);
            if (iStatus==0) {
                memcpy(&stEntry,stData.data,stData.size);
                if (stEntry.lCreationDate+stEntry.lTTL<lCurrent && !bZapDNS) {
                    memset(&stEntry,0,sizeof(CACHEENTRY));
                    lCacheExpired++;
                   }
                else {
                    bCacheValid = 1;
                    lCacheHits++;
                    if (!strcmp(stEntry.szName,"BOGUS-DNS-ENTRY"))
                        memset(&stEntry,0,sizeof(CACHEENTRY));
                   }
               }
           }
        else {
            pToken = strtok(pToken+1," \t\n");
            if (pToken != NULL) {
                if (strcmp(pToken,"BOGUS-DNS-ENTRY"))
                    strcpy(stEntry.szName,pToken);
               }
           }
       }
    if (!bCacheValid && !bZapDNS) {
        lDNSHits++;
        if (Resolve(lAddress,stEntry.szName,sizeof(stEntry.szName),
                    lDNSTimeout,bDNSTrace)<0)
            lDNSBogus++;
        if (lRequestLimit>=0) {
            if (lDNSHits>=lRequestLimit) {
                if (bVerbose>1)
                    fprintf(stderr,"Warning, request limit reached : desactivating DNS resolving\n");
                bZapDNS=1;
               }
           }
       }
    if (!iLearningMode) {
        if (stEntry.szName[0]==0)
            printf("%s %s",szLine,pToken+1);
        else
            printf("%s %s",stEntry.szName,pToken+1);
       }
    if (pstCache!=NULL && !bCacheValid) {
        if (stEntry.szName[0]==0) {
            stEntry.lTTL = lTTLBogus;
            strcpy(stEntry.szName,"BOGUS-DNS-ENTRY");
           }
        else
            stEntry.lTTL = lTTLValid;
        stEntry.lCreationDate = lCurrent;
        stKey.data  = &lAddress;
        stKey.size  = sizeof(unsigned long);
        stData.data = &stEntry;
        stData.size = 2*sizeof(long)+strlen(stEntry.szName)+1;
        pstCache->put(pstCache,&stKey,&stData,0);
        lCacheSaved++;
        if ((lCacheSaved%100)==0)
            pstCache->sync(pstCache,0);
       }
   }

 /* close cache */
 if (pstCache!=NULL)
     pstCache->close(pstCache);

 /* output statistics & exit */
 if (bVerbose) {
     if (bVerbose>1)
         fprintf(stderr,"\r                                                              
               \r");
     fprintf(stderr,"Lines            : %ld\n",lLines);
     fprintf(stderr,"DNS Hits         : %ld (%ld valid/%ld bogus)\n",
             lDNSHits,lDNSHits-lDNSBogus,lDNSBogus);
     fprintf(stderr,"Cache Hits       : %ld\n",lCacheHits);
     fprintf(stderr,"Cache Saved      : %ld\n",lCacheSaved);
     fprintf(stderr,"Cache Expired    : %ld\n",lCacheExpired);
    }

 return(0);
}


Mime
View raw message