]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-network.c
network: add support for dropping address
[thirdparty/systemd.git] / src / network / networkd-network.c
CommitLineData
f579559b
TG
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2013 Tom Gundersen <teg@jklm.no>
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
22#include "networkd.h"
23#include "net-util.h"
24#include "path-util.h"
25#include "conf-files.h"
26#include "conf-parser.h"
27
28static int network_load_one(Manager *manager, const char *filename) {
29 _cleanup_network_free_ Network *network = NULL;
30 _cleanup_fclose_ FILE *file = NULL;
31 int r;
32
bf1bc670
TA
33 assert(manager);
34 assert(filename);
35
f579559b
TG
36 file = fopen(filename, "re");
37 if (!file) {
38 if (errno == ENOENT)
39 return 0;
40 else
41 return errno;
42 }
43
44 network = new0(Network, 1);
45 if (!network)
46 return log_oom();
47
5a3eb5a7
TG
48 network->manager = manager;
49
f579559b 50 LIST_HEAD_INIT(network->addresses);
6ae115c1 51 LIST_HEAD_INIT(network->routes);
f579559b 52
6ae115c1
TG
53 network->addresses_by_section = hashmap_new(uint64_hash_func, uint64_compare_func);
54 if (!network->addresses_by_section)
55 return log_oom();
56
57 network->routes_by_section = hashmap_new(uint64_hash_func, uint64_compare_func);
58 if (!network->routes_by_section)
59 return log_oom();
60
61 network->filename = strdup(filename);
62 if (!network->filename)
63 return log_oom();
64
65 r = config_parse(NULL, filename, file, "Match\0Network\0Address\0Route\0", config_item_perf_lookup,
f579559b
TG
66 (void*) network_gperf_lookup, false, false, network);
67 if (r < 0) {
68 log_warning("Could not parse config file %s: %s", filename, strerror(-r));
69 return r;
70 } else
71 log_debug("Parsed configuration file %s", filename);
72
f579559b
TG
73 LIST_PREPEND(networks, manager->networks, network);
74 network = NULL;
75
76 return 0;
77}
78
79int network_load(Manager *manager) {
80 Network *network;
81 char **files, **f;
82 int r;
83
84 assert(manager);
85
86 while ((network = manager->networks))
87 network_free(network);
88
f579559b
TG
89 r = conf_files_list_strv(&files, ".network", NULL, (const char **)manager->network_dirs);
90 if (r < 0) {
91 log_error("failed to enumerate network files: %s", strerror(-r));
92 return r;
93 }
94
95 STRV_FOREACH_BACKWARDS(f, files) {
96 r = network_load_one(manager, *f);
97 if (r < 0)
98 return r;
99 }
100
101 strv_free(files);
102
103 return 0;
104}
105
f579559b
TG
106void network_free(Network *network) {
107 Route *route;
108 Address *address;
109
110 if (!network)
111 return;
112
113 free(network->filename);
114
115 free(network->match_mac);
116 free(network->match_path);
117 free(network->match_driver);
118 free(network->match_type);
119 free(network->match_name);
120
121 free(network->description);
122
123 while ((route = network->routes))
124 route_free(route);
125
126 while ((address = network->addresses))
127 address_free(address);
128
6ae115c1
TG
129 hashmap_free(network->addresses_by_section);
130 hashmap_free(network->routes_by_section);
131
f579559b
TG
132 LIST_REMOVE(networks, network->manager->networks, network);
133
134 free(network);
135}
136
137int network_get(Manager *manager, struct udev_device *device, Network **ret) {
138 Network *network;
139
140 assert(manager);
141 assert(device);
142 assert(ret);
143
02b59d57
TG
144 if (manager_should_reload(manager))
145 manager_load_config(manager);
f579559b
TG
146
147 LIST_FOREACH(networks, network, manager->networks) {
148 if (net_match_config(network->match_mac, network->match_path,
149 network->match_driver, network->match_type,
150 network->match_name,
151 udev_device_get_sysattr_value(device, "address"),
152 udev_device_get_property_value(device, "ID_PATH"),
153 udev_device_get_driver(device),
154 udev_device_get_devtype(device),
155 udev_device_get_sysname(device))) {
156 log_debug("Network file %s applies to link %s",
157 network->filename,
158 udev_device_get_sysname(device));
159 *ret = network;
160 return 0;
161 }
162 }
163
164 *ret = NULL;
165
166 return -ENOENT;
167}
168
169int network_apply(Manager *manager, Network *network, Link *link) {
f579559b
TG
170 int r;
171
02b59d57
TG
172 log_info("Network '%s' being applied to link '%s'",
173 network->description, link->ifname);
f579559b
TG
174
175 link->network = network;
176
f882c247 177 r = link_configure(link);
f579559b
TG
178 if (r < 0)
179 return r;
180
f579559b
TG
181 return 0;
182}
02b59d57
TG
183
184int config_parse_bridge(const char *unit,
185 const char *filename,
186 unsigned line,
187 const char *section,
188 unsigned section_line,
189 const char *lvalue,
190 int ltype,
191 const char *rvalue,
192 void *data,
193 void *userdata) {
194 Network *network = userdata;
195 Bridge *bridge;
196 int r;
197
198 assert(filename);
199 assert(lvalue);
200 assert(rvalue);
201 assert(data);
202
203 r = bridge_get(network->manager, rvalue, &bridge);
204 if (r < 0) {
205 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
206 "Bridge is invalid, ignoring assignment: %s", rvalue);
207 return 0;
208 }
209
210 network->bridge = bridge;
211
212 return 0;
213}