pdirt/data/
pdirt/data/HELP/
pdirt/data/HELP/0/
pdirt/data/HELP/F/
pdirt/data/HELP/G/
pdirt/data/HELP/H/
pdirt/data/HELP/J/
pdirt/data/HELP/K/
pdirt/data/HELP/O/
pdirt/data/HELP/Q/
pdirt/data/HELP/R/
pdirt/data/HELP/U/
pdirt/data/HELP/V/
pdirt/data/HELP/Y/
pdirt/data/HELP/Z/
pdirt/data/MESSAGES/
pdirt/data/POWERINFO/
pdirt/data/WIZ_ZONES/
pdirt/drv/
pdirt/drv/bin/
pdirt/drv/compiler/converter/
pdirt/drv/compiler/libs/
pdirt/drv/compiler/scripts/
pdirt/drv/include/AberChat/
pdirt/drv/include/InterMud/
pdirt/drv/include/machine/
pdirt/drv/src/InterMud/
pdirt/drv/src/Players/
pdirt/drv/utils/UAFPort/
pdirt/drv/utils/dnsresolv/
pdirt/drv/utils/gdbm/
/******************************************************************************
 ** Project    : pDirt (Aber IV Daemon)
 ** Module     : utils/dnsresolv/dns.c (MUDDNS)
 ** Description: The 2nd part to DNS asynchrone lookup. It will read a records
 **              of 19 bytes and return records of 120 bytes.
 **              INPUT: <nr>:<ip number>.... May not fill the complete 19 bytes
 **                     but it expects 19 bytes!!
 **              OUTPUT: <nr>:<hostnumber>... Again.. it will write 120 bytes,
 **                     so expect 120 bytes!
 **              nr = the socket number inside the mud.
 ** Author     : Peter Eussen
 ** Date       : 6 Dec 1997
 ** Version    : 1.0
 ****************************************************************************/
#include "kernel.h"
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <netdb.h>
#include <signal.h>
#include <unistd.h>
#include "trie.h"


#define SERVERPORT	12000		/* Port the MudDNS listens to */
#define BUFFERDNS      			/* Buffer IP's or not? undef 
					 * for low mem machines.
					 */

int makesock(void);
void read_request(int fd);
void new_conn(int mainfd);
int daemonize(void);
void openLog(void);


fd_set input_set,all_set;
int    width;
FILE   *logfile;

int main()
{  int main_sock,fd,numavail;

   if (daemonize() == -1)
   {  printf("Failed to daemonize.\n");
      return -2;
   }
  
   fclose(stderr);
   fclose(stdout);
   fclose(stdin);
   openLog();
 
   if ((main_sock = makesock()) == -1)
   {  fprintf(logfile,"BOOT: Could not connect to socket. Already running?\n");
      fclose(logfile);
      return -1;
   }

   width = main_sock+1;

   FD_ZERO(&input_set);
   FD_ZERO(&all_set);
   FD_SET(main_sock,&input_set);
   FD_SET(main_sock,&all_set);
   
   while (1) 
   {   input_set = all_set;
       numavail = select(width,&input_set,NULL,NULL,NULL);
       for (fd = 0; numavail > 0; fd++)
       {   if (FD_ISSET(fd,&input_set))
           {   if (fd == main_sock)
                  new_conn(fd);
               else
                  read_request(fd);
               numavail--;
           }
       }
   }
   return 0;
}

int makesock(void) {
  int sock;
  char opt = 1;
  struct sockaddr_in sin;

  if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
    fprintf(logfile,"BOOT: Unable to create socket.\n");
    return(-1);
  }

  setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
 
  sin.sin_family = AF_INET;
  sin.sin_port = htons (SERVERPORT);
  sin.sin_addr.s_addr = htonl(INADDR_ANY);

  if (bind(sock, (struct sockaddr *) &sin, sizeof (sin)) == -1) {
    fprintf(logfile,"BOOT: MudDNS, error in bind.\n");
    return(-1);
  }
  listen(sock, 10);
  fprintf(logfile,"CONNECT: MudDNS connected to port %d\n",SERVERPORT); 
  return(sock);
}

void new_conn(int mainfd) {
  int fd, sin_len;
  struct sockaddr_in sin;
  struct hostent *h;

  bzero ((char *) &sin, sizeof (struct sockaddr_in));
  sin_len = sizeof (struct sockaddr_in);

  if ((fd = accept (mainfd, (struct sockaddr *) &sin, &sin_len)) < 0) {
    fprintf(logfile,"CONN: accept failed.\n");
    return;
  }
  if (fcntl (fd, F_SETFL, FNDELAY) == -1) { 
    perror("fcntl()");
    return;
  }

  h = gethostbyaddr((char *)&sin.sin_addr, sizeof(sin.sin_addr), AF_INET);
 
  if (!h) {
    FD_CLR(fd,&all_set);
    close(fd);
    return;
  }

  fprintf(logfile,"CONN: Connection from %s accepted\n",h->h_name);
  FD_SET(fd,&all_set);
  if (fd >= width)
    width = fd + 1;
}

void read_request(int fd)
{  char line[19];
   char outline[120];
   char ip[16];
   int  plr;
   char *res;
   int num_read = read(fd,line,19);
   unsigned long int inetnum;
   struct hostent *h;
   
   if (num_read < 1) 
   {  printf("Closing Connection.\n");
      FD_CLR(fd,&all_set);
      close(fd);
      return;
   }
 
   sscanf(line,"%d:%s",&plr,ip);

   if (plr < 0 || ip == NULL)
       return;
#ifdef BUFFERDNS
   else
   {   res = trieSearch(ip);
   
       if (res == NULL)
       {   inetnum = inet_addr(ip);
           h = gethostbyaddr((char *)&inetnum, sizeof(inetnum), AF_INET);
           if (h)
           {   res = (char *)h->h_name;
           }
           else
              res = ip;
           insertTrie(ip,res);
       }
       sprintf(outline,"%d:%s ",plr,res);
       outline[strlen(outline)] = '\0';
       write(fd,outline,120);
   }   
#else
   else
   { 
       inetnum = inet_addr(ip);
       h = gethostbyaddr((char *)&inetnum, sizeof(inetnum), AF_INET);
       if (h)
           res = (char *)h->h_name;
       else
           res = ip;
       sprintf(outline,"%d:%s ",plr,res);
       outline[strlen(outline)] = '\0';
       write(fd,outline,120);
   }   
#endif
}

void term_handler(int sig)
{  fprintf(logfile,"END: End session.\n");
   fclose(logfile);
   exit(0);
}

void set_sighandlers(void)
{   signal(SIGALRM,SIG_IGN);
    signal(SIGABRT,SIG_IGN);
    signal(SIGQUIT,SIG_IGN);
    signal(SIGHUP,SIG_IGN);
    signal(SIGTERM,term_handler);
}

int daemonize(void)
{   int pid;

    set_sighandlers();

    switch((pid = fork())) {
    case 0 : break;
    case -1: perror("Deamonize()"); return -1;
    default:
	fflush(stdout);
	fflush(stderr);
        exit(0);		/* Die silently */
    }
    return 0;
}

void openLog(void)
{  logfile=fopen(DATA_DIR"/LOGS/muddns.log","a");
}