chiark / gitweb /
networkd: make metric of routes configurable
[elogind.git] / src / network / networkd-vlan.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 #include "network-internal.h"
26 #include "list.h"
27
28 int netdev_create_vlan(NetDev *netdev, Link *link, sd_rtnl_message_handler_t callback) {
29         _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
30         const char *kind;
31         int r;
32
33         assert(netdev);
34         assert(netdev->kind == NETDEV_KIND_VLAN);
35         assert(link);
36         assert(callback);
37         assert(netdev->ifname);
38         assert(netdev->manager);
39         assert(netdev->manager->rtnl);
40
41         r = sd_rtnl_message_new_link(netdev->manager->rtnl, &req, RTM_NEWLINK, 0);
42         if (r < 0) {
43                 log_error_netdev(netdev,
44                                  "Could not allocate RTM_NEWLINK message: %s",
45                                  strerror(-r));
46                 return r;
47         }
48
49         if (link) {
50                 r = sd_rtnl_message_append_u32(req, IFLA_LINK, link->ifindex);
51                 if (r < 0) {
52                         log_error_netdev(netdev,
53                                          "Could not append IFLA_LINK attribute: %s",
54                                          strerror(-r));
55                         return r;
56                 }
57         }
58
59         r = sd_rtnl_message_append_string(req, IFLA_IFNAME, netdev->ifname);
60         if (r < 0) {
61                 log_error_netdev(netdev,
62                                  "Could not append IFLA_IFNAME attribute: %s",
63                                  strerror(-r));
64                 return r;
65         }
66
67         if (netdev->mtu) {
68                 r = sd_rtnl_message_append_u32(req, IFLA_MTU, netdev->mtu);
69                 if (r < 0) {
70                         log_error_netdev(netdev,
71                                          "Could not append IFLA_MTU attribute: %s",
72                                          strerror(-r));
73                         return r;
74                 }
75         }
76
77         if (netdev->mac) {
78                 r = sd_rtnl_message_append_ether_addr(req, IFLA_ADDRESS, netdev->mac);
79                 if (r < 0) {
80                         log_error_netdev(netdev,
81                                          "Colud not append IFLA_ADDRESS attribute: %s",
82                                          strerror(-r));
83                     return r;
84                 }
85         }
86
87         r = sd_rtnl_message_open_container(req, IFLA_LINKINFO);
88         if (r < 0) {
89                 log_error_netdev(netdev,
90                                  "Could not open IFLA_LINKINFO container: %s",
91                                  strerror(-r));
92                 return r;
93         }
94
95         kind = netdev_kind_to_string(netdev->kind);
96         if (!kind) {
97                 log_error_netdev(netdev, "Invalid kind");
98                 return -EINVAL;
99         }
100
101         r = sd_rtnl_message_open_container_union(req, IFLA_INFO_DATA, kind);
102         if (r < 0) {
103                 log_error_netdev(netdev,
104                                  "Could not open IFLA_INFO_DATA container: %s",
105                                   strerror(-r));
106                 return r;
107         }
108
109         if (netdev->vlanid <= VLANID_MAX) {
110                 r = sd_rtnl_message_append_u16(req, IFLA_VLAN_ID, netdev->vlanid);
111                 if (r < 0) {
112                         log_error_netdev(netdev,
113                                          "Could not append IFLA_VLAN_ID attribute: %s",
114                                          strerror(-r));
115                         return r;
116                 }
117         }
118
119         r = sd_rtnl_message_close_container(req);
120         if (r < 0) {
121                 log_error_netdev(netdev,
122                                  "Could not close IFLA_INFO_DATA container %s",
123                                  strerror(-r));
124                 return r;
125         }
126
127         r = sd_rtnl_message_close_container(req);
128         if (r < 0) {
129                 log_error_netdev(netdev,
130                                  "Could not close IFLA_LINKINFO container %s",
131                                  strerror(-r));
132                 return r;
133         }
134
135         r = sd_rtnl_call_async(netdev->manager->rtnl, req, callback, link, 0, NULL);
136         if (r < 0) {
137                 log_error_netdev(netdev,
138                                  "Could not send rtnetlink message: %s", strerror(-r));
139                 return r;
140         }
141
142         link_ref(link);
143
144         log_debug_netdev(netdev, "creating netdev");
145
146         netdev->state = NETDEV_STATE_CREATING;
147
148         return 0;
149 }