/* $Id: config.h,v 1.85 2000/09/07 19:30:46 jared Exp $ */

#include "defines.h"

#include <signal.h>
#include <stdio.h> 
#include <ctype.h>
#include <stdlib.h>
#include <time.h>  
#include <netdb.h>
#include <string.h>
#include <pwd.h>
#include <limits.h>
#if (defined(__svr4__) || defined(unixware))   /* slo-laris */
#include <sys/filio.h>
#endif
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/param.h>
#ifdef _AIX32
#include <fcntl.h>
#else /* _AIX32 */
#include <sys/fcntl.h>
#endif /* _AIX32 */
#include <errno.h>
#include <unistd.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <arpa/inet.h>
#include <syslog.h>
#include <stdarg.h>
#include <sys/utsname.h>
#include <sys/wait.h>

#define VERS		"System Monitor version v0.83.2"
#define CFILE		"/etc/sysmon.conf"
#define PIDFILE		"/etc/sysmond.pid"
#define PMESG		"%H (%I) %w is %u %d"
#define SUBJECT		"%h is %u"
#define UPCOLOR		"77ff77" /* green  */
#define RECENTCOLOR	"ffff00" /* yellow */
#define DOWNCOLOR	"ff5500" /* sumthin */

#define SYSMON_PORTNUM		1345
#define	MAX_ARGS		100
#define MAX_STRLEN		32768

/* the following should be read from /etc/services */

/* Per rfc */
#define SMTP_PORTNUM 25

/* per rfc */
#define HTTP_PORTNUM 80

/* per rfc */
#define IMAP_PORTNUM 143

/* per rfc */
#define NNTP_PORTNUM 119

/* per rfc? */
#define POP2_PORTNUM 109

/* per rfc? */
#define POP3_PORTNUM 110

/* */
#define DNS_PORTNUM 53

/* Radius */
#define RADIUS_PORTNUM 1643

/* SSL Http */
#define HTTPS_PORTNUM 443

/* Bootp */
#define BOOTP_CLIENT 68
#define BOOTP_SERVER 67

#ifndef bool
#define bool char
#endif

#ifndef MAX
#define MAX(a,b) (((a)>(b))?(a):(b))
#endif /* MAX */

#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif

/* Check Types */
#define SYSM_TYPE_TCP	1 /* TCP Checks */
#define	SYSM_TYPE_UDP	2 /* UDP Checks */
#define SYSM_TYPE_PING	3 /* Ping */
#define	SYSM_TYPE_SNMP	4 /* Snmp based checks */
#define	SYSM_TYPE_NNTP	5 /* nntp checks */
#define SYSM_TYPE_SMTP	6 /* smtp checks */
#define SYSM_TYPE_IMAP	7 /* imap check */
#define	SYSM_TYPE_POP3	8 /* pop3 check */
#define SYSM_TYPE_X500	9 /* umichX500 check */
#define SYSM_TYPE_POP2	10 /* pop2 check */
#define SYSM_TYPE_BOOTP	11 /* bootp check */
#define	SYSM_TYPE_DNS	12 /* check dns server */
#define SYSM_TYPE_WWW	13 /* www content check */
#define SYSM_TYPE_RADIUS 14 /* radius server check */
#define SYSM_TYPE_HTTPS	15 /* https content check */
#define SYSM_TYPE_SYSM	16 /* check another sysmond */
#define SYSM_TYPE_SSHD	17 /* sshd check */
#define SYSM_TYPE_IRCD	18 /* ircd check - connect, send quit */

/* Return Values */
#define SYSM_OK 	0
#define SYSM_CONNREF 	1
#define SYSM_NETUNRCH 	2
#define SYSM_HOSTDOWN	3
#define SYSM_TIMEDOUT 	4
#define SYSM_NODNS	5
#define SYSM_UNPINGABLE	6
#define SYSM_THROTTLED	7
#define SYSM_NOAUTH	8
#define SYSM_NORESP	9
#define SYSM_INPROG	10
#define SYSM_BAD_AUTH 	11
#define SYSM_BAD_RESP 	12
#define X500_WEDGED 	13
#define SYSM_KILLED	14 /* killed locally */
#define SYSM_HOSTUNRCH	15

