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), NULL, NULL)
85 static void test_cookie(void)
87 _cleanup_free_ DHCPMessage *message;
88 size_t len = sizeof(DHCPMessage) + 4;
91 message = malloc0(len);
93 opt = (uint8_t *)(message + 1);
96 assert_se(dhcp_option_parse(message, len, NULL, NULL) == -EINVAL);
103 assert_se(dhcp_option_parse(message, len, NULL, NULL) == -ENOMSG);
106 static DHCPMessage *create_message(uint8_t *options, uint16_t optlen,
107 uint8_t *file, uint8_t filelen,
108 uint8_t *sname, uint8_t snamelen)
110 DHCPMessage *message;
111 size_t len = sizeof(DHCPMessage) + 4 + optlen;
114 message = malloc0(len);
115 opt = (uint8_t *)(message + 1);
122 if (options && optlen)
123 memcpy(&opt[4], options, optlen);
125 if (file && filelen <= 128)
126 memcpy(&message->file, file, filelen);
128 if (sname && snamelen <= 64)
129 memcpy(&message->sname, sname, snamelen);
134 static void test_ignore_opts(uint8_t *descoption, int *descpos, int *desclen)
136 while (*descpos < *desclen) {
137 switch(descoption[*descpos]) {
138 case DHCP_OPTION_PAD:
142 case DHCP_OPTION_MESSAGE_TYPE:
143 case DHCP_OPTION_OVERLOAD:
153 static int test_options_cb(uint8_t code, uint8_t len, const uint8_t *option,
156 struct option_desc *desc = user_data;
157 uint8_t *descoption = NULL;
158 int *desclen = NULL, *descpos = NULL;
163 assert_se((!desc && !code && !len) || desc);
168 assert_se(code != DHCP_OPTION_PAD);
169 assert_se(code != DHCP_OPTION_END);
170 assert_se(code != DHCP_OPTION_MESSAGE_TYPE);
171 assert_se(code != DHCP_OPTION_OVERLOAD);
173 while (desc->pos >= 0 || desc->filepos >= 0 || desc->snamepos >= 0) {
175 if (desc->pos >= 0) {
176 descoption = &desc->options[0];
177 desclen = &desc->len;
178 descpos = &desc->pos;
179 } else if (desc->filepos >= 0) {
180 descoption = &desc->file[0];
181 desclen = &desc->filelen;
182 descpos = &desc->filepos;
183 } else if (desc->snamepos >= 0) {
184 descoption = &desc->sname[0];
185 desclen = &desc->snamelen;
186 descpos = &desc->snamepos;
189 assert_se(descoption && desclen && descpos);
192 test_ignore_opts(descoption, descpos, desclen);
194 if (*descpos < *desclen)
197 if (*descpos == *desclen)
202 assert_se(*descpos != -1);
204 optcode = descoption[*descpos];
205 optlen = descoption[*descpos + 1];
208 printf("DHCP code %2d(%2d) len %2d(%2d) ", code, optcode,
211 assert_se(code == optcode);
212 assert_se(len == optlen);
214 for (i = 0; i < len; i++) {
217 printf("0x%02x(0x%02x) ", option[i],
218 descoption[*descpos + 2 + i]);
220 assert_se(option[i] == descoption[*descpos + 2 + i]);
226 *descpos += optlen + 2;
228 test_ignore_opts(descoption, descpos, desclen);
230 if (desc->pos != -1 && desc->pos == desc->len)
233 if (desc->filepos != -1 && desc->filepos == desc->filelen)
236 if (desc->snamepos != -1 && desc->snamepos == desc->snamelen)
242 static void test_options(struct option_desc *desc)
244 uint8_t *options = NULL;
245 uint8_t *file = NULL;
246 uint8_t *sname = NULL;
251 _cleanup_free_ DHCPMessage *message;
255 file = &desc->file[0];
256 filelen = desc->filelen;
260 sname = &desc->sname[0];
261 snamelen = desc->snamelen;
265 options = &desc->options[0];
269 message = create_message(options, optlen, file, filelen,
272 buflen = sizeof(DHCPMessage) + 4 + optlen;
275 assert_se((res = dhcp_option_parse(message, buflen,
278 } else if (desc->success) {
279 assert_se((res = dhcp_option_parse(message, buflen,
282 assert_se(desc->pos == -1 && desc->filepos == -1 &&
283 desc->snamepos == -1);
285 assert_se((res = dhcp_option_parse(message, buflen,
290 printf("DHCP type %s\n", dhcp_type(res));
293 static uint8_t result[64] = {
297 static uint8_t options[64] = {
301 31, 8, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
303 55, 3, 0x51, 0x52, 0x53,
304 17, 7, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
308 static void test_option_set(void)
314 assert_se(dhcp_option_append(NULL, NULL, 0, 0, NULL) == -EINVAL);
318 assert_se(dhcp_option_append(&opt, NULL, 0, 0, NULL) == -EINVAL);
319 assert_se(opt == &result[0] && len == 0);
321 assert_se(dhcp_option_append(&opt, &len, DHCP_OPTION_PAD,
322 0, NULL) == -ENOBUFS);
323 assert_se(opt == &result[0] && len == 0);
327 assert_se(dhcp_option_append(&opt, &len, DHCP_OPTION_PAD,
329 assert_se(opt == &result[5] && len == 0);
333 while (pos < 64 && options[pos] != DHCP_OPTION_END) {
337 assert_se(dhcp_option_append(&opt, &len, options[pos],
339 &options[pos + 2]) >= 0);
341 if (options[pos] == DHCP_OPTION_PAD) {
342 assert_se(opt == &result[pos + 1]);
343 assert_se(len == oldlen - 1);
346 assert_se(opt == &result[pos + 2 + options[pos + 1]]);
347 assert_se(len == oldlen - 2 - options[pos + 1]);
348 pos += 2 + options[pos + 1];
352 for (i = 0; i < pos; i++) {
354 printf("%2d: 0x%02x(0x%02x)\n", i, result[i],
356 assert_se(result[i] == options[i]);
363 int main(int argc, char *argv[])
367 test_invalid_buffer_length();
372 for (i = 0; i < ELEMENTSOF(option_tests); i++)
373 test_options(&option_tests[i]);