summaryrefslogtreecommitdiffstats
path: root/contrib/ipfilter/l4check/l4check.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/ipfilter/l4check/l4check.c')
-rw-r--r--contrib/ipfilter/l4check/l4check.c822
1 files changed, 0 insertions, 822 deletions
diff --git a/contrib/ipfilter/l4check/l4check.c b/contrib/ipfilter/l4check/l4check.c
deleted file mode 100644
index a096fff..0000000
--- a/contrib/ipfilter/l4check/l4check.c
+++ /dev/null
@@ -1,822 +0,0 @@
-/*
- * (C)Copyright March, 2000 - Darren Reed.
- */
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#include <sys/ioctl.h>
-
-#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/ip.h>
-
-#include <net/if.h>
-
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <ctype.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <stdlib.h>
-
-#include "ip_compat.h"
-#include "ip_fil.h"
-#include "ip_nat.h"
-#include "ipl.h"
-
-#include "ipf.h"
-
-extern char *optarg;
-
-
-typedef struct l4cfg {
- struct l4cfg *l4_next;
- struct ipnat l4_nat; /* NAT rule */
- struct sockaddr_in l4_sin; /* remote socket to connect */
- time_t l4_last; /* when we last connected */
- int l4_alive; /* 1 = remote alive */
- int l4_fd;
- int l4_rw; /* 0 = reading, 1 = writing */
- char *l4_rbuf; /* read buffer */
- int l4_rsize; /* size of buffer */
- int l4_rlen; /* how much used */
- char *l4_wptr; /* next byte to write */
- int l4_wlen; /* length yet to be written */
-} l4cfg_t;
-
-
-l4cfg_t *l4list = NULL;
-char *response = NULL;
-char *probe = NULL;
-l4cfg_t template;
-int frequency = 20;
-int ctimeout = 1;
-int rtimeout = 1;
-size_t plen = 0;
-size_t rlen = 0;
-int natfd = -1;
-int opts = 0;
-
-#if defined(sun) && !defined(__svr4__) && !defined(__SVR4)
-# define strerror(x) sys_errlist[x]
-#endif
-
-
-char *copystr(dst, src)
-char *dst, *src;
-{
- register char *s, *t, c;
- register int esc = 0;
-
- for (s = src, t = dst; s && t && (c = *s++); )
- if (esc) {
- esc = 0;
- switch (c)
- {
- case 'n' :
- *t++ = '\n';
- break;
- case 'r' :
- *t++ = '\r';
- break;
- case 't' :
- *t++ = '\t';
- break;
- }
- } else if (c != '\\')
- *t++ = c;
- else
- esc = 1;
- *t = '\0';
- return dst;
-}
-
-void addnat(l4)
-l4cfg_t *l4;
-{
-
- ipnat_t *ipn = &l4->l4_nat;
-
- printf("Add NAT rule for %s/%#x,%u -> ", inet_ntoa(ipn->in_out[0].in4),
- ipn->in_outmsk, ntohs(ipn->in_pmin));
- printf("%s,%u\n", inet_ntoa(ipn->in_in[0].in4), ntohs(ipn->in_pnext));
- if (!(opts & OPT_DONOTHING)) {
- ipfobj_t obj;
-
- bzero(&obj, sizeof(obj));
- obj.ipfo_rev = IPFILTER_VERSION;
- obj.ipfo_size = sizeof(*ipn);
- obj.ipfo_ptr = ipn;
-
- if (ioctl(natfd, SIOCADNAT, &obj) == -1)
- perror("ioctl(SIOCADNAT)");
- }
-}
-
-
-void delnat(l4)
-l4cfg_t *l4;
-{
- ipnat_t *ipn = &l4->l4_nat;
-
- printf("Remove NAT rule for %s/%#x,%u -> ",
- inet_ntoa(ipn->in_out[0].in4), ipn->in_outmsk, ipn->in_pmin);
- printf("%s,%u\n", inet_ntoa(ipn->in_in[0].in4), ipn->in_pnext);
- if (!(opts & OPT_DONOTHING)) {
- ipfobj_t obj;
-
- bzero(&obj, sizeof(obj));
- obj.ipfo_rev = IPFILTER_VERSION;
- obj.ipfo_size = sizeof(*ipn);
- obj.ipfo_ptr = ipn;
-
- if (ioctl(natfd, SIOCRMNAT, &ipn) == -1)
- perror("ioctl(SIOCRMNAT)");
- }
-}
-
-
-void connectl4(l4)
-l4cfg_t *l4;
-{
- l4->l4_rw = 1;
- l4->l4_rlen = 0;
- l4->l4_wlen = plen;
- if (!l4->l4_wlen) {
- l4->l4_alive = 1;
- addnat(l4);
- } else
- l4->l4_wptr = probe;
-}
-
-
-void closel4(l4, dead)
-l4cfg_t *l4;
-int dead;
-{
- close(l4->l4_fd);
- l4->l4_fd = -1;
- l4->l4_rw = -1;
- if (dead && l4->l4_alive) {
- l4->l4_alive = 0;
- delnat(l4);
- }
-}
-
-
-void connectfd(l4)
-l4cfg_t *l4;
-{
- if (connect(l4->l4_fd, (struct sockaddr *)&l4->l4_sin,
- sizeof(l4->l4_sin)) == -1) {
- if (errno == EISCONN) {
- if (opts & OPT_VERBOSE)
- fprintf(stderr, "Connected fd %d\n",
- l4->l4_fd);
- connectl4(l4);
- return;
- }
- if (opts & OPT_VERBOSE)
- fprintf(stderr, "Connect failed fd %d: %s\n",
- l4->l4_fd, strerror(errno));
- closel4(l4, 1);
- return;
- }
- l4->l4_rw = 1;
-}
-
-
-void writefd(l4)
-l4cfg_t *l4;
-{
- int n, i, fd;
-
- fd = l4->l4_fd;
-
- if (l4->l4_rw == -2) {
- connectfd(l4);
- return;
- }
-
- n = l4->l4_wlen;
-
- i = send(fd, l4->l4_wptr, n, 0);
- if (i == 0 || i == -1) {
- if (opts & OPT_VERBOSE)
- fprintf(stderr, "Send on fd %d failed: %s\n",
- fd, strerror(errno));
- closel4(l4, 1);
- } else {
- l4->l4_wptr += i;
- l4->l4_wlen -= i;
- if (l4->l4_wlen == 0)
- l4->l4_rw = 0;
- if (opts & OPT_VERBOSE)
- fprintf(stderr, "Sent %d bytes to fd %d\n", i, fd);
- }
-}
-
-
-void readfd(l4)
-l4cfg_t *l4;
-{
- char buf[80], *ptr;
- int n, i, fd;
-
- fd = l4->l4_fd;
-
- if (l4->l4_rw == -2) {
- connectfd(l4);
- return;
- }
-
- if (l4->l4_rsize) {
- n = l4->l4_rsize - l4->l4_rlen;
- ptr = l4->l4_rbuf + l4->l4_rlen;
- } else {
- n = sizeof(buf) - 1;
- ptr = buf;
- }
-
- if (opts & OPT_VERBOSE)
- fprintf(stderr, "Read %d bytes on fd %d to %p\n",
- n, fd, ptr);
- i = recv(fd, ptr, n, 0);
- if (i == 0 || i == -1) {
- if (opts & OPT_VERBOSE)
- fprintf(stderr, "Read error on fd %d: %s\n",
- fd, (i == 0) ? "EOF" : strerror(errno));
- closel4(l4, 1);
- } else {
- if (ptr == buf)
- ptr[i] = '\0';
- if (opts & OPT_VERBOSE)
- fprintf(stderr, "%d: Read %d bytes [%*.*s]\n",
- fd, i, i, i, ptr);
- if (ptr != buf) {
- l4->l4_rlen += i;
- if (l4->l4_rlen >= l4->l4_rsize) {
- if (!strncmp(response, l4->l4_rbuf,
- l4->l4_rsize)) {
- printf("%d: Good response\n",
- fd);
- if (!l4->l4_alive) {
- l4->l4_alive = 1;
- addnat(l4);
- }
- closel4(l4, 0);
- } else {
- if (opts & OPT_VERBOSE)
- printf("%d: Bad response\n",
- fd);
- closel4(l4, 1);
- }
- }
- } else if (!l4->l4_alive) {
- l4->l4_alive = 1;
- addnat(l4);
- closel4(l4, 0);
- }
- }
-}
-
-
-int runconfig()
-{
- int fd, opt, res, mfd, i;
- struct timeval tv;
- time_t now, now1;
- fd_set rfd, wfd;
- l4cfg_t *l4;
-
- mfd = 0;
- opt = 1;
- now = time(NULL);
-
- /*
- * First, initiate connections that are closed, as required.
- */
- for (l4 = l4list; l4; l4 = l4->l4_next) {
- if ((l4->l4_last + frequency < now) && (l4->l4_fd == -1)) {
- l4->l4_last = now;
- fd = socket(AF_INET, SOCK_STREAM, 0);
- if (fd == -1)
- continue;
- setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt,
- sizeof(opt));
-#ifdef O_NONBLOCK
- if ((res = fcntl(fd, F_GETFL, 0)) != -1)
- fcntl(fd, F_SETFL, res | O_NONBLOCK);
-#endif
- if (opts & OPT_VERBOSE)
- fprintf(stderr,
- "Connecting to %s,%d (fd %d)...",
- inet_ntoa(l4->l4_sin.sin_addr),
- ntohs(l4->l4_sin.sin_port), fd);
- if (connect(fd, (struct sockaddr *)&l4->l4_sin,
- sizeof(l4->l4_sin)) == -1) {
- if (errno != EINPROGRESS) {
- if (opts & OPT_VERBOSE)
- fprintf(stderr, "failed\n");
- perror("connect");
- close(fd);
- fd = -1;
- } else {
- if (opts & OPT_VERBOSE)
- fprintf(stderr, "waiting\n");
- l4->l4_rw = -2;
- }
- } else {
- if (opts & OPT_VERBOSE)
- fprintf(stderr, "connected\n");
- connectl4(l4);
- }
- l4->l4_fd = fd;
- }
- }
-
- /*
- * Now look for fd's which we're expecting to read/write from.
- */
- FD_ZERO(&rfd);
- FD_ZERO(&wfd);
- tv.tv_sec = MIN(rtimeout, ctimeout);
- tv.tv_usec = 0;
-
- for (l4 = l4list; l4; l4 = l4->l4_next)
- if (l4->l4_rw == 0) {
- if (now - l4->l4_last > rtimeout) {
- if (opts & OPT_VERBOSE)
- fprintf(stderr, "%d: Read timeout\n",
- l4->l4_fd);
- closel4(l4, 1);
- continue;
- }
- if (opts & OPT_VERBOSE)
- fprintf(stderr, "Wait for read on fd %d\n",
- l4->l4_fd);
- FD_SET(l4->l4_fd, &rfd);
- if (l4->l4_fd > mfd)
- mfd = l4->l4_fd;
- } else if ((l4->l4_rw == 1 && l4->l4_wlen) ||
- l4->l4_rw == -2) {
- if ((l4->l4_rw == -2) &&
- (now - l4->l4_last > ctimeout)) {
- if (opts & OPT_VERBOSE)
- fprintf(stderr,
- "%d: connect timeout\n",
- l4->l4_fd);
- closel4(l4);
- continue;
- }
- if (opts & OPT_VERBOSE)
- fprintf(stderr, "Wait for write on fd %d\n",
- l4->l4_fd);
- FD_SET(l4->l4_fd, &wfd);
- if (l4->l4_fd > mfd)
- mfd = l4->l4_fd;
- }
-
- if (opts & OPT_VERBOSE)
- fprintf(stderr, "Select: max fd %d wait %d\n", mfd + 1,
- tv.tv_sec);
- i = select(mfd + 1, &rfd, &wfd, NULL, &tv);
- if (i == -1) {
- perror("select");
- return -1;
- }
-
- now1 = time(NULL);
-
- for (l4 = l4list; (i > 0) && l4; l4 = l4->l4_next) {
- if (l4->l4_fd < 0)
- continue;
- if (FD_ISSET(l4->l4_fd, &rfd)) {
- if (opts & OPT_VERBOSE)
- fprintf(stderr, "Ready to read on fd %d\n",
- l4->l4_fd);
- readfd(l4);
- i--;
- }
-
- if ((l4->l4_fd >= 0) && FD_ISSET(l4->l4_fd, &wfd)) {
- if (opts & OPT_VERBOSE)
- fprintf(stderr, "Ready to write on fd %d\n",
- l4->l4_fd);
- writefd(l4);
- i--;
- }
- }
- return 0;
-}
-
-
-int gethostport(str, lnum, ipp, portp)
-char *str;
-int lnum;
-u_32_t *ipp;
-u_short *portp;
-{
- struct servent *sp;
- struct hostent *hp;
- char *host, *port;
-
- host = str;
- port = strchr(host, ',');
- if (port)
- *port++ = '\0';
-
-#ifdef HAVE_INET_ATON
- if (ISDIGIT(*host) && inet_aton(host, &ip))
- *ipp = ip.s_addr;
-#else
- if (ISDIGIT(*host))
- *ipp = inet_addr(host);
-#endif
- else {
- if (!(hp = gethostbyname(host))) {
- fprintf(stderr, "%d: can't resolve hostname: %s\n",
- lnum, host);
- return 0;
- }
- *ipp = *(u_32_t *)hp->h_addr;
- }
-
- if (port) {
- if (ISDIGIT(*port))
- *portp = htons(atoi(port));
- else {
- sp = getservbyname(port, "tcp");
- if (sp)
- *portp = sp->s_port;
- else {
- fprintf(stderr, "%d: unknown service %s\n",
- lnum, port);
- return 0;
- }
- }
- } else
- *portp = 0;
- return 1;
-}
-
-
-char *mapfile(file, sizep)
-char *file;
-size_t *sizep;
-{
- struct stat sb;
- caddr_t addr;
- int fd;
-
- fd = open(file, O_RDONLY);
- if (fd == -1) {
- perror("open(mapfile)");
- return NULL;
- }
-
- if (fstat(fd, &sb) == -1) {
- perror("fstat(mapfile)");
- close(fd);
- return NULL;
- }
-
- addr = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd, 0);
- if (addr == (caddr_t)-1) {
- perror("mmap(mapfile)");
- close(fd);
- return NULL;
- }
- close(fd);
- *sizep = sb.st_size;
- return (char *)addr;
-}
-
-
-int readconfig(filename)
-char *filename;
-{
- char c, buf[512], *s, *t, *errtxt = NULL, *line;
- int num, err = 0;
- ipnat_t *ipn;
- l4cfg_t *l4;
- FILE *fp;
-
- fp = fopen(filename, "r");
- if (!fp) {
- perror("open(configfile)");
- return -1;
- }
-
- bzero((char *)&template, sizeof(template));
- template.l4_fd = -1;
- template.l4_rw = -1;
- template.l4_sin.sin_family = AF_INET;
- ipn = &template.l4_nat;
- ipn->in_flags = IPN_TCP|IPN_ROUNDR;
- ipn->in_redir = NAT_REDIRECT;
-
- for (num = 1; fgets(buf, sizeof(buf), fp); num++) {
- s = strchr(buf, '\n');
- if (!s) {
- fprintf(stderr, "%d: line too long\n", num);
- fclose(fp);
- return -1;
- }
-
- *s = '\0';
-
- /*
- * lines which are comments
- */
- s = strchr(buf, '#');
- if (s)
- *s = '\0';
-
- /*
- * Skip leading whitespace
- */
- for (line = buf; (c = *line) && ISSPACE(c); line++)
- ;
- if (!*line)
- continue;
-
- if (opts & OPT_VERBOSE)
- fprintf(stderr, "Parsing: [%s]\n", line);
- t = strtok(line, " \t");
- if (!t)
- continue;
- if (!strcasecmp(t, "interface")) {
- s = strtok(NULL, " \t");
- if (s)
- t = strtok(NULL, "\t");
- if (!s || !t) {
- errtxt = line;
- err = -1;
- break;
- }
-
- if (!strchr(t, ',')) {
- fprintf(stderr,
- "%d: local address,port missing\n",
- num);
- err = -1;
- break;
- }
-
- strncpy(ipn->in_ifnames[0], s, LIFNAMSIZ);
- strncpy(ipn->in_ifnames[1], s, LIFNAMSIZ);
- if (!gethostport(t, num, &ipn->in_outip,
- &ipn->in_pmin)) {
- errtxt = line;
- err = -1;
- break;
- }
- ipn->in_outmsk = 0xffffffff;
- ipn->in_pmax = ipn->in_pmin;
- if (opts & OPT_VERBOSE)
- fprintf(stderr,
- "Interface %s %s/%#x port %u\n",
- ipn->in_ifnames[0],
- inet_ntoa(ipn->in_out[0].in4),
- ipn->in_outmsk, ipn->in_pmin);
- } else if (!strcasecmp(t, "remote")) {
- if (!*ipn->in_ifnames[0]) {
- fprintf(stderr,
- "%d: ifname not set prior to remote\n",
- num);
- err = -1;
- break;
- }
- s = strtok(NULL, " \t");
- if (s)
- t = strtok(NULL, "");
- if (!s || !t || strcasecmp(s, "server")) {
- errtxt = line;
- err = -1;
- break;
- }
-
- ipn->in_pnext = 0;
- if (!gethostport(t, num, &ipn->in_inip,
- &ipn->in_pnext)) {
- errtxt = line;
- err = -1;
- break;
- }
- ipn->in_inmsk = 0xffffffff;
- if (ipn->in_pnext == 0)
- ipn->in_pnext = ipn->in_pmin;
-
- l4 = (l4cfg_t *)malloc(sizeof(*l4));
- if (!l4) {
- fprintf(stderr, "%d: out of memory (%d)\n",
- num, sizeof(*l4));
- err = -1;
- break;
- }
- bcopy((char *)&template, (char *)l4, sizeof(*l4));
- l4->l4_sin.sin_addr = ipn->in_in[0].in4;
- l4->l4_sin.sin_port = ipn->in_pnext;
- l4->l4_next = l4list;
- l4list = l4;
- } else if (!strcasecmp(t, "connect")) {
- s = strtok(NULL, " \t");
- if (s)
- t = strtok(NULL, "\t");
- if (!s || !t) {
- errtxt = line;
- err = -1;
- break;
- } else if (!strcasecmp(s, "timeout")) {
- ctimeout = atoi(t);
- if (opts & OPT_VERBOSE)
- fprintf(stderr, "connect timeout %d\n",
- ctimeout);
- } else if (!strcasecmp(s, "frequency")) {
- frequency = atoi(t);
- if (opts & OPT_VERBOSE)
- fprintf(stderr,
- "connect frequency %d\n",
- frequency);
- } else {
- errtxt = line;
- err = -1;
- break;
- }
- } else if (!strcasecmp(t, "probe")) {
- s = strtok(NULL, " \t");
- if (!s) {
- errtxt = line;
- err = -1;
- break;
- } else if (!strcasecmp(s, "string")) {
- if (probe) {
- fprintf(stderr,
- "%d: probe already set\n",
- num);
- err = -1;
- break;
- }
- t = strtok(NULL, "");
- if (!t) {
- fprintf(stderr,
- "%d: No probe string\n", num);
- err = -1;
- break;
- }
-
- probe = malloc(strlen(t));
- copystr(probe, t);
- plen = strlen(probe);
- if (opts & OPT_VERBOSE)
- fprintf(stderr, "Probe string [%s]\n",
- probe);
- } else if (!strcasecmp(s, "file")) {
- t = strtok(NULL, " \t");
- if (!t) {
- errtxt = line;
- err = -1;
- break;
- }
- if (probe) {
- fprintf(stderr,
- "%d: probe already set\n",
- num);
- err = -1;
- break;
- }
- probe = mapfile(t, &plen);
- if (opts & OPT_VERBOSE)
- fprintf(stderr,
- "Probe file %s len %u@%p\n",
- t, plen, probe);
- }
- } else if (!strcasecmp(t, "response")) {
- s = strtok(NULL, " \t");
- if (!s) {
- errtxt = line;
- err = -1;
- break;
- } else if (!strcasecmp(s, "timeout")) {
- t = strtok(NULL, " \t");
- if (!t) {
- errtxt = line;
- err = -1;
- break;
- }
- rtimeout = atoi(t);
- if (opts & OPT_VERBOSE)
- fprintf(stderr,
- "response timeout %d\n",
- rtimeout);
- } else if (!strcasecmp(s, "string")) {
- if (response) {
- fprintf(stderr,
- "%d: response already set\n",
- num);
- err = -1;
- break;
- }
- response = strdup(strtok(NULL, ""));
- rlen = strlen(response);
- template.l4_rsize = rlen;
- template.l4_rbuf = malloc(rlen);
- if (opts & OPT_VERBOSE)
- fprintf(stderr,
- "Response string [%s]\n",
- response);
- } else if (!strcasecmp(s, "file")) {
- t = strtok(NULL, " \t");
- if (!t) {
- errtxt = line;
- err = -1;
- break;
- }
- if (response) {
- fprintf(stderr,
- "%d: response already set\n",
- num);
- err = -1;
- break;
- }
- response = mapfile(t, &rlen);
- template.l4_rsize = rlen;
- template.l4_rbuf = malloc(rlen);
- if (opts & OPT_VERBOSE)
- fprintf(stderr,
- "Response file %s len %u@%p\n",
- t, rlen, response);
- }
- } else {
- errtxt = line;
- err = -1;
- break;
- }
- }
-
- if (errtxt)
- fprintf(stderr, "%d: syntax error at \"%s\"\n", num, errtxt);
- fclose(fp);
- return err;
-}
-
-
-void usage(prog)
-char *prog;
-{
- fprintf(stderr, "Usage: %s -f <configfile>\n", prog);
- exit(1);
-}
-
-
-int main(argc, argv)
-int argc;
-char *argv[];
-{
- char *config = NULL;
- int c;
-
- while ((c = getopt(argc, argv, "f:nv")) != -1)
- switch (c)
- {
- case 'f' :
- config = optarg;
- break;
- case 'n' :
- opts |= OPT_DONOTHING;
- break;
- case 'v' :
- opts |= OPT_VERBOSE;
- break;
- }
-
- if (config == NULL)
- usage(argv[0]);
-
- if (readconfig(config))
- exit(1);
-
- if (!l4list) {
- fprintf(stderr, "No remote servers, exiting.");
- exit(1);
- }
-
- if (!(opts & OPT_DONOTHING)) {
- natfd = open(IPNAT_NAME, O_RDWR);
- if (natfd == -1) {
- perror("open(IPL_NAT)");
- exit(1);
- }
- }
-
- if (opts & OPT_VERBOSE)
- fprintf(stderr, "Starting...\n");
- while (runconfig() == 0)
- ;
-
- exit(1);
-}
OpenPOWER on IntegriCloud