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