1
0
mirror of https://github.com/cmand/yarrp.git synced 2024-05-11 05:55:06 +00:00
Files
cmand-yarrp/entire.cpp

263 lines
8.7 KiB
C++
Raw Normal View History

2018-12-05 10:50:35 -08:00
/****************************************************************************
* Description: Special code for fast, entire Internet-wide IPv4 probing
*
****************************************************************************/
#include "yarrp.h"
void internet(YarrpConfig *config, Traceroute *trace, Patricia *tree, Stats *stats) {
uint8_t ttl;
uint32_t val = 0;
2019-10-09 12:37:00 -07:00
struct in_addr target;
2018-12-05 10:50:35 -08:00
TTLHisto *ttlhisto = NULL;
Status *status = NULL;
uint32_t host = 1 << 24;
char *p = NULL;
int i;
double prob, flip;
uint32_t octets_to_skip[13] = {0, /* reserved */
6, /* Army */
10, /* 1918 */
11, /* DoD */
22, /* DISA */
25, /* UK Defence */
26, /* DISA */
29, /* DISA */
30, /* DISA */
55, /* DoD */
127, /* loopback */
214, /* DoD */
215, /* DoD */
};
cout << ">> Randomizing permutation." << endl;
uint8_t key[KEYLEN] = { 0 };
if (config->seed)
permseed(key, config->seed);
else
permseed(key);
struct cperm_t* perm = cperm_create(UINT32_MAX, PERM_MODE_CYCLE,
PERM_CIPHER_RC5, key, KEYLEN);
p = (char *) &val;
while (PERM_END != cperm_next(perm, &val)) {
2019-10-09 12:37:00 -07:00
target.s_addr = val & 0x00FFFFFF; // pick out 24 bits of network
2018-12-05 10:50:35 -08:00
ttl = val >> 24; // use remaining 8 bits of perm as ttl
/* Probe a host in each /24 that's a function of the /24
(so it appears somewhat random), but is deterministic,
and fast to compute */
host = (p[0] + p[1] + p[2]) & 0xFF;
2019-10-09 12:37:00 -07:00
target.s_addr += (host << 24);
2018-12-05 10:50:35 -08:00
if ( (ttl & 0xE0) != 0x0) { // fast check: ttls in [0,31]
stats->ttl_outside++;
continue;
}
2019-10-09 12:37:00 -07:00
if (ttl >= config->maxttl)
continue;
2018-12-05 10:50:35 -08:00
#if 1
/* Only send probe if destination is in BGP table */
2019-10-09 12:37:00 -07:00
status = (Status *) tree->get(target.s_addr);
2018-12-05 10:50:35 -08:00
if (not status) {
stats->bgp_outside++;
continue;
}
#else
if ( (val & 0xE0) == 0xE0) { // multicast, class E
stats->adr_outside++;
continue;
}
for (i=0;i<13;i++) {
if ( (val & 0xFF) == octets_to_skip[i])
stats->adr_outside++;
continue;
}
#endif
ttl++; // probe ttls from 1 to 32
#if 1
if (ttl < config->ttl_neighborhood) {
ttlhisto = trace->ttlhisto[ttl];
if (ttlhisto->shouldProbe() == false) {
stats->nbr_skipped++;
continue;
}
ttlhisto->probed(trace->elapsed());
}
#endif
/* Running w/ a biased TTL probability distribution */
if (config->poisson) {
prob = poisson_pmf(ttl, config->poisson); /* poisson(k, lambda) */
flip = zrand(); /* uniform [0.0, 1.0) */
if (flip > prob)
continue;
}
2019-10-09 12:37:00 -07:00
/* Passed all checks, continue and send probe */
if (not config->testing)
trace->probe(target.s_addr, ttl);
else
trace->probePrint(&target, ttl);
2018-12-05 10:50:35 -08:00
stats->count++;
if (stats->count == config->count)
break;
/* Every 4096, do this */
if ( (stats->count & 0xFFF) == 0xFFF ) {
2019-10-09 12:37:00 -07:00
if (not config->testing)
stats->dump(stderr);
2018-12-05 10:50:35 -08:00
if (config->rate) {
/* Calculate sleep time based on scan rate */
usleep( (1000000 / config->rate) * 4096 );
}
}
}
}
/* SPECK 48/96 implementation */
#define MASK24 0xFFFFFF
#define SPECK_ROUNDS 23
#define SPECK_KEYLEN 4
#define ROR(x, r) ((x >> r) | (x << (24 - r))&MASK24)&MASK24
#define ROL(x, r) ((x << r) | (x >> (24 - r))&MASK24)&MASK24
#define R(x, y, k) (x = ROR(x, 8), x = (x + y)&MASK24, x ^= k, y = ROL(y, 3), y ^= x)
#define RR(x, y, k) (y ^= x, y = ROR(y, 3), x ^= k, x = (x - y)&MASK24, x = ROL(x, 8))
void speck_48_96_expand(uint32_t const K[SPECK_KEYLEN], uint32_t S[SPECK_ROUNDS])
{
uint32_t i, b = K[0];
uint32_t a[SPECK_KEYLEN - 1];
for (i = 0; i < (SPECK_KEYLEN - 1); i++)
{
a[i] = K[i + 1];
}
S[0] = b;
for (i = 0; i < SPECK_ROUNDS - 1; i++) {
R(a[i % (SPECK_KEYLEN - 1)], b, i);
S[i + 1] = b;
}
}
void speck_48_96_encrypt(uint32_t const pt[2], uint32_t ct[2], uint32_t const K[SPECK_ROUNDS])
{
uint32_t i;
ct[0]=pt[0]; ct[1]=pt[1];
for(i = 0; i < SPECK_ROUNDS; i++){
R(ct[1], ct[0], K[i]);
}
}
/* Use 48 bits speck cipher:
* prefix = 44 bits
* ttl = 4 bits
* Assume global unicast is 2000:/4, thus we generate candidate /48 prefixes
*/
void internet6(YarrpConfig *config, Traceroute *trace, Patricia *tree, Stats *stats) {
uint8_t ttl;
double prob, flip;
uint64_t range = 0xFFFFFFFFFFFF;
uint32_t buffer[2] = {0};
uint32_t exp[SPECK_ROUNDS];
uint32_t key[4] = {0x020100, 0x0a0908, 0x121110, 0x1a1918};
uint32_t plain[2];
struct in6_addr addr;
char addrstring[INET6_ADDRSTRLEN];
TTLHisto *ttlhisto = NULL;
memset(&addr, 0, sizeof(struct in6_addr));
speck_48_96_expand(key, exp);
#if 0
uint8_t iana8[6] = {0x20, 0x24, 0x26, 0x28, 0x2a, 0x2c};
uint16_t iana16[9] = {htons(0x2001), htons(0x2003), htons(0x2400), htons(0x2600),
htons(0x2610), htons(0x2620), htons(0x2800), htons(0x2a00),
htons(0x2c00)};
#endif
for (uint64_t i = 0; i<range; i++) {
plain[0] = i & 0x00FFFFFF;
plain[1] = (i & 0xFFFFFF000000) >> 24;
speck_48_96_encrypt(plain, buffer, exp);
/* magic ensues */
addr.s6_addr[0] = 0x20 | (buffer[0] & 0xF);
if ((addr.s6_addr[0] & 0x1) == 1) {
stats->bgp_outside++;
continue;
}
if (addr.s6_addr[0] == 0x22) {
stats->bgp_outside++;
continue;
}
if (addr.s6_addr[0] == 0x2e) {
stats->bgp_outside++;
continue;
}
addr.s6_addr[1] = (buffer[0] >> 4) & 0xFF;
/* allow only 2800::/12, 2a00::/12, 2c00::/12 */
if ((addr.s6_addr[0] >= 0x28) and ((addr.s6_addr[1] & 0xF0) != 0)) {
stats->bgp_outside++;
continue;
}
/* allow only 2001:: and 2003:: */
if ((addr.s6_addr[0] == 0x20) and ((addr.s6_addr[1] & 0xFD) != 1)) {
stats->bgp_outside++;
continue;
}
if ((addr.s6_addr[0] == 0x24) and ((addr.s6_addr[1] & 0xF0) != 0)) {
stats->bgp_outside++;
continue;
}
addr.s6_addr[2] = (buffer[0] >> 12) & 0xFF;
addr.s6_addr[3] = ((buffer[0] >> 20) & 0xF) << 4;
addr.s6_addr[3] |= buffer[1] & 0xF;
addr.s6_addr[4] = (buffer[1] >> 4) & 0xFF;
addr.s6_addr[5] = (buffer[1] >> 12) & 0xFF;
#if 1
if (tree->get(addr) == NULL) {
stats->bgp_outside++;
continue;
}
#endif
/* set bottom 32 bits to determinstic value of addr */
addr.s6_addr32[3] = (addr.s6_addr[0] + addr.s6_addr[1]) << 5;
addr.s6_addr32[3] += addr.s6_addr[4];
addr.s6_addr[15] = addr.s6_addr[2] + addr.s6_addr[3] + 100;
ttl = ((buffer[1] >> 20) & 0xF) + 1;
#if 0
inet_ntop(AF_INET6, &addr, addrstring, INET6_ADDRSTRLEN);
printf("Addr: %s TTL: %d\n", addrstring, ttl);
#endif
#if 1
if (ttl < config->ttl_neighborhood) {
ttlhisto = trace->ttlhisto[ttl];
if (ttlhisto->shouldProbe() == false) {
stats->nbr_skipped++;
continue;
}
ttlhisto->probed(trace->elapsed());
}
#endif
/* Running w/ a biased TTL probability distribution */
if (config->poisson) {
prob = poisson_pmf(ttl, config->poisson);
flip = zrand();
if (flip > prob)
continue;
}
trace->probe(addr, ttl);
stats->count++;
if (stats->count == config->count)
break;
/* Every 4096, do this */
if ( (stats->count & 0xFFF) == 0xFFF ) {
stats->dump(stderr);
if (config->rate) {
/* Calculate sleep time based on scan rate */
usleep( (1000000 / config->rate) * 4096 );
}
}
}
}