struct hostinfo {
        unsigned char hostname[50]; /* name of system to check */
        unsigned int type; /* 1 = tcp, 2 = udp, 3 = ping, 4 = snmp, 5 = nntp 
		6 = smtp, 7 = imap, 8 = pop3 9 = umichX500 10 = pop2
		11 = bootp 12 = dns 13 = www-content */
        unsigned int port; /* only relevant for tcp/udp */
        unsigned char message[100]; /* message to print for outages */
        unsigned char *contact; /* e-mail contact for this */
	unsigned char *snmp_community; /* snmp community */
        unsigned int lastcheck; /* lastchecked status  0 = ok,  1 = conn ref
		2 = ENETUNREACH, 3 = EHOSTDOWN||EHOSTUNREACH,
		4 = ETIMEDOUT, 5 = no dns entry, 6 = unpingable,
		7 = Throttled, 8 = no auth, 9 = no response 
		10 = connection in progress, 11 = bad auth 
		12 = bad remote response, 13 = x500 error */
	unsigned char username[50]; /* for pop3, imap, etc */
	unsigned char password[50]; /* for pop3, imap, etc */
	unsigned char *hdr;
	unsigned char *hdrval;
	unsigned char *secret; /* used for RADIUS */
	unsigned char lastmsgid[128]; /* Message ID */
	unsigned char unique_id[128]; /* Unique id created by loadconfig
			never to change even if we catch sighup, and be
			unique enough between sysmon respawns */
	unsigned char url[80]; /* url for www */
	unsigned char url_text[80]; /* text to find within url */
	unsigned char *command; /* command to run on failure */
	unsigned long totalchecked; /* total times checked */
	unsigned long totaldown; /* total times checked as down */
	unsigned long downct; /* number of times counted as down.. */
	unsigned long max_down; /* max times down before we contact someone */

	bool reverse; /* if true then {if down, follow siblings}, else
			behave as we do otherwise */
	bool contacted; /* true if mailed contact -- false if not */
	time_t lastcontacted; /* last time we paged someone */
	bool contact_when_up; /* page someone when it comes up */
	
	bool queued; /* 0 if not, 1 if in queue */

	long int inaddr; /* for icmp.c */

	time_t lchecktime; /* time last checked */
	time_t check_start; /* time of start of check */
	time_t deathtime; /* time of death ;-) */
	time_t last_up; /* time it last came back */

        struct hostinfo *child, *sibling;
                /* child is any hosts behind this router
                   or any services that this host provides
                   (except for ping) */
                /* sibling is any hosts on this network */
        } ;

/* for lib.c:parse() */
struct parsed {
	int count;
	char **data;
	} ;

/*
 * perhaps we should move the filedes used in monitordata->
 * into here to aide in select()
 */
struct monitorent {
	struct hostinfo *checkent;
        struct monitorent *next;
	struct timeval queueat; /* time we got queued at */
	struct timeval lastserv; /* time we got last serviced */
	int filedes;		/* filedes used in check */
	int fd_state;		/* 1 = fd waiting for rd, otherwise wr */
	short int started; /* is the check actually started yet */
	short int retval; /* set to the return val, or -1 if check not
			done yet */
	void *monitordata; /* should be free'ed when retval is set */
	};

/* client status */
struct clientstatus {
	time_t lastactivity;
	short int filedes;
	char un[80]; /* username */
	char ip[16];
	int authlvl;
	int clientver;
	char buffer[256];
	struct clientstatus *next;
	};

/* my version of struct hostent -- used in dnscache.c */
struct my_hostent {
  char *h_name;			/* Official name of host */
  int h_addrtype;               /* Host address type.  */
  int h_length;                 /* Length of address.  */
  char *my_h_addr;           /* List of addresses from name server.  */
};


