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