Logo Search packages:      
Sourcecode: netdiag version File versions  Download package

netresolv.c

#include "config.h"
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#ifdef NETINET_SUPP_in
#include <netinet/in.h>
#endif
#include <netdb.h>
#include <setjmp.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>
#include <sys/socket.h>
#include "core.h"
#include "netresolv.h"
enum {FALSE,TRUE};
const int RESOLVE_MAX1=RESOLVE_MAX - 1;
/*    NETRESOLV   - resolve INET addresses and return
                    the INET Hostnames

            Include a timeout of 60 sec. to resolve a name.
            If not resolved, discard the entry...

            Use STDIN to read from the SOCKETPAIR connection
            (i.e. don't care where it comes from...)
            Expect a struct to be sent in a specific format
            Return a struct to STDOUT in another format

*/

/* #define DEBUG 1  */
/* #define DDEBUG 1 */
extern int errno;
sigjmp_buf env;
#define SAVEMASK 1
int processone = 0;
int addedentries = 0;
int clearall = FALSE;
int oktocontinue = TRUE;
enum { START_SIG, STOP_SIG, JUMP_SIG, UNUSED};
enum { INIT, INSIDE_LOOP, WAITING_GETHOST, ADDING_ENTRIES, BUILD_RETURN };
int where_are_you = INIT;
int sig_in_spot = UNUSED;
int sig_time_spot = UNUSED;

FILE *dfp;

typedef void (*sigfunc) (int);

/*
   FOR RELIABLE SIGNAL HANDLING --- make sure a restart of
   system calls is performed when signals interrupt
 */
sigfunc
signal (int signo, sigfunc func)
{
  struct sigaction act, oact;

  act.sa_handler = func;
  sigemptyset (&act.sa_mask);
  act.sa_flags = 0;
  if (signo != SIGALRM)
    act.sa_flags |= SA_RESTART;
  if (sigaction (signo, &act, &oact) < 0)
    return (SIG_ERR);
  return (oact.sa_handler);
}

struct nqueue 
{
      struct resolvaddr resentry;
      struct nqueue *link;
};

struct nqueue *last, *first;
struct nqueue dum;  /* Dummy record header */
#define MAXENTRIES 400
struct resolvaddr entries[MAXENTRIES];

char *dbgaddr(u_int32_t val)
{
      unsigned char *p;
      static char buf[40];  /* Worst case scenario for %u conversions */
      
      p = (unsigned char *)&val;
      sprintf(buf,"%u.%u.%u.%u",p[0],p[1],p[2],p[3]);
      return(buf);
}

void addentry( struct resolvaddr *entry )
{
      struct nqueue *place;
#ifdef DEBUG
      fprintf(dfp,"Adding entry...netresolv... \n");
      fflush(dfp);
#endif
      place = malloc(sizeof(*place));
      place->resentry = *entry;
#ifdef DEBUG
      fprintf(dfp,"Added entry...netresolv... %s\n",dbgaddr(entry->inetaddr));
      fflush(dfp);
#endif
      place->link = NULL;
      last->link = place;
      last = place;
      processone++;
}

void delentry()
{
      struct nqueue *current;

#ifdef DEBUG
      fprintf(dfp,"Deleted entry...netresolv clearall=%d\n",clearall);
#endif
      current = first->link;
      if (last==first->link)
            last = first;
      if (current)
      {
            first->link = current->link;
            free(current);
      }
      processone--;
}

void deleteall()
{
      struct nqueue *current, *h;

#ifdef DEBUG
      fprintf(dfp,"Deleted all...netresolv clearall=%d\n",clearall);
#endif
      current = first->link;
      while (current)
      {
            first->link = current->link;
            h = current;
            current = first->link;
            free(h);
      }
      processone=0;
      dum.link = NULL;
      last = first = &dum;
      
}

void sigincatch(int sig)
{
      int status;
      sigset_t sigset, oldmask;

      sigprocmask(0,NULL,&sigset);
      sigaddset(&sigset,sig);
      sigprocmask(SIG_BLOCK,&sigset,&oldmask);
      sig_in_spot = START_SIG;
#ifdef DEBUG
      fprintf(dfp,"SIGNAL CAUGHT\n");
      fflush(dfp);
#endif
      do
      {
      if (addedentries<MAXENTRIES)
      {
      read(0,&entries[addedentries],sizeof(struct resolvaddr));
      status = errno;
          if (status != EWOULDBLOCK)
          {
#ifdef DEBUG
            fprintf(dfp,"ADDING ENTRY\n");
            fflush(dfp);
#endif
            if (entries[addedentries].inetaddr == 0L)
            {
                if (entries[addedentries].where == 0)
                {
                  clearall=TRUE;
#ifdef DDEBUG
            fprintf(dfp,"CLEARALL Issued, you are %d\n",where_are_you);
            fflush(dfp);
#endif
      /*          addedentries++; */
                    }
                else if (entries[addedentries].where == (char *)1)
                {
                    /* clearall=FALSE; */
#ifdef DDEBUG
            fprintf(dfp,"FINISHED Issued, not yet at CLEARALL false %d\n",where_are_you);
            fflush(dfp);
#endif
                  addedentries++; 

                }
            }
            else
            {
                  addedentries++;
            }     
          }
#ifdef DEBUG
          else
          {
            fprintf(dfp,"READ WOULD HAVE BLOCKED\n");
            fflush(dfp);
          }
#endif
      }
      } while (status != EWOULDBLOCK && addedentries<MAXENTRIES); 
      sigprocmask(SIG_SETMASK,&oldmask,NULL);
      sig_in_spot = STOP_SIG;

}

