1 #include <sys/types.h> 2 #include <sys/socket.h> 3 4 #include <arpa/inet.h> 5 #include <netinet/in.h> 6 7 #include <stdint.h> 8 #include <stdio.h> 9 #include <stdlib.h> 10 #include <string.h> 11 #include <unistd.h> 12 13 #define KEYLEN 40 14 #define HASHLEN 12 15 16 static uint8_t toeplitz_key[KEYLEN]; 17 static uint32_t hash_table[HASHLEN][256]; 18 19 static void toeplitz_init(uint32_t[][256], int, const uint8_t[], int); 20 static void getaddrport(char *, uint32_t *, uint16_t *); 21 22 static void 23 usage(const char *cmd) 24 { 25 fprintf(stderr, "%s [-s s1_hex [-s s2_hex]] [-p] [-m mask] " 26 "addr1.port1 addr2.port2\n", cmd); 27 exit(1); 28 } 29 30 int 31 main(int argc, char *argv[]) 32 { 33 uint32_t saddr, daddr; 34 uint16_t sport, dport; 35 uint32_t res, mask; 36 37 const char *cmd = argv[0]; 38 uint8_t seeds[2] = { 0x6d, 0x5a }; 39 int i, opt, use_port; 40 41 i = 0; 42 use_port = 0; 43 mask = 0xffffffff; 44 45 while ((opt = getopt(argc, argv, "s:pm:")) != -1) { 46 switch (opt) { 47 case 's': 48 if (i >= 2) 49 usage(cmd); 50 seeds[i++] = strtoul(optarg, NULL, 16); 51 break; 52 53 case 'p': 54 use_port = 1; 55 break; 56 57 case 'm': 58 mask = strtoul(optarg, NULL, 16); 59 break; 60 61 default: 62 usage(cmd); 63 } 64 } 65 argc -= optind; 66 argv += optind; 67 68 if (argc != 2) 69 usage(cmd); 70 71 for (i = 0; i < KEYLEN; ++i) { 72 if (i & 1) 73 toeplitz_key[i] = seeds[1]; 74 else 75 toeplitz_key[i] = seeds[0]; 76 } 77 78 getaddrport(argv[0], &saddr, &sport); 79 getaddrport(argv[1], &daddr, &dport); 80 81 toeplitz_init(hash_table, HASHLEN, toeplitz_key, KEYLEN); 82 83 res = hash_table[0][(saddr >> 0) & 0xff]; 84 res ^= hash_table[1][(saddr >> 8) & 0xff]; 85 res ^= hash_table[2][(saddr >> 16) & 0xff]; 86 res ^= hash_table[3][(saddr >> 24) & 0xff]; 87 res ^= hash_table[4][(daddr >> 0) & 0xff]; 88 res ^= hash_table[5][(daddr >> 8) & 0xff]; 89 res ^= hash_table[6][(daddr >> 16) & 0xff]; 90 res ^= hash_table[7][(daddr >> 24) & 0xff]; 91 if (use_port) { 92 res ^= hash_table[8][(sport >> 0) & 0xff]; 93 res ^= hash_table[9][(sport >> 8) & 0xff]; 94 res ^= hash_table[10][(dport >> 0) & 0xff]; 95 res ^= hash_table[11][(dport >> 8) & 0xff]; 96 } 97 98 printf("0x%08x, masked 0x%08x\n", res, res & mask); 99 exit(0); 100 } 101 102 static void 103 toeplitz_init(uint32_t cache[][256], int cache_len, 104 const uint8_t key_str[], int key_strlen) 105 { 106 int i; 107 108 if (key_strlen < cache_len + (int)sizeof(uint32_t)) 109 exit(1); 110 111 for (i = 0; i < cache_len; ++i) { 112 uint32_t key[NBBY]; 113 int j, b, shift, val; 114 115 bzero(key, sizeof(key)); 116 117 /* 118 * Calculate 32bit keys for one byte; one key for each bit. 119 */ 120 for (b = 0; b < NBBY; ++b) { 121 for (j = 0; j < 32; ++j) { 122 uint8_t k; 123 int bit; 124 125 bit = (i * NBBY) + b + j; 126 127 k = key_str[bit / NBBY]; 128 shift = NBBY - (bit % NBBY) - 1; 129 if (k & (1 << shift)) 130 key[b] |= 1 << (31 - j); 131 } 132 } 133 134 /* 135 * Cache the results of all possible bit combination of 136 * one byte. 137 */ 138 for (val = 0; val < 256; ++val) { 139 uint32_t res = 0; 140 141 for (b = 0; b < NBBY; ++b) { 142 shift = NBBY - b - 1; 143 if (val & (1 << shift)) 144 res ^= key[b]; 145 } 146 cache[i][val] = res; 147 } 148 } 149 } 150 151 static void 152 getaddrport(char *ap_str, uint32_t *addr, uint16_t *port0) 153 { 154 uint16_t port; 155 char *p; 156 157 p = strrchr(ap_str, '.'); 158 if (p == NULL) { 159 fprintf(stderr, "invalid addr.port %s\n", ap_str); 160 exit(1); 161 } 162 163 *p = '\0'; 164 ++p; 165 166 port = strtoul(p, NULL, 10); 167 *port0 = htons(port); 168 169 if (inet_pton(AF_INET, ap_str, addr) <= 0) { 170 fprintf(stderr, "invalid addr %s\n", ap_str); 171 exit(1); 172 } 173 } 174