]>
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 | ||
1ea740e9 SS |
9 | #include <loc/libloc.h> |
10 | #include <loc/database.h> | |
11 | #include <loc/network.h> | |
c1590ddd | 12 | #include <loc/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; | |
201 | else | |
202 | croak("Invalid flag"); | |
203 | ||
204 | // Lookup network | |
205 | struct loc_network *network; | |
206 | int err = loc_database_lookup_from_string(db, address, &network); | |
207 | ||
208 | if (!err) { | |
209 | // Check if the network has the given flag. | |
210 | if (loc_network_has_flag(network, iv)) { | |
211 | RETVAL = true; | |
212 | } | |
213 | ||
214 | loc_network_unref(network); | |
215 | } | |
216 | ||
217 | OUTPUT: | |
218 | RETVAL | |
219 | ||
8d4f5f67 SS |
220 | SV* |
221 | lookup_asn(db, address) | |
222 | struct loc_database* db; | |
223 | char* address; | |
224 | ||
225 | CODE: | |
226 | RETVAL = &PL_sv_undef; | |
227 | ||
228 | // Lookup network | |
229 | struct loc_network *network; | |
230 | int err = loc_database_lookup_from_string(db, address, &network); | |
231 | if (!err) { | |
232 | // Extract the ASN | |
233 | unsigned int as_number = loc_network_get_asn(network); | |
234 | if (as_number > 0) { | |
235 | RETVAL = newSViv(as_number); | |
236 | } | |
237 | ||
238 | loc_network_unref(network); | |
239 | } | |
240 | OUTPUT: | |
241 | RETVAL | |
242 | ||
cd022c5f SS |
243 | # |
244 | # Get functions | |
245 | # | |
201bfcd9 SS |
246 | SV* |
247 | get_country_name(db, ccode) | |
248 | struct loc_database* db; | |
249 | char* ccode; | |
250 | ||
251 | CODE: | |
252 | RETVAL = &PL_sv_undef; | |
253 | ||
254 | // Lookup country code | |
255 | struct loc_country *country; | |
256 | int err = loc_database_get_country(db, &country, ccode); | |
257 | if(!err) { | |
258 | // Extract the name for the given country code. | |
259 | const char* country_name = loc_country_get_name(country); | |
260 | RETVAL = newSVpv(country_name, strlen(country_name)); | |
261 | ||
262 | loc_country_unref(country); | |
263 | } | |
264 | ||
265 | OUTPUT: | |
266 | RETVAL | |
267 | ||
cd022c5f SS |
268 | SV* |
269 | get_continent_code(db, ccode) | |
270 | struct loc_database* db; | |
271 | char* ccode; | |
272 | ||
273 | CODE: | |
274 | RETVAL = &PL_sv_undef; | |
275 | ||
276 | // Lookup country code | |
277 | struct loc_country *country; | |
278 | int err = loc_database_get_country(db, &country, ccode); | |
279 | if(!err) { | |
280 | //Extract the continent code for the given country code. | |
281 | const char* continent_code = loc_country_get_continent_code(country); | |
282 | RETVAL = newSVpv(continent_code, strlen(continent_code)); | |
283 | ||
284 | loc_country_unref(country); | |
285 | } | |
286 | ||
287 | OUTPUT: | |
288 | RETVAL | |
289 | ||
30c8e528 SS |
290 | SV* |
291 | get_as_name(db, as_number) | |
292 | struct loc_database* db; | |
293 | unsigned int as_number; | |
294 | ||
295 | CODE: | |
296 | RETVAL = &PL_sv_undef; | |
297 | ||
298 | // Lookup AS. | |
299 | struct loc_as *as; | |
300 | int err = loc_database_get_as(db, &as, as_number); | |
301 | if(!err) { | |
302 | // Get the name of the given AS number. | |
303 | const char* as_name = loc_as_get_name(as); | |
304 | ||
305 | RETVAL = newSVpv(as_name, strlen(as_name)); | |
306 | ||
307 | loc_as_unref(as); | |
308 | } | |
309 | ||
310 | OUTPUT: | |
311 | RETVAL | |
312 | ||
1ea740e9 SS |
313 | void |
314 | DESTROY(db) | |
34eed014 | 315 | struct loc_database* db; |
da1039da | 316 | |
1ea740e9 | 317 | CODE: |
74ad091d | 318 | // Close database |
1ea740e9 | 319 | loc_database_unref(db); |