Line data Source code
1 : /* SPDX-License-Identifier: LGPL-2.1+ */
2 : /***
3 : Copyright © 2014 Axis Communications AB. All rights reserved.
4 : ***/
5 :
6 : #include <errno.h>
7 : #include <netinet/if_ether.h>
8 : #include <stdio.h>
9 : #include <stdlib.h>
10 : #include <sys/socket.h>
11 : #include <sys/types.h>
12 : #include <unistd.h>
13 :
14 : #include "sd-ipv4ll.h"
15 :
16 : #include "arp-util.h"
17 : #include "fd-util.h"
18 : #include "socket-util.h"
19 : #include "tests.h"
20 : #include "util.h"
21 :
22 : static bool verbose = false;
23 : static bool extended = false;
24 : static int test_fd[2];
25 :
26 : static int basic_request_handler_bind = 0;
27 : static int basic_request_handler_stop = 0;
28 : static void* basic_request_handler_userdata = (void*) 0xCABCAB;
29 :
30 1 : static void basic_request_handler(sd_ipv4ll *ll, int event, void *userdata) {
31 1 : assert_se(userdata == basic_request_handler_userdata);
32 :
33 1 : switch(event) {
34 1 : case SD_IPV4LL_EVENT_STOP:
35 1 : basic_request_handler_stop = 1;
36 1 : break;
37 0 : case SD_IPV4LL_EVENT_BIND:
38 0 : basic_request_handler_bind = 1;
39 0 : break;
40 0 : default:
41 0 : assert_se(0);
42 : break;
43 : }
44 1 : }
45 :
46 1 : static int arp_network_send_raw_socket(int fd, int ifindex,
47 : const struct ether_arp *arp) {
48 1 : assert_se(arp);
49 1 : assert_se(ifindex > 0);
50 1 : assert_se(fd >= 0);
51 :
52 1 : if (send(fd, arp, sizeof(struct ether_arp), 0) < 0)
53 0 : return -errno;
54 :
55 1 : return 0;
56 : }
57 :
58 1 : int arp_send_probe(int fd, int ifindex,
59 : be32_t pa, const struct ether_addr *ha) {
60 1 : struct ether_arp ea = {};
61 :
62 1 : assert_se(fd >= 0);
63 1 : assert_se(ifindex > 0);
64 1 : assert_se(pa != 0);
65 1 : assert_se(ha);
66 :
67 1 : return arp_network_send_raw_socket(fd, ifindex, &ea);
68 : }
69 :
70 0 : int arp_send_announcement(int fd, int ifindex,
71 : be32_t pa, const struct ether_addr *ha) {
72 0 : struct ether_arp ea = {};
73 :
74 0 : assert_se(fd >= 0);
75 0 : assert_se(ifindex > 0);
76 0 : assert_se(pa != 0);
77 0 : assert_se(ha);
78 :
79 0 : return arp_network_send_raw_socket(fd, ifindex, &ea);
80 : }
81 :
82 1 : int arp_network_bind_raw_socket(int index, be32_t address, const struct ether_addr *eth_mac) {
83 1 : if (socketpair(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, test_fd) < 0)
84 0 : return -errno;
85 :
86 1 : return test_fd[0];
87 : }
88 :
89 1 : static void test_public_api_setters(sd_event *e) {
90 1 : struct in_addr address = {};
91 1 : uint64_t seed = 0;
92 : sd_ipv4ll *ll;
93 1 : struct ether_addr mac_addr = {
94 : .ether_addr_octet = {'A', 'B', 'C', '1', '2', '3'}};
95 :
96 1 : if (verbose)
97 0 : printf("* %s\n", __FUNCTION__);
98 :
99 1 : assert_se(sd_ipv4ll_new(&ll) == 0);
100 1 : assert_se(ll);
101 :
102 1 : assert_se(sd_ipv4ll_attach_event(NULL, NULL, 0) == -EINVAL);
103 1 : assert_se(sd_ipv4ll_attach_event(ll, e, 0) == 0);
104 1 : assert_se(sd_ipv4ll_attach_event(ll, e, 0) == -EBUSY);
105 :
106 1 : assert_se(sd_ipv4ll_set_callback(NULL, NULL, NULL) == -EINVAL);
107 1 : assert_se(sd_ipv4ll_set_callback(ll, NULL, NULL) == 0);
108 :
109 1 : assert_se(sd_ipv4ll_set_address(ll, &address) == -EINVAL);
110 1 : address.s_addr |= htobe32(169U << 24 | 254U << 16);
111 1 : assert_se(sd_ipv4ll_set_address(ll, &address) == -EINVAL);
112 1 : address.s_addr |= htobe32(0x00FF);
113 1 : assert_se(sd_ipv4ll_set_address(ll, &address) == -EINVAL);
114 1 : address.s_addr |= htobe32(0xF000);
115 1 : assert_se(sd_ipv4ll_set_address(ll, &address) == 0);
116 1 : address.s_addr |= htobe32(0x0F00);
117 1 : assert_se(sd_ipv4ll_set_address(ll, &address) == -EINVAL);
118 :
119 1 : assert_se(sd_ipv4ll_set_address_seed(NULL, seed) == -EINVAL);
120 1 : assert_se(sd_ipv4ll_set_address_seed(ll, seed) == 0);
121 :
122 1 : assert_se(sd_ipv4ll_set_mac(NULL, NULL) == -EINVAL);
123 1 : assert_se(sd_ipv4ll_set_mac(ll, NULL) == -EINVAL);
124 1 : assert_se(sd_ipv4ll_set_mac(ll, &mac_addr) == 0);
125 :
126 1 : assert_se(sd_ipv4ll_set_ifindex(NULL, -1) == -EINVAL);
127 1 : assert_se(sd_ipv4ll_set_ifindex(ll, -1) == -EINVAL);
128 1 : assert_se(sd_ipv4ll_set_ifindex(ll, -99) == -EINVAL);
129 1 : assert_se(sd_ipv4ll_set_ifindex(ll, 1) == 0);
130 1 : assert_se(sd_ipv4ll_set_ifindex(ll, 99) == 0);
131 :
132 1 : assert_se(sd_ipv4ll_ref(ll) == ll);
133 1 : assert_se(sd_ipv4ll_unref(ll) == NULL);
134 :
135 : /* Cleanup */
136 1 : assert_se(sd_ipv4ll_unref(ll) == NULL);
137 1 : }
138 :
139 1 : static void test_basic_request(sd_event *e) {
140 :
141 : sd_ipv4ll *ll;
142 : struct ether_arp arp;
143 1 : struct ether_addr mac_addr = {
144 : .ether_addr_octet = {'A', 'B', 'C', '1', '2', '3'}};
145 :
146 1 : if (verbose)
147 0 : printf("* %s\n", __FUNCTION__);
148 :
149 1 : assert_se(sd_ipv4ll_new(&ll) == 0);
150 1 : assert_se(sd_ipv4ll_start(ll) == -EINVAL);
151 :
152 1 : assert_se(sd_ipv4ll_attach_event(ll, e, 0) == 0);
153 1 : assert_se(sd_ipv4ll_start(ll) == -EINVAL);
154 :
155 1 : assert_se(sd_ipv4ll_set_mac(ll, &mac_addr) == 0);
156 1 : assert_se(sd_ipv4ll_start(ll) == -EINVAL);
157 :
158 1 : assert_se(sd_ipv4ll_set_callback(ll, basic_request_handler,
159 : basic_request_handler_userdata) == 0);
160 1 : assert_se(sd_ipv4ll_start(ll) == -EINVAL);
161 :
162 1 : assert_se(sd_ipv4ll_set_ifindex(ll, 1) == 0);
163 1 : assert_se(sd_ipv4ll_start(ll) == 0);
164 :
165 1 : sd_event_run(e, (uint64_t) -1);
166 1 : assert_se(sd_ipv4ll_start(ll) == -EBUSY);
167 :
168 1 : assert_se(sd_ipv4ll_is_running(ll));
169 :
170 : /* PROBE */
171 1 : sd_event_run(e, (uint64_t) -1);
172 1 : assert_se(recv(test_fd[1], &arp, sizeof(struct ether_arp), 0) == sizeof(struct ether_arp));
173 :
174 1 : if (extended) {
175 : /* PROBE */
176 0 : sd_event_run(e, (uint64_t) -1);
177 0 : assert_se(recv(test_fd[1], &arp, sizeof(struct ether_arp), 0) == sizeof(struct ether_arp));
178 :
179 : /* PROBE */
180 0 : sd_event_run(e, (uint64_t) -1);
181 0 : assert_se(recv(test_fd[1], &arp, sizeof(struct ether_arp), 0) == sizeof(struct ether_arp));
182 :
183 0 : sd_event_run(e, (uint64_t) -1);
184 0 : assert_se(basic_request_handler_bind == 1);
185 : }
186 :
187 1 : sd_ipv4ll_stop(ll);
188 1 : assert_se(basic_request_handler_stop == 1);
189 :
190 : /* Cleanup */
191 1 : assert_se(sd_ipv4ll_unref(ll) == NULL);
192 1 : safe_close(test_fd[1]);
193 1 : }
194 :
195 1 : int main(int argc, char *argv[]) {
196 2 : _cleanup_(sd_event_unrefp) sd_event *e = NULL;
197 :
198 1 : test_setup_logging(LOG_DEBUG);
199 :
200 1 : assert_se(sd_event_new(&e) >= 0);
201 :
202 1 : test_public_api_setters(e);
203 1 : test_basic_request(e);
204 :
205 1 : return 0;
206 : }
|