/* 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; }