/* portcompress, by Doug Hoyte, July, 2007 Allows long lists of port numbers to be encoded in a fairly efficient ASCII-armoured run-length encoded transport medium for efficient storage and convenient interchange. This software is Copyright (C) 2004,2007 By Hardcore Software. The software is distributed under the terms of the GNU General Public License. See the website www.gnu.org for more information. Usage: portcompress [-e|-d] In encode mode (-e) takes whitespace separated decimal port numbers until EOF and prints out a compressed port list. In decode mode (-d) reads in a compressed port list and prints out the corresponding ports separated by newlines. */ /* Protocol: Either 00 = 0 11 = 1 or 01 = RLE string of 0s 10 = RLE string of 1s followed by one of 00 = 2 bits 01 = 4 bits 10 = 8 bits 11 = 16 bits followed by (run length - 4) encoded in a binary number of the previously specified bits Examples: "101" => "110011" "111" => "111111" "1111" => "100000" "11111" => "100001" */ ///////// ARMOUR CODE //////////// /* ASCII Armour Encoding, (C) 2004 HardCore SoftWare These are some small, efficient "plug and play" functions for encoding binary data in a safe ASCII transport medium. It is somewhat similar to base64 encoding, but simpler. This software is Copyright (C) 2004 By Hardcore Software. The software is distributed under the terms of the GNU General Public License. See the website www.gnu.org for more information. This function encodes a collection of binary data stored at the memory location "in", of length "len". It stores the ASCII encoded string in the memory location "out". "out" should have at least %50 more space available than "len". void encodearmour(char *in, int len, char *out); This function decodes an ASCII encoded string created by the encodearmour() function, stored in the memory location "in" and stores it into "out". "out" should have as much space as strlen(in). This function returns the number of bytes of data stored into "out". int decodearmour(char *in, char *out); -Doug Hoyte */ static char map[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+*"; static char revmap[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x3F\x3E\0\0\0\0\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\0\0\0\0\0\0\0\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\0\0\0\0\0\0\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\x30\x31\x32\x33"; void encodearmour(char *in, int len, char *out) { int curpos, bitoff, curbit, t=0; if (len == 0) { *out = '\0'; return; } curpos = curbit = 0; while(1) { curpos = curbit / 8; bitoff = curbit % 8; if (curpos == len-1) { if (bitoff == 2) { t = in[curpos] & 63; *(out++) = map[t]; } else if (bitoff == 0) { t = (in[curpos] & 0xFF) >> 2; *(out++) = map[t]; *(out++) = map[(in[curpos] & 3) << 4]; } else if (bitoff == 4) { t = (in[curpos] & 15) << 2; *(out++) = map[t & 63]; } break; } if (bitoff == 0) t = (in[curpos] & 0xFF) >> 2; else if (bitoff == 2) t = in[curpos] & 63; else if (bitoff == 4) t = ((in[curpos] & 15) << 2) | ((in[curpos+1] & 0xFF) >> 6); else if (bitoff == 6) t = ((in[curpos] & 3) << 4) | ((in[curpos+1] & 0xFF) >> 4); *(out++) = map[t & 63]; curbit += 6; } *out = '\0'; } int decodearmour(char *in, char *out) { int curbit=0, t, c1=0, c2=0, bytes=0; if (*in == 0) return 0; while(*in != '\0' && *in != '\n' && *in != '\r' && *in != ' ') { t = revmap[(int) *(in++)]; if (curbit == 0) c1 = t << 2; else if (curbit == 2) c1 |= t; else if (curbit == 4) { c1 |= t >> 2; c2 = (t & 3) << 6; } else if (curbit == 6) { c1 |= t >> 4; c2 = (t & 15) << 4; } curbit += 6; if (curbit >= 8) { *(out++) = c1 & 0xFF; bytes++; c1 = c2; c2 = 0; curbit %= 8; } } return bytes; } ///////// END OF ARMOUR CODE //////////// #include #include #define MIN(x,y) ((x)<(y)?(x):(y)) // BSS is init to 0s char ports[65536]; char unarm[16384]; int unarm_off = 0; int unarm_bits_left = 8; char arm[32768]; void usage() { fprintf(stderr, "portcompress by Doug Hoyte\n\n Usage: portcompress [-d|-e]\n"); exit(1); } void add_unarm(int bits, int v) { int newbits=-1, newv; if (bits > unarm_bits_left) { newbits = bits - unarm_bits_left; newv = ((1 << newbits) - 1) & v; bits = unarm_bits_left; v >>= newbits; } if (bits < unarm_bits_left) v <<= unarm_bits_left - bits; unarm[unarm_off] |= v; unarm_bits_left -= bits; if (!unarm_bits_left) { unarm_off++; unarm_bits_left = 8; if (newbits != -1) add_unarm(newbits, newv); } } void output_encode(int run, int v) { if (run < 4) { for (;run; run--) { if (v) add_unarm(2, 3); else add_unarm(2, 0); } } else { if (v) add_unarm(2, 2); else add_unarm(2, 1); if (run-4 < 4) { add_unarm(2, 0); add_unarm(2, run-4); } else if (run-4 < 16) { add_unarm(2, 1); add_unarm(4, run-4); } else if (run-4 < 256) { add_unarm(2, 2); add_unarm(8, run-4); } else if (run-4 < 65536) { add_unarm(2, 3); add_unarm(16, run-4); } } } int do_encode() { int v; int curr, run; while(EOF != fscanf(stdin, "%d", &v)) { if (v < 0 || v > 65535) { fprintf(stderr, "portcompress: bad port value: %d\n", v); exit(3); } if (ports[v]) { fprintf(stderr, "portcompress: duplicate port: %d\n", v); exit(4); } ports[v] = 1; } run = 1; v = ports[0] & 0xff; for (curr=1; curr<65536; curr++) { if ((ports[curr] & 0xff) != v) { output_encode(run, v); run=0; v = ports[curr] & 0xff; } run++; } output_encode(run, v); if (unarm_bits_left != 8) unarm_off++; encodearmour(unarm, unarm_off, arm); printf("%s\n", arm); } int getint(int off, int wid) { int r=0; while(wid > 0) { int take, bshift; take = MIN(wid, 8 - (off % 8)); bshift = (8 - (take + (off % 8))); r <<= take; r |= (unarm[off/8] & (((1<> bshift; off += take; wid -= take; } return r; } int do_decode() { char *currread = arm; int curr, v, rlev, rbits, rquant; int currport = 0; currread = arm; while(1) { v = read(0, currread, sizeof(arm)-(currread-arm)); currread += v; if (currread >= arm+sizeof(arm)) { fprintf(stderr, "Input too long\n"); exit(5); } if (v <= 0) break; } if (currread <= arm+2) usage(); decodearmour(arm, unarm); for (curr=0; currport < 65536 && curr/8 < sizeof(unarm);) { v = getint(curr, 2); curr += 2; if (v == 0) ports[currport++] = 0; else if (v == 3) ports[currport++] = 1; else { if (v == 1) rlev = 0; if (v == 2) rlev = 1; rbits = 2 << (getint(curr, 2) & 3); curr += 2; rquant = getint(curr, rbits) + 4; curr += rbits; while(rquant--) ports[currport++] = rlev; } } for (curr=0; curr<65536; curr++) { if (ports[curr]) printf("%d\n", curr); } } int main(int argc, char **argv) { if (argc != 2) usage(); if (0 == strcmp(argv[1], "-e")) do_encode(); else if (0 == strcmp(argv[1], "-d")) do_decode(); else usage(); }