]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/netdev/vxcan.c
man/systemd-sysext: list ephemeral/ephemeral-import in the list of options
[thirdparty/systemd.git] / src / network / netdev / vxcan.c
CommitLineData
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
11static 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
35static 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
51static 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
58static void netdev_vxcan_detach(NetDev *netdev) {
59 VxCan *v = VXCAN(netdev);
60
61 netdev_detach_name(netdev, v->ifname_peer);
62}
63
64static 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
98static 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
112static void vxcan_done(NetDev *netdev) {
113 VxCan *v = VXCAN(netdev);
d6df583c
SS
114
115 free(v->ifname_peer);
116}
117
118const 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};