diff --git a/src/hdng.c b/src/hdng.c index a49643e..df3e7ea 100644 --- a/src/hdng.c +++ b/src/hdng.c @@ -1,96 +1,193 @@ +/* + * Last Modified: Fri 17 Feb 2012 12:08:33 PM CST + * + * _ _Hex Dumper _ ____ _ _ + * | \ | | _____ _| |_ / ___| ___ _ __ ___ _ __ __ _| |_(_) ___ _ __ + * | \| |/ _ \ \/ / __| | | _ / _ \ '_ \ / _ \ '__/ _` | __| |/ _ \| '_ \ + * | |\ | __/> <| |_ | |_| | __/ | | | __/ | | (_| | |_| | (_) | | | | + * |_| \_|\___/_/\_\\__| \____|\___|_| |_|\___|_| \__,_|\__|_|\___/|_| |_| + * + */ + #include #include +#include +#include +#include #include +#include +#include "netre.h" 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", "{", "|", "}", "~", "⌂", - "Ç", "ü", "é", "â", "ä", "à", "å", "ç", "ê", "ë", "è", "ï", "î", "ì", "Ä", "Å", - "É", "æ", "Æ", "ô", "ö", "ò", "û", "ù", "ÿ", "Ö", "Ü", "¢", "£", "¥", "€", "ƒ", - "á", "í", "ó", "ú", "ñ", "Ñ", "ª", "º", "½", "⅓", "¼", "⅕", "⅙", "⅛", "«", "»", - "░", "▒", "▓", "│", "┤", "╡", "╢", "╖", "╕", "╣", "║", "╗", "╝", "╜", "╛", "┐", - "└", "┴", "┬", "├", "─", "┼", "╞", "╟", "╚", "╔", "╩", "╦", "╠", "═", "╬", "╧", - "╨", "╤", "╥", "╙", "╘", "╒", "╓", "╫", "╪", "┘", "┌", "█", "▄", "▌", "▐", "▀", - "α", "ß", "Γ", "π", "Σ", "σ", "µ", "τ", "Φ", "Θ", "Ω", "δ", "∞", "φ", "ε", "∩", - "⁰", "¹", "²", "³", "⁴", "⁵", "⁶", "⁷", "⁸", "⁹", "ⁱ", "ⁿ", "⁽", "⁼", "⁾", "¤" + "·", "☺", "☻", "♥", "♦", "♣", "♠", "•", "◘", "○", "◙", "♂", "♀", "♪", "♫", "☼", + "►", "◄", "↕", "‼", "¶", "§", "▬", "↨", "↑", "↓", "→", "←", "∟", "↔", "▲", "▼", + " ", "!", "\"", "#", "$", "%", "&", "'", "(", ")", "*", "+", ",", "-", ".", "/", + "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 version(bool error) { + fprintf(WHICHOUT(error), "hdng v.%s - %s\n\n", PACKAGE_VERSION, + "The Next Generation Hex Dumper"); + return error ? EX_USAGE : EX_OK; } -int -main(int argc, char *argv[]) -{ - if (1 == argc) { - dump(stdin); - } else { - FILE *f = fopen(argv[1], "rb"); +int usage(bool error, char *prog) { + int retval = version(error); + fprintf(WHICHOUT(error), "Usage: %s [ [-oxsg] [-w width] | -X | -G ] [filename]\n", prog); + fprintf(WHICHOUT(error), "\t-o\tdo not print offsets\n"); + fprintf(WHICHOUT(error), "\t-x\tdo not print hexadecimal bytes\n"); + fprintf(WHICHOUT(error), "\t-s\tdo not abbreviate redundant bytes\n"); + fprintf(WHICHOUT(error), "\t-g\tdo not print glyphs\n"); + fprintf(WHICHOUT(error), "\t-w\tlength of data to show on each line\n\n"); + fprintf(WHICHOUT(error), "\t-X\thex dump mode (continuous)\n"); + fprintf(WHICHOUT(error), "\t-G\tglyph dump mode (continuous)\n\n"); + fprintf(WHICHOUT(error), "\tif a filename is not specified, stdin will be used\n"); + return retval; +} - if (! f) { - perror("open"); - return 1; +void print_hexits(uint8_t buf[], size_t length, bool continuous) { + size_t i; + + for (i = 0; i < length; i += 1) { + printf("%02x ", buf[i]); + if (continuous && ((i+1) % 8 == 0)) printf(" "); + } + if (continuous) printf(" "); +} + +void print_glyphs(uint8_t buf[], size_t length, bool decoration) { + size_t i; + + if (decoration) printf("┆"); + + for (i = 0; i < length; i += 1) + printf("%s", charset[buf[i]]); + + if (decoration) printf("┆"); +} + +int dump(FILE *f, uint8_t width, bool offsets, bool hex, bool glyphs, bool skip, bool nl) { + uint64_t p = 0; + uint64_t op = 0; + int skipping = 0; + size_t offset = 0; + uint8_t buf[2*width]; + + while (!feof(f)) { + uint8_t *bytes = buf + offset; + size_t len; + + offset = width - offset; + + len = fread(bytes, 1, width, f); + if (len == 0) break; + op = p; + p += len; + + if (skip) { + if (op && (memcmp(buf, buf + width, width) == 0)) { + if (skipping == 1) { + printf("*\n"); + skipping = 1; + } + continue; + } else { + skipping = 0; + } + } + + if (offsets) printf("%08lx ", (long unsigned int)op); + if (hex) print_hexits(bytes, len, nl); + if (glyphs) print_glyphs(bytes, len, hex); + if (nl) printf("\n"); } - dump(f); - } - - return 0; + if (offsets) printf("%08lx bytes", (long unsigned int)p); + printf("\n"); + return EX_OK; +} + +int main(int argc, char *argv[]) { + int opt; + FILE *input = stdin; + + /* defaults */ + uint8_t width = 16; + bool hex = true; + bool skip = true; + bool glyphs = true; + bool offsets = true; + bool nl = true; + + /* special modes */ + bool hexdump = false; + bool glyphdump = false; + + /* option parsing */ + while ((opt = getopt(argc, argv, "hvoxsgw:XG")) != -1) { + switch (opt) { + case 'o': /* offset off */ + offsets = false; + break; + case 'x': /* hex off */ + hex = false; + break; + case 's': /* skip off */ + skip = false; + break; + case 'g': /* glyphs off */ + glyphs = false; + break; + case 'w': /* width */ + if (optarg[0] == '-') optarg++; + width = (uint8_t)atoi(optarg); + if (width == 0) width = 16; + break; + case 'X': /* hex dump mode */ + hexdump = true; + break; + case 'G': /* glyph dump mode */ + glyphdump = true; + break; + case 'v': return version(false); + case 'h': return usage(false, argv[0]); + default: return usage(true, argv[0]); + } + } + + /* crazy user! */ + if (!hex && !glyphs) glyphs = true; + + /* modes override other options, hex wins vs. glyphs */ + if (hexdump) { + glyphs = skip = offsets = nl = false; + hex = true; + width = 16; + } else if (glyphdump) { + hex = skip = offsets = nl = false; + glyphs = true; + width = 16; + } + + if (optind < argc) { + input = fopen(argv[optind], "rb"); + if (!input) { + perror("open"); + return EX_OSFILE; + } + } + + return dump(input, width, offsets, hex, glyphs, skip, nl); } diff --git a/src/p4split.c b/src/p4split.c index 4689688..c255269 100644 --- a/src/p4split.c +++ b/src/p4split.c @@ -1,9 +1,24 @@ +/* + * _ _ _ _ _ + * _ __ | || | ___ _ __ | (_) |_ + * | '_ \| || |_/ __| '_ \| | | __| + * | |_) |__ _\__ \ |_) | | | |_ + * | .__/ |_| |___/ .__/|_|_|\__| + * |_| |_| + * + * split a pcap into multiple files, based on a CIDR filter + * + */ + #include #include +#include #include #include #include +#include #include "pcap.h" +#include "netre.h" /* Gaah so much crap */ #include @@ -12,123 +27,151 @@ #include #include +int version(bool error) { + fprintf(WHICHOUT(error), "p4split v.%s - %s\n\n", PACKAGE_VERSION, + "Splits PCAP into up to 256 files based on CIDR"); + return error ? EX_USAGE : EX_OK; +} -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 usage(bool error, char *prog) { + int retval = version(error); + fprintf(WHICHOUT(error), "Usage: %s [-i INPUT] \n", prog); + fprintf(WHICHOUT(error), "\t-i INPUT\tA PCAP to read for input\n"); + fprintf(WHICHOUT(error), "\tCIDR\t\tA network address in CIDR notation\n"); + fprintf(WHICHOUT(error), "\nif INPUT is not specified, stdin will be read\n"); + return retval; } -int -parse_cidr(char *s, uint32_t *addr, uint8_t *bits) -{ - char *slash = index(s, '/'); - struct in_addr inp; +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 (slash != NULL) { + *slash = '\0'; + *bits = (uint8_t)atoi(slash + 1); + } else { + *bits = 0; + } - if (0 == inet_aton(s, &inp)) return -1; - *addr = ntohl(inp.s_addr); + if (inet_aton(s, &inp) == 0) return -1; + *addr = ntohl(inp.s_addr); - return 0; + 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; +int p4split(struct pcap_file input, uint32_t addr, uint8_t bits) { + int i; + struct pcap_file out[256]; + int errid = 0; + uint32_t mask = ~((1 << (32-bits)) - 1); + uint8_t shr = (32-bits) - 8; - 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"); - } + addr &= mask; - mask = ~((1 << (32-bits)) - 1); - addr &= mask; - shr = (32-bits) - 8; + for (i = 0; i < 256; i += 1) out[i].f = NULL; - for (i = 0; i < 256; i += 1) { - out[i].f = NULL; - } + while (true) { + struct pcap_pkthdr hdr; + uint8_t octet; + char frame[MAXFRAME]; - if (-1 == pcap_open_in(&p, stdin)) return usage(0); + if (pcap_read_pkthdr(&input, &hdr) == -1) break; + if (fread(frame, hdr.caplen, 1, input.f) != 1) break; - while (1) { - struct pcap_pkthdr hdr; - uint8_t octet; - char frame[MAXFRAME]; + { + struct ether_header *eh = (struct ether_header *)frame; + struct iphdr *ih = (struct iphdr *)(frame + sizeof(struct ether_header)); + uint32_t a; - ok = 1; - if (-1 == pcap_read_pkthdr(&p, &hdr)) break; - if (1 != fread(frame, hdr.caplen, 1, p.f)) break; + /* VLAN tag */ + if (ntohs(eh->ether_type) == 0x8100) { + ih = (struct iphdr *)((char *)ih + 4); + } - - { - 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; + 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; + } + + if (! out[octet].f) { + char fn[9]; + FILE *f; + + snprintf(fn, 9, "%d.pcap", octet); + + if (((f = fopen(fn, "wb")) == NULL) || + (pcap_open_out(&out[octet], f) == -1)) { + perror("Error creating output"); + errid = EX_CANTCREAT; + break; + } + } + + if ((pcap_write_pkthdr(&out[octet], &hdr) == -1) || + (fwrite(frame, hdr.caplen, 1, out[octet].f) != 1)) { + perror("Error writing"); + errid = EX_IOERR; + break; } - } - octet = (a & ~mask) >> shr; } - ok = 0; - if (! out[octet].f) { - char fn[9]; - FILE *f; + for (i = 0; i < 256; i++) if (out[i].f) pcap_close(&out[i]); - sprintf(fn, "%d.pcap", octet); + pcap_close(&input); - 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; + return errid; +} + +int main(int argc, char *argv[]) { + int opt; + struct pcap_file p; + uint32_t addr; + uint8_t bits; + FILE *input; + + while ((opt = getopt(argc, argv, "hvi:")) != -1) { + switch (opt) { + case 'i': /* input */ + input = fopen(optarg, "rb"); + if (!input) { + perror("open input"); + return EX_IOERR; + } + break; + case 'v': return version(false); + case 'h': return usage(false, argv[0]); + default: return usage(true, argv[0]); + } + } + + if ((optind >= argc) || (argc - optind != 1)) { + fprintf(stderr, "not enough arguments\n"); + return usage(true, argv[0]); + } + + if (parse_cidr(argv[optind], &addr, &bits) == -1) { + fprintf(stderr, "invalid CIDR\n"); + return EX_USAGE; + } + + if (bits > 24) { + fprintf(stderr, "subnet bits must be <= 24\n"); + return EX_USAGE; + } + + if (pcap_open_in(&p, input) == -1) return EX_IOERR; + + if (bits % 8) + fprintf(stderr, "Warning: routing prefix is not a multiple of 8.\n"); + + return p4split(p, addr, bits); } diff --git a/src/pcap.c b/src/pcap.c index 1eb7309..0328fbe 100644 --- a/src/pcap.c +++ b/src/pcap.c @@ -1,51 +1,53 @@ +/* + * PCAP library + * + */ + #include #include #include #include "pcap.h" +#include "netre.h" -int -pcap_open_in(struct pcap_file *ctx, FILE *f) -{ +int pcap_open_in(struct pcap_file *ctx, FILE *f) { struct pcap_file_header h; - if (1 != fread(&h, sizeof(h), 1, f)) { - h.magic = 0; - } + if (fread(&h, sizeof(h), 1, f) != 1) h.magic = 0; if (MAGIC == h.magic) { ctx->swap = 0; + DDUMP("normal order"); } else if (bswap32(MAGIC) == h.magic) { ctx->swap = 1; + DDUMP("swapped order"); } else { return -1; } if ((h.version_major != 2) || (h.version_minor != 4)) return -1; + DDUMP_d(h.version_major); + DDUMP_d(h.version_minor); - if (ctx->swap) h.snaplen = bswap32(h.snaplen); + if (ctx->swap != 0) h.snaplen = bswap32(h.snaplen); + DDUMP_d(h.snaplen); if (h.snaplen > MAXFRAME) return -1; ctx->f = f; return 0; } -int -pcap_open_out(struct pcap_file *ctx, FILE *f) -{ +int pcap_open_out(struct pcap_file *ctx, FILE *f) { struct pcap_file_header h = { MAGIC, 2, 4, 0, 0, MAXFRAME, 1 }; - if (1 != fwrite(&h, sizeof(h), 1, f)) return -1; + if (fwrite(&h, sizeof(h), 1, f) != 1) return -1; + ctx->f = f; ctx->swap = 0; return 0; } -int -pcap_read_pkthdr(struct pcap_file *ctx, struct pcap_pkthdr *hdr) -{ - if (1 != fread(hdr, sizeof(*hdr), 1, ctx->f)) { - return -1; - } +int pcap_read_pkthdr(struct pcap_file *ctx, struct pcap_pkthdr *hdr) { + if (fread(hdr, sizeof(*hdr), 1, ctx->f) != 1) return -1; if (ctx->swap) { hdr->ts.tv_sec = bswap32(hdr->ts.tv_sec); @@ -59,9 +61,7 @@ pcap_read_pkthdr(struct pcap_file *ctx, struct pcap_pkthdr *hdr) return 0; } -int -pcap_write_pkthdr(struct pcap_file *ctx, struct pcap_pkthdr *hdr) -{ +int pcap_write_pkthdr(struct pcap_file *ctx, struct pcap_pkthdr *hdr) { if (ctx->swap) { struct pcap_pkthdr ohdr; @@ -71,16 +71,12 @@ pcap_write_pkthdr(struct pcap_file *ctx, struct pcap_pkthdr *hdr) hdr->caplen = bswap32(hdr->caplen); hdr->len = bswap32(hdr->len); - if (1 != fwrite(&ohdr, sizeof(ohdr), 1, ctx->f)) return -1; + if (fwrite(&ohdr, sizeof(ohdr), 1, ctx->f) != 1) return -1; } else { - if (1 != fwrite(hdr, sizeof(*hdr), 1, ctx->f)) return -1; + if (fwrite(hdr, sizeof(*hdr), 1, ctx->f) != 1) return -1; } return 0; } -void -pcap_close(struct pcap_file *ctx) -{ - fclose(ctx->f); -} +void pcap_close(struct pcap_file *ctx) { fclose(ctx->f); } diff --git a/src/pcap.h b/src/pcap.h index 41ffe6f..709b732 100644 --- a/src/pcap.h +++ b/src/pcap.h @@ -5,7 +5,7 @@ #include #define MAGIC 0xa1b2c3d4 -#define MAXFRAME 9000 +#define MAXFRAME 65535 struct pcap_file { FILE *f; @@ -48,14 +48,6 @@ struct pcap_pkthdr { /* Debugging help */ -#define DUMPf(fmt, args...) fprintf(stderr, "%s:%s:%d " fmt "\n", __FILE__, __FUNCTION__, __LINE__, ##args) -#define DUMP() DUMPf("") -#define DUMP_d(v) DUMPf("%s = %d", #v, v) -#define DUMP_u(v) DUMPf("%s = %u", #v, v) -#define DUMP_x(v) DUMPf("%s = 0x%x", #v, v) -#define DUMP_s(v) DUMPf("%s = %s", #v, v) -#define DUMP_c(v) DUMPf("%s = %c", #v, v) -#define DUMP_p(v) DUMPf("%s = %p", #v, v) int pcap_open_in(struct pcap_file *ctx, FILE *f); int pcap_open_out(struct pcap_file *ctx, FILE *f); diff --git a/src/pmerge.c b/src/pmerge.c index 6c0d71d..36c315a 100644 --- a/src/pmerge.c +++ b/src/pmerge.c @@ -1,127 +1,163 @@ +/* + * _ __ _ __ ___ ___ _ __ __ _ ___ + * | '_ \| '_ ` _ \ / _ \ '__/ _` |/ _ \ + * | |_) | | | | | | __/ | | (_| | __/ + * | .__/|_| |_| |_|\___|_| \__, |\___| + * |_| |___/ + * + * Merges pcap files, outputting time-ordered pcap stream + * + */ + #include #include +#include +#include #include +#include #include "pcap.h" +#include "netre.h" struct input_file { - int active; - struct pcap_file p; - struct pcap_pkthdr next; + int active; + struct pcap_file p; + struct pcap_pkthdr next; }; -int -usage(int ret) -{ - fprintf(stderr, "Usage: pmerge FILE ...\n"); - fprintf(stderr, "\n"); - fprintf(stderr, "Merges pcap files, outputting time-ordered pcap stream\n"); - return ret; +int version(bool error) { + fprintf(WHICHOUT(error), "pmerge v.%s - %s\n\n", PACKAGE_VERSION, + "Merges pcap files, outputting time-ordered pcap stream"); + return error ? EX_USAGE : EX_OK; } -int -read_next(struct input_file *file) -{ - if (! file->active) return -1; - - if (-1 == pcap_read_pkthdr(&file->p, &file->next)) { - pcap_close(&file->p); - file->active = 0; - file->next.ts.tv_sec = 0xffffffff; - file->next.ts.tv_usec = 0xffffffff; - return -1; - } - - return 0; +int usage(bool error, char *prog) { + int retval = version(error); + fprintf(WHICHOUT(error), "Usage: %s [-o OUTPUT] FILE [FILE]*\n", prog); + fprintf(WHICHOUT(error), "\tOUTPUT\toutput filename -- if not specified, stdout will be used\n"); + fprintf(WHICHOUT(error), "\tFILE\tinput filename, at least one is required\n"); + return retval; } -int -main(int argc, char *argv[]) -{ - struct input_file files[argc-1]; - int nfiles = 0; - int nopen; - int i; - struct pcap_file out; +int read_next(struct input_file *file) { + if (! file->active) return -1; - if (1 == argc) return usage(0); - - /* Open input files */ - for (i = 0; i < argc-1; i += 1) { - char *fn = argv[i+1]; - struct input_file *cur = &files[nfiles]; - FILE *f; - - if ('-' == fn[0]) return usage(0); - - f = fopen(fn, "rb"); - if (NULL == f) { - perror(fn); - return EX_NOINPUT; + if (-1 == pcap_read_pkthdr(&file->p, &file->next)) { + pcap_close(&file->p); + file->active = 0; + file->next.ts.tv_sec = 0xffffffff; + file->next.ts.tv_usec = 0xffffffff; + return -1; } - if (-1 == pcap_open_in(&cur->p, f)) { - fprintf(stderr, "%s: unable to process\n", fn); - return EX_IOERR; - } - cur->active = 1; + return 0; +} - if (0 == read_next(cur)) { - nfiles += 1; - } - } +int pmerge(FILE *output, struct input_file files[], int nfiles) { + int nopen; + int i; + struct pcap_file out; - if (-1 == pcap_open_out(&out, stdout)) { - perror("writing header"); - return EX_IOERR; - } - - nopen = nfiles; - while (nopen) { - struct input_file *cur = &files[0]; - char frame[MAXFRAME]; - size_t len; - - /* Find next oldest frame */ - for (i = 0; i < nfiles; i += 1) { - if (files[i].active && - ((files[i].next.ts.tv_sec < cur->next.ts.tv_sec) || - ((files[i].next.ts.tv_sec == cur->next.ts.tv_sec) && - (files[i].next.ts.tv_usec < cur->next.ts.tv_usec)))) { - cur = &files[i]; - } - } - - /* Make sure it'll fit */ - if (cur->next.caplen > sizeof(frame)) { - fprintf(stderr, "error: huge frame (size %u)\n", (unsigned int)len); - return EX_SOFTWARE; - } - - /* Read it */ - len = fread(frame, 1, cur->next.caplen, cur->p.f); - if (len < cur->next.caplen) { - /* Short read */ - cur->next.caplen = len; - pcap_close(&cur->p); - cur->active = 0; - } - - /* Write header + frame */ - if (len) { - if (1 != fwrite(&cur->next, sizeof(cur->next), 1, stdout)) { - perror("error"); + if (pcap_open_out(&out, output) == -1) { + perror("writing pcap header"); return EX_IOERR; - } - if (len != fwrite(frame, 1, len, stdout)) { - perror("error"); - return EX_IOERR; - } } - if (-1 == read_next(cur)) { - nopen -= 1; - } - } + nopen = nfiles; + while (nopen) { + struct input_file *cur = &files[0]; + char frame[MAXFRAME]; + size_t len; - return 0; + /* Find next oldest frame */ + for (i = 0; i < nfiles; i += 1) { + if ( files[i].active && + ((files[i].next.ts.tv_sec < cur->next.ts.tv_sec) || + ((files[i].next.ts.tv_sec == cur->next.ts.tv_sec) && + ( files[i].next.ts.tv_usec < cur->next.ts.tv_usec)))) { + cur = &files[i]; + } + } + + /* Make sure it'll fit */ + if (cur->next.caplen > sizeof(frame)) { + fprintf(stderr, "error: huge frame (size %u)\n", (unsigned int)len); + return EX_SOFTWARE; + } + + /* Read it */ + len = fread(frame, 1, cur->next.caplen, cur->p.f); + if (len < cur->next.caplen) { + /* Short read */ + cur->next.caplen = len; + pcap_close(&cur->p); + cur->active = 0; + } + + /* Write header + frame */ + if (len) { + if (fwrite(&cur->next, sizeof(cur->next), 1, output) != 1) { + perror("error"); + return EX_IOERR; + } + if (len != fwrite(frame, 1, len, output)) { + perror("error"); + return EX_IOERR; + } + } + + if (read_next(cur) == -1) nopen -= 1; + } + + return EX_OK; +} + +int main(int argc, char *argv[]) { + int opt; + FILE *output = stdout; + + while ((opt = getopt(argc, argv, "hvo:")) != -1) { + switch (opt) { + case 'o': /* output file */ + output = fopen(optarg, "wb"); + if (!output) { + perror("Open output"); + return EX_OSFILE; + } + break; + case 'v': return version(false); + case 'h': return usage(false, argv[0]); + default: return usage(true, argv[0]); + } + } + + if (optind >= argc) return usage(true, argv[0]); + + int i; + int nfiles = 0; + struct input_file files[argc - optind]; + + /* Open input files */ + for (i = optind; i < argc; i++) { + char *fn = argv[i]; + struct input_file *cur = &files[nfiles]; + FILE *f; + + if (fn[0] == '-') return usage(true, argv[0]); + + f = fopen(fn, "rb"); + if (!f) { + perror(fn); + return EX_NOINPUT; + } + + if (pcap_open_in(&cur->p, f) == -1) { + fprintf(stderr, "%s: unable to process\n", fn); + return EX_IOERR; + } + cur->active = 1; + + if (read_next(cur) == 0) nfiles += 1; + } + + return pmerge(output, files, nfiles); } diff --git a/src/puniq.c b/src/puniq.c index 6e7ff21..d06f124 100644 --- a/src/puniq.c +++ b/src/puniq.c @@ -1,63 +1,117 @@ +/* _ + * _ __ _ _ _ __ (_) __ _ + * | '_ \| | | | '_ \| |/ _` | + * | |_) | |_| | | | | | (_| | + * | .__/ \__,_|_| |_|_|\__, | + * |_| |_| + * + * filter one to many PCAPs for unique frames + * + */ + +#include #include +#include #include #include +#include "netre.h" #include "pcap.h" -int -main(int argc, char *argv[]) -{ - int i; - struct pcap_pkthdr hdr[2]; - char frame[2][MAXFRAME]; - int cur = 0; - struct pcap_file out; - - memset(&hdr, 0, sizeof(hdr)); - memset(frame, 0, 2 * MAXFRAME); - - if (-1 == pcap_open_out(&out, stdout)) { - perror("writing header"); - return EX_IOERR; - } - - i = 1; - do { - char *fn = argv[i]; - FILE *f; - struct pcap_file p; - - if ((! fn) || (0 == strcmp("-", fn))) { - f = stdin; - } else { - f = fopen(fn, "rb"); - if (NULL == f) { - perror(fn); - return EX_IOERR; - } - } - - if (-1 == pcap_open_in(&p, f)) { - fprintf(stderr, "%s: unable to process\n", fn); - return EX_IOERR; - } - - while (1) { - if (-1 == pcap_read_pkthdr(&p, &hdr[cur])) break; - if (1 != fread(frame[cur], hdr[cur].caplen, 1, p.f)) break; - - if ((0 == memcmp(&hdr[0], &hdr[1], sizeof(hdr[0]))) && - (0 == memcmp(frame[0], frame[1], hdr[cur].caplen))) { - /* Skip this duplicate */ - } else { - if (-1 == pcap_write_pkthdr(&out, &hdr[cur])) break; - if (1 != fwrite(frame[cur], hdr[cur].caplen, 1, out.f)) break; - } - cur = (1 - cur); - } - pcap_close(&p); - - i += 1; - } while (i < argc); - - return 0; +int version(bool error) { + fprintf(WHICHOUT(error), "puniq v.%s - %s\n\n", PACKAGE_VERSION, + "filter one to many PCAPs for unique frames"); + return error ? EX_USAGE : EX_OK; +} + +int usage(bool error, char *prog) { + int retval = version(error); + fprintf(WHICHOUT(error), "Usage: %s [-o OUTPUT] [FILE]*\n", prog); + fprintf(WHICHOUT(error), "\t-o OUTPUT\tfile in which to write output; if not specified, output will be written to stdout\n"); + fprintf(WHICHOUT(error), "\tFILE\tinput pcap file, at least one file is required\n"); + return retval; +} + +int puniq(FILE *output, char *inputs[], int ninputs) { + int i; + struct pcap_pkthdr hdr[2]; + char frame[2][MAXFRAME]; + struct pcap_file out; + int cur; + + if (pcap_open_out(&out, output) == -1) { + perror("writing header"); + return EX_IOERR; + } + + for (i = 0; i < ninputs; i++) { + char *fn = inputs[i]; + FILE *f; + struct pcap_file p; + + if ((! fn) || (strcmp("-", fn) == 0)) { + f = stdin; + } else { + printf("processing: %s\n", fn); + f = fopen(fn, "rb"); + if (NULL == f) { + perror(fn); + return EX_IOERR; + } + } + + if (pcap_open_in(&p, f) == -1) { + fprintf(stderr, "unable to process: %s\n", fn); + return EX_IOERR; + } + + cur = 0; + while (true) { + + memset(&hdr[cur], 0, sizeof(hdr[cur])); + memset(&frame[cur], 0, MAXFRAME); + + if (pcap_read_pkthdr(&p, &hdr[cur]) == -1) break; + if (fread(frame[cur], hdr[cur].caplen, 1, p.f) != 1) break; + if ((memcmp(&hdr[0], &hdr[1], sizeof(hdr[cur])) == 0) && + (memcmp(frame[0], frame[1], hdr[cur].caplen) == 0)) { + /* Skip this duplicate */ + DDUMP("duplicate!"); + } else { + if (pcap_write_pkthdr(&out, &hdr[cur]) == -1) break; + if (fwrite(frame[cur], hdr[cur].caplen, 1, out.f) != 1) break; + } + + cur = (1 - cur); + } + + pcap_close(&p); + } + pcap_close(&out); + + return EX_OK; +} + +int main (int argc, char *argv[]) { + int opt; + FILE *output = stdout; + + while ((opt = getopt(argc, argv, "hvo:")) != -1) { + switch (opt) { + case 'o': /* output file */ + output = fopen(optarg, "wb"); + if (!output) { + perror("opening output"); + return EX_OSFILE; + } + break; + case 'v': return version(false); + case 'h': return usage(false, argv[0]); + default: return usage(true, argv[0]); + } + } + + /* at least one file is required */ + if (argc <= optind) return usage(true, argv[0]); + + return puniq(output, &argv[optind], argc - optind); } diff --git a/src/repr.c b/src/repr.c index 929951c..42c49e6 100644 --- a/src/repr.c +++ b/src/repr.c @@ -1,14 +1,39 @@ +/* + * _ __ ___ _ __ _ __ + * | '__/ _ \ '_ \| '__| + * | | | __/ |_) | | + * |_| \___| .__/|_| + * |_| + * + * Quote non-printable bytes, similar to python's repr() + * + */ + #include +#include +#include +#include +#include "netre.h" -int -main(int argc, char *argv[]) -{ - while (1) { - int c = getchar(); +int version(bool error) { + fprintf(WHICHOUT(error), "repr v.%s - %s\n\n", PACKAGE_VERSION, + "quote non-printable bytes, similar to python's repr()"); + return error ? EX_USAGE : EX_OK; +} +int usage(bool error, char *prog) { + int retval = version(error); + fprintf(WHICHOUT(error), "Usage: %s [filename]\n\n", prog); + fprintf(WHICHOUT(error), "if a file is not specified, stdin will be read\n"); + return retval; +} + +int repr(FILE *f) { + int c; + + while (EOF != (c = getc(f))) { switch (c) { - case EOF: - return 0; + case EOF: return 0; case 134: printf("\\\\"); break; @@ -22,5 +47,29 @@ main(int argc, char *argv[]) } } + printf("\n"); return 0; } + +int main(int argc, char *argv[]) { + int opt; + FILE *input = stdin; + + /* option parsing */ + while ((opt = getopt(argc, argv, "hv")) != -1) { + switch (opt) { + case 'v': return version(false); + case 'h': return usage(false, argv[0]); + default: return usage(true, argv[0]); + } + } + + if (optind < argc) { + input = fopen(argv[optind], "rb"); + if (!input) { + perror("opening input file"); + return EX_OSFILE; + } + } + return repr(input); +} diff --git a/src/unhex.c b/src/unhex.c index 113c35a..686d037 100644 --- a/src/unhex.c +++ b/src/unhex.c @@ -1,26 +1,45 @@ -/* Hex Decoder -- 2012 Zephyr - * - * This file is in the public domain. I make no promises - * about the functionality of this program. +/* + * _ + * _ _ _ __ | |__ _____ __ + * | | | | '_ \| '_ \ / _ \ \/ / + * | |_| | | | | | | | __/> < + * \__,_|_| |_|_| |_|\___/_/\_\ + * + * convert hexits to their binary equivalent + * */ #include +#include +#include +#include +#include "netre.h" -int -main(int argc, char *argv[]) -{ - unsigned char acc = 0; - unsigned char nybble = 0; - unsigned long int count = 0; +int version(bool error) { + fprintf(WHICHOUT(error), "unhex v.%s - %s\n\n", PACKAGE_VERSION, + "convert hexits to their binary equivalent"); + return error ? EX_USAGE : EX_OK; +} - while (1) { - int c = getchar(); +int usage(bool error, char *prog) { + int retval = version(error); + fprintf(WHICHOUT(error), "Usage: %s [filename]\n\n", prog); + fprintf(WHICHOUT(error), "if a file is not specified, stdin will be read\n"); + return retval; +} + +int unhex(FILE *f) { + unsigned char acc = '\0'; + unsigned char nybble = '\0'; + unsigned long int count = 0; + + while (true) { + int c = getc(f); count += 1; switch (c) { - case EOF: - return 0; + case EOF: return EX_OK; case '0' ... '9': acc = (acc << 4) + c - '0'; nybble += 1; @@ -34,9 +53,9 @@ main(int argc, char *argv[]) nybble += 1; break; default: - if (nybble != 0) { - fprintf(stderr, "Warning: non-hex character mid-octet at offset %lu\n", count); - } + if (nybble != 0) + fprintf(stderr, + "Warning: non-hex character mid-octet at offset %lu\n", count); break; } @@ -47,5 +66,29 @@ main(int argc, char *argv[]) } } - return 0; + return EX_OK; +} + +int main(int argc, char *argv[]) { + int opt; + FILE *input = stdin; + + /* option parsing */ + while ((opt = getopt(argc, argv, "hv")) != -1) { + switch (opt) { + case 'v': return version(false); + case 'h': return usage(false, argv[0]); + default: return usage(true, argv[0]); + } + } + + if (optind < argc) { + input = fopen(argv[optind], "rb"); + if (!input) { + perror("opening input"); + return EX_OSFILE; + } + } + + return unhex(input); } diff --git a/src/xor.c b/src/xor.c index b3e5a78..5e2b18f 100644 --- a/src/xor.c +++ b/src/xor.c @@ -1,48 +1,76 @@ -/* xor filter -- 2012 Zephyr - * - * This file is in the public domain. I make no promises - * about the functionality of this program. +/* + * __ _ _ _ + * __ _____ _ __ / _(_) | |_ ___ _ __ + * \ \/ / _ \| '__| | |_| | | __/ _ \ '__| + * > < (_) | | | _| | | || __/ | + * /_/\_\___/|_| |_| |_|_|\__\___|_| + * + * apply mask bytes to the pipeline + * */ #include +#include #include +#include #include +#include +#include +#include "netre.h" -int -main(int argc, char *argv[]) -{ - int start = 1; - int base = 0; - int arg; - - if (argc < 2) { - fprintf(stderr, "Usage: %s [-x] m1 [m2 ...]\n", argv[0]); - return 1; - } - - if (0 == strcmp(argv[1], "-x")) { - base = 16; - start += 1; - } - - arg = start; - - while (1) { - int c = getchar(); - unsigned char mask; - - if (! argv[arg]) { - arg = start; - } - mask = strtol(argv[arg++], NULL, base); - - if (EOF == c) { - break; - } - - c ^= mask; - putchar(c); - } - - return 0; +int version(bool error) { + fprintf(WHICHOUT(error), "xor v.%s - %s\n\n", PACKAGE_VERSION, + "apply mask bytes to the pipeline, using XOR"); + return error ? EX_USAGE : EX_OK; +} + +int usage(bool error, char *prog) { + int retval = version(error); + fprintf(WHICHOUT(error), "Usage: %s [-x] MASK [MASK]*\n", prog); + fprintf(WHICHOUT(error), "\t-x\tmask bytes are hexadecimal\n"); + fprintf(WHICHOUT(error), "\tMASK\ta mask byte\n"); + return retval; +} + +void do_xor(uint8_t mask[], int len) { + int i = 0; + while (true) { + int c = getchar(); + + if (EOF == c) break; + + c ^= mask[i]; + putchar(c); + i = (i + 1) % len; + } +} + +int main(int argc, char *argv[]) { + int opt; + int masklen = 0; + int base = 0; + int i; + + /* option parsing */ + while ((opt = getopt(argc, argv, "hvx")) != -1) { + switch (opt) { + case 'x': + base = 16; + break; + case 'v': return version(false); + case 'h': return usage(false, argv[0]); + default: return usage(true, argv[0]); + } + } + + if (optind >= argc) return usage(true, argv[0]); + + masklen = argc - optind; + uint8_t mask[masklen]; + for (i = optind; i < argc; i++) + mask[i-optind] = (uint8_t)strtol(argv[i], NULL, base); + + do_xor(mask, masklen); + + return EX_OK; }