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