home *** CD-ROM | disk | FTP | other *** search
- #ifndef lint
- static char *RCSid = "$Header: nameserver.c,v 2.3 87/06/24 15:02:59 mike Rel $";
- #endif
-
- /* nameserver --
- Use the IEN 116 protocol to respond to nameserver requests.
-
- Written by Michael I. Bushnell.
- Copyright (c) 1987 Michael I. Bushnell
- You are hereby granted permission to use this program however you wish,
- including copying and distribution. However, you are obligated not to sell
- it or any part of it. Anyone who obtains this program receives the right
- to do the same. This statement may not be removed from this program.
- */
-
- /*
- * $Source: /u1/staff/mike/src/nameserver/RCS/nameserver.c,v $
- * $Revision: 2.3 $
- * $Date: 87/06/24 15:02:59 $
- * $State: Rel $
- * $Author: mike $
- * $Locker: $
- * $Log: nameserver.c,v $
- * Revision 2.3 87/06/24 15:02:59 mike
- * Final preparations for release. Addeed Copyright.
- *
- * Revision 2.2 87/06/24 14:54:29 mike
- * de-lintified. Lint, stupidly, doesn't pick up the definition of h_errno f
- * from libc.a. Sigh. Prepared for release.
- *
- * Revision 2.1 87/06/24 14:48:14 mike
- * Better comments.
- *
- * Revision 2.0 87/06/23 16:55:03 mike
- * Split it up into different functions.
- *
- * Revision 1.9 87/06/23 16:14:09 mike
- * Added stuff to divorce process from shell and control terminal.
- *
- * Revision 1.8 87/06/19 16:59:36 mike
- * Uses syslog instead of perror.
- * Lots of symbolic constants.
- *
- * Revision 1.7 87/06/19 14:43:49 mike
- * Fixed bug... need to initialize addrlen to sizeof(hisname).
- *
- * Revision 1.6 87/06/16 16:08:04 mike
- * Changed all "sizeof (hisaddr)" to "addrlen."
- * Still a bug...the last sendto is returning EINVAL???
- *
- * Revision 1.5 87/06/16 15:57:07 mike
- * Actually...you need to return the raw bytes. So I changed it back.
- * Also added bookoo error checking.
- *
- * Revision 1.4 87/06/15 13:50:22 mike
- * Fixed bug...need to cast the argument of inet_ntoa into a struct in_addr.
- *
- * Revision 1.3 87/06/08 14:16:56 mike
- * Uses a PORT number instead of system chosen default...now its 5001.
- *
- * Revision 1.2 87/06/08 14:10:33 mike
- * Now it compiles.
- *
- * Revision 1.1 87/06/08 13:42:20 mike
- * Initial revision
- *
- */
-
- #include <sys/file.h>
- #include <sgtty.h>
-
- #include <signal.h>
- #include <syslog.h>
-
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <netdb.h>
-
- #include <stdio.h>
-
- /* Generic constants */
- #define PORT 5001 /* Port for the server */
- #define BUFLEN 256 /* Length of input buffer */
- #define DEF_PROTO 0 /* Use default protocol */
- #define NO_FLAGS 0 /* No flags on recvfrom/sendto */
-
- /* Message lengths */
- #define RET_MSG_LEN 6 /* Length of what we add to buf */
- #define ERR_MSG_LEN 3 /* Length of error messages */
-
- /* Message types from IEN 116 */
- #define ADDR_REQ 1 /* Address Request */
- #define ADDR_ANS 2 /* Address Request Answer */
- #define ERR 3 /* Error */
-
- /* Error types from IEN 116 */
- #define UNK_ERR 0 /* Unknown Error */
- #define HOST_UNK 1 /* Host Unknown */
- #define SYNT_ERR 2 /* Syntax Error */
-
- char buf[BUFLEN]; /* Input/Output buffer */
- extern int errno, h_errno;
- extern char *sys_errlist[];
-
- main()
- {
- int sock; /* Datagram socket */
- struct sockaddr_in hisname; /* Address of requestor */
- int addrlen; /* Length of his address */
- struct hostent *hp, *gethostbyname(); /* Host inquired of */
- char *name; /* Name of the machine requested */
- int msglen; /* Length of the message received */
- char *nameloc();
-
- setupsig(); /* Set up signal handling */
- setuplog(); /* Set up the syslog connection */
- divorce(); /* Divorce ourselves from terminal and shell */
- sock = makesocket(); /* make and bind the socket */
-
- addrlen = sizeof(hisname);
-
- /* Main loop */
- restart:
- while (1)
- {
- /* Read a message */
- msglen = recvfrom(sock, buf, BUFLEN - RET_MSG_LEN,
- NO_FLAGS, (struct sockaddr *)&hisname, &addrlen);
- if (msglen == -1)
- {
- syslog(LOG_ERR, "Error on incoming message: %s\n",
- sys_errlist[errno]);
- goto restart;
- }
-
- /* Find the name */
- name = nameloc(buf, BUFLEN, msglen, &hisname, addrlen, sock);
- if ((int) name == -1)
- goto restart;
-
-
- /* Get the host entry */
- if ((hp = gethostbyname(name))== NULL)
- {
- /* Send error message */
- buf[msglen] = ERR;
- buf[msglen+1] = ERR_MSG_LEN;
- if (h_errno == HOST_NOT_FOUND ||
- h_errno == TRY_AGAIN ||
- h_errno == NO_ADDRESS)
- buf[msglen+2] = HOST_UNK;
- else
- buf[msglen+2] = UNK_ERR;
- if (sendto(sock, buf, msglen+ERR_MSG_LEN, NO_FLAGS,
- (struct sockaddr *)&hisname, addrlen)==-1)
- {
- syslog(LOG_ERR, "Error sending error 3: %s\n", sys_errlist[errno]);
- goto restart;
- }
- }
- else
- {
- /* Send the reply */
- buf[msglen] = ADDR_ANS;
- buf[msglen+1] = RET_MSG_LEN;
- buf[msglen+2] = hp->h_addr_list[0][0];
- buf[msglen+3] = hp->h_addr_list[0][1];
- buf[msglen+4] = hp->h_addr_list[0][2];
- buf[msglen+5] = hp->h_addr_list[0][3];
-
- if (sendto(sock, buf, msglen+RET_MSG_LEN, NO_FLAGS,
- (struct sockaddr *)&hisname, addrlen)==-1)
- {
- syslog(LOG_ERR, "Error sending reply: %s\n", sys_errlist[errno]);
- goto restart;
- }
- }
- }
- }
-
-
- /* setupsig -- Set all signals to be ignored. Those which cannot be ignored
- will be left at the default. */
- setupsig()
- {
- int i; /* Index of signals */
-
- for (i=0; i < NSIG; ++i)
- (void) signal(i, SIG_IGN);
- }
-
-
- /* setuplog -- set up the syslog connection */
- setuplog()
- {
- openlog("nameserver", LOG_PID | LOG_CONS, LOG_DAEMON);
- }
-
-
- /* divorce -- Divorce ourselves from the terminal and the shell */
- divorce()
- {
- int term; /* Terminal filed */
-
- /* First the shell */
- switch(fork())
- {
- case -1:
- syslog(LOG_CRIT, "Cannot fork: %s\n", sys_errlist[errno]);
- exit(1);
- break;
- case 0:
- break;
- default:
- exit(0);
- break;
- }
-
- /* Now the files */
- /* POTENTIAL BUG-- ASSUMES THAT THE TERMINAL IS ONLY OPEN ON FILEDS 0,1,2 */
- (void) close (0);
- (void) close (1);
- (void) close (2);
- /* Now the terminal */
- if ((term = open("/dev/tty", O_RDWR, 0)) == -1)
- {
- syslog(LOG_CRIT, "Cannot open /dev/tty: %s\n", sys_errlist[errno]);
- exit(1);
- }
- if (ioctl(term, TIOCNOTTY, (char *) 0) == -1)
- {
- syslog(LOG_CRIT, "Cannot divorce from control terminal: %s\n",
- sys_errlist[errno]);
- exit(1);
- }
- (void) close(term);
- }
-
-
- /* makesocket -- return the filed of a new bound socket */
- makesocket()
- {
- int sock; /* Socket */
- struct sockaddr_in ourname; /* Our name */
-
- /* create the socket */
- sock = socket(AF_INET, SOCK_DGRAM, DEF_PROTO);
- if (sock < 0)
- {
- syslog(LOG_CRIT, "Error opening socket: %s\n", sys_errlist[errno]);
- exit(1);
- }
- ourname.sin_family = AF_INET;
- ourname.sin_port = PORT;
- ourname.sin_addr.s_addr = INADDR_ANY;
- if (bind(sock, &ourname, sizeof(ourname)))
-
- {
- syslog(LOG_CRIT, "Error binding socket: %s\n", sys_errlist[errno]);
- exit(1);
- }
- return sock;
- }
-
-
- /* nameloc -- return the address of a null-terminated string which is the
- name to be looked up. Report syntax errors to reportto through sock.
- If an error occurs, return (char *) -1. If an error occurs, buf will be
- changed. */
- char *
- nameloc(buf, buflen, msglen, reportto, addrlen, sock)
- char *buf; /* Buffer holding the request */
- int buflen, /* Length of the buffer */
- msglen, /* Length of the message in the buffer */
- sock, /* Socket for error replies */
- addrlen; /* Length of reportto */
- struct sockaddr_in *reportto; /* Who we report errors to */
- {
- char *name; /* Address of the name */
- int code; /* Type of request */
-
- buf[msglen] = '\0';
- /* Check type */
- code = buf[0];
- if (code != ADDR_REQ)
- if (code !=ADDR_ANS && code !=ERR)
- {
- /* Send error message */
- buf[0] = ERR;
- buf[1] = ERR_MSG_LEN;
- buf[2] = SYNT_ERR;
- if (sendto(sock, buf, ERR_MSG_LEN, NO_FLAGS,
- (struct sockaddr *)&reportto, addrlen)==-1)
- {
- syslog(LOG_ERR, "Error sending error 0: %s\n", sys_errlist[errno]);
- return (char *) -1;
- }
- }
- else
- return (char *) -1;
-
- /* Put name at the start of a null-terminated string */
- if (buf[2]!='!')
- name=buf+2;
- else
- {
- for(name=buf+2; *name!='!'; ++name)
- if (name-buf >= buflen)
- {
- /* Send error packet */
- buf[0] = ERR;
- buf[1] = ERR_MSG_LEN;
- buf[2] = SYNT_ERR;
- if (sendto(sock, buf, ERR_MSG_LEN, NO_FLAGS,
- (struct sockaddr *)&reportto, addrlen)==-1)
- {
- syslog(LOG_ERR, "Error sending error 1: %s\n",
- sys_errlist[errno]);
- return (char *) -1;
- }
- }
- for(++name; *name!='!'; ++name)
- if (name-buf >= buflen)
- {
- /* Send error packet */
- buf[0] = ERR;
- buf[1] = ERR_MSG_LEN;
- buf[2] = SYNT_ERR;
- if (sendto(sock, buf, ERR_MSG_LEN, NO_FLAGS,
- (struct sockaddr *)&reportto, addrlen)==-1)
- {
- syslog(LOG_ERR, "Error sending error 2: %s\n",
- sys_errlist[errno]);
- return (char *) -1;
- }
- }
- ++name;
- }
- return name;
- }
-
-
-
-