mirror of
https://github.com/cmand/yarrp.git
synced 2024-05-11 05:55:06 +00:00
119 lines
3.4 KiB
C++
119 lines
3.4 KiB
C++
#include "yarrp.h"
|
|
#include "random_list.h"
|
|
|
|
RandomSubnetList::RandomSubnetList(uint8_t _maxttl, uint8_t _gran):SubnetList(_maxttl, _gran) {
|
|
seeded = false;
|
|
perm = NULL;
|
|
memset(key, 0, KEYLEN);
|
|
}
|
|
|
|
RandomSubnetList::~RandomSubnetList() {
|
|
if (perm)
|
|
cperm_destroy(perm);
|
|
}
|
|
|
|
void
|
|
RandomSubnetList::seed() {
|
|
PermMode mode = PERM_MODE_CYCLE;
|
|
assert(addr_count > 0);
|
|
|
|
if (addr_count < 500000) {
|
|
mode = PERM_MODE_PREFIX;
|
|
}
|
|
//printf("%s: permsize: %d\n", __func__, addr_count);
|
|
perm = cperm_create(addr_count, mode, PERM_CIPHER_RC5, key, 16);
|
|
if (!perm) {
|
|
printf("Failed to initialize permutation of size %u. Code: %d\n", addr_count, cperm_get_last_error());
|
|
exit(1);
|
|
}
|
|
seeded = true;
|
|
}
|
|
|
|
uint32_t
|
|
RandomSubnetList::next_address(struct in_addr *in, uint8_t *ttl) {
|
|
list < Subnet >::iterator iter;
|
|
uint64_t next;
|
|
uint32_t subnet_count, current = 0;
|
|
uint32_t addr, offset;
|
|
|
|
if (!seeded)
|
|
seed();
|
|
|
|
if (PERM_END == cperm_next(perm, &next))
|
|
return 0;
|
|
|
|
for (iter = subnets.begin(); iter != subnets.end(); iter++) {
|
|
subnet_count = (*iter).count() * maxttl;
|
|
if (next >= current && next < current + subnet_count) {
|
|
offset = next - current;
|
|
// LSB's encode the TTL
|
|
*ttl = (offset & ttlmask) + 1;
|
|
addr = (*iter).first() + (offset << (8 - ttlmask_bits));
|
|
addr = addr & 0xffffff00;
|
|
addr += getHost((uint8_t *) &addr);
|
|
in->s_addr = htonl(addr);
|
|
return 1;
|
|
}
|
|
current += subnet_count;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
uint32_t
|
|
RandomSubnetList::next_address(struct in6_addr *in, uint8_t * ttl) {
|
|
list < Subnet6 >::iterator iter;
|
|
uint64_t next = 0;
|
|
uint32_t subnet_count, current = 0;
|
|
uint32_t offset = 0;
|
|
uint64_t high, iid = 0;
|
|
|
|
if (!seeded)
|
|
seed();
|
|
|
|
if (PERM_END == cperm_next(perm, &next))
|
|
return 0;
|
|
|
|
for (iter = subnets6.begin(); iter != subnets6.end(); iter++) {
|
|
subnet_count = (*iter).count() * maxttl;
|
|
if (next >= current && next < current + subnet_count) {
|
|
offset = next - current;
|
|
*ttl = (offset & ttlmask);
|
|
// upper bits are offset into subnet
|
|
int subnetoffset = (offset >> ttlmask_bits);
|
|
memcpy(in, (*iter).first(), sizeof(struct in6_addr));
|
|
//char output[INET6_ADDRSTRLEN];
|
|
//inet_ntop(AF_INET6, in, output, INET6_ADDRSTRLEN);
|
|
//cout << "Using first as base: " << output << endl;
|
|
|
|
high = (subnetoffset << (64-granularity));
|
|
(*in).s6_addr32[0] += htonl( (high & 0xFFFFFFFF00000000) >> 32);
|
|
(*in).s6_addr32[1] += htonl( (high & 0x00000000FFFFFFFF));
|
|
|
|
#if 0
|
|
iid = rndIID((uint32_t *)in);
|
|
(*in).s6_addr32[2] += htonl( (iid & 0xFFFFFFFF00000000) >> 32);
|
|
(*in).s6_addr32[3] += htonl( (iid & 0x00000000FFFFFFFF));
|
|
#else
|
|
(*in).s6_addr32[3] = htonl(1);
|
|
#endif
|
|
return 1;
|
|
}
|
|
current += subnet_count;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
uint16_t
|
|
RandomSubnetList::getHost(uint8_t *addr) {
|
|
uint16_t sum = addr[0] + addr[1] + addr[2] + addr[3] + 127;
|
|
return sum & 0xff;
|
|
}
|
|
|
|
uint64_t
|
|
RandomSubnetList::rndIID(uint32_t *addr) {
|
|
uint64_t sum = random();
|
|
sum = (sum<<32);
|
|
sum += random() ^ (addr[0] + addr[1]);
|
|
return sum;
|
|
}
|