diff -ruN bind-9.4.3-P1.orig/lib/dns/acl.c bind-9.4.3-P1/lib/dns/acl.c --- bind-9.4.3-P1.orig/lib/dns/acl.c 2006-03-02 00:37:21.000000000 +0000 +++ bind-9.4.3-P1/lib/dns/acl.c 2009-01-19 14:58:46.000000000 +0000 @@ -21,12 +21,16 @@ #include +#include +#include #include #include #include #include +static GeoIP *geoip = NULL; + isc_result_t dns_acl_create(isc_mem_t *mctx, int n, dns_acl_t **target) { isc_result_t result; @@ -209,6 +213,48 @@ goto matched; break; + case dns_aclelementtype_ipregion: + /* We only match V4 addresses */ + if (reqaddr->family == AF_INET) { + /* Region match */ + + if (NULL == geoip) { + geoip = GeoIP_new(GEOIP_MEMORY_CACHE); + } + if (NULL != geoip) { + GeoIPRecord * value; + + value = GeoIP_record_by_addr(geoip,inet_ntoa(reqaddr->type.in)); + if ((NULL != value) && (NULL != value->region) && (2 == strlen(value->region))) { + if ((e->u.region[0] == value->region[0]) && (e->u.region[1] == value->region[1])) { + goto matched; + } + } + } + } + break; + + case dns_aclelementtype_ipcountry: + /* We only match V4 addresses */ + if (reqaddr->family == AF_INET) { + /* Country match */ + + if (NULL == geoip) { + geoip = GeoIP_new(GEOIP_MEMORY_CACHE); + } + if (NULL != geoip) { + const char *value; + + value = GeoIP_country_code_by_addr(geoip,inet_ntoa(reqaddr->type.in)); + if ((NULL != value) && (2 == strlen(value))) { + if ((e->u.country[0] == value[0]) && (e->u.country[1] == value[1])) { + goto matched; + } + } + } + } + break; + case dns_aclelementtype_keyname: if (reqsigner != NULL && dns_name_equal(reqsigner, &e->u.keyname)) diff -ruN bind-9.4.3-P1.orig/lib/dns/include/dns/acl.h bind-9.4.3-P1/lib/dns/include/dns/acl.h --- bind-9.4.3-P1.orig/lib/dns/include/dns/acl.h 2006-03-02 00:37:21.000000000 +0000 +++ bind-9.4.3-P1/lib/dns/include/dns/acl.h 2009-01-19 15:00:04.000000000 +0000 @@ -47,6 +47,8 @@ typedef enum { dns_aclelementtype_ipprefix, + dns_aclelementtype_ipregion, + dns_aclelementtype_ipcountry, dns_aclelementtype_keyname, dns_aclelementtype_nestedacl, dns_aclelementtype_localhost, @@ -55,6 +57,8 @@ } dns_aclelemettype_t; typedef struct dns_aclipprefix dns_aclipprefix_t; +typedef char dns_aclipregion[3]; +typedef char dns_aclipcountry[3]; struct dns_aclipprefix { isc_netaddr_t address; /* IP4/IP6 */ @@ -66,6 +70,8 @@ isc_boolean_t negative; union { dns_aclipprefix_t ip_prefix; + dns_aclipregion region; + dns_aclipcountry country; dns_name_t keyname; dns_acl_t *nestedacl; } u; diff -ruN bind-9.4.3-P1.orig/lib/isccfg/aclconf.c bind-9.4.3-P1/lib/isccfg/aclconf.c --- bind-9.4.3-P1.orig/lib/isccfg/aclconf.c 2006-03-02 00:37:22.000000000 +0000 +++ bind-9.4.3-P1/lib/isccfg/aclconf.c 2009-01-19 15:00:53.000000000 +0000 @@ -228,6 +228,18 @@ } else if (strcasecmp(name, "none") == 0) { de->type = dns_aclelementtype_any; de->negative = ISC_TF(! de->negative); + } else if ((0 == (strncmp("region_", name, 8))) && (10 == strlen(name))) { + /* It is a region code */ + de->type = dns_aclelementtype_ipregion; + de->u.region[0] = name[8]; + de->u.region[1] = name[9]; + de->u.region[2] = '\0'; + } else if ((0 == (strncmp("country_", name, 8))) && (10 == strlen(name))) { + /* It is a country code */ + de->type = dns_aclelementtype_ipcountry; + de->u.country[0] = name[8]; + de->u.country[1] = name[9]; + de->u.country[2] = '\0'; } else { de->type = dns_aclelementtype_nestedacl; result = convert_named_acl(ce, cctx, lctx,