[comp.sources.unix] v10i073: IEN116 Nameserver

rs@uunet.UU.NET (Rich Salz) (07/31/87)

Submitted-by: mike@turing.unm.edu (Michael I. Bushnell)
Posting-number: Volume 10, Issue 73
Archive-name: ien116-server

[ This provides an old-style (non-domain) nameserver; Mike says it's
  useful for Bridge terminal concentrators, but I wouldn't know.  I
  once wrote something similar for the MIT PC/IP  package.  --r$  ]

#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	Makefile
#	README
#	driver.c
#	nameserver.c
#	nameserver.8
export PATH; PATH=/bin:$PATH
echo shar: extracting "'Makefile'" '(333 characters)'
if test -f 'Makefile'
then
	echo shar: will not over-write existing file "'Makefile'"
else
sed 's/^X//' << \SHAR_EOF > 'Makefile'
X# Makefile for the IEN116 datagram server.
X
X.SUFFIXES: .c,v
XVPATH=RCS
X
XCFLAGS=-g
XNOBJECTS=nameserver.o
XDOBJECTS=driver.o
X
Xall: nameserver driver
X
Xnameserver: $(NOBJECTS)
X	$(CC) $(CFLAGS) -o nameserver $(NOBJECTS)
X
Xdriver: $(DOBJECTS)
X	$(CC) $(CFLAGS) -o driver $(DOBJECTS)
X
X.c,v.o:
X	co -q $*.c
X	$(CC) $(CFLAGS) -c $*.c
X	rm -f $*.c
X
X
SHAR_EOF
if test 333 -ne "`wc -c < 'Makefile'`"
then
	echo shar: error transmitting "'Makefile'" '(should have been 333 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'README'" '(603 characters)'
if test -f 'README'
then
	echo shar: will not over-write existing file "'README'"
else
sed 's/^X//' << \SHAR_EOF > 'README'
X
XThis program implements the IEN 116 nameserver protocol.  A driver is provided,
Xbut it will ask for a machine probably not on your network, so it should be
Xmodified.  This program is of use primarily for Bridge terminal servers, many
Xof which use this protocol in requesting machine addresses.  For further
Xinformation, see the document itself.
X
XTo compile, the command:
X	% make
Xis sufficient.  This will build the nameserver and the driver.
X
XIt is only known that this works on a 4.3BSD Vax, but it is likely that it 
Xwill function on any compatable UNIX(*) machine.
X
X(*) UNIX is a trademark of AT&T.
SHAR_EOF
if test 603 -ne "`wc -c < 'README'`"
then
	echo shar: error transmitting "'README'" '(should have been 603 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'driver.c'" '(2605 characters)'
if test -f 'driver.c'
then
	echo shar: will not over-write existing file "'driver.c'"
