summaryrefslogtreecommitdiffstats
path: root/src/network/netdev/bareudp.c
blob: 22c0e49d94ced74cd57a88d6f38ed28c1d1dfc87 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/* SPDX-License-Identifier: LGPL-2.1-or-later
 * Copyright © 2020 VMware, Inc. */

#include "bareudp.h"
#include "netlink-util.h"
#include "networkd-manager.h"
#include "string-table.h"

static const char* const bare_udp_protocol_table[_BARE_UDP_PROTOCOL_MAX] = {
        [BARE_UDP_PROTOCOL_IPV4]    = "ipv4",
        [BARE_UDP_PROTOCOL_IPV6]    = "ipv6",
        [BARE_UDP_PROTOCOL_MPLS_UC] = "mpls-uc",
        [BARE_UDP_PROTOCOL_MPLS_MC] = "mpls-mc",
};

DEFINE_STRING_TABLE_LOOKUP(bare_udp_protocol, BareUDPProtocol);
DEFINE_CONFIG_PARSE_ENUM(config_parse_bare_udp_iftype, bare_udp_protocol, BareUDPProtocol,
                         "Failed to parse EtherType=");

/* callback for bareudp netdev's created without a backing Link */
static int bare_udp_netdev_create_handler(sd_netlink *rtnl, sd_netlink_message *m, NetDev *netdev) {
        int r;

        assert(netdev);
        assert(netdev->state != _NETDEV_STATE_INVALID);

        r = sd_netlink_message_get_errno(m);
        if (r == -EEXIST)
                log_netdev_info(netdev, "BareUDP netdev exists, using existing without changing its parameters.");
        else if (r < 0) {
                log_netdev_warning_errno(netdev, r, "BareUDP netdev could not be created: %m");
                netdev_drop(netdev);

                return 1;
        }

        log_netdev_debug(netdev, "BareUDP created.");

        return 1;
}

static int netdev_bare_udp_create(NetDev *netdev) {
        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
        BareUDP *u;
        int r;

        assert(netdev);

        u = BAREUDP(netdev);

        assert(u);

        r = sd_rtnl_message_new_link(netdev->manager->rtnl, &m, RTM_NEWLINK, 0);
        if (r < 0)
                return log_netdev_error_errno(netdev, r, "Could not allocate RTM_NEWLINK message: %m");

        r = sd_netlink_message_append_string(m, IFLA_IFNAME, netdev->ifname);
        if (r < 0)
                return log_netdev_error_errno(netdev, r, "Could not append IFLA_IFNAME, attribute: %m");

        r = sd_netlink_message_open_container(m, IFLA_LINKINFO);
        if (r < 0)
                return log_netdev_error_errno(netdev, r, "Could not append IFLA_LINKINFO attribute: %m");

        r = sd_netlink_message_open_container_union(m, IFLA_INFO_DATA, netdev_kind_to_string(netdev->kind));
        if (r < 0)
                return log_netdev_error_errno(netdev, r, "Could not append IFLA_INFO_DATA attribute: %m");

        r = sd_netlink_message_append_u16(m, IFLA_BAREUDP_ETHERTYPE, htobe16(u->iftype));
        if (r < 0)
                return log_netdev_error_errno(netdev, r, "Could not append IFLA_BAREUDP_ETHERTYPE attribute: %m");

        r = sd_netlink_message_append_u16(m, IFLA_BAREUDP_PORT, htobe16(u->dest_port));
        if (r < 0)
                return log_netdev_error_errno(netdev, r, "Could not append IFLA_BAREUDP_PORT attribute: %m");

        r = sd_netlink_message_close_container(m);
        if (r < 0)
                return log_netdev_error_errno(netdev, r, "Could not append IFLA_INFO_DATA attribute: %m");

        r = sd_netlink_message_close_container(m);
        if (r < 0)
                return log_netdev_error_errno(netdev, r, "Could not append IFLA_LINKINFO attribute: %m");

        r = netlink_call_async(netdev->manager->rtnl, NULL, m, bare_udp_netdev_create_handler,
                               netdev_destroy_callback, netdev);
        if (r < 0)
                return log_netdev_error_errno(netdev, r, "Could not send rtnetlink message: %m");

        netdev_ref(netdev);
        netdev->state = NETDEV_STATE_CREATING;

        log_netdev_debug(netdev, "Creating");

        return r;
}

static int netdev_bare_udp_verify(NetDev *netdev, const char *filename) {
        BareUDP *u;

        assert(netdev);
        assert(filename);

        u = BAREUDP(netdev);

        assert(u);

        if (u->dest_port == 0)
                return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
                                                "%s: BareUDP DesinationPort= is not set. Ignoring.", filename);

        if (u->iftype == _BARE_UDP_PROTOCOL_INVALID)
                return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
                                                "%s: BareUDP EtherType= is not set. Ignoring.", filename);

        return 0;
}

static void bare_udp_init(NetDev *netdev) {
        BareUDP *u;

        assert(netdev);

        u = BAREUDP(netdev);

        assert(u);

        u->iftype = _BARE_UDP_PROTOCOL_INVALID;
}

const NetDevVTable bare_udp_vtable = {
        .object_size = sizeof(BareUDP),
        .sections = NETDEV_COMMON_SECTIONS "BareUDP\0",
        .init = bare_udp_init,
        .config_verify = netdev_bare_udp_verify,
        .create = netdev_bare_udp_create,
        .create_type = NETDEV_CREATE_INDEPENDENT,
};