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