aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuido Günther <agx@sigxcpu.org>2014-09-11 09:41:26 +0200
committerGuido Günther <agx@sigxcpu.org>2014-09-11 10:07:14 +0200
commit80765f6f22f26f27dfedf3404fa033fe034c516c (patch)
tree831f91fb438914dba4b4ec39a1867bb0d75411bd
parentb8ceb58385d48a8858eb304369206170cc8a39a0 (diff)
Allow to block all hosts from a domain
Use .example.com to block all hosts in example.com
-rw-r--r--src/nss-dontstalkme.c66
1 files changed, 47 insertions, 19 deletions
diff --git a/src/nss-dontstalkme.c b/src/nss-dontstalkme.c
index 39bf34b..ad3a442 100644
--- a/src/nss-dontstalkme.c
+++ b/src/nss-dontstalkme.c
@@ -41,9 +41,12 @@
#define _public_ __attribute__ ((visibility("default")))
#define ARRAY_CARDINALITY(Array) (sizeof(Array) / sizeof(*(Array)))
-/* The hosts we blacklist */
-const char* stalkers[] = { "www.google-analytics.com",
- "ssl.google-analytics.com",
+/*
+ The hosts we blacklist
+ To blacklist all hosts from domain foo.bar use .foo.bar
+ */
+const char* stalkers[] = { /* https://support.google.com/analytics/answer/1009688?hl=en-GB */
+ ".google-analytics.com",
};
enum nss_status _nss_dontstalkme_gethostbyname4_r(const char *name,
@@ -72,6 +75,44 @@ enum nss_status _nss_dontstalkme_gethostbyname_r(const char *name,
int *errnop, int *h_errnop) _public_;
+/*
+ * check if host matches the given pattern.
+ *
+ * If pattern starts with a dot all names ending in pattern will
+ * match. Otherwise name has to match pattern exactly.
+*/
+static int
+match_pattern (const char *name, const char *pattern)
+{
+ int name_len = strlen(name);
+ int pattern_len = strlen(pattern);
+
+ if (pattern_len && pattern[0] == '.') {
+ if (name_len < pattern_len)
+ return 0;
+
+ return strcmp (name + name_len - pattern_len, pattern) == 0;
+ } else {
+ if (!strcasecmp(name, pattern))
+ return 1;
+ }
+ return 0;
+}
+
+
+static int
+is_stalker (const char* name)
+{
+ unsigned int i = 0;
+
+ for (i = 0; i < ARRAY_CARDINALITY(stalkers); i++) {
+ if (match_pattern(name, stalkers[i]))
+ return 1;
+ }
+ return 0;
+}
+
+
enum nss_status
_nss_dontstalkme_gethostbyname4_r(const char *name,
struct gaih_addrtuple **pat,
@@ -82,17 +123,11 @@ _nss_dontstalkme_gethostbyname4_r(const char *name,
unsigned lo_ifi;
size_t l, idx, ms;
char *r_name;
- unsigned int i;
struct gaih_addrtuple *r_tuple, *r_tuple_prev = NULL;
lo_ifi = if_nametoindex(LOOPBACK_INTERFACE);
- for (i = 0; i < ARRAY_CARDINALITY(stalkers); i++) {
- if (!strcasecmp(stalkers[i], name)) {
- break;
- }
- }
- if (i == ARRAY_CARDINALITY(stalkers)) {
+ if (! is_stalker(name)) {
*errnop = ENOENT;
*h_errnop = HOST_NOT_FOUND;
return NSS_STATUS_NOTFOUND;
@@ -145,7 +180,7 @@ _nss_dontstalkme_gethostbyname4_r(const char *name,
return NSS_STATUS_SUCCESS;
}
-static inline size_t
+static inline size_t
proto_address_size(int proto)
{
assert(proto == AF_INET || proto == AF_INET6);
@@ -233,8 +268,6 @@ _nss_dontstalkme_gethostbyname3_r(const char *name,
int32_t *ttlp,
char **canonp)
{
- unsigned int i;
-
if (af == AF_UNSPEC)
af = AF_INET;
@@ -244,12 +277,7 @@ _nss_dontstalkme_gethostbyname3_r(const char *name,
return NSS_STATUS_UNAVAIL;
}
- for (i = 0; i < ARRAY_CARDINALITY(stalkers); i++) {
- if (!strcasecmp(stalkers[i], name)) {
- break;
- }
- }
- if (i == ARRAY_CARDINALITY(stalkers)) {
+ if (! is_stalker(name)) {
*errnop = ENOENT;
*h_errnop = HOST_NOT_FOUND;
return NSS_STATUS_NOTFOUND;