Working Gapstr

This commit is contained in:
Neale Pickett 2014-08-08 13:57:50 -06:00
parent c992230e54
commit 45b200eb18
20 changed files with 169 additions and 1203 deletions

View File

@ -1,30 +1,13 @@
CFLAGS = -Wall -Werror
TARGETS += puniq
TARGETS += hd
TARGETS += netarch
GOPATH = $(CURDIR)
export GOPATH
all: $(TARGETS)
all:
go build $(TARGETS)
%: src/%.go
go build $@
%: %.go
go build $<
install: $(TARGETS)
install -d $(DESTDIR)$(PREFIX)
install $(TARGETS) $(DESTDIR)$(PREFIX)/bin
pmerge: pmerge.o pcap.o
puniq: puniq.o pcap.o
p4split: p4split.o pcap.o
pcat: pcat.o pcap.o stream.o
pcat.o: CFLAGS += -Wno-unused-variable
test:
go test $(TARGETS)
clean:
rm -f $(TARGETS) *.o
go clean

View File

@ -1,16 +0,0 @@
#! /bin/sh
# Emulate dumbdecode.py from python netarch
# The advantage here is, after the pcat step, you're dealing with text files.
# * cache the output of pcat to speed things up a little.
# * tail -n +5000 to ignore the first 5000 lines of your cache.
# * grep the cache, use sed, awk, whatever
./pmerge "$@" | ./pcat | while read ts proto src dst payload; do
#when=$(TZ=Z date --rfc-3339=ns -d @$ts)
printf "Packet %s None: None\n" $proto
printf " %s -> %s (%s)\n" ${src%,*} ${dst%,*} "$ts"
echo $payload | ./unhex | ./hd
echo
done

98
hd.c
View File

@ -1,98 +0,0 @@
#include <stdio.h>
#include <stdint.h>
#include <string.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", "{", "|", "}", "~", "",
"Ç", "ü", "é", "â", "ä", "à", "å", "ç", "ê", "ë", "è", "ï", "î", "ì", "Ä", "Å",
"É", "æ", "Æ", "ô", "ö", "ò", "û", "ù", "ÿ", "Ö", "Ü", "¢", "£", "¥", "", "ƒ",
"á", "í", "ó", "ú", "ñ", "Ñ", "ª", "º", "½", "", "¼", "", "", "", "«", "»",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"α", "ß", "Γ", "π", "Σ", "σ", "µ", "τ", "Φ", "Θ", "Ω", "δ", "", "φ", "ε", "",
"", "¹", "²", "³", "", "", "", "", "", "", "", "", "", "", "", "¤",
};
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;
}

149
p4split.c
View File

@ -1,149 +0,0 @@
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <sysexits.h>
#include <strings.h>
#include "pcap.h"
/*
* Gaah so much crap
*/
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/ether.h>
#include <netinet/ip.h>
#include <netinet/in.h>
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;
}

101
pcap.c
View File

@ -1,101 +0,0 @@
#include <stdio.h>
#include <sysexits.h>
#include <string.h>
#include "pcap.h"
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 (MAGIC == h.magic) {
ctx->swap = 0;
} else if (bswap32(MAGIC) == h.magic) {
ctx->swap = 1;
} else {
return -1;
}
if ((h.version_major != 2) || (h.version_minor != 4)) {
return -1;
}
if (ctx->swap) {
h.snaplen = bswap32(h.snaplen);
}
if (h.snaplen > MAXFRAME) {
return -1;
}
ctx->linktype = h.linktype;
ctx->f = f;
return 0;
}
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;
}
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;
}
if (ctx->swap) {
hdr->ts.tv_sec = bswap32(hdr->ts.tv_sec);
hdr->ts.tv_usec = bswap32(hdr->ts.tv_usec);
hdr->caplen = bswap32(hdr->caplen);
hdr->len = bswap32(hdr->len);
}
if (hdr->caplen > MAXFRAME) {
return -1;
}
return 0;
}
int
pcap_write_pkthdr(struct pcap_file *ctx, struct pcap_pkthdr *hdr)
{
if (ctx->swap) {
struct pcap_pkthdr ohdr;
memcpy(&ohdr, hdr, sizeof(ohdr));
hdr->ts.tv_sec = bswap32(hdr->ts.tv_sec);
hdr->ts.tv_usec = bswap32(hdr->ts.tv_usec);
hdr->caplen = bswap32(hdr->caplen);
hdr->len = bswap32(hdr->len);
if (1 != fwrite(&ohdr, sizeof(ohdr), 1, ctx->f)) {
return -1;
}
} else {
if (1 != fwrite(hdr, sizeof(*hdr), 1, ctx->f)) {
return -1;
}
}
return 0;
}
void
pcap_close(struct pcap_file *ctx)
{
fclose(ctx->f);
}

