diff --git a/Makefile b/Makefile index e7dffcb..4ce1035 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,11 @@ CFLAGS = -Wall -Werror -TARGETS = pmerge puniq +TARGETS = pmerge puniq p4split hd all: $(TARGETS) pmerge: pmerge.o pcap.o puniq: puniq.o pcap.o +p4split: p4split.c pcap.o clean: - rm -f $(TARGETS) + rm -f $(TARGETS) *.o diff --git a/hd.c b/hd.c new file mode 100644 index 0000000..e9471ef --- /dev/null +++ b/hd.c @@ -0,0 +1,98 @@ +#include +#include +#include + +const char* charset[] = { + "·", "☺", "☻", "♥", "♦", "♣", "♠", "•", "◘", "○", "◙", "♂", "♀", "♪", "♫", "☼", + "►", "◄", "↕", "‼", "¶", "§", "▬", "↨", "↑", "↓", "→", "←", "∟", "↔", "▲", "▼", + " ", "!", "\"", "#", "$", "%", "&", "'", "(", ")", "*", "+", ",", "-", ".", "/", + "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ":", ";", "<", "=", ">", "?", + "@", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", + "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "[", "\\", "]", "^", "_", + "`", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", + "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "{", "|", "}", "~", "⌂", + "Ç", "ü", "é", "â", "ä", "à", "å", "ç", "ê", "ë", "è", "ï", "î", "ì", "Ä", "Å", + "É", "æ", "Æ", "ô", "ö", "ò", "û", "ù", "ÿ", "Ö", "Ü", "¢", "£", "¥", "€", "ƒ", + "á", "í", "ó", "ú", "ñ", "Ñ", "ª", "º", "½", "⅓", "¼", "⅕", "⅙", "⅛", "«", "»", + "░", "▒", "▓", "│", "┤", "╡", "╢", "╖", "╕", "╣", "║", "╗", "╝", "╜", "╛", "┐", + "└", "┴", "┬", "├", "─", "┼", "╞", "╟", "╚", "╔", "╩", "╦", "╠", "═", "╬", "╧", + "╨", "╤", "╥", "╙", "╘", "╒", "╓", "╫", "╪", "┘", "┌", "█", "▄", "▌", "▐", "▀", + "α", "ß", "Γ", "π", "Σ", "σ", "µ", "τ", "Φ", "Θ", "Ω", "δ", "∞", "φ", "ε", "∩", + "⁰", "¹", "²", "³", "⁴", "⁵", "⁶", "⁷", "⁸", "⁹", "ⁱ", "ⁿ", "⁽", "⁼", "⁾", "¤" +}; + +int +dump(FILE *f) +{ + uint64_t p = 0; + uint8_t buf[32]; + int offset = 0; + int skipping = 0; + + while (!feof(f)) { + uint8_t *bytes = buf + offset; + size_t len; + int i; + + offset = 16 - offset; + + len = fread(bytes, 1, 16, f); + if (0 == len) break; + + if (p && (0 == memcmp(buf, buf + 16, 16))) { + if (! skipping) { + printf("*\n"); + skipping = 1; + } + p += 16; + continue; + } else { + skipping = 0; + } + + printf("%08lx ", (long unsigned int)p); + for (i = 0; i < 16; i += 1) { + if (i < len) { + printf("%02x ", bytes[i]); + } else { + printf(" "); + } + if (7 == i) { + printf(" "); + } + } + printf(" ┆"); + for (i = 0; i < len; i += 1) { + printf("%s", charset[bytes[i]]); + } + if (-1 == printf("┆\n")) { + perror("printf"); + return 1; + } + p += len; + } + printf("%08lx\n", (long unsigned int)p); + + return 0; +} + +int +main(int argc, char *argv[]) +{ + if (1 == argc) { + dump(stdin); + } else { + FILE *f = fopen(argv[1], "rb"); + + if (! f) { + perror("open"); + return 1; + } + + dump(f); + } + + return 0; +} + + diff --git a/p4split.c b/p4split.c new file mode 100644 index 0000000..4689688 --- /dev/null +++ b/p4split.c @@ -0,0 +1,134 @@ +#include +#include +#include +#include +#include +#include "pcap.h" + +/* Gaah so much crap */ +#include +#include +#include +#include +#include + + +int +usage(int ret) +{ + fprintf(stderr, "Usage: p4split CIDR\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Splits pcap on stdin into up to 256 files, based on CIDR.\n"); + return ret; +} + + +int +parse_cidr(char *s, uint32_t *addr, uint8_t *bits) +{ + char *slash = index(s, '/'); + struct in_addr inp; + + if (slash) { + *slash = 0; + *bits = atoi(slash + 1); + } else { + *bits = 0; + } + + if (0 == inet_aton(s, &inp)) return -1; + *addr = ntohl(inp.s_addr); + + return 0; +} + + +int +main(int argc, char *argv[]) +{ + struct pcap_file p; + struct pcap_file out[256]; + int ok = 0; + uint32_t addr; + uint32_t mask; + uint8_t bits; + uint8_t shr; + int i; + + if (argc != 2) return usage(0); + if (-1 == parse_cidr(argv[1], &addr, &bits)) return usage(0); + if (bits > 24) return usage(0); + if (bits % 8) { + fprintf(stderr, "Warning: routing prefix is not a multiple of 8.\n"); + } + + mask = ~((1 << (32-bits)) - 1); + addr &= mask; + shr = (32-bits) - 8; + + for (i = 0; i < 256; i += 1) { + out[i].f = NULL; + } + + if (-1 == pcap_open_in(&p, stdin)) return usage(0); + + while (1) { + struct pcap_pkthdr hdr; + uint8_t octet; + char frame[MAXFRAME]; + + ok = 1; + if (-1 == pcap_read_pkthdr(&p, &hdr)) break; + if (1 != fread(frame, hdr.caplen, 1, p.f)) break; + + + { + struct ether_header *eh = (struct ether_header *)frame; + struct iphdr *ih = (struct iphdr *)(frame + sizeof(struct ether_header)); + uint32_t a; + + /* VLAN tag */ + if (ntohs(eh->ether_type) == 0x8100) { + ih = (struct iphdr *)((char *)ih + 4); + } + + a = ntohl(ih->saddr); + if ((a & mask) != addr) { + a = ntohl(ih->daddr); + if ((a & mask) != addr) { + fprintf(stderr, "Warning: dropping unmatched packet %08x -> %08x\n", + ntohl(ih->saddr), ntohl(ih->daddr)); + continue; + } + } + octet = (a & ~mask) >> shr; + } + + ok = 0; + if (! out[octet].f) { + char fn[9]; + FILE *f; + + sprintf(fn, "%d.pcap", octet); + + if (NULL == (f = fopen(fn, "wb"))) break; + if (-1 == pcap_open_out(&out[octet], f)) break; + } + + if (-1 == pcap_write_pkthdr(&out[octet], &hdr)) break; + if (1 != fwrite(frame, hdr.caplen, 1, out[octet].f)) break; + } + + if (! ok) { + perror("Error"); + return 1; + } + + for (i = 0; i < 256; i += 1) { + if (out[i].f) { + pcap_close(&p); + } + } + + return 0; +} diff --git a/pcap.c b/pcap.c index e3e6ae9..1eb7309 100644 --- a/pcap.c +++ b/pcap.c @@ -54,6 +54,8 @@ pcap_read_pkthdr(struct pcap_file *ctx, struct pcap_pkthdr *hdr) hdr->len = bswap32(hdr->len); } + if (hdr->caplen > MAXFRAME) return -1; + return 0; } diff --git a/pmerge.c b/pmerge.c index 94c0c13..6c0d71d 100644 --- a/pmerge.c +++ b/pmerge.c @@ -12,9 +12,9 @@ struct input_file { int usage(int ret) { - printf("Usage: pmerge FILE ...\n"); - printf("\n"); - printf("Merges pcap files, outputting time-ordered pcap stream\n"); + fprintf(stderr, "Usage: pmerge FILE ...\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Merges pcap files, outputting time-ordered pcap stream\n"); return ret; } @@ -93,7 +93,7 @@ main(int argc, char *argv[]) /* Make sure it'll fit */ if (cur->next.caplen > sizeof(frame)) { - fprintf(stderr, "error: huge frame (size %u)\n", len); + fprintf(stderr, "error: huge frame (size %u)\n", (unsigned int)len); return EX_SOFTWARE; }