geoip.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2013-2015  Internet Systems Consortium, Inc. ("ISC")
00003  *
00004  * Permission to use, copy, modify, and/or distribute this software for any
00005  * purpose with or without fee is hereby granted, provided that the above
00006  * copyright notice and this permission notice appear in all copies.
00007  *
00008  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00009  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00010  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00011  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00012  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00013  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00014  * PERFORMANCE OF THIS SOFTWARE.
00015  */
00016 
00017 /*! \file */
00018 
00019 #include <config.h>
00020 
00021 #include <isc/util.h>
00022 
00023 #include <isc/mem.h>
00024 #include <isc/once.h>
00025 #include <isc/string.h>
00026 
00027 #include <dns/acl.h>
00028 #include <dns/geoip.h>
00029 
00030 #include <isc/thread.h>
00031 #include <math.h>
00032 #ifndef WIN32
00033 #include <netinet/in.h>
00034 #else
00035 #ifndef _WINSOCKAPI_
00036 #define _WINSOCKAPI_   /* Prevent inclusion of winsock.h in windows.h */
00037 #endif
00038 #include <winsock2.h>
00039 #endif  /* WIN32 */
00040 #include <dns/log.h>
00041 
00042 #ifdef HAVE_GEOIP
00043 #include <GeoIP.h>
00044 #include <GeoIPCity.h>
00045 
00046 /*
00047  * This structure preserves state from the previous GeoIP lookup,
00048  * so that successive lookups for the same data from the same IP
00049  * address will not require repeated calls into the GeoIP library
00050  * to look up data in the database. This should improve performance
00051  * somewhat.
00052  *
00053  * For lookups in the City and Region databases, we preserve pointers
00054  * to the GeoIPRecord and GeoIPregion structures; these will need to be
00055  * freed by GeoIPRecord_delete() and GeoIPRegion_delete().
00056  *
00057  * for lookups in ISP, AS, Org and Domain we prserve a pointer to
00058  * the returned name; these must be freed by free().
00059  *
00060  * For lookups in Country we preserve a pointer to the text of
00061  * the country code, name, etc (we use a different pointer for this
00062  * than for the names returned by Org, ISP, etc, because those need
00063  * to be freed but country lookups do not).
00064  *
00065  * For lookups in Netspeed we preserve the returned ID.
00066  *
00067  * XXX: Currently this mechanism is only used for IPv4 lookups; the
00068  * family and addr6 fields are to be used IPv6 is added.
00069  */
00070 typedef struct geoip_state {
00071         isc_uint16_t subtype;
00072         unsigned int family;
00073         isc_uint32_t ipnum;
00074         geoipv6_t ipnum6;
00075         isc_uint8_t scope;
00076         GeoIPRecord *record;
00077         GeoIPRegion *region;
00078         const char *text;
00079         char *name;
00080         int id;
00081         isc_mem_t *mctx;
00082 } geoip_state_t;
00083 
00084 #ifdef ISC_PLATFORM_USETHREADS
00085 static isc_mutex_t key_mutex;
00086 static isc_boolean_t state_key_initialized = ISC_FALSE;
00087 static isc_thread_key_t state_key;
00088 static isc_once_t mutex_once = ISC_ONCE_INIT;
00089 static isc_mem_t *state_mctx = NULL;
00090 
00091 static void
00092 key_mutex_init(void) {
00093         RUNTIME_CHECK(isc_mutex_init(&key_mutex) == ISC_R_SUCCESS);
00094 }
00095 
00096 static void
00097 free_state(void *arg) {
00098         geoip_state_t *state = arg;
00099         if (state != NULL && state->record != NULL)
00100                 GeoIPRecord_delete(state->record);
00101         if (state != NULL)
00102                 isc_mem_putanddetach(&state->mctx,
00103                                      state, sizeof(geoip_state_t));
00104         isc_thread_key_setspecific(state_key, NULL);
00105 }
00106 
00107 static isc_result_t
00108 state_key_init(void) {
00109         isc_result_t result;
00110 
00111         result = isc_once_do(&mutex_once, key_mutex_init);
00112         if (result != ISC_R_SUCCESS)
00113                 return (result);
00114 
00115         if (!state_key_initialized) {
00116                 LOCK(&key_mutex);
00117                 if (!state_key_initialized) {
00118                         int ret;
00119 
00120                         if (state_mctx == NULL)
00121                                 result = isc_mem_create2(0, 0, &state_mctx, 0);
00122                         if (result != ISC_R_SUCCESS)
00123                                 goto unlock;
00124                         isc_mem_setname(state_mctx, "geoip_state", NULL);
00125                         isc_mem_setdestroycheck(state_mctx, ISC_FALSE);
00126 
00127                         ret = isc_thread_key_create(&state_key, free_state);
00128                         if (ret == 0)
00129                                 state_key_initialized = ISC_TRUE;
00130                         else
00131                                 result = ISC_R_FAILURE;
00132                 }
00133  unlock:
00134                 UNLOCK(&key_mutex);
00135         }
00136 
00137         return (result);
00138 }
00139 #else
00140 static geoip_state_t saved_state;
00141 #endif
00142 
00143 static void
00144 clean_state(geoip_state_t *state) {
00145         if (state == NULL)
00146                 return;
00147 
00148         if (state->record != NULL) {
00149                 GeoIPRecord_delete(state->record);
00150                 state->record = NULL;
00151         }
00152         if (state->region != NULL) {
00153                 GeoIPRegion_delete(state->region);
00154                 state->region = NULL;
00155         }
00156         if (state->name != NULL) {
00157                 free (state->name);
00158                 state->name = NULL;
00159         }
00160         state->ipnum = 0;
00161         state->text = NULL;
00162         state->id = 0;
00163 }
00164 
00165 static isc_result_t
00166 set_state(unsigned int family, isc_uint32_t ipnum, const geoipv6_t *ipnum6,
00167           isc_uint8_t scope, dns_geoip_subtype_t subtype, GeoIPRecord *record,
00168           GeoIPRegion *region, char *name, const char *text, int id)
00169 {
00170         geoip_state_t *state = NULL;
00171 #ifdef ISC_PLATFORM_USETHREADS
00172         isc_result_t result;
00173 
00174         result = state_key_init();
00175         if (result != ISC_R_SUCCESS)
00176                 return (result);
00177 
00178         state = (geoip_state_t *) isc_thread_key_getspecific(state_key);
00179         if (state == NULL) {
00180                 state = (geoip_state_t *) isc_mem_get(state_mctx,
00181                                                       sizeof(geoip_state_t));
00182                 if (state == NULL)
00183                         return (ISC_R_NOMEMORY);
00184                 memset(state, 0, sizeof(*state));
00185 
00186                 result = isc_thread_key_setspecific(state_key, state);
00187                 if (result != ISC_R_SUCCESS) {
00188                         isc_mem_put(state_mctx, state, sizeof(geoip_state_t));
00189                         return (result);
00190                 }
00191 
00192                 isc_mem_attach(state_mctx, &state->mctx);
00193         } else
00194                 clean_state(state);
00195 #else
00196         state = &saved_state;
00197         clean_state(state);
00198 #endif
00199 
00200         if (family == AF_INET)
00201                 state->ipnum = ipnum;
00202         else
00203                 state->ipnum6 = *ipnum6;
00204 
00205         state->family = family;
00206         state->subtype = subtype;
00207         state->scope = scope;
00208         state->record = record;
00209         state->region = region;
00210         state->name = name;
00211         state->text = text;
00212         state->id = id;
00213 
00214         return (ISC_R_SUCCESS);
00215 }
00216 
00217 static geoip_state_t *
00218 get_state_for(unsigned int family, isc_uint32_t ipnum,
00219               const geoipv6_t *ipnum6)
00220 {
00221         geoip_state_t *state;
00222 
00223 #ifdef ISC_PLATFORM_USETHREADS
00224         isc_result_t result;
00225 
00226         result = state_key_init();
00227         if (result != ISC_R_SUCCESS)
00228                 return (NULL);
00229 
00230         state = (geoip_state_t *) isc_thread_key_getspecific(state_key);
00231         if (state == NULL)
00232                 return (NULL);
00233 #else
00234         state = &saved_state;
00235 #endif
00236 
00237         if (state->family == family &&
00238             ((state->family == AF_INET && state->ipnum == ipnum) ||
00239              (state->family == AF_INET6 && ipnum6 != NULL &&
00240               memcmp(state->ipnum6.s6_addr, ipnum6->s6_addr, 16) == 0)))
00241                 return (state);
00242 
00243         return (NULL);
00244 }
00245 
00246 /*
00247  * Country lookups are performed if the previous lookup was from a
00248  * different IP address than the current, or was for a search of a
00249  * different subtype.
00250  */
00251 static const char *
00252 country_lookup(GeoIP *db, dns_geoip_subtype_t subtype,
00253                unsigned int family,
00254                isc_uint32_t ipnum, const geoipv6_t *ipnum6,
00255                isc_uint8_t *scope)
00256 {
00257         geoip_state_t *prev_state = NULL;
00258         const char *text = NULL;
00259         GeoIPLookup gl;
00260 
00261         REQUIRE(db != NULL);
00262 
00263 #ifndef HAVE_GEOIP_V6
00264         /* no IPv6 support? give up now */
00265         if (family == AF_INET6)
00266                 return (NULL);
00267 #endif
00268 
00269         prev_state = get_state_for(family, ipnum, ipnum6);
00270         if (prev_state != NULL && prev_state->subtype == subtype) {
00271                 text = prev_state->text;
00272                 if (scope != NULL)
00273                         *scope = prev_state->scope;
00274         }
00275 
00276         if (text == NULL) {
00277                 switch (subtype) {
00278                 case dns_geoip_country_code:
00279                         if (family == AF_INET)
00280                                 text = GeoIP_country_code_by_ipnum_gl(db,
00281                                                                  ipnum, &gl);
00282 #ifdef HAVE_GEOIP_V6
00283                         else
00284                                 text = GeoIP_country_code_by_ipnum_v6_gl(db,
00285                                                                  *ipnum6, &gl);
00286 #endif
00287                         break;
00288                 case dns_geoip_country_code3:
00289                         if (family == AF_INET)
00290                                 text = GeoIP_country_code3_by_ipnum_gl(db,
00291                                                                  ipnum, &gl);
00292 #ifdef HAVE_GEOIP_V6
00293                         else
00294                                 text = GeoIP_country_code3_by_ipnum_v6_gl(db,
00295                                                                  *ipnum6, &gl);
00296 #endif
00297                         break;
00298                 case dns_geoip_country_name:
00299                         if (family == AF_INET)
00300                                 text = GeoIP_country_name_by_ipnum_gl(db,
00301                                                                  ipnum, &gl);
00302 #ifdef HAVE_GEOIP_V6
00303                         else
00304                                 text = GeoIP_country_name_by_ipnum_v6_gl(db,
00305                                                                  *ipnum6, &gl);
00306 #endif
00307                         break;
00308                 default:
00309                         INSIST(0);
00310                 }
00311 
00312                 if (text == NULL)
00313                         return (NULL);
00314 
00315                 if (scope != NULL)
00316                         *scope = gl.netmask;
00317 
00318                 set_state(family, ipnum, ipnum6, gl.netmask, subtype,
00319                           NULL, NULL, NULL, text, 0);
00320         }
00321 
00322         return (text);
00323 }
00324 
00325 static char *
00326 city_string(GeoIPRecord *record, dns_geoip_subtype_t subtype, int *maxlen) {
00327         const char *s;
00328         char *deconst;
00329 
00330         REQUIRE(record != NULL);
00331         REQUIRE(maxlen != NULL);
00332 
00333         /* Set '*maxlen' to the maximum length of this subtype, if any */
00334         switch (subtype) {
00335         case dns_geoip_city_countrycode:
00336         case dns_geoip_city_region:
00337         case dns_geoip_city_continentcode:
00338                 *maxlen = 2;
00339                 break;
00340 
00341         case dns_geoip_city_countrycode3:
00342                 *maxlen = 3;
00343                 break;
00344 
00345         default:
00346                 /* No fixed length; just use strcasecmp() for comparison */
00347                 *maxlen = 255;
00348         }
00349 
00350         switch (subtype) {
00351         case dns_geoip_city_countrycode:
00352                 return (record->country_code);
00353         case dns_geoip_city_countrycode3:
00354                 return (record->country_code3);
00355         case dns_geoip_city_countryname:
00356                 return (record->country_name);
00357         case dns_geoip_city_region:
00358                 return (record->region);
00359         case dns_geoip_city_regionname:
00360                 s = GeoIP_region_name_by_code(record->country_code,
00361                                               record->region);
00362                 DE_CONST(s, deconst);
00363                 return (deconst);
00364         case dns_geoip_city_name:
00365                 return (record->city);
00366         case dns_geoip_city_postalcode:
00367                 return (record->postal_code);
00368         case dns_geoip_city_continentcode:
00369                 return (record->continent_code);
00370         case dns_geoip_city_timezonecode:
00371                 s = GeoIP_time_zone_by_country_and_region(record->country_code,
00372                                                           record->region);
00373                 DE_CONST(s, deconst);
00374                 return (deconst);
00375         default:
00376                 INSIST(0);
00377         }
00378 }
00379 
00380 static isc_boolean_t
00381 is_city(dns_geoip_subtype_t subtype) {
00382         switch (subtype) {
00383         case dns_geoip_city_countrycode:
00384         case dns_geoip_city_countrycode3:
00385         case dns_geoip_city_countryname:
00386         case dns_geoip_city_region:
00387         case dns_geoip_city_regionname:
00388         case dns_geoip_city_name:
00389         case dns_geoip_city_postalcode:
00390         case dns_geoip_city_continentcode:
00391         case dns_geoip_city_timezonecode:
00392         case dns_geoip_city_metrocode:
00393         case dns_geoip_city_areacode:
00394                 return (ISC_TRUE);
00395         default:
00396                 return (ISC_FALSE);
00397         }
00398 }
00399 
00400 /*
00401  * GeoIPRecord lookups are performed if the previous lookup was
00402  * from a different IP address than the current, or was for a search
00403  * outside the City database.
00404  */
00405 static GeoIPRecord *
00406 city_lookup(GeoIP *db, dns_geoip_subtype_t subtype,
00407             unsigned int family, isc_uint32_t ipnum,
00408             const geoipv6_t *ipnum6,
00409             isc_uint8_t *scope)
00410 {
00411         GeoIPRecord *record = NULL;
00412         geoip_state_t *prev_state = NULL;
00413 
00414         REQUIRE(db != NULL);
00415 
00416 #ifndef HAVE_GEOIP_V6
00417         /* no IPv6 support? give up now */
00418         if (family == AF_INET6)
00419                 return (NULL);
00420 #endif
00421 
00422         prev_state = get_state_for(family, ipnum, ipnum6);
00423         if (prev_state != NULL && is_city(prev_state->subtype)) {
00424                 record = prev_state->record;
00425                 if (scope != NULL)
00426                         *scope = record->netmask;
00427         }
00428 
00429         if (record == NULL) {
00430                 if (family == AF_INET)
00431                         record = GeoIP_record_by_ipnum(db, ipnum);
00432 #ifdef HAVE_GEOIP_V6
00433                 else
00434                         record = GeoIP_record_by_ipnum_v6(db, *ipnum6);
00435 #endif
00436                 if (record == NULL)
00437                         return (NULL);
00438 
00439                 if (scope != NULL)
00440                         *scope = record->netmask;
00441 
00442                 set_state(family, ipnum, ipnum6, record->netmask, subtype,
00443                           record, NULL, NULL, NULL, 0);
00444         }
00445 
00446         return (record);
00447 }
00448 
00449 static char * region_string(GeoIPRegion *region, dns_geoip_subtype_t subtype, int *maxlen) {
00450         const char *s;
00451         char *deconst;
00452 
00453         REQUIRE(region != NULL);
00454         REQUIRE(maxlen != NULL);
00455 
00456         switch (subtype) {
00457         case dns_geoip_region_countrycode:
00458                 *maxlen = 2;
00459                 return (region->country_code);
00460         case dns_geoip_region_code:
00461                 *maxlen = 2;
00462                 return (region->region);
00463         case dns_geoip_region_name:
00464                 *maxlen = 255;
00465                 s = GeoIP_region_name_by_code(region->country_code,
00466                                               region->region);
00467                 DE_CONST(s, deconst);
00468                 return (deconst);
00469         default:
00470                 INSIST(0);
00471         }
00472 }
00473 
00474 static isc_boolean_t
00475 is_region(dns_geoip_subtype_t subtype) {
00476         switch (subtype) {
00477         case dns_geoip_region_countrycode:
00478         case dns_geoip_region_code:
00479                 return (ISC_TRUE);
00480         default:
00481                 return (ISC_FALSE);
00482         }
00483 }
00484 
00485 /*
00486  * GeoIPRegion lookups are performed if the previous lookup was
00487  * from a different IP address than the current, or was for a search
00488  * outside the Region database.
00489  */
00490 static GeoIPRegion *
00491 region_lookup(GeoIP *db, dns_geoip_subtype_t subtype,
00492               isc_uint32_t ipnum, isc_uint8_t *scope)
00493 {
00494         GeoIPRegion *region = NULL;
00495         geoip_state_t *prev_state = NULL;
00496         GeoIPLookup gl;
00497 
00498         REQUIRE(db != NULL);
00499 
00500         prev_state = get_state_for(AF_INET, ipnum, NULL);
00501         if (prev_state != NULL && is_region(prev_state->subtype)) {
00502                 region = prev_state->region;
00503                 if (scope != NULL)
00504                         *scope = prev_state->scope;
00505         }
00506 
00507         if (region == NULL) {
00508                 region = GeoIP_region_by_ipnum_gl(db, ipnum, &gl);
00509                 if (region == NULL)
00510                         return (NULL);
00511 
00512                 if (scope != NULL)
00513                         *scope = gl.netmask;
00514 
00515                 set_state(AF_INET, ipnum, NULL, gl.netmask,
00516                           subtype, NULL, region, NULL, NULL, 0);
00517         }
00518 
00519         return (region);
00520 }
00521 
00522 /*
00523  * ISP, Organization, AS Number and Domain lookups are performed if
00524  * the previous lookup was from a different IP address than the current,
00525  * or was for a search of a different subtype.
00526  */
00527 static char *
00528 name_lookup(GeoIP *db, dns_geoip_subtype_t subtype,
00529             isc_uint32_t ipnum, isc_uint8_t *scope)
00530 {
00531         char *name = NULL;
00532         geoip_state_t *prev_state = NULL;
00533         GeoIPLookup gl;
00534 
00535         REQUIRE(db != NULL);
00536 
00537         prev_state = get_state_for(AF_INET, ipnum, NULL);
00538         if (prev_state != NULL && prev_state->subtype == subtype) {
00539                 name = prev_state->name;
00540                 if (scope != NULL)
00541                         *scope = prev_state->scope;
00542         }
00543 
00544         if (name == NULL) {
00545                 name = GeoIP_name_by_ipnum_gl(db, ipnum, &gl);
00546                 if (name == NULL)
00547                         return (NULL);
00548 
00549                 if (scope != NULL)
00550                         *scope = gl.netmask;
00551 
00552                 set_state(AF_INET, ipnum, NULL, gl.netmask,
00553                           subtype, NULL, NULL, name, NULL, 0);
00554         }
00555 
00556         return (name);
00557 }
00558 
00559 /*
00560  * Netspeed lookups are performed if the previous lookup was from a
00561  * different IP address than the current, or was for a search of a
00562  * different subtype.
00563  */
00564 static int
00565 netspeed_lookup(GeoIP *db, dns_geoip_subtype_t subtype,
00566                 isc_uint32_t ipnum, isc_uint8_t *scope)
00567 {
00568         geoip_state_t *prev_state = NULL;
00569         isc_boolean_t found = ISC_FALSE;
00570         GeoIPLookup gl;
00571         int id = -1;
00572 
00573         REQUIRE(db != NULL);
00574 
00575         prev_state = get_state_for(AF_INET, ipnum, NULL);
00576         if (prev_state != NULL && prev_state->subtype == subtype) {
00577                 id = prev_state->id;
00578                 if (scope != NULL)
00579                         *scope = prev_state->scope;
00580                 found = ISC_TRUE;
00581         }
00582 
00583         if (!found) {
00584                 id = GeoIP_id_by_ipnum_gl(db, ipnum, &gl);
00585                 if (id == 0)
00586                         return (0);
00587 
00588                 if (scope != NULL)
00589                         *scope = gl.netmask;
00590 
00591                 set_state(AF_INET, ipnum, NULL, gl.netmask,
00592                           subtype, NULL, NULL, NULL, NULL, id);
00593         }
00594 
00595         return (id);
00596 }
00597 #endif /* HAVE_GEOIP */
00598 
00599 #define DB46(addr, geoip, name) \
00600         ((addr->family == AF_INET) ? (geoip->name##_v4) : (geoip->name##_v6))
00601 
00602 #ifdef HAVE_GEOIP
00603 /*
00604  * Find the best database to answer a generic subtype
00605  */
00606 static dns_geoip_subtype_t
00607 fix_subtype(const isc_netaddr_t *reqaddr, const dns_geoip_databases_t *geoip,
00608             dns_geoip_subtype_t subtype)
00609 {
00610         dns_geoip_subtype_t ret = subtype;
00611 
00612         switch (subtype) {
00613         case dns_geoip_countrycode:
00614                 if (DB46(reqaddr, geoip, city) != NULL)
00615                         ret = dns_geoip_city_countrycode;
00616                 else if (reqaddr->family == AF_INET && geoip->region != NULL)
00617                         ret = dns_geoip_region_countrycode;
00618                 else if (DB46(reqaddr, geoip, country) != NULL)
00619                         ret = dns_geoip_country_code;
00620                 break;
00621         case dns_geoip_countrycode3:
00622                 if (DB46(reqaddr, geoip, city) != NULL)
00623                         ret = dns_geoip_city_countrycode3;
00624                 else if (DB46(reqaddr, geoip, country) != NULL)
00625                         ret = dns_geoip_country_code3;
00626                 break;
00627         case dns_geoip_countryname:
00628                 if (DB46(reqaddr, geoip, city) != NULL)
00629                         ret = dns_geoip_city_countryname;
00630                 else if (DB46(reqaddr, geoip, country) != NULL)
00631                         ret = dns_geoip_country_name;
00632                 break;
00633         case dns_geoip_region:
00634                 if (DB46(reqaddr, geoip, city) != NULL)
00635                         ret = dns_geoip_city_region;
00636                 else if (reqaddr->family == AF_INET && geoip->region != NULL)
00637                         ret = dns_geoip_region_code;
00638                 break;
00639         case dns_geoip_regionname:
00640                 if (DB46(reqaddr, geoip, city) != NULL)
00641                         ret = dns_geoip_city_regionname;
00642                 else if (reqaddr->family == AF_INET && geoip->region != NULL)
00643                         ret = dns_geoip_region_name;
00644                 break;
00645         default:
00646                 break;
00647         }
00648 
00649         return (ret);
00650 }
00651 #endif /* HAVE_GEOIP */
00652 
00653 isc_boolean_t
00654 dns_geoip_match(const isc_netaddr_t *reqaddr, isc_uint8_t *scope,
00655                 const dns_geoip_databases_t *geoip,
00656                 const dns_geoip_elem_t *elt)
00657 {
00658 #ifndef HAVE_GEOIP
00659         UNUSED(reqaddr);
00660         UNUSED(geoip);
00661         UNUSED(elt);
00662 
00663         return (ISC_FALSE);
00664 #else
00665         GeoIP *db;
00666         GeoIPRecord *record;
00667         GeoIPRegion *region;
00668         dns_geoip_subtype_t subtype;
00669         isc_uint32_t ipnum = 0;
00670         int maxlen = 0, id, family;
00671         const char *cs;
00672         char *s;
00673 #ifdef HAVE_GEOIP_V6
00674         const geoipv6_t *ipnum6 = NULL;
00675 #else
00676         const void *ipnum6 = NULL;
00677 #endif
00678 
00679         INSIST(geoip != NULL);
00680 
00681         family = reqaddr->family;
00682         switch (family) {
00683         case AF_INET:
00684                 ipnum = ntohl(reqaddr->type.in.s_addr);
00685                 break;
00686         case AF_INET6:
00687 #ifdef HAVE_GEOIP_V6
00688                 ipnum6 = &reqaddr->type.in6;
00689                 break;
00690 #else
00691                 return (ISC_FALSE);
00692 #endif
00693         default:
00694                 return (ISC_FALSE);
00695         }
00696 
00697         subtype = fix_subtype(reqaddr, geoip, elt->subtype);
00698 
00699         switch (subtype) {
00700         case dns_geoip_country_code:
00701                 maxlen = 2;
00702                 goto getcountry;
00703 
00704         case dns_geoip_country_code3:
00705                 maxlen = 3;
00706                 goto getcountry;
00707 
00708         case dns_geoip_country_name:
00709                 maxlen = 255;
00710  getcountry:
00711                 db = DB46(reqaddr, geoip, country);
00712                 if (db == NULL)
00713                         return (ISC_FALSE);
00714 
00715                 INSIST(elt->as_string != NULL);
00716 
00717                 cs = country_lookup(db, subtype, family, ipnum, ipnum6, scope);
00718                 if (cs != NULL && strncasecmp(elt->as_string, cs, maxlen) == 0)
00719                         return (ISC_TRUE);
00720                 break;
00721 
00722         case dns_geoip_city_countrycode:
00723         case dns_geoip_city_countrycode3:
00724         case dns_geoip_city_countryname:
00725         case dns_geoip_city_region:
00726         case dns_geoip_city_regionname:
00727         case dns_geoip_city_name:
00728         case dns_geoip_city_postalcode:
00729         case dns_geoip_city_continentcode:
00730         case dns_geoip_city_timezonecode:
00731                 INSIST(elt->as_string != NULL);
00732 
00733                 db = DB46(reqaddr, geoip, city);
00734                 if (db == NULL)
00735                         return (ISC_FALSE);
00736 
00737                 record = city_lookup(db, subtype, family,
00738                                      ipnum, ipnum6, scope);
00739                 if (record == NULL)
00740                         break;
00741 
00742                 s = city_string(record, subtype, &maxlen);
00743                 INSIST(maxlen != 0);
00744                 if (s != NULL && strncasecmp(elt->as_string, s, maxlen) == 0)
00745                         return (ISC_TRUE);
00746                 break;
00747 
00748         case dns_geoip_city_metrocode:
00749                 db = DB46(reqaddr, geoip, city);
00750                 if (db == NULL)
00751                         return (ISC_FALSE);
00752 
00753                 record = city_lookup(db, subtype, family,
00754                                      ipnum, ipnum6, scope);
00755                 if (record == NULL)
00756                         break;
00757 
00758                 if (elt->as_int == record->metro_code)
00759                         return (ISC_TRUE);
00760                 break;
00761 
00762         case dns_geoip_city_areacode:
00763                 db = DB46(reqaddr, geoip, city);
00764                 if (db == NULL)
00765                         return (ISC_FALSE);
00766 
00767                 record = city_lookup(db, subtype, family,
00768                                      ipnum, ipnum6, scope);
00769                 if (record == NULL)
00770                         break;
00771 
00772                 if (elt->as_int == record->area_code)
00773                         return (ISC_TRUE);
00774                 break;
00775 
00776         case dns_geoip_region_countrycode:
00777         case dns_geoip_region_code:
00778         case dns_geoip_region_name:
00779         case dns_geoip_region:
00780                 if (geoip->region == NULL)
00781                         return (ISC_FALSE);
00782 
00783                 INSIST(elt->as_string != NULL);
00784 
00785                 /* Region DB is not supported for IPv6 */
00786                 if (family == AF_INET6)
00787                         return (ISC_FALSE);
00788 
00789                 region = region_lookup(geoip->region, subtype, ipnum, scope);
00790                 if (region == NULL)
00791                         break;
00792 
00793                 s = region_string(region, subtype, &maxlen);
00794                 INSIST(maxlen != 0);
00795                 if (s != NULL && strncasecmp(elt->as_string, s, maxlen) == 0)
00796                         return (ISC_TRUE);
00797                 break;
00798 
00799         case dns_geoip_isp_name:
00800                 db = geoip->isp;
00801                 goto getname;
00802 
00803         case dns_geoip_org_name:
00804                 db = geoip->org;
00805                 goto getname;
00806 
00807         case dns_geoip_as_asnum:
00808                 db = geoip->as;
00809                 goto getname;
00810 
00811         case dns_geoip_domain_name:
00812                 db = geoip->domain;
00813 
00814  getname:
00815                 if (db == NULL)
00816                         return (ISC_FALSE);
00817 
00818                 INSIST(elt->as_string != NULL);
00819                 /* ISP, Org, AS, and Domain are not supported for IPv6 */
00820                 if (family == AF_INET6)
00821                         return (ISC_FALSE);
00822 
00823                 s = name_lookup(db, subtype, ipnum, scope);
00824                 if (s != NULL) {
00825                         size_t l;
00826                         if (strcasecmp(elt->as_string, s) == 0)
00827                                 return (ISC_TRUE);
00828                         if (subtype != dns_geoip_as_asnum)
00829                                 break;
00830                         /*
00831                          * Just check if the ASNNNN value matches.
00832                          */
00833                         l = strlen(elt->as_string);
00834                         if (l > 0U && strchr(elt->as_string, ' ') == NULL &&
00835                             strncasecmp(elt->as_string, s, l) == 0 &&
00836                             s[l] == ' ')
00837                                 return (ISC_TRUE);
00838                 }
00839                 break;
00840 
00841         case dns_geoip_netspeed_id:
00842                 INSIST(geoip->netspeed != NULL);
00843 
00844                 /* Netspeed DB is not supported for IPv6 */
00845                 if (family == AF_INET6)
00846                         return (ISC_FALSE);
00847 
00848                 id = netspeed_lookup(geoip->netspeed, subtype, ipnum, scope);
00849                 if (id == elt->as_int)
00850                         return (ISC_TRUE);
00851                 break;
00852 
00853         case dns_geoip_countrycode:
00854         case dns_geoip_countrycode3:
00855         case dns_geoip_countryname:
00856         case dns_geoip_regionname:
00857                 /*
00858                  * If these were not remapped by fix_subtype(),
00859                  * the database was unavailable. Always return false.
00860                  */
00861                 break;
00862 
00863         default:
00864                 INSIST(0);
00865         }
00866 
00867         return (ISC_FALSE);
00868 #endif
00869 }
00870 
00871 void
00872 dns_geoip_shutdown(void) {
00873 #ifdef HAVE_GEOIP
00874         GeoIP_cleanup();
00875 #ifdef ISC_PLATFORM_USETHREADS
00876         if (state_mctx != NULL)
00877                 isc_mem_detach(&state_mctx);
00878 #endif
00879 #else
00880         return;
00881 #endif
00882 }

Generated on Tue Apr 28 17:40:56 2015 by Doxygen 1.5.4 for BIND9 Internals 9.11.0pre-alpha