76
pcap.h
View File

@ -1,76 +0,0 @@
#ifndef __PCAP_H__
#define __PCAP_H__
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#define MAGIC 0xa1b2c3d4
#define MAXFRAME 9000
/*
* Described at http://www.tcpdump.org/linktypes.html
*/
#define LINKTYPE_ETHERNET 1
#define LINKTYPE_RAW 101
struct pcap_file {
FILE *f;
uint32_t linktype;
bool swap;
};
struct pcap_file_header {
uint32_t magic;
uint16_t version_major;
uint16_t version_minor;
int32_t thiszone; /* gmt to local correction */
uint32_t sigfigs; /* accuracy of timestamps */
int32_t snaplen; /* max length saved portion of each pkt */
int32_t linktype; /* data link type (LINKTYPE_*) */
};
struct pcap_pkthdr {
struct pcap_timeval {
uint32_t tv_sec;
uint32_t tv_usec;
} ts; /* time stamp */
uint32_t caplen; /* length of portion present */
uint32_t len; /* length this packet (off wire) */
};
#ifndef max
#define max(a, b) ((a)>(b)?(a):(b))
#endif
#ifndef min
#define min(a, b) ((a)<(b)?(a):(b))
#endif
#define bswap32(i) (((i & 0xff000000) >> 030) | \
((i & 0x00ff0000) >> 010) | \
((i & 0x0000ff00) << 010) | \
((i & 0x000000ff) << 030))
#define bswap16(i) (((i & 0xff00) >> 010) | \
((i & 0x00ff) << 010))
/*
* 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);
int pcap_read_pkthdr(struct pcap_file *ctx, struct pcap_pkthdr *hdr);
int pcap_write_pkthdr(struct pcap_file *ctx, struct pcap_pkthdr *hdr);
void pcap_close(struct pcap_file *ctx);
#endif /* __PCAP_H__ */

207
pcat.c
View File

