ftp.nice.ch/peanuts/GeneralData/Documents/user-groups/rmNUG/dialupip.tar.gz#/dialupip/src/diald/readconfig.c

This is readconfig.c in view mode; [Download] [Up]

/*
**  Copyright (c) 1991 Bolt Beranek and Newman, Inc.
**  All rights reserved.
**
**  Redistribution and use in source and binary forms are permitted
**  provided that: (1) source distributions retain this entire copyright
**  notice and comment, and (2) distributions including binaries display
**  the following acknowledgement:  ``This product includes software
**  developed by Bolt Beranek and Newman, Inc. and CREN/CSNET'' in the
**  documentation or other materials provided with the distribution and in
**  all advertising materials mentioning features or use of this software.
**  Neither the name of Bolt Beranek and Newman nor CREN/CSNET may be used
**  to endorse or promote products derived from this software without
**  specific prior written permission.
**
**  THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
**  WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
**  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#include <stdio.h>
#include <ctype.h>
#include <netdb.h>
#include <sgtty.h>
#include <sys/types.h>
#include <sys/param.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include "dialupip.h"
#include "diald.h"


/*
**  Some systems don't have these in their <netinet/in.h>
*/
#ifndef	IPPROTO_EGP
#define IPPROTO_EGP	8
#endif	/* IPPROTO_EGP */
#ifndef	IPPROTO_RDP
#define IPPROTO_RDP	27
#endif	/* IPPROTO_EGP */


#define EQ(a, b)	(strcmp((a), (b)) == 0)
#define nexttok()	strtok((char *)NULL, SEPARATORS)


static int		errorcount;
static int		linenum;
static char		SEPARATORS[] = " \t";
static REMOTE		*RemoteTable;
static int		RemoteCount;
static char		WHERE[] = "readconfig";


/*
**  Find this interface in our list.
*/
REMOTE *
findconfig(device)
    register char	*device;
{
    register REMOTE	*rp;
    register int	i;

    for (rp = RemoteTable, i = RemoteCount; --i >= 0; rp++)
	if (strcmp(device, rp->Device) == 0)
	    return rp;
    return NULL;
}


/*
**  Is the host (or its network) on the list of hosts and networks?
*/
int
hostinlist(list, addr)
    struct in_addr	*list;
    struct in_addr	addr;
{
    register int	i;
    register int	j;

    j = i = addr.s_addr % MAXHOSTS;

    do {
	if (list[j].s_addr == 0)
	    return 0;
	if (list[j].s_addr == addr.s_addr)
	    return 1;
	if (inet_lnaof(list[j].s_addr) == 0
	 && inet_netof(list[j].s_addr) == inet_netof(addr.s_addr))
	    return 1;

	if (++j == MAXHOSTS)
	    j = 0;
    } while (j != i);

    return 0;
}



static void
yyerror(path, fmt, arg)
    char	*path;
    char	*fmt;
    char	*arg;
{
    char	buff[256];

    (void)sprintf(buff, "Error near line %d of\n\t \"%s\":  %s\n",
	linenum, path, fmt);
    d_log(DLOG_GENERAL, WHERE, buff, arg);
    errorcount++;
}


static void
parseprotocols(path, lp)
    char	*path;
    u_long	*lp;
{
    char	*p;
    int		i;

    while (p = nexttok()) {
	if (EQ(p, "tcp"))
	    i = IPPROTO_TCP;
	else if (EQ(p, "rdp"))
	    i = IPPROTO_RDP;
	else if (EQ(p, "egp"))
	    i = IPPROTO_EGP;
	else if (EQ(p, "icmp"))
	    i = IPPROTO_ICMP;
	else if (EQ(p, "udp"))
	    i = IPPROTO_UDP;
	else if (EQ(p, "ggp"))
	    i = IPPROTO_GGP;
	else {
	    yyerror(path, "Bad protocol \"%s\"", p);
	    continue;
	}
	lp[P_WORD(i)] |= P_BIT(i);
    }
}


static int
positivenumber(p)
    char	*p;
{
    if (*p == '\0')
	return 0;
    for ( ; *p; p++)
	if (!isdigit(*p))
	    return 0;
    return 1;
}


static long
parsetime(path)
    char	*path;
{
    long	l;
    int		i;
    char	*p;

    for (l = 0; p = nexttok(); )
	if (!positivenumber(p) || (i = atoi(p)) < 0 || i > 23)
	    yyerror(path, "Bad hour \"%s\"", p);
	else
	    l |= (1L << i);
    return l;
}


static int
addhosttolist(list, addr)
    struct in_addr	*list;
    struct in_addr	addr;
{
    register int	i;
    register int	j;

    j = i = addr.s_addr % MAXHOSTS;
    do {
	if (list[j].s_addr == 0) {
	    list[j] = addr;
	    return 1;
	}
	if (++j == MAXHOSTS)
	    j = 0;
    } while (j != i);