/* the actual dns cache list */
struct dnscache {
	char *hostname;
	struct my_hostent *hp;
	time_t lastquery;
	struct dnscache *next;
	};

/* we should use this someday */
struct bootp_pkt {
        unsigned char   bp_op;          /* packet opcode type */
        unsigned char   bp_htype;       /* hardware addr type */
        unsigned char   bp_hlen;        /* hardware addr length */
        unsigned char   bp_hops;        /* gateway hops */
        unsigned long	bp_xid;         /* transaction ID */
        unsigned short  bp_secs;        /* seconds since boot began */
        unsigned short  bp_unused;
        struct in_addr  bp_ciaddr;      /* client IP address */
        struct in_addr  bp_yiaddr;      /* 'your' IP address */
        struct in_addr  bp_siaddr;      /* server IP address */
        struct in_addr  bp_giaddr;      /* gateway IP address */
        unsigned char   bp_chaddr[16];  /* client hardware address */
        unsigned char   bp_sname[64];   /* server host name */
        unsigned char   bp_file[128];   /* boot file name */
        unsigned char   bp_vend[64];    /* vendor-specific area */
};




#define BOOTP_REQUEST 1
#define BOOTP_REPLY 2

/* Maximum times to try if you get a connection refused */
#define MAX_TRIES       7

/* ****************************************** *
 * NO USER SERVICABLE PARTS BEYOND THIS POINT *
 * ****************************************** */

#define HEARTBEAT_HOST "puck.nether.net"
#define HEARTBEAT_PORT 1345


/* misc defines for any/all external functions */
extern char *myname; /* my called name when I startup */
extern char *statefile;
extern bool mallocdebug;
extern char *errorsto;
extern char *authkey;
extern char *replyto;
extern char *downcolor, *upcolor, *recentcolor;
extern char *statusfilename;
extern time_t boottime; /* does a time() when program starts */
extern bool debug;
extern int dnsexpire;
extern bool donotify;
extern time_t dnslog_last_log;
extern int dnslog;
extern int facility;
extern int globtimeout, globtimeoutlen;
extern char *globhdr, *globhdrval;
extern bool gotsighup;
extern int heartbeat;
extern int html;
extern unsigned short disable_icmp;
extern int glob_icmp_fd; /* icmp.c + syswatch.c */
extern int inactivetime;
extern int numfailures;
extern int numqueued; /* num of elements in the queue */
extern int queuetime;
extern int pageinterval;
extern bool showupalso;
extern struct clientstatus *clienthead;
extern struct monitorent *queuehead;
extern struct dnscache *dnshead;
extern struct hostinfo *currenthead;
extern struct hostinfo *first;
extern struct protoent *icmpproto;
extern unsigned char *ident_hash;
extern char *pmesg;
extern char *subject;
extern char *sender;
extern int maxqueued;
extern bool ckconfigonly;
extern bool badconfig;


/* new routine names */

/* in sysmon.c */
void start_check_sysmon(struct monitorent *);
void service_check_sysmon(struct monitorent *);
void stop_check_sysmon(struct monitorent *);

void start_test_dns(struct monitorent *);
void service_test_dns(struct monitorent *);

void start_test_bootp(struct monitorent *);
void service_test_bootp(struct monitorent *);
void start_test_www(struct monitorent *);
void service_test_www(struct monitorent *);
void start_test_https(struct monitorent *);
void service_test_https(struct monitorent *);

/* icmp.c */
void setup_icmp_fd();
void handle_icmp_responses();
void start_test_ping(struct monitorent *);
void service_test_ping(struct monitorent *);

void start_test_imap(struct monitorent *);
void service_test_imap(struct monitorent *);
void start_test_nntp(struct monitorent *);
void service_test_nntp(struct monitorent *);
void start_test_pop3(struct monitorent *);
void service_test_pop3(struct monitorent *);

