chiark / gitweb /
networkd: store netmask and mac address explicitly
[elogind.git] / src / network / networkd-network.c
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
28 static 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
33         file = fopen(filename, "re");
34         if (!file) {
35                 if (errno == ENOENT)
36                         return 0;
37                 else
38                         return errno;
39         }
40
41         network = new0(Network, 1);
42         if (!network)
43                 return log_oom();
44
45         LIST_HEAD_INIT(network->addresses);
46
47         r = config_parse(NULL, filename, file, "Match\0Network\0", config_item_perf_lookup,
48                         (void*) network_gperf_lookup, false, false, network);
49         if (r < 0) {
50                 log_warning("Could not parse config file %s: %s", filename, strerror(-r));
51                 return r;
52         } else
53                 log_debug("Parsed configuration file %s", filename);
54
55         network->filename = strdup(filename);
56         if (!network->filename)
57                 return log_oom();
58
59         LIST_PREPEND(networks, manager->networks, network);
60         network = NULL;
61
62         return 0;
63 }
64
65 int network_load(Manager *manager) {
66         Network *network;
67         char **files, **f;
68         int r;
69
70         assert(manager);
71
72         while ((network = manager->networks))
73                 network_free(network);
74
75         /* update timestamp */
76         paths_check_timestamp(manager->network_dirs, &manager->network_dirs_ts_usec, true);
77
78         r = conf_files_list_strv(&files, ".network", NULL, (const char **)manager->network_dirs);
79         if (r < 0) {
80                 log_error("failed to enumerate network files: %s", strerror(-r));
81                 return r;
82         }
83
84         STRV_FOREACH_BACKWARDS(f, files) {
85                 r = network_load_one(manager, *f);
86                 if (r < 0)
87                         return r;
88         }
89
90         strv_free(files);
91
92         return 0;
93 }
94
95 bool network_should_reload(Manager *manager) {
96         return paths_check_timestamp(manager->network_dirs, &manager->network_dirs_ts_usec, false);
97 }
98
99 void network_free(Network *network) {
100         Route *route;
101         Address *address;
102
103         if (!network)
104                 return;
105
106         free(network->filename);
107
108         free(network->match_mac);
109         free(network->match_path);
110         free(network->match_driver);
111         free(network->match_type);
112         free(network->match_name);
113
114         free(network->description);
115
116         while ((route = network->routes))
117                 route_free(route);
118
119         while ((address = network->addresses))
120                 address_free(address);
121
122         LIST_REMOVE(networks, network->manager->networks, network);
123
124         free(network);
125 }
126
127 int network_get(Manager *manager, struct udev_device *device, Network **ret) {
128         Network *network;
129
130         assert(manager);
131         assert(device);
132         assert(ret);
133
134         if (network_should_reload(manager))
135                 network_load(manager);
136
137         LIST_FOREACH(networks, network, manager->networks) {
138                 if (net_match_config(network->match_mac, network->match_path,
139                                         network->match_driver, network->match_type,
140                                         network->match_name,
141                                         udev_device_get_sysattr_value(device, "address"),
142                                         udev_device_get_property_value(device, "ID_PATH"),
143                                         udev_device_get_driver(device),
144                                         udev_device_get_devtype(device),
145                                         udev_device_get_sysname(device))) {
146                         log_debug("Network file %s applies to link %s",
147                                         network->filename,
148                                         udev_device_get_sysname(device));
149                         *ret = network;
150                         return 0;
151                 }
152         }
153
154         *ret = NULL;
155
156         return -ENOENT;
157 }
158
159 int network_apply(Manager *manager, Network *network, Link *link) {
160         Address *address;
161         Route *route;
162         int r;
163
164         log_info("Network '%s' being applied to link '%u'",
165                         network->description, (unsigned) link->ifindex);
166
167         link->network = network;
168
169         LIST_FOREACH(addresses, address, network->addresses) {
170                 r = address_configure(manager, address, link);
171                 if (r < 0)
172                         return r;
173         }
174
175         r = link_up(manager, link);
176         if (r < 0)
177                 return r;
178
179         LIST_FOREACH(routes, route, network->routes) {
180                 r = route_configure(manager, route, link);
181                 if (r < 0)
182                         return r;
183         }
184
185         return 0;
186 }