Added macros for generating static DHCP options
[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 #include <gpxe/udp.h>
14
15 /** Construct a tag value for an encapsulated option
16  *
17  * This tag value can be passed to Etherboot functions when searching
18  * for DHCP options in order to search for a tag within an
19  * encapsulated options block.
20  */
21 #define DHCP_ENCAP_OPT( encapsulator, encapsulated ) \
22         ( ( (encapsulator) << 8 ) | (encapsulated) )
23 /** Extract encapsulating option block tag from encapsulated tag value */
24 #define DHCP_ENCAPSULATOR( encap_opt ) ( (encap_opt) >> 8 )
25 /** Extract encapsulated option tag from encapsulated tag value */
26 #define DHCP_ENCAPSULATED( encap_opt ) ( (encap_opt) & 0xff )
27 /** Option is encapsulated */
28 #define DHCP_IS_ENCAP_OPT( opt ) DHCP_ENCAPSULATOR( opt )
29
30 /**
31  * @defgroup dhcpopts DHCP option tags
32  * @{
33  */
34
35 /** Padding
36  *
37  * This tag does not have a length field; it is always only a single
38  * byte in length.
39  */
40 #define DHCP_PAD 0
41
42 /** Minimum normal DHCP option */
43 #define DHCP_MIN_OPTION 1
44
45 /** Vendor encapsulated options */
46 #define DHCP_VENDOR_ENCAP 43
47
48 /** Option overloading
49  *
50  * The value of this option is the bitwise-OR of zero or more
51  * DHCP_OPTION_OVERLOAD_XXX constants.
52  */
53 #define DHCP_OPTION_OVERLOAD 52
54
55 /** The "file" field is overloaded to contain extra DHCP options */
56 #define DHCP_OPTION_OVERLOAD_FILE 1
57
58 /** The "sname" field is overloaded to contain extra DHCP options */
59 #define DHCP_OPTION_OVERLOAD_SNAME 2
60
61 /** DHCP message type */
62 #define DHCP_MESSAGE_TYPE 53
63 #define DHCPDISCOVER 1
64 #define DHCPOFFER 2
65 #define DHCPREQUEST 3
66 #define DHCPDECLINE 4
67 #define DHCPACK 5
68 #define DHCPNAK 6
69 #define DHCPRELEASE 7
70 #define DHCPINFORM 8
71
72 /** TFTP server name
73  *
74  * This option replaces the fixed "sname" field, when that field is
75  * used to contain overloaded options.
76  */
77 #define DHCP_TFTP_SERVER_NAME 66
78
79 /** Bootfile name
80  *
81  * This option replaces the fixed "file" field, when that field is
82  * used to contain overloaded options.
83  */
84 #define DHCP_BOOTFILE_NAME 67
85
86 /** Etherboot-specific encapsulated options
87  *
88  * This encapsulated options field is used to contain all options
89  * specific to Etherboot (i.e. not assigned by IANA or other standards
90  * bodies).
91  */
92 #define DHCP_EB_ENCAP 175
93
94 /** Priority of this options block
95  *
96  * This is a signed 8-bit integer field indicating the priority of
97  * this block of options.  It can be used to specify the relative
98  * priority of multiple option blocks (e.g. options from non-volatile
99  * storage versus options from a DHCP server).
100  */
101 #define DHCP_EB_PRIORITY DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 1 )
102
103 /** "Your" IP address
104  *
105  * This option is used internally to contain the value of the "yiaddr"
106  * field, in order to provide a consistent approach to storing and
107  * processing options.  It should never be present in a DHCP packet.
108  */
109 #define DHCP_EB_YIADDR DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 2 )
110
111 /** "Server" IP address
112  *
113  * This option is used internally to contain the value of the "siaddr"
114  * field, in order to provide a consistent approach to storing and
115  * processing options.  It should never be present in a DHCP packet.
116  */
117 #define DHCP_EB_SIADDR DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 3 )
118
119 /** Maximum normal DHCP option */
120 #define DHCP_MAX_OPTION 254
121
122 /** End of options
123  *
124  * This tag does not have a length field; it is always only a single
125  * byte in length.
126  */
127 #define DHCP_END 255
128
129 /** @} */
130
131 /**
132  * Count number of arguments to a variadic macro
133  *
134  * This rather neat, non-iterative solution is courtesy of Laurent
135  * Deniau.
136  *
137  */
138 #define _VA_ARG_COUNT(  _1,  _2,  _3,  _4,  _5,  _6,  _7,  _8,          \
139                         _9, _10, _11, _12, _13, _14, _15, _16,          \
140                        _17, _18, _19, _20, _21, _22, _23, _24,          \
141                        _25, _26, _27, _28, _29, _30, _31, _32,          \
142                        _33, _34, _35, _36, _37, _38, _39, _40,          \
143                        _41, _42, _43, _44, _45, _46, _47, _48,          \
144                        _49, _50, _51, _52, _53, _54, _55, _56,          \
145                        _57, _58, _59, _60, _61, _62, _63,   N, ... ) N
146 #define VA_ARG_COUNT( ... )                                             \
147         _VA_ARG_COUNT ( __VA_ARGS__,                                    \
148                         63, 62, 61, 60, 59, 58, 57, 56,                 \
149                         55, 54, 53, 52, 51, 50, 49, 48,                 \
150                         47, 46, 45, 44, 43, 42, 41, 40,                 \
151                         39, 38, 37, 36, 35, 34, 33, 32,                 \
152                         31, 30, 29, 28, 27, 26, 25, 24,                 \
153                         23, 22, 21, 20, 19, 18, 17, 16,                 \
154                         15, 14, 13, 12, 11, 10,  9,  8,                 \
155                          7,  6,  5,  4,  3,  2,  1,  0 )
156
157 /** Construct a DHCP option from a list of bytes */
158 #define DHCP_OPTION( ... ) VA_ARG_COUNT ( __VA_ARGS__ ), __VA_ARGS__
159
160 /** Construct a DHCP option from a list of characters */
161 #define DHCP_STRING( ... ) DHCP_OPTION ( __VA_ARGS__ )
162
163 /** Construct a byte-valued DHCP option */
164 #define DHCP_BYTE( value ) DHCP_OPTION ( value )
165
166 /** Construct a word-valued DHCP option */
167 #define DHCP_WORD( value ) DHCP_OPTION ( ( ( (value) >> 8 ) & 0xff ),   \
168                                          ( ( (value) >> 0  ) & 0xff ) )
169
170 /** Construct a dword-valued DHCP option */
171 #define DHCP_DWORD( value ) DHCP_OPTION ( ( ( (value) >> 24 ) & 0xff ), \
172                                           ( ( (value) >> 16 ) & 0xff ), \
173                                           ( ( (value) >> 8  ) & 0xff ), \
174                                           ( ( (value) >> 0  ) & 0xff ) )
175
176 /** Construct a DHCP encapsulated options field */
177 #define DHCP_ENCAP( ... ) DHCP_OPTION ( __VA_ARGS__, DHCP_END )
178
179 /**
180  * A DHCP option
181  *
182  * DHCP options consist of a mandatory tag, a length field that is
183  * mandatory for all options except @c DHCP_PAD and @c DHCP_END, and a
184  * payload.  
185  */
186 struct dhcp_option {
187         /** Tag
188          *
189          * Must be a @c DHCP_XXX value.
190          */
191         uint8_t tag;
192         /** Length
193          *
194          * This is the length of the data field (i.e. excluding the
195          * tag and length fields).  For the two tags @c DHCP_PAD and
196          * @c DHCP_END, the length field is implicitly zero and is
197          * also missing, i.e. these DHCP options are only a single
198          * byte in length.
199          */
200         uint8_t len;
201         /** Option data
202          *
203          * Interpretation of the content is entirely dependent upon
204          * the tag.  For fields containing a multi-byte integer, the
205          * field is defined to be in network-endian order (unless you
206          * are Intel and feel like violating the spec for fun).
207          */
208         union {
209                 uint8_t byte;
210                 uint16_t word;
211                 uint32_t dword;
212                 uint8_t bytes[0];
213         } data;
214 } __attribute__ (( packed ));
215
216 /**
217  * Length of a DHCP option header
218  *
219  * The header is the portion excluding the data, i.e. the tag and the
220  * length.
221  */
222 #define DHCP_OPTION_HEADER_LEN ( offsetof ( struct dhcp_option, data ) )
223
224 /** Maximum length for a single DHCP option */
225 #define DHCP_MAX_LEN 0xff
226
227 /** A DHCP options block */
228 struct dhcp_option_block {
229         /** List of option blocks */
230         struct list_head list;
231         /** Option block raw data */
232         void *data;
233         /** Option block length */
234         size_t len;
235         /** Option block maximum length */
236         size_t max_len;
237         /** Block priority
238          *
239          * This is determined at the time of the call to
240          * register_options() by searching for the @c DHCP_EB_PRIORITY
241          * option.
242          */
243         signed int priority;
244 };
245
246 /**
247  * A DHCP header
248  *
249  */
250 struct dhcphdr {
251         /** Operation
252          *
253          * This must be either @c BOOTP_REQUEST or @c BOOTP_REPLY.
254          */
255         uint8_t op;
256         /** Hardware address type
257          *
258          * This is an ARPHRD_XXX constant.  Note that ARPHRD_XXX
259          * constants are nominally 16 bits wide; this could be
260          * considered to be a bug in the BOOTP/DHCP specification.
261          */
262         uint8_t htype;
263         /** Hardware address length */
264         uint8_t hlen;
265         /** Number of hops from server */
266         uint8_t hops;
267         /** Transaction ID */
268         uint32_t xid;
269         /** Seconds since start of acquisition */
270         uint16_t secs;
271         /** Flags */
272         uint16_t flags;
273         /** "Client" IP address
274          *
275          * This is filled in if the client already has an IP address
276          * assigned and can respond to ARP requests.
277          */
278         struct in_addr ciaddr;
279         /** "Your" IP address
280          *
281          * This is the IP address assigned by the server to the client.
282          */
283         struct in_addr yiaddr;
284         /** "Server" IP address
285          *
286          * This is the IP address of the next server to be used in the
287          * boot process.
288          */
289         struct in_addr siaddr;
290         /** "Gateway" IP address
291          *
292          * This is the IP address of the DHCP relay agent, if any.
293          */
294         struct in_addr giaddr;
295         /** Client hardware address */
296         uint8_t chaddr[16];
297         /** Server host name (null terminated)
298          *
299          * This field may be overridden and contain DHCP options
300          */
301         uint8_t sname[64];
302         /** Boot file name (null terminated)
303          *
304          * This field may be overridden and contain DHCP options
305          */
306         uint8_t file[128];
307         /** DHCP magic cookie
308          *
309          * Must have the value @c DHCP_MAGIC_COOKIE.
310          */
311         uint32_t magic;
312         /** DHCP options
313          *
314          * Variable length; extends to the end of the packet.
315          */
316         uint8_t options[0];
317 };
318
319 /** Opcode for a request from client to server */
320 #define BOOTP_REQUEST 1
321
322 /** Opcode for a reply from server to client */
323 #define BOOTP_REPLY 2
324
325 /** DHCP magic cookie */
326 #define DHCP_MAGIC_COOKIE 0x63825363UL
327
328 /** DHCP packet option block fill order
329  *
330  * This is the order in which option blocks are filled when
331  * reassembling a DHCP packet.  We fill the smallest field ("sname")
332  * first, to maximise the chances of being able to fit large options
333  * within fields which are large enough to contain them.
334  */
335 enum dhcp_packet_option_block_fill_order {
336         OPTS_SNAME = 0,
337         OPTS_FILE,
338         OPTS_MAIN,
339         NUM_OPT_BLOCKS
340 };
341
342 /**
343  * A DHCP packet
344  *
345  */
346 struct dhcp_packet {
347         /** The DHCP packet contents */
348         struct dhcphdr *dhcphdr;
349         /** Maximum length of the DHCP packet buffer */
350         size_t max_len;
351         /** Used length of the DHCP packet buffer */
352         size_t len;
353         /** DHCP option blocks within a DHCP packet
354          *
355          * A DHCP packet contains three fields which can be used to
356          * contain options: the actual "options" field plus the "file"
357          * and "sname" fields (which can be overloaded to contain
358          * options).
359          */
360         struct dhcp_option_block options[NUM_OPT_BLOCKS];
361 };
362
363 /** A DHCP session */
364 struct dhcp_session {
365         /** UDP connection for this session */
366         struct udp_connection udp;
367
368         /** State of the session
369          *
370          * This is a value for the @c DHCP_MESSAGE_TYPE option
371          * (e.g. @c DHCPDISCOVER).
372          */
373         int state;
374         
375         /** Network device being configured */
376         struct net_device *netdev;
377         /** Transaction ID, in network-endian order */
378         uint32_t xid;
379 };
380
381 extern const struct dhcp_option_block dhcp_request_options;
382 extern unsigned long dhcp_num_option ( struct dhcp_option *option );
383 extern struct dhcp_option *
384 find_dhcp_option ( struct dhcp_option_block *options, unsigned int tag );
385 extern void register_dhcp_options ( struct dhcp_option_block *options );
386 extern void unregister_dhcp_options ( struct dhcp_option_block *options );
387 extern void init_dhcp_options ( struct dhcp_option_block *options,
388                                 void *data, size_t max_len );
389 extern struct dhcp_option_block * alloc_dhcp_options ( size_t max_len );
390 extern void free_dhcp_options ( struct dhcp_option_block *options );
391 extern struct dhcp_option *
392 set_dhcp_option ( struct dhcp_option_block *options, unsigned int tag,
393                   const void *data, size_t len );
394 extern struct dhcp_option * find_global_dhcp_option ( unsigned int tag );
395 extern unsigned long find_dhcp_num_option ( struct dhcp_option_block *options,
396                                             unsigned int tag );
397 extern unsigned long find_global_dhcp_num_option ( unsigned int tag );
398 extern void delete_dhcp_option ( struct dhcp_option_block *options,
399                                  unsigned int tag );
400
401 #endif /* _GPXE_DHCP_H */