1 | /* |
---|
2 | * dhcpcd - DHCP client daemon |
---|
3 | * Copyright (c) 2006-2014 Roy Marples <roy@marples.name> |
---|
4 | * All rights reserved |
---|
5 | |
---|
6 | * Redistribution and use in source and binary forms, with or without |
---|
7 | * modification, are permitted provided that the following conditions |
---|
8 | * are met: |
---|
9 | * 1. Redistributions of source code must retain the above copyright |
---|
10 | * notice, this list of conditions and the following disclaimer. |
---|
11 | * 2. Redistributions in binary form must reproduce the above copyright |
---|
12 | * notice, this list of conditions and the following disclaimer in the |
---|
13 | * documentation and/or other materials provided with the distribution. |
---|
14 | * |
---|
15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
---|
16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
---|
17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
---|
18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
---|
19 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
---|
20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
---|
21 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
---|
22 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
---|
23 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
---|
24 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
---|
25 | * SUCH DAMAGE. |
---|
26 | */ |
---|
27 | |
---|
28 | #ifndef DHCP_H |
---|
29 | #define DHCP_H |
---|
30 | |
---|
31 | #include <arpa/inet.h> |
---|
32 | #include <netinet/in.h> |
---|
33 | |
---|
34 | #include <limits.h> |
---|
35 | #include <stdint.h> |
---|
36 | |
---|
37 | #include "auth.h" |
---|
38 | #include "dhcp-common.h" |
---|
39 | |
---|
40 | /* UDP port numbers for DHCP */ |
---|
41 | #define DHCP_SERVER_PORT 67 |
---|
42 | #define DHCP_CLIENT_PORT 68 |
---|
43 | |
---|
44 | #define MAGIC_COOKIE 0x63825363 |
---|
45 | #define BROADCAST_FLAG 0x8000 |
---|
46 | |
---|
47 | /* DHCP message OP code */ |
---|
48 | #define DHCP_BOOTREQUEST 1 |
---|
49 | #define DHCP_BOOTREPLY 2 |
---|
50 | |
---|
51 | /* DHCP message type */ |
---|
52 | #define DHCP_DISCOVER 1 |
---|
53 | #define DHCP_OFFER 2 |
---|
54 | #define DHCP_REQUEST 3 |
---|
55 | #define DHCP_DECLINE 4 |
---|
56 | #define DHCP_ACK 5 |
---|
57 | #define DHCP_NAK 6 |
---|
58 | #define DHCP_RELEASE 7 |
---|
59 | #define DHCP_INFORM 8 |
---|
60 | |
---|
61 | /* Constants taken from RFC 2131. */ |
---|
62 | #define T1 0.5 |
---|
63 | #define T2 0.875 |
---|
64 | #define DHCP_BASE 4 |
---|
65 | #define DHCP_MAX 64 |
---|
66 | #define DHCP_RAND_MIN -1 |
---|
67 | #define DHCP_RAND_MAX 1 |
---|
68 | #define DHCP_ARP_FAIL 2 |
---|
69 | |
---|
70 | /* number of usecs in a second. */ |
---|
71 | #define USECS_SECOND 1000000 |
---|
72 | /* As we use timevals, we should use the usec part for |
---|
73 | * greater randomisation. */ |
---|
74 | #define DHCP_RAND_MIN_U DHCP_RAND_MIN * USECS_SECOND |
---|
75 | #define DHCP_RAND_MAX_U DHCP_RAND_MAX * USECS_SECOND |
---|
76 | #define PROBE_MIN_U PROBE_MIN * USECS_SECOND |
---|
77 | #define PROBE_MAX_U PROBE_MAX * USECS_SECOND |
---|
78 | |
---|
79 | /* DHCP options */ |
---|
80 | enum DHO { |
---|
81 | DHO_PAD = 0, |
---|
82 | DHO_SUBNETMASK = 1, |
---|
83 | DHO_ROUTER = 3, |
---|
84 | DHO_DNSSERVER = 6, |
---|
85 | DHO_HOSTNAME = 12, |
---|
86 | DHO_DNSDOMAIN = 15, |
---|
87 | DHO_MTU = 26, |
---|
88 | DHO_BROADCAST = 28, |
---|
89 | DHO_STATICROUTE = 33, |
---|
90 | DHO_NISDOMAIN = 40, |
---|
91 | DHO_NISSERVER = 41, |
---|
92 | DHO_NTPSERVER = 42, |
---|
93 | DHO_VENDOR = 43, |
---|
94 | DHO_IPADDRESS = 50, |
---|
95 | DHO_LEASETIME = 51, |
---|
96 | DHO_OPTIONSOVERLOADED = 52, |
---|
97 | DHO_MESSAGETYPE = 53, |
---|
98 | DHO_SERVERID = 54, |
---|
99 | DHO_PARAMETERREQUESTLIST = 55, |
---|
100 | DHO_MESSAGE = 56, |
---|
101 | DHO_MAXMESSAGESIZE = 57, |
---|
102 | DHO_RENEWALTIME = 58, |
---|
103 | DHO_REBINDTIME = 59, |
---|
104 | DHO_VENDORCLASSID = 60, |
---|
105 | DHO_CLIENTID = 61, |
---|
106 | DHO_USERCLASS = 77, /* RFC 3004 */ |
---|
107 | DHO_RAPIDCOMMIT = 80, /* RFC 4039 */ |
---|
108 | DHO_FQDN = 81, |
---|
109 | DHO_AUTHENTICATION = 90, /* RFC 3118 */ |
---|
110 | DHO_VIVCO = 124, /* RFC 3925 */ |
---|
111 | DHO_VIVSO = 125, /* RFC 3925 */ |
---|
112 | DHO_DNSSEARCH = 119, /* RFC 3397 */ |
---|
113 | DHO_CSR = 121, /* RFC 3442 */ |
---|
114 | DHO_SIXRD = 212, /* RFC 5969 */ |
---|
115 | DHO_MSCSR = 249, /* MS code for RFC 3442 */ |
---|
116 | DHO_END = 255 |
---|
117 | }; |
---|
118 | |
---|
119 | /* FQDN values - lsnybble used in flags |
---|
120 | * hsnybble to create order |
---|
121 | * and to allow 0x00 to mean disable |
---|
122 | */ |
---|
123 | enum FQDN { |
---|
124 | FQDN_DISABLE = 0x00, |
---|
125 | FQDN_NONE = 0x18, |
---|
126 | FQDN_PTR = 0x20, |
---|
127 | FQDN_BOTH = 0x31 |
---|
128 | }; |
---|
129 | |
---|
130 | /* Sizes for DHCP options */ |
---|
131 | #define DHCP_CHADDR_LEN 16 |
---|
132 | #define SERVERNAME_LEN 64 |
---|
133 | #define BOOTFILE_LEN 128 |
---|
134 | #define DHCP_UDP_LEN (14 + 20 + 8) |
---|
135 | #define DHCP_FIXED_LEN (DHCP_UDP_LEN + 226) |
---|
136 | #define DHCP_OPTION_LEN (MTU_MAX - DHCP_FIXED_LEN) |
---|
137 | |
---|
138 | /* Some crappy DHCP servers require the BOOTP minimum length */ |
---|
139 | #define BOOTP_MESSAGE_LENTH_MIN 300 |
---|
140 | |
---|
141 | /* Don't import common.h as that defines __unused which causes problems |
---|
142 | * on some Linux systems which define it as part of a structure */ |
---|
143 | #if __GNUC__ > 2 || defined(__INTEL_COMPILER) |
---|
144 | # ifndef __packed |
---|
145 | # define __packed __attribute__((__packed__)) |
---|
146 | # endif |
---|
147 | #else |
---|
148 | # ifndef __packed |
---|
149 | # define __packed |
---|
150 | # endif |
---|
151 | #endif |
---|
152 | |
---|
153 | struct dhcp_message { |
---|
154 | uint8_t op; /* message type */ |
---|
155 | uint8_t hwtype; /* hardware address type */ |
---|
156 | uint8_t hwlen; /* hardware address length */ |
---|
157 | uint8_t hwopcount; /* should be zero in client message */ |
---|
158 | uint32_t xid; /* transaction id */ |
---|
159 | uint16_t secs; /* elapsed time in sec. from boot */ |
---|
160 | uint16_t flags; |
---|
161 | uint32_t ciaddr; /* (previously allocated) client IP */ |
---|
162 | uint32_t yiaddr; /* 'your' client IP address */ |
---|
163 | uint32_t siaddr; /* should be zero in client's messages */ |
---|
164 | uint32_t giaddr; /* should be zero in client's messages */ |
---|
165 | uint8_t chaddr[DHCP_CHADDR_LEN]; /* client's hardware address */ |
---|
166 | uint8_t servername[SERVERNAME_LEN]; /* server host name */ |
---|
167 | uint8_t bootfile[BOOTFILE_LEN]; /* boot file name */ |
---|
168 | uint32_t cookie; |
---|
169 | uint8_t options[DHCP_OPTION_LEN]; /* message options - cookie */ |
---|
170 | } __packed; |
---|
171 | |
---|
172 | struct dhcp_lease { |
---|
173 | struct in_addr addr; |
---|
174 | struct in_addr net; |
---|
175 | struct in_addr brd; |
---|
176 | uint32_t leasetime; |
---|
177 | uint32_t renewaltime; |
---|
178 | uint32_t rebindtime; |
---|
179 | struct in_addr server; |
---|
180 | time_t leasedfrom; |
---|
181 | struct timeval boundtime; |
---|
182 | uint8_t frominfo; |
---|
183 | uint32_t cookie; |
---|
184 | }; |
---|
185 | |
---|
186 | enum DHS { |
---|
187 | DHS_INIT, |
---|
188 | DHS_DISCOVER, |
---|
189 | DHS_REQUEST, |
---|
190 | DHS_BOUND, |
---|
191 | DHS_RENEW, |
---|
192 | DHS_REBIND, |
---|
193 | DHS_REBOOT, |
---|
194 | DHS_INFORM, |
---|
195 | DHS_RENEW_REQUESTED, |
---|
196 | DHS_INIT_IPV4LL, |
---|
197 | DHS_PROBE |
---|
198 | }; |
---|
199 | |
---|
200 | struct dhcp_state { |
---|
201 | enum DHS state; |
---|
202 | struct dhcp_message *sent; |
---|
203 | struct dhcp_message *offer; |
---|
204 | struct dhcp_message *new; |
---|
205 | struct dhcp_message *old; |
---|
206 | struct dhcp_lease lease; |
---|
207 | const char *reason; |
---|
208 | time_t interval; |
---|
209 | time_t nakoff; |
---|
210 | uint32_t xid; |
---|
211 | int socket; |
---|
212 | int probes; |
---|
213 | int claims; |
---|
214 | int conflicts; |
---|
215 | time_t defend; |
---|
216 | struct in_addr fail; |
---|
217 | size_t arping_index; |
---|
218 | |
---|
219 | int raw_fd; |
---|
220 | int udp_fd; |
---|
221 | int arp_fd; |
---|
222 | size_t buffer_size, buffer_len, buffer_pos; |
---|
223 | unsigned char *buffer; |
---|
224 | |
---|
225 | struct in_addr addr; |
---|
226 | struct in_addr net; |
---|
227 | struct in_addr dst; |
---|
228 | |
---|
229 | char leasefile[PATH_MAX]; |
---|
230 | time_t start_uptime; |
---|
231 | |
---|
232 | unsigned char *clientid; |
---|
233 | |
---|
234 | struct authstate auth; |
---|
235 | }; |
---|
236 | |
---|
237 | #define D_STATE(ifp) \ |
---|
238 | ((struct dhcp_state *)(ifp)->if_data[IF_DATA_DHCP]) |
---|
239 | #define D_CSTATE(ifp) \ |
---|
240 | ((const struct dhcp_state *)(ifp)->if_data[IF_DATA_DHCP]) |
---|
241 | |
---|
242 | #include "dhcpcd.h" |
---|
243 | #include "if-options.h" |
---|
244 | #include "net.h" |
---|
245 | |
---|
246 | #ifdef INET |
---|
247 | extern struct dhcp_opt *dhcp_opts; |
---|
248 | extern size_t dhcp_opts_len; |
---|
249 | |
---|
250 | char *decode_rfc3361(int dl, const uint8_t *data); |
---|
251 | ssize_t decode_rfc3442(char *out, ssize_t len, int pl, const uint8_t *p); |
---|
252 | ssize_t decode_rfc5969(char *out, ssize_t len, int pl, const uint8_t *p); |
---|
253 | |
---|
254 | void dhcp_printoptions(void); |
---|
255 | char *get_option_string(const struct dhcp_message *, uint8_t); |
---|
256 | int get_option_addr(struct in_addr *, const struct dhcp_message *, uint8_t); |
---|
257 | #define is_bootp(m) (m && \ |
---|
258 | !IN_LINKLOCAL(htonl((m)->yiaddr)) && \ |
---|
259 | get_option_uint8(NULL, m, DHO_MESSAGETYPE) == -1) |
---|
260 | struct rt_head *get_option_routes(struct interface *, |
---|
261 | const struct dhcp_message *); |
---|
262 | ssize_t dhcp_env(char **, const char *, const struct dhcp_message *, |
---|
263 | const struct interface *); |
---|
264 | |
---|
265 | uint32_t dhcp_xid(const struct interface *); |
---|
266 | struct dhcp_message *dhcp_message_new(const struct in_addr *addr, |
---|
267 | const struct in_addr *mask); |
---|
268 | int dhcp_message_add_addr(struct dhcp_message *, uint8_t, struct in_addr); |
---|
269 | ssize_t make_message(struct dhcp_message **, const struct interface *, |
---|
270 | uint8_t); |
---|
271 | int valid_dhcp_packet(unsigned char *); |
---|
272 | |
---|
273 | ssize_t write_lease(const struct interface *, const struct dhcp_message *); |
---|
274 | struct dhcp_message *read_lease(struct interface *); |
---|
275 | void get_lease(struct dhcp_lease *, const struct dhcp_message *); |
---|
276 | |
---|
277 | void dhcp_handleifa(int, struct interface *, |
---|
278 | const struct in_addr *, const struct in_addr *, const struct in_addr *); |
---|
279 | |
---|
280 | void dhcp_drop(struct interface *, const char *); |
---|
281 | void dhcp_start(struct interface *); |
---|
282 | void dhcp_stop(struct interface *); |
---|
283 | void dhcp_decline(struct interface *); |
---|
284 | void dhcp_discover(void *); |
---|
285 | void dhcp_inform(struct interface *); |
---|
286 | void dhcp_bind(void *); |
---|
287 | void dhcp_reboot_newopts(struct interface *, int); |
---|
288 | void dhcp_close(struct interface *); |
---|
289 | void dhcp_free(struct interface *); |
---|
290 | int dhcp_dump(const char *); |
---|
291 | #else |
---|
292 | #define dhcp_printoptions |
---|
293 | #define dhcp_drop(a, b) |
---|
294 | #define dhcp_start(a) {} |
---|
295 | #define dhcp_reboot(a, b) b = b |
---|
296 | #define dhcp_reboot_newopts(a, b) |
---|
297 | #define dhcp_close(a) |
---|
298 | #define dhcp_free(a) |
---|
299 | #define dhcp_dump(a) -1 |
---|
300 | #endif |
---|
301 | |
---|
302 | #endif |
---|