4 // #include <arpa/inet.h>
5 #include <netinet/in.h>
11 * Pack DHCP options into an option field, without overload support.
12 * On return, len contains the number of active bytes, and the full
13 * field is zero-padded.
15 * Options which are successfully placed have their length zeroed out.
17 static int dhcp_pack_field_zero(void *field
, size_t *len
,
18 struct dhcp_option opt
[256])
30 for (i
= 1; i
< 255; i
++) {
34 /* We need to handle the 0 case as well as > 255 */
35 if (opt
[i
].len
<= 255)
36 xlen
= opt
[i
].len
+ 2;
38 xlen
= opt
[i
].len
+ 2*((opt
[i
].len
+254)/255);
43 /* This option doesn't fit... */
51 *q
++ = plen
= xlen
> 255 ? 255 : xlen
;
63 *q
++ = 255; /* End marker */
64 memset(q
, 0, spc
); /* Zero-pad the rest of the field */
66 *len
= xlen
= q
- (uint8_t *)field
;
71 * Pack DHCP options into an option field, without overload support.
72 * On return, len contains the number of active bytes, and the full
73 * field is zero-padded.
75 * Use this to encode encapsulated option fields.
77 int dhcp_pack_field(void *field
, size_t *len
,
78 struct dhcp_option opt
[256])
80 struct dhcp_option ox
[256];
82 memcpy(ox
, opt
, sizeof ox
);
83 return dhcp_pack_field_zero(field
, len
, ox
);
87 * Pack DHCP options into a packet.
88 * Apply overloading if (and only if) the "file" or "sname" option
89 * doesn't fit in the respective dedicated fields.
91 int dhcp_pack_packet(void *packet
, size_t *len
,
92 const struct dhcp_option opt
[256])
94 struct dhcp_packet
*pkt
= packet
;
97 struct dhcp_option ox
[256];
101 if (spc
< sizeof(struct dhcp_packet
))
102 return ENOSPC
; /* Buffer impossibly small */
104 pkt
->magic
= htonl(DHCP_VENDOR_MAGIC
);
106 memcpy(ox
, opt
, sizeof ox
);
108 /* Figure out if we should do overloading or not */
111 if (opt
[67].len
> 128)
116 if (opt
[66].len
> 64)
121 /* Kill any passed-in overload option */
127 /* Force option 53 (DHCP packet type) first */
128 if (ox
[53].len
== 1) {
131 *q
++ = *(uint8_t *)ox
[53].data
;
136 /* Follow with the overload option, if applicable */
144 err
= dhcp_pack_field_zero(q
, &spc
, ox
);
145 *len
= spc
+ (q
-(uint8_t *)packet
);
149 err
= dhcp_pack_field_zero(pkt
->file
, &spc
, ox
);
151 memset(pkt
->file
, 0, 128);
153 memcpy(pkt
->file
, opt
[67].data
, opt
[67].len
);
158 err
= dhcp_pack_field_zero(pkt
->sname
, &spc
, ox
);
160 memset(pkt
->sname
, 0, 64);
162 memcpy(pkt
->sname
, opt
[66].data
, opt
[66].len
);