    return 0;
}



static int
parseaddresslist(path, list)
    char		*path;
    struct in_addr	*list;
{
    char		*p;
    struct in_addr	new;
    int			i;
    struct hostent	*hp;
    struct netent	*np;

    for (i = 0; p = nexttok(); i++) {
	if ((new.s_addr = inet_addr(p)) != -1)
	    ;
	else if (np = getnetbyname(p))
	    new = inet_makeaddr(np->n_net, 0);
	else if (hp = gethostbyname(p))
	    bcopy(hp->h_addr, (caddr_t)&new, sizeof new);
	else {
	    yyerror(path, "Bad IP address \"%s\"", p);
	    continue;
	}
	if (!hostinlist(list, new) && !addhosttolist(list, new))
	    yyerror(path, "Can't add \"%s\" to address list", p);
    }
    return i;
}


static int
readentry(path, rp, line)
    char		*path;
    REMOTE		*rp;
    char		*line;
{
    static char		MISSINGFIELD[] = "Required \"%s\" field is missing";
    FILE		*F;
    char		*sitep;
    char		*ttysp;
    char		*scriptp;
    char		*transp;
    char		*accessp;
    char		*word;
    char		*p;
    char		*fp;
    char		buff[BUFSIZ];
    int			i;

    /* Make sure we have six colon-separated fields. */
    if ((sitep = strchr(line, ':')) == NULL
     || (ttysp = strchr(sitep + 1, ':')) == NULL
     || (scriptp = strchr(ttysp + 1, ':')) == NULL
     || (transp = strchr(scriptp + 1, ':')) == NULL
     || (accessp = strchr(transp + 1, ':')) == NULL) {
	yyerror(path, "Too few fields", (char *)NULL);
	return 0;
    }
    *sitep++ = '\0';
    *ttysp++ = '\0';
    *scriptp++ = '\0';
    *transp++ = '\0';
    *accessp++ = '\0';

    /* Field one, the interface. */
    if (*line == '\0') {
	yyerror(path, MISSINGFIELD, "interface");
	return 0;
    }
    (void)strcpy(rp->Device, line);

    /* Field two, the site name. */
    if (*sitep == '\0') {
	yyerror(path, MISSINGFIELD, "site");
	return 0;
    }
    (void)strcpy(rp->Sitename, sitep);

    /* Field three, the tty#baudrate entries. */
    if (*ttysp == '\0' || (p = strtok(ttysp, SEPARATORS)) == NULL) {
	yyerror(path, MISSINGFIELD, "ttys");
	return 0;
    }
    for (i = 0; p && i < MAXDEVICES; i++, p = nexttok()) {
	if ((fp = strchr(p, '#')) == NULL)
	    rp->Speeds[i] = -1;
	else
	    *fp++ = '\0';
	(void)strcpy(rp->Lines[i], p);
	if (fp)
	    switch (atoi(fp)) {
	    default:
		yyerror(path, "Bad speed \"%s\"\n", fp);
		break;
	    case 1200:	rp->Speeds[i] = B1200;	break;
	    case 2400:	rp->Speeds[i] = B2400;	break;
	    case 4800:	rp->Speeds[i] = B4800;	break;
	    case 9600:	rp->Speeds[i] = B9600;	break;
	    case 19200:	rp->Speeds[i] = EXTA;	break;
	    case 38400:	rp->Speeds[i] = EXTB;	break;
	    }
    }
    if (i >= MAXDEVICES) {
	yyerror(path, "Too many tty entries", (char *)NULL);
	return 0;
    }
    while (i < MAXDEVICES)
	rp->Lines[i++][0] = '\0';

    /* Field four, the script file and parameters. */
    if (*scriptp == '\0' || (p = strtok(scriptp, SEPARATORS)) == NULL) {
	yyerror(path, "Missing script name", (char *)NULL);
	return 0;
    }
    if (*p == '/')
	(void)strcpy(rp->Script, p);
    else
	(void)sprintf(rp->Script, "%s/%s", CONFIG_DIR, p);
    for (fp = rp->FieldData, i = 0; i < 10 && (p = nexttok()); i++) {
	if (fp > &rp->FieldData[sizeof rp->FieldData - 1]) {
	    yyerror(path, "Parameters too long", (char *)NULL);
	    break;
	}
	rp->Fields[i] = fp - rp->FieldData;
	fp += strlen(strcpy(fp, p));
	*fp++ = '\0';
    }
    if (i >= 10) {
	yyerror(path, "Too many parameters", (char *)NULL);
	return 0;
    }
    rp->FieldCount = i;

    /* Field five, the transcript file. */
    if ((p = strchr(transp, '@')) && isdigit(p[1]) && p[2] == '\0')
	rp->Transtyle = *++p == '0' ? TS_LOW : TS_HIGH;
    else
	rp->Transtyle = TS_LOW;
    if (*transp == '/')
	(void)strcpy(rp->Transcript, transp);
    else
	(void)sprintf(rp->Transcript, "%s/%s", CONFIG_DIR, transp);

    /* Set access defaults. */
    for (i = 0; i < 7; i++)
	rp->Times[i] = ~0;
    for (i = 0; i < 8; i++)
	rp->Protocols[i] = ~0;
    for (rp->AllowCount = 0, i = 0; i < MAXHOSTS; i++)
	rp->AllowTo[i].s_addr = 0;
    for (rp->DisallowCount = 0, i = 0; i < MAXHOSTS; i++)
	rp->DisallowFrom[i].s_addr = 0;
    rp->Inactivity = INACT_UNDEF;

    /* Field five, the access file. */
    if (*accessp == '\0')
	return errorcount == 0;

    if (*accessp == '/')
	(void)strcpy(buff, accessp);
    else
	(void)sprintf(buff, "%s/%s", CONFIG_DIR, accessp);
    if ((F = fopen(buff, "r")) == NULL) {
	yyerror(path, "Can't open access file \"%s\"", accessp);
	return 0;
    }

    /* Read lines. */
    for (linenum = 1; fgets(buff, sizeof buff, F); linenum++) {
	if ((p = strchr(buff, '\n')) == NULL) {
	    yyerror(buff, "Line too long", (char *)NULL);
	    (void)fclose(F);
	    return 0;
	}
	*p = '\0';
	if (*p == '\0' || *p == '#')
	    continue;
	if ((word = strtok(buff, SEPARATORS)) == NULL)
	    continue;
	/* Dispatch on the word to fill in the fields. */
	if (EQ(word, "allowto") || EQ(word, "gooddstaddresses"))
	    rp->AllowCount += parseaddresslist(path, rp->AllowTo);
	else if (EQ(word, "disallowfrom") || EQ(word, "badsrcaddresses"))
	    rp->DisallowCount += parseaddresslist(path, rp->DisallowFrom);
	else if (EQ(word, "protocols"))
	    parseprotocols(path, rp->Protocols);
	else if (EQ(word, "inactivity")) {
	    if (p = nexttok())
		if (!positivenumber(p))
		    yyerror(accessp, "Bad number \"%s\"", p);
		else
		    rp->Inactivity = atoi(p);
	}
	else if (EQ(word, "weekdays"))
	    rp->Times[1] = rp->Times[2] = rp->Times[3] =
	    rp->Times[4] = rp->Times[5] = parsetime(path);
	else if (EQ(word, "weekends"))
	    rp->Times[0] = rp->Times[6] = parsetime(path);
	else if (EQ(word, "sun") || EQ(word, "sunday"))
	    rp->Times[0] = parsetime(path);
	else if (EQ(word, "mon") || EQ(word, "monday"))
	    rp->Times[1] = parsetime(path);
	else if (EQ(word, "tue") || EQ(word, "tuesday"))
	    rp->Times[2] = parsetime(path);
	else if (EQ(word, "wed") || EQ(word, "wednesday"))
	    rp->Times[3] = parsetime(path);
	else if (EQ(word, "thu") || EQ(word, "thursday"))
	    rp->Times[4] = parsetime(path);
	else if (EQ(word, "fri") || EQ(word, "friday"))
	    rp->Times[5] = parsetime(path);
	else if (EQ(word, "sat") || EQ(word, "saturday"))
	    rp->Times[6] = parsetime(path);
	else
	    yyerror(accessp, "Bad parameter \"%s\"", word);
    }

    (void)fclose(F);
    return errorcount == 0;
}


