forked from robertdavidgraham/masscan
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmassip-addr.h
182 lines (159 loc) · 5.33 KB
/
massip-addr.h
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
/*
Simple module for handling addresses (IPv6, IPv4, MAC).
Also implements a 128-bit type for dealing with addresses.
This is the module that almost all the other code depends
upon, because everything else deals with the IP address
types defined here.
*/
#ifndef MASSIP_ADDR_H
#define MASSIP_ADDR_H
#include <stdint.h>
#include <stddef.h>
#if defined(_MSC_VER) && !defined(inline)
#define inline __inline
#endif
#if defined(_MSC_VER)
#pragma warning(disable: 4201)
#endif
/**
* An IPv6 address is represented as two 64-bit integers instead of a single
* 128-bit integer. This is because currently (year 2020) most compilers
* do not support the `uint128_t` type, but all relevant ones do support
* the `uint64_t` type.
*/
struct ipv6address {uint64_t hi; uint64_t lo;};
typedef struct ipv6address ipv6address;
typedef struct ipv6address ipv6address_t;
/**
* IPv4 addresses are represented simply with an integer.
*/
typedef unsigned ipv4address;
typedef ipv4address ipv4address_t;
/**
* MAC address (layer 2). Since we have canonical types for IPv4/IPv6
* addresses, we may as well have a canonical type for MAC addresses,
* too.
*/
struct macaddress_t {unsigned char addr[6];};
typedef struct macaddress_t macaddress_t;
/**
* In many cases we need to do arithmetic on IPv6 addresses, treating
* them as a large 128-bit integer. Thus, we declare our own 128-bit
* integer type (and some accompanying math functions). But it's
* still just the same as a 128-bit integer.
*/
typedef ipv6address massint128_t;
/**
* Most of the code in this project is agnostic to the version of IP
* addresses (IPv4 or IPv6). Therefore, we represent them as a union
* distinguished by a version number. The `version` is an integer
* with a value of either 4 or 6.
*/
struct ipaddress {
union {
unsigned ipv4;
ipv6address ipv6;
};
unsigned char version;
};
typedef struct ipaddress ipaddress;
/** @return true if the IPv6 address is zero [::] */
static inline int ipv6address_is_zero(ipv6address_t a) {
return a.hi == 0 && a.lo == 0;
}
#define massint128_is_zero ipv6address_is_zero
/** The IPv6 address [FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF]
* is invalid */
static inline int ipv6address_is_invalid(ipv6address_t a) {
return a.hi == ~0ULL && a.lo == ~0ULL;
}
/** Compare two IPv6 addresses */
static inline int ipv6address_is_equal(ipv6address_t a, ipv6address_t b) {
return a.hi == b.hi && a.lo == b.lo;
}
/** Compare two IPv6 addresses, to see which one comes frist. This is used
* in sorting the addresses
* @return true if a < b, false otherwise */
static inline int ipv6address_is_lessthan(ipv6address_t a, ipv6address_t b) {
return (a.hi == b.hi)?(a.lo < b.lo):(a.hi < b.hi);
}
/**
* Mask the lower bits of each address and test if the upper bits are equal
*/
int ipv6address_is_equal_prefixed(ipv6address_t lhs, ipv6address_t rhs, unsigned prefix);
/**
* Given a typical EXTERNAL representation of an IPv6 address, which is
* an array of 16 bytes, convert to the canonical INTERNAL address.
*/
static inline ipv6address ipv6address_from_bytes(const unsigned char *buf) {
ipv6address addr;
addr.hi = (uint64_t)buf[ 0] << 56
| (uint64_t)buf[ 1] << 48
| (uint64_t)buf[ 2] << 40
| (uint64_t)buf[ 3] << 32
| (uint64_t)buf[ 4] << 24
| (uint64_t)buf[ 5] << 16
| (uint64_t)buf[ 6] << 8
| (uint64_t)buf[ 7] << 0;
addr.lo = (uint64_t)buf[ 8] << 56
| (uint64_t)buf[ 9] << 48
| (uint64_t)buf[10] << 40
| (uint64_t)buf[11] << 32
| (uint64_t)buf[12] << 24
| (uint64_t)buf[13] << 16
| (uint64_t)buf[14] << 8
| (uint64_t)buf[15] << 0;
return addr;
}
/**
* Given a typical EXTERNAL representation of an Ethernet MAC address,
* which is an array of 6 bytes, convert to the canonical INTERNAL address.
*/
static inline macaddress_t macaddress_from_bytes(const void *vbuf)
{
const unsigned char *buf = (const unsigned char *)vbuf;
macaddress_t result;
result.addr[0] = buf[0];
result.addr[1] = buf[1];
result.addr[2] = buf[2];
result.addr[3] = buf[3];
result.addr[4] = buf[4];
result.addr[5] = buf[5];
return result;
}
/** Test if the Ethernet MAC address is all zeroes */
static inline int macaddress_is_zero(macaddress_t mac)
{
return mac.addr[0] == 0
&& mac.addr[1] == 0
&& mac.addr[2] == 0
&& mac.addr[3] == 0
&& mac.addr[4] == 0
&& mac.addr[5] == 0;
}
/** Compare two Ethernet MAC addresses to see if they are equal */
static inline int macaddress_is_equal(macaddress_t lhs, macaddress_t rhs)
{
return lhs.addr[0] == rhs.addr[0]
&& lhs.addr[1] == rhs.addr[1]
&& lhs.addr[2] == rhs.addr[2]
&& lhs.addr[3] == rhs.addr[3]
&& lhs.addr[4] == rhs.addr[4]
&& lhs.addr[5] == rhs.addr[5];
}
/**
* Return a buffer with the formatted address
*/
typedef struct ipaddress_formatted {
char string[48];
} ipaddress_formatted_t;
struct ipaddress_formatted ipv6address_fmt(ipv6address a);
struct ipaddress_formatted ipv4address_fmt(ipv4address a);
struct ipaddress_formatted ipaddress_fmt(ipaddress a);
struct ipaddress_formatted macaddress_fmt(macaddress_t a);
unsigned massint128_bitcount(massint128_t num);
/**
* @return 0 on success, 1 on failure
*/
int ipv6address_selftest(void);
#endif