]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd-dhcp/test-dhcp-client.c
dhcp: Add test for discover DHCP packet creation
[thirdparty/systemd.git] / src / libsystemd-dhcp / test-dhcp-client.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
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>
25 #include <stdio.h>
26
27 #include "util.h"
28
29 #include "dhcp-protocol.h"
30 #include "dhcp-internal.h"
31 #include "sd-dhcp-client.h"
32
33 static struct ether_addr mac_addr = {
34 .ether_addr_octet = {'A', 'B', 'C', '1', '2', '3'}
35 };
36
37 static void test_request_basic(void)
38 {
39 sd_dhcp_client *client;
40
41 client = sd_dhcp_client_new();
42
43 assert(client);
44
45 assert(sd_dhcp_client_set_request_option(NULL, 0) == -EINVAL);
46 assert(sd_dhcp_client_set_request_address(NULL, NULL) == -EINVAL);
47 assert(sd_dhcp_client_set_index(NULL, 0) == -EINVAL);
48
49 assert(sd_dhcp_client_set_index(client, 15) == 0);
50 assert(sd_dhcp_client_set_index(client, -42) == -EINVAL);
51 assert(sd_dhcp_client_set_index(client, -1) == 0);
52
53 assert(sd_dhcp_client_set_request_option(client,
54 DHCP_OPTION_SUBNET_MASK) == -EEXIST);
55 assert(sd_dhcp_client_set_request_option(client,
56 DHCP_OPTION_ROUTER) == -EEXIST);
57 assert(sd_dhcp_client_set_request_option(client,
58 DHCP_OPTION_HOST_NAME) == -EEXIST);
59 assert(sd_dhcp_client_set_request_option(client,
60 DHCP_OPTION_DOMAIN_NAME) == -EEXIST);
61 assert(sd_dhcp_client_set_request_option(client,
62 DHCP_OPTION_DOMAIN_NAME_SERVER)
63 == -EEXIST);
64 assert(sd_dhcp_client_set_request_option(client,
65 DHCP_OPTION_NTP_SERVER) == -EEXIST);
66
67 assert(sd_dhcp_client_set_request_option(client,
68 DHCP_OPTION_PAD) == -EINVAL);
69 assert(sd_dhcp_client_set_request_option(client,
70 DHCP_OPTION_END) == -EINVAL);
71 assert(sd_dhcp_client_set_request_option(client,
72 DHCP_OPTION_MESSAGE_TYPE) == -EINVAL);
73 assert(sd_dhcp_client_set_request_option(client,
74 DHCP_OPTION_OVERLOAD) == -EINVAL);
75 assert(sd_dhcp_client_set_request_option(client,
76 DHCP_OPTION_PARAMETER_REQUEST_LIST)
77 == -EINVAL);
78
79 assert(sd_dhcp_client_set_request_option(client, 33) == 0);
80 assert(sd_dhcp_client_set_request_option(client, 33) == -EEXIST);
81 assert(sd_dhcp_client_set_request_option(client, 44) == 0);
82 }
83
84 static uint16_t client_checksum(void *buf, int len)
85 {
86 uint32_t sum;
87 uint16_t *check;
88 int i;
89 uint8_t *odd;
90
91 sum = 0;
92 check = buf;
93
94 for (i = 0; i < len / 2 ; i++)
95 sum += check[i];
96
97 if (len & 0x01) {
98 odd = buf;
99 sum += odd[len];
100 }
101
102 return ~((sum & 0xffff) + (sum >> 16));
103 }
104
105 static void test_checksum(void)
106 {
107 uint8_t buf[20] = {
108 0x45, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00,
109 0x40, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
110 0xff, 0xff, 0xff, 0xff
111 };
112
113 uint8_t check[2] = {
114 0x78, 0xae
115 };
116
117 uint16_t *val = (uint16_t *)check;
118
119 assert(client_checksum(&buf, 20) == *val);
120 }
121
122 static int check_options(uint8_t code, uint8_t len, const uint8_t *option,
123 void *user_data)
124 {
125 return 0;
126 }
127
128 int dhcp_network_send_raw_packet(int index, const void *packet, size_t len)
129 {
130 size_t size;
131 _cleanup_free_ DHCPPacket *discover;
132 uint16_t ip_check, udp_check;
133 int res;
134
135 assert(index == 42);
136 assert(packet);
137
138 size = sizeof(DHCPPacket) + 4;
139 assert(len > size);
140
141 discover = memdup(packet, len);
142
143 assert(memcmp(discover->dhcp.chaddr,
144 &mac_addr.ether_addr_octet, 6) == 0);
145 assert(discover->ip.ttl == IPDEFTTL);
146 assert(discover->ip.protocol == IPPROTO_UDP);
147 assert(discover->ip.saddr == INADDR_ANY);
148 assert(discover->ip.daddr == INADDR_BROADCAST);
149 assert(discover->udp.source == ntohs(DHCP_PORT_CLIENT));
150 assert(discover->udp.dest == ntohs(DHCP_PORT_SERVER));
151
152 ip_check = discover->ip.check;
153
154 discover->ip.ttl = 0;
155 discover->ip.check = discover->udp.len;
156
157 udp_check = ~client_checksum(&discover->ip.ttl, len - 8);
158 assert(udp_check == 0xffff);
159
160 discover->ip.ttl = IPDEFTTL;
161 discover->ip.check = ip_check;
162
163 ip_check = ~client_checksum(&discover->ip, sizeof(discover->ip));
164 assert(ip_check == 0xffff);
165
166 size = len - sizeof(struct iphdr) - sizeof(struct udphdr);
167
168 res = dhcp_option_parse(&discover->dhcp, size, check_options, NULL);
169 if (res < 0)
170 return res;
171
172 return 575;
173 }
174
175 static void test_discover_message(void)
176 {
177 sd_dhcp_client *client;
178 int res;
179
180 client = sd_dhcp_client_new();
181 assert(client);
182
183 assert(sd_dhcp_client_set_index(client, 42) >= 0);
184 assert(sd_dhcp_client_set_mac(client, &mac_addr) >= 0);
185
186 assert(sd_dhcp_client_set_request_option(client, 248) >= 0);
187
188 res = sd_dhcp_client_start(client);
189
190 assert(res == 0 || res == -EINPROGRESS);
191 }
192
193 int main(int argc, char *argv[])
194 {
195 test_request_basic();
196 test_checksum();
197
198 test_discover_message();
199
200 return 0;
201 }