/*
 * Access.c - routines to deal with an ip acl.
 * 
 * Tom Coppeto 2/21/91
 * MIT Network Services
 */

#include <stdio.h>
#include "access.h"

static struct _access access[MAX_ACCESS];
static int n_access = 0;
static int init = 0;
char *AccessFile = "/usr/local/etc/websterd.ac";

/*
 * REFUSE_CONNECTION -- check file to see if we do not wish to continue
 *  
 *       a session with a particular moron.
 */


refuse_connection(addr)
     unsigned long addr;
{
  unsigned long laddr;        
  unsigned long lmask;        
  unsigned long save;         
  short auth = 1;             
  short val  = 0;             
  short sn;                   
  int   i = 0;

  if(!init)
    {
      read_access_file(AccessFile);
      init = 1;
    }

  while(i < n_access)
    {
      sn    = 0;
      save  = addr;
      laddr = access[i].addr;
      lmask = access[i].mask;
      
      while(lmask)
	{
	  if(((laddr & 0xff) == (save & 0xff)) && (lmask & 0xff))
	    ++sn;	    
	  else
	    if(lmask & 0xff)
              {
                sn = 0;
                break;
              }

	    save  = save >> 8;
            laddr = laddr >> 8;
	    lmask = lmask >> 8;
	  }

      if(sn && (val <= sn))
	{
	  auth = access[i].auth;
	  val  = sn;
	}
      ++i;
    }  
  return(auth);
}
	

read_access_file(file)
     char *file;
{
  FILE *fp;
  char  line[80];             

  if(!AccessFile)
    return(1);

  if(!(fp = fopen(AccessFile, "r")))
    return(1);
  
  while(fgets(line, sizeof(line)-1, fp) && (n_access < MAX_ACCESS))
    if(parse_access_line(line, &access[n_access]) == 0)
      ++n_access;
  
  fclose(fp);
  return(0);
}


parse_access_line(line, a)
     char *line;
     struct _access *a;
{
  char *c;
  
  if(*line == '+')
    a->auth = 0;
  else
    if(*line == '-')
      a->auth = 1;
    else
      return(1);

  c = ++line;      
  while(*line && (*line != '\n') && (*line != '\t') && 
	(*line != ' ') && (*line != ' '))
    ++line;
  *line++ = '\0';
  if((a->addr = inet_addr(c)) < 1)
    return(1);

  while((*line == ' ' ) || (*line == '\t'))
    ++line;

  c = line;      
  while(*line && (*line != '\n') && (*line != '\t') && 
	(*line != ' ') && (*line != ' '))
    ++line;
  *line = '\0';
  if((a->mask = inet_addr(c)) < 1)
    return(1);

  return(0);
}
