]> git.ipfire.org Git - thirdparty/systemd.git/blame_incremental - src/libsystemd-network/test-ndisc-rs.c
sd-ndisc: introduce separate callbacks
[thirdparty/systemd.git] / src / libsystemd-network / test-ndisc-rs.c
... / ...
CommitLineData
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright (C) 2014 Intel Corporation. All rights reserved.
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
22#include <netinet/icmp6.h>
23
24#include "sd-ndisc.h"
25
26#include "icmp6-util.h"
27#include "socket-util.h"
28
29static struct ether_addr mac_addr = {
30 .ether_addr_octet = {'A', 'B', 'C', '1', '2', '3'}
31};
32
33static bool verbose = false;
34static sd_event_source *test_hangcheck;
35static int test_fd[2];
36
37typedef int (*send_ra_t)(uint8_t flags);
38static send_ra_t send_ra_function;
39
40static int test_rs_hangcheck(sd_event_source *s, uint64_t usec,
41 void *userdata) {
42 assert_se(false);
43
44 return 0;
45}
46
47int icmp6_bind_router_solicitation(int index) {
48 assert_se(index == 42);
49
50 if (socketpair(AF_UNIX, SOCK_DGRAM, 0, test_fd) < 0)
51 return -errno;
52
53 return test_fd[0];
54}
55
56static int send_ra(uint8_t flags) {
57 uint8_t advertisement[] = {
58 0x86, 0x00, 0xde, 0x83, 0x40, 0xc0, 0x00, 0xb4,
59 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
60 0x03, 0x04, 0x40, 0xc0, 0x00, 0x00, 0x01, 0xf4,
61 0x00, 0x00, 0x01, 0xb8, 0x00, 0x00, 0x00, 0x00,
62 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
63 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
64 0x19, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
65 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
66 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
67 0x1f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
68 0x03, 0x6c, 0x61, 0x62, 0x05, 0x69, 0x6e, 0x74,
69 0x72, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
70 0x01, 0x01, 0x78, 0x2b, 0xcb, 0xb3, 0x6d, 0x53,
71 };
72
73 advertisement[5] = flags;
74
75 assert_se(write(test_fd[1], advertisement, sizeof(advertisement)) ==
76 sizeof(advertisement));
77
78 if (verbose)
79 printf(" sent RA with flag 0x%02x\n", flags);
80
81 return 0;
82}
83
84int icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr) {
85 return send_ra_function(0);
86}
87
88static void test_rs_done(sd_ndisc *nd, uint8_t flags, const struct in6_addr *gateway, unsigned lifetime, int pref, void *userdata) {
89 sd_event *e = userdata;
90 static unsigned idx = 0;
91 uint8_t flags_array[] = {
92 0,
93 0,
94 0,
95 ND_RA_FLAG_OTHER,
96 ND_RA_FLAG_MANAGED
97 };
98 uint32_t mtu;
99
100 assert_se(nd);
101
102 assert_se(flags == flags_array[idx]);
103 idx++;
104
105 if (verbose)
106 printf(" got event 0x%02x\n", flags);
107
108 if (idx < ELEMENTSOF(flags_array)) {
109 send_ra(flags_array[idx]);
110 return;
111 }
112
113 assert_se(sd_ndisc_get_mtu(nd, &mtu) == -ENOMSG);
114
115 sd_event_exit(e, 0);
116}
117
118static void test_rs(void) {
119 sd_event *e;
120 sd_ndisc *nd;
121 usec_t time_now = now(clock_boottime_or_monotonic());
122
123 if (verbose)
124 printf("* %s\n", __FUNCTION__);
125
126 send_ra_function = send_ra;
127
128 assert_se(sd_event_new(&e) >= 0);
129
130 assert_se(sd_ndisc_new(&nd) >= 0);
131 assert_se(nd);
132
133 assert_se(sd_ndisc_attach_event(nd, e, 0) >= 0);
134
135 assert_se(sd_ndisc_set_index(nd, 42) >= 0);
136 assert_se(sd_ndisc_set_mac(nd, &mac_addr) >= 0);
137 assert_se(sd_ndisc_set_callback(nd, test_rs_done, NULL, NULL, NULL, e) >= 0);
138
139 assert_se(sd_event_add_time(e, &test_hangcheck, clock_boottime_or_monotonic(),
140 time_now + 2 *USEC_PER_SEC, 0,
141 test_rs_hangcheck, NULL) >= 0);
142
143 assert_se(sd_ndisc_stop(nd) >= 0);
144 assert_se(sd_ndisc_router_discovery_start(nd) >= 0);
145 assert_se(sd_ndisc_stop(nd) >= 0);
146
147 assert_se(sd_ndisc_router_discovery_start(nd) >= 0);
148
149 sd_event_loop(e);
150
151 test_hangcheck = sd_event_source_unref(test_hangcheck);
152
153 nd = sd_ndisc_unref(nd);
154 assert_se(!nd);
155
156 close(test_fd[1]);
157
158 sd_event_unref(e);
159}
160
161int main(int argc, char *argv[]) {
162
163 log_set_max_level(LOG_DEBUG);
164 log_parse_environment();
165 log_open();
166
167 test_rs();
168
169 return 0;
170}