.. | .. |
---|
1 | 1 | /* Key type used to cache DNS lookups made by the kernel |
---|
2 | 2 | * |
---|
3 | | - * See Documentation/networking/dns_resolver.txt |
---|
| 3 | + * See Documentation/networking/dns_resolver.rst |
---|
4 | 4 | * |
---|
5 | 5 | * Copyright (c) 2007 Igor Mammedov |
---|
6 | 6 | * Author(s): Igor Mammedov (niallain@gmail.com) |
---|
.. | .. |
---|
29 | 29 | #include <linux/keyctl.h> |
---|
30 | 30 | #include <linux/err.h> |
---|
31 | 31 | #include <linux/seq_file.h> |
---|
| 32 | +#include <linux/dns_resolver.h> |
---|
32 | 33 | #include <keys/dns_resolver-type.h> |
---|
33 | 34 | #include <keys/user-type.h> |
---|
34 | 35 | #include "internal.h" |
---|
.. | .. |
---|
48 | 49 | /* |
---|
49 | 50 | * Preparse instantiation data for a dns_resolver key. |
---|
50 | 51 | * |
---|
51 | | - * The data must be a NUL-terminated string, with the NUL char accounted in |
---|
52 | | - * datalen. |
---|
| 52 | + * For normal hostname lookups, the data must be a NUL-terminated string, with |
---|
| 53 | + * the NUL char accounted in datalen. |
---|
53 | 54 | * |
---|
54 | 55 | * If the data contains a '#' characters, then we take the clause after each |
---|
55 | 56 | * one to be an option of the form 'key=value'. The actual data of interest is |
---|
56 | 57 | * the string leading up to the first '#'. For instance: |
---|
57 | 58 | * |
---|
58 | 59 | * "ip1,ip2,...#foo=bar" |
---|
| 60 | + * |
---|
| 61 | + * For server list requests, the data must begin with a NUL char and be |
---|
| 62 | + * followed by a byte indicating the version of the data format. Version 1 |
---|
| 63 | + * looks something like (note this is packed): |
---|
| 64 | + * |
---|
| 65 | + * u8 Non-string marker (ie. 0) |
---|
| 66 | + * u8 Content (DNS_PAYLOAD_IS_*) |
---|
| 67 | + * u8 Version (e.g. 1) |
---|
| 68 | + * u8 Source of server list |
---|
| 69 | + * u8 Lookup status of server list |
---|
| 70 | + * u8 Number of servers |
---|
| 71 | + * foreach-server { |
---|
| 72 | + * __le16 Name length |
---|
| 73 | + * __le16 Priority (as per SRV record, low first) |
---|
| 74 | + * __le16 Weight (as per SRV record, higher first) |
---|
| 75 | + * __le16 Port |
---|
| 76 | + * u8 Source of address list |
---|
| 77 | + * u8 Lookup status of address list |
---|
| 78 | + * u8 Protocol (DNS_SERVER_PROTOCOL_*) |
---|
| 79 | + * u8 Number of addresses |
---|
| 80 | + * char[] Name (not NUL-terminated) |
---|
| 81 | + * foreach-address { |
---|
| 82 | + * u8 Family (DNS_ADDRESS_IS_*) |
---|
| 83 | + * union { |
---|
| 84 | + * u8[4] ipv4_addr |
---|
| 85 | + * u8[16] ipv6_addr |
---|
| 86 | + * } |
---|
| 87 | + * } |
---|
| 88 | + * } |
---|
| 89 | + * |
---|
59 | 90 | */ |
---|
60 | 91 | static int |
---|
61 | 92 | dns_resolver_preparse(struct key_preparsed_payload *prep) |
---|
62 | 93 | { |
---|
| 94 | + const struct dns_payload_header *bin; |
---|
63 | 95 | struct user_key_payload *upayload; |
---|
64 | 96 | unsigned long derrno; |
---|
65 | 97 | int ret; |
---|
66 | 98 | int datalen = prep->datalen, result_len = 0; |
---|
67 | 99 | const char *data = prep->data, *end, *opt; |
---|
68 | 100 | |
---|
| 101 | + if (datalen <= 1 || !data) |
---|
| 102 | + return -EINVAL; |
---|
| 103 | + |
---|
| 104 | + if (data[0] == 0) { |
---|
| 105 | + /* It may be a server list. */ |
---|
| 106 | + if (datalen <= sizeof(*bin)) |
---|
| 107 | + return -EINVAL; |
---|
| 108 | + |
---|
| 109 | + bin = (const struct dns_payload_header *)data; |
---|
| 110 | + kenter("[%u,%u],%u", bin->content, bin->version, datalen); |
---|
| 111 | + if (bin->content != DNS_PAYLOAD_IS_SERVER_LIST) { |
---|
| 112 | + pr_warn_ratelimited( |
---|
| 113 | + "dns_resolver: Unsupported content type (%u)\n", |
---|
| 114 | + bin->content); |
---|
| 115 | + return -EINVAL; |
---|
| 116 | + } |
---|
| 117 | + |
---|
| 118 | + if (bin->version != 1) { |
---|
| 119 | + pr_warn_ratelimited( |
---|
| 120 | + "dns_resolver: Unsupported server list version (%u)\n", |
---|
| 121 | + bin->version); |
---|
| 122 | + return -EINVAL; |
---|
| 123 | + } |
---|
| 124 | + |
---|
| 125 | + result_len = datalen; |
---|
| 126 | + goto store_result; |
---|
| 127 | + } |
---|
| 128 | + |
---|
69 | 129 | kenter("'%*.*s',%u", datalen, datalen, data, datalen); |
---|
70 | 130 | |
---|
71 | | - if (datalen <= 1 || !data || data[datalen - 1] != '\0') |
---|
| 131 | + if (!data || data[datalen - 1] != '\0') |
---|
72 | 132 | return -EINVAL; |
---|
73 | 133 | datalen--; |
---|
74 | 134 | |
---|
.. | .. |
---|
144 | 204 | return 0; |
---|
145 | 205 | } |
---|
146 | 206 | |
---|
| 207 | +store_result: |
---|
147 | 208 | kdebug("store result"); |
---|
148 | 209 | prep->quotalen = result_len; |
---|
149 | 210 | |
---|
.. | .. |
---|
253 | 314 | |
---|
254 | 315 | struct key_type key_type_dns_resolver = { |
---|
255 | 316 | .name = "dns_resolver", |
---|
| 317 | + .flags = KEY_TYPE_NET_DOMAIN, |
---|
256 | 318 | .preparse = dns_resolver_preparse, |
---|
257 | 319 | .free_preparse = dns_resolver_free_preparse, |
---|
258 | 320 | .instantiate = generic_key_instantiate, |
---|