]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-network.c
networkd: do not deference null pointer in cleanup
[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
f048a16b
TG
50 LIST_HEAD_INIT(network->static_addresses);
51 LIST_HEAD_INIT(network->static_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;
449f7554 70 }
f579559b 71
f579559b
TG
72 LIST_PREPEND(networks, manager->networks, network);
73 network = NULL;
74
75 return 0;
76}
77
78int network_load(Manager *manager) {
79 Network *network;
80 char **files, **f;
81 int r;
82
83 assert(manager);
84
85 while ((network = manager->networks))
86 network_free(network);
87
f579559b
TG
88 r = conf_files_list_strv(&files, ".network", NULL, (const char **)manager->network_dirs);
89 if (r < 0) {
449f7554 90 log_error("Failed to enumerate network files: %s", strerror(-r));
f579559b
TG
91 return r;
92 }
93
94 STRV_FOREACH_BACKWARDS(f, files) {
95 r = network_load_one(manager, *f);
96 if (r < 0)
97 return r;
98 }
99
100 strv_free(files);
101
102 return 0;
103}
104
f579559b
TG
105void network_free(Network *network) {
106 Route *route;
107 Address *address;
108
109 if (!network)
110 return;
111
7384fa92
ZJS
112 assert(network->manager);
113
f579559b
TG
114 free(network->filename);
115
116 free(network->match_mac);
117 free(network->match_path);
118 free(network->match_driver);
119 free(network->match_type);
120 free(network->match_name);
121
122 free(network->description);
123
f048a16b 124 while ((route = network->static_routes))
f579559b
TG
125 route_free(route);
126
f048a16b 127 while ((address = network->static_addresses))
f579559b
TG
128 address_free(address);
129
6ae115c1
TG
130 hashmap_free(network->addresses_by_section);
131 hashmap_free(network->routes_by_section);
132
7384fa92
ZJS
133 if (network->manager->networks)
134 LIST_REMOVE(networks, network->manager->networks, network);
f579559b
TG
135
136 free(network);
137}
138
139int network_get(Manager *manager, struct udev_device *device, Network **ret) {
140 Network *network;
141
142 assert(manager);
143 assert(device);
144 assert(ret);
145
02b59d57
TG
146 if (manager_should_reload(manager))
147 manager_load_config(manager);
f579559b
TG
148
149 LIST_FOREACH(networks, network, manager->networks) {
150 if (net_match_config(network->match_mac, network->match_path,
151 network->match_driver, network->match_type,
152 network->match_name,
153 udev_device_get_sysattr_value(device, "address"),
154 udev_device_get_property_value(device, "ID_PATH"),
155 udev_device_get_driver(device),
156 udev_device_get_devtype(device),
157 udev_device_get_sysname(device))) {
449f7554
TG
158 log_debug("%s: found matching network '%s'",
159 udev_device_get_sysname(device),
160 network->filename);
f579559b
TG
161 *ret = network;
162 return 0;
163 }
164 }
165
166 *ret = NULL;
167
168 return -ENOENT;
169}
170
171int network_apply(Manager *manager, Network *network, Link *link) {
f579559b
TG
172 int r;
173
f579559b
TG
174 link->network = network;
175
f882c247 176 r = link_configure(link);
f579559b
TG
177 if (r < 0)
178 return r;
179
f579559b
TG
180 return 0;
181}
02b59d57
TG
182
183int config_parse_bridge(const char *unit,
184 const char *filename,
185 unsigned line,
186 const char *section,
187 unsigned section_line,
188 const char *lvalue,
189 int ltype,
190 const char *rvalue,
191 void *data,
192 void *userdata) {
193 Network *network = userdata;
194 Bridge *bridge;
195 int r;
196
197 assert(filename);
198 assert(lvalue);
199 assert(rvalue);
200 assert(data);
201
202 r = bridge_get(network->manager, rvalue, &bridge);
203 if (r < 0) {
204 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
205 "Bridge is invalid, ignoring assignment: %s", rvalue);
206 return 0;
207 }
208
209 network->bridge = bridge;
210
211 return 0;
212}