else
sed 's/^X//' << \SHAR_EOF > 'driver.c'
X#ifndef lint
X  static char *RCSid = "$Header: driver.c,v 1.5 87/06/24 15:02:38 mike Rel $";
X#endif
X
X/* driver --
X   drive the IEN 116 nameserver.
X
X   Written by Michael I. Bushnell.
X   Copyright (c) 1987 Michael I. Bushnell
X   You are hereby granted permission to use this program however you wish, 
X   including copying and distribution.  However, you are obligated not to sell
X   it or any part of it.  Anyone who obtains this program receives the right
X   to do the same.  This statement may not be removed from this program.
X*/
X
X/*
X * $Source: /u1/staff/mike/src/nameserver/RCS/driver.c,v $
X * $Revision: 1.5 $
X * $Date: 87/06/24 15:02:38 $
X * $State: Rel $
X * $Author: mike $
X * $Locker:  $
X * $Log:	driver.c,v $
X * Revision 1.5  87/06/24  15:02:38  mike
X * Prepared for final release.  Added Copyright.
X * 
X * Revision 1.4  87/06/19  17:00:05  mike
X * More toying around.
X * 
X * Revision 1.3  87/06/19  14:44:13  mike
X * Toyed around.
X * 
X * Revision 1.2  87/06/15  13:50:51  mike
X * Changed the host it asks for
X * 
X * Revision 1.1  87/06/12  13:42:29  mike
X * Initial revision
X * 
X */
X
X#include <sys/types.h>
X#include <sys/socket.h>
X#include <netinet/in.h>
X#include <stdio.h>
X#include <netdb.h>
X
X#define PORT 5001
X#define BUFLEN 256
Xchar buf[BUFLEN];
X
X/* Driver for the IEN 116 nameserver */
X
Xmain()
X{
X  int sock;			/* Datagram socket */
X  struct sockaddr_in from;	/* Where we got the reply from */
X  struct sockaddr_in server;	/* Server's address */
X  struct sockaddr_in ourname;	/* Our address */
X  int addrlen;			/* Address length */
X  int c,i;			/* Generic counters */
X  
X
X  sock = socket(AF_INET, SOCK_DGRAM, 0);
X  if (sock < 0)
X    {
X      perror("driver: opening socket");
X      exit (1);
X    }
X  ourname.sin_family = AF_INET;
X  ourname.sin_port = 0;
X  ourname.sin_addr.s_addr = INADDR_ANY;
X  if (bind(sock, (struct sockaddr *)&ourname, sizeof(ourname)))
X    {
X      perror("driver: binding socket");
X      exit(1);
X    }
X  
X  server.sin_family = AF_INET;
X  server.sin_port = PORT;
X  server.sin_addr.s_addr = INADDR_ANY;
X
X/* stick in whatever machine you want here */
X  buf[0] = 1;			/* Code for request */
X  buf[1] = 8;			/* Length of message */
X  buf[2] = 'c';
X  buf[3] = 'h';
X  buf[4] = 'a';
X  buf[5] = 'r';
X  buf[6] = 'o';
X  buf[7] = 'n';
X
X  if (sendto(sock, buf, 8, 0, (struct sockaddr *)&server, sizeof(server))==-1)
X    {
X      perror("driver: sending message");
X      exit(1);
X    }
X
X  if ((c=recvfrom(sock, buf, BUFLEN, 0, (struct sockaddr *)&from, sizeof(from)))==-1)
X    {
X      perror("driver: getting message");
X      exit(1);
X    }
X
X  for(i=0;i<c; ++i)
X    putchar(buf[i]);
X}
SHAR_EOF
if test 2605 -ne "`wc -c < 'driver.c'`"
then
	echo shar: error transmitting "'driver.c'" '(should have been 2605 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'nameserver.c'" '(9178 characters)'
if test -f 'nameserver.c'
then
	echo shar: will not over-write existing file "'nameserver.c'"
