1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 #include <linux/can/vxcan.h>
4 #include <linux/if_arp.h>
6 #include "sd-netlink.h"
8 #include "string-util.h"
11 static int netdev_vxcan_fill_message_create(NetDev
*netdev
, Link
*link
, sd_netlink_message
*m
) {
15 VxCan
*v
= VXCAN(netdev
);
18 r
= sd_netlink_message_open_container(m
, VXCAN_INFO_PEER
);
23 r
= sd_netlink_message_append_string(m
, IFLA_IFNAME
, v
->ifname_peer
);
28 r
= sd_netlink_message_close_container(m
);
35 static int netdev_vxcan_verify(NetDev
*netdev
, const char *filename
) {
38 VxCan
*v
= VXCAN(netdev
);
41 return log_netdev_warning_errno(netdev
, SYNTHETIC_ERRNO(EINVAL
),
42 "VxCan NetDev without peer name configured in %s. Ignoring", filename
);
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.");
51 static int netdev_vxcan_attach(NetDev
*netdev
) {
52 VxCan
*v
= VXCAN(netdev
);
53 assert(v
->ifname_peer
);
55 return netdev_attach_name(netdev
, v
->ifname_peer
);
58 static void netdev_vxcan_detach(NetDev
*netdev
) {
59 VxCan
*v
= VXCAN(netdev
);
61 netdev_detach_name(netdev
, v
->ifname_peer
);
64 static int netdev_vxcan_set_ifindex(NetDev
*netdev
, const char *name
, int ifindex
) {
65 VxCan
*v
= VXCAN(netdev
);
71 if (streq(netdev
->ifname
, name
)) {
72 r
= netdev_set_ifindex_internal(netdev
, ifindex
);
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
);
84 v
->ifindex_peer
= ifindex
;
85 log_netdev_debug(netdev
, "Peer interface %s gained index %i.", v
->ifname_peer
, ifindex
);
88 return log_netdev_warning_errno(netdev
, SYNTHETIC_ERRNO(EINVAL
),
89 "Received netlink message with unexpected interface name %s (ifindex=%i).",
92 if (netdev
->ifindex
> 0 && v
->ifindex_peer
> 0)
93 return netdev_enter_ready(netdev
);
98 static int netdev_vxcan_get_ifindex(NetDev
*netdev
, const char *name
) {
99 VxCan
*v
= VXCAN(netdev
);
103 if (streq(netdev
->ifname
, name
))
104 return netdev
->ifindex
;
106 if (streq(v
->ifname_peer
, name
))
107 return v
->ifindex_peer
;
112 static void vxcan_done(NetDev
*netdev
) {
113 VxCan
*v
= VXCAN(netdev
);
115 free(v
->ifname_peer
);
118 const NetDevVTable vxcan_vtable
= {
119 .object_size
= sizeof(VxCan
),
120 .sections
= NETDEV_COMMON_SECTIONS
"VXCAN\0",
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,