int
readconfig(path)
    char		*path;
{
    FILE		*F;
    char		*p;
    char		buff[BUFSIZ];
    int			i;

    /* Count the number of lines in the file. */
    linenum = 0;
    if ((F = fopen(path, "r")) == NULL) {
	yyerror(path, "Can't open for reading, %m", (char *)NULL);
	return 0;
    }
    while (fgets(buff, sizeof buff, F))
	if (buff[0] != '#')
	    linenum++;
    rewind(F);

    /* Allocate space for the table. */
    if (RemoteTable)
	free((char *)RemoteTable);
    RemoteTable = (REMOTE *)malloc((unsigned int)linenum * sizeof (REMOTE));
    if (RemoteTable == NULL) {
	yyerror(path, "Can't allocate table, %m", (char *)NULL);
	return 0;
    }

    errorcount = 0;
    for (i = 1, RemoteCount = 0; fgets(buff, sizeof buff, F); i++) {
	if ((p = strchr(buff, '\n')) == NULL) {
	    yyerror(path, "Line too long", (char *)NULL);
	    (void)fclose(F);
	    return 0;
	}
	*p = '\0';
	if (buff[0] == '#' || buff[0] == '\0')
	    continue;

	linenum = i;
	if (readentry(path, &RemoteTable[RemoteCount], buff))
	    RemoteCount++;
    }

    (void)fclose(F);
    return errorcount == 0;
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.