-
Notifications
You must be signed in to change notification settings - Fork 3
/
in6calc.c
64 lines (54 loc) · 1.8 KB
/
in6calc.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
/*
* IPv6 Address Calculations
*
* @author Damien Bezborodov
* @link https://github.com/emden-norfolk/cidrl
*/
#include <arpa/inet.h>
/**
* Calculate a 128-bit mask given a network prefix.
*/
void in6_addr_mask(struct in6_addr *mask, uint8_t bits)
{
for (uint8_t i = 0; i < sizeof(mask->s6_addr); i++) {
mask->s6_addr[i] = bits ? ~0 << (8 - (bits > 8 ? 8 : bits)) : 0;
if (bits < 8) bits = 0;
else bits -= 8;
}
}
/**
* Calculate the first address in a network given a mask.
*/
void in6_addr_network(struct in6_addr *network, struct in6_addr *addr, struct in6_addr *mask)
{
for (uint8_t i = 0; i < sizeof(network->s6_addr); i++) {
network->s6_addr[i] = addr->s6_addr[i] & mask->s6_addr[i];
}
}
/**
* Calculate the last address in a network given a mask.
*/
void in6_addr_end(struct in6_addr *end, struct in6_addr *addr, struct in6_addr *mask)
{
for (uint8_t i = 0; i < sizeof(end->s6_addr); i++) {
end->s6_addr[i] = (addr->s6_addr[i] & mask->s6_addr[i]) | ~mask->s6_addr[i];
}
}
/**
* Increment an address by two to the power of n, where n is the exponent.
*
* To increment by 1, set n = 0. Remember that two to the power of zero is one.
*/
void in6_addr_incr_pow2(struct in6_addr *addr, uint8_t n)
{
uint8_t i, addend;
uint16_t sum; // 16-bit sum of two 8-bit integers.
i = (127 - n) / 8; // The byte where begin addition.
addend = 1 << (7 - ((127 - n) % 8)); // Scale the addend to i with the remainder.
while (addend) {
sum = addr->s6_addr[i] + addend; // Perform addition with the addend.
addr->s6_addr[i] = sum; // Save the sum to the current byte.
addend = sum >> 8; // Carry overflow to next significant byte.
if (!i--) break; // Go to next significant byte (and check if out of range.)
}
}