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

This is diald.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 <signal.h>
#include <errno.h>
#include <setjmp.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/file.h>
#include <sys/param.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/if_du.h>
#include "dialupip.h"
#include "diald.h"

typedef struct _TABLE {
    int		Protocol;
    char	*Name;
} TABLE;


static jmp_buf	context;
static int	pleaserescan;
static int	pleasequit;
static char	*WHERE = "diald";
static TABLE	ProtocolNames[] = {
#ifdef	IPPROTO_IP
    { IPPROTO_IP, "IP Dummy" },
#endif
#ifdef	IPPROTO_ICMP
    { IPPROTO_ICMP, "ICMP" },
#endif
#ifdef	IPPROTO_GGP
    { IPPROTO_GGP, "GGP" },
#endif
#ifdef	IPPROTO_TCP
    { IPPROTO_TCP, "TCP" },
#endif
#ifdef	IPPROTO_EGP
    { IPPROTO_EGP, "EGP" },
#endif
#ifdef	IPPROTO_PUP
    { IPPROTO_PUP, "PUP" },
#endif
#ifdef	IPPROTO_UDP
    { IPPROTO_UDP, "UDP" },
#endif
#ifdef IPPROTO_IDP
    { IPPROTO_IDP, "IDP" },
#endif
#ifdef IPPROTO_RAW
    { IPPROTO_RAW, "RAW" },
#endif
    { 0, NULL }
};



static int
authorized(rp, pkt)
    register REMOTE		*rp;
    register struct du_pkt	*pkt;
{
    register int		i;
    register TABLE		*tp;
    struct timeval		tv;
    struct tm			*tm;

    /* check protocol */
    i = pkt->du_ip.ip_p;
    if ((rp->Protocols[P_WORD(i)] & P_BIT(i)) == 0) {
	for (tp = ProtocolNames; tp->Name; tp++)
	    if (i == tp->Protocol)
		break;
	d_log(DLOG_INFO, WHERE, "Bad protocol %s (%d)",
	    tp ? tp->Name : "unknown");
	return 0;
    }

    /* Check time. */
    if (gettimeofday(&tv, (struct timezone *)NULL) < 0) {
	d_log(DLOG_GENERAL, WHERE, "Can't do gettimeofday, %m");
	return 0;
    }
    if ((tm = localtime(&tv.tv_sec)) == NULL) {
	d_log(DLOG_GENERAL, WHERE, "Can't do localtime, %m");
	return 0;
    }
    if ((rp->Times[tm->tm_wday] & (1L << tm->tm_hour)) == 0) {
	d_log(DLOG_INFO, WHERE, "Bad time to call");
	return 0;
    }

    /* Check addresses. */
    if (rp->AllowCount && !hostinlist(rp->AllowTo, pkt->du_ip.ip_dst)) {
	d_log(DLOG_INFO, WHERE, "Bad destination address \"%s\"",
	    inet_ntoa(pkt->du_ip.ip_dst));
	return 0;
    }
    if (rp->DisallowCount && hostinlist(rp->DisallowFrom, pkt->du_ip.ip_src)) {
	d_log(DLOG_INFO, WHERE, "Bad source address \"%s\"",
	    inet_ntoa(pkt->du_ip.ip_src));
	return 0;
    }

    /* o.k. to make call */
    return 1;
}


static void
catchsigterm()
{
    pleasequit++;
    longjmp(context, 1);
}


static void
catchsighup()
{
    pleaserescan++;
    (void)signal(SIGHUP, catchsighup);
    longjmp(context, 1);
}


static void
catchsigchld()
{
    union wait	wstatus;

    while (wait3(&wstatus, WNOHANG, (struct rusage *)NULL) > 0)
	;
}



static void
usage()
{
    (void)fprintf(stderr, "usage: %s [options]\n", progname);
    d_log(DLOG_GENERAL, WHERE, "Usage error");
    exit(1);
}


