1 #define _GNU_SOURCE /* For strnlen() */
5 // #include <arpa/inet.h>
6 #include <netinet/in.h>
12 * Unpack DHCP options from a field. Assumes opt is pre-initalized
13 * (to all zero in the common case.)
15 int dhcp_unpack_field(const void *field
, size_t len
,
16 struct dhcp_option opt
[256])
18 const uint8_t *p
= field
;
37 opt
[op
].data
= realloc(opt
[op
].data
,
38 opt
[op
].len
+ xlen
+ 1);
43 memcpy((char *)opt
[op
].data
+ opt
[op
].len
, p
, xlen
);
45 /* Null-terminate as a courtesy to users */
46 *((char *)opt
[op
].data
+ opt
[op
].len
) = 0;
56 * Unpack a DHCP packet, with overload support. Do not use this
57 * to unpack an encapsulated option set.
59 int dhcp_unpack_packet(const void *packet
, size_t len
,
60 struct dhcp_option opt
[256])
62 const struct dhcp_packet
*pkt
= packet
;
67 if (len
< 240 || pkt
->magic
!= htonl(DHCP_VENDOR_MAGIC
))
68 return EINVAL
; /* Bogus packet */
70 for (i
= 0; i
< 256; i
++) {
71 opt
[i
].len
= -1; /* Option not present */
75 err
= dhcp_unpack_field(pkt
->options
, len
-240, opt
);
78 if (opt
[52].len
== 1) {
79 overload
= *(uint8_t *)opt
[52].data
;
86 err
|= dhcp_unpack_field(pkt
->file
, 128, opt
);
88 opt
[67].len
= strnlen((const char *)pkt
->file
, 128);
90 opt
[67].data
= malloc(opt
[67].len
+ 1);
92 memcpy(opt
[67].data
, pkt
->file
, opt
[67].len
);
93 *((char *)opt
[67].data
+ opt
[67].len
) = 0;
101 err
|= dhcp_unpack_field(pkt
->sname
, 64, opt
);
103 opt
[66].len
= strnlen((const char *)pkt
->sname
, 64);
105 opt
[66].data
= malloc(opt
[66].len
+ 1);
107 memcpy(opt
[66].data
, pkt
->file
, opt
[66].len
);
108 *((char *)opt
[66].data
+ opt
[66].len
) = 0;