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, ARPHRD_ETHER, 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);
120 if (options && optlen)
121 memcpy(&message->options, options, optlen);
123 if (file && filelen <= 128)
124 memcpy(&message->file, file, filelen);
126 if (sname && snamelen <= 64)
127 memcpy(&message->sname, sname, snamelen);
132 static void test_ignore_opts(uint8_t *descoption, int *descpos, int *desclen)
134 while (*descpos < *desclen) {
135 switch(descoption[*descpos]) {
136 case DHCP_OPTION_PAD:
140 case DHCP_OPTION_MESSAGE_TYPE:
141 case DHCP_OPTION_OVERLOAD:
151 static int test_options_cb(uint8_t code, uint8_t len, const uint8_t *option,
154 struct option_desc *desc = user_data;
155 uint8_t *descoption = NULL;
156 int *desclen = NULL, *descpos = NULL;
161 assert_se((!desc && !code && !len) || desc);
166 assert_se(code != DHCP_OPTION_PAD);
167 assert_se(code != DHCP_OPTION_END);
168 assert_se(code != DHCP_OPTION_MESSAGE_TYPE);
169 assert_se(code != DHCP_OPTION_OVERLOAD);
171 while (desc->pos >= 0 || desc->filepos >= 0 || desc->snamepos >= 0) {
173 if (desc->pos >= 0) {
174 descoption = &desc->options[0];
175 desclen = &desc->len;
176 descpos = &desc->pos;
177 } else if (desc->filepos >= 0) {
178 descoption = &desc->file[0];
179 desclen = &desc->filelen;
180 descpos = &desc->filepos;
181 } else if (desc->snamepos >= 0) {
182 descoption = &desc->sname[0];
183 desclen = &desc->snamelen;
184 descpos = &desc->snamepos;
187 assert_se(descoption && desclen && descpos);
190 test_ignore_opts(descoption, descpos, desclen);
192 if (*descpos < *desclen)
195 if (*descpos == *desclen)
200 assert_se(*descpos != -1);
202 optcode = descoption[*descpos];
203 optlen = descoption[*descpos + 1];
206 printf("DHCP code %2d(%2d) len %2d(%2d) ", code, optcode,
209 assert_se(code == optcode);
210 assert_se(len == optlen);
212 for (i = 0; i < len; i++) {
215 printf("0x%02x(0x%02x) ", option[i],
216 descoption[*descpos + 2 + i]);
218 assert_se(option[i] == descoption[*descpos + 2 + i]);
224 *descpos += optlen + 2;
226 test_ignore_opts(descoption, descpos, desclen);
228 if (desc->pos != -1 && desc->pos == desc->len)
231 if (desc->filepos != -1 && desc->filepos == desc->filelen)
234 if (desc->snamepos != -1 && desc->snamepos == desc->snamelen)
240 static void test_options(struct option_desc *desc)
242 uint8_t *options = NULL;
243 uint8_t *file = NULL;
244 uint8_t *sname = NULL;
249 _cleanup_free_ DHCPMessage *message = NULL;
253 file = &desc->file[0];
254 filelen = desc->filelen;
258 sname = &desc->sname[0];
259 snamelen = desc->snamelen;
263 options = &desc->options[0];
267 message = create_message(options, optlen, file, filelen,
270 buflen = sizeof(DHCPMessage) + optlen;
273 assert_se((res = dhcp_option_parse(message, buflen,
276 } else if (desc->success) {
277 assert_se((res = dhcp_option_parse(message, buflen,
280 assert_se(desc->pos == -1 && desc->filepos == -1 &&
281 desc->snamepos == -1);
283 assert_se((res = dhcp_option_parse(message, buflen,
288 printf("DHCP type %s\n", dhcp_type(res));
291 static uint8_t options[64] = {
295 31, 8, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
297 55, 3, 0x51, 0x52, 0x53,
298 17, 7, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
302 static void test_option_set(void)
304 _cleanup_free_ DHCPMessage *result = NULL;
305 size_t offset = 0, len, pos;
308 result = malloc0(sizeof(DHCPMessage) + 11);
311 result->options[0] = 'A';
312 result->options[1] = 'B';
313 result->options[2] = 'C';
314 result->options[3] = 'D';
316 assert_se(dhcp_option_append(result, 0, &offset, 0, DHCP_OPTION_PAD,
317 0, NULL) == -ENOBUFS);
318 assert_se(offset == 0);
321 assert_se(dhcp_option_append(result, 5, &offset, 0, DHCP_OPTION_PAD,
322 0, NULL) == -ENOBUFS);
323 assert_se(offset == 4);
324 assert_se(dhcp_option_append(result, 6, &offset, 0, DHCP_OPTION_PAD,
326 assert_se(offset == 5);
330 while (pos < len && options[pos] != DHCP_OPTION_END) {
331 assert_se(dhcp_option_append(result, len, &offset, DHCP_OVERLOAD_SNAME,
334 &options[pos + 2]) >= 0);
336 if (options[pos] == DHCP_OPTION_PAD)
339 pos += 2 + options[pos + 1];
342 assert_se(offset == pos);
345 for (i = 0; i < 9; i++) {
347 printf("%2d: 0x%02x(0x%02x) (options)\n", i, result->options[i],
349 assert_se(result->options[i] == options[i]);
353 printf("%2d: 0x%02x(0x%02x) (options)\n", 9, result->options[9],
356 assert_se(result->options[9] == DHCP_OPTION_END);
359 printf("%2d: 0x%02x(0x%02x) (options)\n", 10, result->options[10],
362 assert_se(result->options[10] == DHCP_OPTION_PAD);
364 for (i = 0; i < pos - 8; i++) {
366 printf("%2d: 0x%02x(0x%02x) (sname)\n", i, result->sname[i],
368 assert_se(result->sname[i] == options[i + 9]);
375 int main(int argc, char *argv[])
379 test_invalid_buffer_length();
384 for (i = 0; i < ELEMENTSOF(option_tests); i++)
385 test_options(&option_tests[i]);