chiark / gitweb /
sd-dhcp6-lease: Add helper function to compute remaining expiry time
[elogind.git] / src / libsystemd-network / test-icmp6-rs.c
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 "socket-util.h"
25
26 #include "dhcp6-internal.h"
27 #include "sd-icmp6-nd.h"
28
29 static struct ether_addr mac_addr = {
30         .ether_addr_octet = {'A', 'B', 'C', '1', '2', '3'}
31 };
32
33 static bool verbose = false;
34 static sd_event_source *test_hangcheck;
35 static int test_fd[2];
36
37 static int test_rs_hangcheck(sd_event_source *s, uint64_t usec,
38                              void *userdata) {
39         assert(false);
40
41         return 0;
42 }
43
44 int dhcp_network_icmp6_bind_router_solicitation(int index) {
45         assert(index == 42);
46
47         if (socketpair(AF_UNIX, SOCK_DGRAM, 0, test_fd) < 0)
48                 return -errno;
49
50         return test_fd[0];
51 }
52
53 static int send_ra(uint8_t flags) {
54         uint8_t advertisement[] = {
55                 0x86, 0x00, 0xde, 0x83, 0x40, 0xc0, 0x00, 0xb4,
56                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
57                 0x03, 0x04, 0x40, 0xc0, 0x00, 0x00, 0x01, 0xf4,
58                 0x00, 0x00, 0x01, 0xb8, 0x00, 0x00, 0x00, 0x00,
59                 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
60                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
61                 0x19, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
62                 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
63                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
64                 0x1f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
65                 0x03, 0x6c, 0x61, 0x62, 0x05, 0x69, 0x6e, 0x74,
66                 0x72, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
67                 0x01, 0x01, 0x78, 0x2b, 0xcb, 0xb3, 0x6d, 0x53,
68         };
69
70         advertisement[5] = flags;
71
72         assert(write(test_fd[1], advertisement, sizeof(advertisement)) ==
73                sizeof(advertisement));
74
75         if (verbose)
76                 printf("  sent RA with flag 0x%02x\n", flags);
77
78         return 0;
79 }
80
81 int dhcp_network_icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr) {
82         return send_ra(0);
83 }
84
85 static void test_rs_done(sd_icmp6_nd *nd, int event, void *userdata) {
86         sd_event *e = userdata;
87         static int idx = 0;
88         struct {
89                 uint8_t flag;
90                 int event;
91         } flag_event[] = {
92                 { 0, ICMP6_EVENT_ROUTER_ADVERTISMENT_NONE },
93                 { ND_RA_FLAG_OTHER, ICMP6_EVENT_ROUTER_ADVERTISMENT_OTHER },
94                 { ND_RA_FLAG_MANAGED, ICMP6_EVENT_ROUTER_ADVERTISMENT_MANAGED }
95         };
96         assert(nd);
97
98         assert(event == flag_event[idx].event);
99         idx++;
100
101         if (verbose)
102                 printf("  got event %d\n", event);
103
104         if (idx < 3)
105                 send_ra(flag_event[idx].flag);
106         else
107                 sd_event_exit(e, 0);
108 }
109
110 static void test_rs(sd_event *e) {
111         usec_t time_now = now(CLOCK_MONOTONIC);
112         sd_icmp6_nd *nd;
113
114         if (verbose)
115                 printf("* %s\n", __FUNCTION__);
116
117         assert(sd_icmp6_nd_new(&nd) >= 0);
118         assert(nd);
119
120         assert(sd_icmp6_nd_attach_event(nd, e, 0) >= 0);
121
122         assert(sd_icmp6_nd_set_index(nd, 42) >= 0);
123         assert(sd_icmp6_nd_set_mac(nd, &mac_addr) >= 0);
124         assert(sd_icmp6_nd_set_callback(nd, test_rs_done, e) >= 0);
125
126         assert(sd_event_add_time(e, &test_hangcheck, CLOCK_MONOTONIC,
127                                  time_now + 2 *USEC_PER_SEC, 0,
128                                  test_rs_hangcheck, NULL) >= 0);
129
130         assert(sd_icmp6_nd_stop(nd) >= 0);
131         assert(sd_icmp6_router_solicitation_start(nd) >= 0);
132         assert(sd_icmp6_nd_stop(nd) >= 0);
133
134         assert(sd_icmp6_router_solicitation_start(nd) >= 0);
135
136         sd_event_loop(e);
137
138         test_hangcheck = sd_event_source_unref(test_hangcheck);
139
140         nd = sd_icmp6_nd_unref(nd);
141         assert(!nd);
142
143         close(test_fd[1]);
144 }
145
146 int main(int argc, char *argv[]) {
147         sd_event *e;
148
149         assert(sd_event_new(&e) >= 0);
150
151         log_set_max_level(LOG_DEBUG);
152         log_parse_environment();
153         log_open();
154
155         test_rs(e);
156
157         return 0;
158 }