Add sketch code to reassemble a DHCP packet from our internal "everything
[people/mcb30/gpxe.git] / src / include / gpxe / dhcp.h
1 #ifndef _GPXE_DHCP_H
2 #define _GPXE_DHCP_H
3
4 /** @file
5  *
6  * Dynamic Host Configuration Protocol
7  *
8  */
9
10 #include <stdint.h>
11 #include <gpxe/list.h>
12 #include <gpxe/in.h>
13
14 /**
15  * A DHCP packet
16  *
17  */
18 struct dhcp_packet {
19         /** Operation
20          *
21          * This must be either @c BOOTP_REQUEST or @c BOOTP_REPLY.
22          */
23         uint8_t op;
24         /** Hardware address type
25          *
26          * This is an ARPHRD_XXX constant.
27          */
28         uint8_t htype;
29         /** Hardware address length */
30         uint8_t hlen;
31         /** Number of hops from server */
32         uint8_t hops;
33         /** Transaction ID */
34         uint32_t xid;
35         /** Seconds since start of acquisition */
36         uint16_t secs;
37         /** Flags */
38         uint16_t flags;
39         /** "Client" IP address
40          *
41          * This is filled in if the client already has an IP address
42          * assigned and can respond to ARP requests.
43          */
44         struct in_addr ciaddr;
45         /** "Your" IP address
46          *
47          * This is the IP address assigned by the server to the client.
48          */
49         struct in_addr yiaddr;
50         /** "Server" IP address
51          *
52          * This is the IP address of the next server to be used in the
53          * boot process.
54          */
55         struct in_addr siaddr;
56         /** "Gateway" IP address
57          *
58          * This is the IP address of the DHCP relay agent, if any.
59          */
60         struct in_addr giaddr;
61         /** Client hardware address */
62         uint8_t chaddr[16];
63         /** Server host name (null terminated)
64          *
65          * This field may be overridden and contain DHCP options
66          */
67         uint8_t sname[64];
68         /** Boot file name (null terminated)
69          *
70          * This field may be overridden and contain DHCP options
71          */
72         uint8_t file[128];
73         /** DHCP magic cookie
74          *
75          * Must have the value @c DHCP_MAGIC_COOKIE.
76          */
77         uint32_t magic;
78         /** DHCP options
79          *
80          * Variable length; extends to the end of the packet.
81          */
82         uint8_t options[0];
83 };
84
85 /** Opcode for a request from client to server */
86 #define BOOTP_REQUEST 1
87
88 /** Opcode for a reply from server to client */
89 #define BOOTP_REPLY 2
90
91 /** DHCP magic cookie */
92 #define DHCP_MAGIC_COOKIE 0x63825363UL
93
94 /** Construct a tag value for an encapsulated option
95  *
96  * This tag value can be passed to Etherboot functions when searching
97  * for DHCP options in order to search for a tag within an
98  * encapsulated options block.
99  */
100 #define DHCP_ENCAP_OPT( encapsulator, encapsulated ) \
101         ( ( (encapsulator) << 8 ) | (encapsulated) )
102 /** Extract encapsulating option block tag from encapsulated tag value */
103 #define DHCP_ENCAPSULATOR( encap_opt ) ( (encap_opt) >> 8 )
104 /** Extract encapsulated option tag from encapsulated tag value */
105 #define DHCP_ENCAPSULATED( encap_opt ) ( (encap_opt) & 0xff )
106 /** Option is encapsulated */
107 #define DHCP_IS_ENCAP_OPT( opt ) DHCP_ENCAPSULATOR( opt )
108
109 /**
110  * @defgroup dhcpopts DHCP option tags
111  * @{
112  */
113
114 /** Padding
115  *
116  * This tag does not have a length field; it is always only a single
117  * byte in length.
118  */
119 #define DHCP_PAD 0
120
121 /** Minimum normal DHCP option */
122 #define DHCP_MIN_OPTION 1
123
124 /** Vendor encapsulated options */
125 #define DHCP_VENDOR_ENCAP 43
126
127 /** Option overloading
128  *
129  * The value of this option is the bitwise-OR of zero or more
130  * DHCP_OPTION_OVERLOAD_XXX constants.
131  */
132 #define DHCP_OPTION_OVERLOAD 52
133
134 /** The "file" field is overloaded to contain extra DHCP options */
135 #define DHCP_OPTION_OVERLOAD_FILE 1
136
137 /** The "sname" field is overloaded to contain extra DHCP options */
138 #define DHCP_OPTION_OVERLOAD_SNAME 2
139
140 /** DHCP message type */
141 #define DHCP_MESSAGE_TYPE 53
142 #define DHCPDISCOVER 1
143 #define DHCPOFFER 2
144 #define DHCPREQUEST 3
145 #define DHCPDECLINE 4
146 #define DHCPACK 5
147 #define DHCPNAK 6
148 #define DHCPRELEASE 7
149 #define DHCPINFORM 8
150
151 /** TFTP server name
152  *
153  * This option replaces the fixed "sname" field, when that field is
154  * used to contain overloaded options.
155  */
156 #define DHCP_TFTP_SERVER_NAME 66
157
158 /** Bootfile name
159  *
160  * This option replaces the fixed "file" field, when that field is
161  * used to contain overloaded options.
162  */
163 #define DHCP_BOOTFILE_NAME 67
164
165 /** Etherboot-specific encapsulated options
166  *
167  * This encapsulated options field is used to contain all options
168  * specific to Etherboot (i.e. not assigned by IANA or other standards
169  * bodies).
170  */
171 #define DHCP_EB_ENCAP 175
172
173 /** Priority of this options block
174  *
175  * This is a signed 8-bit integer field indicating the priority of
176  * this block of options.  It can be used to specify the relative
177  * priority of multiple option blocks (e.g. options from non-volatile
178  * storage versus options from a DHCP server).
179  */
180 #define DHCP_EB_PRIORITY DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 1 )
181
182 /** "Your" IP address
183  *
184  * This option is used internally to contain the value of the "yiaddr"
185  * field, in order to provide a consistent approach to storing and
186  * processing options.  It should never be present in a DHCP packet.
187  */
188 #define DHCP_EB_YIADDR DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 2 )
189
190 /** "Server" IP address
191  *
192  * This option is used internally to contain the value of the "siaddr"
193  * field, in order to provide a consistent approach to storing and
194  * processing options.  It should never be present in a DHCP packet.
195  */
196 #define DHCP_EB_SIADDR DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 3 )
197
198 /** Maximum normal DHCP option */
199 #define DHCP_MAX_OPTION 254
200
201 /** End of options
202  *
203  * This tag does not have a length field; it is always only a single
204  * byte in length.
205  */
206 #define DHCP_END 255
207
208 /** @} */
209
210 /**
211  * A DHCP option
212  *
213  * DHCP options consist of a mandatory tag, a length field that is
214  * mandatory for all options except @c DHCP_PAD and @c DHCP_END, and a
215  * payload.  
216  */
217 struct dhcp_option {
218         /** Tag
219          *
220          * Must be a @c DHCP_XXX value.
221          */
222         uint8_t tag;
223         /** Length
224          *
225          * This is the length of the data field (i.e. excluding the
226          * tag and length fields).  For the two tags @c DHCP_PAD and
227          * @c DHCP_END, the length field is implicitly zero and is
228          * also missing, i.e. these DHCP options are only a single
229          * byte in length.
230          */
231         uint8_t len;
232         /** Option data
233          *
234          * Interpretation of the content is entirely dependent upon
235          * the tag.  For fields containing a multi-byte integer, the
236          * field is defined to be in network-endian order (unless you
237          * are Intel and feel like violating the spec for fun).
238          */
239         union {
240                 uint8_t byte;
241                 uint16_t word;
242                 uint32_t dword;
243                 uint8_t bytes[0];
244         } data;
245 } __attribute__ (( packed ));
246
247 /**
248  * Length of a DHCP option header
249  *
250  * The header is the portion excluding the data, i.e. the tag and the
251  * length.
252  */
253 #define DHCP_OPTION_HEADER_LEN ( offsetof ( struct dhcp_option, data ) )
254
255 /** Maximum length for a single DHCP option */
256 #define DHCP_MAX_LEN 0xff
257
258 /** A DHCP options block */
259 struct dhcp_option_block {
260         /** List of option blocks */
261         struct list_head list;
262         /** Option block raw data */
263         void *data;
264         /** Option block length */
265         size_t len;
266         /** Option block maximum length */
267         size_t max_len;
268         /** Block priority
269          *
270          * This is determined at the time of the call to
271          * register_options() by searching for the @c DHCP_EB_PRIORITY
272          * option.
273          */
274         signed int priority;
275 };
276
277 extern unsigned long dhcp_num_option ( struct dhcp_option *option );
278 extern struct dhcp_option *
279 find_dhcp_option ( struct dhcp_option_block *options, unsigned int tag );
280 extern struct dhcp_option * find_global_dhcp_option ( unsigned int tag );
281 extern void register_dhcp_options ( struct dhcp_option_block *options );
282 extern void unregister_dhcp_options ( struct dhcp_option_block *options );
283 extern void init_dhcp_options ( struct dhcp_option_block *options,
284                                 void *data, size_t max_len );
285 extern struct dhcp_option_block * alloc_dhcp_options ( size_t max_len );
286 extern void free_dhcp_options ( struct dhcp_option_block *options );
287 extern struct dhcp_option *
288 set_dhcp_option ( struct dhcp_option_block *options, unsigned int tag,
289                   const void *data, size_t len );
290
291 /**
292  * Find DHCP numerical option, and return its value
293  *
294  * @v options           DHCP options block
295  * @v tag               DHCP option tag to search for
296  * @ret value           Numerical value of the option, or 0 if not found
297  *
298  * This function exists merely as a notational shorthand for a call to
299  * find_dhcp_option() followed by a call to dhcp_num_option().  It is
300  * not possible to distinguish between the cases "option not found"
301  * and "option has a value of zero" using this function; if this
302  * matters to you then issue the two constituent calls directly and
303  * check that find_dhcp_option() returns a non-NULL value.
304  */
305 static inline unsigned long
306 find_dhcp_num_option ( struct dhcp_option_block *options, unsigned int tag ) {
307         return dhcp_num_option ( find_dhcp_option ( options, tag ) );
308 }
309
310 /**
311  * Find DHCP numerical option, and return its value
312  *
313  * @v tag               DHCP option tag to search for
314  * @ret value           Numerical value of the option, or 0 if not found
315  *
316  * This function exists merely as a notational shorthand for a call to
317  * find_global_dhcp_option() followed by a call to dhcp_num_option().
318  * It is not possible to distinguish between the cases "option not
319  * found" and "option has a value of zero" using this function; if
320  * this matters to you then issue the two constituent calls directly
321  * and check that find_global_dhcp_option() returns a non-NULL value.
322  */
323 static inline unsigned long
324 find_global_dhcp_num_option ( unsigned int tag ) {
325         return dhcp_num_option ( find_global_dhcp_option ( tag ) );
326 }
327
328 /**
329  * Delete DHCP option
330  *
331  * @v options           DHCP options block
332  * @v tag               DHCP option tag
333  */
334 static inline void delete_dhcp_option ( struct dhcp_option_block *options,
335                                         unsigned int tag ) {
336         set_dhcp_option ( options, tag, NULL, 0 );
337 }
338
339 #endif /* _GPXE_DHCP_H */