void start_test_radius(struct monitorent *);
void service_test_radius(struct monitorent *);

void start_test_smtp(struct monitorent *);
void service_test_smtp(struct monitorent *);
void start_test_tcp(struct monitorent *);
void service_test_tcp(struct monitorent *);
void start_test_udp(struct monitorent *);
void service_test_udp(struct monitorent *);
void start_test_x500(struct monitorent *);
void service_test_x500(struct monitorent *);
void stop_test_tcp(struct monitorent *);
void stop_test_udp(struct monitorent *);
void stop_test_ping(struct monitorent *);
void stop_test_snmp(struct monitorent *);
void stop_test_nntp(struct monitorent *);
void stop_test_smtp(struct monitorent *);
void stop_test_imap(struct monitorent *);
void stop_test_pop3(struct monitorent *);
void stop_test_x500(struct monitorent *);
void stop_test_pop2(struct monitorent *);
void stop_test_bootp(struct monitorent *);
void stop_test_dns(struct monitorent *);
void stop_test_www(struct monitorent *);
void stop_test_radius(struct monitorent *);
void stop_test_https(struct monitorent *);
void stop_test_sysm(struct monitorent *);
void stop_test_sshd(struct monitorent *);
int is_open(int);
void set_defaults();
void free_tree(struct hostinfo *);
void stop_daemon();
void service_this(struct monitorent *);
void print_queue(int );
void reload_config();
struct hostinfo *sync_after_sighup(struct hostinfo *, char *);
float mydifftime(struct timeval, struct timeval);
void blocktillready(int, int);
void expire_dns();
void nop(); /* a do nothing function... */
/* in lib.c: */
char randchar();
void gen_rand_ascii(char *, int);
int check_runtime(struct timeval, struct timeval, char *, int); /* Logs funcs that suck time */
int errno_to_error(int);
void print_err (int, const char *, ...);
void ABORT();

/* in smtp.c */
int check_smtp(char*);

int test_imap(char *, char *, char *);
int um_x500_monitor(char *, int);
void do_tree_periodic();
int tcp_open_sock(int);
int nextfd();
int udp_open_sock();
int init_socket();
int icmp_open_sock(int);

/* dnscache.c */
struct my_hostent *my_gethostbyname(char *);
char *get_ip(struct my_hostent *);
char *get_hostname(struct my_hostent *);
void warn_dnscache_lameness();


void client_poll();
int test_udp(char*, int);
int test_tcp(char*, int);
int sendline(int , char *);
void hard_copy(struct hostinfo *old, struct hostinfo *new);
void dump_to_file(char *, int );
void add_line(FILE *, struct hostinfo, int, time_t);
int data_waiting_read(int, int);
void walk_this_way(FILE *, struct hostinfo *, int, time_t);
int check_nntp(char *);
void timeout_clients();
void dead_client_cleanup();
int ping(struct hostinfo *);
char *str_difftime(time_t, time_t);
char *str_difftime_sec(time_t, time_t);
void page_someone(struct hostinfo*);
struct hostinfo *parseline(int *, int*, char*, FILE*);
int test_pop3(char*,char*,char*);
int check_http(char*,char*, char*);
char *yes_no(int);
int getline_tcp(int , char *);
void set_nonblock(int);
int can_write(int, int);
struct hostinfo *loadconfig(char*);
int parse(char *, struct parsed *);
void free_parsed(struct parsed *);
int open_host(char*, int, int*, int);
int open_sock();
char *errtostr(int);
char *type_to_name(int);
char *timedata(time_t);
void syslogmsg(char *);
void send_heartbeat(char *);

/* auth dns check */
int gethost(char *,struct sockaddr_in *);
int check_authdns(char *,char *);
int chk_ns(char *, char *,int,int ,int , int ,int );

/* radius check */
void start_check_radius(struct monitorent *);
void service_check_radius(struct monitorent *);
void stop_check_radius(struct monitorent *);
void md5_calc (unsigned char *, unsigned char *, unsigned int);

