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;
89 size_t len = sizeof(DHCPMessage) + optlen;
92 message = malloc0(len);
94 opt = (uint8_t *)(message + 1);
96 assert_se(dhcp_message_init(message, BOOTREQUEST, 0x12345678,
97 DHCP_DISCOVER, &opt, &optlen) >= 0);
99 assert_se(message->xid == htobe32(0x12345678));
100 assert_se(message->op == BOOTREQUEST);
102 magic = (uint8_t*)&message->magic;
104 assert_se(magic[0] == 99);
105 assert_se(magic[1] = 130);
106 assert_se(magic[2] = 83);
107 assert_se(magic[3] = 99);
109 assert_se(dhcp_option_parse(message, len, NULL, NULL) >= 0);
112 static DHCPMessage *create_message(uint8_t *options, uint16_t optlen,
113 uint8_t *file, uint8_t filelen,
114 uint8_t *sname, uint8_t snamelen)
116 DHCPMessage *message;
117 size_t len = sizeof(DHCPMessage) + optlen;
120 message = malloc0(len);
121 opt = (uint8_t *)(message + 1);
123 if (options && optlen)
124 memcpy(opt, options, optlen);
126 if (file && filelen <= 128)
127 memcpy(&message->file, file, filelen);
129 if (sname && snamelen <= 64)
130 memcpy(&message->sname, sname, snamelen);
135 static void test_ignore_opts(uint8_t *descoption, int *descpos, int *desclen)
137 while (*descpos < *desclen) {
138 switch(descoption[*descpos]) {
139 case DHCP_OPTION_PAD:
143 case DHCP_OPTION_MESSAGE_TYPE:
144 case DHCP_OPTION_OVERLOAD:
154 static int test_options_cb(uint8_t code, uint8_t len, const uint8_t *option,
157 struct option_desc *desc = user_data;
158 uint8_t *descoption = NULL;
159 int *desclen = NULL, *descpos = NULL;
164 assert_se((!desc && !code && !len) || desc);
169 assert_se(code != DHCP_OPTION_PAD);
170 assert_se(code != DHCP_OPTION_END);
171 assert_se(code != DHCP_OPTION_MESSAGE_TYPE);
172 assert_se(code != DHCP_OPTION_OVERLOAD);
174 while (desc->pos >= 0 || desc->filepos >= 0 || desc->snamepos >= 0) {
176 if (desc->pos >= 0) {
177 descoption = &desc->options[0];
178 desclen = &desc->len;
179 descpos = &desc->pos;
180 } else if (desc->filepos >= 0) {
181 descoption = &desc->file[0];
182 desclen = &desc->filelen;
183 descpos = &desc->filepos;
184 } else if (desc->snamepos >= 0) {
185 descoption = &desc->sname[0];
186 desclen = &desc->snamelen;
187 descpos = &desc->snamepos;
190 assert_se(descoption && desclen && descpos);
193 test_ignore_opts(descoption, descpos, desclen);
195 if (*descpos < *desclen)
198 if (*descpos == *desclen)
203 assert_se(*descpos != -1);
205 optcode = descoption[*descpos];
206 optlen = descoption[*descpos + 1];
209 printf("DHCP code %2d(%2d) len %2d(%2d) ", code, optcode,
212 assert_se(code == optcode);
213 assert_se(len == optlen);
215 for (i = 0; i < len; i++) {
218 printf("0x%02x(0x%02x) ", option[i],
219 descoption[*descpos + 2 + i]);
221 assert_se(option[i] == descoption[*descpos + 2 + i]);
227 *descpos += optlen + 2;
229 test_ignore_opts(descoption, descpos, desclen);
231 if (desc->pos != -1 && desc->pos == desc->len)
234 if (desc->filepos != -1 && desc->filepos == desc->filelen)
237 if (desc->snamepos != -1 && desc->snamepos == desc->snamelen)
243 static void test_options(struct option_desc *desc)
245 uint8_t *options = NULL;
246 uint8_t *file = NULL;
247 uint8_t *sname = NULL;
252 _cleanup_free_ DHCPMessage *message = NULL;
256 file = &desc->file[0];
257 filelen = desc->filelen;
261 sname = &desc->sname[0];
262 snamelen = desc->snamelen;
266 options = &desc->options[0];
270 message = create_message(options, optlen, file, filelen,
273 buflen = sizeof(DHCPMessage) + optlen;
276 assert_se((res = dhcp_option_parse(message, buflen,
279 } else if (desc->success) {
280 assert_se((res = dhcp_option_parse(message, buflen,
283 assert_se(desc->pos == -1 && desc->filepos == -1 &&
284 desc->snamepos == -1);
286 assert_se((res = dhcp_option_parse(message, buflen,
291 printf("DHCP type %s\n", dhcp_type(res));
294 static uint8_t result[64] = {
298 static uint8_t options[64] = {
302 31, 8, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
304 55, 3, 0x51, 0x52, 0x53,
305 17, 7, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
309 static void test_option_set(void)
315 assert_se(dhcp_option_append(NULL, NULL, 0, 0, NULL) == -EINVAL);
319 assert_se(dhcp_option_append(&opt, NULL, 0, 0, NULL) == -EINVAL);
320 assert_se(opt == &result[0] && len == 0);
322 assert_se(dhcp_option_append(&opt, &len, DHCP_OPTION_PAD,
323 0, NULL) == -ENOBUFS);
324 assert_se(opt == &result[0] && len == 0);
328 assert_se(dhcp_option_append(&opt, &len, DHCP_OPTION_PAD,
330 assert_se(opt == &result[5] && len == 0);
334 while (pos < 64 && options[pos] != DHCP_OPTION_END) {
338 assert_se(dhcp_option_append(&opt, &len, options[pos],
340 &options[pos + 2]) >= 0);
342 if (options[pos] == DHCP_OPTION_PAD) {
343 assert_se(opt == &result[pos + 1]);
344 assert_se(len == oldlen - 1);
347 assert_se(opt == &result[pos + 2 + options[pos + 1]]);
348 assert_se(len == oldlen - 2 - options[pos + 1]);
349 pos += 2 + options[pos + 1];
353 for (i = 0; i < pos; i++) {
355 printf("%2d: 0x%02x(0x%02x)\n", i, result[i],
357 assert_se(result[i] == options[i]);
364 int main(int argc, char *argv[])
368 test_invalid_buffer_length();
373 for (i = 0; i < ELEMENTSOF(option_tests); i++)
374 test_options(&option_tests[i]);