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, message->options, 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 result[64] = {
294 static uint8_t options[64] = {
298 31, 8, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
300 55, 3, 0x51, 0x52, 0x53,
301 17, 7, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
305 static void test_option_set(void)
307 size_t offset = 0, len, pos;
310 assert_se(dhcp_option_append(result, 0, &offset, DHCP_OPTION_PAD,
311 0, NULL) == -ENOBUFS);
312 assert_se(offset == 0);
315 assert_se(dhcp_option_append(result, 1, &offset, DHCP_OPTION_PAD,
317 assert_se(offset == 5);
321 while (pos < 64 && options[pos] != DHCP_OPTION_END) {
324 assert_se(dhcp_option_append(result, len, &offset,
327 &options[pos + 2]) >= 0);
329 if (options[pos] == DHCP_OPTION_PAD)
332 pos += 2 + options[pos + 1];
334 assert_se(offset == pos);
337 for (i = 0; i < pos; i++) {
339 printf("%2d: 0x%02x(0x%02x)\n", i, result[i],
341 assert_se(result[i] == options[i]);
348 int main(int argc, char *argv[])
352 test_invalid_buffer_length();
357 for (i = 0; i < ELEMENTSOF(option_tests); i++)
358 test_options(&option_tests[i]);