Oh - Here's the official path that the ISC-DHCP client takes when generating /etc/resolv.conf; It results in a new file with each DHCP reconfiguration. We should definitely not be appending, since we want to defer to whatever server search order the DHCP server is sending to us:
https://source.isc.org/cgi-bin/gitweb.cgi?p=dhcp.git;a=blob;f=client/scripts/linux;h=0c42969744e4fd0ea513f9d5516183cef207c3b4;hb=HEAD I will need to look at extending our DHCP client to import the domain name and domain search order parameters, and add those to our generated file as well - in order to be fully in tune with the official standard. I'll try to get that into the next dhcp.cc patch I send, but we'll see how that goes. :) On Wednesday, February 6, 2019 at 10:44:04 AM UTC-5, Brian Ledbetter wrote: > > Maybe there's a simpler fix - Apparently Go can be forced to use the > libc-based (or musl-based) resolver by setting the environment variable. > > GODEBUG=netdns=cgo > > Perhaps this is something we can set in our localized Go package instead? > Google's default DNS servers won't work for anyone that needs local DNS for > their systems to function - like AWS users. (And I'll note that this would > fix Go by setting reasonable defaults, but not Erlang or any other package > that depends on /etc/resolv.conf to exist.) I still like the idea of > providing an option to behave like a standard UNIX DHCP client for software > that is ancient and depends on that. But are there any other packages like > that? I'm not about to try booting Oracle under OSv ;) > > I'll suggest an additional patch that will enable this by default; It > checks for /etc/resolv.conf's existence and falls back to Cgo if it cannot > be found. Tested on this end and seems to work in both cases (with and > without resolv file). As for the kernel flag, I'm a fan of short, easily > explainable flags. I only picked --resolv since --resolv_conf was too much > typing. Happy to defer to you guys on what the "right" kernel flag for it > would be. > > I'll work on revising the dhcp.cc patch to check for errors (running on > ROFS) more thoroughly, and post that as soon as it's better. Thanks for > your patience with me! :) > > Go patch follows: > > --- ./modules/golang/go.cc~ 2019-02-06 10:21:39.769962944 -0500 > +++ ./modules/golang/go.cc 2019-02-06 10:39:55.050571909 -0500 > @@ -33,6 +33,19 @@ > extern "C" > int main(int argc, char **argv) > { > + // On environments that do not have a /etc/resolv.conf file, Go's > native > + // DNS resolver will be broken. Therefore, we need to instruct Go to > use > + // the OSv-native resolver instead. > > + // > + if( access( "/etc/resolv.conf", F_OK ) < 0 ) > + { > + // > + // File does not exist or is not readable. Revert to Cgo. > + // > + setenv( "GODEBUG", "netdns=cgo", 1 ); > + printf( "go: /etc/resolv.conf could not be found, using native > resolver\n" ); > + } > + > const std::string go_program(argv[1]); > > std::vector<std::string> go_program_arguments; > > > > > > > > On Tuesday, February 5, 2019 at 11:35:25 AM UTC-5, Waldek Kozaczuk wrote: >> >> Hi, >> >> Sorry for the long delay. >> >> Let me recap couple of things at least for my own sake of having better >> understanding of the problem. So there are two aspects around resolv.conf - >> (1) how the file is used and (2) how it constructed. As far as 1) goes >> normally apps rely on libc to resolve host names which hides existence of >> the file. In OSv case which uses musl you can see details here - >> https://wiki.musl-libc.org/functional-differences-from-glibc.html (see >> 'Names Resolver/DNS section'). Golang (and probably Erlang) are different >> and they directly use resolve.conf - I think this golang source code has >> details of the logic - >> https://github.com/golang/go/blob/9ff11b026089791c4d2bc14c17647f3cb4f4aa22/src/net/conf.go#L100 >> >> <https://www.google.com/url?q=https%3A%2F%2Fgithub.com%2Fgolang%2Fgo%2Fblob%2F9ff11b026089791c4d2bc14c17647f3cb4f4aa22%2Fsrc%2Fnet%2Fconf.go%23L100&sa=D&sntz=1&usg=AFQjCNEUFbFa_Kg259aQ2qNjJryAmtSPQg> >> . >> >> I have also found article of how resolv.conf is constructed - >> https://www.ctrl.blog/entry/resolvconf-tutorial >> <https://www.google.com/url?q=https%3A%2F%2Fwww.ctrl.blog%2Fentry%2Fresolvconf-tutorial&sa=D&sntz=1&usg=AFQjCNGCnE8q82MgWIT4b0JxMncw_KS1XQ> >> . >> >> So here is what I propose: >> 1. Make simple change to golang module to add the default resolv.conf >> (see >> https://github.com/cloudius-systems/osv-apps/blob/master/erlang/default/resolv.conf >> >> for example) which points to Google public DNS server. This would make all >> Golang apps work out of the box as far as making outgoing HTTP calls which >> we discover does not work unless resolv.conf is present. This fix is super >> trivial. >> 2. For efficiency reasons to make Golang apps use DNS server that is >> resolved as part of DHCP lookup. I agree with Brian's approach that this >> should be optional. >> >> I wonder what others think? >> >> Waldek >> >> PS. Please see my patch comments below. >> >> On Friday, January 25, 2019 at 11:27:37 AM UTC-5, Brian Ledbetter wrote: >>> >>> Here's my first stab at solving this problem in a backwards-compatible >>> way, let me know what you think. I've added a --resolv flag to the loader >>> to enable this behavior. >>> >>> Please see >> https://github.com/cloudius-systems/osv/wiki/Formatting-and-sending-patches >> for how to format and send patches to the group. Thanks. >> >>> patch-dhcp.cc: >>> >>> --- ./core/dhcp.cc~ 2019-01-25 11:18:29.173860626 -0500 >>> +++ ./core/dhcp.cc 2019-01-25 11:17:19.546083373 -0500 >>> >> I agree that dhcp.cc is the right place for this logic. >> >>> @@ -29,6 +29,12 @@ >>> #include <libc/network/__dns.hh> >>> >>> using namespace boost::asio; >>> +bool generate_resolv_conf = false; >>> + >>> +void enable_resolv_conf() >>> +{ >>> + generate_resolv_conf = true; >>> +} >>> >>> dhcp::dhcp_worker net_dhcp_worker; >>> >>> @@ -720,6 +726,31 @@ >>> }); >>> >>> osv::set_dns_config(dm.get_dns_ips(), >>> std::vector<std::string>()); >>> + >>> + // Some linux applications (go, erlang) depend on >>> /etc/resolv.conf to be >>> + // populated with DNS server information in order to >>> function. The --resolv >>> + // option has been added to the kernel loader, which will >>> enable this >>> + // feature. >>> + // >>> + // TODO: It's possible that the /etc directory does not >>> exist at this time. >>> + // We should ideally check and create it if necessary. >>> What's the right >>> + // way to do that? >>> >> Probably. What if the filesystem is read-only\? >> >>> + // >>> + // TODO: We are currently ignoring DHCP-provided default >>> domain >>> + // names. I'll have to dig further into the code to see if I >>> can ingest >>> + // those. >>> + // >>> + if( generate_resolv_conf ) >>> + { >>> + FILE *f = fopen("/etc/resolv.conf", "w+"); >>> >> Should we be appending if file already exists rather than overwrite it? >> >>> + if( f ) { >>> + fprintf( f, "## Autoconfigured by DHCP\n" ); >>> >> I think this fprintf is redundant - you are printing the result below >> anyway. >> >>> + for( auto &ip : dm.get_dns_ips() ) >>> + { >>> + fprintf( f, "server %s\n", >>> ip.to_string().c_str() ); >>> + dhcp_i( "Added DNS server: %s\n", >>> ip.to_string().c_str() ); >>> + } >>> + fclose( f ); >>> + dhcp_i( "Generated /etc/resolv.conf" ); >>> >> You could refine this message that it was generated from DHCP. >> >>> + } >>> >> Should we be handling the error of opening file and warn user that we >> could not generate the file? >> >>> + } >>> + >>> if (dm.get_hostname().size()) { >>> sethostname(dm.get_hostname().c_str(), >>> dm.get_hostname().size()); >>> dhcp_i("Set hostname to: %s", >>> dm.get_hostname().c_str()); >>> >>> >>> patch-loader.cc: >>> >>> --- ./loader.cc~ 2019-01-25 11:10:40.091359718 -0500 >>> +++ ./loader.cc 2019-01-25 11:11:40.243167695 -0500 >>> @@ -144,10 +144,13 @@ >>> bool opt_assign_net = false; >>> bool opt_maxnic = false; >>> int maxnic; >>> +static bool opt_resolv_conf = false; >>> >>> static int sampler_frequency; >>> static bool opt_enable_sampler = false; >>> >>> +void enable_resolv_conf(); >>> + >>> void parse_options(int loader_argc, char** loader_argv) >>> { >>> namespace bpo = boost::program_options; >>> @@ -182,6 +185,7 @@ >>> ("delay", bpo::value<float>()->default_value(0), "delay in >>> seconds before boot") >>> ("redirect", bpo::value<std::string>(), "redirect stdout and >>> stderr to file") >>> ("disable_rofs_cache", "disable ROFS memory cache") >>> + ("resolv", "generate an /etc/resolv.conf file with DHCP DNS >>> values (for Linux compatibility)") >>> ; >>> bpo::variables_map vars; >>> // don't allow --foo bar (require --foo=bar) so we can find the >>> first non-option >>> @@ -234,6 +238,11 @@ >>> enable_verbose(); >>> } >>> >>> + if (vars.count("resolv")) { >>> + opt_resolv_conf = true; >>> + enable_resolv_conf(); >>> + } >>> + >>> if (vars.count("sampler")) { >>> sampler_frequency = vars["sampler"].as<int>(); >>> opt_enable_sampler = true; >>> >>> >>> patch-run.py: >>> >>> --- ./scripts/run.py~ 2019-01-25 11:14:20.858654652 -0500 >>> +++ ./scripts/run.py 2019-01-25 11:14:52.406553829 -0500 >>> @@ -43,6 +43,8 @@ >>> execute = cmdline.read() >>> if options.verbose: >>> execute = "--verbose " + execute >>> + if options.resolv: >>> + execute = "--resolv " + execute >>> >> Maybe resolve_DNS? >> >>> >>> if options.jvm_debug or options.jvm_suspend: >>> if '-agentlib:jdwp' in execute: >>> @@ -461,6 +463,8 @@ >>> help="Enable graphics mode.") >>> parser.add_argument("-V", "--verbose", action="store_true", >>> help="pass --verbose to OSv, to display more >>> debugging information on the console") >>> + parser.add_argument("--resolv", action="store_true", >>> + help="pass --resolv to OSv, to generate an >>> /etc/resolv.conf file for Linux compatibility") >>> parser.add_argument("--forward", metavar="RULE", action="append", >>> default=[], >>> help="add network forwarding RULE (QEMU >>> syntax)") >>> parser.add_argument("--dry-run", action="store_true", >>> >>> >>> -- You received this message because you are subscribed to the Google Groups "OSv Development" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.
