summaryrefslogtreecommitdiffstats
path: root/src/lib-dns/dns-util.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib-dns/dns-util.c')
-rw-r--r--src/lib-dns/dns-util.c85
1 files changed, 85 insertions, 0 deletions
diff --git a/src/lib-dns/dns-util.c b/src/lib-dns/dns-util.c
new file mode 100644
index 0000000..a8469ce
--- /dev/null
+++ b/src/lib-dns/dns-util.c
@@ -0,0 +1,85 @@
+/* Copyright (c) 2010-2018 Dovecot authors, see the included COPYING file */
+#include "lib.h"
+#include "dns-util.h"
+
+/**
+ return first position from b->a of c or a if not found
+ */
+static inline
+const char *strchr_ba(const char *a, const char *b, char c)
+{
+ for(;b>a && *b != c; b--);
+ return b;
+}
+
+int dns_ncompare(const char *a, const char *b, size_t n)
+{
+ if (a == NULL && b == NULL) return 0;
+ if (a == NULL && b != NULL) return 1;
+ if (a != NULL && b == NULL) return -1;
+
+ for(size_t i = 0; i < n &&
+ *a != '\0' &&
+ *b != '\0' &&
+ dns_tolower(*a) == dns_tolower(*b);
+ i++, a++, b++);
+
+ return dns_tolower(*a) - dns_tolower(*b);
+}
+
+int dns_compare(const char *a, const char *b)
+{
+ return dns_ncompare(a, b, SIZE_MAX);
+}
+
+int dns_compare_labels(const char *a, const char *b)
+{
+ if (a == NULL && b == NULL) return 0;
+ if (a == NULL && b != NULL) return 1;
+ if (a != NULL && b == NULL) return -1;
+
+ const char *ptr_a = a + strlen(a);
+ const char *ptr_b = b + strlen(b);
+ const char *label_a = ptr_a, *label_b = ptr_b;
+ int comp = 0;
+
+ while(comp == 0 && ptr_a > a && ptr_b > b) {
+ /* look for start of label, including dot */
+ label_a = strchr_ba(a, ptr_a, '.');
+ label_b = strchr_ba(b, ptr_b, '.');
+ if (ptr_a - label_a != ptr_b - label_b)
+ /* compare labels up to minimum length
+ but include \0 to make sure that we
+ don't consider alpha and alphabet
+ equal */
+ return dns_ncompare(label_a, label_b,
+ I_MIN(ptr_a - label_a,
+ ptr_b - label_b)+1);
+ comp = dns_ncompare(label_a, label_b, ptr_a -label_a);
+ ptr_a = label_a - 1;
+ ptr_b = label_b - 1;
+ }
+
+ return dns_tolower(*label_a) - dns_tolower(*label_b);
+}
+
+int dns_match_wildcard(const char *name, const char *mask)
+{
+ i_assert(name != NULL && mask != NULL);
+
+ for(;*name != '\0' && *mask != '\0'; name++, mask++) {
+ switch(*mask) {
+ case '*':
+ name = strchr(name, '.');
+ if (name == NULL || mask[1] != '.') return -1;
+ mask++;
+ break;
+ case '?':
+ break;
+ default:
+ if (dns_tolower(*name) != dns_tolower(*mask)) return -1;
+ }
+ }
+ if (*mask == '*') mask++;
+ return dns_tolower(*name) == dns_tolower(*mask) ? 0 : -1;
+}