10 #include "dhcp-protocol.h"
11 #include "dhcp-internal.h"
26 static bool verbose = false;
28 static struct option_desc option_tests[] = {
29 { {}, 0, {}, 0, { 42, 5, 65, 66, 67, 68, 69 }, 7, false, },
30 { {}, 0, {}, 0, { 42, 5, 65, 66, 67, 68, 69, 0, 0,
31 DHCP_OPTION_MESSAGE_TYPE, 1, DHCP_ACK }, 12, true, },
32 { {}, 0, {}, 0, { 8, 255, 70, 71, 72 }, 5, false, },
33 { {}, 0, {}, 0, { 0x35, 0x01, 0x05, 0x36, 0x04, 0x01, 0x00, 0xa8,
34 0xc0, 0x33, 0x04, 0x00, 0x01, 0x51, 0x80, 0x01,
35 0x04, 0xff, 0xff, 0xff, 0x00, 0x03, 0x04, 0xc0,
36 0xa8, 0x00, 0x01, 0x06, 0x04, 0xc0, 0xa8, 0x00,
37 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
39 { {}, 0, {}, 0, { DHCP_OPTION_MESSAGE_TYPE, 1, DHCP_OFFER,
40 42, 3, 0, 0, 0 }, 8, true, },
41 { {}, 0, {}, 0, { 42, 2, 1, 2, 44 }, 5, false, },
44 { 222, 3, 1, 2, 3, DHCP_OPTION_MESSAGE_TYPE, 1, DHCP_NAK }, 8,
45 { DHCP_OPTION_OVERLOAD, 1, DHCP_OVERLOAD_FILE }, 3, true, },
47 { { 1, 4, 1, 2, 3, 4, DHCP_OPTION_MESSAGE_TYPE, 1, DHCP_ACK }, 9,
48 { 222, 3, 1, 2, 3 }, 5,
49 { DHCP_OPTION_OVERLOAD, 1,
50 DHCP_OVERLOAD_FILE|DHCP_OVERLOAD_SNAME }, 3, true, },
53 static const char *dhcp_type(int type)
57 return "DHCPDISCOVER";
75 static void test_invalid_buffer_length(void)
79 assert_se(dhcp_option_parse(&message, 0, NULL, NULL) == -EINVAL);
80 assert_se(dhcp_option_parse(&message, sizeof(DHCPMessage) - 1, NULL, NULL)
84 static void test_message_init(void)
86 _cleanup_free_ DHCPMessage *message = NULL;
87 size_t optlen = 4, optoffset;
88 size_t len = sizeof(DHCPMessage) + optlen;
91 message = malloc0(len);
93 assert_se(dhcp_message_init(message, BOOTREQUEST, 0x12345678,
94 DHCP_DISCOVER, ARPHRD_ETHER, optlen, &optoffset) >= 0);
96 assert_se(message->xid == htobe32(0x12345678));
97 assert_se(message->op == BOOTREQUEST);
99 magic = (uint8_t*)&message->magic;
101 assert_se(magic[0] == 99);
102 assert_se(magic[1] == 130);
103 assert_se(magic[2] == 83);
104 assert_se(magic[3] == 99);
106 assert_se(dhcp_option_parse(message, len, NULL, NULL) >= 0);
109 static DHCPMessage *create_message(uint8_t *options, uint16_t optlen,
110 uint8_t *file, uint8_t filelen,
111 uint8_t *sname, uint8_t snamelen)
113 DHCPMessage *message;
114 size_t len = sizeof(DHCPMessage) + optlen;
116 message = malloc0(len);
119 if (options && optlen)
120 memcpy(&message->options, options, optlen);
122 if (file && filelen <= 128)
123 memcpy(&message->file, file, filelen);
125 if (sname && snamelen <= 64)
126 memcpy(&message->sname, sname, snamelen);
131 static void test_ignore_opts(uint8_t *descoption, int *descpos, int *desclen)
133 assert(*descpos >= 0);
135 while (*descpos < *desclen) {
136 switch(descoption[*descpos]) {
137 case DHCP_OPTION_PAD:
141 case DHCP_OPTION_MESSAGE_TYPE:
142 case DHCP_OPTION_OVERLOAD:
152 static int test_options_cb(uint8_t code, uint8_t len, const uint8_t *option,
155 struct option_desc *desc = user_data;
156 uint8_t *descoption = NULL;
157 int *desclen = NULL, *descpos = NULL;
162 assert_se((!desc && !code && !len) || desc);
167 assert_se(code != DHCP_OPTION_PAD);
168 assert_se(code != DHCP_OPTION_END);
169 assert_se(code != DHCP_OPTION_MESSAGE_TYPE);
170 assert_se(code != DHCP_OPTION_OVERLOAD);
172 while (desc->pos >= 0 || desc->filepos >= 0 || desc->snamepos >= 0) {
174 if (desc->pos >= 0) {
175 descoption = &desc->options[0];
176 desclen = &desc->len;
177 descpos = &desc->pos;
178 } else if (desc->filepos >= 0) {
179 descoption = &desc->file[0];
180 desclen = &desc->filelen;
181 descpos = &desc->filepos;
182 } else if (desc->snamepos >= 0) {
183 descoption = &desc->sname[0];
184 desclen = &desc->snamelen;
185 descpos = &desc->snamepos;
188 assert_se(descoption && desclen && descpos);
191 test_ignore_opts(descoption, descpos, desclen);
193 if (*descpos < *desclen)
196 if (*descpos == *desclen)
201 assert_se(*descpos != -1);
203 optcode = descoption[*descpos];
204 optlen = descoption[*descpos + 1];
207 printf("DHCP code %2d(%2d) len %2d(%2d) ", code, optcode,
210 assert_se(code == optcode);
211 assert_se(len == optlen);
213 for (i = 0; i < len; i++) {
216 printf("0x%02x(0x%02x) ", option[i],
217 descoption[*descpos + 2 + i]);
219 assert_se(option[i] == descoption[*descpos + 2 + i]);
225 *descpos += optlen + 2;
227 test_ignore_opts(descoption, descpos, desclen);
229 if (desc->pos != -1 && desc->pos == desc->len)
232 if (desc->filepos != -1 && desc->filepos == desc->filelen)
235 if (desc->snamepos != -1 && desc->snamepos == desc->snamelen)
241 static void test_options(struct option_desc *desc)
243 uint8_t *options = NULL;
244 uint8_t *file = NULL;
245 uint8_t *sname = NULL;
250 _cleanup_free_ DHCPMessage *message = NULL;
254 file = &desc->file[0];
255 filelen = desc->filelen;
259 sname = &desc->sname[0];
260 snamelen = desc->snamelen;
264 options = &desc->options[0];
268 message = create_message(options, optlen, file, filelen,
271 buflen = sizeof(DHCPMessage) + optlen;
274 assert_se((res = dhcp_option_parse(message, buflen,
277 } else if (desc->success) {
278 assert_se((res = dhcp_option_parse(message, buflen,
281 assert_se(desc->pos == -1 && desc->filepos == -1 &&
282 desc->snamepos == -1);
284 assert_se((res = dhcp_option_parse(message, buflen,
289 printf("DHCP type %s\n", dhcp_type(res));
292 static uint8_t options[64] = {
296 31, 8, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
298 55, 3, 0x51, 0x52, 0x53,
299 17, 7, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
303 static void test_option_set(void)
305 _cleanup_free_ DHCPMessage *result = NULL;
306 size_t offset = 0, len, pos;
309 result = malloc0(sizeof(DHCPMessage) + 11);
312 result->options[0] = 'A';
313 result->options[1] = 'B';
314 result->options[2] = 'C';
315 result->options[3] = 'D';
317 assert_se(dhcp_option_append(result, 0, &offset, 0, DHCP_OPTION_PAD,
318 0, NULL) == -ENOBUFS);
319 assert_se(offset == 0);
322 assert_se(dhcp_option_append(result, 5, &offset, 0, DHCP_OPTION_PAD,
323 0, NULL) == -ENOBUFS);
324 assert_se(offset == 4);
325 assert_se(dhcp_option_append(result, 6, &offset, 0, DHCP_OPTION_PAD,
327 assert_se(offset == 5);
331 while (pos < len && options[pos] != DHCP_OPTION_END) {
332 assert_se(dhcp_option_append(result, len, &offset, DHCP_OVERLOAD_SNAME,
335 &options[pos + 2]) >= 0);
337 if (options[pos] == DHCP_OPTION_PAD)
340 pos += 2 + options[pos + 1];
343 assert_se(offset == pos);
346 for (i = 0; i < 9; i++) {
348 printf("%2u: 0x%02x(0x%02x) (options)\n", i, result->options[i],
350 assert_se(result->options[i] == options[i]);
354 printf("%2d: 0x%02x(0x%02x) (options)\n", 9, result->options[9],
357 assert_se(result->options[9] == DHCP_OPTION_END);
360 printf("%2d: 0x%02x(0x%02x) (options)\n", 10, result->options[10],
363 assert_se(result->options[10] == DHCP_OPTION_PAD);
365 for (i = 0; i < pos - 8; i++) {
367 printf("%2u: 0x%02x(0x%02x) (sname)\n", i, result->sname[i],
369 assert_se(result->sname[i] == options[i + 9]);
376 int main(int argc, char *argv[])
380 test_invalid_buffer_length();
385 for (i = 0; i < ELEMENTSOF(option_tests); i++)
386 test_options(&option_tests[i]);