Coverage Report

Created: 2025-11-16 06:36

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/systemd/src/network/netdev/vxcan.c
Line
Count
Source
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
0
static int netdev_vxcan_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
12
0
        assert(!link);
13
0
        assert(m);
14
15
0
        VxCan *v = VXCAN(netdev);
16
0
        int r;
17
18
0
        r = sd_netlink_message_open_container(m, VXCAN_INFO_PEER);
19
0
        if (r < 0)
20
0
                return r;
21
22
0
        if (v->ifname_peer) {
23
0
                r = sd_netlink_message_append_string(m, IFLA_IFNAME, v->ifname_peer);
24
0
                if (r < 0)
25
0
                        return r;
26
0
        }
27
28
0
        r = sd_netlink_message_close_container(m);
29
0
        if (r < 0)
30
0
                return r;
31
32
0
        return 0;
33
0
}
34
35
67
static int netdev_vxcan_verify(NetDev *netdev, const char *filename) {
36
67
        assert(filename);
37
38
67
        VxCan *v = VXCAN(netdev);
39
40
67
        if (!v->ifname_peer)
41
1
                return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
42
66
                                                "VxCan NetDev without peer name configured in %s. Ignoring", filename);
43
44
66
        if (streq(v->ifname_peer, netdev->ifname))
45
1
                return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
46
65
                                                "VxCan peer name cannot be the same as the main interface name.");
47
48
65
        return 0;
49
66
}
50
51
0
static int netdev_vxcan_attach(NetDev *netdev) {
52
0
        VxCan *v = VXCAN(netdev);
53
0
        assert(v->ifname_peer);
54
55
0
        return netdev_attach_name(netdev, v->ifname_peer);
56
0
}
57
58
67
static void netdev_vxcan_detach(NetDev *netdev) {
59
67
        VxCan *v = VXCAN(netdev);
60
61
67
        netdev_detach_name(netdev, v->ifname_peer);
62
67
}
63
64
0
static int netdev_vxcan_set_ifindex(NetDev *netdev, const char *name, int ifindex) {
65
0
        VxCan *v = VXCAN(netdev);
66
0
        int r;
67
68
0
        assert(name);
69
0
        assert(ifindex > 0);
70
71
0
        if (streq(netdev->ifname, name)) {
72
0
                r = netdev_set_ifindex_internal(netdev, ifindex);
73
0
                if (r <= 0)
74
0
                        return r;
75
76
0
        } else if (streq(v->ifname_peer, name)) {
77
0
                if (v->ifindex_peer == ifindex)
78
0
                        return 0; /* already set */
79
0
                if (v->ifindex_peer > 0 && v->ifindex_peer != ifindex)
80
0
                        return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EEXIST),
81
0
                                                        "Could not set ifindex %i for peer %s, already set to %i.",
82
0
                                                        ifindex, v->ifname_peer, v->ifindex_peer);
83
84
0
                v->ifindex_peer = ifindex;
85
0
                log_netdev_debug(netdev, "Peer interface %s gained index %i.", v->ifname_peer, ifindex);
86
87
0
        } else
88
0
                return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
89
0
                                                "Received netlink message with unexpected interface name %s (ifindex=%i).",
90
0
                                                name, ifindex);
91
92
0
        if (netdev->ifindex > 0 && v->ifindex_peer > 0)
93
0
                return netdev_enter_ready(netdev);
94
95
0
        return 0;
96
0
}
97
98
0
static int netdev_vxcan_get_ifindex(NetDev *netdev, const char *name) {
99
0
        VxCan *v = VXCAN(netdev);
100
101
0
        assert(name);
102
103
0
        if (streq(netdev->ifname, name))
104
0
                return netdev->ifindex;
105
106
0
        if (streq(v->ifname_peer, name))
107
0
                return v->ifindex_peer;
108
109
0
        return -ENODEV;
110
0
}
111
112
67
static void vxcan_done(NetDev *netdev) {
113
67
        VxCan *v = VXCAN(netdev);
114
115
67
        free(v->ifname_peer);
116
67
}
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
};