]>
git.ipfire.org Git - location/libloc.git/blob - src/libloc/private.h
2 libloc - A library to determine the location of someone on the Internet
4 Copyright (C) 2017 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_PRIVATE_H
18 #define LIBLOC_PRIVATE_H
23 #include <netinet/in.h>
28 #include <libloc/libloc.h>
30 static inline void __attribute__((always_inline
, format(printf
, 2, 3)))
31 loc_log_null(struct loc_ctx
*ctx
, const char *format
, ...) {}
33 #define loc_log_cond(ctx, prio, arg...) \
35 if (loc_get_log_priority(ctx) >= prio) \
36 loc_log(ctx, prio, __FILE__, __LINE__, __FUNCTION__, ## arg); \
40 # define DEBUG(ctx, arg...) loc_log_cond(ctx, LOG_DEBUG, ## arg)
42 # define DEBUG(ctx, arg...) loc_log_null(ctx, ## arg)
45 #define INFO(ctx, arg...) loc_log_cond(ctx, LOG_INFO, ## arg)
46 #define ERROR(ctx, arg...) loc_log_cond(ctx, LOG_ERR, ## arg)
48 #ifndef HAVE_SECURE_GETENV
49 # ifdef HAVE___SECURE_GETENV
50 # define secure_getenv __secure_getenv
52 # define secure_getenv getenv
56 #define LOC_EXPORT __attribute__ ((visibility("default")))
58 void loc_log(struct loc_ctx
*ctx
,
59 int priority
, const char *file
, int line
, const char *fn
,
60 const char *format
, ...) __attribute__((format(printf
, 6, 7)));
62 static inline int in6_addr_cmp(const struct in6_addr
* a1
, const struct in6_addr
* a2
) {
63 for (unsigned int i
= 0; i
< 16; i
++) {
64 if (a1
->s6_addr
[i
] > a2
->s6_addr
[i
])
67 else if (a1
->s6_addr
[i
] < a2
->s6_addr
[i
])
74 static inline int in6_addr_get_bit(const struct in6_addr
* address
, unsigned int i
) {
75 return ((address
->s6_addr
[i
/ 8] >> (7 - (i
% 8))) & 1);
78 static inline void in6_addr_set_bit(struct in6_addr
* address
, unsigned int i
, unsigned int val
) {
79 address
->s6_addr
[i
/ 8] ^= (-val
^ address
->s6_addr
[i
/ 8]) & (1 << (7 - (i
% 8)));
82 static inline struct in6_addr
loc_prefix_to_bitmask(const unsigned int prefix
) {
83 struct in6_addr bitmask
;
85 for (unsigned int i
= 0; i
< 16; i
++)
86 bitmask
.s6_addr
[i
] = 0;
88 for (int i
= prefix
, j
= 0; i
> 0; i
-= 8, j
++) {
90 bitmask
.s6_addr
[j
] = 0xff;
92 bitmask
.s6_addr
[j
] = 0xff << (8 - i
);
98 static inline unsigned int __loc_address6_bit_length(const struct in6_addr
* address
) {
99 unsigned int length
= 128;
101 for (int octet
= 0; octet
<= 15; octet
++) {
102 if (address
->s6_addr
[octet
]) {
103 length
-= __builtin_clz(address
->s6_addr
[octet
]) - 24;
112 static inline unsigned int __loc_address4_bit_length(const struct in6_addr
* address
) {
113 unsigned int length
= 32;
115 for (int octet
= 12; octet
<= 15; octet
++) {
116 if (address
->s6_addr
[octet
]) {
117 length
-= __builtin_clz(address
->s6_addr
[octet
]) - 24;
126 static inline unsigned int loc_address_bit_length(const struct in6_addr
* address
) {
127 if (IN6_IS_ADDR_V4MAPPED(address
))
128 return __loc_address4_bit_length(address
);
130 return __loc_address6_bit_length(address
);
133 static inline int loc_address_reset(struct in6_addr
* address
, int family
) {
136 address
->s6_addr32
[0] = 0x0000;
137 address
->s6_addr32
[1] = 0x0000;
138 address
->s6_addr32
[2] = 0x0000;
139 address
->s6_addr32
[3] = 0x0000;
143 address
->s6_addr32
[0] = 0x0000;
144 address
->s6_addr32
[1] = 0x0000;
145 address
->s6_addr32
[2] = htonl(0xffff);
146 address
->s6_addr32
[3] = 0x0000;
153 static inline int loc_address_reset_last(struct in6_addr
* address
, int family
) {
156 address
->s6_addr32
[0] = 0xffff;
157 address
->s6_addr32
[1] = 0xffff;
158 address
->s6_addr32
[2] = 0xffff;
159 address
->s6_addr32
[3] = 0xffff;
163 address
->s6_addr32
[0] = 0x0000;
164 address
->s6_addr32
[1] = 0x0000;
165 address
->s6_addr32
[2] = htonl(0xffff);
166 address
->s6_addr32
[3] = 0xffff;
173 static inline struct in6_addr
loc_address_and(
174 const struct in6_addr
* address
, const struct in6_addr
* bitmask
) {
177 // Perform bitwise AND
178 for (unsigned int i
= 0; i
< 4; i
++)
179 a
.s6_addr32
[i
] = address
->s6_addr32
[i
] & bitmask
->s6_addr32
[i
];
184 static inline struct in6_addr
loc_address_or(
185 const struct in6_addr
* address
, const struct in6_addr
* bitmask
) {
188 // Perform bitwise OR
189 for (unsigned int i
= 0; i
< 4; i
++)
190 a
.s6_addr32
[i
] = address
->s6_addr32
[i
] | ~bitmask
->s6_addr32
[i
];
195 static inline int __loc_address6_sub(struct in6_addr
* result
,
196 const struct in6_addr
* address1
, const struct in6_addr
* address2
) {
199 for (int octet
= 15; octet
>= 0; octet
--) {
200 int x
= address1
->s6_addr
[octet
] - address2
->s6_addr
[octet
] + remainder
;
202 // Store remainder for the next iteration
203 remainder
= (x
>> 8);
205 result
->s6_addr
[octet
] = x
& 0xff;
211 static inline int __loc_address4_sub(struct in6_addr
* result
,
212 const struct in6_addr
* address1
, const struct in6_addr
* address2
) {
215 for (int octet
= 15; octet
>= 12; octet
--) {
216 int x
= address1
->s6_addr
[octet
] - address2
->s6_addr
[octet
] + remainder
;
218 // Store remainder for the next iteration
219 remainder
= (x
>> 8);
221 result
->s6_addr
[octet
] = x
& 0xff;
227 static inline int loc_address_sub(struct in6_addr
* result
,
228 const struct in6_addr
* address1
, const struct in6_addr
* address2
) {
229 // XXX should be using loc_address_family
230 int family1
= IN6_IS_ADDR_V4MAPPED(address1
) ? AF_INET
: AF_INET6
;
231 int family2
= IN6_IS_ADDR_V4MAPPED(address2
) ? AF_INET
: AF_INET6
;
233 // Address family must match
234 if (family1
!= family2
) {
240 int r
= loc_address_reset(result
, family1
);
246 return __loc_address6_sub(result
, address1
, address2
);
249 return __loc_address4_sub(result
, address1
, address2
);
257 static inline void hexdump(struct loc_ctx
* ctx
, const void* addr
, size_t len
) {
258 char buffer_hex
[16 * 3 + 6];
259 char buffer_ascii
[17];
262 unsigned char* p
= (unsigned char*)addr
;
264 DEBUG(ctx
, "Dumping %zu byte(s)\n", len
);
266 // Process every byte in the data
267 for (i
= 0; i
< len
; i
++) {
268 // Multiple of 16 means new line (with line offset)
270 // Just don't print ASCII for the zeroth line
272 DEBUG(ctx
, " %s %s\n", buffer_hex
, buffer_ascii
);
274 // Output the offset.
275 sprintf(buffer_hex
, "%04x ", i
);
278 // Now the hex code for the specific character
279 sprintf(buffer_hex
+ 5 + ((i
% 16) * 3), " %02x", p
[i
]);
281 // And store a printable ASCII character for later
282 if ((p
[i
] < 0x20) || (p
[i
] > 0x7e))
283 buffer_ascii
[i
% 16] = '.';
285 buffer_ascii
[i
% 16] = p
[i
];
288 buffer_ascii
[(i
% 16) + 1] = '\0';
291 // Pad out last line if not exactly 16 characters
292 while ((i
% 16) != 0) {
293 sprintf(buffer_hex
+ 5 + ((i
% 16) * 3), " ");
297 // And print the final bit
298 DEBUG(ctx
, " %s %s\n", buffer_hex
, buffer_ascii
);