#include <stdint.h>
#include <string.h>
#include <stdlib.h>
+#include <errno.h>
#include <sys/socket.h>
#include <linux/if.h>
#include <linux/netlink.h>
#include <pb-config/pb-config.h>
#include <system/system.h>
+#include "file.h"
#include "network.h"
#define HWADDR_SIZE 6
bool dry_run;
};
-static const struct network_config *find_config_by_hwaddr(
+static const struct interface_config *find_config_by_hwaddr(
uint8_t *hwaddr)
{
const struct config *config;
if (!config)
return NULL;
- for (i = 0; i < config->n_network_configs; i++) {
- struct network_config *netconf = config->network_configs[i];
+ for (i = 0; i < config->network.n_interfaces; i++) {
+ struct interface_config *ifconf = config->network.interfaces[i];
- if (!memcmp(netconf->hwaddr, hwaddr, HWADDR_SIZE))
- return netconf;
+ if (!memcmp(ifconf->hwaddr, hwaddr, HWADDR_SIZE))
+ return ifconf;
}
return NULL;
return 0;
}
-static int interface_up(struct network *network, struct interface *interface)
+static int interface_change(struct network *network,
+ struct interface *interface,
+ bool up)
{
int rc;
+ const char *statestr = up ? "up" : "down";
const char *argv[] = {
pb_system_apps.ip,
"link",
"set",
interface->name,
- "up",
+ statestr,
NULL,
};
rc = pb_run_cmd(argv, 1, network->dry_run);
if (rc) {
- pb_log("failed to bring interface %s up\n", interface->name);
+ pb_log("failed to bring interface %s %s\n", interface->name,
+ statestr);
return -1;
}
return 0;
}
+static int interface_up(struct network *network,
+ struct interface *interface)
+{
+ return interface_change(network, interface, true);
+}
+
+static int interface_down(struct network *network,
+ struct interface *interface)
+{
+ return interface_change(network, interface, false);
+}
+
static void configure_interface_dhcp(struct network *network,
struct interface *interface)
{
static void configure_interface_static(struct network *network,
struct interface *interface,
- const struct network_config *config)
+ const struct interface_config *config)
{
const char *addr_argv[] = {
pb_system_apps.ip,
static void configure_interface(struct network *network,
struct interface *interface, bool up, bool link)
{
- const struct network_config *config = NULL;
+ const struct interface_config *config = NULL;
if (interface->state == IFSTATE_IGNORED)
return;
return 0;
}
+static void network_init_dns(struct network *network)
+{
+ const struct config *config;
+ int i, rc, len;
+ bool modified;
+ char *buf;
+
+ if (network->dry_run)
+ return;
+
+ config = config_get();
+ if (!config || !config->network.n_dns_servers)
+ return;
+
+ rc = read_file(network, "/etc/resolv.conf", &buf, &len);
+
+ if (rc) {
+ buf = talloc_strdup(network, "");
+ len = 0;
+ }
+
+ modified = false;
+
+ for (i = 0; i < config->network.n_dns_servers; i++) {
+ int dns_conf_len;
+ char *dns_conf;
+
+ dns_conf = talloc_asprintf(network, "nameserver %s\n",
+ config->network.dns_servers[i]);
+
+ if (strstr(buf, dns_conf)) {
+ talloc_free(dns_conf);
+ continue;
+ }
+
+ dns_conf_len = strlen(dns_conf);
+ buf = talloc_realloc(network, buf, char, len + dns_conf_len);
+ memcpy(buf + len, dns_conf, dns_conf_len);
+ len += dns_conf_len;
+ modified = true;
+
+ talloc_free(dns_conf);
+ }
+
+ if (modified) {
+ rc = replace_file("/etc/resolv.conf", buf, len);
+ if (rc)
+ pb_log("error replacing resolv.conf: %s\n",
+ strerror(errno));
+ }
+
+ talloc_free(buf);
+}
+
struct network *network_init(void *ctx, struct waitset *waitset, bool dry_run)
{
struct network *network;
network->manual_config = false;
network->dry_run = dry_run;
+ network_init_dns(network);
+
rc = network_init_netlink(network);
if (rc)
goto err;
int network_shutdown(struct network *network)
{
+ struct interface *interface;
+
if (network->waiter)
waiter_remove(network->waiter);
+ list_for_each_entry(&network->interfaces, interface, list)
+ interface_down(network, interface);
+
close(network->netlink_sd);
talloc_free(network);
return 0;