1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2024-10-28 11:55:23 +03:00

dhcp6-option: Add helper function for uncompressed domain names

Add a helper function containing a modified version of dns_packet_read_name()
that does not use DnsPacket to extract a string array of domain names from
the provided option data. The domain names are stored uncompressed as defined
in Section 8. of RFC 3315.
This commit is contained in:
Patrik Flykt 2015-05-04 13:23:46 +03:00
parent b553817ccf
commit f96ccab7e0
2 changed files with 84 additions and 0 deletions

View File

@ -71,6 +71,8 @@ int dhcp6_option_parse_ia(uint8_t **buf, size_t *buflen, uint16_t iatype,
int dhcp6_option_parse_ip6addrs(uint8_t *optval, uint16_t optlen,
struct in6_addr **addrs, size_t count,
size_t *allocated);
int dhcp6_option_parse_domainname(const uint8_t *optval, uint16_t optlen,
char ***str_arr);
int dhcp6_network_bind_udp_socket(int index, struct in6_addr *address);
int dhcp6_network_send_udp_socket(int s, struct in6_addr *address,

View File

@ -26,9 +26,11 @@
#include "sparse-endian.h"
#include "unaligned.h"
#include "util.h"
#include "strv.h"
#include "dhcp6-internal.h"
#include "dhcp6-protocol.h"
#include "dns-domain.h"
#define DHCP6_OPTION_IA_NA_LEN 12
#define DHCP6_OPTION_IA_TA_LEN 4
@ -335,3 +337,83 @@ int dhcp6_option_parse_ip6addrs(uint8_t *optval, uint16_t optlen,
return count;
}
int dhcp6_option_parse_domainname(const uint8_t *optval, uint16_t optlen,
char ***str_arr)
{
size_t pos = 0, idx = 0;
_cleanup_free_ char **names = NULL;
int r;
assert_return(optlen > 1, -ENODATA);
assert_return(optval[optlen] == '\0', -EINVAL);
while (pos < optlen) {
_cleanup_free_ char *ret = NULL;
size_t n = 0, allocated = 0;
bool first = true;
for (;;) {
uint8_t c;
c = optval[pos++];
if (c == 0)
/* End of name */
break;
else if (c <= 63) {
_cleanup_free_ char *t = NULL;
const char *label;
/* Literal label */
label = (const char *)&optval[pos];
pos += c;
if (pos > optlen)
return -EMSGSIZE;
r = dns_label_escape(label, c, &t);
if (r < 0)
goto fail;
if (!GREEDY_REALLOC0(ret, allocated, n + !first + strlen(t) + 1)) {
r = -ENOMEM;
goto fail;
}
if (!first)
ret[n++] = '.';
else
first = false;
memcpy(ret + n, t, r);
n += r;
continue;
} else {
r = -EBADMSG;
goto fail;
}
}
if (!GREEDY_REALLOC(ret, allocated, n + 1)) {
r = -ENOMEM;
goto fail;
}
ret[n] = 0;
r = strv_extend(&names, ret);
if (r < 0)
goto fail;
ret = NULL;
idx++;
}
*str_arr = names;
names = NULL;
return idx;
fail:
return r;
}