chiark / gitweb /
networkd: Initialize variable to NULL
[elogind.git] / src / network / networkd-address.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 <net/if.h>
23
24 #include "networkd.h"
25
26 #include "utf8.h"
27 #include "util.h"
28 #include "conf-parser.h"
29 #include "net-util.h"
30
31 int address_new(Network *network, unsigned section, Address **ret) {
32         _cleanup_address_free_ Address *address = NULL;
33
34         if (section) {
35                 uint64_t key = section;
36                 address = hashmap_get(network->addresses_by_section, &key);
37                 if (address) {
38                         *ret = address;
39                         address = NULL;
40
41                         return 0;
42                 }
43         }
44
45         address = new0(Address, 1);
46         if (!address)
47                 return -ENOMEM;
48
49         address->network = network;
50
51         LIST_PREPEND(addresses, network->addresses, address);
52
53         if (section) {
54                 address->section = section;
55                 hashmap_put(network->addresses_by_section, &address->section, address);
56         }
57
58         *ret = address;
59         address = NULL;
60
61         return 0;
62 }
63
64 void address_free(Address *address) {
65         if (!address)
66                 return;
67
68         LIST_REMOVE(addresses, address->network->addresses, address);
69
70         if (address->section)
71                 hashmap_remove(address->network->addresses_by_section,
72                                &address->section);
73
74         free(address);
75 }
76
77 int address_configure(Address *address, Link *link,
78                       sd_rtnl_message_handler_t callback) {
79         _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
80         int r;
81
82         assert(address);
83         assert(address->family == AF_INET || address->family == AF_INET6);
84         assert(link);
85         assert(link->ifindex > 0);
86         assert(link->manager);
87         assert(link->manager->rtnl);
88
89         r = sd_rtnl_message_addr_new(RTM_NEWADDR, link->ifindex,
90                         address->family, address->prefixlen,
91                         IFA_F_PERMANENT, RT_SCOPE_UNIVERSE, &req);
92         if (r < 0) {
93                 log_error("Could not allocate RTM_NEWADDR message: %s",
94                           strerror(-r));
95                 return r;
96         }
97
98         r = sd_rtnl_message_append(req, IFA_LOCAL, &address->in_addr);
99         if (r < 0) {
100                 log_error("Could not append IFA_LOCAL attribute: %s",
101                           strerror(-r));
102                 return r;
103         }
104
105         if (address->family == AF_INET) {
106                 struct in_addr broadcast;
107
108                 broadcast.s_addr = address->in_addr.in.s_addr | address->netmask.s_addr;
109
110                 r = sd_rtnl_message_append(req, IFA_BROADCAST, &broadcast);
111                 if (r < 0) {
112                         log_error("Could not append IFA_BROADCAST attribute: %s",
113                                   strerror(-r));
114                         return r;
115                 }
116         }
117
118         if (address->label) {
119                 r = sd_rtnl_message_append(req, IFA_LABEL, address->label);
120                 if (r < 0) {
121                         log_error("Could not append IFA_LABEL attribute: %s",
122                                   strerror(-r));
123                         return r;
124                 }
125         }
126
127         r = sd_rtnl_call_async(link->manager->rtnl, req, callback, link, 0, NULL);
128         if (r < 0) {
129                 log_error("Could not send rtnetlink message: %s", strerror(-r));
130                 return r;
131         }
132
133         return 0;
134 }
135
136 int config_parse_address(const char *unit,
137                 const char *filename,
138                 unsigned line,
139                 const char *section,
140                 unsigned section_line,
141                 const char *lvalue,
142                 int ltype,
143                 const char *rvalue,
144                 void *data,
145                 void *userdata) {
146         Network *network = userdata;
147         _cleanup_address_free_ Address *n = NULL;
148         _cleanup_free_ char *address = NULL;
149         const char *e;
150         int r;
151
152         assert(filename);
153         assert(section);
154         assert(lvalue);
155         assert(rvalue);
156         assert(data);
157
158         r = address_new(network, section_line, &n);
159         if (r < 0)
160                 return r;
161
162         /* Address=address/prefixlen */
163
164         /* prefixlen */
165         e = strchr(rvalue, '/');
166         if (e) {
167                 unsigned i;
168                 r = safe_atou(e + 1, &i);
169                 if (r < 0) {
170                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
171                                    "Interface prefix length is invalid, "
172                                    "ignoring assignment: %s", e + 1);
173                         return 0;
174                 }
175
176                 n->prefixlen = (unsigned char) i;
177                 n->netmask.s_addr = htonl(0xfffffffflu >> n->prefixlen);
178
179                 address = strndup(rvalue, e - rvalue);
180                 if (!address)
181                         return log_oom();
182         } else {
183                 address = strdup(rvalue);
184                 if (!address)
185                         return log_oom();
186         }
187
188         r = net_parse_inaddr(address, &n->family, &n->in_addr);
189         if (r < 0) {
190                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
191                            "Address is invalid, ignoring assignment: %s", address);
192                 return 0;
193         }
194
195         n = NULL;
196
197         return 0;
198 }
199
200 int config_parse_label(const char *unit,
201                 const char *filename,
202                 unsigned line,
203                 const char *section,
204                 unsigned section_line,
205                 const char *lvalue,
206                 int ltype,
207                 const char *rvalue,
208                 void *data,
209                 void *userdata) {
210         Network *network = userdata;
211         _cleanup_address_free_ Address *n = NULL;
212         char *label;
213         int r;
214
215         assert(filename);
216         assert(section);
217         assert(lvalue);
218         assert(rvalue);
219         assert(data);
220
221         r = address_new(network, section_line, &n);
222         if (r < 0)
223                 return r;
224
225         label = strdup(rvalue);
226         if (!label)
227                 return log_oom();
228
229         if (!ascii_is_valid(label) || strlen(label) >= IFNAMSIZ) {
230                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
231                            "Interface label is not ASCII clean or is too"
232                            " long, ignoring assignment: %s", rvalue);
233                 free(label);
234                 return 0;
235         }
236
237         free(n->label);
238         if (*label)
239                 n->label = label;
240         else {
241                 free(label);
242                 n->label = NULL;
243         }
244
245         n = NULL;
246
247         return 0;
248 }