]>
Commit | Line | Data |
---|---|---|
7951dea2 SS |
1 | /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ |
2 | ||
3 | /*** | |
4 | This file is part of systemd. | |
5 | ||
6 | Copyright 2014 Susant Sahani <susant@redhat.com> | |
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 <netinet/ether.h> | |
23 | #include <arpa/inet.h> | |
24 | #include <net/if.h> | |
25 | #include <linux/ip.h> | |
26 | #include <linux/if_tunnel.h> | |
7951dea2 SS |
27 | |
28 | #include "sd-rtnl.h" | |
29 | #include "networkd.h" | |
30 | #include "network-internal.h" | |
31 | #include "util.h" | |
81577dc2 | 32 | #include "missing.h" |
6ef892fc | 33 | #include "conf-parser.h" |
7951dea2 SS |
34 | |
35 | ||
36 | static int netdev_fill_ipip_rtnl_message(Link *link, sd_rtnl_message *m) { | |
37 | NetDev *netdev; | |
38 | int r; | |
39 | ||
40 | assert(link); | |
41 | assert(link->network); | |
42 | assert(link->network->tunnel); | |
43 | assert(m); | |
44 | ||
45 | netdev = link->network->tunnel; | |
46 | ||
4826dd68 TG |
47 | assert(netdev->family == AF_INET); |
48 | ||
af4e9e2c | 49 | r = sd_rtnl_message_append_string(m, IFLA_IFNAME, netdev->ifname); |
7951dea2 SS |
50 | if (r < 0) { |
51 | log_error_netdev(netdev, | |
52 | "Could not append IFLA_IFNAME, attribute: %s", | |
53 | strerror(-r)); | |
54 | return r; | |
55 | } | |
56 | ||
57 | if(netdev->mtu) { | |
58 | r = sd_rtnl_message_append_u32(m, IFLA_MTU, netdev->mtu); | |
59 | if (r < 0) { | |
60 | log_error_netdev(netdev, | |
61 | "Could not append IFLA_MTU attribute: %s", | |
62 | strerror(-r)); | |
63 | return r; | |
64 | } | |
65 | } | |
66 | ||
96c90742 TG |
67 | if (netdev->mac) { |
68 | r = sd_rtnl_message_append_ether_addr(m, IFLA_ADDRESS, netdev->mac); | |
69 | if (r < 0) { | |
70 | log_error_netdev(netdev, | |
71 | "Colud not append IFLA_ADDRESS attribute: %s", | |
72 | strerror(-r)); | |
73 | return r; | |
74 | } | |
75 | } | |
76 | ||
7951dea2 SS |
77 | r = sd_rtnl_message_open_container(m, IFLA_LINKINFO); |
78 | if (r < 0) { | |
79 | log_error_netdev(netdev, | |
80 | "Could not append IFLA_LINKINFO attribute: %s", | |
81 | strerror(-r)); | |
82 | return r; | |
83 | } | |
84 | ||
85 | r = sd_rtnl_message_open_container_union(m, IFLA_INFO_DATA, | |
86 | netdev_kind_to_string(netdev->kind)); | |
87 | if (r < 0) { | |
88 | log_error_netdev(netdev, | |
89 | "Could not append IFLA_INFO_DATA attribute: %s", | |
90 | strerror(-r)); | |
91 | return r; | |
92 | } | |
93 | ||
94 | r = sd_rtnl_message_append_u32(m, IFLA_IPTUN_LINK, link->ifindex); | |
95 | if (r < 0) { | |
96 | log_error_netdev(netdev, | |
97 | "Could not append IFLA_IPTUN_LINK attribute: %s", | |
98 | strerror(-r)); | |
99 | return r; | |
100 | } | |
101 | ||
4826dd68 | 102 | r = sd_rtnl_message_append_in_addr(m, IFLA_IPTUN_LOCAL, &netdev->local.in); |
7951dea2 SS |
103 | if (r < 0) { |
104 | log_error_netdev(netdev, | |
105 | "Could not append IFLA_IPTUN_LOCAL attribute: %s", | |
106 | strerror(-r)); | |
107 | return r; | |
108 | } | |
109 | ||
4826dd68 | 110 | r = sd_rtnl_message_append_in_addr(m, IFLA_IPTUN_REMOTE, &netdev->remote.in); |
7951dea2 SS |
111 | if (r < 0) { |
112 | log_error_netdev(netdev, | |
113 | "Could not append IFLA_IPTUN_REMOTE attribute: %s", | |
114 | strerror(-r)); | |
115 | return r; | |
116 | } | |
117 | ||
1324e3ae | 118 | r = sd_rtnl_message_append_u8(m, IFLA_IPTUN_TTL, netdev->ttl); |
9ae70211 SS |
119 | if (r < 0) { |
120 | log_error_netdev(netdev, | |
121 | "Could not append IFLA_IPTUN_TTL attribute: %s", | |
122 | strerror(-r)); | |
123 | return r; | |
124 | } | |
125 | ||
7951dea2 SS |
126 | r = sd_rtnl_message_close_container(m); |
127 | if (r < 0) { | |
128 | log_error_netdev(netdev, | |
129 | "Could not append IFLA_INFO_DATA attribute: %s", | |
130 | strerror(-r)); | |
131 | return r; | |
132 | } | |
133 | ||
134 | r = sd_rtnl_message_close_container(m); | |
135 | if (r < 0) { | |
136 | log_error_netdev(netdev, | |
137 | "Could not append IFLA_LINKINFO attribute: %s", | |
138 | strerror(-r)); | |
139 | return r; | |
140 | } | |
141 | ||
142 | return r; | |
143 | } | |
144 | ||
abf446af SS |
145 | static int netdev_fill_sit_rtnl_message(Link *link, sd_rtnl_message *m) { |
146 | NetDev *netdev; | |
147 | int r; | |
148 | ||
149 | assert(link); | |
150 | assert(link->network); | |
151 | assert(link->network->tunnel); | |
152 | assert(m); | |
153 | ||
154 | netdev = link->network->tunnel; | |
155 | ||
4826dd68 TG |
156 | assert(netdev->family == AF_INET); |
157 | ||
abf446af SS |
158 | r = sd_rtnl_message_append_string(m, IFLA_IFNAME, netdev->ifname); |
159 | if (r < 0) { | |
160 | log_error_netdev(netdev, | |
161 | "Could not append IFLA_IFNAME, attribute: %s", | |
162 | strerror(-r)); | |
163 | return r; | |
164 | } | |
165 | ||
166 | if(netdev->mtu) { | |
167 | r = sd_rtnl_message_append_u32(m, IFLA_MTU, netdev->mtu); | |
168 | if (r < 0) { | |
169 | log_error_netdev(netdev, | |
170 | "Could not append IFLA_MTU attribute: %s", | |
171 | strerror(-r)); | |
172 | return r; | |
173 | } | |
174 | } | |
175 | ||
96c90742 TG |
176 | if (netdev->mac) { |
177 | r = sd_rtnl_message_append_ether_addr(m, IFLA_ADDRESS, netdev->mac); | |
178 | if (r < 0) { | |
179 | log_error_netdev(netdev, | |
180 | "Colud not append IFLA_ADDRESS attribute: %s", | |
181 | strerror(-r)); | |
182 | return r; | |
183 | } | |
184 | } | |
185 | ||
abf446af SS |
186 | r = sd_rtnl_message_open_container(m, IFLA_LINKINFO); |
187 | if (r < 0) { | |
188 | log_error_netdev(netdev, | |
189 | "Could not append IFLA_LINKINFO attribute: %s", | |
190 | strerror(-r)); | |
191 | return r; | |
192 | } | |
193 | ||
194 | r = sd_rtnl_message_open_container_union(m, IFLA_INFO_DATA, | |
195 | netdev_kind_to_string(netdev->kind)); | |
196 | if (r < 0) { | |
197 | log_error_netdev(netdev, | |
198 | "Could not append IFLA_INFO_DATA attribute: %s", | |
199 | strerror(-r)); | |
200 | return r; | |
201 | } | |
202 | ||
203 | r = sd_rtnl_message_append_u32(m, IFLA_IPTUN_LINK, link->ifindex); | |
204 | if (r < 0) { | |
205 | log_error_netdev(netdev, | |
206 | "Could not append IFLA_IPTUN_LINK attribute: %s", | |
207 | strerror(-r)); | |
208 | return r; | |
209 | } | |
210 | ||
4826dd68 | 211 | r = sd_rtnl_message_append_in_addr(m, IFLA_IPTUN_LOCAL, &netdev->local.in); |
abf446af SS |
212 | if (r < 0) { |
213 | log_error_netdev(netdev, | |
214 | "Could not append IFLA_IPTUN_LOCAL attribute: %s", | |
215 | strerror(-r)); | |
216 | return r; | |
217 | } | |
218 | ||
4826dd68 | 219 | r = sd_rtnl_message_append_in_addr(m, IFLA_IPTUN_REMOTE, &netdev->remote.in); |
abf446af SS |
220 | if (r < 0) { |
221 | log_error_netdev(netdev, | |
222 | "Could not append IFLA_IPTUN_REMOTE attribute: %s", | |
223 | strerror(-r)); | |
224 | return r; | |
225 | } | |
226 | ||
1324e3ae | 227 | r = sd_rtnl_message_append_u8(m, IFLA_IPTUN_TOS, netdev->tos); |
abf446af SS |
228 | if (r < 0) { |
229 | log_error_netdev(netdev, | |
230 | "Could not append IFLA_IPTUN_TOS attribute: %s", | |
231 | strerror(-r)); | |
232 | return r; | |
233 | } | |
234 | ||
a9f434cf SS |
235 | r = sd_rtnl_message_append_u8(m, IFLA_IPTUN_PMTUDISC, netdev->tunnel_pmtudisc); |
236 | if (r < 0) { | |
237 | log_error_netdev(netdev, | |
238 | "Could not append IFLA_IPTUN_PMTUDISC attribute: %s", | |
239 | strerror(-r)); | |
240 | return r; | |
241 | } | |
242 | ||
abf446af SS |
243 | r = sd_rtnl_message_close_container(m); |
244 | if (r < 0) { | |
245 | log_error_netdev(netdev, | |
246 | "Could not append IFLA_INFO_DATA attribute: %s", | |
247 | strerror(-r)); | |
248 | return r; | |
249 | } | |
250 | ||
251 | r = sd_rtnl_message_close_container(m); | |
252 | if (r < 0) { | |
253 | log_error_netdev(netdev, | |
254 | "Could not append IFLA_LINKINFO attribute: %s", | |
255 | strerror(-r)); | |
256 | return r; | |
257 | } | |
258 | ||
259 | return r; | |
260 | } | |
261 | ||
8bb088c5 SS |
262 | static int netdev_fill_ipgre_rtnl_message(Link *link, sd_rtnl_message *m) { |
263 | NetDev *netdev; | |
264 | int r; | |
265 | ||
266 | assert(link); | |
267 | assert(link->network); | |
268 | assert(link->network->tunnel); | |
269 | assert(m); | |
270 | ||
271 | netdev = link->network->tunnel; | |
272 | ||
4826dd68 TG |
273 | assert(netdev->family == AF_INET); |
274 | ||
8bb088c5 SS |
275 | r = sd_rtnl_message_append_string(m, IFLA_IFNAME, netdev->ifname); |
276 | if (r < 0) { | |
277 | log_error_netdev(netdev, | |
278 | "Could not append IFLA_IFNAME, attribute: %s", | |
279 | strerror(-r)); | |
280 | return r; | |
281 | } | |
282 | ||
283 | if(netdev->mtu) { | |
284 | r = sd_rtnl_message_append_u32(m, IFLA_MTU, netdev->mtu); | |
285 | if (r < 0) { | |
286 | log_error_netdev(netdev, | |
287 | "Could not append IFLA_MTU attribute: %s", | |
288 | strerror(-r)); | |
289 | return r; | |
290 | } | |
291 | } | |
292 | ||
96c90742 TG |
293 | if (netdev->mac) { |
294 | r = sd_rtnl_message_append_ether_addr(m, IFLA_ADDRESS, netdev->mac); | |
295 | if (r < 0) { | |
296 | log_error_netdev(netdev, | |
297 | "Colud not append IFLA_ADDRESS attribute: %s", | |
298 | strerror(-r)); | |
299 | return r; | |
300 | } | |
301 | } | |
302 | ||
8bb088c5 SS |
303 | r = sd_rtnl_message_open_container(m, IFLA_LINKINFO); |
304 | if (r < 0) { | |
305 | log_error_netdev(netdev, | |
306 | "Could not append IFLA_LINKINFO attribute: %s", | |
307 | strerror(-r)); | |
308 | return r; | |
309 | } | |
310 | ||
311 | r = sd_rtnl_message_open_container_union(m, IFLA_INFO_DATA, | |
312 | netdev_kind_to_string(netdev->kind)); | |
313 | if (r < 0) { | |
314 | log_error_netdev(netdev, | |
315 | "Could not append IFLA_INFO_DATA attribute: %s", | |
316 | strerror(-r)); | |
317 | return r; | |
318 | } | |
319 | ||
320 | r = sd_rtnl_message_append_u32(m, IFLA_GRE_LINK, link->ifindex); | |
321 | if (r < 0) { | |
322 | log_error_netdev(netdev, | |
323 | "Could not append IFLA_GRE_LINK attribute: %s", | |
324 | strerror(-r)); | |
325 | return r; | |
326 | } | |
327 | ||
4826dd68 | 328 | r = sd_rtnl_message_append_in_addr(m, IFLA_GRE_LOCAL, &netdev->local.in); |
8bb088c5 SS |
329 | if (r < 0) { |
330 | log_error_netdev(netdev, | |
331 | "Could not append IFLA_GRE_LOCAL attribute: %s", | |
332 | strerror(-r)); | |
333 | return r; | |
334 | } | |
335 | ||
4826dd68 | 336 | r = sd_rtnl_message_append_in_addr(m, IFLA_GRE_REMOTE, &netdev->remote.in); |
8bb088c5 SS |
337 | if (r < 0) { |
338 | log_error_netdev(netdev, | |
339 | "Could not append IFLA_GRE_REMOTE attribute: %s", | |
340 | strerror(-r)); | |
341 | return r; | |
342 | } | |
343 | ||
1324e3ae | 344 | r = sd_rtnl_message_append_u8(m, IFLA_GRE_TTL, netdev->ttl); |
8bb088c5 SS |
345 | if (r < 0) { |
346 | log_error_netdev(netdev, | |
347 | "Could not append IFLA_GRE_TTL attribute: %s", | |
348 | strerror(-r)); | |
349 | return r; | |
350 | } | |
351 | ||
1324e3ae | 352 | r = sd_rtnl_message_append_u8(m, IFLA_GRE_TOS, netdev->tos); |
8bb088c5 SS |
353 | if (r < 0) { |
354 | log_error_netdev(netdev, | |
355 | "Could not append IFLA_GRE_TOS attribute: %s", | |
356 | strerror(-r)); | |
357 | return r; | |
358 | } | |
359 | ||
360 | r = sd_rtnl_message_close_container(m); | |
361 | if (r < 0) { | |
362 | log_error_netdev(netdev, | |
363 | "Could not append IFLA_INFO_DATA attribute: %s", | |
364 | strerror(-r)); | |
365 | return r; | |
366 | } | |
367 | ||
368 | r = sd_rtnl_message_close_container(m); | |
369 | if (r < 0) { | |
370 | log_error_netdev(netdev, | |
371 | "Could not append IFLA_LINKINFO attribute: %s", | |
372 | strerror(-r)); | |
373 | return r; | |
374 | } | |
375 | ||
376 | return r; | |
377 | } | |
378 | ||
a613382b SS |
379 | static int netdev_fill_vti_rtnl_message(Link *link, sd_rtnl_message *m) { |
380 | NetDev *netdev; | |
381 | int r; | |
382 | ||
383 | assert(link); | |
384 | assert(link->network); | |
385 | assert(link->network->tunnel); | |
386 | assert(m); | |
387 | ||
388 | netdev = link->network->tunnel; | |
389 | ||
4826dd68 TG |
390 | assert(netdev->family == AF_INET); |
391 | ||
a613382b SS |
392 | r = sd_rtnl_message_append_string(m, IFLA_IFNAME, netdev->ifname); |
393 | if (r < 0) { | |
394 | log_error_netdev(netdev, | |
395 | "Could not append IFLA_IFNAME, attribute: %s", | |
396 | strerror(-r)); | |
397 | return r; | |
398 | } | |
399 | ||
400 | if(netdev->mtu) { | |
401 | r = sd_rtnl_message_append_u32(m, IFLA_MTU, netdev->mtu); | |
402 | if (r < 0) { | |
403 | log_error_netdev(netdev, | |
404 | "Could not append IFLA_MTU attribute: %s", | |
405 | strerror(-r)); | |
406 | return r; | |
407 | } | |
408 | } | |
409 | ||
96c90742 TG |
410 | if (netdev->mac) { |
411 | r = sd_rtnl_message_append_ether_addr(m, IFLA_ADDRESS, netdev->mac); | |
412 | if (r < 0) { | |
413 | log_error_netdev(netdev, | |
414 | "Colud not append IFLA_ADDRESS attribute: %s", | |
415 | strerror(-r)); | |
416 | return r; | |
417 | } | |
418 | } | |
419 | ||
a613382b SS |
420 | r = sd_rtnl_message_open_container(m, IFLA_LINKINFO); |
421 | if (r < 0) { | |
422 | log_error_netdev(netdev, | |
423 | "Could not append IFLA_LINKINFO attribute: %s", | |
424 | strerror(-r)); | |
425 | return r; | |
426 | } | |
427 | ||
428 | r = sd_rtnl_message_open_container_union(m, IFLA_INFO_DATA, | |
429 | netdev_kind_to_string(netdev->kind)); | |
430 | if (r < 0) { | |
431 | log_error_netdev(netdev, | |
432 | "Could not append IFLA_INFO_DATA attribute: %s", | |
433 | strerror(-r)); | |
434 | return r; | |
435 | } | |
436 | ||
437 | r = sd_rtnl_message_append_u32(m, IFLA_VTI_LINK, link->ifindex); | |
438 | if (r < 0) { | |
439 | log_error_netdev(netdev, | |
440 | "Could not append IFLA_IPTUN_LINK attribute: %s", | |
441 | strerror(-r)); | |
442 | return r; | |
443 | } | |
444 | ||
4826dd68 | 445 | r = sd_rtnl_message_append_in_addr(m, IFLA_VTI_LOCAL, &netdev->local.in); |
a613382b SS |
446 | if (r < 0) { |
447 | log_error_netdev(netdev, | |
448 | "Could not append IFLA_IPTUN_LOCAL attribute: %s", | |
449 | strerror(-r)); | |
450 | return r; | |
451 | } | |
452 | ||
4826dd68 | 453 | r = sd_rtnl_message_append_in_addr(m, IFLA_VTI_REMOTE, &netdev->remote.in); |
a613382b SS |
454 | if (r < 0) { |
455 | log_error_netdev(netdev, | |
456 | "Could not append IFLA_IPTUN_REMOTE attribute: %s", | |
457 | strerror(-r)); | |
458 | return r; | |
459 | } | |
460 | ||
461 | r = sd_rtnl_message_close_container(m); | |
462 | if (r < 0) { | |
463 | log_error_netdev(netdev, | |
464 | "Could not append IFLA_INFO_DATA attribute: %s", | |
465 | strerror(-r)); | |
466 | return r; | |
467 | } | |
468 | ||
469 | r = sd_rtnl_message_close_container(m); | |
470 | if (r < 0) { | |
471 | log_error_netdev(netdev, | |
472 | "Could not append IFLA_LINKINFO attribute: %s", | |
473 | strerror(-r)); | |
474 | return r; | |
475 | } | |
476 | ||
477 | return r; | |
478 | } | |
8bb088c5 | 479 | |
d5b3d845 | 480 | int netdev_create_tunnel(NetDev *netdev, Link *link, sd_rtnl_message_handler_t callback) { |
7951dea2 | 481 | _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL; |
7951dea2 SS |
482 | int r; |
483 | ||
7951dea2 | 484 | assert(netdev); |
af4e9e2c | 485 | assert(netdev->ifname); |
7951dea2 SS |
486 | assert(netdev->manager); |
487 | assert(netdev->manager->rtnl); | |
d5b3d845 TG |
488 | assert(link); |
489 | assert(link->network); | |
490 | assert(link->network->tunnel == netdev); | |
7951dea2 SS |
491 | |
492 | r = sd_rtnl_message_new_link(netdev->manager->rtnl, &m, RTM_NEWLINK, 0); | |
493 | if (r < 0) { | |
494 | log_error_netdev(netdev, | |
495 | "Could not allocate RTM_NEWLINK message: %s", | |
496 | strerror(-r)); | |
497 | return r; | |
498 | } | |
499 | ||
500 | switch(netdev->kind) { | |
501 | case NETDEV_KIND_IPIP: | |
502 | r = netdev_fill_ipip_rtnl_message(link, m); | |
503 | if(r < 0) | |
504 | return r; | |
505 | break; | |
7951dea2 | 506 | case NETDEV_KIND_SIT: |
abf446af SS |
507 | r = netdev_fill_sit_rtnl_message(link, m); |
508 | if(r < 0) | |
509 | return r; | |
510 | break; | |
a613382b SS |
511 | case NETDEV_KIND_VTI: |
512 | netdev_fill_vti_rtnl_message(link, m); | |
513 | if(r < 0) | |
514 | return r; | |
515 | break; | |
abf446af | 516 | case NETDEV_KIND_GRE: |
8bb088c5 SS |
517 | r = netdev_fill_ipgre_rtnl_message(link, m); |
518 | if(r < 0) | |
519 | return r; | |
520 | break; | |
7951dea2 SS |
521 | default: |
522 | return -ENOTSUP; | |
523 | } | |
524 | ||
d5b3d845 | 525 | r = sd_rtnl_call_async(netdev->manager->rtnl, m, callback, link, 0, NULL); |
7951dea2 SS |
526 | if (r < 0) { |
527 | log_error_netdev(netdev, | |
528 | "Could not send rtnetlink message: %s", strerror(-r)); | |
529 | return r; | |
530 | } | |
531 | ||
e04468de TG |
532 | link_ref(link); |
533 | ||
7951dea2 SS |
534 | log_debug_netdev(netdev, "Creating tunnel netdev: %s", |
535 | netdev_kind_to_string(netdev->kind)); | |
536 | ||
537 | netdev->state = NETDEV_STATE_CREATING; | |
538 | ||
539 | return 0; | |
540 | } | |
6ef892fc TG |
541 | |
542 | int config_parse_tunnel_address(const char *unit, | |
543 | const char *filename, | |
544 | unsigned line, | |
545 | const char *section, | |
546 | unsigned section_line, | |
547 | const char *lvalue, | |
548 | int ltype, | |
549 | const char *rvalue, | |
550 | void *data, | |
551 | void *userdata) { | |
552 | NetDev *n = userdata; | |
553 | union in_addr_union *addr = data; | |
554 | int r; | |
555 | ||
556 | assert(filename); | |
557 | assert(lvalue); | |
558 | assert(rvalue); | |
559 | assert(data); | |
560 | ||
561 | r = net_parse_inaddr(rvalue, &n->family, addr); | |
562 | if (r < 0) { | |
563 | log_syntax(unit, LOG_ERR, filename, line, EINVAL, | |
564 | "Tunnel address is invalid, ignoring assignment: %s", rvalue); | |
565 | return 0; | |
566 | } | |
567 | ||
568 | return 0; | |
569 | } |