chiark / gitweb /
dhcp: Add test for discover DHCP packet creation
[elogind.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 }