1
0
Files
irix-657m-src/eoe/cmd/slip/slip.c
2022-09-29 17:59:04 +03:00

979 lines
21 KiB
C

/* IRIX SLIP deamon
*/
#ident "$Revision: 1.50 $"
#include <unistd.h>
#include <stdlib.h>
#include <values.h>
#include <getopt.h>
#include <fcntl.h>
#include <sys/param.h>
#include <sys/sysmacros.h>
#include <sys/types.h>
#include <sys/stropts.h>
#include <sys/time.h>
#include <stdio.h>
#include <errno.h>
#include <syslog.h>
#include <sys/if_sl.h>
#include <netdb.h>
#include <net/if.h>
#include <net/raw.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <arpa/inet.h>
#include <protocols/routed.h>
#define DEFINE
#include "pputil.h"
struct dev dv;
struct dev *dp0 = &dv;
/* This program runs in one of two modes. As the caller, it looks for
* the callee in the UUCP control files, dials it, identifies itself,
* and starts SLIPing. As the callee, when it is often run as if it
* were a 'shell,' it is given the address of caller either as
* an argument or in a single line of text from the caller. The
* callee then attaches its standard input and starts to SLIP.
*
* This code includes the necessary equivalent of ifconfig(1M).
*/
static int noicmp; /* >0 if dropping ICMP */
static int ccount; /* count of connections */
static struct afilter *afilter;
static int proto = SC_STD;
static int mtu = 0; /* limit interactive latency */
static int cur_mtu;
static char *remhost_nam;
static char *lochost_nam;
static void usage(void);
static void badhost(char*, char*);
static void make_mod(void);
static void init_afilter(void);
static void moredebug();
static void lessdebug();
void
main(int argc, char **argv)
{
int i;
long l;
char *p;
struct hostent *hp;
struct timeval timer;
time_t c_dly;
int was_idle;
fd_set in;
int fds;
char b;
struct servent *sp;
char ansbuf[128];
if (0 != (p = strrchr(argv[0], '/')))
pgmname = p+1;
else
pgmname = argv[0];
dv.callmode = UNKNOWN_CALL;
dv.devfd = -1;
dv.dev_index = -1;
dv.devfd_save = -1;
dv.rendpid = -1;
clr_acct(&dv);
dv.modwait = DEFAULT_ASYNC_MODWAIT;
dv.modtries = DEFAULT_MODTRIES;
ctty = open("/dev/tty", O_RDONLY|O_NDELAY);
if (isatty(stderrfd))
interact = 1;
else
no_interact();
openlog(pgmname, LOG_PID | LOG_ODELAY | LOG_NOWAIT, LOG_DAEMON);
opterr = 0;
while (i = getopt(argc,argv,"dcIm:M:s:A:P:T:R:S:p:u:l:r:ioq"),
i != EOF)
switch (i) {
case 'd':
++debug;
SET_Debug();
break;
case 'c':
if (dv.callmode == CALLEE) {
log_complain("","cannot camp as callee");
} else {
camping = 1;
}
break;
case 'I':
noicmp = 1;
break;
case 'm':
if (inet_aton(optarg, &netmask.sin_addr) <= 0) {
log_complain("","bad netmask \"%s\"",
optarg);
netmask.sin_addr.s_addr = 0;
}
break;
case 'M':
i = strtol(optarg,&p,0);
if (*p != '\0'
|| i < 0
|| i >= HOPCNT_INFINITY) {
log_complain("","bad metric \"%s\"",
optarg);
} else {
metric = i;
}
break;
case 's':
i = strtol(optarg,&p,0);
if (*p != '\0' || i < 256 || i > 16384) {
log_complain("","bad MTU \"%s\"", optarg);
} else {
cur_mtu = mtu = i;
}
break;
case 'A':
init_afilter();
sactime = strtol(optarg,&p,0);
if (*p == ',')
lactime = strtol(p+1,&p,0);
else
lactime = sactime;
if (*p != '\0' || sactime < MIN(DEFAULT_ASYNC_MODWAIT,
BEEP)
|| lactime < sactime) {
log_complain("","bad activity timer \"%s\"",
optarg);
lactime = DEFAULT_LACTIME;
sactime = DEFAULT_SACTIME;
}
break;
case 'P':
init_afilter();
if (optarg[0] == '-' && optarg[1] == '\0') {
bzero(afilter->port,sizeof(afilter->port));
} else if (0 != (sp = getservbyname(optarg, "tcp"))) {
SET_PORT(afilter, sp->s_port);
} else if (0 != (sp = getservbyname(optarg, "udp"))) {
SET_PORT(afilter, sp->s_port);
} else {
i = strtol(optarg,&p,0);
if (*p != '\0' || i < 1 || i > 65535) {
log_complain("","bad port \"%s\"",
optarg);
} else {
SET_PORT(afilter, i);
}
}
break;
case 'T':
init_afilter();
if (optarg[0] == '-' && optarg[1] == '\0') {
bzero(afilter->icmp,sizeof(afilter->icmp));
} else {
i = strtol(optarg,&p,0);
if (*p != '\0' || i < 0 || i > ICMP_MAXTYPE) {
log_complain("",
"bad ICMP type \"%s\"",
optarg);
} else {
SET_ICMP(afilter, i);
}
}
break;
case 'R':
if (add_route) {
log_complain("","only one -R permitted");
} else {
add_route = optarg;
}
break;
case 'S':
if (num_smods >= MAX_SMODS) {
log_complain("","too many -S arguments");
} else {
smods[num_smods++] = optarg;
}
break;
case 'p':
if (!strcmp(optarg,"std")) {
proto = SC_STD;
} else if (!strcmp(optarg,"cksum")) {
proto = SC_CKSUM;
} else if (!strcmp(optarg,"comp")) {
proto = SC_COMP;
} else if (!strcmp(optarg,"cslip")) {
proto = SC_CSLIP;
} else {
proto = -1;
}
switch (proto) {
case SC_STD:
case SC_CKSUM:
case SC_COMP:
case SC_CSLIP:
break;
default:
log_complain("","bad protocol \"%s\"",
optarg);
}
break;
case 'u':
if (dv.uucp_nam[0] != '\0')
usage();
(void)strncpy(dv.uucp_nam, optarg,
sizeof(dv.uucp_nam)-1);
break;
case 'l':
if (lochost_nam != 0)
usage();
lochost_nam = optarg;
break;
case 'r':
if (remote != 0)
usage();
remote = optarg;
break;
case 'i':
if (dv.callmode != UNKNOWN_CALL)
usage();
if (camping)
log_complain("","cannot camp as callee");
dv.callmode = CALLEE;
no_interact();
break;
case 'o':
if (dv.callmode != UNKNOWN_CALL)
usage();
dv.callmode = CALLER;
break;
case 'q':
if (dv.callmode != UNKNOWN_CALL)
usage();
dv.callmode = Q_CALLER;
init_afilter();
break;
default:
usage();
}
if (argc != optind)
usage();
if (debug)
kludge_stderr();
if (geteuid() != 0) {
log_complain("","requires UID 0");
exit(1);
}
dv.sync = SYNC_OFF;
dv.conf_sync = SYNC_OFF;
if (dv.callmode == UNKNOWN_CALL)
dv.callmode = (afilter != 0) ? Q_CALLER : CALLER;
if (dv.callmode == Q_CALLER && sactime == 0) {
lactime = DEFAULT_LACTIME;
sactime = DEFAULT_SACTIME;
}
if (dv.callmode != Q_CALLER && afilter != 0) {
log_complain("","cannot use -A, -P, or -T except with -q");
free(afilter);
afilter = 0;
}
demand_dial = (sactime != 0); /* XXX */
if (lochost_nam == 0) {
/* use our main name for the near side */
static char ourhost_nam[MAXHOSTNAMELEN];
if (0 > gethostname(&ourhost_nam[0], sizeof(ourhost_nam))) {
log_errno("gethostnam","");
exit(1);
}
lochost_nam = &ourhost_nam[0];
}
hp = gethostbyname(lochost_nam);
if (0 == hp)
badhost("local", lochost_nam);
lochost.sin_family = hp->h_addrtype;
bcopy(hp->h_addr, &lochost.sin_addr, sizeof(lochost.sin_addr));
if (dv.uucp_nam[0] == '\0') {
if (remote == 0)
usage();
(void)strncpy(dv.uucp_nam, remote,
sizeof(dv.uucp_nam)-1);
}
if (remote == 0) {
if (dv.uucp_nam[0] == '\0')
usage();
remote = dv.uucp_nam;
}
hp = gethostbyname(remhost_nam = remote);
if (0 == hp)
badhost("remote", remhost_nam);
remhost.sin_family = hp->h_addrtype;
bcopy(hp->h_addr, &remhost.sin_addr, sizeof(remhost.sin_addr));
if (add_route != 0
&& (add_route[0] == '\0'
|| (add_route[0] == '-' && add_route[1] == '\0'))) {
#ifdef SLIP_IRIX_53
add_route = malloc(sizeof("add default x 1")
+strlen(remhost_nam));
#else
add_route = malloc(sizeof("add default x")
+strlen(remhost_nam));
#endif
(void)strcpy(add_route, "add default ");
(void)strcat(add_route, remhost_nam);
#ifdef SLIP_IRIX_53
(void)strcat(add_route, " 1");
#endif
}
if (stderrpid <= 0)
stderrfd = -1; /* start complaining to system log */
(void)signal(SIGHUP, SIG_IGN);
(void)signal(SIGINT, cleanup);
(void)signal(SIGTERM, cleanup);
(void)signal(SIGUSR1, moredebug);
(void)signal(SIGUSR2, lessdebug);
for (;;) {
make_mod();
closefds(); /* avoid signals from the terminal */
if (dv.callmode == Q_CALLER) {
goto shut;
} else if (dv.callmode == RE_CALLEE
|| dv.callmode == CALLEE) {
if (!rdy_tty_dev(&dv)) /* get the device ready */
goto shut;
} else if (dv.callmode == CALLER
|| dv.callmode == RE_CALLER) {
i = get_conn(&dv,1);
if (!i) {
log_complain("","giving up for now");
if (0 > ioctl(modfd, TCFLSH, 2))
log_errno("ioctl(modfd,TCFLSH,2)","");
/* flush attention getters */
for (;;) {
i = read(modfd,ansbuf,sizeof(ansbuf));
if (i <= 0) {
if (errno != EAGAIN)
log_errno("clear read(modfd)", "");
goto shut;
}
}
}
if (i == 2) { /* rendezvoused */
continue;
}
if (!set_tty_modes(&dv))
goto shut;
/* If debugging, log the banner or anything else
* from the remote machine. Read the banner even
* if not debugging to be consistent and predictable.
*/
for (l = 0; l <= 3*sizeof(ansbuf); ) {
timer.tv_sec = 1;
timer.tv_usec = 1000000/20;
FD_ZERO(&in);
FD_SET(dv.devfd, &in);
if (0 > select(dv.devfd+1, &in,0,0, &timer)
&& errno != EINTR)
log_errno("banner select()","");
i = read(dv.devfd,ansbuf,sizeof(ansbuf));
if (i <= 0) {
if (i < 0)
log_errno("read(banner)","");
break;
}
if (!Debug)
continue;
if (l == 0)
fputs("banner: ",stderr);
for (p = ansbuf; p < &ansbuf[i]; p++, l++) {
*p = toascii(*p);
if (iscntrl(*p))
(void)fprintf(stderr,
"^%c",
(char)(*p+'@'));
else
(void)fprintf(stderr,"%c",*p);
}
}
if (l != 0)
putc('\n',stderr);
(void)fflush(stderr);
if (!rdy_tty_dev(&dv)) /* get the device ready */
goto shut;
}
++ccount;
if (demand_dial || debug > 0)
log_complain("",
((ccount > 1)
? "restart %s on %s using %s protocol"
: "start %s on %s using %s protocol"),
remote, dv.line,
((proto == SC_STD) ? "std"
: ((proto == SC_CKSUM) ? "cksum"
: ((proto == SC_COMP) ? "comp"
: "cslip"))));
/* Link the device STREAMS stack to the driver.
*/
dv.dev_index = ioctl(modfd,I_LINK,dv.devfd);
if (dv.dev_index < 0) {
log_errno("I_LINK","");
goto shut;
}
dv.devfd = -1;
/* set SLIP parameters
*/
dv.devtio.c_lflag = proto;
dv.devtio.c_oflag = (noicmp ? SC_NOICMP : 0);
#if defined(SLIP_IRIX_62) || defined(SLIP_IRIX_53)
if (mtu == 0 && (dv.devtio.c_cflag&CBAUD) == B38400)
#else
if (mtu == 0 && dv.devtio.c_ospeed >= B38400)
#endif
cur_mtu = 1500;
dv.devtio.c_cc[VMIN] = (cur_mtu>>8) & 0xff;
dv.devtio.c_cc[VTIME] = cur_mtu & 0xff;
if (0 > ioctl(modfd, TCSETA, (char*)&dv.devtio)) {
log_errno("TCSETA-on","");
goto shut;
}
/* Wait forever, or until the line dies.
*/
was_idle = 0;
act_devs(0,0);
fds = 1+MAX(modfd,rendnode);
for (;;) {
FD_ZERO(&in);
FD_SET(modfd, &in);
FD_SET(rendnode, &in);
timer.tv_usec = 0;
if (sactime == 0) {
timer.tv_sec = HEARTBEAT;
} else {
timer.tv_sec = dv.active - get_clk();
/* defend against time changes */
if (timer.tv_sec < 0)
timer.tv_sec = 0;
else if (timer.tv_sec > HEARTBEAT)
timer.tv_sec = HEARTBEAT;
}
i = select(fds, &in,0,0, &timer);
if (i < 0) {
if (errno == EINTR)
continue;
if (errno != EAGAIN)
bad_errno("select()","");
i = 0;
}
c_dly = get_clk() - dv.acct.sconn;
if (dv.callmode == CALLEE
|| dv.callmode == RE_CALLEE) {
dv.acct.ans_conn += c_dly;
if (i == 0 || was_idle)
dv.acct.ans_idle += c_dly;
} else {
dv.acct.orig_conn += c_dly;
if (i == 0 || was_idle)
dv.acct.orig_idle += c_dly;
}
dv.acct.sconn = clk.tv_sec;
ck_acct(&dv,0);
/* If things are quiet, maybe we should shut down
* the device.
*/
if (i == 0) {
was_idle = 1;
if (sactime != 0
&& clk.tv_sec > dv.active) {
log_debug(1,"",
"%s activity timer expired",
dv.line);
break;
}
} else if (was_idle) {
/* count idleness in previous period */
was_idle = 0;
}
if (FD_ISSET(modfd,&in)) {
/* see what the kernel has to say */
if (1 != read(modfd, &b, 1))
bad_errno("active read()","");
if (b == BEEP_DEAD) {
log_debug(1,"","line off");
break;
} else if (b == BEEP_ACTIVE) {
log_debug(2,"","TCP/IP active");
act_devs(0,1);
} else if (b == BEEP_WEAK) {
log_debug(2,"","IP active");
act_devs(1,1);
} else {
log_complain("","wild beep %#x", b);
}
}
if (FD_ISSET(rendnode,&in))
(void)rendezvous(0);
}
if (dv.callmode == CALLEE || dv.callmode == RE_CALLEE)
dv.acct.ans_conn += clk.tv_sec - dv.acct.sconn;
else
dv.acct.orig_conn += clk.tv_sec - dv.acct.sconn;
shut:
if (rendnode >= 0 && demand_dial) {
rel_dev(&dv);
c_dly = get_clk() + dv.modwait;
for (;;) {
(void)get_clk();
/* Check that the socket has not been removed.
* Quit if some other process owns the link.
*/
if (make_rend(1)) {
log_complain("","link stolen");
unmade_rend();
cleanup(1);
}
ck_acct(dp0,0);
FD_ZERO(&in);
FD_SET(rendnode, &in);
timer.tv_usec = 0;
if (clk.tv_sec >= c_dly) {
/* listen for new traffic
* after the modem has cooled
*/
timer.tv_sec = HEARTBEAT;
FD_SET(modfd, &in);
} else {
timer.tv_sec = c_dly - clk.tv_sec;
}
fds = 1+MAX(rendnode,modfd);
i = select(fds,&in,0,0, &timer);
if (i < 0) {
if (errno == EINTR)
continue;
if (errno != EAGAIN)
bad_errno("select()","");
i = 0;
}
dv.acct.sconn = get_clk();
if (i > 0) {
if (FD_ISSET(modfd,&in)) {
/* see what kernel has to say */
if (1 != read(modfd, &b, 1))
bad_errno("sleep read()",
"");
log_debug(2,"",
"read %#02x", b);
if (b == BEEP_ACTIVE
|| b == BEEP_WEAK) {
dv.callmode = RE_CALLER;
break;
} else {
log_complain("",
"odd beep %#x",
b);
}
}
if (FD_ISSET(rendnode,&in)
&& 0 != rendezvous(1)) {
break;
}
}
}
} else if (camping) {
/* If camping, try to reopen line. First make the
* interface go away for the rest of the system
*/
modfd = -1;
rel_dev(&dv);
(void)sleep(dv.modwait); /* let the modem cool */
} else {
/* must be simple, one-shot CALLEE */
cleanup(0);
}
}
}
static void
usage(void)
{
kludge_stderr();
(void)fprintf(stderr, "usage: [-dcI] [-m netmask] "
"[-M metric] [-s mtu] [-A secs[,secs]]\n "
"[-P port] [-T icmp_type] [-R \"routecmd\"] "
"[-S smods]\n [-p proto] [-u uucp] [-l local] "
"-r remote {-i|-o|-q}\n");
exit(1);
}
static void
badhost(char *msg, char *nam)
{
kludge_stderr();
(void)fprintf(stderr, "%s: %s %s: %s\n",
pgmname, msg, nam, hstrerror(h_errno));
exit(1);
}
/* create the protocol streams module/driver */
static void
make_mod(void)
{
# define RCMDV "route -n "
# define RCMD "route -n -q "
char *rcmd;
struct stat sbuf;
char newline[BUFSIZ];
if (modfd >= 0)
return;
init_rand();
if (dv.devfd < 0 && dv.callmode == CALLEE)
grab_dev("starting SLIP", &dv);
(void)add_rend_name("",inet_ntoa(remhost.sin_addr));
if (make_rend(1)) {
/* poke the existing daemon and wait for it
* to kill us
*/
log_debug(1,"","waiting to be killed");
no_signals(killed);
(void)sprintf(newline, "%.55s pid=%ld", dv.line, getpid());
if (0 > write(rendnode, newline, strlen(newline)+1))
bad_errno("write(caller poke) ",dv.line);
rends[0].made = 0;
rendnode = -1;
closefds();
for (;;)
(void)pause();
}
modfd = open("/dev/if_sl", O_RDWR | O_NONBLOCK);
if (0 > modfd)
bad_errno("open()","/dev/if_sl");
/* get the unit number */
if (0 > fstat(modfd, &sbuf))
bad_errno("fstat(unit#)","");
dv.unit = minor(sbuf.st_rdev);
(void)sprintf(ifname, "sl%d", dv.unit);
set_ip();
if (afilter != 0) {
int soc;
struct sockaddr_raw sr;
soc = socket(AF_RAW, SOCK_RAW, RAWPROTO_SNOOP);
if (soc < 0)
bad_errno("raw socket()","");
bzero(&sr, sizeof(sr));
(void)strncpy(sr.sr_ifname, ifname, sizeof(sr.sr_ifname));
sr.sr_family = AF_RAW;
sr.sr_port = 0;
if (0 > bind(soc, &sr, sizeof(sr))) {
perror("raw bind()");
cleanup(1);
}
if (0 > ioctl(soc, SIOC_SL_AFILTER, &afilter))
bad_errno("SIOC_SL_AFILTER","");
(void)close(soc);
}
/* Install a default route if asked.
* Decide each time whether to be verbose.
*/
if (add_route != 0) {
rcmd = malloc(strlen(RCMD)+strlen(add_route)+1);
sprintf(rcmd, "%s%s", debug ? RCMDV : RCMD, add_route);
call_system("", "", rcmd,0);
free(rcmd);
}
}
/* see what the other daemon wants
*/
int /* 1=took his device */
rendezvous(int mode) /* 0=kill him. 1=take his device */
{
char newlockfile[MAXPATHLEN]; /* lockfile name */
char newline[BUFSIZ];
char newnode[sizeof(dv.nodename)];
int newfd;
FILE *lf;
pid_t pid, ckpid;
int i;
extern void stlock(char*);
extern void sethup(int);
i = read(rendnode,newline,sizeof(newline));
if (i < 0) {
log_errno("read(rendnode)","");
return 0;
}
if (i < 5+1+1+4+1) {
log_complain("","bogus short rendezvous message \"%s\"",
newline);
return 0;
}
if (2 != sscanf(newline, "/dev/%50s pid=%ld", &newnode[0], &pid)) {
log_complain("","bogus rendezvous message \"%s\"",
newline);
return 0;
}
newline[strlen(newnode)+5] = '\0';
(void)lockname(newnode, newlockfile, sizeof(newlockfile));
lf = fopen(newlockfile,"r+");
if (!lf) {
log_errno("fopen(rendezvous) lock file ", newlockfile);
return 0;
}
if (1 != fscanf(lf, "%ld", &ckpid)
|| ckpid != pid) {
log_complain("","bogus rendezvous lock file: %s",
newlockfile);
(void)kill(pid,SIGINT);
(void)fclose(lf);
return 0;
}
/* If we do not need another port, kill the other guy and unlock
* his device.
*/
if (!mode) {
(void)kill(pid, SIGINT);
(void)unlink(newlockfile);
(void)fclose(lf);
log_debug(1,"","refuse to rendezvous with pid %d for %s",
pid,newline);
return 0;
}
/* Steal his device.
*/
newfd = open(newline,O_RDWR|O_NDELAY,0);
if (newfd < 0) {
log_errno("failed to steal ", newline);
(void)kill(pid, SIGINT);
return 0;
}
sethup(newfd);
(void)rewind(lf);
(void)fprintf(lf, LOCKPID_PAT, getpid());
stlock(newlockfile);
(void)fclose(lf);
/* remember to kill him */
dv.rendpid = pid;
dv.devfd = newfd;
dv.dev_index = -1;
dv.devfd_save = -1;
(void)strncpy(dv.line,newline,sizeof(dv.line));
(void)strncpy(dv.nodename,newnode,sizeof(dv.nodename));
(void)strncpy(dv.lockfile,newlockfile,sizeof(dv.lockfile));
dv.acct.sconn = get_clk();
dv.acct.answered++;
dv.callmode = RE_CALLEE;
log_debug(1,"","took %s from %d", dv.line, pid);
return 1;
}
/* create an initial stab at the activity filter
*/
static void
init_afilter(void)
{
static struct plist {
char *name;
int num;
} ports[] = {
{"daytime", 13},
{"time", 37},
{"ntp", 123},
{"route", 520},
{"timed", 525},
{"", 0}
};
struct plist *pp;
struct servent *sp;
if (afilter != 0)
return;
afilter = (struct afilter*)malloc(sizeof(*afilter));
bzero(afilter, sizeof(*afilter));
SET_ICMP(afilter, ICMP_UNREACH);
SET_ICMP(afilter, ICMP_SOURCEQUENCH);
SET_ICMP(afilter, ICMP_TSTAMP);
SET_ICMP(afilter, ICMP_TSTAMPREPLY);
for (pp = &ports[0]; pp->name[0] != '\0'; pp++) {
sp = getservbyname(pp->name, "tcp");
if (!sp)
sp = getservbyname(pp->name, "udp");
if (!sp)
SET_PORT(afilter, pp->num);
else
SET_PORT(afilter, sp->s_port);
}
}
/* dummy since SLIP does not log in or out
*/
/* ARGSUSED */
void
dologout(struct dev *dp)
{
}
/* change debugging
*/
static void
moredebug()
{
int soc;
struct ifreq ifr;
++debug;
SET_Debug();
if (debug != 0)
kludge_stderr();
if (debug > 1 &&ifname[0] != '\0') {
soc = socket(AF_INET, SOCK_DGRAM, 0);
if (soc < 0)
log_errno("moredebug socket()","");
(void)strncpy(ifr.ifr_name, ifname,
sizeof(ifr.ifr_name));
if (0 > ioctl(soc, SIOCGIFFLAGS, (char*)&ifr))
log_errno("moredebug SIOCGIFFLAGS","");
ifr.ifr_flags |= IFF_DEBUG;
(void)strncpy(ifr.ifr_name, ifname,
sizeof(ifr.ifr_name));
if (0 > ioctl(soc, SIOCSIFFLAGS, (char*)&ifr))
log_errno("moredebug SIOCSIFFLAGS","");
}
log_complain("","debug=%d", debug);
(void)signal(SIGUSR1, moredebug);
}
static void
lessdebug()
{
int soc;
struct ifreq ifr;
if (--debug < 1)
debug = 0;
SET_Debug();
if (debug <= 1 && ifname[0] != '\0') {
soc = socket(AF_INET, SOCK_DGRAM, 0);
if (soc < 0)
log_errno("lessdebug socket()","");
(void)strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
if (0 > ioctl(soc, SIOCGIFFLAGS, (char*)&ifr))
log_errno("lessdebug SIOCGIFFLAGS","");
ifr.ifr_flags &= ~IFF_DEBUG;
(void)strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
if (0 > ioctl(soc, SIOCSIFFLAGS, (char*)&ifr))
log_errno("lessdebug SIOCSIFFLAGS","");
}
log_complain("","debug=%d", debug);
(void)signal(SIGUSR2, lessdebug);
}