networkd-network.c revision a9bc6d2df16c1d9f8a99d2cc9be2babf62bd173f
e2417e4143bb892e4599b01de7b031763421bb64Daniel J Walsh/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
e2417e4143bb892e4599b01de7b031763421bb64Daniel J Walsh
cad45ba11ec3572296361f53f5852ffb97a97fa3Lennart Poettering/***
e2417e4143bb892e4599b01de7b031763421bb64Daniel J Walsh This file is part of systemd.
e2417e4143bb892e4599b01de7b031763421bb64Daniel J Walsh
e2417e4143bb892e4599b01de7b031763421bb64Daniel J Walsh Copyright 2013 Tom Gundersen <teg@jklm.no>
e2417e4143bb892e4599b01de7b031763421bb64Daniel J Walsh
e2417e4143bb892e4599b01de7b031763421bb64Daniel J Walsh systemd is free software; you can redistribute it and/or modify it
e2417e4143bb892e4599b01de7b031763421bb64Daniel J Walsh under the terms of the GNU Lesser General Public License as published by
e2417e4143bb892e4599b01de7b031763421bb64Daniel J Walsh the Free Software Foundation; either version 2.1 of the License, or
03e22642617f360a6b55cb853bcf59604754ea5dKay Sievers (at your option) any later version.
03e22642617f360a6b55cb853bcf59604754ea5dKay Sievers
e2417e4143bb892e4599b01de7b031763421bb64Daniel J Walsh systemd is distributed in the hope that it will be useful, but
e2417e4143bb892e4599b01de7b031763421bb64Daniel J Walsh WITHOUT ANY WARRANTY; without even the implied warranty of
e2417e4143bb892e4599b01de7b031763421bb64Daniel J Walsh MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
e2417e4143bb892e4599b01de7b031763421bb64Daniel J Walsh Lesser General Public License for more details.
e2417e4143bb892e4599b01de7b031763421bb64Daniel J Walsh
03e22642617f360a6b55cb853bcf59604754ea5dKay Sievers You should have received a copy of the GNU Lesser General Public License
e2417e4143bb892e4599b01de7b031763421bb64Daniel J Walsh along with systemd; If not, see <http://www.gnu.org/licenses/>.
03e22642617f360a6b55cb853bcf59604754ea5dKay Sievers***/
e2417e4143bb892e4599b01de7b031763421bb64Daniel J Walsh
e2417e4143bb892e4599b01de7b031763421bb64Daniel J Walsh#include "networkd.h"
e2417e4143bb892e4599b01de7b031763421bb64Daniel J Walsh#include "net-util.h"
718db96199eb307751264e4163555662c9a389faLennart Poettering#include "path-util.h"
718db96199eb307751264e4163555662c9a389faLennart Poettering#include "conf-files.h"
718db96199eb307751264e4163555662c9a389faLennart Poettering#include "conf-parser.h"
e94937df954451eb4aa63573f0d7404ed2db987eLukas Nykryn
ffc227c9568eb0a12dc750761d1e5d68ea125aadLennart Poetteringstatic int network_load_one(Manager *manager, const char *filename) {
8a188de9e0ea41509beda12084126d7a75ebe86eWaLyong Cho _cleanup_network_free_ Network *network = NULL;
ffc227c9568eb0a12dc750761d1e5d68ea125aadLennart Poettering _cleanup_fclose_ FILE *file = NULL;
8a188de9e0ea41509beda12084126d7a75ebe86eWaLyong Cho int r;
cad45ba11ec3572296361f53f5852ffb97a97fa3Lennart Poettering
8a188de9e0ea41509beda12084126d7a75ebe86eWaLyong Cho file = fopen(filename, "re");
e94937df954451eb4aa63573f0d7404ed2db987eLukas Nykryn if (!file) {
cad45ba11ec3572296361f53f5852ffb97a97fa3Lennart Poettering if (errno == ENOENT)
cad45ba11ec3572296361f53f5852ffb97a97fa3Lennart Poettering return 0;
8a188de9e0ea41509beda12084126d7a75ebe86eWaLyong Cho else
8a188de9e0ea41509beda12084126d7a75ebe86eWaLyong Cho return errno;
4f4f70361a64957c45a2d8f40bfb04c77b454697Lennart Poettering }
8a188de9e0ea41509beda12084126d7a75ebe86eWaLyong Cho
4f4f70361a64957c45a2d8f40bfb04c77b454697Lennart Poettering network = new0(Network, 1);
4f4f70361a64957c45a2d8f40bfb04c77b454697Lennart Poettering if (!network)
8a188de9e0ea41509beda12084126d7a75ebe86eWaLyong Cho return log_oom();
4f4f70361a64957c45a2d8f40bfb04c77b454697Lennart Poettering
cad45ba11ec3572296361f53f5852ffb97a97fa3Lennart Poettering network->manager = manager;
cad45ba11ec3572296361f53f5852ffb97a97fa3Lennart Poettering
cad45ba11ec3572296361f53f5852ffb97a97fa3Lennart Poettering LIST_HEAD_INIT(network->addresses);
8a188de9e0ea41509beda12084126d7a75ebe86eWaLyong Cho LIST_HEAD_INIT(network->routes);
8a188de9e0ea41509beda12084126d7a75ebe86eWaLyong Cho
cad45ba11ec3572296361f53f5852ffb97a97fa3Lennart Poettering network->addresses_by_section = hashmap_new(uint64_hash_func, uint64_compare_func);
e2417e4143bb892e4599b01de7b031763421bb64Daniel J Walsh if (!network->addresses_by_section)
return log_oom();
network->routes_by_section = hashmap_new(uint64_hash_func, uint64_compare_func);
if (!network->routes_by_section)
return log_oom();
network->filename = strdup(filename);
if (!network->filename)
return log_oom();
r = config_parse(NULL, filename, file, "Match\0Network\0Address\0Route\0", config_item_perf_lookup,
(void*) network_gperf_lookup, false, false, network);
if (r < 0) {
log_warning("Could not parse config file %s: %s", filename, strerror(-r));
return r;
} else
log_debug("Parsed configuration file %s", filename);
LIST_PREPEND(networks, manager->networks, network);
network = NULL;
return 0;
}
int network_load(Manager *manager) {
Network *network;
char **files, **f;
int r;
assert(manager);
while ((network = manager->networks))
network_free(network);
/* update timestamp */
paths_check_timestamp(manager->network_dirs, &manager->network_dirs_ts_usec, true);
r = conf_files_list_strv(&files, ".network", NULL, (const char **)manager->network_dirs);
if (r < 0) {
log_error("failed to enumerate network files: %s", strerror(-r));
return r;
}
STRV_FOREACH_BACKWARDS(f, files) {
r = network_load_one(manager, *f);
if (r < 0)
return r;
}
strv_free(files);
return 0;
}
bool network_should_reload(Manager *manager) {
return paths_check_timestamp(manager->network_dirs, &manager->network_dirs_ts_usec, false);
}
void network_free(Network *network) {
Route *route;
Address *address;
if (!network)
return;
free(network->filename);
free(network->match_mac);
free(network->match_path);
free(network->match_driver);
free(network->match_type);
free(network->match_name);
free(network->description);
while ((route = network->routes))
route_free(route);
while ((address = network->addresses))
address_free(address);
hashmap_free(network->addresses_by_section);
hashmap_free(network->routes_by_section);
LIST_REMOVE(networks, network->manager->networks, network);
free(network);
}
int network_get(Manager *manager, struct udev_device *device, Network **ret) {
Network *network;
assert(manager);
assert(device);
assert(ret);
if (network_should_reload(manager))
network_load(manager);
LIST_FOREACH(networks, network, manager->networks) {
if (net_match_config(network->match_mac, network->match_path,
network->match_driver, network->match_type,
network->match_name,
udev_device_get_sysattr_value(device, "address"),
udev_device_get_property_value(device, "ID_PATH"),
udev_device_get_driver(device),
udev_device_get_devtype(device),
udev_device_get_sysname(device))) {
log_debug("Network file %s applies to link %s",
network->filename,
udev_device_get_sysname(device));
*ret = network;
return 0;
}
}
*ret = NULL;
return -ENOENT;
}
int network_apply(Manager *manager, Network *network, Link *link) {
int r;
log_info("Network '%s' being applied to link '%ju'",
network->description, link->ifindex);
link->network = network;
r = link_configure(link);
if (r < 0)
return r;
return 0;
}