]>
Commit | Line | Data |
---|---|---|
064af421 BP |
1 | /* |
2 | * Copyright (c) 2008 Nicira Networks. | |
3 | * | |
a14bc59f BP |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. | |
6 | * You may obtain a copy of the License at: | |
064af421 | 7 | * |
a14bc59f BP |
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | * | |
10 | * Unless required by applicable law or agreed to in writing, software | |
11 | * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | * See the License for the specific language governing permissions and | |
14 | * limitations under the License. | |
064af421 BP |
15 | */ |
16 | ||
17 | #ifndef DHCP_H | |
18 | #define DHCP_H 1 | |
19 | ||
20 | #include <stdint.h> | |
21 | #include "packets.h" | |
22 | #include "util.h" | |
23 | ||
24 | struct ds; | |
25 | struct ofpbuf; | |
26 | ||
27 | /* Values for 'op' field. */ | |
28 | #define DHCP_BOOTREQUEST 1 /* Message sent by DHCP client. */ | |
29 | #define DHCP_BOOTREPLY 2 /* Message sent by DHCP server. */ | |
30 | ||
31 | /* Bits in 'flags' field. */ | |
32 | #define DHCP_FLAGS_BROADCAST 0x8000 /* Server must broadcast all replies. */ | |
33 | #define DHCP_FLAGS_MBZ 0x7fff /* Must be zero. */ | |
34 | ||
35 | /* First four bytes of 'options' field. */ | |
36 | #define DHCP_OPTS_COOKIE 0x63825363 | |
37 | ||
38 | #define DHCP_HEADER_LEN 236 | |
39 | struct dhcp_header { | |
40 | uint8_t op; /* DHCP_BOOTREQUEST or DHCP_BOOTREPLY. */ | |
41 | uint8_t htype; /* ARP_HRD_ETHERNET (typically). */ | |
42 | uint8_t hlen; /* ETH_ADDR_LEN (typically). */ | |
43 | uint8_t hops; /* Hop count; set to 0 by client. */ | |
44 | uint32_t xid; /* Transaction ID. */ | |
45 | uint16_t secs; /* Since client started address acquisition. */ | |
46 | uint16_t flags; /* DHCP_FLAGS_*. */ | |
47 | uint32_t ciaddr; /* Client IP, if it has a lease for one. */ | |
48 | uint32_t yiaddr; /* Client ("your") IP address. */ | |
49 | uint32_t siaddr; /* Next server IP address. */ | |
50 | uint32_t giaddr; /* Relay agent IP address. */ | |
51 | uint8_t chaddr[16]; /* Client hardware address. */ | |
52 | char sname[64]; /* Optional server host name. */ | |
53 | char file[128]; /* Boot file name. */ | |
54 | /* Followed by variable-length options field. */ | |
55 | }; | |
56 | BUILD_ASSERT_DECL(DHCP_HEADER_LEN == sizeof(struct dhcp_header)); | |
57 | ||
58 | #define DHCP_ARGS \ | |
59 | DHCP_ARG(FIXED, 0) /* Fixed-length option (PAD and END only). */ \ | |
60 | DHCP_ARG(IP, 4) /* IP addresses. */ \ | |
61 | DHCP_ARG(SECS, 4) /* 32-bit duration in seconds. */ \ | |
62 | DHCP_ARG(STRING, 1) /* NVT string, optionally null-terminated. */ \ | |
63 | DHCP_ARG(UINT8, 1) /* 8-bit unsigned integer. */ \ | |
64 | DHCP_ARG(UINT16, 2) /* 16-bit unsigned integer. */ \ | |
65 | DHCP_ARG(UINT32, 4) /* 32-bit unsigned integer. */ \ | |
66 | DHCP_ARG(BOOLEAN, 1) /* Boolean octet (0 or 1). */ | |
67 | ||
68 | /* DHCP option argument types. */ | |
69 | enum dhcp_arg_type { | |
70 | #define DHCP_ARG(NAME, SIZE) DHCP_ARG_##NAME, | |
71 | DHCP_ARGS | |
72 | #undef DHCP_ARG | |
73 | }; | |
74 | ||
75 | #define DHCP_MSGS \ | |
76 | DHCP_MSG(DHCPDISCOVER, 1) /* Client->server: What IPs are available? */ \ | |
77 | DHCP_MSG(DHCPOFFER, 2) /* Server->client: This IP is available. */ \ | |
78 | DHCP_MSG(DHCPREQUEST, 3) /* Client->server: I want that IP. */ \ | |
79 | DHCP_MSG(DHCPDECLINE, 4) /* Client->server: That IP is in use!. */ \ | |
80 | DHCP_MSG(DHCPACK, 5) /* Server->client: You can have that IP. */ \ | |
81 | DHCP_MSG(DHCPNAK, 6) /* Server->client: You can't have that IP. */ \ | |
82 | DHCP_MSG(DHCPRELEASE, 7) /* Client->server: I'm done with this IP. */ \ | |
83 | DHCP_MSG(DCHPINFORM, 8) /* Client->server: I'm using this IP. */ | |
84 | ||
85 | /* DHCP message type (this is the argument for the DHCP_MSG_TYPE option). */ | |
86 | enum dhcp_msg_type { | |
87 | #define DHCP_MSG(NAME, VALUE) NAME = VALUE, | |
88 | DHCP_MSGS | |
89 | #undef DHCP_MSG | |
90 | }; | |
91 | const char *dhcp_type_name(enum dhcp_msg_type); | |
92 | ||
93 | /* DHCP allows for 256 standardized options and 256 vendor-specific options. | |
94 | * We put them in a single array, with the standard options at the | |
95 | * beginning. */ | |
96 | #define DHCP_N_OPTIONS 512 | |
97 | #define DHCP_VENDOR_OFS 256 | |
98 | ||
99 | /* DHCP options. */ | |
100 | #define DHCP_OPTS \ | |
101 | /* arg min max */ \ | |
102 | /* name code type args args */ \ | |
103 | DHCP_OPT(PAD, 0, FIXED, 0, 0) \ | |
104 | DHCP_OPT(END, 255, FIXED, 0, 0) \ | |
105 | DHCP_OPT(SUBNET_MASK, 1, IP, 1, 1) \ | |
106 | DHCP_OPT(TIME_OFFSET, 2, SECS, 1, 1) \ | |
107 | DHCP_OPT(ROUTER, 3, IP, 1, SIZE_MAX) \ | |
108 | /* Time Server Option is obsolete. */ \ | |
109 | /* Name Server Option is obsolete. */ \ | |
110 | DHCP_OPT(DNS_SERVER, 6, IP, 1, SIZE_MAX) \ | |
111 | /* Log Server Option is obsolete. */ \ | |
112 | /* Cookie Server Option is obsolete. */ \ | |
113 | DHCP_OPT(LPR_SERVER, 9, IP, 1, SIZE_MAX) \ | |
114 | /* Impress Server Option is obsolete. */ \ | |
115 | /* Resource Location Server Option is obsolete. */ \ | |
116 | DHCP_OPT(HOST_NAME, 12, STRING, 1, SIZE_MAX) \ | |
117 | DHCP_OPT(BOOT_FILE_SIZE, 13, UINT16, 1, 1) \ | |
118 | /* Merit Dump File option is obsolete. */ \ | |
119 | DHCP_OPT(DOMAIN_NAME, 15, STRING, 1, SIZE_MAX) \ | |
120 | /* Swap Server option is obsolete. */ \ | |
121 | DHCP_OPT(ROOT_PATH, 17, STRING, 1, SIZE_MAX) \ | |
122 | DHCP_OPT(EXTENSIONS_PATH, 18, STRING, 1, SIZE_MAX) \ | |
123 | DHCP_OPT(IP_FORWARDING, 19, BOOLEAN, 1, 1) \ | |
124 | DHCP_OPT(SOURCE_ROUTING, 20, BOOLEAN, 1, 1) \ | |
125 | DHCP_OPT(POLICY_FILTER, 21, IP, 2, SIZE_MAX) \ | |
126 | DHCP_OPT(MAX_DGRAM_REASSEMBLY, 22, UINT16, 1, 1) \ | |
127 | DHCP_OPT(IP_TTL, 23, UINT8, 1, 1) \ | |
128 | DHCP_OPT(PATH_MTU_TIMEOUT, 24, SECS, 1, 1) \ | |
129 | DHCP_OPT(PATH_MTU_PLATEAU, 25, UINT16, 2, SIZE_MAX) \ | |
130 | DHCP_OPT(MTU, 26, UINT16, 1, 1) \ | |
131 | DHCP_OPT(ALL_SUBNETS_ARE_LOCAL, 27, BOOLEAN, 1, 1) \ | |
132 | DHCP_OPT(BROADCAST_ADDRESS, 28, IP, 1, 1) \ | |
133 | DHCP_OPT(PERFORM_MASK_DISCOVERY, 29, BOOLEAN, 1, 1) \ | |
134 | DHCP_OPT(MASK_SUPPLIER, 30, BOOLEAN, 1, 1) \ | |
135 | DHCP_OPT(PERFORM_ROUTER_DISCOVERY, 31, BOOLEAN, 1, 1) \ | |
136 | DHCP_OPT(ROUTER_SOLICITATION, 32, IP, 1, 1) \ | |
137 | DHCP_OPT(STATIC_ROUTE, 33, IP, 2, SIZE_MAX) \ | |
138 | /* Trailer Encapsulation Option is obsolete. */ \ | |
139 | DHCP_OPT(ARP_CACHE_TIMEOUT, 35, SECS, 1, 1) \ | |
140 | DHCP_OPT(ETHERNET_ENCAPSULATION, 36, BOOLEAN, 1, 1) \ | |
141 | DHCP_OPT(TCP_TTL, 37, UINT8, 1, 1) \ | |
142 | DHCP_OPT(TCP_KEEPALIVE_INTERVAL, 38, SECS, 1, 1) \ | |
143 | DHCP_OPT(TCP_KEEPALIVE_GARBAGE, 39, BOOLEAN, 1, 1) \ | |
144 | DHCP_OPT(NIS_DOMAIN, 40, STRING, 1, SIZE_MAX) \ | |
145 | DHCP_OPT(NIS_SERVERS, 41, IP, 1, SIZE_MAX) \ | |
146 | DHCP_OPT(NTP_SERVERS, 42, IP, 1, SIZE_MAX) \ | |
147 | DHCP_OPT(VENDOR_SPECIFIC, 43, UINT8, 1, SIZE_MAX) \ | |
148 | DHCP_OPT(NETBIOS_NS, 44, IP, 1, SIZE_MAX) \ | |
149 | DHCP_OPT(NETBIOS_DDS, 45, IP, 1, SIZE_MAX) \ | |
150 | DHCP_OPT(NETBIOS_NODE_TYPE, 46, UINT8, 1, 1) \ | |
151 | DHCP_OPT(NETBIOS_SCOPE, 47, STRING, 1, SIZE_MAX) \ | |
152 | DHCP_OPT(X_FONT_SERVER, 48, IP, 1, SIZE_MAX) \ | |
153 | DHCP_OPT(XDM, 49, IP, 1, SIZE_MAX) \ | |
154 | DHCP_OPT(NISPLUS_DOMAIN, 64, STRING, 1, SIZE_MAX) \ | |
155 | DHCP_OPT(NISPLUS_SERVERS, 65, IP, 1, SIZE_MAX) \ | |
156 | DHCP_OPT(MOBILE_IP_HOME_AGENT, 68, IP, 0, SIZE_MAX) \ | |
157 | DHCP_OPT(SMTP_SERVER, 69, IP, 1, SIZE_MAX) \ | |
158 | DHCP_OPT(POP3_SERVER, 70, IP, 1, SIZE_MAX) \ | |
159 | DHCP_OPT(NNTP_SERVER, 71, IP, 1, SIZE_MAX) \ | |
160 | DHCP_OPT(WWW_SERVER, 72, IP, 1, SIZE_MAX) \ | |
161 | DHCP_OPT(FINGER_SERVER, 73, IP, 1, SIZE_MAX) \ | |
162 | DHCP_OPT(IRC_SERVER, 74, IP, 1, SIZE_MAX) \ | |
163 | /* StreetTalk Server Option is obsolete. */ \ | |
164 | /* StreetTalk Directory Assistance Server Option is obsolete. */ \ | |
165 | DHCP_OPT(REQUESTED_IP, 50, IP, 1, 1) \ | |
166 | DHCP_OPT(LEASE_TIME, 51, SECS, 1, 1) \ | |
167 | DHCP_OPT(OPTION_OVERLOAD, 52, UINT8, 1, 1) \ | |
168 | DHCP_OPT(TFTP_SERVER, 66, STRING, 1, SIZE_MAX) \ | |
169 | DHCP_OPT(BOOTFILE_NAME, 67, STRING, 1, SIZE_MAX) \ | |
170 | DHCP_OPT(DHCP_MSG_TYPE, 53, UINT8, 1, 1) \ | |
171 | DHCP_OPT(SERVER_IDENTIFIER, 54, IP, 1, 1) \ | |
172 | DHCP_OPT(PARAMETER_REQUEST_LIST, 55, UINT8, 1, SIZE_MAX) \ | |
173 | DHCP_OPT(MESSAGE, 56, STRING, 1, SIZE_MAX) \ | |
174 | DHCP_OPT(MAX_DHCP_MSG_SIZE, 57, UINT16, 1, 1) \ | |
175 | DHCP_OPT(T1, 58, SECS, 1, 1) \ | |
176 | DHCP_OPT(T2, 59, SECS, 1, 1) \ | |
177 | DHCP_OPT(VENDOR_CLASS, 60, STRING, 1, SIZE_MAX) \ | |
178 | DHCP_OPT(CLIENT_ID, 61, UINT8, 2, SIZE_MAX) \ | |
179 | DHCP_VNDOPT(OFP_CONTROLLER_VCONN, 1, STRING, 1, SIZE_MAX) \ | |
180 | DHCP_VNDOPT(OFP_PKI_URI, 2, STRING, 1, SIZE_MAX) | |
181 | ||
182 | /* Shorthand for defining vendor options (used above). */ | |
183 | #define DHCP_VNDOPT(NAME, CODE, ARG, MIN, MAX) \ | |
184 | DHCP_OPT(NAME, (CODE) + DHCP_VENDOR_OFS, ARG, MIN, MAX) | |
185 | ||
186 | /* DHCP option codes. */ | |
187 | enum { | |
188 | #define DHCP_OPT(NAME, VALUE, ARGTYPE, MIN_ARGS, MAX_ARGS) \ | |
189 | DHCP_CODE_##NAME = VALUE, | |
190 | DHCP_OPTS | |
191 | #undef DHCP_OPT | |
192 | }; | |
193 | ||
194 | /* The contents of a DHCP option. | |
195 | * | |
196 | * DHCP options can (rarely) be present but lack content. To represent such an | |
197 | * option, 'n' is 0 and 'data' is non-null (but does not point to anything | |
198 | * useful). */ | |
199 | struct dhcp_option { | |
200 | size_t n; /* Number of bytes of data. */ | |
201 | void *data; /* Data. */ | |
202 | }; | |
203 | ||
204 | const char *dhcp_option_to_string(const struct dhcp_option *, int code, | |
205 | struct ds *); | |
206 | bool dhcp_option_equals(const struct dhcp_option *, | |
207 | const struct dhcp_option *); | |
208 | ||
209 | /* Abstracted DHCP protocol message, to make them easier to manipulate than | |
210 | * through raw protocol buffers. */ | |
211 | struct dhcp_msg { | |
212 | /* For use by calling code. */ | |
213 | uint8_t op; /* DHCP_BOOTREQUEST or DHCP_BOOTREPLY. */ | |
214 | uint32_t xid; /* Transaction ID. */ | |
215 | uint16_t secs; /* Since client started address acquisition. */ | |
216 | uint16_t flags; /* DHCP_FLAGS_*. */ | |
217 | uint32_t ciaddr; /* Client IP, if it has a lease for one. */ | |
218 | uint32_t yiaddr; /* Client ("your") IP address. */ | |
219 | uint32_t siaddr; /* Next server IP address. */ | |
220 | uint32_t giaddr; /* Relay agent IP address. */ | |
221 | uint8_t chaddr[ETH_ADDR_LEN]; /* Client hardware address. */ | |
222 | enum dhcp_msg_type type; /* DHCP_CODE_DHCP_MSG_TYPE option argument. */ | |
223 | struct dhcp_option options[DHCP_N_OPTIONS]; /* Indexed by option code. */ | |
224 | ||
225 | /* For direct use only by dhcp_msg_*() functions. */ | |
226 | uint8_t *data; | |
227 | size_t data_used, data_allocated; | |
228 | }; | |
229 | ||
230 | void dhcp_msg_init(struct dhcp_msg *); | |
231 | void dhcp_msg_uninit(struct dhcp_msg *); | |
232 | void dhcp_msg_copy(struct dhcp_msg *, const struct dhcp_msg *); | |
233 | void dhcp_msg_put(struct dhcp_msg *, int code, const void *, size_t); | |
234 | void dhcp_msg_put_bool(struct dhcp_msg *, int code, bool); | |
235 | void dhcp_msg_put_secs(struct dhcp_msg *, int code, uint32_t); | |
236 | void dhcp_msg_put_ip(struct dhcp_msg *, int code, uint32_t); | |
237 | void dhcp_msg_put_string(struct dhcp_msg *, int code, const char *); | |
238 | void dhcp_msg_put_uint8(struct dhcp_msg *, int code, uint8_t); | |
239 | void dhcp_msg_put_uint8_array(struct dhcp_msg *, int code, | |
240 | const uint8_t[], size_t n); | |
241 | void dhcp_msg_put_uint16(struct dhcp_msg *, int code, uint16_t); | |
242 | void dhcp_msg_put_uint16_array(struct dhcp_msg *, int code, | |
243 | const uint16_t[], size_t n); | |
244 | const void *dhcp_msg_get(const struct dhcp_msg *, int code, size_t offset, | |
245 | size_t size); | |
246 | bool dhcp_msg_get_bool(const struct dhcp_msg *, int code, | |
247 | size_t offset, bool *); | |
248 | bool dhcp_msg_get_secs(const struct dhcp_msg *, int code, | |
249 | size_t offset, uint32_t *); | |
250 | bool dhcp_msg_get_ip(const struct dhcp_msg *, int code, | |
251 | size_t offset, uint32_t *); | |
252 | char *dhcp_msg_get_string(const struct dhcp_msg *, int code); | |
253 | bool dhcp_msg_get_uint8(const struct dhcp_msg *, int code, | |
254 | size_t offset, uint8_t *); | |
255 | bool dhcp_msg_get_uint16(const struct dhcp_msg *, int code, | |
256 | size_t offset, uint16_t *); | |
257 | const char *dhcp_msg_to_string(const struct dhcp_msg *, bool multiline, | |
258 | struct ds *); | |
259 | int dhcp_parse(struct dhcp_msg *, const struct ofpbuf *); | |
260 | void dhcp_assemble(const struct dhcp_msg *, struct ofpbuf *); | |
261 | ||
262 | #endif /* dhcp.h */ |