1
0
mirror of https://github.com/cmand/yarrp.git synced 2024-05-11 05:55:06 +00:00
Files
2018-12-05 10:50:35 -08:00

105 lines
3.3 KiB
C++

#include "yarrp.h"
#include "subnet.h"
static uint32_t NETMASKS[] = {
0x00000000,
0x80000000, 0xc0000000, 0xe0000000, 0xf0000000,
0xf8000000, 0xfc000000, 0xfe000000, 0xff000000,
0xff800000, 0xffc00000, 0xffe00000, 0xfff00000,
0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000,
0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000,
0xfffff800, 0xfffffc00, 0xfffffe00, 0xffffff00,
0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0,
0xfffffff8, 0xfffffffc, 0xfffffffe, 0xffffffff
};
Subnet::Subnet(string s) {
uint32_t addr;
uint8_t mask;
char *p = strdup(s.c_str());
if (2 == sscanf(s.c_str(), "%[0-9.]/%hhu", p, &mask)) {
addr = ntohl(inet_addr(p));
if (mask > 32) {
start = end = offset = 0;
fatal("Bad IPv4 subnet mask: %s", s.c_str());
}
start = addr & NETMASKS[mask];
smask = mask;
offset = 0;
end = start + (1 << (32 - mask));
} else {
fatal("Error parsing IPv4 subnet: %s", s.c_str());
}
free(p);
}
Subnet6::Subnet6(string s) {
uint8_t m;
char *p = strdup(s.c_str());
if (2 == sscanf(s.c_str(), "%[a-fA-F0-9:]/%hhu", p, &m)) {
//cout << "Got IPv6 prefix: " << p << " mask: " << int (m) << endl;
if (inet_pton(AF_INET6, p, &start) != 1) {
fatal("Error parsing IPv6 address: %s", p);
}
smask = m;
/* we divide everything into /48s */
if (smask > 48) {
fatal("IPv6 Prefix must be /48 or smaller!");
}
cnt = 1 << (48-m);
/* four 32-bits words in ipv6 address; which one is subnet boundary */
uint8_t boundary_word = m / 32;
uint8_t boundary_mask = m % 32;
//char output[INET6_ADDRSTRLEN];
//inet_ntop(AF_INET6, &start, output, INET6_ADDRSTRLEN);
//cout << "Start: " << output << endl;
//cout << "boundary word:" << (int) boundary_word << endl;
//cout << "boundary mask:" << (int) boundary_mask << endl;
for (int i=boundary_word+1; i<4; i++ ) {
start.s6_addr32[i] = 0;
}
//printf("WORD: %08x\n", ntohl(start.s6_addr32[boundary_word]));
//printf("MASK: %08x\n", NETMASKS[boundary_mask]);
start.s6_addr32[boundary_word] = htonl( ntohl(start.s6_addr32[boundary_word]) & NETMASKS[boundary_mask] );
//printf("WORD: %08x\n", ntohl(start.s6_addr32[boundary_word]));
//inet_ntop(AF_INET6, &start, output, INET6_ADDRSTRLEN);
//cout << "Start: " << output << endl;
memcpy(&end, &start, sizeof(struct in6_addr));
for (int i=boundary_word+1; i<4; i++ ) {
end.s6_addr32[i] += NETMASKS[32];
}
end.s6_addr32[boundary_word] += htonl( (1 << (32-boundary_mask))-1);
//inet_ntop(AF_INET6, &end, output, INET6_ADDRSTRLEN);
//cout << "End: " << output << endl;
} else {
fatal("Error parsing IPv6 subnet: %s", s.c_str());
}
free(p);
}
Subnet::~Subnet() {
}
Subnet6::~Subnet6() {
}
uint32_t Subnet::first() {
return start;
}
struct in6_addr *Subnet6::first() {
return &start;
}
uint32_t Subnet::last() {
return end - 1;
}
/* we iterate through /24's. so, count is number of /24s */
uint32_t Subnet::count() {
return (end - start) >> 8;
}