Branch data Line data Source code
1 : : /* SPDX-License-Identifier: LGPL-2.1+ */
2 : :
3 : : #include <errno.h>
4 : : #include <stdlib.h>
5 : : #include <unistd.h>
6 : :
7 : : #include <linux/veth.h>
8 : : #include <net/if.h>
9 : :
10 : : #include "sd-event.h"
11 : : #include "sd-ipv4acd.h"
12 : : #include "sd-netlink.h"
13 : :
14 : : #include "in-addr-util.h"
15 : : #include "netlink-util.h"
16 : : #include "tests.h"
17 : : #include "util.h"
18 : :
19 : 0 : static void acd_handler(sd_ipv4acd *acd, int event, void *userdata) {
20 [ # # ]: 0 : assert_se(acd);
21 : :
22 [ # # # # ]: 0 : switch (event) {
23 : 0 : case SD_IPV4ACD_EVENT_BIND:
24 [ # # ]: 0 : log_info("bound");
25 : 0 : break;
26 : 0 : case SD_IPV4ACD_EVENT_CONFLICT:
27 [ # # ]: 0 : log_info("conflict");
28 : 0 : break;
29 : 0 : case SD_IPV4ACD_EVENT_STOP:
30 [ # # ]: 0 : log_error("the client was stopped");
31 : 0 : break;
32 : 0 : default:
33 : 0 : assert_not_reached("invalid ACD event");
34 : : }
35 : 0 : }
36 : :
37 : 0 : static int client_run(int ifindex, const struct in_addr *pa, const struct ether_addr *ha, sd_event *e) {
38 : : sd_ipv4acd *acd;
39 : :
40 [ # # ]: 0 : assert_se(sd_ipv4acd_new(&acd) >= 0);
41 [ # # ]: 0 : assert_se(sd_ipv4acd_attach_event(acd, e, 0) >= 0);
42 : :
43 [ # # ]: 0 : assert_se(sd_ipv4acd_set_ifindex(acd, ifindex) >= 0);
44 [ # # ]: 0 : assert_se(sd_ipv4acd_set_mac(acd, ha) >= 0);
45 [ # # ]: 0 : assert_se(sd_ipv4acd_set_address(acd, pa) >= 0);
46 [ # # ]: 0 : assert_se(sd_ipv4acd_set_callback(acd, acd_handler, NULL) >= 0);
47 : :
48 [ # # ]: 0 : log_info("starting IPv4ACD client");
49 : :
50 [ # # ]: 0 : assert_se(sd_ipv4acd_start(acd) >= 0);
51 : :
52 [ # # ]: 0 : assert_se(sd_event_loop(e) >= 0);
53 : :
54 [ # # ]: 0 : assert_se(!sd_ipv4acd_unref(acd));
55 : :
56 : 0 : return EXIT_SUCCESS;
57 : : }
58 : :
59 : 0 : static int test_acd(const char *ifname, const char *address) {
60 : 0 : _cleanup_(sd_event_unrefp) sd_event *e = NULL;
61 : 0 : _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
62 : 0 : _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *reply = NULL;
63 : : union in_addr_union pa;
64 : : struct ether_addr ha;
65 : : int ifindex;
66 : :
67 [ # # ]: 0 : assert_se(in_addr_from_string(AF_INET, address, &pa) >= 0);
68 : :
69 [ # # ]: 0 : assert_se(sd_event_new(&e) >= 0);
70 : :
71 [ # # ]: 0 : assert_se(sd_netlink_open(&rtnl) >= 0);
72 [ # # ]: 0 : assert_se(sd_netlink_attach_event(rtnl, e, 0) >= 0);
73 : :
74 [ # # ]: 0 : assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, 0) >= 0);
75 [ # # ]: 0 : assert_se(sd_netlink_message_append_string(m, IFLA_IFNAME, ifname) >= 0);
76 [ # # ]: 0 : assert_se(sd_netlink_call(rtnl, m, 0, &reply) >= 0);
77 : :
78 [ # # ]: 0 : assert_se(sd_rtnl_message_link_get_ifindex(reply, &ifindex) >= 0);
79 [ # # ]: 0 : assert_se(sd_netlink_message_read_ether_addr(reply, IFLA_ADDRESS, &ha) >= 0);
80 : :
81 : 0 : client_run(ifindex, &pa.in, &ha, e);
82 : :
83 : 0 : return EXIT_SUCCESS;
84 : : }
85 : :
86 : 0 : int main(int argc, char *argv[]) {
87 : 0 : test_setup_logging(LOG_DEBUG);
88 : :
89 [ # # ]: 0 : if (argc == 3)
90 : 0 : return test_acd(argv[1], argv[2]);
91 : : else {
92 [ # # ]: 0 : log_error("This program takes two arguments.\n"
93 : : "\t %s <ifname> <IPv4 address>", program_invocation_short_name);
94 : 0 : return EXIT_FAILURE;
95 : : }
96 : : }
|