else
sed 's/^X//' << \SHAR_EOF > 'nameserver.c'
X#ifndef lint
X  static char *RCSid = "$Header: nameserver.c,v 2.3 87/06/24 15:02:59 mike Rel $";
X#endif
X
X/* nameserver --
X   Use the IEN 116 protocol to respond to nameserver requests.
X
X   Written by Michael I. Bushnell.
X   Copyright (c) 1987 Michael I. Bushnell
X   You are hereby granted permission to use this program however you wish,
X   including copying and distribution.  However, you are obligated not to sell
X   it or any part of it.  Anyone who obtains this program receives the right
X   to do the same.  This statement may not be removed from this program.
X*/
X
X/*
X * $Source: /u1/staff/mike/src/nameserver/RCS/nameserver.c,v $
X * $Revision: 2.3 $
X * $Date: 87/06/24 15:02:59 $
X * $State: Rel $
X * $Author: mike $
X * $Locker:  $
X * $Log:	nameserver.c,v $
X * Revision 2.3  87/06/24  15:02:59  mike
X * Final preparations for release.  Addeed Copyright.
X * 
X * Revision 2.2  87/06/24  14:54:29  mike
X * de-lintified.  Lint, stupidly, doesn't pick up the definition of h_errno f
X * from libc.a.  Sigh.  Prepared for release.
X * 
X * Revision 2.1  87/06/24  14:48:14  mike
X * Better comments.
X * 
X * Revision 2.0  87/06/23  16:55:03  mike
X * Split it up into different functions.
X * 
X * Revision 1.9  87/06/23  16:14:09  mike
X * Added stuff to divorce process from shell and control terminal.
X * 
X * Revision 1.8  87/06/19  16:59:36  mike
X * Uses syslog instead of perror.
X * Lots of symbolic constants.
X * 
X * Revision 1.7  87/06/19  14:43:49  mike
X * Fixed bug... need to initialize addrlen to sizeof(hisname).
X * 
X * Revision 1.6  87/06/16  16:08:04  mike
X * Changed all "sizeof (hisaddr)" to "addrlen."
X * Still a bug...the last sendto is returning EINVAL???
X * 
X * Revision 1.5  87/06/16  15:57:07  mike
X * Actually...you need to return the raw bytes.  So I changed it back.
X * Also added bookoo error checking.
X * 
X * Revision 1.4  87/06/15  13:50:22  mike
X * Fixed bug...need to cast the argument of inet_ntoa into a struct in_addr.
X * 
X * Revision 1.3  87/06/08  14:16:56  mike
X * Uses a PORT number instead of system chosen default...now its 5001.
X * 
X * Revision 1.2  87/06/08  14:10:33  mike
X * Now it compiles.
X * 
X * Revision 1.1  87/06/08  13:42:20  mike
X * Initial revision
X * 
X */
X
X#include <sys/file.h>
X#include <sgtty.h>
X
X#include <signal.h>
X#include <syslog.h>
X
X#include <sys/types.h>
X#include <sys/socket.h>
X#include <netinet/in.h>
X#include <netdb.h>
X
X#include <stdio.h>
X
X/* Generic constants */
X#define PORT 5001		/* Port for the server */
X#define BUFLEN 256		/* Length of input buffer */
X#define DEF_PROTO 0		/* Use default protocol */
X#define NO_FLAGS 0		/* No flags on recvfrom/sendto */
X
X/* Message lengths */
X#define RET_MSG_LEN 6		/* Length of what we add to buf */
X#define ERR_MSG_LEN 3		/* Length of error messages */
X
X/* Message types from IEN 116 */
X#define ADDR_REQ 1		/* Address Request */
X#define ADDR_ANS 2		/* Address Request Answer */
X#define ERR      3		/* Error */
X
X/* Error types from IEN 116 */
X#define UNK_ERR  0		/* Unknown Error */
X#define HOST_UNK 1		/* Host Unknown */
X#define SYNT_ERR 2		/* Syntax Error */
X
Xchar buf[BUFLEN];		/* Input/Output buffer */
Xextern int errno, h_errno;
Xextern char *sys_errlist[];
X
Xmain()
X{
X  int sock;			/* Datagram socket */
X  struct sockaddr_in hisname;	/* Address of requestor */
X  int addrlen;			/* Length of his address */
X  struct hostent *hp, *gethostbyname();	/* Host inquired of */
X  char *name;			/* Name of the machine requested */
X  int msglen;			/* Length of the message received */
X  char *nameloc();
X
X  setupsig();			/* Set up signal handling */
X  setuplog();			/* Set up the syslog connection */
X  divorce();			/* Divorce ourselves from terminal and shell */
X  sock = makesocket();		/* make and bind the socket */
X 
X  addrlen = sizeof(hisname);	
X
X  /* Main loop */
X restart:
X  while (1)
X    {
X      /* Read a message */
X      msglen = recvfrom(sock, buf, BUFLEN - RET_MSG_LEN,
X			NO_FLAGS, (struct sockaddr *)&hisname, &addrlen);
X      if (msglen == -1)
X	{
X	  syslog(LOG_ERR, "Error on incoming message: %s\n", 
X		 sys_errlist[errno]);
X	  goto restart;
X	}
X
X      /* Find the name */
X      name = nameloc(buf, BUFLEN, msglen, &hisname, addrlen, sock);
X      if ((int) name == -1) 
X	goto restart;
X
X
X      /* Get the host entry */
X      if ((hp = gethostbyname(name))== NULL)
X	{
X	  /* Send error message */
X	  buf[msglen] = ERR;	
X	  buf[msglen+1] = ERR_MSG_LEN;
X	  if (h_errno == HOST_NOT_FOUND ||
X	      h_errno == TRY_AGAIN ||
X	      h_errno == NO_ADDRESS) 
X	    buf[msglen+2] = HOST_UNK; 
X	  else
X	    buf[msglen+2] = UNK_ERR; 
X	  if (sendto(sock, buf, msglen+ERR_MSG_LEN, NO_FLAGS, 
X		     (struct sockaddr *)&hisname, addrlen)==-1)
X	    {
X	      syslog(LOG_ERR, "Error sending error 3: %s\n", sys_errlist[errno]);
X	      goto restart;
X	    }  
X	}
X      else
X	{
X	  /* Send the reply */
X	  buf[msglen] = ADDR_ANS;
X	  buf[msglen+1] = RET_MSG_LEN;
X	  buf[msglen+2] = hp->h_addr_list[0][0];
X	  buf[msglen+3] = hp->h_addr_list[0][1];
X	  buf[msglen+4] = hp->h_addr_list[0][2];
X	  buf[msglen+5] = hp->h_addr_list[0][3];
X
X	  if (sendto(sock, buf, msglen+RET_MSG_LEN, NO_FLAGS, 
X		     (struct sockaddr *)&hisname, addrlen)==-1)
X	    {
X	      syslog(LOG_ERR, "Error sending reply: %s\n", sys_errlist[errno]);
X	      goto restart;
X	    }
X	}
X    }
X}
X
X
X/* setupsig -- Set all signals to be ignored.  Those which cannot be ignored
X   will be left at the default. */
Xsetupsig()
X{
X  int i;			/* Index of signals */
X  
X  for (i=0; i < NSIG; ++i)
X    (void) signal(i, SIG_IGN);
X}
X  
X
X/* setuplog -- set up the syslog connection */
Xsetuplog()
X{
X  openlog("nameserver", LOG_PID | LOG_CONS, LOG_DAEMON);
X}
X
X
X/* divorce -- Divorce ourselves from the terminal and the shell */
Xdivorce()
X{
X  int term;			/* Terminal filed */
X
X  /* First the shell */
X  switch(fork()) 
X    {
X    case -1:
X      syslog(LOG_CRIT, "Cannot fork: %s\n", sys_errlist[errno]);
X      exit(1);
X      break;
X    case 0:
X      break;
X    default:
X      exit(0);
X      break;
X    }
X
X  /* Now the files */
X  /* POTENTIAL BUG-- ASSUMES THAT THE TERMINAL IS ONLY OPEN ON FILEDS 0,1,2 */
X  (void) close (0);
X  (void) close (1);
X  (void) close (2);
X  /* Now the terminal */
X  if ((term = open("/dev/tty", O_RDWR, 0)) == -1)
X    {
X      syslog(LOG_CRIT, "Cannot open /dev/tty: %s\n", sys_errlist[errno]);
X      exit(1);
X    }
X  if (ioctl(term, TIOCNOTTY, (char *) 0) == -1)
X    {
X      syslog(LOG_CRIT, "Cannot divorce from control terminal: %s\n", 
X	     sys_errlist[errno]);
X      exit(1);
X    }
X  (void) close(term);
X}
X
X
X/* makesocket -- return the filed of a new bound socket */
Xmakesocket()
X{
X  int sock;			/* Socket */
X  struct sockaddr_in ourname;	/* Our name */
X
X  /* create the socket */
X  sock = socket(AF_INET, SOCK_DGRAM, DEF_PROTO);
X  if (sock < 0)
X    {
X      syslog(LOG_CRIT, "Error opening socket: %s\n", sys_errlist[errno]);
X      exit(1);
X    }
X  ourname.sin_family = AF_INET;
X  ourname.sin_port = PORT;
X  ourname.sin_addr.s_addr = INADDR_ANY;
X  if (bind(sock, &ourname, sizeof(ourname)))
X
X    {
X      syslog(LOG_CRIT, "Error binding socket: %s\n", sys_errlist[errno]);
X      exit(1);
X    }
X  return sock;
X}  
X
X
X/* nameloc -- return the address of a null-terminated string which is the
X   name to be looked up.  Report syntax errors to reportto through sock.
X   If an error occurs, return (char *) -1.  If an error occurs, buf will be 
X   changed. */
Xchar *
Xnameloc(buf, buflen, msglen, reportto, addrlen, sock)
X     char *buf;			/* Buffer holding the request */
X     int buflen,		/* Length of the buffer */
X       msglen,			/* Length of the message in the buffer */
X       sock,			/* Socket for error replies */
X       addrlen;			/* Length of reportto */
X     struct sockaddr_in *reportto; /* Who we report errors to */
X{
X  char *name;			/* Address of the name */
X  int code;			/* Type of request */
X
X  buf[msglen] = '\0';
X  /* Check type */      
X  code = buf[0];
X  if (code != ADDR_REQ)
X    if (code !=ADDR_ANS && code !=ERR)
X      {
X	/* Send error message */
X	buf[0] = ERR;	
X	buf[1] = ERR_MSG_LEN;
X	buf[2] = SYNT_ERR;
X	if (sendto(sock, buf, ERR_MSG_LEN, NO_FLAGS, 
X		   (struct sockaddr *)&reportto, addrlen)==-1)
X	  {
X	    syslog(LOG_ERR, "Error sending error 0: %s\n", sys_errlist[errno]);
X	    return (char *) -1;
X	  }	    
X      }
X    else
X      return (char *) -1;
X  
X  /* Put name at the start of a null-terminated string */
X  if (buf[2]!='!')
X    name=buf+2;
X  else
X    {
X      for(name=buf+2; *name!='!'; ++name)
X	if (name-buf >= buflen)
X	  {			
X	    /* Send error packet */
X	    buf[0] = ERR;
X	    buf[1] = ERR_MSG_LEN;
X	    buf[2] = SYNT_ERR;
X	    if (sendto(sock, buf, ERR_MSG_LEN, NO_FLAGS, 
X		       (struct sockaddr *)&reportto, addrlen)==-1)
X	      {
X		syslog(LOG_ERR, "Error sending error 1: %s\n", 
X		       sys_errlist[errno]);
X		return (char *) -1;
X	      }
X	  }
X      for(++name; *name!='!'; ++name)
X	if (name-buf >= buflen)
X	  {			
X	    /* Send error packet */
X	    buf[0] = ERR;
X	    buf[1] = ERR_MSG_LEN;
X	    buf[2] = SYNT_ERR;
X	    if (sendto(sock, buf, ERR_MSG_LEN, NO_FLAGS, 
X		       (struct sockaddr *)&reportto, addrlen)==-1)
X	      {
X		syslog(LOG_ERR, "Error sending error 2: %s\n", 
X		       sys_errlist[errno]);
X		return (char *) -1;
X	      }
X	  }
X      ++name;
X    }
X  return name;
X}
X
X
X
SHAR_EOF
if test 9178 -ne "`wc -c < 'nameserver.c'`"
then
	echo shar: error transmitting "'nameserver.c'" '(should have been 9178 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'nameserver.8'" '(702 characters)'
