]>
Commit | Line | Data |
---|---|---|
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 | static int netdev_vxcan_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) { | |
12 | assert(!link); | |
13 | assert(m); | |
14 | ||
15 | VxCan *v = VXCAN(netdev); | |
16 | int r; | |
17 | ||
18 | r = sd_netlink_message_open_container(m, VXCAN_INFO_PEER); | |
19 | if (r < 0) | |
20 | return r; | |
21 | ||
22 | if (v->ifname_peer) { | |
23 | r = sd_netlink_message_append_string(m, IFLA_IFNAME, v->ifname_peer); | |
24 | if (r < 0) | |
25 | return r; | |
26 | } | |
27 | ||
28 | r = sd_netlink_message_close_container(m); | |
29 | if (r < 0) | |
30 | return r; | |
31 | ||
32 | return 0; | |
33 | } | |
34 | ||
35 | static int netdev_vxcan_verify(NetDev *netdev, const char *filename) { | |
36 | assert(filename); | |
37 | ||
38 | VxCan *v = VXCAN(netdev); | |
39 | ||
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); | |
43 | ||
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 | ||
48 | return 0; | |
49 | } | |
50 | ||
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 | ||
112 | static void vxcan_done(NetDev *netdev) { | |
113 | VxCan *v = VXCAN(netdev); | |
114 | ||
115 | free(v->ifname_peer); | |
116 | } | |
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 | }; |