]> git.ipfire.org Git - location/libloc.git/blame - src/libloc/private.h
network: Implement bit length function for IPv4
[location/libloc.git] / src / libloc / private.h
CommitLineData
46aded9a
MT
1/*
2 libloc - A library to determine the location of someone on the Internet
3
4 Copyright (C) 2017 IPFire Development Team <info@ipfire.org>
5
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.
10
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.
15*/
16
17#ifndef LIBLOC_PRIVATE_H
18#define LIBLOC_PRIVATE_H
19
1a3cb1b4
MT
20#ifdef LIBLOC_PRIVATE
21
2a30e4de 22#include <netinet/in.h>
46aded9a 23#include <stdbool.h>
726f9984 24#include <stdio.h>
46aded9a
MT
25#include <syslog.h>
26
c12a1385 27#include <libloc/libloc.h>
46aded9a
MT
28
29static inline void __attribute__((always_inline, format(printf, 2, 3)))
30loc_log_null(struct loc_ctx *ctx, const char *format, ...) {}
31
32#define loc_log_cond(ctx, prio, arg...) \
33 do { \
34 if (loc_get_log_priority(ctx) >= prio) \
35 loc_log(ctx, prio, __FILE__, __LINE__, __FUNCTION__, ## arg); \
36 } while (0)
37
38#ifdef ENABLE_DEBUG
39# define DEBUG(ctx, arg...) loc_log_cond(ctx, LOG_DEBUG, ## arg)
40#else
41# define DEBUG(ctx, arg...) loc_log_null(ctx, ## arg)
42#endif
43
44#define INFO(ctx, arg...) loc_log_cond(ctx, LOG_INFO, ## arg)
45#define ERROR(ctx, arg...) loc_log_cond(ctx, LOG_ERR, ## arg)
46
47#ifndef HAVE_SECURE_GETENV
48# ifdef HAVE___SECURE_GETENV
49# define secure_getenv __secure_getenv
50# else
d0cef0e8 51# define secure_getenv getenv
46aded9a
MT
52# endif
53#endif
54
55#define LOC_EXPORT __attribute__ ((visibility("default")))
56
57void loc_log(struct loc_ctx *ctx,
58 int priority, const char *file, int line, const char *fn,
59 const char *format, ...) __attribute__((format(printf, 6, 7)));
60
2a30e4de 61static inline int in6_addr_cmp(const struct in6_addr* a1, const struct in6_addr* a2) {
e14564aa
MT
62 for (unsigned int i = 0; i < 16; i++) {
63 if (a1->s6_addr[i] > a2->s6_addr[i])
64 return 1;
65
66 else if (a1->s6_addr[i] < a2->s6_addr[i])
67 return -1;
68 }
69
70 return 0;
2a30e4de
MT
71}
72
73static inline int in6_addr_get_bit(const struct in6_addr* address, unsigned int i) {
20e3a06f 74 return ((address->s6_addr[i / 8] >> (7 - (i % 8))) & 1);
2a30e4de
MT
75}
76
77static inline void in6_addr_set_bit(struct in6_addr* address, unsigned int i, unsigned int val) {
20e3a06f 78 address->s6_addr[i / 8] ^= (-val ^ address->s6_addr[i / 8]) & (1 << (7 - (i % 8)));
2a30e4de
MT
79}
80
30f0f0ed
MT
81static inline struct in6_addr loc_prefix_to_bitmask(const unsigned int prefix) {
82 struct in6_addr bitmask;
83
84 for (unsigned int i = 0; i < 16; i++)
85 bitmask.s6_addr[i] = 0;
86
87 for (int i = prefix, j = 0; i > 0; i -= 8, j++) {
88 if (i >= 8)
89 bitmask.s6_addr[j] = 0xff;
90 else
91 bitmask.s6_addr[j] = 0xff << (8 - i);
92 }
93
94 return bitmask;
95}
96
b074be0b 97static inline unsigned int __loc_address6_bit_length(const struct in6_addr* address) {
f69e0c8b
MT
98 unsigned int length = 128;
99
100 for (int octet = 0; octet <= 15; octet++) {
101 if (address->s6_addr[octet]) {
102 length -= __builtin_clz(address->s6_addr[octet]) - 24;
103 break;
104 } else
105 length -= 8;
106 }
107
108 return length;
109}
110
b074be0b
MT
111static inline unsigned int __loc_address4_bit_length(const struct in6_addr* address) {
112 unsigned int length = 32;
113
114 for (int octet = 12; octet <= 15; octet++) {
115 if (address->s6_addr[octet]) {
116 length -= __builtin_clz(address->s6_addr[octet]) - 24;
117 break;
118 } else
119 length -= 8;
120 }
121
122 return length;
123}
124
125static inline unsigned int loc_address_bit_length(const struct in6_addr* address) {
126 if (IN6_IS_ADDR_V4MAPPED(address))
127 return __loc_address4_bit_length(address);
128 else
129 return __loc_address6_bit_length(address);
130}
131
30f0f0ed
MT
132static inline struct in6_addr loc_address_and(
133 const struct in6_addr* address, const struct in6_addr* bitmask) {
134 struct in6_addr a;
135
136 // Perform bitwise AND
137 for (unsigned int i = 0; i < 4; i++)
138 a.s6_addr32[i] = address->s6_addr32[i] & bitmask->s6_addr32[i];
139
140 return a;
141}
142
143static inline struct in6_addr loc_address_or(
144 const struct in6_addr* address, const struct in6_addr* bitmask) {
145 struct in6_addr a;
146
147 // Perform bitwise OR
148 for (unsigned int i = 0; i < 4; i++)
149 a.s6_addr32[i] = address->s6_addr32[i] | ~bitmask->s6_addr32[i];
150
151 return a;
152}
153
d701dcfd
MT
154static inline struct in6_addr loc_address_sub(
155 const struct in6_addr* address1, const struct in6_addr* address2) {
156 struct in6_addr a;
157
158 int remainder = 0;
159
160 for (int octet = 15; octet >= 0; octet--) {
161 int x = address1->s6_addr[octet] - address2->s6_addr[octet] + remainder;
162
163 // Store remainder for the next iteration
164 remainder = (x >> 8);
165
166 a.s6_addr[octet] = x & 0xff;
167 }
168
169 return a;
170}
171
257626f5
MT
172static inline void hexdump(struct loc_ctx* ctx, const void* addr, size_t len) {
173 char buffer_hex[16 * 3 + 6];
174 char buffer_ascii[17];
175
176 unsigned int i = 0;
177 unsigned char* p = (unsigned char*)addr;
178
356cabc1
MT
179 DEBUG(ctx, "Dumping %zu byte(s)\n", len);
180
257626f5
MT
181 // Process every byte in the data
182 for (i = 0; i < len; i++) {
183 // Multiple of 16 means new line (with line offset)
184 if ((i % 16) == 0) {
185 // Just don't print ASCII for the zeroth line
186 if (i != 0)
187 DEBUG(ctx, " %s %s\n", buffer_hex, buffer_ascii);
188
189 // Output the offset.
190 sprintf(buffer_hex, "%04x ", i);
191 }
192
193 // Now the hex code for the specific character
194 sprintf(buffer_hex + 5 + ((i % 16) * 3), " %02x", p[i]);
195
196 // And store a printable ASCII character for later
197 if ((p[i] < 0x20) || (p[i] > 0x7e))
198 buffer_ascii[i % 16] = '.';
199 else
200 buffer_ascii[i % 16] = p[i];
201
202 // Terminate string
203 buffer_ascii[(i % 16) + 1] = '\0';
204 }
205
206 // Pad out last line if not exactly 16 characters
207 while ((i % 16) != 0) {
208 sprintf(buffer_hex + 5 + ((i % 16) * 3), " ");
209 i++;
210 }
211
212 // And print the final bit
213 DEBUG(ctx, " %s %s\n", buffer_hex, buffer_ascii);
214}
215
46aded9a 216#endif
1a3cb1b4 217#endif