options/posix: parse CNAME DNS record
This commit is contained in:
parent
1729680c1f
commit
05018a7921
|
@ -14,6 +14,11 @@
|
|||
|
||||
namespace mlibc {
|
||||
|
||||
namespace {
|
||||
constexpr unsigned int RECORD_A = 1;
|
||||
constexpr unsigned int RECORD_CNAME = 5;
|
||||
}
|
||||
|
||||
static frg::string<MemoryAllocator> read_dns_name(char *buf, char *&it) {
|
||||
frg::string<MemoryAllocator> res{getAllocator()};
|
||||
while (true) {
|
||||
|
@ -40,7 +45,8 @@ static frg::string<MemoryAllocator> read_dns_name(char *buf, char *&it) {
|
|||
return res;
|
||||
}
|
||||
|
||||
int lookup_name_dns(frg::vector<struct dns_addr_buf, MemoryAllocator> &buf, const char *name) {
|
||||
int lookup_name_dns(struct lookup_result &buf, const char *name,
|
||||
frg::string<MemoryAllocator> &canon_name) {
|
||||
frg::string<MemoryAllocator> request{getAllocator()};
|
||||
|
||||
int num_q = 1;
|
||||
|
@ -118,19 +124,29 @@ int lookup_name_dns(frg::vector<struct dns_addr_buf, MemoryAllocator> &buf, cons
|
|||
for (int i = 0; i < ntohs(response_header->no_ans); i++) {
|
||||
struct dns_addr_buf buffer;
|
||||
auto dns_name = read_dns_name(response, it);
|
||||
buffer.name = std::move(dns_name);
|
||||
|
||||
uint16_t rr_type = (it[0] << 8) | it[1];
|
||||
uint16_t rr_class = (it[2] << 8) | it[3];
|
||||
uint16_t rr_length = (it[8] << 8) | it[9];
|
||||
it += 10;
|
||||
|
||||
if (rr_type == 1) {
|
||||
memcpy(buffer.addr, it, rr_length);
|
||||
buffer.family = AF_INET;
|
||||
buf.push_back(std::move(buffer));
|
||||
switch (rr_type) {
|
||||
case RECORD_A:
|
||||
memcpy(buffer.addr, it, rr_length);
|
||||
it += rr_length;
|
||||
buffer.family = AF_INET;
|
||||
buffer.name = std::move(dns_name);
|
||||
buf.buf.push(std::move(buffer));
|
||||
break;
|
||||
case RECORD_CNAME:
|
||||
canon_name = std::move(read_dns_name(response, it));
|
||||
buf.aliases.push(std::move(dns_name));
|
||||
break;
|
||||
default:
|
||||
mlibc::infoLogger() << "lookup_name_dns: unknown rr type "
|
||||
<< rr_type << frg::endlog;
|
||||
break;
|
||||
}
|
||||
it += rr_length;
|
||||
}
|
||||
num_ans += ntohs(response_header->no_ans);
|
||||
|
||||
|
@ -139,10 +155,10 @@ int lookup_name_dns(frg::vector<struct dns_addr_buf, MemoryAllocator> &buf, cons
|
|||
}
|
||||
|
||||
close(fd);
|
||||
return buf.size();
|
||||
return buf.buf.size();
|
||||
}
|
||||
|
||||
int lookup_name_hosts(frg::vector<struct dns_addr_buf, MemoryAllocator> &buf, const char *name,
|
||||
int lookup_name_hosts(struct lookup_result &buf, const char *name,
|
||||
frg::string<MemoryAllocator> &canon_name) {
|
||||
auto file = fopen("/etc/hosts", "r");
|
||||
if (!file) {
|
||||
|
@ -189,24 +205,23 @@ int lookup_name_hosts(frg::vector<struct dns_addr_buf, MemoryAllocator> &buf, co
|
|||
buffer.family = AF_INET;
|
||||
buffer.name = frg::string<MemoryAllocator>{pos,
|
||||
static_cast<size_t>(end - pos), getAllocator()};
|
||||
if (!canon_name.size())
|
||||
canon_name = buffer.name;
|
||||
canon_name = buffer.name;
|
||||
|
||||
buf.push(std::move(buffer));
|
||||
buf.buf.push(std::move(buffer));
|
||||
|
||||
pos = end;
|
||||
while (pos[1]) {
|
||||
for (; *pos && isspace(*pos); pos++);
|
||||
for (end = pos; *end && !isspace(*end); end++);
|
||||
buffer.name = frg::string<MemoryAllocator>{pos,
|
||||
auto name = frg::string<MemoryAllocator>{pos,
|
||||
static_cast<size_t>(end - pos), getAllocator()};
|
||||
buf.push(std::move(buffer));
|
||||
buf.aliases.push(std::move(name));
|
||||
pos = end;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
return buf.size();
|
||||
return buf.buf.size();
|
||||
}
|
||||
|
||||
} // namespace mlibc
|
||||
|
|
|
@ -66,12 +66,12 @@ int getaddrinfo(const char *__restrict node, const char *__restrict service,
|
|||
if (serv_count < 0)
|
||||
return -serv_count;
|
||||
|
||||
frg::vector<struct mlibc::dns_addr_buf, MemoryAllocator> addr_buf(getAllocator());
|
||||
struct mlibc::lookup_result addr_buf;
|
||||
int addr_count = 1;
|
||||
frg::string<MemoryAllocator> canon{getAllocator()};
|
||||
if (node) {
|
||||
if ((addr_count = mlibc::lookup_name_hosts(addr_buf, node, canon)) <= 0)
|
||||
addr_count = mlibc::lookup_name_dns(addr_buf, node);
|
||||
addr_count = mlibc::lookup_name_dns(addr_buf, node, canon);
|
||||
else
|
||||
addr_count = 1;
|
||||
if (addr_count < 0)
|
||||
|
@ -83,32 +83,30 @@ int getaddrinfo(const char *__restrict node, const char *__restrict service,
|
|||
auto out = (struct mlibc::ai_buf *) calloc(serv_count * addr_count,
|
||||
sizeof(struct addrinfo));
|
||||
|
||||
if (node && !canon.size()) {
|
||||
//TODO(geert): this should be part of lookup_name_dns()
|
||||
if (node && !canon.size())
|
||||
canon = frg::string<MemoryAllocator>{node, getAllocator()};
|
||||
}
|
||||
|
||||
for (int i = 0, k = 0; i < addr_count; i++) {
|
||||
for (int j = 0; j < serv_count; j++, k++) {
|
||||
out[i].ai.ai_family = addr_buf[i].family;
|
||||
out[i].ai.ai_family = addr_buf.buf[i].family;
|
||||
out[i].ai.ai_socktype = serv_buf[j].socktype;
|
||||
out[i].ai.ai_protocol = serv_buf[j].protocol;
|
||||
out[i].ai.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG;
|
||||
out[i].ai.ai_addr = (struct sockaddr *) &out[i].sa;
|
||||
out[i].ai.ai_canonname = canon.data();
|
||||
out[i].ai.ai_next = NULL;
|
||||
switch (addr_buf[i].family) {
|
||||
switch (addr_buf.buf[i].family) {
|
||||
case AF_INET:
|
||||
out[i].ai.ai_addrlen = sizeof(struct sockaddr_in);
|
||||
out[i].sa.sin.sin_port = serv_buf[j].port;
|
||||
out[i].sa.sin.sin_family = AF_INET;
|
||||
memcpy(&out[i].sa.sin.sin_addr, addr_buf[i].addr, 4);
|
||||
memcpy(&out[i].sa.sin.sin_addr, addr_buf.buf[i].addr, 4);
|
||||
break;
|
||||
case AF_INET6:
|
||||
out[i].ai.ai_addrlen = sizeof(struct sockaddr_in6);
|
||||
out[i].sa.sin6.sin6_family = serv_buf[j].port;
|
||||
out[i].sa.sin6.sin6_family = AF_INET6;
|
||||
memcpy(&out[i].sa.sin6.sin6_addr, addr_buf[i].addr, 16);
|
||||
memcpy(&out[i].sa.sin6.sin6_addr, addr_buf.buf[i].addr, 16);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -151,11 +149,11 @@ struct hostent *gethostbyname(const char *name) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
frg::vector<struct mlibc::dns_addr_buf, MemoryAllocator> buf(getAllocator());
|
||||
struct mlibc::lookup_result buf;
|
||||
frg::string<MemoryAllocator> canon{getAllocator()};
|
||||
int ret = 0;
|
||||
if ((ret = mlibc::lookup_name_hosts(buf, name, canon)) <= 0)
|
||||
ret = mlibc::lookup_name_dns(buf, name);
|
||||
ret = mlibc::lookup_name_dns(buf, name, canon);
|
||||
if (ret <= 0) {
|
||||
h_errno = HOST_NOT_FOUND;
|
||||
return NULL;
|
||||
|
@ -181,14 +179,10 @@ struct hostent *gethostbyname(const char *name) {
|
|||
|
||||
h.h_name = canon.data();
|
||||
|
||||
h.h_aliases = reinterpret_cast<char**>(malloc((ret + 1) * sizeof(char*)));
|
||||
h.h_aliases = reinterpret_cast<char**>(malloc((buf.aliases.size() + 1)
|
||||
* sizeof(char*)));
|
||||
int alias_pos = 0;
|
||||
for (int i = 0; i < ret; i++) {
|
||||
auto &buf_name = buf[i].name;
|
||||
if (buf_name == canon)
|
||||
continue;
|
||||
|
||||
// we have found an entry that is an alias
|
||||
for (auto &buf_name : buf.aliases) {
|
||||
h.h_aliases[alias_pos] = buf_name.data();
|
||||
buf_name.detach();
|
||||
alias_pos++;
|
||||
|
@ -197,7 +191,7 @@ struct hostent *gethostbyname(const char *name) {
|
|||
canon.detach();
|
||||
|
||||
// just pick the first family as the one for all addresses...??
|
||||
h.h_addrtype = buf[0].family;
|
||||
h.h_addrtype = buf.buf[0].family;
|
||||
if (h.h_addrtype != AF_INET && h.h_addrtype != AF_INET6) {
|
||||
// this is not allowed per spec
|
||||
h_errno = NO_DATA;
|
||||
|
@ -209,10 +203,10 @@ struct hostent *gethostbyname(const char *name) {
|
|||
h.h_addr_list = reinterpret_cast<char**>(malloc((ret + 1) * sizeof(char*)));
|
||||
int addr_pos = 0;
|
||||
for (int i = 0; i < ret; i++) {
|
||||
if (buf[i].family != h.h_addrtype)
|
||||
if (buf.buf[i].family != h.h_addrtype)
|
||||
continue;
|
||||
h.h_addr_list[addr_pos] = reinterpret_cast<char*>(malloc(h.h_length));
|
||||
memcpy(h.h_addr_list[addr_pos], buf[i].addr, h.h_length);
|
||||
memcpy(h.h_addr_list[addr_pos], buf.buf[i].addr, h.h_length);
|
||||
addr_pos++;
|
||||
}
|
||||
h.h_addr_list[addr_pos] = NULL;
|
||||
|
|
|
@ -11,13 +11,20 @@
|
|||
namespace mlibc {
|
||||
|
||||
struct dns_addr_buf {
|
||||
dns_addr_buf() : name(getAllocator())
|
||||
{}
|
||||
dns_addr_buf()
|
||||
: name(getAllocator()) {}
|
||||
frg::string<MemoryAllocator> name;
|
||||
int family;
|
||||
uint8_t addr[16];
|
||||
};
|
||||
|
||||
struct lookup_result {
|
||||
lookup_result()
|
||||
: buf(getAllocator()), aliases(getAllocator()) {}
|
||||
frg::vector<struct dns_addr_buf, MemoryAllocator> buf;
|
||||
frg::vector<frg::string<MemoryAllocator>, MemoryAllocator> aliases;
|
||||
};
|
||||
|
||||
struct dns_header {
|
||||
uint16_t identification;
|
||||
uint16_t flags;
|
||||
|
@ -35,8 +42,9 @@ struct ai_buf {
|
|||
} sa;
|
||||
};
|
||||
|
||||
int lookup_name_dns(frg::vector<struct dns_addr_buf, MemoryAllocator> &buf, const char *name);
|
||||
int lookup_name_hosts(frg::vector<struct dns_addr_buf, MemoryAllocator> &buf, const char *name,
|
||||
int lookup_name_dns(struct lookup_result &buf, const char *name,
|
||||
frg::string<MemoryAllocator> &canon_name);
|
||||
int lookup_name_hosts(struct lookup_result &buf, const char *name,
|
||||
frg::string<MemoryAllocator> &canon_name);
|
||||
|
||||
} // namespace mlibc
|
||||
|
|
Loading…
Reference in a new issue