some of these are worse than others

Paul Vixie paul at vix.com
Mon Nov 18 22:45:39 UTC 2002


> Which signature database you use to match these or just log the 404's ?

i wrote my own.  since it's only 247 lines long, i'll include it here.

/* httpk - killer of http requests
 * vixie 05aug01 [from netperf 14jan92 [original]]
 *
 * $Id: httpk.c,v 1.5 2002/11/18 21:33:33 vixie Exp $
 */

#include <setjmp.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

#include <sys/errno.h>
#include <sys/fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/time.h>

#include "inetlib.h"
#include <arpa/inet.h>

extern int optind, opterr;
extern char *optarg;

static char *host = "localhost";
static char *serv = "http";
jmp_buf timedout;
static int timelim;
struct { char *base; size_t size; } content;
static int sndbuf = 16*1024;

static void setcontent(const char *);
static void httpk(const char *, const char *);
static void timeout(int);

#define outc(Ch) \
		if (isascii(Ch) && (isprint(Ch) || Ch == '\n')) \
			putchar(Ch); \
		else \
			printf("\\%03o", (u_char)Ch)

static void
usage(const char *msg) {
	fprintf(stderr, "usage error: %s\n", msg);
	fprintf(stderr,
	"usage:\thttpk\t[-h host] [-s serv] [-t timelim] [-f file] [-l]\n");
	exit(1);
}

main(int argc, char **argv) {
	int c;

	while (EOF != (c = getopt(argc, argv, "h:s:t:f:l"))) {
		switch (c) {
		case 'h':
			host = optarg;
			break;
		case 's':
			serv = optarg;
			break;
		case 't':
			timelim = atoi(optarg);
			break;
		case 'f':
			setcontent(optarg);
			break;
		case 'l':
			setlinebuf(stdout);
			break;
		default:
			usage("unknown option");
		}
	}
	httpk(host, serv);
}

static void
setcontent(const char *filename) {
	struct stat sb;
	int fd;
	char *cp;

	if ((fd = open(filename, O_RDONLY)) < 0) {
		perror(filename);
		exit(1);
	}
	if (fstat(fd, &sb) < 0) {
		perror("fstat");
		exit(1);
	}
	content.size = sb.st_size;
	content.base = mmap(NULL, content.size, PROT_READ, 0, fd, 0);
	if (content.base == NULL) {
		perror("mmap");
		exit(1);
	}
}

static void
httpk(const char *host, const char *serv) {
	void *sockaddr;
	int server, client, i, tsize, rsize;
	long rtt;
	struct sockaddr_in sa;
	socklen_t sa_len;
	struct timeval whenrcvd;
	struct pkt *rbuf, *tbuf;

	sockaddr = InetSockAddr(host, serv, "tcp");
	if (!sockaddr) {
		perror("InetSockAddr");
		exit(1);
	}

	server = TcpServer(sockaddr, 0);
	if (server < 0) {
		perror("TcpServer");
		exit(1);
	}

	signal(SIGALRM, timeout);
 loop:
	sa_len = sizeof sa;
	client = accept(server, (struct sockaddr *)&sa, &sa_len);
	if (client < 0) {
		if (errno == ECONNABORTED)
			goto loop;
	} else {
		struct sockaddr_in me;
		socklen_t me_len;
		char ch, lch;
		time_t now;
		FILE *fp;
		int n, l;

		me_len = sizeof me;
		if (getsockname(client, (struct sockaddr *)&me, &me_len) < 0) {
			perror("getsockname");
			exit(1);
		}
		now = time(0);
		printf("src [%s].%u; ",
		       inet_ntoa(sa.sin_addr), ntohs(sa.sin_port));
		printf("dst [%s].%u; ",
		       inet_ntoa(me.sin_addr), ntohs(me.sin_port));
		printf("%s", ctime(&now));
		fp = fdopen(client, "r+");
		if (!fp) {
			perror("fdopen");
			close(client);
			exit(1);
		}

		if (setjmp(timedout) != 0) {
			printf("*TIMEOUT*\n\n");
		} else {
			enum { out, in, num } state;
			int conlen_p = 0;
			u_long conlen;

			if (timelim != 0)
				alarm(timelim);
			while (ch = getc(fp), !feof(fp)) {
				n = 0;
				state = in;
				do {
					if (isascii(ch) && isupper(ch))
						lch = tolower(ch);
					else
						lch = ch;
					if (state == in)
						if (lch=="content-length:"[n]){
							if (lch == ':') {
								state = num;
								conlen = 0;
								conlen_p = 0;
							}
						} else
							state = out;
					else if (state == num) {
						if (!isascii(ch))
							;
						else if (!conlen_p &&
						      isspace(ch))
							;
						else if (isdigit(ch)) {
							conlen *= 10;
							conlen += (ch - '0');
							conlen_p = 1;
						} else
							state = out;
					}
					if (ch == '\n')
						break;
					if (ch != '\r') {
						outc(ch);
						n++;
					}
				} while (ch = getc(fp), !feof(fp));
				if (n == 0)
					break;
				putchar('\n');
			}
			if (conlen_p) {
				putchar('+');
				putchar('\n');
				n = 0;
				while (n < conlen &&
				       (ch = getc(fp), !feof(fp))) {
					outc(ch);
					n++;
				}
				if (n > 0 && ch != '\n')
					putchar('\n');
			}
			putchar('\n');
			if (timelim != 0)
				alarm(0);
		}
		shutdown(client, SHUT_RD);
		setsockopt(client, 6, SO_SNDBUF, &sndbuf, sizeof sndbuf);
		fcntl(client, F_SETFL, fcntl(client, F_GETFL) | O_NONBLOCK);
		if (content.base != NULL && content.size != 0) {
			fprintf(fp, "HTTP/1.1 404 %s\r\n",
				"You are digging in the wrong place");
			fprintf(fp, "Connection: close\r\n");
			fprintf(fp, "Content-Length: %d\r\n", content.size);
			fprintf(fp, "Content-Type: text/html\r\n");
			fputs("\r\n", fp);
			fflush(fp);
			writev(client, &content, 1);
		} else {
			fputs("HTTP/1.1 204 Zilch\r\n", fp);
			fputs("Connection: close\r\n", fp);
			fputs("Content-Length: 0\r\n", fp);
			fputs("\r\n", fp);
		}
		fclose(fp);
		goto loop;
	}
	perror("accept");
	signal(SIGALRM, SIG_DFL);
}

static void
timeout(int foo) {
	longjmp(timedout, 1);
}



More information about the NANOG mailing list