freebsd-nq/gnu/usr.sbin/isdn/ittd/ittd.c
1995-02-15 00:46:26 +00:00

527 lines
8.8 KiB
C

static char rcsid[] = "@(#)$Id: ittd.c,v 1.2 1995/01/25 14:01:28 jkr Exp jkr $";
/*******************************************************************************
* II Version 0.1 - $Revision: 1.2 $ $State: Exp $
*
* Copyright 1994 Dietmar Friede
*******************************************************************************
* Bug reports, patches, comments, suggestions should be sent to:
*
* jkr@saarlink.de or jkrause@guug.de
*
*******************************************************************************
* $Log: ittd.c,v $
*
******************************************************************************/
/* This is a ISDN-Daemon for tty dialin */
#include <sys/types.h>
#include <stdio.h>
#include <signal.h>
#include <errno.h>
#include <setjmp.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/file.h>
#include "../../../../sys/gnu/isdn/isdn_ioctl.h"
#define min(a,b) ((a)<(b)?(a):(b))
#define NITTY 2
#define NOTTY 2
#define NTTY (NITTY + NOTTY)
listen_t listen;
isdn_param ip[NTTY];
dial_t dial[NOTTY];
struct iline
{
char occupied;
u_char an, cn;
char no[15];
} iline[NTTY];
int dofork = 1;
int quit = 0, rescan = 0;
jmp_buf context;
char *logfile = "/var/log/isdn.itt";
char *configfile = "/etc/isdn.itt";
int subadr, prot, bsize, timeout, spv, ui, serv;
int def_subadr = 3;
int ind, rind;
char rbuf[2048];
unsigned short si_mask;
void
catchsig()
{
quit++;
longjmp(context, 1);
}
void
catchsighup()
{
rescan++;
(void) signal(SIGHUP, catchsighup);
longjmp(context, 1);
}
setdefault()
{
subadr = -1;
prot = 2;
ui = 1;
serv = 7;
timeout = 0;
bsize = 2048;
spv = 0;
}
char *
gettoc()
{
if (rind == -1)
{
rind = 0;
return (rbuf);
}
while (rbuf[++rind]);
rind++;
if (rind >= ind)
return (NULL);
return (&rbuf[rind]);
}
filline(FILE * f)
{
int c;
ind = 1;
rbuf[0] = 'H';
while ((c = fgetc(f)) != EOF)
{
if (isalnum(c))
{
rbuf[ind++] = c;
} else
switch (c)
{
case '#':
fgets(rbuf + ind, 2048 - ind, f);
if (ind == 1)
break;
/* Fall through */
case '\n':
rbuf[ind] = 0;
rind = -1;
return (0);
case ':':
rbuf[ind++] = 0;
break;
}
}
if (ind > 1)
return (0);
return (EOF);
}
process(FILE * f, int n)
{
char *p;
int ap = 0;
setdefault();
if (filline(f) != EOF)
{
while ((p = gettoc()) != NULL)
switch (p[0])
{
case 'A':
def_subadr = p[1] - '0';
listen.subadr_mask |= 1 << def_subadr;
break;
case 'p':
switch (p[1])
{
case 'r':
serv = 7;
prot = 2;
ui = 0;
break;
case 'u':
serv = 7;
prot = 2;
ui = 1;
break;
case 'X':
serv = 7;
prot = 1;
ui = 0;
break;
case 'C':
serv = 15;
prot = 5;
ui = 0;
break;
default:
fprintf(stderr, "Protocoll not supported\n");
exit(1);
}
break;
case 'w':
timeout = atoi(p + 1);
break;
case 's':
bsize = atoi(p + 1);
break;
case 'S':
spv++;
break;
default:
}
}
for (ap = 0; ap < NTTY; ap++)
{
fillparam(ap, &ip[ap]);
if (ioctl(n, ISDN_SET_PARAM, &ip[ap]) < 0)
{
perror("ioctl: Set Param");
exit(3);
}
}
listen.si_mask = si_mask;
if (listen.subadr_mask == 0)
listen.subadr_mask |= 1 << def_subadr;
listen.inf_mask = 3;
listen.ctrl = 0;
if (ioctl(n, ISDN_LISTEN, &listen) < 0)
{
perror("ioctl: Listen");
exit(4);
}
}
fillparam(int ap, isdn_param * ip)
{
if (subadr == -1)
subadr = def_subadr;
si_mask |= (u_short) (1 << serv);
/*
* spv = 0;
*/
bzero(ip, sizeof(isdn_param));
ip->appl = ap;
ip->dlpd.protokoll = prot;
ip->dlpd.length = 7;
ip->dlpd.data_length = bsize;
ip->timeout = timeout;
ip->prot = ui;
ip->ncpd.protokoll = 4;
}
realine(char *b)
{
int c;
ind = 0;
while (c = *b & 0x7f)
{
b++;
if (isalnum(c))
{
rbuf[ind++] = c;
} else if (c == '.')
rbuf[ind++] = 0;
}
if (ind > 1)
return (0);
return (EOF);
}
process_dial(int n, int ap, char *b)
{
char *p;
telno_t *t;
setdefault();
if (realine(b) == EOF)
return;
rind = -1;
while ((p = gettoc()) != NULL)
{
switch (p[0])
{
case 'a':
subadr = p[1] - '0';
break;
case 'd':
t = &dial[ap - NITTY].telno;
t->length = strlen(p + 1) + 1;
if (t->length > 123)
{
fprintf(stderr, "ISDN number too long\n");
exit(1);
}
t->no[0] = 0x81;
strncpy(&t->no[1], p + 1, t->length);
break;
case 'p':
switch (p[1])
{
case 'r':
serv = 7;
prot = 2;
ui = 0;
break;
case 'u':
serv = 7;
prot = 2;
ui = 1;
break;
case 'X':
serv = 7;
prot = 1;
ui = 0;
break;
case 'C':
serv = 15;
prot = 5;
ui = 0;
break;
default:
fprintf(stderr, "Protocoll not supported\n");
exit(1);
}
break;
case 'w':
timeout = atoi(p + 1);
break;
case 's':
bsize = atoi(p + 1);
break;
case 'S':
spv++;
break;
default:
}
}
filldial(ap, &ip[ap], &dial[ap - NITTY]);
if (ioctl(n, ISDN_SET_PARAM, &ip[ap]) < 0)
{
perror("ioctl: Set Param");
exit(3);
}
}
filldial(int ap, isdn_param * ip, dial_t * d)
{
if (subadr == -1)
subadr = def_subadr;
/*
* spv = 0;
*/
bzero(ip, sizeof(isdn_param));
d->appl = ip->appl = ap;
d->b_channel = 0x83;
d->inf_mask = 3;
d->out_serv = serv;
d->src_subadr = '0' + subadr;
ip->dlpd.protokoll = prot;
ip->dlpd.length = 7;
ip->dlpd.data_length = bsize;
ip->timeout = timeout;
ip->prot = ui;
ip->ncpd.protokoll = 4;
}
void
main(int argc, char **argv)
{
FILE *f;
int a, n, i;
u_char buf[4];
dofork = 1;
while ((i = getopt(argc, argv, "c:l:F")) != EOF)
switch (i)
{
default:
fprintf(stderr, "Usage: ittd [ -F ] [ -c configfile ] [ -l logfile ]\n");
exit(1);
case 'c':
configfile = optarg;
break;
case 'l':
logfile = optarg;
break;
case 'F':
dofork = 0;
break;
}
if (dofork)
{
if ((i = fork()) < 0)
{
fprintf(stderr, "Can't fork, %m");
exit(1);
}
if (i > 0)
exit(0);
} /* running as daemon now */
if (freopen(logfile, "a", stderr) == NULL)
{
perror(logfile);
exit(1);
}
if ((n = open("/dev/isdn1", O_RDWR)) < 0)
{
perror("open: /dev/isdn1");
exit(1);
}
if ((f = fopen(configfile, "r")) == NULL)
{
perror(configfile);
exit(1);
}
process(f, n);
fclose(f);
(void) signal(SIGHUP, catchsighup);
(void) signal(SIGTERM, catchsig);
(void) signal(SIGKILL, catchsig);
(void) signal(SIGINT, catchsig);
(void) signal(SIGQUIT, catchsig);
rescan = quit = 0;
fprintf(stderr, "s:ittd started\n");
fflush(stderr);
while (1)
{
int l;
int an, cn, serv, serv_add, subadr;
int typ, nl, dl;
char *tn;
(void) setjmp(context);
if ((l = read(n, rbuf, 1024)) > 0)
{
switch (rbuf[0])
{
case 'a':
sscanf(rbuf + 2, "%d %d %d %d %d %d %d %n",
&an, &cn, &serv, &serv_add, &subadr, &typ, &nl, &l);
l += 2;
buf[0] = cn;
buf[1] = find_appl();
buf[2] = buf[3] = 0;
if (buf[1] == 0xff)
{
buf[2] = 0x3e; /* call reject */
}
if (ioctl(n, ISDN_ACCEPT, &buf) < 0)
{
perror("ioctl: Accept");
}
if (buf[1] == 0xff)
fprintf(stderr, "r:%d:%s\n", an, rbuf + l);
else
fprintf(stderr, "a:%d:%s\n", an, rbuf + l);
break;
case 'i':
sscanf(rbuf + 2, "%d %d %d %n", &an, &typ, &nl, &l);
fprintf(stderr, "i:%d:%x:%s\n", an, typ, rbuf + l + 2);
switch (typ)
{
case 2:
break;
}
break;
case 'C':
sscanf(rbuf + 2, "%d %d %d", &an, &cn, &dl);
if (dl)
{
buf[0] = cn;
buf[1] = an;
buf[2] = 0;
if (ioctl(n, ISDN_ACCEPT, buf) < 0)
{
perror("ioctl: Accept");
}
}
fprintf(stderr, "C:%d:%d\n", an, cn);
break;
case 'D':
sscanf(rbuf + 2, "%d %d", &an, &cn);
iline[an].occupied = 0;
fprintf(stderr, "D:%d:%d\n", an, cn);
break;
case 'M':
sscanf(rbuf + 2, "%d %n", &an, &l);
process_dial(n, an, rbuf + l + 2);
if (ioctl(n, ISDN_DIAL, &dial[an - NITTY]) < 0)
{
perror("ioctl: Dial");
}
fprintf(stderr, "d:%d:%s\n", an, &dial[an - NITTY].telno.no[1]);
break;
default:
break;
}
}
if (quit)
{
fprintf(stderr, "s:Quit\n");
exit(0);
}
if (rescan)
{
fprintf(stderr, "s:rescan\n");
rescan = 0;
if ((f = fopen(configfile, "r")) == NULL)
perror(configfile);
else
{
process(f, n);
fclose(f);
}
}
fflush(stderr);
}
}
int
find_appl()
{
int i;
struct iline *a;
for (i = 0; i < NITTY; i++)
{
a = &iline[i];
if (a->occupied == 0)
{
a->occupied = 1;
return (i);
}
}
return (-1);
}