/src/systemd/src/network/netdev/vxcan.c
Line | Count | Source |
1 | | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
2 | | |
3 | | #include <linux/can/vxcan.h> |
4 | | #include <linux/if_arp.h> |
5 | | |
6 | | #include "sd-netlink.h" |
7 | | |
8 | | #include "string-util.h" |
9 | | #include "vxcan.h" |
10 | | |
11 | 0 | static int netdev_vxcan_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) { |
12 | 0 | assert(!link); |
13 | 0 | assert(m); |
14 | |
|
15 | 0 | VxCan *v = VXCAN(netdev); |
16 | 0 | int r; |
17 | |
|
18 | 0 | r = sd_netlink_message_open_container(m, VXCAN_INFO_PEER); |
19 | 0 | if (r < 0) |
20 | 0 | return r; |
21 | | |
22 | 0 | if (v->ifname_peer) { |
23 | 0 | r = sd_netlink_message_append_string(m, IFLA_IFNAME, v->ifname_peer); |
24 | 0 | if (r < 0) |
25 | 0 | return r; |
26 | 0 | } |
27 | | |
28 | 0 | r = sd_netlink_message_close_container(m); |
29 | 0 | if (r < 0) |
30 | 0 | return r; |
31 | | |
32 | 0 | return 0; |
33 | 0 | } |
34 | | |
35 | 67 | static int netdev_vxcan_verify(NetDev *netdev, const char *filename) { |
36 | 67 | assert(filename); |
37 | | |
38 | 67 | VxCan *v = VXCAN(netdev); |
39 | | |
40 | 67 | if (!v->ifname_peer) |
41 | 1 | return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL), |
42 | 66 | "VxCan NetDev without peer name configured in %s. Ignoring", filename); |
43 | | |
44 | 66 | if (streq(v->ifname_peer, netdev->ifname)) |
45 | 1 | return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL), |
46 | 65 | "VxCan peer name cannot be the same as the main interface name."); |
47 | | |
48 | 65 | return 0; |
49 | 66 | } |
50 | | |
51 | 0 | static int netdev_vxcan_attach(NetDev *netdev) { |
52 | 0 | VxCan *v = VXCAN(netdev); |
53 | 0 | assert(v->ifname_peer); |
54 | |
|
55 | 0 | return netdev_attach_name(netdev, v->ifname_peer); |
56 | 0 | } |
57 | | |
58 | 67 | static void netdev_vxcan_detach(NetDev *netdev) { |
59 | 67 | VxCan *v = VXCAN(netdev); |
60 | | |
61 | 67 | netdev_detach_name(netdev, v->ifname_peer); |
62 | 67 | } |
63 | | |
64 | 0 | static int netdev_vxcan_set_ifindex(NetDev *netdev, const char *name, int ifindex) { |
65 | 0 | VxCan *v = VXCAN(netdev); |
66 | 0 | int r; |
67 | |
|
68 | 0 | assert(name); |
69 | 0 | assert(ifindex > 0); |
70 | |
|
71 | 0 | if (streq(netdev->ifname, name)) { |
72 | 0 | r = netdev_set_ifindex_internal(netdev, ifindex); |
73 | 0 | if (r <= 0) |
74 | 0 | return r; |
75 | |
|
76 | 0 | } else if (streq(v->ifname_peer, name)) { |
77 | 0 | if (v->ifindex_peer == ifindex) |
78 | 0 | return 0; /* already set */ |
79 | 0 | if (v->ifindex_peer > 0 && v->ifindex_peer != ifindex) |
80 | 0 | return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EEXIST), |
81 | 0 | "Could not set ifindex %i for peer %s, already set to %i.", |
82 | 0 | ifindex, v->ifname_peer, v->ifindex_peer); |
83 | | |
84 | 0 | v->ifindex_peer = ifindex; |
85 | 0 | log_netdev_debug(netdev, "Peer interface %s gained index %i.", v->ifname_peer, ifindex); |
86 | |
|
87 | 0 | } else |
88 | 0 | return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL), |
89 | 0 | "Received netlink message with unexpected interface name %s (ifindex=%i).", |
90 | 0 | name, ifindex); |
91 | | |
92 | 0 | if (netdev->ifindex > 0 && v->ifindex_peer > 0) |
93 | 0 | return netdev_enter_ready(netdev); |
94 | | |
95 | 0 | return 0; |
96 | 0 | } |
97 | | |
98 | 0 | static int netdev_vxcan_get_ifindex(NetDev *netdev, const char *name) { |
99 | 0 | VxCan *v = VXCAN(netdev); |
100 | |
|
101 | 0 | assert(name); |
102 | |
|
103 | 0 | if (streq(netdev->ifname, name)) |
104 | 0 | return netdev->ifindex; |
105 | | |
106 | 0 | if (streq(v->ifname_peer, name)) |
107 | 0 | return v->ifindex_peer; |
108 | | |
109 | 0 | return -ENODEV; |
110 | 0 | } |
111 | | |
112 | 67 | static void vxcan_done(NetDev *netdev) { |
113 | 67 | VxCan *v = VXCAN(netdev); |
114 | | |
115 | 67 | free(v->ifname_peer); |
116 | 67 | } |
117 | | |
118 | | const NetDevVTable vxcan_vtable = { |
119 | | .object_size = sizeof(VxCan), |
120 | | .sections = NETDEV_COMMON_SECTIONS "VXCAN\0", |
121 | | .done = vxcan_done, |
122 | | .fill_message_create = netdev_vxcan_fill_message_create, |
123 | | .create_type = NETDEV_CREATE_INDEPENDENT, |
124 | | .config_verify = netdev_vxcan_verify, |
125 | | .attach = netdev_vxcan_attach, |
126 | | .detach = netdev_vxcan_detach, |
127 | | .set_ifindex = netdev_vxcan_set_ifindex, |
128 | | .get_ifindex = netdev_vxcan_get_ifindex, |
129 | | .iftype = ARPHRD_CAN, |
130 | | .keep_existing = true, |
131 | | }; |