mirror of
https://github.com/cmand/yarrp.git
synced 2024-05-11 05:55:06 +00:00
212 lines
5.1 KiB
C++
212 lines
5.1 KiB
C++
#include "yarrp.h"
|
|
#include "random_list.h"
|
|
|
|
IPList::IPList(uint8_t _maxttl, bool _rand, bool _entire) : seeded(false) {
|
|
perm = NULL;
|
|
permsize = 0;
|
|
maxttl = _maxttl;
|
|
ttlbits = intlog(maxttl);
|
|
ttlmask = 0xffffffff >> (32 - ttlbits);
|
|
ttlprefix = ttlmask ^ 0xff;
|
|
rand = _rand;
|
|
entire = _entire;
|
|
if (entire)
|
|
permsize = UINT32_MAX;
|
|
memset(key, 0, KEYLEN);
|
|
}
|
|
|
|
void IPList::setkey(int seed) {
|
|
debug(HIGH, ">> Seed: " << seed);
|
|
permseed(key, seed);
|
|
}
|
|
|
|
IPList4::~IPList4() {
|
|
targets.clear();
|
|
cperm_destroy(perm);
|
|
}
|
|
|
|
IPList6::~IPList6() {
|
|
targets.clear();
|
|
cperm_destroy(perm);
|
|
}
|
|
|
|
/* seed */
|
|
void IPList4::seed() {
|
|
PermMode mode = PERM_MODE_CYCLE;
|
|
if (not entire) {
|
|
assert(targets.size() > 0);
|
|
permsize = targets.size() * maxttl;
|
|
if (permsize < 1000000)
|
|
mode = PERM_MODE_PREFIX;
|
|
}
|
|
perm = cperm_create(permsize, mode, PERM_CIPHER_RC5, key, 16);
|
|
assert(perm);
|
|
seeded = true;
|
|
}
|
|
|
|
void IPList6::seed() {
|
|
PermMode mode = PERM_MODE_PREFIX;
|
|
assert(targets.size() > 0);
|
|
permsize = targets.size() * maxttl;
|
|
if (permsize > 5000000) {
|
|
mode = PERM_MODE_CYCLE;
|
|
std::cout << ">> Warning: reduced IPv6 performance with this many targets" << std::endl;
|
|
std::cout << ">> use fewer targets, or lower max TTL (-m)" << std::endl;
|
|
}
|
|
perm = cperm_create(permsize, mode, PERM_CIPHER_SPECK, key, 8);
|
|
assert(perm);
|
|
seeded = true;
|
|
}
|
|
|
|
/* Read list of input IPs */
|
|
void IPList::read(char *in) {
|
|
if (*in == '-') {
|
|
read(std::cin);
|
|
} else {
|
|
std::ifstream ifile(in);
|
|
if (ifile.good() == false)
|
|
fatal("Bad input file: %s", in);
|
|
read(ifile);
|
|
}
|
|
}
|
|
|
|
/* Read list of input IPs */
|
|
void IPList4::read(std::istream& inlist) {
|
|
std::string line;
|
|
struct in_addr addr;
|
|
while (getline(inlist, line)) {
|
|
if (!line.empty() && line[line.size() - 1] == '\r')
|
|
line.erase( std::remove(line.begin(), line.end(), '\r'), line.end() );
|
|
if (inet_aton(line.c_str(), &addr) != 1)
|
|
fatal("** Couldn't parse IPv4 address: %s", line.c_str());
|
|
targets.push_back(addr.s_addr);
|
|
}
|
|
debug(LOW, ">> IPv4 targets: " << targets.size());
|
|
}
|
|
|
|
/* Read list of input IPs */
|
|
void IPList6::read(std::istream& inlist) {
|
|
std::string line;
|
|
struct in6_addr addr;
|
|
while (getline(inlist, line)) {
|
|
if (!line.empty() && line[line.size() - 1] == '\r')
|
|
line.erase( std::remove(line.begin(), line.end(), '\r'), line.end() );
|
|
if (inet_pton(AF_INET6, line.c_str(), &addr) != 1)
|
|
fatal("** Couldn't parse IPv6 address: %s", line.c_str());
|
|
targets.push_back(addr);
|
|
}
|
|
debug(LOW, ">> IPv6 targets: " << targets.size());
|
|
}
|
|
|
|
uint32_t IPList4::next_address(struct in_addr *in, uint8_t * ttl) {
|
|
if (entire)
|
|
return next_address_entire(in, ttl);
|
|
else if (rand)
|
|
return next_address_rand(in, ttl);
|
|
else
|
|
return next_address_seq(in, ttl);
|
|
}
|
|
|
|
/* sequential next address */
|
|
uint32_t IPList4::next_address_seq(struct in_addr *in, uint8_t * ttl) {
|
|
static std::vector<uint32_t>::iterator iter = targets.begin();
|
|
static uint32_t last_addr = *iter;
|
|
static uint8_t last_ttl = 0;
|
|
|
|
if (last_ttl + 1 > maxttl) {
|
|
iter++;
|
|
if (iter == targets.end())
|
|
return 0;
|
|
last_ttl = 0;
|
|
last_addr = *(iter);
|
|
}
|
|
*ttl = last_ttl;
|
|
last_ttl+=1;
|
|
in->s_addr = last_addr;
|
|
return 1;
|
|
}
|
|
|
|
/* random next address */
|
|
uint32_t IPList4::next_address_rand(struct in_addr *in, uint8_t * ttl) {
|
|
static uint32_t next = 0;
|
|
|
|
if (not seeded)
|
|
seed();
|
|
|
|
if (PERM_END == cperm_next(perm, &next))
|
|
return 0;
|
|
|
|
in->s_addr = targets[next >> ttlbits];
|
|
if (ttlbits == 0)
|
|
*ttl = 0;
|
|
else
|
|
*ttl = (next & ttlmask);
|
|
return 1;
|
|
}
|
|
|
|
/* Internet-wide scanning mode */
|
|
uint32_t IPList4::next_address_entire(struct in_addr *in, uint8_t * ttl) {
|
|
static uint32_t next = 0;
|
|
static uint32_t host;
|
|
static char *p;
|
|
|
|
if (not seeded)
|
|
seed();
|
|
|
|
p = (char *) &next;
|
|
while (PERM_END != cperm_next(perm, &next)) {
|
|
*ttl = next >> 24; // use remaining 8 bits of perm as ttl
|
|
if ( (*ttl & ttlprefix) != 0x0) { // fast check: ttls in [0,31]
|
|
continue;
|
|
}
|
|
in->s_addr = next & 0x00FFFFFF; // pick out 24 bits of network
|
|
host = (p[0] + p[1] + p[2]) & 0xFF;
|
|
in->s_addr += (host << 24);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
uint32_t IPList6::next_address(struct in6_addr *in, uint8_t * ttl) {
|
|
if (rand)
|
|
return next_address_rand(in, ttl);
|
|
else
|
|
return next_address_seq(in, ttl);
|
|
}
|
|
|
|
/* sequential next address */
|
|
uint32_t IPList6::next_address_seq(struct in6_addr *in, uint8_t * ttl) {
|
|
static std::vector<struct in6_addr>::iterator iter = targets.begin();
|
|
static struct in6_addr last_addr = *iter;
|
|
static uint8_t last_ttl = 0;
|
|
int i;
|
|
|
|
if (last_ttl + 1 > maxttl) {
|
|
iter++;
|
|
if (iter == targets.end())
|
|
return 0;
|
|
last_ttl = 0;
|
|
last_addr = *(iter);
|
|
}
|
|
*ttl = last_ttl;
|
|
for(i = 0; i < 16; i++)
|
|
in->s6_addr[i] = last_addr.s6_addr[i];
|
|
last_ttl+=1;
|
|
return 1;
|
|
}
|
|
|
|
/* random next address */
|
|
uint32_t IPList6::next_address_rand(struct in6_addr *in, uint8_t * ttl) {
|
|
static uint32_t next = 0;
|
|
|
|
if (not seeded)
|
|
seed();
|
|
|
|
if (PERM_END == cperm_next(perm, &next))
|
|
return 0;
|
|
|
|
*in = targets[next >> ttlbits];
|
|
*ttl = (next & ttlmask);
|
|
return 1;
|
|
}
|