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(dhcp_option_parse(&message, 0, NULL, NULL) == -EINVAL);
81 assert(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(dhcp_option_parse(message, len, NULL, NULL) == -EINVAL);
103 assert(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((!desc && !code && !len) || desc);
168 assert(code != DHCP_OPTION_PAD);
169 assert(code != DHCP_OPTION_END);
170 assert(code != DHCP_OPTION_MESSAGE_TYPE);
171 assert(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(descoption && desclen && descpos);
192 test_ignore_opts(descoption, descpos, desclen);
194 if (*descpos < *desclen)
197 if (*descpos == *desclen)
201 assert(*descpos != -1);
203 optcode = descoption[*descpos];
204 optlen = descoption[*descpos + 1];
207 printf("DHCP code %2d(%2d) len %2d(%2d) ", code, optcode,
210 assert(code == optcode);
211 assert(len == optlen);
213 for (i = 0; i < len; i++) {
216 printf("0x%02x(0x%02x) ", option[i],
217 descoption[*descpos + 2 + i]);
219 assert(option[i] == descoption[*descpos + 2 + i]);
225 *descpos += optlen + 2;
227 test_ignore_opts(descoption, descpos, desclen);
229 if (desc->pos != -1 && desc->pos == desc->len)
232 if (desc->filepos != -1 && desc->filepos == desc->filelen)
235 if (desc->snamepos != -1 && desc->snamepos == desc->snamelen)
241 static void test_options(struct option_desc *desc)
243 uint8_t *options = NULL;
244 uint8_t *file = NULL;
245 uint8_t *sname = NULL;
250 _cleanup_free_ DHCPMessage *message;
254 file = &desc->file[0];
255 filelen = desc->filelen;
259 sname = &desc->sname[0];
260 snamelen = desc->snamelen;
264 options = &desc->options[0];
268 message = create_message(options, optlen, file, filelen,
271 buflen = sizeof(DHCPMessage) + 4 + optlen;
274 assert((res = dhcp_option_parse(message, buflen,
277 } else if (desc->success) {
278 assert((res = dhcp_option_parse(message, buflen,
281 assert(desc->pos == -1 && desc->filepos == -1 &&
282 desc->snamepos == -1);
284 assert((res = dhcp_option_parse(message, buflen,
289 printf("DHCP type %s\n", dhcp_type(res));
292 int main(int argc, char *argv[])
296 test_invalid_buffer_length();
301 for (i = 0; i < ELEMENTSOF(option_tests); i++)
302 test_options(&option_tests[i]);