@ -1,207 +0,0 @@
/*
* pcat.c -- pcap to text
*
* Reads pcap on stdin, dumps text representation to stdout.
* This discards or ignores some parts of packets. If fidelity is a concern,
* deal directly with the original pcap.
*
* Output lines are of the form:
*
* PROTO SRC DST OPTS PAYLOAD
*
*/
#include <stdio.h>
#include <stdint.h>
#include "pcap.h"
#include "stream.h"
#define IPPROTO_TCP 6
#define IPPROTO_UDP 17
#define IPPROTO_ICMP 1
#define TH_FIN 0x01
#define TH_SYN 0x02
#define TH_RST 0x04
#define TH_PSH 0x08
#define TH_ACK 0x10
#define TH_URG 0x20
void
ip4_addr(char *addr_s, uint32_t addr)
{
snprintf(addr_s, 16, "%u.%u.%u.%u", (addr >> 24) & 0xff, (addr >> 16) & 0xff, (addr >> 8) & 0xff, (addr >> 0) & 0xff);
}
void
print_payload(struct stream *s)
{
while (s->len) {
printf("%02x", read_uint8(s));
}
}
void
process_tcp(struct stream *s, char *saddr_s, char *daddr_s)
{
uint16_t sport = read_uint16(s);
uint16_t dport = read_uint16(s);
uint32_t seq = read_uint32(s);
uint32_t ack = read_uint32(s);
uint8_t off = read_uint8(s);
uint8_t hlen = (off >> 4) * 4;
uint8_t flags = read_uint8(s);
uint16_t window = read_uint16(s);
uint16_t chksum = read_uint16(s);
uint16_t urgent = read_uint16(s);
if (hlen < 20) {
printf("!");
}
printf("TCP %s,%u %s,%u %u,%u,%d ", saddr_s, sport, daddr_s, dport, seq, ack, flags);
}
void
process_udp(struct stream *s, char *saddr_s, char *daddr_s)
{
uint16_t sport = read_uint16(s);
uint16_t dport = read_uint16(s);
uint16_t len = read_uint16(s);
uint16_t chksum = read_uint16(s);
printf("UDP %s,%u %s,%u 0 ", saddr_s, sport, daddr_s, dport);
}
void
process_icmp(struct stream *s, char *saddr_s, char *daddr_s)
{
uint8_t type = read_uint8(s);
uint8_t code = read_uint8(s);
uint16_t checksum = read_uint16(s);
printf("ICMP %d,%d %s %s ", type, code, saddr_s, daddr_s);
}
void
process_ip4(struct stream *s)
{
uint8_t vhl = read_uint8(s);
uint8_t ihl = (vhl & 0x0f) * 4;
uint8_t tos = read_uint8(s);
uint16_t length = read_uint16(s);
uint16_t id = read_uint16(s);
uint16_t off = read_uint16(s);
uint8_t ttl = read_uint8(s);
uint8_t proto = read_uint8(s);
uint16_t chksum = read_uint16(s);
uint32_t saddr = read_uint32(s);
uint32_t daddr = read_uint32(s);
char saddr_s[20];
char daddr_s[20];
ip4_addr(saddr_s, saddr);
ip4_addr(daddr_s, daddr);
// Ignore options
sskip(s, 20 - ihl);
// Force stream length to IP payload length
s->len = length - ihl;
switch (proto) {
case IPPROTO_TCP:
process_tcp(s, saddr_s, daddr_s);
break;
case IPPROTO_UDP:
process_udp(s, saddr_s, daddr_s);
break;
case IPPROTO_ICMP:
process_icmp(s, saddr_s, daddr_s);
break;
default:
printf("P%d %s %s ", proto, saddr_s, daddr_s);
break;
}
print_payload(s);
}
void
print_ethernet(struct stream *s)
{
uint8_t saddr[6];
uint8_t daddr[6];
uint16_t ethertype;
sread(s, &saddr, sizeof(saddr));
sread(s, &daddr, sizeof(daddr));
ethertype = read_uint16(s);
if (ethertype == 0x8100) {
// VLAN
read_uint16(s);
ethertype = read_uint16(s);
}
switch (ethertype) {
case 0x0800: // IPv4
process_ip4(s);
break;
}
}
void
print_frame(struct pcap_file *p, struct pcap_pkthdr *hdr, char const *frame)
{
struct stream streambuf;
struct stream *s = &streambuf;
sinit(s, frame, hdr->caplen);
printf("%u.%u ", hdr->ts.tv_sec, hdr->ts.tv_usec);
switch (p->linktype) {
case LINKTYPE_ETHERNET:
print_ethernet(s);
break;
case LINKTYPE_RAW:
process_ip4(s);
break;
}
printf("\n");
}
void
pcat(FILE * f)
{
struct pcap_file p;
if (-1 == pcap_open_in(&p, f))
return;
for (;;) {
struct pcap_pkthdr hdr;
char frame[MAXFRAME];
if (-1 == pcap_read_pkthdr(&p, &hdr)) {
break;
}
if (1 != fread(frame, hdr.caplen, 1, f)) {
break;
}
print_frame(&p, &hdr, frame);
}
}
int
main(int argc, char *argv[])
{
pcat(stdin);
return 0;
}

