Branch data Line data Source code
1 : : /* SPDX-License-Identifier: LGPL-2.1+ */
2 : :
3 : : #include <errno.h>
4 : : #include <net/if.h>
5 : : #include <stdlib.h>
6 : : #include <unistd.h>
7 : : #include <linux/veth.h>
8 : :
9 : : #include "sd-event.h"
10 : : #include "sd-ipv4ll.h"
11 : : #include "sd-netlink.h"
12 : :
13 : : #include "alloc-util.h"
14 : : #include "in-addr-util.h"
15 : : #include "netlink-util.h"
16 : : #include "parse-util.h"
17 : : #include "string-util.h"
18 : : #include "tests.h"
19 : : #include "util.h"
20 : :
21 : 0 : static void ll_handler(sd_ipv4ll *ll, int event, void *userdata) {
22 : 0 : _cleanup_free_ char *address = NULL;
23 : 0 : struct in_addr addr = {};
24 : :
25 [ # # ]: 0 : assert_se(ll);
26 : :
27 [ # # ]: 0 : if (sd_ipv4ll_get_address(ll, &addr) >= 0)
28 [ # # ]: 0 : assert_se(in_addr_to_string(AF_INET, (const union in_addr_union*) &addr, &address) >= 0);
29 : :
30 [ # # # # ]: 0 : switch (event) {
31 : 0 : case SD_IPV4LL_EVENT_BIND:
32 [ # # ]: 0 : log_info("bound %s", strna(address));
33 : 0 : break;
34 : 0 : case SD_IPV4LL_EVENT_CONFLICT:
35 [ # # ]: 0 : log_info("conflict on %s", strna(address));
36 : 0 : break;
37 : 0 : case SD_IPV4LL_EVENT_STOP:
38 [ # # ]: 0 : log_error("the client was stopped with address %s", strna(address));
39 : 0 : break;
40 : 0 : default:
41 : 0 : assert_not_reached("invalid LL event");
42 : : }
43 : 0 : }
44 : :
45 : 0 : static int client_run(int ifindex, const char *seed_str, const struct ether_addr *ha, sd_event *e) {
46 : : sd_ipv4ll *ll;
47 : :
48 [ # # ]: 0 : assert_se(sd_ipv4ll_new(&ll) >= 0);
49 [ # # ]: 0 : assert_se(sd_ipv4ll_attach_event(ll, e, 0) >= 0);
50 : :
51 [ # # ]: 0 : assert_se(sd_ipv4ll_set_ifindex(ll, ifindex) >= 0);
52 [ # # ]: 0 : assert_se(sd_ipv4ll_set_mac(ll, ha) >= 0);
53 [ # # ]: 0 : assert_se(sd_ipv4ll_set_callback(ll, ll_handler, NULL) >= 0);
54 : :
55 [ # # ]: 0 : if (seed_str) {
56 : : unsigned seed;
57 : :
58 [ # # ]: 0 : assert_se(safe_atou(seed_str, &seed) >= 0);
59 : :
60 [ # # ]: 0 : assert_se(sd_ipv4ll_set_address_seed(ll, seed) >= 0);
61 : : }
62 : :
63 [ # # ]: 0 : log_info("starting IPv4LL client");
64 : :
65 [ # # ]: 0 : assert_se(sd_ipv4ll_start(ll) >= 0);
66 : :
67 [ # # ]: 0 : assert_se(sd_event_loop(e) >= 0);
68 : :
69 [ # # ]: 0 : assert_se(!sd_ipv4ll_unref(ll));
70 : :
71 : 0 : return EXIT_SUCCESS;
72 : : }
73 : :
74 : 0 : static int test_ll(const char *ifname, const char *seed) {
75 : 0 : _cleanup_(sd_event_unrefp) sd_event *e = NULL;
76 : 0 : _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
77 : 0 : _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *reply = NULL;
78 : : struct ether_addr ha;
79 : : int ifindex;
80 : :
81 [ # # ]: 0 : assert_se(sd_event_new(&e) >= 0);
82 : :
83 [ # # ]: 0 : assert_se(sd_netlink_open(&rtnl) >= 0);
84 [ # # ]: 0 : assert_se(sd_netlink_attach_event(rtnl, e, 0) >= 0);
85 : :
86 [ # # ]: 0 : assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, 0) >= 0);
87 [ # # ]: 0 : assert_se(sd_netlink_message_append_string(m, IFLA_IFNAME, ifname) >= 0);
88 [ # # ]: 0 : assert_se(sd_netlink_call(rtnl, m, 0, &reply) >= 0);
89 : :
90 [ # # ]: 0 : assert_se(sd_rtnl_message_link_get_ifindex(reply, &ifindex) >= 0);
91 [ # # ]: 0 : assert_se(sd_netlink_message_read_ether_addr(reply, IFLA_ADDRESS, &ha) >= 0);
92 : :
93 : 0 : client_run(ifindex, seed, &ha, e);
94 : :
95 : 0 : return EXIT_SUCCESS;
96 : : }
97 : :
98 : 0 : int main(int argc, char *argv[]) {
99 : 0 : test_setup_logging(LOG_DEBUG);
100 : :
101 [ # # ]: 0 : if (argc == 2)
102 : 0 : return test_ll(argv[1], NULL);
103 [ # # ]: 0 : else if (argc == 3)
104 : 0 : return test_ll(argv[1], argv[2]);
105 : : else {
106 [ # # ]: 0 : log_error("This program takes one or two arguments.\n"
107 : : "\t %s <ifname> [<seed>]", program_invocation_short_name);
108 : 0 : return EXIT_FAILURE;
109 : : }
110 : : }
|