chiark / gitweb /
sd-dhcp-server: add basic DISCOVER/OFFER support
[elogind.git] / src / libsystemd-network / test-dhcp-server.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) 2013 Intel Corporation. All rights reserved.
7   Copyright (C) 2014 Tom Gundersen
8
9   systemd is free software; you can redistribute it and/or modify it
10   under the terms of the GNU Lesser General Public License as published by
11   the Free Software Foundation; either version 2.1 of the License, or
12   (at your option) any later version.
13
14   systemd is distributed in the hope that it will be useful, but
15   WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17   Lesser General Public License for more details.
18
19   You should have received a copy of the GNU Lesser General Public License
20   along with systemd; If not, see <http://www.gnu.org/licenses/>.
21 ***/
22
23 #include <netinet/if_ether.h>
24 #include <assert.h>
25 #include <errno.h>
26
27 #include "sd-event.h"
28 #include "event-util.h"
29
30 #include "sd-dhcp-server.h"
31 #include "dhcp-server-internal.h"
32
33 static void test_basic(sd_event *event) {
34         _cleanup_dhcp_server_unref_ sd_dhcp_server *server = NULL;
35         struct in_addr address_lo = {
36                 .s_addr = htonl(INADDR_LOOPBACK),
37         };
38         struct in_addr address_any = {
39                 .s_addr = htonl(INADDR_ANY),
40         };
41
42         /* attach to loopback interface */
43         assert_se(sd_dhcp_server_new(&server, 1) >= 0);
44         assert_se(server);
45
46         assert_se(sd_dhcp_server_attach_event(server, event, 0) >= 0);
47         assert_se(sd_dhcp_server_attach_event(server, event, 0) == -EBUSY);
48         assert_se(sd_dhcp_server_get_event(server) == event);
49         assert_se(sd_dhcp_server_detach_event(server) >= 0);
50         assert_se(!sd_dhcp_server_get_event(server));
51         assert_se(sd_dhcp_server_attach_event(server, NULL, 0) >= 0);
52         assert_se(sd_dhcp_server_attach_event(server, NULL, 0) == -EBUSY);
53
54         assert_se(sd_dhcp_server_ref(server) == server);
55         assert_se(!sd_dhcp_server_unref(server));
56
57         assert_se(sd_dhcp_server_start(server) == -EUNATCH);
58         assert_se(sd_dhcp_server_set_address(server, &address_any) == -EINVAL);
59         assert_se(sd_dhcp_server_set_address(server, &address_lo) >= 0);
60         assert_se(sd_dhcp_server_set_address(server, &address_lo) == -EBUSY);
61
62         assert_se(sd_dhcp_server_start(server) >= 0);
63         assert_se(sd_dhcp_server_start(server) == -EBUSY);
64         assert_se(sd_dhcp_server_stop(server) >= 0);
65         assert_se(sd_dhcp_server_stop(server) >= 0);
66         assert_se(sd_dhcp_server_start(server) >= 0);
67 }
68
69 static void test_message_handler(void) {
70         _cleanup_dhcp_server_unref_ sd_dhcp_server *server = NULL;
71         struct {
72                 DHCPMessage message;
73                 struct {
74                         uint8_t code;
75                         uint8_t length;
76                         uint8_t type;
77                 } _packed_ option_type;
78                 uint8_t end;
79         } _packed_ test = {
80                 .message.op = BOOTREQUEST,
81                 .message.htype = ARPHRD_ETHER,
82                 .message.hlen = ETHER_ADDR_LEN,
83                 .option_type.code = DHCP_OPTION_MESSAGE_TYPE,
84                 .option_type.length = 1,
85                 .option_type.type = DHCP_DISCOVER,
86                 .end = DHCP_OPTION_END,
87         };
88         struct in_addr address_lo = {
89                 .s_addr = htonl(INADDR_LOOPBACK),
90         };
91
92         assert_se(sd_dhcp_server_new(&server, 1) >= 0);
93         assert_se(sd_dhcp_server_set_address(server, &address_lo) >= 0);
94         assert_se(sd_dhcp_server_attach_event(server, NULL, 0) >= 0);
95         assert_se(sd_dhcp_server_start(server) >= 0);
96
97         assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
98
99         test.end = 0;
100         /* TODO, shouldn't this fail? */
101         assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
102         test.end = DHCP_OPTION_END;
103         assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
104
105         test.option_type.code = 0;
106         test.option_type.length = 0;
107         test.option_type.type = 0;
108         assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
109         test.option_type.code = DHCP_OPTION_MESSAGE_TYPE;
110         test.option_type.length = 1;
111         test.option_type.type = DHCP_DISCOVER;
112         assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
113
114         test.message.op = 0;
115         assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
116         test.message.op = BOOTREQUEST;
117         assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
118
119         test.message.htype = 0;
120         assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
121         test.message.htype = ARPHRD_ETHER;
122         assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
123
124         test.message.hlen = 0;
125         assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
126         test.message.hlen = ETHER_ADDR_LEN;
127         assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
128 }
129
130 int main(int argc, char *argv[]) {
131         _cleanup_event_unref_ sd_event *e;
132
133         log_set_max_level(LOG_DEBUG);
134         log_parse_environment();
135         log_open();
136
137         assert_se(sd_event_new(&e) >= 0);
138
139         test_basic(e);
140         test_message_handler();
141
142         return 0;
143 }