diff -ruN bind9.orig/lib/dns/acl.c bind9/lib/dns/acl.c --- bind9.orig/lib/dns/acl.c 2008-02-17 09:05:04.000000000 +0800 +++ bind9/lib/dns/acl.c 2009-10-01 19:43:06.000000000 +0800 @@ -21,12 +21,15 @@ #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; @@ -208,6 +211,27 @@ e->u.ip_prefix.prefixlen)) 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 && diff -ruN bind9.orig/lib/dns/include/dns/acl.h bind9/lib/dns/include/dns/acl.h --- bind9.orig/lib/dns/include/dns/acl.h 2008-02-17 09:05:04.000000000 +0800 +++ bind9/lib/dns/include/dns/acl.h 2009-10-01 19:44:57.000000000 +0800 @@ -47,6 +47,7 @@ typedef enum { dns_aclelementtype_ipprefix, + dns_aclelementtype_ipcountry, dns_aclelementtype_keyname, dns_aclelementtype_nestedacl, dns_aclelementtype_localhost, @@ -55,6 +56,7 @@ } dns_aclelemettype_t; typedef struct dns_aclipprefix dns_aclipprefix_t; +typedef char dns_aclipcountry[3]; struct dns_aclipprefix { isc_netaddr_t address; /* IP4/IP6 */ @@ -66,6 +68,7 @@ isc_boolean_t negative; union { dns_aclipprefix_t ip_prefix; + dns_aclipcountry country; dns_name_t keyname; dns_acl_t *nestedacl; } u; diff -ruN bind9.orig/lib/isccfg/aclconf.c bind9/lib/isccfg/aclconf.c --- bind9.orig/lib/isccfg/aclconf.c 2007-06-03 07:21:46.000000000 +0800 +++ bind9/lib/isccfg/aclconf.c 2009-10-01 19:45:37.000000000 +0800 @@ -228,6 +228,12 @@ } else if (strcasecmp(name, "none") == 0) { de->type = dns_aclelementtype_any; de->negative = ISC_TF(! de->negative); + } 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,