]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
dns-domain: add dns_name_to_wire_format()
authorBeniamino Galvani <bgalvani@redhat.com>
Mon, 16 Nov 2015 16:35:50 +0000 (17:35 +0100)
committerBeniamino Galvani <bgalvani@redhat.com>
Tue, 17 Nov 2015 14:06:01 +0000 (15:06 +0100)
The function converts a domain name string to the wire format
described in RFC 1035 Section 3.1.

src/shared/dns-domain.c
src/shared/dns-domain.h
src/test/test-dns-domain.c

index 7af15e00984e077f3a27cb35912b98749f2973ea..423ccca9cc99c7ca3252e888e25a76357c5f47d7 100644 (file)
@@ -715,3 +715,37 @@ int dns_name_single_label(const char *name) {
 
         return r == 0 && *name == 0;
 }
+
+/* Encode a domain name according to RFC 1035 Section 3.1 */
+int dns_name_to_wire_format(const char *domain, uint8_t *buffer, size_t len) {
+        uint8_t *label_length;
+        uint8_t *out;
+        int r;
+
+        assert_return(buffer, -EINVAL);
+        assert_return(domain, -EINVAL);
+        assert_return(domain[0], -EINVAL);
+
+        out = buffer;
+
+        do {
+                /* reserve a byte for label length */
+                if (len == 0)
+                        return -ENOBUFS;
+                len--;
+                label_length = out;
+                out++;
+
+                /* convert and copy a single label */
+                r = dns_label_unescape(&domain, (char *) out, len);
+                if (r < 0)
+                        return r;
+
+                /* fill label length, move forward */
+                *label_length = r;
+                out += r;
+                len -= r;
+        } while (r != 0);
+
+        return out - buffer;
+}
index 1f0d242c18bb0e5aecde3aba12a4e2a5f571ac26..b2148974409678398f9d962a73837b9ab80b5599 100644 (file)
@@ -67,3 +67,5 @@ int dns_name_address(const char *p, int *family, union in_addr_union *a);
 
 int dns_name_root(const char *name);
 int dns_name_single_label(const char *name);
+
+int dns_name_to_wire_format(const char *domain, uint8_t *buffer, size_t len);
index d5778748a05036722f3a8bb1a0197880d310adc4..407c7d8ef792a736443d61c4302b06bfc2502160 100644 (file)
@@ -52,6 +52,36 @@ static void test_dns_label_unescape(void) {
         test_dns_label_unescape_one("foobar.", "foobar", 20, 6);
 }
 
+static void test_dns_name_to_wire_format_one(const char *what, const char *expect, size_t buffer_sz, int ret) {
+        uint8_t buffer[buffer_sz];
+        int r;
+
+        r = dns_name_to_wire_format(what, buffer, buffer_sz);
+        assert_se(r == ret);
+
+        if (r < 0)
+                return;
+
+        assert_se(!memcmp(buffer, expect, r));
+}
+
+static void test_dns_name_to_wire_format(void) {
+        const char out1[] = { 3, 'f', 'o', 'o', 0 };
+        const char out2[] = { 5, 'h', 'a', 'l', 'l', 'o', 3, 'f', 'o', 'o', 3, 'b', 'a', 'r', 0 };
+        const char out3[] = { 4, ' ', 'f', 'o', 'o', 3, 'b', 'a', 'r', 0 };
+
+        test_dns_name_to_wire_format_one("", NULL, 0, -EINVAL);
+
+        test_dns_name_to_wire_format_one("foo", out1, sizeof(out1), sizeof(out1));
+        test_dns_name_to_wire_format_one("foo", out1, sizeof(out1) + 1, sizeof(out1));
+        test_dns_name_to_wire_format_one("foo", out1, sizeof(out1) - 1, -ENOBUFS);
+
+        test_dns_name_to_wire_format_one("hallo.foo.bar", out2, sizeof(out2), sizeof(out2));
+        test_dns_name_to_wire_format_one("hallo.foo..bar", NULL, 32, -EINVAL);
+
+        test_dns_name_to_wire_format_one("\\032foo.bar", out3, sizeof(out3), sizeof(out3));
+}
+
 static void test_dns_label_unescape_suffix_one(const char *what, const char *expect1, const char *expect2, size_t buffer_sz, int ret1, int ret2) {
         char buffer[buffer_sz];
         const char *label;
@@ -300,6 +330,7 @@ int main(int argc, char *argv[]) {
         test_dns_name_reverse();
         test_dns_name_concat();
         test_dns_name_is_valid();
+        test_dns_name_to_wire_format();
 
         return 0;
 }