mbtask added portcheck, code cleanup
This commit is contained in:
parent
9cefcf9b3a
commit
19183e73b6
@ -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.
|
||||
|
@ -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
|
||||
|
154
mbtask/calllist.c
Normal file
154
mbtask/calllist.c
Normal file
@ -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;
|
||||
}
|
||||
|
||||
|
26
mbtask/calllist.h
Normal file
26
mbtask/calllist.h
Normal file
@ -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
|
||||
|
420
mbtask/mbtask.c
420
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
|
||||
|
@ -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);
|
||||
|
106
mbtask/outstat.c
106
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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
370
mbtask/ping.c
Normal file
370
mbtask/ping.c
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
22
mbtask/ping.h
Normal file
22
mbtask/ping.h
Normal file
@ -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
|
188
mbtask/ports.c
Normal file
188
mbtask/ports.c
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
28
mbtask/ports.h
Normal file
28
mbtask/ports.h
Normal file
@ -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
|
Reference in New Issue
Block a user