if test -f 'nameserver.8'
then
	echo shar: will not over-write existing file "'nameserver.8'"
else
sed 's/^X//' << \SHAR_EOF > 'nameserver.8'
X.TH nameserver 8 "Local \- June 24, 1987" "M. I. Bushnell"
X.SH NAME
Xnameserver \- process IEN 116 requests
X.SH SYNOPSIS
X.B nameserver
X.SH DESCRIPTION
X\fBNameserver\fR processes requests for network addresses using the IEN 116
Xprotocol.
X.SH SEE ALSO
XIEN 116 \- Internet Name Server (J. Postel)
X.SH DIAGNOSTICS
XVarious messages logged by syslog using LOG_CRIT and LOG_ERR.
XMainly self-explanatory.  Errors such as
X.RS .5i
XError sending error \fIn\fR: ....
X.RE
Xrefer to errors in the transmission of error messages back to the requestor.
XFor explanation of the numbers, see the source.
X.SH BUGS
XWill not properly detach from the terminal if the terminal is opened on
Xany descriptor other than 0, 1, or 2.
SHAR_EOF
if test 702 -ne "`wc -c < 'nameserver.8'`"
then
	echo shar: error transmitting "'nameserver.8'" '(should have been 702 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0
					Michael I. Bushnell
					a/k/a Bach II
					mike@turing.UNM.EDU
---
Somewhere in Tenafly, New Jersey, a chiropractor is viewing
 ``Leave it to Beaver''!
				-- Zippy the Pinhead

-- 

Rich $alz			"Anger is an energy"
Cronus Project, BBN Labs	rsalz@bbn.com
Moderator, comp.sources.unix	sources@uunet.uu.net