9442f857917d215e2edaab20dec27e092a96130b
[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 /** Option overloading
122  *
123  * The value of this option is the bitwise-OR of zero or more
124  * DHCP_OPTION_OVERLOAD_XXX constants.
125  */
126 #define DHCP_OPTION_OVERLOAD 52
127
128 /** The "file" field is overloaded to contain extra DHCP options */
129 #define DHCP_OPTION_OVERLOAD_FILE 1
130
131 /** The "sname" field is overloaded to contain extra DHCP options */
132 #define DHCP_OPTION_OVERLOAD_SNAME 2
133
134 /** TFTP server name
135  *
136  * This option replaces the fixed "sname" field, when that field is
137  * used to contain overloaded options.
138  */
139 #define DHCP_TFTP_SERVER_NAME 66
140
141 /** Bootfile name
142  *
143  * This option replaces the fixed "file" field, when that field is
144  * used to contain overloaded options.
145  */
146 #define DHCP_BOOTFILE_NAME 67
147
148 /** Etherboot-specific encapsulated options
149  *
150  * This encapsulated options field is used to contain all options
151  * specific to Etherboot (i.e. not assigned by IANA or other standards
152  * bodies).
153  */
154 #define DHCP_EB_ENCAP 175
155
156 /** Priority of this options block
157  *
158  * This is a signed 8-bit integer field indicating the priority of
159  * this block of options.  It can be used to specify the relative
160  * priority of multiple option blocks (e.g. options from non-volatile
161  * storage versus options from a DHCP server).
162  */
163 #define DHCP_EB_PRIORITY DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 1 )
164
165 /** "Your" IP address
166  *
167  * This option is used internally to contain the value of the "yiaddr"
168  * field, in order to provide a consistent approach to storing and
169  * processing options.  It should never be present in a DHCP packet.
170  */
171 #define DHCP_EB_YIADDR DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 2 )
172
173 /** "Server" IP address
174  *
175  * This option is used internally to contain the value of the "siaddr"
176  * field, in order to provide a consistent approach to storing and
177  * processing options.  It should never be present in a DHCP packet.
178  */
179 #define DHCP_EB_SIADDR DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 3 )
180
181 /** End of options
182  *
183  * This tag does not have a length field; it is always only a single
184  * byte in length.
185  */
186 #define DHCP_END 255
187
188 /** @} */
189
190 /**
191  * A DHCP option
192  *
193  * DHCP options consist of a mandatory tag, a length field that is
194  * mandatory for all options except @c DHCP_PAD and @c DHCP_END, and a
195  * payload.  
196  */
197 struct dhcp_option {
198         /** Tag
199          *
200          * Must be a @c DHCP_XXX value.
201          */
202         uint8_t tag;
203         /** Length
204          *
205          * This is the length of the data field (i.e. excluding the
206          * tag and length fields).  For the two tags @c DHCP_PAD and
207          * @c DHCP_END, the length field is implicitly zero and is
208          * also missing, i.e. these DHCP options are only a single
209          * byte in length.
210          */
211         uint8_t len;
212         /** Option data
213          *
214          * Interpretation of the content is entirely dependent upon
215          * the tag.  For fields containing a multi-byte integer, the
216          * field is defined to be in network-endian order (unless you
217          * are Intel and feel like violating the spec for fun).
218          */
219         union {
220                 uint8_t byte;
221                 uint16_t word;
222                 uint32_t dword;
223                 uint8_t bytes[0];
224         } data;
225 } __attribute__ (( packed ));
226
227 /**
228  * Length of a DHCP option header
229  *
230  * The header is the portion excluding the data, i.e. the tag and the
231  * length.
232  */
233 #define DHCP_OPTION_HEADER_LEN ( offsetof ( struct dhcp_option, data ) )
234
235 /** Maximum length for a single DHCP option */
236 #define DHCP_MAX_LEN 0xff
237
238 /** A DHCP options block */
239 struct dhcp_option_block {
240         /** List of option blocks */
241         struct list_head list;
242         /** Option block raw data */
243         void *data;
244         /** Option block length */
245         size_t len;
246         /** Option block maximum length */
247         size_t max_len;
248         /** Block priority
249          *
250          * This is determined at the time of the call to
251          * register_options() by searching for the @c DHCP_EB_PRIORITY
252          * option.
253          */
254         signed int priority;
255 };
256
257 extern unsigned long dhcp_num_option ( struct dhcp_option *option );
258 extern struct dhcp_option *
259 find_dhcp_option ( struct dhcp_option_block *options, unsigned int tag );
260 extern struct dhcp_option * find_global_dhcp_option ( unsigned int tag );
261 extern void register_dhcp_options ( struct dhcp_option_block *options );
262 extern void unregister_dhcp_options ( struct dhcp_option_block *options );
263 extern struct dhcp_option_block * alloc_dhcp_options ( size_t max_len );
264 extern void free_dhcp_options ( struct dhcp_option_block *options );
265 extern struct dhcp_option *
266 set_dhcp_option ( struct dhcp_option_block *options, unsigned int tag,
267                   const void *data, size_t len );
268
269 /**
270  * Find DHCP numerical option, and return its value
271  *
272  * @v options           DHCP options block
273  * @v tag               DHCP option tag to search for
274  * @ret value           Numerical value of the option, or 0 if not found
275  *
276  * This function exists merely as a notational shorthand for a call to
277  * find_dhcp_option() followed by a call to dhcp_num_option().  It is
278  * not possible to distinguish between the cases "option not found"
279  * and "option has a value of zero" using this function; if this
280  * matters to you then issue the two constituent calls directly and
281  * check that find_dhcp_option() returns a non-NULL value.
282  */
283 static inline unsigned long
284 find_dhcp_num_option ( struct dhcp_option_block *options, unsigned int tag ) {
285         return dhcp_num_option ( find_dhcp_option ( options, tag ) );
286 }
287
288 /**
289  * Find DHCP numerical option, and return its value
290  *
291  * @v tag               DHCP option tag to search for
292  * @ret value           Numerical value of the option, or 0 if not found
293  *
294  * This function exists merely as a notational shorthand for a call to
295  * find_global_dhcp_option() followed by a call to dhcp_num_option().
296  * It is not possible to distinguish between the cases "option not
297  * found" and "option has a value of zero" using this function; if
298  * this matters to you then issue the two constituent calls directly
299  * and check that find_global_dhcp_option() returns a non-NULL value.
300  */
301 static inline unsigned long
302 find_global_dhcp_num_option ( unsigned int tag ) {
303         return dhcp_num_option ( find_global_dhcp_option ( tag ) );
304 }
305
306 /**
307  * Delete DHCP option
308  *
309  * @v options           DHCP options block
310  * @v tag               DHCP option tag
311  */
312 static inline void delete_dhcp_option ( struct dhcp_option_block *options,
313                                         unsigned int tag ) {
314         set_dhcp_option ( options, tag, NULL, 0 );
315 }
316
317 #endif /* _GPXE_DHCP_H */