]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-network/test-ndisc-rs.c
sd-ndisc: introduce separate callbacks
[thirdparty/systemd.git] / src / libsystemd-network / test-ndisc-rs.c
CommitLineData
f20a35cc
PF
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
07630cea 24#include "sd-ndisc.h"
f20a35cc 25
940367a0 26#include "icmp6-util.h"
07630cea 27#include "socket-util.h"
f20a35cc
PF
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
99af546d
PF
37typedef int (*send_ra_t)(uint8_t flags);
38static send_ra_t send_ra_function;
39
f20a35cc
PF
40static int test_rs_hangcheck(sd_event_source *s, uint64_t usec,
41 void *userdata) {
787784c4 42 assert_se(false);
f20a35cc
PF
43
44 return 0;
45}
46
940367a0 47int icmp6_bind_router_solicitation(int index) {
787784c4 48 assert_se(index == 42);
f20a35cc
PF
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
787784c4 75 assert_se(write(test_fd[1], advertisement, sizeof(advertisement)) ==
f20a35cc
PF
76 sizeof(advertisement));
77
78 if (verbose)
79 printf(" sent RA with flag 0x%02x\n", flags);
80
81 return 0;
82}
83
940367a0 84int icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr) {
99af546d 85 return send_ra_function(0);
f20a35cc
PF
86}
87
9d96e6c3 88static void test_rs_done(sd_ndisc *nd, uint8_t flags, const struct in6_addr *gateway, unsigned lifetime, int pref, void *userdata) {
f20a35cc 89 sd_event *e = userdata;
cb53894d 90 static unsigned idx = 0;
9d96e6c3
TG
91 uint8_t flags_array[] = {
92 0,
93 0,
94 0,
95 ND_RA_FLAG_OTHER,
96 ND_RA_FLAG_MANAGED
f20a35cc 97 };
8d7f2c6a
PF
98 uint32_t mtu;
99
787784c4 100 assert_se(nd);
f20a35cc 101
9d96e6c3 102 assert_se(flags == flags_array[idx]);
f20a35cc
PF
103 idx++;
104
105 if (verbose)
9d96e6c3 106 printf(" got event 0x%02x\n", flags);
f20a35cc 107
9d96e6c3
TG
108 if (idx < ELEMENTSOF(flags_array)) {
109 send_ra(flags_array[idx]);
8d7f2c6a
PF
110 return;
111 }
112
4d7b83da 113 assert_se(sd_ndisc_get_mtu(nd, &mtu) == -ENOMSG);
8d7f2c6a
PF
114
115 sd_event_exit(e, 0);
f20a35cc
PF
116}
117
99af546d
PF
118static void test_rs(void) {
119 sd_event *e;
4d7b83da 120 sd_ndisc *nd;
99af546d 121 usec_t time_now = now(clock_boottime_or_monotonic());
f20a35cc
PF
122
123 if (verbose)
124 printf("* %s\n", __FUNCTION__);
125
99af546d
PF
126 send_ra_function = send_ra;
127
128 assert_se(sd_event_new(&e) >= 0);
129
4d7b83da 130 assert_se(sd_ndisc_new(&nd) >= 0);
787784c4 131 assert_se(nd);
f20a35cc 132
4d7b83da 133 assert_se(sd_ndisc_attach_event(nd, e, 0) >= 0);
f20a35cc 134
4d7b83da
TG
135 assert_se(sd_ndisc_set_index(nd, 42) >= 0);
136 assert_se(sd_ndisc_set_mac(nd, &mac_addr) >= 0);
9d96e6c3 137 assert_se(sd_ndisc_set_callback(nd, test_rs_done, NULL, NULL, NULL, e) >= 0);
f20a35cc 138
787784c4 139 assert_se(sd_event_add_time(e, &test_hangcheck, clock_boottime_or_monotonic(),
f20a35cc
PF
140 time_now + 2 *USEC_PER_SEC, 0,
141 test_rs_hangcheck, NULL) >= 0);
142
4d7b83da
TG
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);
836cf090 146
4d7b83da 147 assert_se(sd_ndisc_router_discovery_start(nd) >= 0);
f20a35cc
PF
148
149 sd_event_loop(e);
150
151 test_hangcheck = sd_event_source_unref(test_hangcheck);
152
4d7b83da 153 nd = sd_ndisc_unref(nd);
787784c4 154 assert_se(!nd);
f20a35cc 155
f20a35cc 156 close(test_fd[1]);
99af546d
PF
157
158 sd_event_unref(e);
f20a35cc
PF
159}
160
161int main(int argc, char *argv[]) {
f20a35cc
PF
162
163 log_set_max_level(LOG_DEBUG);
164 log_parse_environment();
165 log_open();
166
99af546d 167 test_rs();
f20a35cc
PF
168
169 return 0;
170}