From 19183e73b6c19edca9ac45f9371ebe67aef133ec Mon Sep 17 00:00:00 2001 From: Michiel Broek Date: Fri, 22 Feb 2002 21:15:21 +0000 Subject: [PATCH] mbtask added portcheck, code cleanup --- ChangeLog | 2 + mbtask/Makefile | 16 +- mbtask/calllist.c | 154 +++++++++++++++++ mbtask/calllist.h | 26 +++ mbtask/mbtask.c | 420 ++-------------------------------------------- mbtask/mbtask.h | 30 ++-- mbtask/outstat.c | 106 +----------- mbtask/outstat.h | 17 -- mbtask/ping.c | 370 ++++++++++++++++++++++++++++++++++++++++ mbtask/ping.h | 22 +++ mbtask/ports.c | 188 +++++++++++++++++++++ mbtask/ports.h | 28 ++++ 12 files changed, 828 insertions(+), 551 deletions(-) create mode 100644 mbtask/calllist.c create mode 100644 mbtask/calllist.h create mode 100644 mbtask/ping.c create mode 100644 mbtask/ping.h create mode 100644 mbtask/ports.c create mode 100644 mbtask/ports.h diff --git a/ChangeLog b/ChangeLog index 82603287..85ddaa67 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4637,6 +4637,8 @@ v0.33.20 10-Feb-2002 Removed some debug logging. Creates the semafore is_inet when the internet connections is available, and removes it when it is down. + Added test for ISDN/modem lines in use. + Lost of code cleanup. mbcico: Fixed binkp driver to accept incoming unprotected sessions. diff --git a/mbtask/Makefile b/mbtask/Makefile index f25ddf72..cd3b9cb4 100644 --- a/mbtask/Makefile +++ b/mbtask/Makefile @@ -5,11 +5,14 @@ include ../Makefile.global SRCS = callstat.c nodelist.c scanout.c taskcomm.c taskinfo.c taskstat.c \ - mbtask.c outstat.c signame.c taskdisk.c taskregs.c taskutil.c + mbtask.c outstat.c signame.c taskdisk.c taskregs.c taskutil.c \ + ports.c calllist.c ping.c HDRS = callstat.h mbtask.h outstat.h signame.h taskdisk.h taskregs.h taskutil.h \ - libs.h nodelist.h scanout.h taskcomm.h taskinfo.h taskstat.h + libs.h nodelist.h scanout.h taskcomm.h taskinfo.h taskstat.h \ + ports.h calllist.h ping.h OBJS = callstat.o nodelist.o scanout.o taskcomm.o taskinfo.o taskstat.o \ - mbtask.o outstat.o signame.o taskdisk.o taskregs.o taskutil.o + mbtask.o outstat.o signame.o taskdisk.o taskregs.o taskutil.o \ + ports.o calllist.o ping.o OTHER = Makefile issue issue.netbsd ############################################################################# @@ -80,10 +83,13 @@ scanout.o: libs.h ../lib/structs.h taskutil.h scanout.h taskcomm.o: libs.h ../lib/structs.h taskstat.h taskregs.h taskdisk.h taskinfo.h taskutil.h taskcomm.h taskinfo.o: libs.h ../lib/structs.h taskinfo.h taskstat.o: libs.h ../lib/structs.h taskstat.h callstat.h outstat.h taskutil.h -mbtask.o: libs.h ../lib/structs.h signame.h taskstat.h taskutil.h taskregs.h taskcomm.h callstat.h outstat.h nodelist.h mbtask.h -outstat.o: libs.h ../lib/structs.h taskutil.h taskstat.h scanout.h nodelist.h callstat.h outstat.h +mbtask.o: libs.h ../lib/structs.h signame.h taskstat.h taskutil.h taskregs.h taskcomm.h callstat.h outstat.h nodelist.h ports.h calllist.h ping.h mbtask.h +outstat.o: libs.h ../lib/structs.h taskutil.h taskstat.h scanout.h nodelist.h callstat.h ports.h outstat.h signame.o: signame.h taskdisk.o: libs.h ../lib/structs.h taskdisk.h taskutil.h taskregs.o: libs.h ../lib/structs.h taskstat.h taskregs.h taskutil.h taskutil.o: libs.h ../lib/structs.h signame.h scanout.h taskutil.h +ports.o: libs.h ../lib/structs.h taskutil.h nodelist.h ports.h +calllist.o: libs.h ../lib/structs.h taskstat.h taskutil.h callstat.h outstat.h mbtask.h ports.h calllist.h +ping.o: libs.h ../lib/structs.h taskstat.h taskutil.h ping.h # End of generated dependencies diff --git a/mbtask/calllist.c b/mbtask/calllist.c new file mode 100644 index 00000000..5c11567c --- /dev/null +++ b/mbtask/calllist.c @@ -0,0 +1,154 @@ +/***************************************************************************** + * + * $Id$ + * Purpose ...............: mbtask - calllist + * + ***************************************************************************** + * Copyright (C) 1997-2002 + * + * Michiel Broek FIDO: 2:280/2802 + * Beekmansbos 10 + * 1971 BV IJmuiden + * the Netherlands + * + * This file is part of MBSE BBS. + * + * This BBS is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * MBSE BBS is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with MBSE BBS; see the file COPYING. If not, write to the Free + * Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + *****************************************************************************/ + +#include "libs.h" +#include "../lib/structs.h" +#include "taskstat.h" +#include "taskutil.h" +#include "callstat.h" +#include "outstat.h" +#include "mbtask.h" +#include "ports.h" +#include "calllist.h" + + + +/* + * Global variables + */ +tocall calllist[MAXTASKS]; /* Array with calllist */ +extern int internet; /* Internet is down */ +extern int s_scanout; /* Scan outbound sema */ +extern int s_do_inet; /* Internet wanted */ +extern _alist_l *alist; /* Nodes to call list */ +extern int pots_calls; +extern int isdn_calls; +extern int inet_calls; + + + + +/* + * Check the actual list of nodes to call. + */ +int check_calllist(void) +{ + int i, found, call_work; + struct _alist *tmp; + + /* + * Check callist, remove obsolete entries. + */ + for (i = 0; i < MAXTASKS; i++) { + if (calllist[i].addr.zone) { + found = FALSE; + for (tmp = alist; tmp; tmp = tmp->next) { + if ((calllist[i].addr.zone == tmp->addr.zone) && (calllist[i].addr.net == tmp->addr.net) && + (calllist[i].addr.node == tmp->addr.node) && (calllist[i].addr.point == tmp->addr.point) && + ((tmp->flavors) & F_CALL)) { + found = TRUE; + } + } + if (!found) { + tasklog('c', "Removing slot %d node %s from calllist", i, ascfnode(calllist[i].addr, 0x0f)); + memset(&calllist[i], 0, sizeof(tocall)); + } + } + } + + check_ports(); + + if (pots_calls || isdn_calls || inet_calls) { + call_work = 0; + for (tmp = alist; tmp; tmp = tmp->next) { + if (tmp->callmode != CM_NONE) { + call_work++; + found = FALSE; + for (i = 0; i < MAXTASKS; i++) { + if ((calllist[i].addr.zone == tmp->addr.zone) && (calllist[i].addr.net == tmp->addr.net) && + (calllist[i].addr.node == tmp->addr.node) && (calllist[i].addr.point == tmp->addr.point)) { + found = TRUE; + /* + * Refresh last call status + */ + calllist[i].cst = tmp->cst; + } + } + if (!found) { + for (i = 0; i < MAXTASKS; i++) { + if (!calllist[i].addr.zone) { + tasklog('c', "Adding %s to calllist slot %d", ascfnode(tmp->addr, 0x1f), i); + calllist[i].addr = tmp->addr; + calllist[i].cst = tmp->cst; + calllist[i].callmode = tmp->callmode; + calllist[i].moflags = tmp->moflags; + calllist[i].diflags = tmp->diflags; + calllist[i].ipflags = tmp->ipflags; + break; + } + } + } + } + } + tasklog('o', "%d systems to call", call_work); + } else { + if (s_scanout) + sem_set((char *)"scanout", FALSE); + } + + /* + * Check if we need to remove the do_inet semafore + */ + if (!inet_calls && internet && s_do_inet) { + tasklog('c', "Removing do_inet semafore"); + s_do_inet = FALSE; + if (IsSema((char *)"do_inet")) { + RemoveSema((char *)"do_inet"); + } + } + + call_work = 0; + for (i = 0; i < MAXTASKS; i++) { + if (calllist[i].addr.zone) { + if (!call_work) { + tasklog('c', "Slot Call Pid Try Status Mode Modem ISDN TCP/IP Address"); + tasklog('c', "---- ----- ----- --- ------- ------- -------- -------- -------- ----------------"); + } + call_work++; + tasklog('c', "%4d %s %5d %3d %s %s %08x %08x %08x %s", i, calllist[i].calling?"true ":"false", calllist[i].taskpid, + calllist[i].cst.tryno, callstatus(calllist[i].cst.trystat), callmode(calllist[i].callmode), + calllist[i].moflags, calllist[i].diflags, calllist[i].ipflags, ascfnode(calllist[i].addr, 0x1f)); + } + } + + return call_work; +} + + diff --git a/mbtask/calllist.h b/mbtask/calllist.h new file mode 100644 index 00000000..7b6dc198 --- /dev/null +++ b/mbtask/calllist.h @@ -0,0 +1,26 @@ +/* $Id$ */ + +#ifndef _CALLLIST_H +#define _CALLLIST_H + + + +/* + * Callist + */ +typedef struct _tocall { + fidoaddr addr; /* Address to call */ + int callmode; /* Method to use */ + callstat cst; /* Last call status */ + int calling; /* Is calling */ + pid_t taskpid; /* Task pid number */ + unsigned long moflags; /* Modem flags */ + unsigned long diflags; /* ISDN flags */ + unsigned long ipflags; /* TCP/IP flags */ +} tocall; + + +int check_calllist(void); + +#endif + diff --git a/mbtask/mbtask.c b/mbtask/mbtask.c index 503c56e8..9b546c19 100644 --- a/mbtask/mbtask.c +++ b/mbtask/mbtask.c @@ -38,32 +38,18 @@ #include "callstat.h" #include "outstat.h" #include "nodelist.h" +#include "ports.h" +#include "calllist.h" +#include "ping.h" #include "mbtask.h" -/* - * Defines. - * SLOWRUN is number of seconds for scheduling mailer calls. Leave at 20! - */ -#define MAXTASKS 10 -#define SLOWRUN 20 -#define TMPNAME "TMP." -#define LCKNAME "LOCKTASK" -#define ICMP_BASEHDR_LEN 8 -#define ICMP_MAX_ERRS 5 -#define SET_SOCKA_LEN4(socka) - - -typedef enum {P_INIT, P_SENT, P_FAIL, P_OK, P_ERROR, P_NONE} PINGSTATE; - - - /* * Global variables */ static onetask task[MAXTASKS]; /* Array with tasks */ -static tocall calllist[MAXTASKS]; /* Array with calllist */ +extern tocall calllist[MAXTASKS]; /* Array with calllist */ reg_info reginfo[MAXCLIENT]; /* Array with clients */ static pid_t pgrp; /* Pids group */ static char lockfile[PATH_MAX]; /* Lockfile */ @@ -85,8 +71,7 @@ time_t tty_time; /* TTY config time */ char tcfgfn[PATH_MAX]; /* Config file name */ char cfgfn[PATH_MAX]; /* Config file name */ char ttyfn[PATH_MAX]; /* TTY file name */ -int ping_isocket; /* Ping socket */ -int icmp_errs = 0; /* ICMP error counter */ +extern int ping_isocket; /* Ping socket */ int internet = FALSE; /* Internet is down */ double Load; /* System Load */ int Processing; /* Is system running */ @@ -101,10 +86,7 @@ extern int s_newnews; /* New news semafore */ extern int s_reqindex; /* Create req index sem */ extern int s_msglink; /* Messages link sem */ extern int s_do_inet; /* Internet wanted */ -int pingstate = P_INIT; /* Ping state */ -int pingnr = 1; /* Ping #, 1 or 2 */ -int pingresult[2]; /* Ping results */ -char pingaddress[41]; /* Ping current address */ +extern int pingresult[2]; /* Ping results */ int masterinit = FALSE; /* Master init needed */ int ptimer = PAUSETIME; /* Pause timer */ int tflags = FALSE; /* if nodes with Txx */ @@ -466,103 +448,6 @@ void load_taskcfg(void) -/* - * Check the actual list of nodes to call. - */ -int check_calllist(void); -int check_calllist(void) -{ - int i, found, call_work; - struct _alist *tmp; - - /* - * Check callist, remove obsolete entries. - */ - for (i = 0; i < MAXTASKS; i++) { - if (calllist[i].addr.zone) { - found = FALSE; - for (tmp = alist; tmp; tmp = tmp->next) { - if ((calllist[i].addr.zone == tmp->addr.zone) && (calllist[i].addr.net == tmp->addr.net) && - (calllist[i].addr.node == tmp->addr.node) && (calllist[i].addr.point == tmp->addr.point) && - ((tmp->flavors) & F_CALL)) { - found = TRUE; - } - } - if (!found) { - tasklog('c', "Removing slot %d node %s from calllist", i, ascfnode(calllist[i].addr, 0x0f)); - memset(&calllist[i], 0, sizeof(tocall)); - } - } - } - - if (pots_calls || isdn_calls || inet_calls) { - call_work = 0; - for (tmp = alist; tmp; tmp = tmp->next) { - if (tmp->callmode != CM_NONE) { - call_work++; - found = FALSE; - for (i = 0; i < MAXTASKS; i++) { - if ((calllist[i].addr.zone == tmp->addr.zone) && (calllist[i].addr.net == tmp->addr.net) && - (calllist[i].addr.node == tmp->addr.node) && (calllist[i].addr.point == tmp->addr.point)) { - found = TRUE; - /* - * Refresh last call status - */ - calllist[i].cst = tmp->cst; - } - } - if (!found) { - for (i = 0; i < MAXTASKS; i++) { - if (!calllist[i].addr.zone) { - tasklog('c', "Adding %s to calllist slot %d", ascfnode(tmp->addr, 0x1f), i); - calllist[i].addr = tmp->addr; - calllist[i].cst = tmp->cst; - calllist[i].callmode = tmp->callmode; - calllist[i].moflags = tmp->moflags; - calllist[i].diflags = tmp->diflags; - calllist[i].ipflags = tmp->ipflags; - break; - } - } - } - } - } - tasklog('o', "%d systems to call", call_work); - } else { - if (s_scanout) - sem_set((char *)"scanout", FALSE); - } - - /* - * Check if we need to remove the do_inet semafore - */ - if (!inet_calls && internet && s_do_inet) { - tasklog('c', "Removing do_inet semafore"); - s_do_inet = FALSE; - if (IsSema((char *)"do_inet")) { - RemoveSema((char *)"do_inet"); - } - } - - call_work = 0; - for (i = 0; i < MAXTASKS; i++) { - if (calllist[i].addr.zone) { - if (!call_work) { - tasklog('c', "Slot Call Pid Try Status Mode Modem ISDN TCP/IP Address"); - tasklog('c', "---- ----- ----- --- ------- ------- -------- -------- -------- ----------------"); - } - call_work++; - tasklog('c', "%4d %s %5d %3d %s %s %08x %08x %08x %s", i, calllist[i].calling?"true ":"false", calllist[i].taskpid, - calllist[i].cst.tryno, callstatus(calllist[i].cst.trystat), callmode(calllist[i].callmode), - calllist[i].moflags, calllist[i].diflags, calllist[i].ipflags, ascfnode(calllist[i].addr, 0x1f)); - } - } - - return call_work; -} - - - /* * Launch an external program in the background. * On success add it to the tasklist and return @@ -885,216 +770,6 @@ void ulocktask(void) } -/* different names, same thing... be careful, as these are macros... */ -#if defined(__FreeBSD__) || defined(__NetBSD__) -# define icmphdr icmp -# define iphdr ip -# define ip_saddr ip_src.s_addr -# define ip_daddr ip_dst.s_addr -#else -# define ip_saddr saddr -# define ip_daddr daddr -# define ip_hl ihl -# define ip_p protocol -#endif - - -#ifdef __linux__ -# define icmp_type type -# define icmp_code code -# define icmp_cksum checksum -# ifdef icmp_id -# undef icmp_id -# endif -# define icmp_id un.echo.id -# ifdef icmp_seq -# undef icmp_seq -# endif -# define icmp_seq un.echo.sequence -#endif - -#if defined(__FreeBSD__) || defined(__NetBSD__) -# define ICMP_DEST_UNREACH ICMP_UNREACH -# define ICMP_TIME_EXCEEDED ICMP_TIMXCEED -#endif - -#define ICMP_BASEHDR_LEN 8 -#define ICMP4_ECHO_LEN ICMP_BASEHDR_LEN - - - -/* - * Takes a packet as send out and a recieved ICMP packet and looks whether the ICMP packet is - * an error reply on the sent-out one. packet is only the packet (without IP header). - * errmsg includes an IP header. - * to is the destination address of the original packet (the only thing that is actually - * compared of the IP header). The RFC sais that we get at least 8 bytes of the offending packet. - * We do not compare more, as this is all we need. - */ -static int icmp4_errcmp(char *packet, int plen, struct in_addr *to, char *errmsg, int elen, int errtype) -{ - struct iphdr iph; - struct icmphdr icmph; - struct iphdr eiph; - char *data; - - /* XXX: lots of memcpy to avoid unaligned accesses on alpha */ - if (elen < sizeof(struct iphdr)) - return 0; - memcpy(&iph, errmsg, sizeof(iph)); - if (iph.ip_p != IPPROTO_ICMP || elen < iph.ip_hl * 4 + ICMP_BASEHDR_LEN + sizeof(eiph)) - return 0; - memcpy(&icmph, errmsg + iph.ip_hl * 4, ICMP_BASEHDR_LEN); - memcpy(&eiph, errmsg + iph.ip_hl * 4 + ICMP_BASEHDR_LEN, sizeof(eiph)); - if (elen < iph.ip_hl * 4 + ICMP_BASEHDR_LEN + eiph.ip_hl * 4 + 8) - return 0; - data = errmsg + iph.ip_hl * 4 + ICMP_BASEHDR_LEN + eiph.ip_hl * 4; - return icmph.icmp_type == errtype && memcmp(&to->s_addr, &eiph.ip_daddr, sizeof(to->s_addr)) == 0 && - memcmp(data, packet, plen < 8 ?plen:8) == 0; -} - - - -unsigned short get_rand16(void) -{ - return random()&0xffff; -} - - -short p_sequence = 0; -unsigned short id; -struct icmphdr icmpd; -struct sockaddr_in to; - -/* - * IPv4/ICMPv4 ping. Called from ping (see below) - */ -int ping_send(struct in_addr addr) -{ - int len; - int isock; -#ifdef __linux__ - struct icmp_filter f; -#else - struct protoent *pe; - int SOL_IP; -#endif - unsigned long sum; - unsigned short *ptr; - -#ifndef __linux__ - if (!(pe = getprotobyname("ip"))) { - tasklog('?', "icmp ping: getprotobyname() failed: %s", strerror(errno)); - return -1; - } - SOL_IP = pe->p_proto; -#endif - - isock = ping_isocket; - p_sequence = 1; - id = (unsigned short)get_rand16(); /* randomize a ping id */ - -#ifdef __linux__ - /* Fancy ICMP filering -- only on Linux (as far is I know) */ - - /* In fact, there should be macros for treating icmp_filter, but I haven't found them in Linux 2.2.15. - * So, set it manually and unportable ;-) */ - /* This filter lets ECHO_REPLY (0), DEST_UNREACH(3) and TIME_EXCEEDED(11) pass. */ - /* !(0000 1000 0000 1001) = 0xff ff f7 f6 */ - f.data=0xfffff7f6; - if (setsockopt(isock, SOL_RAW, ICMP_FILTER, &f, sizeof(f)) == -1) { - if (icmp_errs < ICMP_MAX_ERRS) - tasklog('?', "$icmp ping: setsockopt() failed %d", isock); - return -1; - } -#endif - - icmpd.icmp_type = ICMP_ECHO; - icmpd.icmp_code = 0; - icmpd.icmp_cksum = 0; - icmpd.icmp_id = htons((short)id); - icmpd.icmp_seq = htons(p_sequence); - - /* Checksumming - Algorithm taken from nmap. Thanks... */ - - ptr = (unsigned short *)&icmpd; - sum = 0; - - for (len = 0; len < 4; len++) { - sum += *ptr++; - } - sum = (sum >> 16) + (sum & 0xffff); - sum += (sum >> 16); - icmpd.icmp_cksum = ~sum; - - memset(&to, 0, sizeof(to)); - to.sin_family = AF_INET; - to.sin_port = 0; - to.sin_addr = addr; - SET_SOCKA_LEN4(to); - if (sendto(isock, &icmpd, ICMP4_ECHO_LEN, 0, (struct sockaddr *)&to, sizeof(to)) == -1) { - return -2; - } - return 0; -} - - - -int ping_receive(struct in_addr addr) -{ - char buf[1024]; - int isock; - int len; - struct sockaddr_in ffrom; - struct icmphdr icmpp; - struct iphdr iph; - socklen_t sl; - struct pollfd pfd; - - isock = ping_isocket; - - pfd.fd = isock; - pfd.events = POLLIN; - /* - * 10 mSec is enough, this function is called at regular intervals. - */ - if (poll(&pfd, 1, 10) < 0) { - if (icmp_errs < ICMP_MAX_ERRS) - tasklog('?', "$poll/select failed"); - return -3; - } - - if (pfd.revents & POLLIN || pfd.revents & POLLERR || pfd.revents & POLLHUP || pfd.revents & POLLNVAL) { - sl = sizeof(ffrom); - if ((len = recvfrom(isock, &buf, sizeof(buf), 0,(struct sockaddr *)&ffrom, &sl)) != -1) { - if (len > sizeof(struct iphdr)) { - memcpy(&iph, buf, sizeof(iph)); - if (len - iph.ip_hl * 4 >= ICMP_BASEHDR_LEN) { - memcpy(&icmpp, ((unsigned long int *)buf)+iph.ip_hl, sizeof(icmpp)); - if (iph.ip_saddr == addr.s_addr && - icmpp.icmp_type == ICMP_ECHOREPLY && - ntohs(icmpp.icmp_id) == id && - ntohs(icmpp.icmp_seq) <= p_sequence) { - return 0; - } else { - /* No regular echo reply. Maybe an error? */ - if (icmp4_errcmp((char *)&icmpd, ICMP4_ECHO_LEN, - &to.sin_addr, buf, len, ICMP_DEST_UNREACH) || - icmp4_errcmp((char *)&icmpd, ICMP4_ECHO_LEN, - &to.sin_addr, buf, len, ICMP_TIME_EXCEEDED)) { - return -4; - } - } - } - } - } else { - return -5; /* error */ - } - } - return -6; /* no answer */ -} - - /* * External Semafore Checks @@ -1169,7 +844,6 @@ void scheduler(void) FILE *fp; #endif struct pollfd pfd; - struct in_addr paddr; int call_work; static int call_entry = MAXTASKS; double loadavg[3]; @@ -1271,7 +945,7 @@ void scheduler(void) check_sema(); /* - * Check the systems load average. FIXME: doesn't work in FreeBSD !!! + * Check the systems load average. */ Load = loadavg[0] = loadavg[1] = loadavg[2] = 0.0; #if defined(__FreeBSD__) || defined(__NetBSD__) @@ -1345,6 +1019,7 @@ void scheduler(void) if (file_time(ttyfn) != tty_time) { tasklog('+', "Ports configuration changed, reloading"); load_ports(); + check_ports(); sem_set((char *)"scanout", TRUE); } @@ -1440,69 +1115,7 @@ void scheduler(void) */ oldmin = tm->tm_sec / SLOWRUN; - /* - * If the previous pingstat is still P_SENT, then we now consider it a timeout. - */ - if (pingstate == P_SENT) { - pingresult[pingnr] = FALSE; - icmp_errs++; - if (icmp_errs < ICMP_MAX_ERRS) - tasklog('p', "ping %s seq=%d timeout", pingaddress, p_sequence); - } - - /* - * Check internet connection with ICMP ping - */ - rc = 0; - if (pingnr == 1) { - pingnr = 2; - if (strlen(TCFG.isp_ping2)) { - sprintf(pingaddress, "%s", TCFG.isp_ping2); - } else { - pingstate = P_NONE; - } - } else { - pingnr = 1; - if (strlen(TCFG.isp_ping1)) { - sprintf(pingaddress, "%s", TCFG.isp_ping1); - } else { - pingstate = P_NONE; - } - } - - if (inet_aton(pingaddress, &paddr)) { - rc = ping_send(paddr); - if (rc) { - if (icmp_errs++ < ICMP_MAX_ERRS) - tasklog('?', "ping send %s rc=%d", pingaddress, rc); - pingstate = P_FAIL; - pingresult[pingnr] = FALSE; - } else { - pingstate = P_SENT; - } - } else { - if (icmp_errs++ < ICMP_MAX_ERRS) - tasklog('?', "Ping address %d is invalid \"%s\"", pingnr, pingaddress); - pingstate = P_NONE; - } - - if (pingresult[1] == FALSE && pingresult[2] == FALSE) { - icmp_errs++; - if (internet) { - tasklog('!', "Internet connection is down"); - internet = FALSE; - sem_set((char *)"scanout", TRUE); - RemoveSema((char *)"is_inet"); - } - } else { - if (!internet) { - tasklog('!', "Internet connection is up"); - internet = TRUE; - sem_set((char *)"scanout", TRUE); - CreateSema((char *)"is_inet"); - } - icmp_errs = 0; - } + check_ping(); /* * Update outbound status if needed. @@ -1580,19 +1193,7 @@ void scheduler(void) /* * PING state changes */ - switch (pingstate) { - case P_NONE: pingresult[pingnr] = TRUE; - break; - case P_SENT: rc = ping_receive(paddr); - if (!rc) { - pingstate = P_OK; - pingresult[pingnr] = TRUE; - } else { - if (rc != -6) - tasklog('p', "ping recv %s id=%d rc=%d", pingaddress, id, rc); - } - break; - } + state_ping(); } else { if (Processing) { @@ -1679,6 +1280,7 @@ int main(int argc, char **argv) sprintf(ttyfn, "%s/etc/ttyinfo.data", getenv("MBSE_ROOT")); load_ports(); + check_ports(); /* * Now that init is complete and this program is locked, it is diff --git a/mbtask/mbtask.h b/mbtask/mbtask.h index 83255dd5..c7270d8a 100644 --- a/mbtask/mbtask.h +++ b/mbtask/mbtask.h @@ -1,6 +1,16 @@ +/* $Id */ + #ifndef _MBTASK_H #define _MBTASK_H +/* + * Defines. + * SLOWRUN is number of seconds for scheduling mailer calls. Leave at 20! + */ +#define MAXTASKS 10 +#define SLOWRUN 20 +#define TMPNAME "TMP." +#define LCKNAME "LOCKTASK" /* @@ -19,22 +29,6 @@ typedef struct _onetask { -/* - * Callist - */ -typedef struct _tocall { - fidoaddr addr; /* Address to call */ - int callmode; /* Method to use */ - callstat cst; /* Last call status */ - int calling; /* Is calling */ - pid_t taskpid; /* Task pid number */ - unsigned long moflags; /* Modem flags */ - unsigned long diflags; /* ISDN flags */ - unsigned long ipflags; /* TCP/IP flags */ -} tocall; - - - /* * Logging flagbits, ' ' ? ! + - */ @@ -53,10 +47,6 @@ pid_t launch(char *, char *, char *, int); int runtasktype(int); int checktasks(int); void die(int); -static int icmp4_errcmp(char *, int, struct in_addr *, char *, int, int); -unsigned short get_rand16(void); -int ping_send(struct in_addr); -int ping_receive(struct in_addr); void scheduler(void); int locktask(char *); void ulocktask(void); diff --git a/mbtask/outstat.c b/mbtask/outstat.c index ff422a1c..e8fa42e2 100644 --- a/mbtask/outstat.c +++ b/mbtask/outstat.c @@ -35,6 +35,7 @@ #include "scanout.h" #include "nodelist.h" #include "callstat.h" +#include "ports.h" #include "outstat.h" @@ -42,13 +43,11 @@ extern int do_quiet; extern int internet; /* Internet status */ extern struct sysconfig CFG; /* Main configuration */ extern struct taskrec TCFG; /* Task configuration */ -extern char ttyfn[]; /* TTY file name */ -extern time_t tty_time; /* TTY update time */ int nxt_hour, nxt_min; /* Time of next event */ int inet_calls; /* Internet calls to make */ int isdn_calls; /* ISDN calls to make */ int pots_calls; /* POTS calls to make */ -pp_list *pl = NULL; /* Portlist */ +extern pp_list *pl; /* Portlist */ _alist_l *alist = NULL; /* Nodes to call list */ extern int s_do_inet; /* Internet wanted */ @@ -383,7 +382,7 @@ int outstat() */ if ((tmp->callmode == CM_NONE) && TCFG.max_isdn) { /* - * Dialup node, check available dialout ports + * ISDN node, check available dialout ports */ for (tpl = pl; tpl; tpl = tpl->next) { if (tpl->dflags & tmp->diflags) { @@ -394,6 +393,9 @@ int outstat() } } if ((tmp->callmode == CM_NONE) && TCFG.max_pots) { + /* + * POTS node, check available modems + */ for (tpl = pl; tpl; tpl = tpl->next) { if (tpl->mflags & tmp->moflags) { pots_calls++; @@ -563,99 +565,3 @@ int each(faddr *addr, char flavor, int isflo, char *fname) } - -/* - * Tidy the portlist - */ -void tidy_portlist(pp_list **); -void tidy_portlist(pp_list ** fdp) -{ - pp_list *tmp, *old; - - tasklog('p', "tidy_portlist"); - for (tmp = *fdp; tmp; tmp = old) { - old = tmp->next; - free(tmp); - } - *fdp = NULL; -} - - - -/* - * Add a port to the portlist - */ -void fill_portlist(pp_list **, pp_list *); -void fill_portlist(pp_list **fdp, pp_list *new) -{ - pp_list *tmp, *ta; - - tmp = (pp_list *)malloc(sizeof(pp_list)); - tmp->next = NULL; - strncpy(tmp->tty, new->tty, 6); - tmp->mflags = new->mflags; - tmp->dflags = new->dflags; - - if (*fdp == NULL) { - *fdp = tmp; - } else { - for (ta = *fdp; ta; ta = ta->next) - if (ta->next == NULL) { - ta->next = (pp_list *)tmp; - break; - } - } -} - - - -/* - * Build a list of available dialout ports. - */ -void load_ports() -{ - FILE *fp; - pp_list new; - int count = 0, j, stdflag; - char *p, *q; - - tidy_portlist(&pl); - if ((fp = fopen(ttyfn, "r")) == NULL) { - tasklog('?', "$Can't open %s", ttyfn); - return; - } - fread(&ttyinfohdr, sizeof(ttyinfohdr), 1, fp); - - tasklog('p', "Building portlist..."); - while (fread(&ttyinfo, ttyinfohdr.recsize, 1, fp) == 1) { - if (((ttyinfo.type == POTS) || (ttyinfo.type == ISDN)) && (ttyinfo.available) && (ttyinfo.callout)) { - memset(&new, 0, sizeof(new)); - strncpy(new.tty, ttyinfo.tty, 6); - - stdflag = TRUE; - q = xstrcpy(ttyinfo.flags); - for (p = q; p; p = q) { - if ((q = strchr(p, ','))) - *q++ = '\0'; - if ((strncasecmp(p, "U", 1) == 0) && (strlen(p) == 1)) { - stdflag = FALSE; - } else { - for (j = 0; fkey[j].key; j++) - if (strcasecmp(p, fkey[j].key) == 0) - new.mflags |= fkey[j].flag; - for (j = 0; dkey[j].key; j++) - if (strcasecmp(p, dkey[j].key) == 0) - new.dflags |= dkey[j].flag; - } - } - tasklog('p', "port %s modem %08lx ISDN %08lx", new.tty, new.mflags, new.dflags); - fill_portlist(&pl, &new); - count++; - } - } - fclose(fp); - tty_time = file_time(ttyfn); - tasklog('p', "make_portlist %d ports", count); -} - - diff --git a/mbtask/outstat.h b/mbtask/outstat.h index fd5e619a..9b1ccc83 100644 --- a/mbtask/outstat.h +++ b/mbtask/outstat.h @@ -31,17 +31,6 @@ typedef struct _alist } _alist_l; -/* - * Linked list of available dialout ports. - */ -typedef struct _pp_list { - struct _pp_list *next; - char tty[7]; /* tty name of the port */ - unsigned long mflags; /* Analogue modem flags */ - unsigned long dflags; /* ISDN flags */ - int locked; /* If port is locked */ -} pp_list; - /* * Bitmasks for calling status @@ -58,15 +47,9 @@ typedef struct _pp_list { -struct _ttyinfohdr ttyinfohdr; /* TTY lines */ -struct _ttyinfo ttyinfo; - - int each(faddr *, char, int, char *); char *callstatus(int); char *callmode(int); int outstat(void); -void load_ports(void); #endif - diff --git a/mbtask/ping.c b/mbtask/ping.c new file mode 100644 index 00000000..69895c14 --- /dev/null +++ b/mbtask/ping.c @@ -0,0 +1,370 @@ +/***************************************************************************** + * + * $Id$ + * Purpose ...............: mbtask - ping functions + * + ***************************************************************************** + * Copyright (C) 1997-2002 + * + * Michiel Broek FIDO: 2:280/2802 + * Beekmansbos 10 + * 1971 BV IJmuiden + * the Netherlands + * + * This file is part of MBSE BBS. + * + * This BBS is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * MBSE BBS is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with MBSE BBS; see the file COPYING. If not, write to the Free + * Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + *****************************************************************************/ + +#include "libs.h" +#include "../lib/structs.h" +#include "taskstat.h" +#include "taskutil.h" +#include "ping.h" + + + + + +/* + * Global variables + */ +extern struct taskrec TCFG; /* Task config record */ +int ping_isocket; /* Ping socket */ +int icmp_errs = 0; /* ICMP error counter */ +extern int internet; /* Internet is down */ +int pingstate = P_INIT; /* Ping state */ +int pingnr = 1; /* Ping #, 1 or 2 */ +int pingresult[2]; /* Ping results */ +char pingaddress[41]; /* Ping current address */ +struct in_addr paddr; /* Current ping address */ + + + +static int icmp4_errcmp(char *, int, struct in_addr *, char *, int, int); +unsigned short get_rand16(void); +int ping_send(struct in_addr); +int ping_receive(struct in_addr); + + +/* + * different names, same thing... be careful, as these are macros... + */ +#if defined(__FreeBSD__) || defined(__NetBSD__) +# define icmphdr icmp +# define iphdr ip +# define ip_saddr ip_src.s_addr +# define ip_daddr ip_dst.s_addr +#else +# define ip_saddr saddr +# define ip_daddr daddr +# define ip_hl ihl +# define ip_p protocol +#endif + + +#ifdef __linux__ +# define icmp_type type +# define icmp_code code +# define icmp_cksum checksum +# ifdef icmp_id +# undef icmp_id +# endif +# define icmp_id un.echo.id +# ifdef icmp_seq +# undef icmp_seq +# endif +# define icmp_seq un.echo.sequence +#endif + +#if defined(__FreeBSD__) || defined(__NetBSD__) +# define ICMP_DEST_UNREACH ICMP_UNREACH +# define ICMP_TIME_EXCEEDED ICMP_TIMXCEED +#endif + +#define ICMP_BASEHDR_LEN 8 +#define ICMP4_ECHO_LEN ICMP_BASEHDR_LEN + + + +/* + * Takes a packet as send out and a recieved ICMP packet and looks whether the ICMP packet is + * an error reply on the sent-out one. packet is only the packet (without IP header). + * errmsg includes an IP header. + * to is the destination address of the original packet (the only thing that is actually + * compared of the IP header). The RFC sais that we get at least 8 bytes of the offending packet. + * We do not compare more, as this is all we need. + */ +static int icmp4_errcmp(char *packet, int plen, struct in_addr *to, char *errmsg, int elen, int errtype) +{ + struct iphdr iph; + struct icmphdr icmph; + struct iphdr eiph; + char *data; + + /* XXX: lots of memcpy to avoid unaligned accesses on alpha */ + if (elen < sizeof(struct iphdr)) + return 0; + memcpy(&iph, errmsg, sizeof(iph)); + if (iph.ip_p != IPPROTO_ICMP || elen < iph.ip_hl * 4 + ICMP_BASEHDR_LEN + sizeof(eiph)) + return 0; + memcpy(&icmph, errmsg + iph.ip_hl * 4, ICMP_BASEHDR_LEN); + memcpy(&eiph, errmsg + iph.ip_hl * 4 + ICMP_BASEHDR_LEN, sizeof(eiph)); + if (elen < iph.ip_hl * 4 + ICMP_BASEHDR_LEN + eiph.ip_hl * 4 + 8) + return 0; + data = errmsg + iph.ip_hl * 4 + ICMP_BASEHDR_LEN + eiph.ip_hl * 4; + return icmph.icmp_type == errtype && memcmp(&to->s_addr, &eiph.ip_daddr, sizeof(to->s_addr)) == 0 && + memcmp(data, packet, plen < 8 ?plen:8) == 0; +} + + + +unsigned short get_rand16(void) +{ + return random()&0xffff; +} + + +short p_sequence = 0; +unsigned short id; +struct icmphdr icmpd; +struct sockaddr_in to; + + + +/* + * IPv4/ICMPv4 ping. Called from ping (see below) + */ +int ping_send(struct in_addr addr) +{ + int len; + int isock; +#ifdef __linux__ + struct icmp_filter f; +#else + struct protoent *pe; + int SOL_IP; +#endif + unsigned long sum; + unsigned short *ptr; + +#ifndef __linux__ + if (!(pe = getprotobyname("ip"))) { + tasklog('?', "icmp ping: getprotobyname() failed: %s", strerror(errno)); + return -1; + } + SOL_IP = pe->p_proto; +#endif + + isock = ping_isocket; + p_sequence = 1; + id = (unsigned short)get_rand16(); /* randomize a ping id */ + +#ifdef __linux__ + /* Fancy ICMP filering -- only on Linux (as far is I know) */ + + /* In fact, there should be macros for treating icmp_filter, but I haven't found them in Linux 2.2.15. + * So, set it manually and unportable ;-) */ + /* This filter lets ECHO_REPLY (0), DEST_UNREACH(3) and TIME_EXCEEDED(11) pass. */ + /* !(0000 1000 0000 1001) = 0xff ff f7 f6 */ + f.data=0xfffff7f6; + if (setsockopt(isock, SOL_RAW, ICMP_FILTER, &f, sizeof(f)) == -1) { + if (icmp_errs < ICMP_MAX_ERRS) + tasklog('?', "$icmp ping: setsockopt() failed %d", isock); + return -1; + } +#endif + + icmpd.icmp_type = ICMP_ECHO; + icmpd.icmp_code = 0; + icmpd.icmp_cksum = 0; + icmpd.icmp_id = htons((short)id); + icmpd.icmp_seq = htons(p_sequence); + + /* Checksumming - Algorithm taken from nmap. Thanks... */ + + ptr = (unsigned short *)&icmpd; + sum = 0; + + for (len = 0; len < 4; len++) { + sum += *ptr++; + } + sum = (sum >> 16) + (sum & 0xffff); + sum += (sum >> 16); + icmpd.icmp_cksum = ~sum; + + memset(&to, 0, sizeof(to)); + to.sin_family = AF_INET; + to.sin_port = 0; + to.sin_addr = addr; + SET_SOCKA_LEN4(to); + if (sendto(isock, &icmpd, ICMP4_ECHO_LEN, 0, (struct sockaddr *)&to, sizeof(to)) == -1) { + return -2; + } + return 0; +} + + + +int ping_receive(struct in_addr addr) +{ + char buf[1024]; + int isock; + int len; + struct sockaddr_in ffrom; + struct icmphdr icmpp; + struct iphdr iph; + socklen_t sl; + struct pollfd pfd; + + isock = ping_isocket; + + pfd.fd = isock; + pfd.events = POLLIN; + /* + * 10 mSec is enough, this function is called at regular intervals. + */ + if (poll(&pfd, 1, 10) < 0) { + if (icmp_errs < ICMP_MAX_ERRS) + tasklog('?', "$poll/select failed"); + return -3; + } + + if (pfd.revents & POLLIN || pfd.revents & POLLERR || pfd.revents & POLLHUP || pfd.revents & POLLNVAL) { + sl = sizeof(ffrom); + if ((len = recvfrom(isock, &buf, sizeof(buf), 0,(struct sockaddr *)&ffrom, &sl)) != -1) { + if (len > sizeof(struct iphdr)) { + memcpy(&iph, buf, sizeof(iph)); + if (len - iph.ip_hl * 4 >= ICMP_BASEHDR_LEN) { + memcpy(&icmpp, ((unsigned long int *)buf)+iph.ip_hl, sizeof(icmpp)); + if (iph.ip_saddr == addr.s_addr && + icmpp.icmp_type == ICMP_ECHOREPLY && + ntohs(icmpp.icmp_id) == id && + ntohs(icmpp.icmp_seq) <= p_sequence) { + return 0; + } else { + /* No regular echo reply. Maybe an error? */ + if (icmp4_errcmp((char *)&icmpd, ICMP4_ECHO_LEN, + &to.sin_addr, buf, len, ICMP_DEST_UNREACH) || + icmp4_errcmp((char *)&icmpd, ICMP4_ECHO_LEN, + &to.sin_addr, buf, len, ICMP_TIME_EXCEEDED)) { + return -4; + } + } + } + } + } else { + return -5; /* error */ + } + } + return -6; /* no answer */ +} + + + +void check_ping(void) +{ + int rc; + + /* + * If the previous pingstat is still P_SENT, then we now consider it a timeout. + */ + if (pingstate == P_SENT) { + pingresult[pingnr] = FALSE; + icmp_errs++; + if (icmp_errs < ICMP_MAX_ERRS) + tasklog('p', "ping %s seq=%d timeout", pingaddress, p_sequence); + } + + /* + * Check internet connection with ICMP ping + */ + rc = 0; + if (pingnr == 1) { + pingnr = 2; + if (strlen(TCFG.isp_ping2)) { + sprintf(pingaddress, "%s", TCFG.isp_ping2); + } else { + pingstate = P_NONE; + } + } else { + pingnr = 1; + if (strlen(TCFG.isp_ping1)) { + sprintf(pingaddress, "%s", TCFG.isp_ping1); + } else { + pingstate = P_NONE; + } + } + + if (inet_aton(pingaddress, &paddr)) { + rc = ping_send(paddr); + if (rc) { + if (icmp_errs++ < ICMP_MAX_ERRS) + tasklog('?', "ping send %s rc=%d", pingaddress, rc); + pingstate = P_FAIL; + pingresult[pingnr] = FALSE; + } else { + pingstate = P_SENT; + } + } else { + if (icmp_errs++ < ICMP_MAX_ERRS) + tasklog('?', "Ping address %d is invalid \"%s\"", pingnr, pingaddress); + pingstate = P_NONE; + } + + if (pingresult[1] == FALSE && pingresult[2] == FALSE) { + icmp_errs++; + if (internet) { + tasklog('!', "Internet connection is down"); + internet = FALSE; + sem_set((char *)"scanout", TRUE); + RemoveSema((char *)"is_inet"); + } + } else { + if (!internet) { + tasklog('!', "Internet connection is up"); + internet = TRUE; + sem_set((char *)"scanout", TRUE); + CreateSema((char *)"is_inet"); + } + icmp_errs = 0; + } +} + + + +void state_ping(void) +{ + int rc; + + /* + * PING state changes + */ + switch (pingstate) { + case P_NONE: pingresult[pingnr] = TRUE; + break; + case P_SENT: rc = ping_receive(paddr); + if (!rc) { + pingstate = P_OK; + pingresult[pingnr] = TRUE; + } else { + if (rc != -6) + tasklog('p', "ping recv %s id=%d rc=%d", pingaddress, id, rc); + } + break; + } +} + + diff --git a/mbtask/ping.h b/mbtask/ping.h new file mode 100644 index 00000000..5b996241 --- /dev/null +++ b/mbtask/ping.h @@ -0,0 +1,22 @@ +/* $Id */ + +#ifndef _PING_H +#define _PING_H + + +typedef enum {P_INIT, P_SENT, P_FAIL, P_OK, P_ERROR, P_NONE} PINGSTATE; + + + +/* + * Defines. + */ +#define ICMP_BASEHDR_LEN 8 +#define ICMP_MAX_ERRS 5 +#define SET_SOCKA_LEN4(socka) + +void check_ping(void); +void state_ping(void); + + +#endif diff --git a/mbtask/ports.c b/mbtask/ports.c new file mode 100644 index 00000000..b527fb46 --- /dev/null +++ b/mbtask/ports.c @@ -0,0 +1,188 @@ +/***************************************************************************** + * + * $Id$ + * Purpose ...............: mbtask - mode portlists + * + ***************************************************************************** + * Copyright (C) 1997-2002 + * + * Michiel Broek FIDO: 2:280/2802 + * Beekmansbos 10 + * 1971 BV IJmuiden + * the Netherlands + * + * This file is part of MBSE BBS. + * + * This BBS is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * MBSE BBS is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with MBSE BBS; see the file COPYING. If not, write to the Free + * Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + *****************************************************************************/ + +#include "libs.h" +#include "../lib/structs.h" +#include "taskutil.h" +#include "nodelist.h" +#include "ports.h" + + +#ifndef LOCKDIR +#if defined(__FreeBSD__) || defined(__NetBSD__) +#define LOCKDIR "/var/spool/lock" +#else +#define LOCKDIR "/var/lock" +#endif +#endif + +#define LCKPREFIX LOCKDIR"/LCK.." +#define LCKTMP LOCKDIR"/TMP." + + +extern char ttyfn[]; /* TTY file name */ +extern time_t tty_time; /* TTY update time */ +pp_list *pl = NULL; /* Portlist */ + + + +/* + * Tidy the portlist + */ +void tidy_portlist(pp_list **); +void tidy_portlist(pp_list ** fdp) +{ + pp_list *tmp, *old; + + tasklog('p', "tidy_portlist"); + for (tmp = *fdp; tmp; tmp = old) { + old = tmp->next; + free(tmp); + } + *fdp = NULL; +} + + + +/* + * Add a port to the portlist + */ +void fill_portlist(pp_list **, pp_list *); +void fill_portlist(pp_list **fdp, pp_list *new) +{ + pp_list *tmp, *ta; + + tmp = (pp_list *)malloc(sizeof(pp_list)); + tmp->next = NULL; + strncpy(tmp->tty, new->tty, 6); + tmp->mflags = new->mflags; + tmp->dflags = new->dflags; + + if (*fdp == NULL) { + *fdp = tmp; + } else { + for (ta = *fdp; ta; ta = ta->next) + if (ta->next == NULL) { + ta->next = (pp_list *)tmp; + break; + } + } +} + + + +/* + * Build a list of available dialout ports. + */ +void load_ports() +{ + FILE *fp; + pp_list new; + int count = 0, j, stdflag; + char *p, *q; + + tidy_portlist(&pl); + if ((fp = fopen(ttyfn, "r")) == NULL) { + tasklog('?', "$Can't open %s", ttyfn); + return; + } + fread(&ttyinfohdr, sizeof(ttyinfohdr), 1, fp); + + tasklog('p', "Building portlist..."); + while (fread(&ttyinfo, ttyinfohdr.recsize, 1, fp) == 1) { + if (((ttyinfo.type == POTS) || (ttyinfo.type == ISDN)) && (ttyinfo.available) && (ttyinfo.callout)) { + memset(&new, 0, sizeof(new)); + strncpy(new.tty, ttyinfo.tty, 6); + + stdflag = TRUE; + q = xstrcpy(ttyinfo.flags); + for (p = q; p; p = q) { + if ((q = strchr(p, ','))) + *q++ = '\0'; + if ((strncasecmp(p, "U", 1) == 0) && (strlen(p) == 1)) { + stdflag = FALSE; + } else { + for (j = 0; fkey[j].key; j++) + if (strcasecmp(p, fkey[j].key) == 0) + new.mflags |= fkey[j].flag; + for (j = 0; dkey[j].key; j++) + if (strcasecmp(p, dkey[j].key) == 0) + new.dflags |= dkey[j].flag; + } + } + tasklog('p', "port %s modem %08lx ISDN %08lx", new.tty, new.mflags, new.dflags); + fill_portlist(&pl, &new); + count++; + } + } + fclose(fp); + tty_time = file_time(ttyfn); + tasklog('p', "make_portlist %d ports", count); +} + + + +/* + * Check status of all modem/ISDN ports + */ +void check_ports(void) +{ + pp_list *tpl; + char lckname[256]; + FILE *lf; + int tmppid; + pid_t rempid = 0; + + for (tpl = pl; tpl; tpl = tpl->next) { + sprintf(lckname, "%s%s", LCKPREFIX, tpl->tty); +// tasklog('p', "checking %s", lckname); + if ((lf = fopen(lckname, "r")) == NULL) { + if (tpl->locked) { + tpl->locked = 0; + tasklog('+', "Port %s is now free", tpl->tty); + } + } else { + fscanf(lf, "%d", &tmppid); + rempid = tmppid; + fclose(lf); + if (kill(rempid, 0) && (errno == ESRCH)) { + tasklog('+', "Stale lockfile for %s, unlink", tpl->tty); + unlink(lckname); + } else { + if (!tpl->locked) { + tpl->locked = rempid; + tasklog('+', "Port %s locked, pid %d", tpl->tty, rempid); + } + } + } + } +} + + diff --git a/mbtask/ports.h b/mbtask/ports.h new file mode 100644 index 00000000..84b62233 --- /dev/null +++ b/mbtask/ports.h @@ -0,0 +1,28 @@ +/* $Id$ */ + +#ifndef _PORTS_H +#define _PORTS_H + + + +/* + * Linked list of available dialout ports. + */ +typedef struct _pp_list { + struct _pp_list *next; + char tty[7]; /* tty name of the port */ + unsigned long mflags; /* Analogue modem flags */ + unsigned long dflags; /* ISDN flags */ + int locked; /* If port is locked */ +} pp_list; + + +struct _ttyinfohdr ttyinfohdr; /* TTY lines */ +struct _ttyinfo ttyinfo; + + +void load_ports(void); /* Initialize portlist */ +void check_ports(void); /* Check status of all ports */ + + +#endif