diff --git a/options/posix/generic/lookup.cpp b/options/posix/generic/lookup.cpp index 66cf3a64d..c6526daa8 100644 --- a/options/posix/generic/lookup.cpp +++ b/options/posix/generic/lookup.cpp @@ -18,6 +18,8 @@ namespace { constexpr unsigned int RECORD_A = 1; constexpr unsigned int RECORD_CNAME = 5; constexpr unsigned int RECORD_PTR = 12; + + struct nameserver_data default_nameserver("127.0.0.1", AF_INET); } static frg::string read_dns_name(char *buf, char *&it) { @@ -86,10 +88,27 @@ int lookup_name_dns(struct lookup_result &buf, const char *name, // for dns sin.sin_port = htons(53); - auto nameserver = get_nameserver(); - if (!inet_aton(nameserver ? nameserver->name.data() : "127.0.0.1", &sin.sin_addr)) { - mlibc::infoLogger() << "lookup_name_dns(): inet_aton() failed!" << frg::endlog; - return -EAI_SYSTEM; + int nameserver_idx = 0; + while (true) { + auto nameserver = get_nameserver(nameserver_idx++); + if (!nameserver) { + // no more nameservers in resolf.conf, + // use default + if (!inet_pton(default_nameserver.af, default_nameserver.name.data(), &sin.sin_addr)) { + mlibc::infoLogger() << "lookup_name_dns(): no nameservers available!" << frg::endlog; + return -EAI_SYSTEM; + } + break; + } + + // TODO: ipv6 + if (nameserver->af != AF_INET) + continue; + + if (!inet_pton(nameserver->af, nameserver->name.data(), &sin.sin_addr)) + continue; + + break; } int fd = socket(AF_INET, SOCK_DGRAM, 0); @@ -215,10 +234,27 @@ int lookup_addr_dns(frg::span name, frg::array &addr, int fam // for dns sin.sin_port = htons(53); - auto nameserver = get_nameserver(); - if (!inet_aton(nameserver ? nameserver->name.data() : "127.0.0.1", &sin.sin_addr)) { - mlibc::infoLogger() << "lookup_name_dns(): inet_aton() failed!" << frg::endlog; - return -EAI_SYSTEM; + int nameserver_idx = 0; + while (true) { + auto nameserver = get_nameserver(nameserver_idx++); + if (!nameserver) { + // no more nameservers in resolf.conf, + // use default + if (!inet_pton(default_nameserver.af, default_nameserver.name.data(), &sin.sin_addr)) { + mlibc::infoLogger() << "lookup_addr_dns(): no nameservers available!" << frg::endlog; + return -EAI_SYSTEM; + } + break; + } + + // TODO: ipv6 + if (nameserver->af != AF_INET) + continue; + + if (!inet_pton(nameserver->af, nameserver->name.data(), &sin.sin_addr)) + continue; + + break; } int fd = socket(AF_INET, SOCK_DGRAM, 0); diff --git a/options/posix/generic/resolv_conf.cpp b/options/posix/generic/resolv_conf.cpp index a5c3aa7c8..73fbf716b 100644 --- a/options/posix/generic/resolv_conf.cpp +++ b/options/posix/generic/resolv_conf.cpp @@ -2,16 +2,20 @@ #include #include #include +#include +#include +#include namespace mlibc { -frg::optional get_nameserver() { +frg::optional get_nameserver(int idx) { auto file = fopen("/etc/resolv.conf", "r"); if (!file) return frg::null_opt; char line[128]; struct nameserver_data ret; + int cur = 0; while (fgets(line, 128, file)) { char *pos; if (!strchr(line, '\n') && !feof(file)) { @@ -20,15 +24,30 @@ frg::optional get_nameserver() { continue; } - // TODO(geert): resolv.conf can actually have multiple nameservers - // but we just pick the first one for now if (!strncmp(line, "nameserver", 10) && isspace(line[10])) { + if (cur != idx) { + cur++; + continue; + } + char *end; for (pos = line + 11; isspace(*pos); pos++); for (end = pos; *end && !isspace(*end); end++); *end = '\0'; - ret.name = frg::string( + auto str = frg::string( pos, end - pos, getAllocator()); + + + struct in_addr ipv4; + struct in6_addr ipv6; + if (inet_pton(AF_INET, str.data(), &ipv4)) + ret.af = AF_INET; + else if (inet_pton(AF_INET6, str.data(), &ipv6)) + ret.af = AF_INET6; + else + break; + + ret.name = str; break; } } diff --git a/options/posix/include/mlibc/resolv_conf.hpp b/options/posix/include/mlibc/resolv_conf.hpp index 2a349c782..6f9e2db5e 100644 --- a/options/posix/include/mlibc/resolv_conf.hpp +++ b/options/posix/include/mlibc/resolv_conf.hpp @@ -10,11 +10,15 @@ namespace mlibc { struct nameserver_data { nameserver_data() : name(getAllocator()) {} + nameserver_data(const char *name_, int af_) + : name(name_, getAllocator()), af(af_) {} + frg::string name; + int af; // for in the future we can also store options here }; -frg::optional get_nameserver(); +frg::optional get_nameserver(int idx); } // namespace mlibc