11 #include "dhcp-protocol.h"
12 #include "dhcp-internal.h"
27 static bool verbose = false;
29 static struct option_desc option_tests[] = {
30 { {}, 0, {}, 0, { 42, 5, 65, 66, 67, 68, 69 }, 7, false, },
31 { {}, 0, {}, 0, { 42, 5, 65, 66, 67, 68, 69, 0, 0,
32 DHCP_OPTION_MESSAGE_TYPE, 1, DHCP_ACK }, 12, true, },
33 { {}, 0, {}, 0, { 8, 255, 70, 71, 72 }, 5, false, },
34 { {}, 0, {}, 0, { 0x35, 0x01, 0x05, 0x36, 0x04, 0x01, 0x00, 0xa8,
35 0xc0, 0x33, 0x04, 0x00, 0x01, 0x51, 0x80, 0x01,
36 0x04, 0xff, 0xff, 0xff, 0x00, 0x03, 0x04, 0xc0,
37 0xa8, 0x00, 0x01, 0x06, 0x04, 0xc0, 0xa8, 0x00,
38 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
40 { {}, 0, {}, 0, { DHCP_OPTION_MESSAGE_TYPE, 1, DHCP_OFFER,
41 42, 3, 0, 0, 0 }, 8, true, },
42 { {}, 0, {}, 0, { 42, 2, 1, 2, 44 }, 5, false, },
45 { 222, 3, 1, 2, 3, DHCP_OPTION_MESSAGE_TYPE, 1, DHCP_NAK }, 8,
46 { DHCP_OPTION_OVERLOAD, 1, DHCP_OVERLOAD_FILE }, 3, true, },
48 { { 1, 4, 1, 2, 3, 4, DHCP_OPTION_MESSAGE_TYPE, 1, DHCP_ACK }, 9,
49 { 222, 3, 1, 2, 3 }, 5,
50 { DHCP_OPTION_OVERLOAD, 1,
51 DHCP_OVERLOAD_FILE|DHCP_OVERLOAD_SNAME }, 3, true, },
54 static const char *dhcp_type(int type)
58 return "DHCPDISCOVER";
76 static void test_invalid_buffer_length(void)
80 assert_se(dhcp_option_parse(&message, 0, NULL, NULL) == -EINVAL);
81 assert_se(dhcp_option_parse(&message, sizeof(DHCPMessage) - 1, NULL, NULL)
85 static void test_message_init(void)
87 _cleanup_free_ DHCPMessage *message = NULL;
88 size_t optlen = 4, optoffset;
89 size_t len = sizeof(DHCPMessage) + optlen;
92 message = malloc0(len);
94 assert_se(dhcp_message_init(message, BOOTREQUEST, 0x12345678,
95 DHCP_DISCOVER, optlen, &optoffset) >= 0);
97 assert_se(message->xid == htobe32(0x12345678));
98 assert_se(message->op == BOOTREQUEST);
100 magic = (uint8_t*)&message->magic;
102 assert_se(magic[0] == 99);
103 assert_se(magic[1] = 130);
104 assert_se(magic[2] = 83);
105 assert_se(magic[3] = 99);
107 assert_se(dhcp_option_parse(message, len, NULL, NULL) >= 0);
110 static DHCPMessage *create_message(uint8_t *options, uint16_t optlen,
111 uint8_t *file, uint8_t filelen,
112 uint8_t *sname, uint8_t snamelen)
114 DHCPMessage *message;
115 size_t len = sizeof(DHCPMessage) + optlen;
117 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 while (*descpos < *desclen) {
134 switch(descoption[*descpos]) {
135 case DHCP_OPTION_PAD:
139 case DHCP_OPTION_MESSAGE_TYPE:
140 case DHCP_OPTION_OVERLOAD:
150 static int test_options_cb(uint8_t code, uint8_t len, const uint8_t *option,
153 struct option_desc *desc = user_data;
154 uint8_t *descoption = NULL;
155 int *desclen = NULL, *descpos = NULL;
160 assert_se((!desc && !code && !len) || desc);
165 assert_se(code != DHCP_OPTION_PAD);
166 assert_se(code != DHCP_OPTION_END);
167 assert_se(code != DHCP_OPTION_MESSAGE_TYPE);
168 assert_se(code != DHCP_OPTION_OVERLOAD);
170 while (desc->pos >= 0 || desc->filepos >= 0 || desc->snamepos >= 0) {
172 if (desc->pos >= 0) {
173 descoption = &desc->options[0];
174 desclen = &desc->len;
175 descpos = &desc->pos;
176 } else if (desc->filepos >= 0) {
177 descoption = &desc->file[0];
178 desclen = &desc->filelen;
179 descpos = &desc->filepos;
180 } else if (desc->snamepos >= 0) {
181 descoption = &desc->sname[0];
182 desclen = &desc->snamelen;
183 descpos = &desc->snamepos;
186 assert_se(descoption && desclen && descpos);
189 test_ignore_opts(descoption, descpos, desclen);
191 if (*descpos < *desclen)
194 if (*descpos == *desclen)
199 assert_se(*descpos != -1);
201 optcode = descoption[*descpos];
202 optlen = descoption[*descpos + 1];
205 printf("DHCP code %2d(%2d) len %2d(%2d) ", code, optcode,
208 assert_se(code == optcode);
209 assert_se(len == optlen);
211 for (i = 0; i < len; i++) {
214 printf("0x%02x(0x%02x) ", option[i],
215 descoption[*descpos + 2 + i]);
217 assert_se(option[i] == descoption[*descpos + 2 + i]);
223 *descpos += optlen + 2;
225 test_ignore_opts(descoption, descpos, desclen);
227 if (desc->pos != -1 && desc->pos == desc->len)
230 if (desc->filepos != -1 && desc->filepos == desc->filelen)
233 if (desc->snamepos != -1 && desc->snamepos == desc->snamelen)
239 static void test_options(struct option_desc *desc)
241 uint8_t *options = NULL;
242 uint8_t *file = NULL;
243 uint8_t *sname = NULL;
248 _cleanup_free_ DHCPMessage *message = NULL;
252 file = &desc->file[0];
253 filelen = desc->filelen;
257 sname = &desc->sname[0];
258 snamelen = desc->snamelen;
262 options = &desc->options[0];
266 message = create_message(options, optlen, file, filelen,
269 buflen = sizeof(DHCPMessage) + optlen;
272 assert_se((res = dhcp_option_parse(message, buflen,
275 } else if (desc->success) {
276 assert_se((res = dhcp_option_parse(message, buflen,
279 assert_se(desc->pos == -1 && desc->filepos == -1 &&
280 desc->snamepos == -1);
282 assert_se((res = dhcp_option_parse(message, buflen,
287 printf("DHCP type %s\n", dhcp_type(res));
290 static uint8_t options[64] = {
294 31, 8, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
296 55, 3, 0x51, 0x52, 0x53,
297 17, 7, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
301 static void test_option_set(void)
303 _cleanup_free_ DHCPMessage *result = NULL;
304 size_t offset = 0, len, pos;
307 result = malloc0(sizeof(DHCPMessage) + 11);
310 result->options[0] = 'A';
311 result->options[1] = 'B';
312 result->options[2] = 'C';
313 result->options[3] = 'D';
315 assert_se(dhcp_option_append(result, 0, &offset, 0, DHCP_OPTION_PAD,
316 0, NULL) == -ENOBUFS);
317 assert_se(offset == 0);
320 assert_se(dhcp_option_append(result, 5, &offset, 0, DHCP_OPTION_PAD,
321 0, NULL) == -ENOBUFS);
322 assert_se(offset == 4);
323 assert_se(dhcp_option_append(result, 6, &offset, 0, DHCP_OPTION_PAD,
325 assert_se(offset == 5);
329 while (pos < len && options[pos] != DHCP_OPTION_END) {
330 assert_se(dhcp_option_append(result, len, &offset, DHCP_OVERLOAD_SNAME,
333 &options[pos + 2]) >= 0);
335 if (options[pos] == DHCP_OPTION_PAD)
338 pos += 2 + options[pos + 1];
341 assert_se(offset == pos);
344 for (i = 0; i < 9; i++) {
346 printf("%2d: 0x%02x(0x%02x) (options)\n", i, result->options[i],
348 assert_se(result->options[i] == options[i]);
352 printf("%2d: 0x%02x(0x%02x) (options)\n", 9, result->options[9],
355 assert_se(result->options[9] == DHCP_OPTION_END);
358 printf("%2d: 0x%02x(0x%02x) (options)\n", 10, result->options[10],
361 assert_se(result->options[10] == DHCP_OPTION_PAD);
363 for (i = 0; i < pos - 8; i++) {
365 printf("%2d: 0x%02x(0x%02x) (sname)\n", i, result->sname[i],
367 assert_se(result->sname[i] == options[i + 9]);
374 int main(int argc, char *argv[])
378 test_invalid_buffer_length();
383 for (i = 0; i < ELEMENTSOF(option_tests); i++)
384 test_options(&option_tests[i]);