main(argc, argv)
    int			argc;
    char		*argv[];
{
    int			f;
    int			dofork;
    int			i;
    struct du_pkt	pkt;
    REMOTE		*rp;
    char		buff[256];
    char		*configfile;

    /* Set defaults. */
    setprogname(argv[0]);
    WHERE = progname;
    dofork = 1;
    configfile = DIALD_CONFIG;

    /* Parse flags. */
    while ((i = getopt(argc, argv, "c:d:F")) != EOF)
	switch (i) {
	default:
	    usage();
	    /* NOTREACHED */
	case 'c':
	    configfile = optarg;
	    break;
	case 'd':
	    log_level = atoi(optarg);
	    break;
	case 'F':
	    dofork = 0;
	    break;
	}
    argc -= optind;
    argv += optind;
    if (argc)
	usage();

    /* Fork us off */
    if (dofork) {
	if ((i = fork()) < 0) {
	    d_log(DLOG_GENERAL, WHERE, "Can't fork, %m");
	    exit(1);
	}
	if (i > 0)
	    exit(0);
	if (freopen("/dev/console", "w", stderr) == NULL)
	    d_log(DLOG_GENERAL, WHERE, "Can't set stderr to /dev/console, %m");
    }

    /* Read configuration data. */
    if (!readconfig(configfile))
	exit(1);

    /* Open the request device. */
    if ((f = open(DEVDIAL, O_RDONLY)) < 0) {
	d_log(DLOG_GENERAL, WHERE, "Can't open \"%s\", %m", DEVDIAL);
	exit(1);
    }
#ifdef	FIOCLEX
    if (ioctl(f, FIOCLEX, (caddr_t)NULL) < 0)
	d_log(DLOG_INFO, WHERE, "Can't do FIOCLEX on \"%s\", %m", DEVDIAL);
#endif	/* FIOCLEX */

    /* Tell the log file where are here */
    d_log(DLOG_GENERAL, WHERE, "Diald %s started", dip_release());
    (void)record_pid(progname);

    /* Process requests */
    (void)signal(SIGHUP, catchsighup);
    (void)signal(SIGTERM, catchsigterm);
    (void)signal(SIGCHLD, catchsigchld);
    for ( ; ; ) {
	(void)setjmp(context);
	if (pleasequit)
	    break;
	if (pleaserescan) {
	    d_log(DLOG_GENERAL, WHERE, "Rescanning config files");
	    if (!readconfig(configfile)) {
		unlock_pid();
		exit(1);
	    }
	    (void)signal(SIGHUP, catchsighup);
	    pleaserescan = 0;
	    continue;
	}

	/* Read the device. */
	if ((i = read(f, (char *)&pkt, sizeof pkt)) != sizeof pkt) {
	    if (errno != EINTR)
		d_log(DLOG_GENERAL, WHERE,
		    "Bad read (%d bytes) from \"%s\", %m",
		    i, DEVDIAL);
	    continue;
	}

	/* Find config data for the address. */
	(void)sprintf(buff, "%s%d", pkt.du_ifname, pkt.du_ifunit);
	if ((rp = findconfig(buff)) == NULL) {
	    d_log(DLOG_GENERAL, WHERE, "Address %s not configured",
		inet_ntoa(pkt.du_sin.sin_addr));
	    continue;
	}

	/* Is this packet is authorized? */
	if (pkt.du_checkit && !authorized(rp, &pkt)) {
	    (void)sprintf(buff, "%s not authorized to reach %s",
		    inet_ntoa(pkt.du_ip.ip_src), inet_ntoa(pkt.du_ip.ip_dst));
	    failcall(rp->Device, buff);
	    continue;
	}

	/* Make the call. */
	if (!dofork) {
	    makecall(rp);
	    continue;
	}
	if ((i = fork()) == 0) {
	    (void)setpgrp(0, getpgrp(0));
	    makecall(rp);
	    break;
	}
	if (i < 0)
	    d_log(DLOG_GENERAL, WHERE, "Can't fork dialing process, %m");
    }

    d_log(DLOG_GENERAL, WHERE, "Diald %s exiting", dip_release());
    unlock_pid();
    exit(0);
    /* NOTREACHED */
}

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