/* https */

int check_https(char *host,char *url,char *txt,int port);


/* in lib.c */
void *MALLOC(size_t, char *);
void FREE(void *);
short int name_to_type(char *);
/* end lib.c */

#if (defined(HAVE_LIBNCURSES) || defined(HAVE_LIBCURSES))
void pretty_print_down(struct hostinfo*);
void update_screen();
void setup_screen();
#endif

#if (defined(linux)) /* || defined(unixware)) */
#define ICMPHDR icmphdr
#define ICMP_TYPE type
#define ICMP_CHECKSUM checksum
#define ICMP_CODE code
#define IPHDR iphdr
#define IHL ihl
#define ICMP_SEQ un.echo.sequence
#define ICMP_ECHO_ID un.echo.id
#ifndef RLIMIT_OFILE   
#define RLIMIT_OFILE RLIMIT_NOFILE
#endif            
#endif

#if (defined(unixware) || defined(__APPLE_CC__))
#define RLIMIT_OFILE RLIMIT_NOFILE
#define ICMPHDR icmp
#define ICMP_CHECKSUM icmp_cksum
#define ICMP_TYPE icmp_type
#define ICMP_CODE icmp_code
#define IPHDR ip
#define IHL ip_hl
#define ICMP_SEQ icmp_seq
#define ICMP_ECHO_ID icmp_id
#endif


#if (defined(__NetBSD__) || defined(__FreeBSD) || defined(sgi)|| \
	defined(FreeBSD) || defined(__FreeBSD__) || defined(__bsdi__) || \
	defined(__OpenBSD__))

#if (defined(sgi) || defined(__NetBSD__) || defined(__OpenBSD__))
#define RLIMIT_OFILE RLIMIT_NOFILE
#endif
#define ICMPHDR icmp
#define ICMP_CHECKSUM icmp_cksum
#define ICMP_TYPE icmp_type
#define ICMP_CODE icmp_code
#define IPHDR ip
#define IHL ip_hl
#define ICMP_SEQ icmp_seq
#define ICMP_ECHO_ID icmp_id
#endif

#if (defined(sun) && defined(unix))   /* sunos, solaris, should work for most all */
#define ICMPHDR icmp
#define ICMP_CHECKSUM icmp_cksum
#define ICMP_TYPE icmp_type
#define ICMP_CODE icmp_code
#define IPHDR ip
#define IHL ip_hl
#define ICMP_SEQ icmp_seq
#define ICMP_ECHO_ID icmp_id
#endif

/*
 * this came from an OSF/1 machine
 */
#if (defined(__osf__) && defined(__alpha__))
#define ICMPHDR icmp
#define ICMP_CHECKSUM icmp_cksum
#define ICMP_TYPE icmp_type
#define ICMP_CODE icmp_code
#define IPHDR ip
#define IHL ip_vhl
#define ICMP_SEQ icmp_seq
#define ICMP_ECHO_ID icmp_id
#define RLIMIT_OFILE RLIMIT_NOFILE
#endif

#ifdef _AIX /* AIX */
#define ICMPHDR icmp
#define ICMP_CHECKSUM icmp_cksum
#define ICMP_TYPE icmp_type
#define ICMP_CODE icmp_code
#define IPHDR ip
#define IHL ip_vhl
#define ICMP_SEQ icmp_seq
#define ICMP_ECHO_ID icmp_id
#endif


#ifndef hpux
#ifdef _HPUX_SOURCE
#define hpux
#endif /* _HPUX_SOURCE */
#endif /* hpux */

#ifdef hpux
#define ICMPHDR icmp
#define ICMP_CHECKSUM icmp_cksum
#define ICMP_TYPE icmp_type
#define ICMP_CODE icmp_code
#define IPHDR ip
#define IHL ip_hl
#define ICMP_SEQ icmp_seq
#define ICMP_ECHO_ID icmp_id
#define RLIMIT_OFILE RLIMIT_NOFILE
#endif

