home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume10 / ien116-server / nameserver.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-07-29  |  9.0 KB  |  345 lines

  1. #ifndef lint
  2.   static char *RCSid = "$Header: nameserver.c,v 2.3 87/06/24 15:02:59 mike Rel $";
  3. #endif
  4.  
  5. /* nameserver --
  6.    Use the IEN 116 protocol to respond to nameserver requests.
  7.  
  8.    Written by Michael I. Bushnell.
  9.    Copyright (c) 1987 Michael I. Bushnell
  10.    You are hereby granted permission to use this program however you wish,
  11.    including copying and distribution.  However, you are obligated not to sell
  12.    it or any part of it.  Anyone who obtains this program receives the right
  13.    to do the same.  This statement may not be removed from this program.
  14. */
  15.  
  16. /*
  17.  * $Source: /u1/staff/mike/src/nameserver/RCS/nameserver.c,v $
  18.  * $Revision: 2.3 $
  19.  * $Date: 87/06/24 15:02:59 $
  20.  * $State: Rel $
  21.  * $Author: mike $
  22.  * $Locker:  $
  23.  * $Log:    nameserver.c,v $
  24.  * Revision 2.3  87/06/24  15:02:59  mike
  25.  * Final preparations for release.  Addeed Copyright.
  26.  * 
  27.  * Revision 2.2  87/06/24  14:54:29  mike
  28.  * de-lintified.  Lint, stupidly, doesn't pick up the definition of h_errno f
  29.  * from libc.a.  Sigh.  Prepared for release.
  30.  * 
  31.  * Revision 2.1  87/06/24  14:48:14  mike
  32.  * Better comments.
  33.  * 
  34.  * Revision 2.0  87/06/23  16:55:03  mike
  35.  * Split it up into different functions.
  36.  * 
  37.  * Revision 1.9  87/06/23  16:14:09  mike
  38.  * Added stuff to divorce process from shell and control terminal.
  39.  * 
  40.  * Revision 1.8  87/06/19  16:59:36  mike
  41.  * Uses syslog instead of perror.
  42.  * Lots of symbolic constants.
  43.  * 
  44.  * Revision 1.7  87/06/19  14:43:49  mike
  45.  * Fixed bug... need to initialize addrlen to sizeof(hisname).
  46.  * 
  47.  * Revision 1.6  87/06/16  16:08:04  mike
  48.  * Changed all "sizeof (hisaddr)" to "addrlen."
  49.  * Still a bug...the last sendto is returning EINVAL???
  50.  * 
  51.  * Revision 1.5  87/06/16  15:57:07  mike
  52.  * Actually...you need to return the raw bytes.  So I changed it back.
  53.  * Also added bookoo error checking.
  54.  * 
  55.  * Revision 1.4  87/06/15  13:50:22  mike
  56.  * Fixed bug...need to cast the argument of inet_ntoa into a struct in_addr.
  57.  * 
  58.  * Revision 1.3  87/06/08  14:16:56  mike
  59.  * Uses a PORT number instead of system chosen default...now its 5001.
  60.  * 
  61.  * Revision 1.2  87/06/08  14:10:33  mike
  62.  * Now it compiles.
  63.  * 
  64.  * Revision 1.1  87/06/08  13:42:20  mike
  65.  * Initial revision
  66.  * 
  67.  */
  68.  
  69. #include <sys/file.h>
  70. #include <sgtty.h>
  71.  
  72. #include <signal.h>
  73. #include <syslog.h>
  74.  
  75. #include <sys/types.h>
  76. #include <sys/socket.h>
  77. #include <netinet/in.h>
  78. #include <netdb.h>
  79.  
  80. #include <stdio.h>
  81.  
  82. /* Generic constants */
  83. #define PORT 5001        /* Port for the server */
  84. #define BUFLEN 256        /* Length of input buffer */
  85. #define DEF_PROTO 0        /* Use default protocol */
  86. #define NO_FLAGS 0        /* No flags on recvfrom/sendto */
  87.  
  88. /* Message lengths */
  89. #define RET_MSG_LEN 6        /* Length of what we add to buf */
  90. #define ERR_MSG_LEN 3        /* Length of error messages */
  91.  
  92. /* Message types from IEN 116 */
  93. #define ADDR_REQ 1        /* Address Request */
  94. #define ADDR_ANS 2        /* Address Request Answer */
  95. #define ERR      3        /* Error */
  96.  
  97. /* Error types from IEN 116 */
  98. #define UNK_ERR  0        /* Unknown Error */
  99. #define HOST_UNK 1        /* Host Unknown */
  100. #define SYNT_ERR 2        /* Syntax Error */
  101.  
  102. char buf[BUFLEN];        /* Input/Output buffer */
  103. extern int errno, h_errno;
  104. extern char *sys_errlist[];
  105.  
  106. main()
  107. {
  108.   int sock;            /* Datagram socket */
  109.   struct sockaddr_in hisname;    /* Address of requestor */
  110.   int addrlen;            /* Length of his address */
  111.   struct hostent *hp, *gethostbyname();    /* Host inquired of */
  112.   char *name;            /* Name of the machine requested */
  113.   int msglen;            /* Length of the message received */
  114.   char *nameloc();
  115.  
  116.   setupsig();            /* Set up signal handling */
  117.   setuplog();            /* Set up the syslog connection */
  118.   divorce();            /* Divorce ourselves from terminal and shell */
  119.   sock = makesocket();        /* make and bind the socket */
  120.  
  121.   addrlen = sizeof(hisname);    
  122.  
  123.   /* Main loop */
  124.  restart:
  125.   while (1)
  126.     {
  127.       /* Read a message */
  128.       msglen = recvfrom(sock, buf, BUFLEN - RET_MSG_LEN,
  129.             NO_FLAGS, (struct sockaddr *)&hisname, &addrlen);
  130.       if (msglen == -1)
  131.     {
  132.       syslog(LOG_ERR, "Error on incoming message: %s\n", 
  133.          sys_errlist[errno]);
  134.       goto restart;
  135.     }
  136.  
  137.       /* Find the name */
  138.       name = nameloc(buf, BUFLEN, msglen, &hisname, addrlen, sock);
  139.       if ((int) name == -1) 
  140.     goto restart;
  141.  
  142.  
  143.       /* Get the host entry */
  144.       if ((hp = gethostbyname(name))== NULL)
  145.     {
  146.       /* Send error message */
  147.       buf[msglen] = ERR;    
  148.       buf[msglen+1] = ERR_MSG_LEN;
  149.       if (h_errno == HOST_NOT_FOUND ||
  150.           h_errno == TRY_AGAIN ||
  151.           h_errno == NO_ADDRESS) 
  152.         buf[msglen+2] = HOST_UNK; 
  153.       else
  154.         buf[msglen+2] = UNK_ERR; 
  155.       if (sendto(sock, buf, msglen+ERR_MSG_LEN, NO_FLAGS, 
  156.              (struct sockaddr *)&hisname, addrlen)==-1)
  157.         {
  158.           syslog(LOG_ERR, "Error sending error 3: %s\n", sys_errlist[errno]);
  159.           goto restart;
  160.         }  
  161.     }
  162.       else
  163.     {
  164.       /* Send the reply */
  165.       buf[msglen] = ADDR_ANS;
  166.       buf[msglen+1] = RET_MSG_LEN;
  167.       buf[msglen+2] = hp->h_addr_list[0][0];
  168.       buf[msglen+3] = hp->h_addr_list[0][1];
  169.       buf[msglen+4] = hp->h_addr_list[0][2];
  170.       buf[msglen+5] = hp->h_addr_list[0][3];
  171.  
  172.       if (sendto(sock, buf, msglen+RET_MSG_LEN, NO_FLAGS, 
  173.              (struct sockaddr *)&hisname, addrlen)==-1)
  174.         {
  175.           syslog(LOG_ERR, "Error sending reply: %s\n", sys_errlist[errno]);
  176.           goto restart;
  177.         }
  178.     }
  179.     }
  180. }
  181.  
  182.  
  183. /* setupsig -- Set all signals to be ignored.  Those which cannot be ignored
  184.    will be left at the default. */
  185. setupsig()
  186. {
  187.   int i;            /* Index of signals */
  188.   
  189.   for (i=0; i < NSIG; ++i)
  190.     (void) signal(i, SIG_IGN);
  191. }
  192.   
  193.  
  194. /* setuplog -- set up the syslog connection */
  195. setuplog()
  196. {
  197.   openlog("nameserver", LOG_PID | LOG_CONS, LOG_DAEMON);
  198. }
  199.  
  200.  
  201. /* divorce -- Divorce ourselves from the terminal and the shell */
  202. divorce()
  203. {
  204.   int term;            /* Terminal filed */
  205.  
  206.   /* First the shell */
  207.   switch(fork()) 
  208.     {
  209.     case -1:
  210.       syslog(LOG_CRIT, "Cannot fork: %s\n", sys_errlist[errno]);
  211.       exit(1);
  212.       break;
  213.     case 0:
  214.       break;
  215.     default:
  216.       exit(0);
  217.       break;
  218.     }
  219.  
  220.   /* Now the files */
  221.   /* POTENTIAL BUG-- ASSUMES THAT THE TERMINAL IS ONLY OPEN ON FILEDS 0,1,2 */
  222.   (void) close (0);
  223.   (void) close (1);
  224.   (void) close (2);
  225.   /* Now the terminal */
  226.   if ((term = open("/dev/tty", O_RDWR, 0)) == -1)
  227.     {
  228.       syslog(LOG_CRIT, "Cannot open /dev/tty: %s\n", sys_errlist[errno]);
  229.       exit(1);
  230.     }
  231.   if (ioctl(term, TIOCNOTTY, (char *) 0) == -1)
  232.     {
  233.       syslog(LOG_CRIT, "Cannot divorce from control terminal: %s\n", 
  234.          sys_errlist[errno]);
  235.       exit(1);
  236.     }
  237.   (void) close(term);
  238. }
  239.  
  240.  
  241. /* makesocket -- return the filed of a new bound socket */
  242. makesocket()
  243. {
  244.   int sock;            /* Socket */
  245.   struct sockaddr_in ourname;    /* Our name */
  246.  
  247.   /* create the socket */
  248.   sock = socket(AF_INET, SOCK_DGRAM, DEF_PROTO);
  249.   if (sock < 0)
  250.     {
  251.       syslog(LOG_CRIT, "Error opening socket: %s\n", sys_errlist[errno]);
  252.       exit(1);
  253.     }
  254.   ourname.sin_family = AF_INET;
  255.   ourname.sin_port = PORT;
  256.   ourname.sin_addr.s_addr = INADDR_ANY;
  257.   if (bind(sock, &ourname, sizeof(ourname)))
  258.  
  259.     {
  260.       syslog(LOG_CRIT, "Error binding socket: %s\n", sys_errlist[errno]);
  261.       exit(1);
  262.     }
  263.   return sock;
  264. }  
  265.  
  266.  
  267. /* nameloc -- return the address of a null-terminated string which is the
  268.    name to be looked up.  Report syntax errors to reportto through sock.
  269.    If an error occurs, return (char *) -1.  If an error occurs, buf will be 
  270.    changed. */
  271. char *
  272. nameloc(buf, buflen, msglen, reportto, addrlen, sock)
  273.      char *buf;            /* Buffer holding the request */
  274.      int buflen,        /* Length of the buffer */
  275.        msglen,            /* Length of the message in the buffer */
  276.        sock,            /* Socket for error replies */
  277.        addrlen;            /* Length of reportto */
  278.      struct sockaddr_in *reportto; /* Who we report errors to */
  279. {
  280.   char *name;            /* Address of the name */
  281.   int code;            /* Type of request */
  282.  
  283.   buf[msglen] = '\0';
  284.   /* Check type */      
  285.   code = buf[0];
  286.   if (code != ADDR_REQ)
  287.     if (code !=ADDR_ANS && code !=ERR)
  288.       {
  289.     /* Send error message */
  290.     buf[0] = ERR;    
  291.     buf[1] = ERR_MSG_LEN;
  292.     buf[2] = SYNT_ERR;
  293.     if (sendto(sock, buf, ERR_MSG_LEN, NO_FLAGS, 
  294.            (struct sockaddr *)&reportto, addrlen)==-1)
  295.       {
  296.         syslog(LOG_ERR, "Error sending error 0: %s\n", sys_errlist[errno]);
  297.         return (char *) -1;
  298.       }        
  299.       }
  300.     else
  301.       return (char *) -1;
  302.   
  303.   /* Put name at the start of a null-terminated string */
  304.   if (buf[2]!='!')
  305.     name=buf+2;
  306.   else
  307.     {
  308.       for(name=buf+2; *name!='!'; ++name)
  309.     if (name-buf >= buflen)
  310.       {            
  311.         /* Send error packet */
  312.         buf[0] = ERR;
  313.         buf[1] = ERR_MSG_LEN;
  314.         buf[2] = SYNT_ERR;
  315.         if (sendto(sock, buf, ERR_MSG_LEN, NO_FLAGS, 
  316.                (struct sockaddr *)&reportto, addrlen)==-1)
  317.           {
  318.         syslog(LOG_ERR, "Error sending error 1: %s\n", 
  319.                sys_errlist[errno]);
  320.         return (char *) -1;
  321.           }
  322.       }
  323.       for(++name; *name!='!'; ++name)
  324.     if (name-buf >= buflen)
  325.       {            
  326.         /* Send error packet */
  327.         buf[0] = ERR;
  328.         buf[1] = ERR_MSG_LEN;
  329.         buf[2] = SYNT_ERR;
  330.         if (sendto(sock, buf, ERR_MSG_LEN, NO_FLAGS, 
  331.                (struct sockaddr *)&reportto, addrlen)==-1)
  332.           {
  333.         syslog(LOG_ERR, "Error sending error 2: %s\n", 
  334.                sys_errlist[errno]);
  335.         return (char *) -1;
  336.           }
  337.       }
  338.       ++name;
  339.     }
  340.   return name;
  341. }
  342.  
  343.  
  344.  
  345.