]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/test-dhcp-client.c
sd-dhcp-client: refactor client_{free,new}
[thirdparty/systemd.git] / src / libsystemd / test-dhcp-client.c
CommitLineData
be391925
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) 2013 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 <stdlib.h>
23#include <assert.h>
24#include <errno.h>
39b7f596 25#include <stdio.h>
8c00042c
PF
26#include <sys/types.h>
27#include <sys/socket.h>
28#include <unistd.h>
be391925 29
290c7324 30#include "util.h"
8c00042c 31#include "socket-util.h"
290c7324 32
be391925 33#include "dhcp-protocol.h"
290c7324 34#include "dhcp-internal.h"
be391925
PF
35#include "sd-dhcp-client.h"
36
290c7324
PF
37static struct ether_addr mac_addr = {
38 .ether_addr_octet = {'A', 'B', 'C', '1', '2', '3'}
39};
40
8c00042c
PF
41static int test_fd[2];
42
d3d8ac2f 43static void test_request_basic(sd_event *e)
be391925 44{
b25ef18b
TG
45 int r;
46
be391925
PF
47 sd_dhcp_client *client;
48
b25ef18b 49 r = sd_dhcp_client_new(&client);
be391925 50
b25ef18b 51 assert(r >= 0);
be391925
PF
52 assert(client);
53
b25ef18b
TG
54 r = sd_dhcp_client_attach_event(client, e, 0);
55 assert(r >= 0);
56
be391925
PF
57 assert(sd_dhcp_client_set_request_option(NULL, 0) == -EINVAL);
58 assert(sd_dhcp_client_set_request_address(NULL, NULL) == -EINVAL);
59 assert(sd_dhcp_client_set_index(NULL, 0) == -EINVAL);
60
61 assert(sd_dhcp_client_set_index(client, 15) == 0);
62 assert(sd_dhcp_client_set_index(client, -42) == -EINVAL);
63 assert(sd_dhcp_client_set_index(client, -1) == 0);
64
65 assert(sd_dhcp_client_set_request_option(client,
66 DHCP_OPTION_SUBNET_MASK) == -EEXIST);
67 assert(sd_dhcp_client_set_request_option(client,
68 DHCP_OPTION_ROUTER) == -EEXIST);
69 assert(sd_dhcp_client_set_request_option(client,
70 DHCP_OPTION_HOST_NAME) == -EEXIST);
71 assert(sd_dhcp_client_set_request_option(client,
72 DHCP_OPTION_DOMAIN_NAME) == -EEXIST);
73 assert(sd_dhcp_client_set_request_option(client,
74 DHCP_OPTION_DOMAIN_NAME_SERVER)
75 == -EEXIST);
76 assert(sd_dhcp_client_set_request_option(client,
77 DHCP_OPTION_NTP_SERVER) == -EEXIST);
78
79 assert(sd_dhcp_client_set_request_option(client,
80 DHCP_OPTION_PAD) == -EINVAL);
81 assert(sd_dhcp_client_set_request_option(client,
82 DHCP_OPTION_END) == -EINVAL);
83 assert(sd_dhcp_client_set_request_option(client,
84 DHCP_OPTION_MESSAGE_TYPE) == -EINVAL);
85 assert(sd_dhcp_client_set_request_option(client,
86 DHCP_OPTION_OVERLOAD) == -EINVAL);
87 assert(sd_dhcp_client_set_request_option(client,
88 DHCP_OPTION_PARAMETER_REQUEST_LIST)
89 == -EINVAL);
90
91 assert(sd_dhcp_client_set_request_option(client, 33) == 0);
92 assert(sd_dhcp_client_set_request_option(client, 33) == -EEXIST);
93 assert(sd_dhcp_client_set_request_option(client, 44) == 0);
7a7c74ca 94 assert(sd_dhcp_client_set_request_option(client, 33) == -EEXIST);
be391925
PF
95}
96
39b7f596
PF
97static uint16_t client_checksum(void *buf, int len)
98{
99 uint32_t sum;
100 uint16_t *check;
101 int i;
102 uint8_t *odd;
103
104 sum = 0;
105 check = buf;
106
107 for (i = 0; i < len / 2 ; i++)
108 sum += check[i];
109
110 if (len & 0x01) {
111 odd = buf;
0c6a3c88 112 sum += odd[len - 1];
39b7f596
PF
113 }
114
0c6a3c88
PF
115 while (sum >> 16)
116 sum = (sum & 0xffff) + (sum >> 16);
117
118 return ~sum;
39b7f596
PF
119}
120
121static void test_checksum(void)
122{
123 uint8_t buf[20] = {
124 0x45, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00,
125 0x40, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
126 0xff, 0xff, 0xff, 0xff
127 };
128
2fba7b03 129 assert(client_checksum(&buf, 20) == be16toh(0x78ae));
39b7f596
PF
130}
131
290c7324
PF
132static int check_options(uint8_t code, uint8_t len, const uint8_t *option,
133 void *user_data)
134{
135 return 0;
136}
137
8c00042c
PF
138int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link,
139 const void *packet, size_t len)
290c7324
PF
140{
141 size_t size;
142 _cleanup_free_ DHCPPacket *discover;
143 uint16_t ip_check, udp_check;
144 int res;
145
8c00042c 146 assert(s >= 0);
290c7324
PF
147 assert(packet);
148
149 size = sizeof(DHCPPacket) + 4;
150 assert(len > size);
151
152 discover = memdup(packet, len);
153
154 assert(memcmp(discover->dhcp.chaddr,
155 &mac_addr.ether_addr_octet, 6) == 0);
156 assert(discover->ip.ttl == IPDEFTTL);
157 assert(discover->ip.protocol == IPPROTO_UDP);
158 assert(discover->ip.saddr == INADDR_ANY);
159 assert(discover->ip.daddr == INADDR_BROADCAST);
8c00042c
PF
160 assert(discover->udp.source == be16toh(DHCP_PORT_CLIENT));
161 assert(discover->udp.dest == be16toh(DHCP_PORT_SERVER));
290c7324
PF
162
163 ip_check = discover->ip.check;
164
165 discover->ip.ttl = 0;
166 discover->ip.check = discover->udp.len;
167
168 udp_check = ~client_checksum(&discover->ip.ttl, len - 8);
169 assert(udp_check == 0xffff);
170
171 discover->ip.ttl = IPDEFTTL;
172 discover->ip.check = ip_check;
173
174 ip_check = ~client_checksum(&discover->ip, sizeof(discover->ip));
175 assert(ip_check == 0xffff);
176
177 size = len - sizeof(struct iphdr) - sizeof(struct udphdr);
178
179 res = dhcp_option_parse(&discover->dhcp, size, check_options, NULL);
180 if (res < 0)
181 return res;
182
183 return 575;
184}
185
8c00042c
PF
186int dhcp_network_bind_raw_socket(int index, union sockaddr_union *link)
187{
188 if (socketpair(AF_UNIX, SOCK_STREAM, 0, test_fd) < 0)
189 return -errno;
190
191 return test_fd[0];
192}
193
234fc2df
PF
194int dhcp_network_bind_udp_socket(int index, be32_t client_address)
195{
196 return 0;
197}
198
199int dhcp_network_send_udp_socket(int s, be32_t server_address,
200 const void *packet, size_t len)
201{
202 return 0;
203}
204
d3d8ac2f 205static void test_discover_message(sd_event *e)
290c7324
PF
206{
207 sd_dhcp_client *client;
b25ef18b 208 int res, r;
290c7324 209
b25ef18b
TG
210 r = sd_dhcp_client_new(&client);
211 assert(r >= 0);
290c7324
PF
212 assert(client);
213
b25ef18b
TG
214 r = sd_dhcp_client_attach_event(client, e, 0);
215 assert(r >= 0);
216
290c7324
PF
217 assert(sd_dhcp_client_set_index(client, 42) >= 0);
218 assert(sd_dhcp_client_set_mac(client, &mac_addr) >= 0);
219
220 assert(sd_dhcp_client_set_request_option(client, 248) >= 0);
221
222 res = sd_dhcp_client_start(client);
223
224 assert(res == 0 || res == -EINPROGRESS);
8c00042c
PF
225
226 close(test_fd[0]);
227 close(test_fd[1]);
290c7324
PF
228}
229
be391925
PF
230int main(int argc, char *argv[])
231{
d3d8ac2f
PF
232 sd_event *e;
233
234 assert(sd_event_new(&e) >= 0);
235
236 test_request_basic(e);
39b7f596 237 test_checksum();
be391925 238
d3d8ac2f
PF
239 test_discover_message(e);
240 sd_event_run(e, (uint64_t) -1);
290c7324 241
be391925
PF
242 return 0;
243}