2 libloc - A library to determine the location of someone on the Internet
4 Copyright (C) 2019 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.
21 #include <libloc/libloc.h>
22 #include <libloc/compat.h>
23 #include <libloc/country.h>
24 #include <libloc/network.h>
25 #include <libloc/private.h>
27 static const struct loc_special_country
{
29 enum loc_network_flags flags
;
30 } loc_special_countries
[] = {
31 { "A1", LOC_NETWORK_FLAG_ANONYMOUS_PROXY
},
32 { "A2", LOC_NETWORK_FLAG_SATELLITE_PROVIDER
},
33 { "A3", LOC_NETWORK_FLAG_ANYCAST
},
34 { "XD", LOC_NETWORK_FLAG_DROP
},
42 // Store the country code in a 3 byte buffer. Two bytes for the code, and NULL so
43 // that we can use strcmp() and return a pointer.
45 char continent_code
[3];
50 LOC_EXPORT
int loc_country_new(struct loc_ctx
* ctx
, struct loc_country
** country
, const char* country_code
) {
51 // Check of the country code is valid
52 if (!loc_country_code_is_valid(country_code
)) {
57 struct loc_country
* c
= calloc(1, sizeof(*c
));
61 c
->ctx
= loc_ref(ctx
);
64 // Set the country code
65 loc_country_code_copy(c
->code
, country_code
);
67 DEBUG(c
->ctx
, "Country %s allocated at %p\n", c
->code
, c
);
73 LOC_EXPORT
struct loc_country
* loc_country_ref(struct loc_country
* country
) {
79 static void loc_country_free(struct loc_country
* country
) {
80 DEBUG(country
->ctx
, "Releasing country %s %p\n", country
->code
, country
);
85 loc_unref(country
->ctx
);
89 LOC_EXPORT
struct loc_country
* loc_country_unref(struct loc_country
* country
) {
90 if (--country
->refcount
> 0)
93 loc_country_free(country
);
97 LOC_EXPORT
const char* loc_country_get_code(struct loc_country
* country
) {
101 LOC_EXPORT
const char* loc_country_get_continent_code(struct loc_country
* country
) {
102 if (!*country
->continent_code
)
105 return country
->continent_code
;
108 LOC_EXPORT
int loc_country_set_continent_code(struct loc_country
* country
, const char* continent_code
) {
109 // Check for valid input
110 if (!continent_code
|| strlen(continent_code
) != 2) {
116 loc_country_code_copy(country
->continent_code
, continent_code
);
121 LOC_EXPORT
const char* loc_country_get_name(struct loc_country
* country
) {
122 return country
->name
;
125 LOC_EXPORT
int loc_country_set_name(struct loc_country
* country
, const char* name
) {
130 country
->name
= strdup(name
);
132 // Report error if we could not copy the string
140 LOC_EXPORT
int loc_country_cmp(struct loc_country
* country1
, struct loc_country
* country2
) {
141 return strncmp(country1
->code
, country2
->code
, 2);
144 int loc_country_new_from_database_v1(struct loc_ctx
* ctx
, struct loc_stringpool
* pool
,
145 struct loc_country
** country
, const struct loc_database_country_v1
* dbobj
) {
146 char buffer
[3] = "XX";
149 loc_country_code_copy(buffer
, dbobj
->code
);
151 // Create a new country object
152 int r
= loc_country_new(ctx
, country
, buffer
);
156 // Copy continent code
157 if (*dbobj
->continent_code
)
158 loc_country_code_copy((*country
)->continent_code
, dbobj
->continent_code
);
161 const char* name
= loc_stringpool_get(pool
, be32toh(dbobj
->name
));
163 r
= loc_country_set_name(*country
, name
);
171 loc_country_unref(*country
);
175 int loc_country_to_database_v1(struct loc_country
* country
,
176 struct loc_stringpool
* pool
, struct loc_database_country_v1
* dbobj
) {
181 loc_country_code_copy(dbobj
->code
, country
->code
);
183 // Add continent code
184 if (*country
->continent_code
)
185 loc_country_code_copy(dbobj
->continent_code
, country
->continent_code
);
187 // Save the name string in the string pool
189 name
= loc_stringpool_add(pool
, country
->name
);
191 dbobj
->name
= htobe32(name
);
196 LOC_EXPORT
int loc_country_code_is_valid(const char* cc
) {
201 // It must be 2 characters long
205 // It must only contain A-Z
206 for (unsigned int i
= 0; i
< 2; i
++) {
207 if (cc
[i
] < 'A' || cc
[i
] > 'Z')
211 // The code cannot begin with an X (those are reserved for private use)
219 LOC_EXPORT
int loc_country_special_code_to_flag(const char* cc
) {
220 // Check if we got some input
226 // Return flags for any known special country
227 for (const struct loc_special_country
* country
= loc_special_countries
;
228 country
->flags
; country
++) {
229 if (strncmp(country
->code
, cc
, 2) == 0)
230 return country
->flags
;