]>
git.ipfire.org Git - location/libloc.git/blob - src/libloc/address.h
ea4a87c1e127539ae99a6baab2c3527941991920
2 libloc - A library to determine the location of someone on the Internet
4 Copyright (C) 2022 IPFire Development Team <info@ipfire.org>
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
17 #ifndef LIBLOC_ADDRESS_H
18 #define LIBLOC_ADDRESS_H
23 #include <netinet/in.h>
26 All of these functions are private and for internal use only
29 static inline int loc_address_family(const struct in6_addr
* address
) {
30 if (IN6_IS_ADDR_V4MAPPED(address
))
36 static inline int in6_addr_cmp(const struct in6_addr
* a1
, const struct in6_addr
* a2
) {
37 for (unsigned int i
= 0; i
< 16; i
++) {
38 if (a1
->s6_addr
[i
] > a2
->s6_addr
[i
])
41 else if (a1
->s6_addr
[i
] < a2
->s6_addr
[i
])
48 static inline int in6_addr_get_bit(const struct in6_addr
* address
, unsigned int i
) {
49 return ((address
->s6_addr
[i
/ 8] >> (7 - (i
% 8))) & 1);
52 static inline void in6_addr_set_bit(struct in6_addr
* address
, unsigned int i
, unsigned int val
) {
53 address
->s6_addr
[i
/ 8] ^= (-val
^ address
->s6_addr
[i
/ 8]) & (1 << (7 - (i
% 8)));
56 static inline struct in6_addr
loc_prefix_to_bitmask(const unsigned int prefix
) {
57 struct in6_addr bitmask
;
59 for (unsigned int i
= 0; i
< 16; i
++)
60 bitmask
.s6_addr
[i
] = 0;
62 for (int i
= prefix
, j
= 0; i
> 0; i
-= 8, j
++) {
64 bitmask
.s6_addr
[j
] = 0xff;
66 bitmask
.s6_addr
[j
] = 0xff << (8 - i
);
72 static inline unsigned int __loc_address6_bit_length(const struct in6_addr
* address
) {
73 unsigned int length
= 128;
75 for (int octet
= 0; octet
<= 15; octet
++) {
76 if (address
->s6_addr
[octet
]) {
77 length
-= __builtin_clz(address
->s6_addr
[octet
]) - 24;
86 static inline unsigned int __loc_address4_bit_length(const struct in6_addr
* address
) {
87 unsigned int length
= 32;
89 for (int octet
= 12; octet
<= 15; octet
++) {
90 if (address
->s6_addr
[octet
]) {
91 length
-= __builtin_clz(address
->s6_addr
[octet
]) - 24;
100 static inline unsigned int loc_address_bit_length(const struct in6_addr
* address
) {
101 if (IN6_IS_ADDR_V4MAPPED(address
))
102 return __loc_address4_bit_length(address
);
104 return __loc_address6_bit_length(address
);
107 static inline int loc_address_reset(struct in6_addr
* address
, int family
) {
110 address
->s6_addr32
[0] = 0x0000;
111 address
->s6_addr32
[1] = 0x0000;
112 address
->s6_addr32
[2] = 0x0000;
113 address
->s6_addr32
[3] = 0x0000;
117 address
->s6_addr32
[0] = 0x0000;
118 address
->s6_addr32
[1] = 0x0000;
119 address
->s6_addr32
[2] = htonl(0xffff);
120 address
->s6_addr32
[3] = 0x0000;
127 static inline int loc_address_reset_last(struct in6_addr
* address
, int family
) {
130 address
->s6_addr32
[0] = 0xffff;
131 address
->s6_addr32
[1] = 0xffff;
132 address
->s6_addr32
[2] = 0xffff;
133 address
->s6_addr32
[3] = 0xffff;
137 address
->s6_addr32
[0] = 0x0000;
138 address
->s6_addr32
[1] = 0x0000;
139 address
->s6_addr32
[2] = htonl(0xffff);
140 address
->s6_addr32
[3] = 0xffff;
147 static inline struct in6_addr
loc_address_and(
148 const struct in6_addr
* address
, const struct in6_addr
* bitmask
) {
151 // Perform bitwise AND
152 for (unsigned int i
= 0; i
< 4; i
++)
153 a
.s6_addr32
[i
] = address
->s6_addr32
[i
] & bitmask
->s6_addr32
[i
];
158 static inline struct in6_addr
loc_address_or(
159 const struct in6_addr
* address
, const struct in6_addr
* bitmask
) {
162 // Perform bitwise OR
163 for (unsigned int i
= 0; i
< 4; i
++)
164 a
.s6_addr32
[i
] = address
->s6_addr32
[i
] | ~bitmask
->s6_addr32
[i
];
169 static inline int __loc_address6_sub(struct in6_addr
* result
,
170 const struct in6_addr
* address1
, const struct in6_addr
* address2
) {
173 for (int octet
= 15; octet
>= 0; octet
--) {
174 int x
= address1
->s6_addr
[octet
] - address2
->s6_addr
[octet
] + remainder
;
176 // Store remainder for the next iteration
177 remainder
= (x
>> 8);
179 result
->s6_addr
[octet
] = x
& 0xff;
185 static inline int __loc_address4_sub(struct in6_addr
* result
,
186 const struct in6_addr
* address1
, const struct in6_addr
* address2
) {
189 for (int octet
= 15; octet
>= 12; octet
--) {
190 int x
= address1
->s6_addr
[octet
] - address2
->s6_addr
[octet
] + remainder
;
192 // Store remainder for the next iteration
193 remainder
= (x
>> 8);
195 result
->s6_addr
[octet
] = x
& 0xff;
201 static inline int loc_address_sub(struct in6_addr
* result
,
202 const struct in6_addr
* address1
, const struct in6_addr
* address2
) {
203 // XXX should be using loc_address_family
204 int family1
= IN6_IS_ADDR_V4MAPPED(address1
) ? AF_INET
: AF_INET6
;
205 int family2
= IN6_IS_ADDR_V4MAPPED(address2
) ? AF_INET
: AF_INET6
;
207 // Address family must match
208 if (family1
!= family2
) {
214 int r
= loc_address_reset(result
, family1
);
220 return __loc_address6_sub(result
, address1
, address2
);
223 return __loc_address4_sub(result
, address1
, address2
);
231 static inline struct in6_addr
address_increment(const struct in6_addr
* address
) {
232 struct in6_addr a
= *address
;
234 for (int octet
= 15; octet
>= 0; octet
--) {
235 if (a
.s6_addr
[octet
] < 255) {
239 a
.s6_addr
[octet
] = 0;
246 static inline struct in6_addr
address_decrement(const struct in6_addr
* address
) {
247 struct in6_addr a
= *address
;
249 for (int octet
= 15; octet
>= 0; octet
--) {
250 if (a
.s6_addr
[octet
] > 0) {
259 static inline int loc_address_family_bit_length(const int family
) {
272 static inline int loc_address_all_zeroes(const struct in6_addr
* address
) {
273 struct in6_addr all_zeroes
= IN6ADDR_ANY_INIT
;
275 const int family
= loc_address_family(address
);
277 int r
= loc_address_reset(&all_zeroes
, family
);
281 if (in6_addr_cmp(address
, &all_zeroes
) == 0)
287 static inline int loc_address_count_trailing_zero_bits(const struct in6_addr
* address
) {
290 for (int octet
= 15; octet
>= 0; octet
--) {
291 if (address
->s6_addr
[octet
]) {
292 zeroes
+= __builtin_ctz(address
->s6_addr
[octet
]);
301 #endif /* LIBLOC_PRIVATE */
303 #endif /* LIBLOC_ADDRESS_H */