networkd-network.c revision edbb03e95a3c31bf719d5c6c46eec14d0bcb9c8f
97a9a944b5887e91042b019776c41d5dd74557aferikabele/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
97a9a944b5887e91042b019776c41d5dd74557aferikabele
97a9a944b5887e91042b019776c41d5dd74557aferikabele/***
a945f35eff8b6a88009ce73de6d4c862ce58de3cslive This file is part of systemd.
a945f35eff8b6a88009ce73de6d4c862ce58de3cslive
a945f35eff8b6a88009ce73de6d4c862ce58de3cslive Copyright 2013 Tom Gundersen <teg@jklm.no>
5a58787efeb02a1c3f06569d019ad81fd2efa06end
5a58787efeb02a1c3f06569d019ad81fd2efa06end systemd is free software; you can redistribute it and/or modify it
5a58787efeb02a1c3f06569d019ad81fd2efa06end under the terms of the GNU Lesser General Public License as published by
5a58787efeb02a1c3f06569d019ad81fd2efa06end the Free Software Foundation; either version 2.1 of the License, or
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen (at your option) any later version.
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen systemd is distributed in the hope that it will be useful, but
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen WITHOUT ANY WARRANTY; without even the implied warranty of
5a58787efeb02a1c3f06569d019ad81fd2efa06end MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5a58787efeb02a1c3f06569d019ad81fd2efa06end Lesser General Public License for more details.
5a58787efeb02a1c3f06569d019ad81fd2efa06end
d229f940abfb2490dee17979e9a5ff31b7012eb5rbowen You should have received a copy of the GNU Lesser General Public License
3f08db06526d6901aa08c110b5bc7dde6bc39905nd along with systemd; If not, see <http://www.gnu.org/licenses/>.
5a58787efeb02a1c3f06569d019ad81fd2efa06end***/
5a58787efeb02a1c3f06569d019ad81fd2efa06end
5a58787efeb02a1c3f06569d019ad81fd2efa06end#include "networkd.h"
3f08db06526d6901aa08c110b5bc7dde6bc39905nd#include "net-util.h"
5a58787efeb02a1c3f06569d019ad81fd2efa06end#include "path-util.h"
a63f0ab647ad2ab72efc9bea7a66e24e9ebc5cc2nd#include "conf-files.h"
3b3b7fc78d1f5bfc2769903375050048ff41ff26nd#include "conf-parser.h"
ad74a0524a06bfe11b7de9e3b4ce7233ab3bd3f7nd#include "util.h"
ad74a0524a06bfe11b7de9e3b4ce7233ab3bd3f7nd
e1e8390280254f7f0580d701e583f670643d4f3fnilgunstatic int network_load_one(Manager *manager, const char *filename) {
f086b4b402fa9a2fefc7dda85de2a3cc1cd0a654rjung _cleanup_network_free_ Network *network = NULL;
3b3b7fc78d1f5bfc2769903375050048ff41ff26nd _cleanup_fclose_ FILE *file = NULL;
5a58787efeb02a1c3f06569d019ad81fd2efa06end Route *route;
5a58787efeb02a1c3f06569d019ad81fd2efa06end Address *address;
5a58787efeb02a1c3f06569d019ad81fd2efa06end int r;
5a58787efeb02a1c3f06569d019ad81fd2efa06end
5a58787efeb02a1c3f06569d019ad81fd2efa06end assert(manager);
5a58787efeb02a1c3f06569d019ad81fd2efa06end assert(filename);
9b6a3a558cc90ffdaa0b50bd02546ffec424ded7slive
55478342807b8fbc71ba2af7444e3a06fad7ebf1rbowen file = fopen(filename, "re");
55478342807b8fbc71ba2af7444e3a06fad7ebf1rbowen if (!file) {
55478342807b8fbc71ba2af7444e3a06fad7ebf1rbowen if (errno == ENOENT)
9b6a3a558cc90ffdaa0b50bd02546ffec424ded7slive return 0;
9b6a3a558cc90ffdaa0b50bd02546ffec424ded7slive else
9b6a3a558cc90ffdaa0b50bd02546ffec424ded7slive return errno;
06ba4a61654b3763ad65f52283832ebf058fdf1cslive }
9b6a3a558cc90ffdaa0b50bd02546ffec424ded7slive
9b6a3a558cc90ffdaa0b50bd02546ffec424ded7slive network = new0(Network, 1);
ffb01336be79c64046b636e59fa8ddca8ec029edsf if (!network)
ffb01336be79c64046b636e59fa8ddca8ec029edsf return log_oom();
9b6a3a558cc90ffdaa0b50bd02546ffec424ded7slive
9b6a3a558cc90ffdaa0b50bd02546ffec424ded7slive network->manager = manager;
5a58787efeb02a1c3f06569d019ad81fd2efa06end
5a58787efeb02a1c3f06569d019ad81fd2efa06end LIST_HEAD_INIT(network->static_addresses);
5a58787efeb02a1c3f06569d019ad81fd2efa06end LIST_HEAD_INIT(network->static_routes);
117c1f888a14e73cdd821dc6c23eb0411144a41cnd
deeee6bb6fd94c0ba5f3730b58abd9d299c89ccdnd network->vlans = hashmap_new(uint64_hash_func, uint64_compare_func);
4db28ee269aa06f7c6232e11cd01f58c3349af23noodl if (!network->vlans)
117c1f888a14e73cdd821dc6c23eb0411144a41cnd return log_oom();
117c1f888a14e73cdd821dc6c23eb0411144a41cnd
4a31db3c3a0202003c1b9f87affa7cc143e120e5sf network->addresses_by_section = hashmap_new(uint64_hash_func, uint64_compare_func);
117c1f888a14e73cdd821dc6c23eb0411144a41cnd if (!network->addresses_by_section)
ffb01336be79c64046b636e59fa8ddca8ec029edsf return log_oom();
117c1f888a14e73cdd821dc6c23eb0411144a41cnd
117c1f888a14e73cdd821dc6c23eb0411144a41cnd network->routes_by_section = hashmap_new(uint64_hash_func, uint64_compare_func);
117c1f888a14e73cdd821dc6c23eb0411144a41cnd if (!network->routes_by_section)
2bc7f1cf720973a67f8ff7a8d523e40569ae5b6cnd return log_oom();
117c1f888a14e73cdd821dc6c23eb0411144a41cnd
117c1f888a14e73cdd821dc6c23eb0411144a41cnd network->filename = strdup(filename);
117c1f888a14e73cdd821dc6c23eb0411144a41cnd if (!network->filename)
117c1f888a14e73cdd821dc6c23eb0411144a41cnd return log_oom();
4db28ee269aa06f7c6232e11cd01f58c3349af23noodl
5a58787efeb02a1c3f06569d019ad81fd2efa06end network->dhcp_dns = true;
5a58787efeb02a1c3f06569d019ad81fd2efa06end network->dhcp_hostname = true;
5a58787efeb02a1c3f06569d019ad81fd2efa06end network->dhcp_domainname = true;
5a58787efeb02a1c3f06569d019ad81fd2efa06end
5a58787efeb02a1c3f06569d019ad81fd2efa06end r = config_parse(NULL, filename, file, "Match\0Network\0Address\0Route\0DHCPv4\0", config_item_perf_lookup,
5a58787efeb02a1c3f06569d019ad81fd2efa06end (void*) network_network_gperf_lookup, false, false, network);
55478342807b8fbc71ba2af7444e3a06fad7ebf1rbowen if (r < 0) {
a63f0ab647ad2ab72efc9bea7a66e24e9ebc5cc2nd log_warning("Could not parse config file %s: %s", filename, strerror(-r));
30471a4650391f57975f60bbb6e4a90be7b284bfhumbedooh return r;
5a58787efeb02a1c3f06569d019ad81fd2efa06end }
5a58787efeb02a1c3f06569d019ad81fd2efa06end
5a58787efeb02a1c3f06569d019ad81fd2efa06end LIST_PREPEND(networks, manager->networks, network);
06ba4a61654b3763ad65f52283832ebf058fdf1cslive
06ba4a61654b3763ad65f52283832ebf058fdf1cslive LIST_FOREACH(static_routes, route, network->static_routes) {
55478342807b8fbc71ba2af7444e3a06fad7ebf1rbowen if (!route->family) {
06ba4a61654b3763ad65f52283832ebf058fdf1cslive log_warning("Route section without Gateway field configured in %s. "
06ba4a61654b3763ad65f52283832ebf058fdf1cslive "Ignoring", filename);
06ba4a61654b3763ad65f52283832ebf058fdf1cslive return 0;
06ba4a61654b3763ad65f52283832ebf058fdf1cslive }
06ba4a61654b3763ad65f52283832ebf058fdf1cslive }
97a9a944b5887e91042b019776c41d5dd74557aferikabele
97a9a944b5887e91042b019776c41d5dd74557aferikabele LIST_FOREACH(static_addresses, address, network->static_addresses) {
97a9a944b5887e91042b019776c41d5dd74557aferikabele if (!address->family) {
ffb01336be79c64046b636e59fa8ddca8ec029edsf log_warning("Address section without Address field configured in %s. "
06ba4a61654b3763ad65f52283832ebf058fdf1cslive "Ignoring", filename);
55478342807b8fbc71ba2af7444e3a06fad7ebf1rbowen return 0;
06ba4a61654b3763ad65f52283832ebf058fdf1cslive }
06ba4a61654b3763ad65f52283832ebf058fdf1cslive }
ffb01336be79c64046b636e59fa8ddca8ec029edsf
ffb01336be79c64046b636e59fa8ddca8ec029edsf network = NULL;
06ba4a61654b3763ad65f52283832ebf058fdf1cslive
06ba4a61654b3763ad65f52283832ebf058fdf1cslive return 0;
06ba4a61654b3763ad65f52283832ebf058fdf1cslive}
06ba4a61654b3763ad65f52283832ebf058fdf1cslive
a63f0ab647ad2ab72efc9bea7a66e24e9ebc5cc2ndint network_load(Manager *manager) {
a63f0ab647ad2ab72efc9bea7a66e24e9ebc5cc2nd Network *network;
55478342807b8fbc71ba2af7444e3a06fad7ebf1rbowen _cleanup_strv_free_ char **files = NULL;
55478342807b8fbc71ba2af7444e3a06fad7ebf1rbowen char **f;
06ba4a61654b3763ad65f52283832ebf058fdf1cslive int r;
9b6a3a558cc90ffdaa0b50bd02546ffec424ded7slive
06ba4a61654b3763ad65f52283832ebf058fdf1cslive assert(manager);
4a31db3c3a0202003c1b9f87affa7cc143e120e5sf
06ba4a61654b3763ad65f52283832ebf058fdf1cslive while ((network = manager->networks))
06ba4a61654b3763ad65f52283832ebf058fdf1cslive network_free(network);
709e3a21ba73b8433462959cd56c773454b34441trawick
709e3a21ba73b8433462959cd56c773454b34441trawick r = conf_files_list_strv(&files, ".network", NULL, network_dirs);
709e3a21ba73b8433462959cd56c773454b34441trawick if (r < 0) {
709e3a21ba73b8433462959cd56c773454b34441trawick log_error("Failed to enumerate network files: %s", strerror(-r));
709e3a21ba73b8433462959cd56c773454b34441trawick return r;
709e3a21ba73b8433462959cd56c773454b34441trawick }
709e3a21ba73b8433462959cd56c773454b34441trawick
5a58787efeb02a1c3f06569d019ad81fd2efa06end STRV_FOREACH_BACKWARDS(f, files) {
5a58787efeb02a1c3f06569d019ad81fd2efa06end r = network_load_one(manager, *f);
5a58787efeb02a1c3f06569d019ad81fd2efa06end if (r < 0)
5a58787efeb02a1c3f06569d019ad81fd2efa06end return r;
5a58787efeb02a1c3f06569d019ad81fd2efa06end }
9fc1345bb54ea7f68c2e59ff3a618c1237a30918yoshiki
5a58787efeb02a1c3f06569d019ad81fd2efa06end return 0;
5a58787efeb02a1c3f06569d019ad81fd2efa06end}
5a58787efeb02a1c3f06569d019ad81fd2efa06end
5a58787efeb02a1c3f06569d019ad81fd2efa06endvoid network_free(Network *network) {
5a58787efeb02a1c3f06569d019ad81fd2efa06end Route *route;
06ba4a61654b3763ad65f52283832ebf058fdf1cslive Address *address;
06ba4a61654b3763ad65f52283832ebf058fdf1cslive
06ba4a61654b3763ad65f52283832ebf058fdf1cslive if (!network)
a63f0ab647ad2ab72efc9bea7a66e24e9ebc5cc2nd return;
a63f0ab647ad2ab72efc9bea7a66e24e9ebc5cc2nd
06ba4a61654b3763ad65f52283832ebf058fdf1cslive free(network->filename);
06ba4a61654b3763ad65f52283832ebf058fdf1cslive
06ba4a61654b3763ad65f52283832ebf058fdf1cslive free(network->match_mac);
f989aee1278b24f2b6e3a8e3b0935b590349de81jorton free(network->match_path);
55478342807b8fbc71ba2af7444e3a06fad7ebf1rbowen free(network->match_driver);
a63f0ab647ad2ab72efc9bea7a66e24e9ebc5cc2nd free(network->match_type);
5a58787efeb02a1c3f06569d019ad81fd2efa06end free(network->match_name);
5a58787efeb02a1c3f06569d019ad81fd2efa06end
5a58787efeb02a1c3f06569d019ad81fd2efa06end free(network->description);
5a58787efeb02a1c3f06569d019ad81fd2efa06end
5a58787efeb02a1c3f06569d019ad81fd2efa06end address_free(network->dns);
5fe85d8662e07bb4e9dbe9c2d0274e90a3058135rbowen
5a58787efeb02a1c3f06569d019ad81fd2efa06end hashmap_free(network->vlans);
5a58787efeb02a1c3f06569d019ad81fd2efa06end
5a58787efeb02a1c3f06569d019ad81fd2efa06end while ((route = network->static_routes))
5a58787efeb02a1c3f06569d019ad81fd2efa06end route_free(route);
5a58787efeb02a1c3f06569d019ad81fd2efa06end
5a58787efeb02a1c3f06569d019ad81fd2efa06end while ((address = network->static_addresses))
5a58787efeb02a1c3f06569d019ad81fd2efa06end address_free(address);
a63f0ab647ad2ab72efc9bea7a66e24e9ebc5cc2nd
5a58787efeb02a1c3f06569d019ad81fd2efa06end hashmap_free(network->addresses_by_section);
5a58787efeb02a1c3f06569d019ad81fd2efa06end hashmap_free(network->routes_by_section);
5a58787efeb02a1c3f06569d019ad81fd2efa06end
5a58787efeb02a1c3f06569d019ad81fd2efa06end if (network->manager && network->manager->networks)
06ba4a61654b3763ad65f52283832ebf058fdf1cslive LIST_REMOVE(networks, network->manager->networks, network);
06ba4a61654b3763ad65f52283832ebf058fdf1cslive
06ba4a61654b3763ad65f52283832ebf058fdf1cslive free(network);
a63f0ab647ad2ab72efc9bea7a66e24e9ebc5cc2nd}
2bfb6b5514fae5aff3a3a56a15f3d5a545395c41igalic
2bfb6b5514fae5aff3a3a56a15f3d5a545395c41igalicint network_get(Manager *manager, struct udev_device *device, Network **ret) {
2bfb6b5514fae5aff3a3a56a15f3d5a545395c41igalic Network *network;
2bfb6b5514fae5aff3a3a56a15f3d5a545395c41igalic
2bfb6b5514fae5aff3a3a56a15f3d5a545395c41igalic assert(manager);
06ba4a61654b3763ad65f52283832ebf058fdf1cslive assert(device);
06ba4a61654b3763ad65f52283832ebf058fdf1cslive assert(ret);
06ba4a61654b3763ad65f52283832ebf058fdf1cslive
06ba4a61654b3763ad65f52283832ebf058fdf1cslive LIST_FOREACH(networks, network, manager->networks) {
5a58787efeb02a1c3f06569d019ad81fd2efa06end if (net_match_config(network->match_mac, network->match_path,
5a58787efeb02a1c3f06569d019ad81fd2efa06end network->match_driver, network->match_type,
5a58787efeb02a1c3f06569d019ad81fd2efa06end network->match_name, network->match_host,
5a58787efeb02a1c3f06569d019ad81fd2efa06end network->match_virt, network->match_kernel,
5a58787efeb02a1c3f06569d019ad81fd2efa06end network->match_arch,
5fe85d8662e07bb4e9dbe9c2d0274e90a3058135rbowen udev_device_get_sysattr_value(device, "address"),
5a58787efeb02a1c3f06569d019ad81fd2efa06end udev_device_get_property_value(device, "ID_PATH"),
5a58787efeb02a1c3f06569d019ad81fd2efa06end udev_device_get_driver(udev_device_get_parent(device)),
5a58787efeb02a1c3f06569d019ad81fd2efa06end udev_device_get_devtype(device),
3b3b7fc78d1f5bfc2769903375050048ff41ff26nd udev_device_get_sysname(device))) {
ad74a0524a06bfe11b7de9e3b4ce7233ab3bd3f7nd log_debug("%s: found matching network '%s'",
ad74a0524a06bfe11b7de9e3b4ce7233ab3bd3f7nd udev_device_get_sysname(device),
e1e8390280254f7f0580d701e583f670643d4f3fnilgun network->filename);
f086b4b402fa9a2fefc7dda85de2a3cc1cd0a654rjung *ret = network;
727872d18412fc021f03969b8641810d8896820bhumbedooh return 0;
0d0ba3a410038e179b695446bb149cce6264e0abnd }
727872d18412fc021f03969b8641810d8896820bhumbedooh }
cc7e1025de9ac63bd4db6fe7f71c158b2cf09fe4humbedooh
0d0ba3a410038e179b695446bb149cce6264e0abnd *ret = NULL;
cc7e1025de9ac63bd4db6fe7f71c158b2cf09fe4humbedooh
727872d18412fc021f03969b8641810d8896820bhumbedooh return -ENOENT;
0d0ba3a410038e179b695446bb149cce6264e0abnd}
0d0ba3a410038e179b695446bb149cce6264e0abnd
0d0ba3a410038e179b695446bb149cce6264e0abndint network_apply(Manager *manager, Network *network, Link *link) {
727872d18412fc021f03969b8641810d8896820bhumbedooh int r;
0d0ba3a410038e179b695446bb149cce6264e0abnd
0d0ba3a410038e179b695446bb149cce6264e0abnd link->network = network;
0d0ba3a410038e179b695446bb149cce6264e0abnd
727872d18412fc021f03969b8641810d8896820bhumbedooh r = link_configure(link);
0d0ba3a410038e179b695446bb149cce6264e0abnd if (r < 0)
0d0ba3a410038e179b695446bb149cce6264e0abnd return r;
30471a4650391f57975f60bbb6e4a90be7b284bfhumbedooh
5effc8b39fae5cd169d17f342bfc265705840014rbowen if (network->dns) {
d229f940abfb2490dee17979e9a5ff31b7012eb5rbowen r = manager_update_resolv_conf(manager);
0d0ba3a410038e179b695446bb149cce6264e0abnd if (r < 0)
7fec19672a491661b2fe4b29f685bc7f4efa64d4nd return r;
7fec19672a491661b2fe4b29f685bc7f4efa64d4nd }
7fec19672a491661b2fe4b29f685bc7f4efa64d4nd
5a58787efeb02a1c3f06569d019ad81fd2efa06end return 0;
}
int config_parse_bridge(const char *unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
Network *network = userdata;
NetDev *netdev;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
r = netdev_get(network->manager, rvalue, &netdev);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, EINVAL,
"Bridge is invalid, ignoring assignment: %s", rvalue);
return 0;
}
if (netdev->kind != NETDEV_KIND_BRIDGE) {
log_syntax(unit, LOG_ERR, filename, line, EINVAL,
"NetDev is not a bridge, ignoring assignment: %s", rvalue);
return 0;
}
network->bridge = netdev;
return 0;
}
int config_parse_bond(const char *unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
Network *network = userdata;
NetDev *netdev;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
r = netdev_get(network->manager, rvalue, &netdev);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, EINVAL,
"Bond is invalid, ignoring assignment: %s", rvalue);
return 0;
}
if (netdev->kind != NETDEV_KIND_BOND) {
log_syntax(unit, LOG_ERR, filename, line, EINVAL,
"NetDev is not a bond, ignoring assignment: %s", rvalue);
return 0;
}
network->bond = netdev;
return 0;
}
int config_parse_vlan(const char *unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
Network *network = userdata;
NetDev *netdev;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
r = netdev_get(network->manager, rvalue, &netdev);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, EINVAL,
"VLAN is invalid, ignoring assignment: %s", rvalue);
return 0;
}
if (netdev->kind != NETDEV_KIND_VLAN) {
log_syntax(unit, LOG_ERR, filename, line, EINVAL,
"NetDev is not a VLAN, ignoring assignment: %s", rvalue);
return 0;
}
r = hashmap_put(network->vlans, &netdev->vlanid, netdev);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, EINVAL,
"Can not add VLAN to network: %s", rvalue);
return 0;
}
return 0;
}