142
pmerge.c
View File

@ -1,142 +0,0 @@
#include <stdio.h>
#include <stdint.h>
#include <sysexits.h>
#include "pcap.h"
struct input_file {
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
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
main(int argc, char *argv[])
{
struct input_file files[argc - 1];
int nfiles = 0;
int nopen;
int i;
struct pcap_file out;
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_open_in(&cur->p, f)) {
fprintf(stderr, "%s: unable to process\n", fn);
return EX_IOERR;
}
cur->active = 1;
if (0 == read_next(cur)) {
nfiles += 1;
}
}
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");
return EX_IOERR;
}
if (len != fwrite(frame, 1, len, stdout)) {
perror("error");
return EX_IOERR;
}
}
if (-1 == read_next(cur)) {
nopen -= 1;
}
}
return 0;
}

View File

@ -1,40 +0,0 @@
#include <stdio.h>
#include <ctype.h>
int
main(int argc, char *argv[])
{
printf("printf ");
while (!feof(stdin)) {
int c = getchar();
switch (c) {
case EOF:
break;
case '\n':
printf("\\n");
break;
case '\r':
printf("\\r");
break;
case '\t':
printf("\\t");
break;
case '"':
printf("\\\"");
break;
default:
if (isprint(c)) {
putchar(c);
} else {
printf("\\%03o", c);
}
break;
}
}
putchar('\n');
return 0;
}

68
puniq.c
View File

@ -1,68 +0,0 @@
#include <stdio.h>
#include <sysexits.h>
#include <string.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;
}

26
pyesc.c
View File

@ -1,26 +0,0 @@
#include <stdio.h>
int
main(int argc, char *argv[])
{
while (1) {
int c = getchar();
switch (c) {
case EOF:
return 0;
case 134:
printf("\\\\");
break;
case 32 ... 91:
case 93 ... 126:
putchar(c);
break;
default:
printf("\\x%02x", c);
break;
}
}
return 0;
}

View File

