} else
return -EINVAL;
- } else if (*n >= ' ' && *n != 127) {
+ } else if ((uint8_t) *n >= (uint8_t) ' ' && *n != 127) {
/* Normal character */
*(d++) = *(n++);
/* Proper character */
*(q++) = *p;
- } else if (*p >= ' ' && *p != 127) {
+ } else if ((uint8_t) *p >= (uint8_t) ' ' && *p != 127) {
/* Everything else */
*(q++) = '\\';
- *(q++) = '0' + (char) ((unsigned) *p / 100);
- *(q++) = '0' + (char) (((unsigned) *p / 10) % 10);
- *(q++) = '0' + (char) ((unsigned) *p % 10);
+ *(q++) = '0' + (char) ((uint8_t) *p / 100);
+ *(q++) = '0' + (char) (((uint8_t) *p / 10) % 10);
+ *(q++) = '0' + (char) ((uint8_t) *p % 10);
} else
return -EINVAL;
int r;
assert(s);
- assert(_ret);
for (;;) {
_cleanup_free_ char *t = NULL;
n += r;
}
+ if (n > DNS_NAME_MAX)
+ return -EINVAL;
+
if (!GREEDY_REALLOC(ret, allocated, n + 1))
return -ENOMEM;
ret[n] = 0;
- *_ret = ret;
- ret = NULL;
+
+ if (_ret) {
+ *_ret = ret;
+ ret = NULL;
+ }
return 0;
}
unsigned long dns_name_hash_func(const void *s, const uint8_t hash_key[HASH_KEY_SIZE]) {
const char *p = s;
- unsigned long ul = 0;
+ unsigned long ul = hash_key[0];
int r;
assert(p);
label[r] = 0;
ascii_strlower(label);
- ul = hash_key[0] * ul + ul + string_hash_func(label, hash_key);
+ ul = ul * hash_key[1] + ul + string_hash_func(label, hash_key);
}
return ul;
return 0;
}
+int dns_name_address(const char *p, int *family, union in_addr_union *address) {
+ int r;
+
+ assert(p);
+ assert(family);
+ assert(address);
+
+ r = dns_name_endswith(p, "in-addr.arpa");
+ if (r < 0)
+ return r;
+ if (r > 0) {
+ uint8_t a[4];
+ unsigned i;
+
+ for (i = 0; i < ELEMENTSOF(a); i++) {
+ char label[DNS_LABEL_MAX+1];
+
+ r = dns_label_unescape(&p, label, sizeof(label));
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return -EINVAL;
+ if (r > 3)
+ return -EINVAL;
+
+ r = safe_atou8(label, &a[i]);
+ if (r < 0)
+ return r;
+ }
+
+ r = dns_name_equal(p, "in-addr.arpa");
+ if (r <= 0)
+ return r;
+
+ *family = AF_INET;
+ address->in.s_addr = htobe32(((uint32_t) a[3] << 24) |
+ ((uint32_t) a[2] << 16) |
+ ((uint32_t) a[1] << 8) |
+ (uint32_t) a[0]);
+
+ return 1;
+ }
+
+ r = dns_name_endswith(p, "ip6.arpa");
+ if (r < 0)
+ return r;
+ if (r > 0) {
+ struct in6_addr a;
+ unsigned i;
+
+ for (i = 0; i < ELEMENTSOF(a.s6_addr); i++) {
+ char label[DNS_LABEL_MAX+1];
+ int x, y;
+
+ r = dns_label_unescape(&p, label, sizeof(label));
+ if (r <= 0)
+ return r;
+ if (r != 1)
+ return -EINVAL;
+ x = unhexchar(label[0]);
+ if (x < 0)
+ return -EINVAL;
+
+ r = dns_label_unescape(&p, label, sizeof(label));
+ if (r <= 0)
+ return r;
+ if (r != 1)
+ return -EINVAL;
+ y = unhexchar(label[0]);
+ if (y < 0)
+ return -EINVAL;
+
+ a.s6_addr[ELEMENTSOF(a.s6_addr) - i - 1] = (uint8_t) y << 4 | (uint8_t) x;
+ }
+
+ r = dns_name_equal(p, "ip6.arpa");
+ if (r <= 0)
+ return r;
+
+ *family = AF_INET6;
+ address->in6 = a;
+ return 1;
+ }
+
+ return 0;
+}
+
int dns_name_root(const char *name) {
char label[DNS_LABEL_MAX+1];
int r;
r = dns_label_unescape(&name, label, sizeof(label));
if (r < 0)
return r;
-
if (r == 0)
return 0;