void sigtimecatch(int sig)
{
      sig_time_spot = START_SIG;
#ifdef DEBUG
      fprintf(dfp,"TIMEOUT SIGNAL CAUGHT\n");
      fflush(dfp);
#endif
      sig_time_spot = STOP_SIG;
      siglongjmp(env,1);      
}

void setupsignals()
{
      signal(SIGALRM, sigtimecatch);
      signal(SIGUSR1, sigincatch);
      signal(SIGUSR2, SIG_IGN);
}

int main()
{
      struct nqueue *top;
      struct nqueue cptop;
      struct gotname finalentry;
      struct hostent *res;
      unsigned char *p;
      u_int32_t *pu;
      int i;

#ifdef DDEBUG
      dfp = fopen("dbugfile","w");
      fprintf(dfp,"Starting NETRESOLV\n");
      fflush(dfp);
#endif
      dum.link = NULL;
      last = &dum;
      first = &dum;
      fcntl(0,F_SETFL,FNDELAY);
      setupsignals();
      while (1)
      {
            if (addedentries)
            {
                  where_are_you = ADDING_ENTRIES;
#ifdef DEBUG
                  fprintf(dfp,"Loop to ADD %d entries\n",addedentries);
                  fflush(dfp);
#endif
                  signal(SIGUSR1,SIG_IGN);
                  for (i=0;i<addedentries;i++)
                        addentry(&entries[i]);
                  addedentries = 0;
                  signal(SIGUSR1,sigincatch);
            }
            if (processone)
            {
#ifdef DEBUG
                  fprintf(dfp,"In processone section = %d\n",processone);
                  fflush(dfp);
#endif
                  top = first->link;
                  if (top)
                  {
                     cptop = *top;
                     if (sigsetjmp( env , SAVEMASK)==0)
                     {
                        alarm(60);  
                        p = (unsigned char *)&(cptop.resentry.inetaddr);
                        pu = (u_int32_t *)p;
#ifdef DEBUG
                  fprintf(dfp,"Actual Get host by address call\n");
                  fflush(dfp);
#endif
                        where_are_you = WAITING_GETHOST;          
                        if (*pu != 0L)
                        {
                           if (clearall)
                              res = NULL;
                           else
                              res = gethostbyaddr(p,
                                    sizeof(struct in_addr),AF_INET);
                        }
                        else
                              res = (struct hostent *)1;
                        alarm(0);
                        where_are_you = BUILD_RETURN;
                        /* Build return entry... */
                        if (res)
                        {
#ifdef DEBUG
                              fprintf(dfp,"FINAL ENTRY = %p  RES=%p\n",cptop.resentry.where,res);
                              fflush(dfp);
#endif
                              finalentry.where = cptop.resentry.where;
                              if (finalentry.where>(char *)1 &&
                                    res != (struct hostent *)1)
                              strncpy(finalentry.name,res->h_name,RESOLVE_MAX1);
                              else
                              {
#ifdef DDEBUG
                              fprintf(dfp,"SHOULD set clearall false\n");
                              fflush(dfp);
#endif
                                    finalentry.name[0]=0;
                                    if (finalentry.where == 
                                          (char *)1)
                                          clearall = FALSE;
#ifdef DDEBUG
                              else
                                {
                              fprintf(dfp,"NEVER HAPPENS\n");
                              fflush(dfp);
                              }
#endif
                                    
                              }
#ifdef DEBUG
                              fprintf(dfp,"Returning %s\n",finalentry.name);
                              fflush(dfp);
#endif
                              finalentry.name[RESOLVE_MAX1] = 0;
                              write(1,&finalentry,sizeof(finalentry));
                        /* Send signal to indicate ALL is ready */
                        kill(cptop.resentry.pid,SIGUSR2);
                        }
#ifdef DEBUG
                        else
                        {
                              fprintf(dfp,"Failed GETHOSTBYADDR with %d",errno);
                              fflush(dfp);
                        }
#endif
                                                            
                     }
                     else
                     {
                        /*  TIMED OUT */
#ifdef DEBUG
                  fprintf(dfp,"Timed out\n");
                  fflush(dfp);
#endif
                        
                        kill(cptop.resentry.pid,SIGUSR1);
                     }
                     delentry();                
                  }
#ifdef DEBUG
                  else
                  {
                  fprintf(dfp,"TOP NULL VALUE!!\n");
                  fflush(dfp);
                  
                  }
#endif
            }
            else              
               usleep(100);
            where_are_you = INSIDE_LOOP;
      }
      return(0);
}

Generated by  Doxygen 1.6.0   Back to index