@ -8,7 +8,13 @@ import (
func main() {
g := new(netarch.Gapstr)
g = g.AppendString("hello")
g = g.AppendGap(12)
g = g.AppendGap(10)
g = g.AppendString(" world")
fmt.Println("hi", g.String())
fmt.Printf("%v\n", g)
fmt.Printf("%#v\n", g.Slice(0, 4))
fmt.Printf("%#v\n", g.Slice(4, 8))
fmt.Printf("%#v\n", g.Slice(8, 12))
fmt.Printf("%#v\n", g.Slice(12, 16))
}

View File

View File

@ -4,26 +4,80 @@ import (
"bytes"
)
func min(a, b int) int {
if a < b {
return a
}
return b
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
type chunk interface{}
func chunkLen(c chunk) int {
switch c.(type) {
case int:
return c.(int)
case string:
return len(c.(string))
}
return 0
}
func chunkSlice(c chunk, beg, end int) chunk {
switch c.(type) {
case int:
return end - beg
case string:
return c.(string)[beg:end]
}
return 0
}
// The type of a function to be passed to Map
type Processor func(int, string) string
type Gapstr struct {
chunks []chunk
}
func GapstrOfString(s string) *Gapstr {
return &Gapstr{[]chunk{s}}
func (g *Gapstr) Length() int {
ret := 0
for _, c := range g.chunks {
ret += chunkLen(c)
}
return ret
}
func (g *Gapstr) appendChunk(c chunk) *Gapstr {
return &Gapstr{append(g.chunks, c)}
func (g *Gapstr) HasGaps() bool {
for _, c := range g.chunks {
switch c.(type) {
case int:
return true
}
}
return false
}
func (g *Gapstr) Copy() *Gapstr {
chunks := make([]chunk, len(g.chunks))
copy(chunks, g.chunks)
return &Gapstr{chunks}
}
func (g *Gapstr) AppendString(s string) *Gapstr {
return g.appendChunk(s)
return &Gapstr{append(g.chunks, s)}
}
func (g *Gapstr) AppendGap(len int) *Gapstr {
return g.appendChunk(len)
return &Gapstr{append(g.chunks, len)}
}
func (g *Gapstr) String() string {
@ -38,3 +92,54 @@ func (g *Gapstr) String() string {
}
return b.String()
}
// Apply proc to everything in g
func (g *Gapstr) Map(proc Processor) *Gapstr {
chunks := make([]chunk, 0, len(g.chunks))
pos := 0
for _, c := range g.chunks {
switch c.(type) {
case int:
chunks = append(chunks, c)
case string:
chunks = append(chunks, proc(pos, c.(string)))
}
pos += chunkLen(c)
}
return &Gapstr{chunks}
}
func (g *Gapstr) Xor(mask []byte) *Gapstr {
xorproc := func(pos int, s string) string {
var b bytes.Buffer
for i := 0; i < len(s); i += 1 {
p := (pos + i) % len(mask)
b.WriteByte(s[i] ^ mask[p])
}
return b.String()
}
return g.Map(xorproc)
}
func (g *Gapstr) Slice(beg, end int) *Gapstr {
pos := 0
chunks := make([]chunk, 0)
for _, c := range g.chunks {
cl := chunkLen(c)
if (pos + cl > beg) && (pos <= end) {
cb := max(beg - pos, 0)
ce := min(end - pos, cl)
chunks = append(chunks, chunkSlice(c, cb, ce))
}
pos += cl
}
return &Gapstr{chunks}
}

View File

@ -0,0 +1,43 @@
package netarch
import (
"testing"
)
func AssertEqual(t *testing.T, a, b interface{}) {
if a != b {
t.Errorf("Not equal: %#v, %#v", a, b)
}
}
func TestChunk(t *testing.T) {
c := chunk("hello")
AssertEqual(t, chunkLen(c), 5)
AssertEqual(t, chunkSlice(c, 0, 3), "hel")
AssertEqual(t, chunkSlice(c, 3, 5), "lo")
c = chunk(5)
AssertEqual(t, chunkLen(c), 5)
AssertEqual(t, chunkSlice(c, 0, 3), 3)
AssertEqual(t, chunkSlice(c, 3, 5), 2)
}
func TestGapstr(t *testing.T) {
g := new(Gapstr)
g = g.AppendString("hello")
g = g.AppendGap(10)
g = g.AppendString(" world")
gs := g.String()
AssertEqual(t, gs, "hello\000\000\000\000\000\000\000\000\000\000 world")
for i := 0; i <= 20; i += 4 {
j := i+4
if j > len(gs) {
j = len(gs)
}
AssertEqual(t, g.Slice(i, i+4).String(), gs[i:j])
}
AssertEqual(t, g.Slice(0, 12).String(), gs[0:12])
}

View File

@ -99,9 +99,6 @@ func (r *Reader) Read() (*Frame, error) {
var h FrameHeader
err := binary.Read(r.r, r.order, &h)
if err == EOF {
return nil, nil
}
if err != nil {
return nil, err
}

118
stream.c
View File

@ -1,118 +0,0 @@
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include "stream.h"
void
sinit(struct stream *s, char const *buf, size_t buflen, enum endianness endian)
{
s->buf = buf;
s->len = buflen;
s->endian = endian;
}
bool
sskip(struct stream *s, size_t count)
{
if (count > s->len) {
s->len = 0;
return false;
}
s->buf += count;
s->len -= count;
return true;
}
bool
sread(struct stream *s, void *buf, size_t count)
{
void const *d = s->buf;
if (!sskip(s, count)) {
return false;
}
memcpy(buf, d, count);
return true;
}
uint8_t
read_uint8(struct stream *s)
{
uint8_t *d = (uint8_t *) s->buf;
if (!sskip(s, 1)) {
return 0;
}
return d[0];
}
uint16_t
read_uint16be(struct stream *s)
{
uint8_t *d = (uint8_t *) s->buf;
if (!sskip(s, 2)) {
return 0;
}
return ((d[0] << 8) | (d[1] << 0));
}
uint16_t
read_uint16le(struct stream *s)
{
uint8_t *d = (uint8_t *) s->buf;
if (!sskip(s, 2)) {
return 0;
}
return ((d[0] << 0) | (d[1] << 8));
}
uint16_t
read_uint16(struct stream *s)
{
if (s->endian == ENDIAN_BIG) {
return read_uint16be(s);
} else {
return read_uint16le(s);
}
}
uint32_t
read_uint32be(struct stream *s)
{
uint8_t *d = (uint8_t *) s->buf;
if (!sskip(s, 4)) {
return 0;
}
return ((d[0] << 24) | (d[1] << 16) | (d[2] << 8) | (d[3] << 0));
}
uint32_t
read_uint32le(struct stream *s)
{
uint8_t *d = (uint8_t *) s->buf;
if (!sskip(s, 4)) {
return 0;
}
return ((d[0] << 0) | (d[1] << 8) | (d[2] << 16) | (d[3] << 24));
}
uint32_t
read_uint32(struct stream *s)
{
if (s->endian == ENDIAN_BIG) {
return read_uint32be(s);
} else {
return read_uint32le(s);
}
}

View File

@ -1,30 +0,0 @@
#ifndef _STREAM_H
#define _STREAM_H
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
enum endianness {
ENDIAN_BIG,
ENDIAN_LITTLE
};
struct stream {
char const *buf;
size_t len;
enum endianness endian;
};
void sinit(struct stream *s, char const *buf, size_t len, enum endianness endian);
bool sskip(struct stream *s, size_t count);
bool sread(struct stream *s, void *buf, size_t count);
uint8_t read_uint8(struct stream *s);
uint16_t read_uint16be(struct stream *s);
uint16_t read_uint16le(struct stream *s);
uint16_t read_uint16(struct stream *s);
uint32_t read_uint32be(struct stream *s);
uint32_t read_uint32le(struct stream *s);
uint32_t read_uint32(struct stream *s);
#endif

50
unhex.c
View File

@ -1,50 +0,0 @@
/*
* Hex Decoder -- 2012 Zephyr <zephyr@dirtbags.net> This file is in the public domain. I make no promises about the functionality
* of this program.
*/
#include <stdio.h>
int
main(int argc, char *argv[])
{
unsigned char acc = 0;
unsigned char nybble = 0;
unsigned long int count = 0;
while (1) {
int c = getchar();
count += 1;
switch (c) {
case EOF:
return 0;
case '0' ... '9':
acc = (acc << 4) + c - '0';
nybble += 1;
break;
case 'a' ... 'f':
acc = (acc << 4) + c - 'a' + 10;
nybble += 1;
break;
case 'A' ... 'F':
acc = (acc << 4) + c - 'A' + 10;
nybble += 1;
break;
default:
if (nybble != 0) {
fprintf(stderr, "Warning: non-hex character mid-octet at offset %lu\n", count);
}
break;
}
if (nybble == 2) {
putchar(acc);
acc = 0;
nybble = 0;
}
}
return 0;
}

47
xor.c
View File

@ -1,47 +0,0 @@
/*
* xor filter -- 2012 Zephyr <zephyr@dirtbags.net> This file is in the public domain. I make no promises about the functionality
* of this program.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.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;
}