mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-09 04:15:52 +00:00
libc_lwip_nic_dhcp: provide '/etc/resolv.conf'
With this patch, the 'libc_lwip_nic_dhcp' plugin provides the DNS server address acquired by lwIP via DHCP in the file '/etc/resolv.conf'. This feature can be disabled from the config file: <libc resolv="no" /> The static network interface configuration attributes are now also a part of the '<libc>' config node: <libc ip_addr="..." netmask="..." gateway="..." /> Fixes #731.
This commit is contained in:
parent
d184599a89
commit
339a0354ce
@ -1,4 +1,4 @@
|
||||
SRC_CC = init.cc
|
||||
SRC_CC = init.cc plugin.cc
|
||||
|
||||
vpath %.cc $(REP_DIR)/src/lib/libc_lwip_nic_dhcp
|
||||
|
||||
|
@ -109,7 +109,7 @@ mimetype.assign = (
|
||||
<start name="lighttpd">
|
||||
<resource name="RAM" quantum="256M" />
|
||||
<config>
|
||||
<interface ip_addr="10.0.2.55" netmask="255.255.255.0" gateway="10.0.2.1"/>
|
||||
<libc ip_addr="10.0.2.55" netmask="255.255.255.0" gateway="10.0.2.1"/>
|
||||
<arg value="lighttpd" />
|
||||
<arg value="-f" />
|
||||
<arg value="/etc/lighttpd/lighttpd.conf" />
|
||||
|
@ -27,12 +27,15 @@ extern "C" {
|
||||
|
||||
|
||||
extern void create_lwip_plugin();
|
||||
extern void create_etc_resolv_conf_plugin();
|
||||
|
||||
|
||||
void __attribute__((constructor)) init_nic_dhcp(void)
|
||||
{
|
||||
PDBG("init_nic_dhcp()\n");
|
||||
|
||||
bool provide_etc_resolv_conf = true;
|
||||
|
||||
char ip_addr_str[16] = {0};
|
||||
char netmask_str[16] = {0};
|
||||
char gateway_str[16] = {0};
|
||||
@ -40,50 +43,57 @@ void __attribute__((constructor)) init_nic_dhcp(void)
|
||||
genode_int32_t ip_addr = 0;
|
||||
genode_int32_t netmask = 0;
|
||||
genode_int32_t gateway = 0;
|
||||
|
||||
|
||||
try {
|
||||
Genode::Xml_node interface_node = Genode::config()->xml_node().sub_node("interface");
|
||||
Genode::Xml_node libc_node = Genode::config()->xml_node().sub_node("libc");
|
||||
|
||||
try {
|
||||
interface_node.attribute("ip_addr").value(ip_addr_str, sizeof(ip_addr_str));
|
||||
}
|
||||
catch(Genode::Xml_node::Nonexistent_attribute)
|
||||
{
|
||||
PERR("Missing \"ip_addr\" attribute. Ignore interface config.");
|
||||
throw;
|
||||
}
|
||||
if (libc_node.attribute("resolv").has_value("no"))
|
||||
provide_etc_resolv_conf = false;
|
||||
} catch(...) { }
|
||||
|
||||
try {
|
||||
interface_node.attribute("netmask").value(netmask_str, sizeof(netmask_str));
|
||||
}
|
||||
catch(Genode::Xml_node::Nonexistent_attribute)
|
||||
{
|
||||
PERR("Missing \"netmask\" attribute. Ignore interface config.");
|
||||
throw;
|
||||
}
|
||||
libc_node.attribute("ip_addr").value(ip_addr_str, sizeof(ip_addr_str));
|
||||
} catch(...) { }
|
||||
|
||||
try {
|
||||
interface_node.attribute("gateway").value(gateway_str, sizeof(gateway_str));
|
||||
}
|
||||
catch(Genode::Xml_node::Nonexistent_attribute)
|
||||
{
|
||||
PERR("Missing \"gateway\" attribute. Ignore interface config.");
|
||||
throw;
|
||||
}
|
||||
|
||||
PDBG("interface: ip_addr=%s netmask=%s gateway=%s ",
|
||||
libc_node.attribute("netmask").value(netmask_str, sizeof(netmask_str));
|
||||
} catch(...) { }
|
||||
|
||||
try {
|
||||
libc_node.attribute("gateway").value(gateway_str, sizeof(gateway_str));
|
||||
} catch(...) { }
|
||||
|
||||
/* either none or all 3 interface attributes must exist */
|
||||
if ((strlen(ip_addr_str) != 0) ||
|
||||
(strlen(netmask_str) != 0) ||
|
||||
(strlen(gateway_str) != 0)) {
|
||||
if (strlen(ip_addr_str) == 0) {
|
||||
PERR("Missing \"ip_addr\" attribute. Ignoring network interface config.");
|
||||
throw Genode::Xml_node::Nonexistent_attribute();
|
||||
} else if (strlen(netmask_str) == 0) {
|
||||
PERR("Missing \"netmask\" attribute. Ignoring network interface config.");
|
||||
throw Genode::Xml_node::Nonexistent_attribute();
|
||||
} else if (strlen(gateway_str) == 0) {
|
||||
PERR("Missing \"gateway\" attribute. Ignoring network interface config.");
|
||||
throw Genode::Xml_node::Nonexistent_attribute();
|
||||
}
|
||||
} else
|
||||
throw -1;
|
||||
|
||||
PDBG("static network interface: ip_addr=%s netmask=%s gateway=%s ",
|
||||
ip_addr_str, netmask_str, gateway_str
|
||||
);
|
||||
|
||||
genode_int32_t ip, nm, gw;
|
||||
genode_uint32_t ip, nm, gw;
|
||||
|
||||
ip = inet_addr(ip_addr_str);
|
||||
nm = inet_addr(netmask_str);
|
||||
gw = inet_addr(gateway_str);
|
||||
|
||||
if (ip == INADDR_NONE || nm == INADDR_NONE || gw == INADDR_NONE) {
|
||||
PERR("Invalid interface config.");
|
||||
throw;
|
||||
PERR("Invalid network interface config.");
|
||||
throw -1;
|
||||
} else {
|
||||
ip_addr = ip;
|
||||
netmask = nm;
|
||||
@ -102,4 +112,7 @@ void __attribute__((constructor)) init_nic_dhcp(void)
|
||||
} catch (Genode::Parent::Service_denied) {
|
||||
/* ignore for now */
|
||||
}
|
||||
|
||||
if (provide_etc_resolv_conf)
|
||||
create_etc_resolv_conf_plugin();
|
||||
}
|
||||
|
234
libports/src/lib/libc_lwip_nic_dhcp/plugin.cc
Normal file
234
libports/src/lib/libc_lwip_nic_dhcp/plugin.cc
Normal file
@ -0,0 +1,234 @@
|
||||
/*
|
||||
* \brief Libc plugin providing lwIP's DNS server address in the
|
||||
* '/etc/resolv.conf' file
|
||||
* \author Christian Prochaska
|
||||
* \date 2013-05-02
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* lwip includes */
|
||||
#include <lwip/err.h>
|
||||
#include <lwip/ip_addr.h>
|
||||
#include <lwip/dns.h>
|
||||
|
||||
/* fix redefinition warnings */
|
||||
#undef LITTLE_ENDIAN
|
||||
#undef BIG_ENDIAN
|
||||
#undef BYTE_ORDER
|
||||
|
||||
/* libc plugin interface */
|
||||
#include <libc-plugin/plugin.h>
|
||||
#include <libc-plugin/fd_alloc.h>
|
||||
|
||||
/* libc includes */
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/env.h>
|
||||
#include <util/misc_math.h>
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
class Plugin_context : public Libc::Plugin_context
|
||||
{
|
||||
private:
|
||||
|
||||
int _status_flags;
|
||||
off_t _seek_offset;
|
||||
|
||||
public:
|
||||
|
||||
Plugin_context() : _status_flags(0), _seek_offset(0) { }
|
||||
|
||||
/**
|
||||
* Set/get file status status flags
|
||||
*/
|
||||
void status_flags(int flags) { _status_flags = flags; }
|
||||
int status_flags() { return _status_flags; }
|
||||
|
||||
/**
|
||||
* Set seek offset
|
||||
*/
|
||||
void seek_offset(size_t seek_offset) { _seek_offset = seek_offset; }
|
||||
|
||||
/**
|
||||
* Return seek offset
|
||||
*/
|
||||
off_t seek_offset() const { return _seek_offset; }
|
||||
|
||||
/**
|
||||
* Advance current seek position by 'incr' number of bytes
|
||||
*/
|
||||
void advance_seek_offset(size_t incr)
|
||||
{
|
||||
_seek_offset += incr;
|
||||
}
|
||||
|
||||
void infinite_seek_offset()
|
||||
{
|
||||
_seek_offset = ~0;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
static inline Plugin_context *context(Libc::File_descriptor *fd)
|
||||
{
|
||||
return static_cast<Plugin_context *>(fd->context);
|
||||
}
|
||||
|
||||
|
||||
class Plugin : public Libc::Plugin
|
||||
{
|
||||
private:
|
||||
|
||||
/**
|
||||
* File name this plugin feels responsible for
|
||||
*/
|
||||
static char const *_file_name() { return "/etc/resolv.conf"; }
|
||||
|
||||
const char *_file_content()
|
||||
{
|
||||
static char result[32];
|
||||
ip_addr_t nameserver_ip = dns_getserver(0);
|
||||
snprintf(result, sizeof(result), "nameserver %s\n",
|
||||
ipaddr_ntoa(&nameserver_ip));
|
||||
return result;
|
||||
}
|
||||
|
||||
::off_t _file_size(Libc::File_descriptor *fd)
|
||||
{
|
||||
struct stat stat_buf;
|
||||
if (fstat(fd, &stat_buf) == -1)
|
||||
return -1;
|
||||
return stat_buf.st_size;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Plugin() { }
|
||||
|
||||
bool supports_stat(const char *path)
|
||||
{
|
||||
return (Genode::strcmp(path, "/etc") == 0) ||
|
||||
(Genode::strcmp(path, _file_name()) == 0);
|
||||
}
|
||||
|
||||
bool supports_open(const char *path, int flags)
|
||||
{
|
||||
return (Genode::strcmp(path, _file_name()) == 0);
|
||||
}
|
||||
|
||||
Libc::File_descriptor *open(const char *pathname, int flags)
|
||||
{
|
||||
Plugin_context *context = new (Genode::env()->heap()) Plugin_context;
|
||||
context->status_flags(flags);
|
||||
return Libc::file_descriptor_allocator()->alloc(this, context);
|
||||
}
|
||||
|
||||
int close(Libc::File_descriptor *fd)
|
||||
{
|
||||
Genode::destroy(Genode::env()->heap(), context(fd));
|
||||
Libc::file_descriptor_allocator()->free(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int stat(const char *path, struct stat *buf)
|
||||
{
|
||||
if (buf) {
|
||||
Genode::memset(buf, 0, sizeof(struct stat));
|
||||
if (Genode::strcmp(path, "/etc") == 0)
|
||||
buf->st_mode = S_IFDIR;
|
||||
else if (Genode::strcmp(path, _file_name()) == 0) {
|
||||
buf->st_mode = S_IFREG;
|
||||
buf->st_size = strlen(_file_content()) + 1;
|
||||
} else {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fstat(Libc::File_descriptor *fd, struct stat *buf)
|
||||
{
|
||||
if (buf) {
|
||||
Genode::memset(buf, 0, sizeof(struct stat));
|
||||
buf->st_mode = S_IFREG;
|
||||
buf->st_size = strlen(_file_content()) + 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
::off_t lseek(Libc::File_descriptor *fd, ::off_t offset, int whence)
|
||||
{
|
||||
switch (whence) {
|
||||
|
||||
case SEEK_SET:
|
||||
context(fd)->seek_offset(offset);
|
||||
return offset;
|
||||
|
||||
case SEEK_CUR:
|
||||
context(fd)->advance_seek_offset(offset);
|
||||
return context(fd)->seek_offset();
|
||||
|
||||
case SEEK_END:
|
||||
if (offset != 0) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
context(fd)->infinite_seek_offset();
|
||||
return _file_size(fd);
|
||||
|
||||
default:
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t read(Libc::File_descriptor *fd, void *buf, ::size_t count)
|
||||
{
|
||||
::off_t seek_offset = context(fd)->seek_offset();
|
||||
|
||||
if (seek_offset >= _file_size(fd))
|
||||
return 0;
|
||||
|
||||
const char *content = _file_content();
|
||||
count = Genode::min((::off_t)count, _file_size(fd) - seek_offset);
|
||||
|
||||
memcpy(buf, &content[seek_offset], count);
|
||||
|
||||
context(fd)->advance_seek_offset(count);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
int fcntl(Libc::File_descriptor *fd, int cmd, long arg)
|
||||
{
|
||||
switch (cmd) {
|
||||
case F_GETFL: return context(fd)->status_flags();
|
||||
default: PERR("fcntl(): command %d not supported", cmd); return -1;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} /* unnamed namespace */
|
||||
|
||||
|
||||
void create_etc_resolv_conf_plugin()
|
||||
{
|
||||
static Plugin plugin;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user