]>
Commit | Line | Data |
---|---|---|
1ea740e9 SS |
1 | #define PERL_NO_GET_CONTEXT |
2 | #include "EXTERN.h" | |
3 | #include "perl.h" | |
4 | #include "XSUB.h" | |
5 | ||
6 | #include <stdio.h> | |
7 | #include <string.h> | |
8 | ||
c12a1385 MT |
9 | #include <libloc/libloc.h> |
10 | #include <libloc/database.h> | |
11 | #include <libloc/network.h> | |
12 | #include <libloc/country.h> | |
1ea740e9 SS |
13 | |
14 | MODULE = Location PACKAGE = Location | |
15 | ||
16 | struct loc_database * | |
3bbf013a | 17 | init(file) |
e5a1a0bd | 18 | char* file; |
1ea740e9 SS |
19 | |
20 | CODE: | |
da1039da | 21 | struct loc_ctx* ctx = NULL; |
1ea740e9 | 22 | |
74ad091d | 23 | // Initialise location context |
da1039da | 24 | int err = loc_new(&ctx); |
1ea740e9 | 25 | if (err < 0) |
5242283a | 26 | croak("Could not initialize libloc context: %d\n", err); |
1ea740e9 | 27 | |
74ad091d | 28 | // Open the database file for reading |
1ea740e9 SS |
29 | FILE* f = fopen(file, "r"); |
30 | if (!f) { | |
c820094d MT |
31 | loc_unref(ctx); |
32 | ||
5242283a MT |
33 | croak("Could not open file for reading: %s: %s\n", |
34 | file, strerror(errno)); | |
1ea740e9 SS |
35 | } |
36 | ||
74ad091d | 37 | // Parse the database |
c820094d | 38 | struct loc_database* db = NULL; |
1ea740e9 | 39 | err = loc_database_new(ctx, &db, f); |
46d6c767 MT |
40 | |
41 | // We can close the database file straight away | |
42 | // because loc_database_new creates a copy of the file descriptor | |
43 | fclose(f); | |
44 | ||
1ea740e9 | 45 | if (err) { |
c820094d MT |
46 | loc_unref(ctx); |
47 | ||
5242283a | 48 | croak("Could not read database: %s\n", file); |
1ea740e9 SS |
49 | } |
50 | ||
3bbf013a MT |
51 | // Cleanup |
52 | loc_unref(ctx); | |
53 | ||
54 | RETVAL = db; | |
55 | OUTPUT: | |
56 | RETVAL | |
57 | ||
58 | # | |
59 | # Database functions | |
60 | # | |
61 | bool | |
62 | verify(db, keyfile) | |
63 | struct loc_database* db; | |
64 | char* keyfile; | |
65 | ||
66 | CODE: | |
2061ff77 | 67 | // Try to open the keyfile |
3bbf013a | 68 | FILE* f = fopen(keyfile, "r"); |
2061ff77 | 69 | if (!f) { |
2061ff77 SS |
70 | croak("Could not open keyfile %s: %s\n", |
71 | keyfile, strerror(errno)); | |
72 | } | |
73 | ||
74 | // Verify the database | |
75 | int status = loc_database_verify(db, f); | |
76 | if (status) { | |
3bbf013a | 77 | RETVAL = false; |
2061ff77 SS |
78 | fclose(f); |
79 | ||
80 | croak("Could not verify the database signature\n"); | |
81 | } | |
82 | ||
3bbf013a MT |
83 | // Database was validated successfully |
84 | RETVAL = true; | |
85 | ||
2061ff77 SS |
86 | // Close the keyfile |
87 | fclose(f); | |
1ea740e9 SS |
88 | OUTPUT: |
89 | RETVAL | |
90 | ||
777959b2 MT |
91 | const char* |
92 | get_vendor(db) | |
93 | struct loc_database* db; | |
94 | ||
95 | CODE: | |
96 | // Get vendor | |
97 | RETVAL = loc_database_get_vendor(db); | |
98 | OUTPUT: | |
99 | RETVAL | |
100 | ||
973c5f03 SS |
101 | const char* |
102 | get_description(db) | |
103 | struct loc_database* db; | |
104 | ||
105 | CODE: | |
106 | // Get database description | |
107 | RETVAL = loc_database_get_description(db); | |
108 | OUTPUT: | |
109 | RETVAL | |
110 | ||
733bd087 SS |
111 | const char* |
112 | get_license(db) | |
113 | struct loc_database* db; | |
114 | ||
115 | CODE: | |
116 | // Get database license | |
117 | RETVAL = loc_database_get_license(db); | |
118 | OUTPUT: | |
119 | RETVAL | |
120 | ||
c1590ddd SS |
121 | void |
122 | database_countries(db) | |
123 | struct loc_database* db; | |
124 | ||
125 | PPCODE: | |
126 | // Create Database enumerator | |
127 | struct loc_database_enumerator* enumerator; | |
681ff05c | 128 | int err = loc_database_enumerator_new(&enumerator, db, LOC_DB_ENUMERATE_COUNTRIES, 0); |
c1590ddd SS |
129 | |
130 | if (err) { | |
131 | croak("Could not create a database enumerator\n"); | |
132 | } | |
133 | ||
134 | // Init and enumerate first country. | |
135 | struct loc_country* country; | |
136 | err = loc_database_enumerator_next_country(enumerator, &country); | |
137 | if (err) { | |
138 | croak("Could not enumerate next country\n"); | |
139 | } | |
140 | ||
141 | while (country) { | |
142 | // Extract the country code. | |
143 | const char* ccode = loc_country_get_code(country); | |
144 | ||
145 | // Push country code. | |
146 | XPUSHs(sv_2mortal(newSVpv(ccode, 2))); | |
147 | ||
148 | // Unref country pointer. | |
149 | loc_country_unref(country); | |
150 | ||
151 | // Enumerate next item. | |
152 | err = loc_database_enumerator_next_country(enumerator, &country); | |
153 | if (err) { | |
154 | croak("Could not enumerate next country\n"); | |
155 | } | |
156 | } | |
157 | ||
158 | loc_database_enumerator_unref(enumerator); | |
159 | ||
46fbc975 SS |
160 | # |
161 | # Lookup functions | |
162 | # | |
6aa97cac | 163 | SV* |
70f45781 | 164 | lookup_country_code(db, address) |
e5a1a0bd MT |
165 | struct loc_database* db; |
166 | char* address; | |
1ea740e9 SS |
167 | |
168 | CODE: | |
6aa97cac SS |
169 | RETVAL = &PL_sv_undef; |
170 | ||
74ad091d | 171 | // Lookup network |
1ea740e9 | 172 | struct loc_network *network; |
d3daf87c | 173 | int err = loc_database_lookup_from_string(db, address, &network); |
6aa97cac SS |
174 | if (!err) { |
175 | // Extract the country code | |
176 | const char* country_code = loc_network_get_country_code(network); | |
177 | RETVAL = newSVpv(country_code, strlen(country_code)); | |
1ea740e9 | 178 | |
6aa97cac | 179 | loc_network_unref(network); |
1ea740e9 | 180 | } |
1ea740e9 SS |
181 | OUTPUT: |
182 | RETVAL | |
183 | ||
c8e6ee4e SS |
184 | bool |
185 | lookup_network_has_flag(db, address, flag) | |
186 | struct loc_database* db; | |
187 | char* address; | |
188 | char* flag; | |
189 | ||
190 | CODE: | |
191 | RETVAL = false; | |
192 | ||
193 | enum loc_network_flags iv = 0; | |
194 | ||
195 | if (strcmp("LOC_NETWORK_FLAG_ANONYMOUS_PROXY", flag) == 0) | |
196 | iv |= LOC_NETWORK_FLAG_ANONYMOUS_PROXY; | |
197 | else if (strcmp("LOC_NETWORK_FLAG_SATELLITE_PROVIDER", flag) == 0) | |
198 | iv |= LOC_NETWORK_FLAG_SATELLITE_PROVIDER; | |
199 | else if (strcmp("LOC_NETWORK_FLAG_ANYCAST", flag) == 0) | |
200 | iv |= LOC_NETWORK_FLAG_ANYCAST; | |
e17e804e PM |
201 | else if (strcmp("LOC_NETWORK_FLAG_DROP", flag) == 0) |
202 | iv |= LOC_NETWORK_FLAG_DROP; | |
c8e6ee4e SS |
203 | else |
204 | croak("Invalid flag"); | |
205 | ||
206 | // Lookup network | |
207 | struct loc_network *network; | |
208 | int err = loc_database_lookup_from_string(db, address, &network); | |
209 | ||
210 | if (!err) { | |
211 | // Check if the network has the given flag. | |
212 | if (loc_network_has_flag(network, iv)) { | |
213 | RETVAL = true; | |
214 | } | |
215 | ||
216 | loc_network_unref(network); | |
217 | } | |
218 | ||
219 | OUTPUT: | |
220 | RETVAL | |
221 | ||
8d4f5f67 SS |
222 | SV* |
223 | lookup_asn(db, address) | |
224 | struct loc_database* db; | |
225 | char* address; | |
226 | ||
227 | CODE: | |
228 | RETVAL = &PL_sv_undef; | |
229 | ||
230 | // Lookup network | |
231 | struct loc_network *network; | |
232 | int err = loc_database_lookup_from_string(db, address, &network); | |
233 | if (!err) { | |
234 | // Extract the ASN | |
235 | unsigned int as_number = loc_network_get_asn(network); | |
236 | if (as_number > 0) { | |
237 | RETVAL = newSViv(as_number); | |
238 | } | |
239 | ||
240 | loc_network_unref(network); | |
241 | } | |
242 | OUTPUT: | |
243 | RETVAL | |
244 | ||
cd022c5f SS |
245 | # |
246 | # Get functions | |
247 | # | |
201bfcd9 SS |
248 | SV* |
249 | get_country_name(db, ccode) | |
250 | struct loc_database* db; | |
251 | char* ccode; | |
252 | ||
253 | CODE: | |
254 | RETVAL = &PL_sv_undef; | |
255 | ||
256 | // Lookup country code | |
257 | struct loc_country *country; | |
258 | int err = loc_database_get_country(db, &country, ccode); | |
259 | if(!err) { | |
260 | // Extract the name for the given country code. | |
261 | const char* country_name = loc_country_get_name(country); | |
262 | RETVAL = newSVpv(country_name, strlen(country_name)); | |
263 | ||
264 | loc_country_unref(country); | |
265 | } | |
266 | ||
267 | OUTPUT: | |
268 | RETVAL | |
269 | ||
cd022c5f SS |
270 | SV* |
271 | get_continent_code(db, ccode) | |
272 | struct loc_database* db; | |
273 | char* ccode; | |
274 | ||
275 | CODE: | |
276 | RETVAL = &PL_sv_undef; | |
277 | ||
278 | // Lookup country code | |
279 | struct loc_country *country; | |
280 | int err = loc_database_get_country(db, &country, ccode); | |
281 | if(!err) { | |
282 | //Extract the continent code for the given country code. | |
283 | const char* continent_code = loc_country_get_continent_code(country); | |
284 | RETVAL = newSVpv(continent_code, strlen(continent_code)); | |
285 | ||
286 | loc_country_unref(country); | |
287 | } | |
288 | ||
289 | OUTPUT: | |
290 | RETVAL | |
291 | ||
30c8e528 SS |
292 | SV* |
293 | get_as_name(db, as_number) | |
294 | struct loc_database* db; | |
295 | unsigned int as_number; | |
296 | ||
297 | CODE: | |
298 | RETVAL = &PL_sv_undef; | |
299 | ||
300 | // Lookup AS. | |
301 | struct loc_as *as; | |
302 | int err = loc_database_get_as(db, &as, as_number); | |
303 | if(!err) { | |
304 | // Get the name of the given AS number. | |
305 | const char* as_name = loc_as_get_name(as); | |
306 | ||
307 | RETVAL = newSVpv(as_name, strlen(as_name)); | |
308 | ||
309 | loc_as_unref(as); | |
310 | } | |
311 | ||
312 | OUTPUT: | |
313 | RETVAL | |
314 | ||
1ea740e9 SS |
315 | void |
316 | DESTROY(db) | |
34eed014 | 317 | struct loc_database* db; |
da1039da | 318 | |
1ea740e9 | 319 | CODE: |
74ad091d | 320 | // Close database |
1ea740e9 | 321 | loc_database_unref(db); |