1 | /* |
2 | * dhcpcd - DHCP client daemon |
3 | * Copyright (c) 2006-2019 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 <netinet/ip.h> |
35 | #define __FAVOR_BSD /* Nasty glibc hack so we can use BSD semantics for UDP */ |
36 | #include <netinet/udp.h> |
37 | #undef __FAVOR_BSD |
38 | |
39 | #include <limits.h> |
40 | #include <stdint.h> |
41 | |
42 | #include "arp.h" |
43 | #include "auth.h" |
44 | #include "dhcp-common.h" |
45 | |
46 | /* UDP port numbers for BOOTP */ |
47 | #define BOOTPS 67 |
48 | #define BOOTPC 68 |
49 | |
50 | #define MAGIC_COOKIE 0x63825363 |
51 | #define BROADCAST_FLAG 0x8000 |
52 | |
53 | /* BOOTP message OP code */ |
54 | #define BOOTREQUEST 1 |
55 | #define BOOTREPLY 2 |
56 | |
57 | /* DHCP message type */ |
58 | #define DHCP_DISCOVER 1 |
59 | #define DHCP_OFFER 2 |
60 | #define DHCP_REQUEST 3 |
61 | #define DHCP_DECLINE 4 |
62 | #define DHCP_ACK 5 |
63 | #define DHCP_NAK 6 |
64 | #define DHCP_RELEASE 7 |
65 | #define DHCP_INFORM 8 |
66 | #define DHCP_FORCERENEW 9 |
67 | |
68 | /* Constants taken from RFC 2131. */ |
69 | #define T1 0.5 |
70 | #define T2 0.875 |
71 | #define DHCP_BASE 4 |
72 | #define DHCP_MAX 64 |
73 | #define DHCP_RAND_MIN -1 |
74 | #define DHCP_RAND_MAX 1 |
75 | |
76 | #ifdef RFC2131_STRICT |
77 | /* Be strictly conformant for section 4.1.1 */ |
78 | # define DHCP_MIN_DELAY 1 |
79 | # define DHCP_MAX_DELAY 10 |
80 | #else |
81 | /* or mirror the more modern IPv6RS and DHCPv6 delays */ |
82 | # define DHCP_MIN_DELAY 0 |
83 | # define DHCP_MAX_DELAY 1 |
84 | #endif |
85 | |
86 | /* DHCP options */ |
87 | enum DHO { |
88 | DHO_PAD = 0, |
89 | DHO_SUBNETMASK = 1, |
90 | DHO_ROUTER = 3, |
91 | DHO_DNSSERVER = 6, |
92 | DHO_HOSTNAME = 12, |
93 | DHO_DNSDOMAIN = 15, |
94 | DHO_MTU = 26, |
95 | DHO_BROADCAST = 28, |
96 | DHO_STATICROUTE = 33, |
97 | DHO_NISDOMAIN = 40, |
98 | DHO_NISSERVER = 41, |
99 | DHO_NTPSERVER = 42, |
100 | DHO_VENDOR = 43, |
101 | DHO_IPADDRESS = 50, |
102 | DHO_LEASETIME = 51, |
103 | DHO_OPTSOVERLOADED = 52, |
104 | DHO_MESSAGETYPE = 53, |
105 | DHO_SERVERID = 54, |
106 | DHO_PARAMETERREQUESTLIST = 55, |
107 | DHO_MESSAGE = 56, |
108 | DHO_MAXMESSAGESIZE = 57, |
109 | DHO_RENEWALTIME = 58, |
110 | DHO_REBINDTIME = 59, |
111 | DHO_VENDORCLASSID = 60, |
112 | DHO_CLIENTID = 61, |
113 | DHO_USERCLASS = 77, /* RFC 3004 */ |
114 | DHO_RAPIDCOMMIT = 80, /* RFC 4039 */ |
115 | DHO_FQDN = 81, |
116 | DHO_AUTHENTICATION = 90, /* RFC 3118 */ |
117 | DHO_AUTOCONFIGURE = 116, /* RFC 2563 */ |
118 | DHO_DNSSEARCH = 119, /* RFC 3397 */ |
119 | DHO_CSR = 121, /* RFC 3442 */ |
120 | DHO_VIVCO = 124, /* RFC 3925 */ |
121 | DHO_VIVSO = 125, /* RFC 3925 */ |
122 | DHO_FORCERENEW_NONCE = 145, /* RFC 6704 */ |
123 | DHO_MUDURL = 161, /* draft-ietf-opsawg-mud */ |
124 | DHO_SIXRD = 212, /* RFC 5969 */ |
125 | DHO_MSCSR = 249, /* MS code for RFC 3442 */ |
126 | DHO_END = 255 |
127 | }; |
128 | |
129 | /* FQDN values - lsnybble used in flags |
130 | * hsnybble to create order |
131 | * and to allow 0x00 to mean disable |
132 | */ |
133 | enum FQDN { |
134 | FQDN_DISABLE = 0x00, |
135 | FQDN_NONE = 0x18, |
136 | FQDN_PTR = 0x20, |
137 | FQDN_BOTH = 0x31 |
138 | }; |
139 | |
140 | /* Sizes for BOOTP options */ |
141 | #define BOOTP_CHADDR_LEN 16 |
142 | #define BOOTP_SNAME_LEN 64 |
143 | #define BOOTP_FILE_LEN 128 |
144 | #define BOOTP_VEND_LEN 64 |
145 | |
146 | /* DHCP is basically an extension to BOOTP */ |
147 | struct bootp { |
148 | uint8_t op; /* message type */ |
149 | uint8_t htype; /* hardware address type */ |
150 | uint8_t hlen; /* hardware address length */ |
151 | uint8_t hops; /* should be zero in client message */ |
152 | uint32_t xid; /* transaction id */ |
153 | uint16_t secs; /* elapsed time in sec. from boot */ |
154 | uint16_t flags; /* such as broadcast flag */ |
155 | uint32_t ciaddr; /* (previously allocated) client IP */ |
156 | uint32_t yiaddr; /* 'your' client IP address */ |
157 | uint32_t siaddr; /* should be zero in client's messages */ |
158 | uint32_t giaddr; /* should be zero in client's messages */ |
159 | uint8_t chaddr[BOOTP_CHADDR_LEN]; /* client's hardware address */ |
160 | uint8_t sname[BOOTP_SNAME_LEN]; /* server host name */ |
161 | uint8_t file[BOOTP_FILE_LEN]; /* boot file name */ |
162 | uint8_t vend[BOOTP_VEND_LEN]; /* vendor specific area */ |
163 | /* DHCP allows a variable length vendor area */ |
164 | }; |
165 | |
166 | struct bootp_pkt |
167 | { |
168 | struct ip ip; |
169 | struct udphdr udp; |
170 | struct bootp bootp; |
171 | }; |
172 | |
173 | struct dhcp_lease { |
174 | struct in_addr addr; |
175 | struct in_addr mask; |
176 | struct in_addr brd; |
177 | uint32_t leasetime; |
178 | uint32_t renewaltime; |
179 | uint32_t rebindtime; |
180 | struct in_addr server; |
181 | uint8_t frominfo; |
182 | uint32_t cookie; |
183 | }; |
184 | |
185 | enum DHS { |
186 | DHS_NONE, |
187 | DHS_INIT, |
188 | DHS_DISCOVER, |
189 | DHS_REQUEST, |
190 | DHS_PROBE, |
191 | DHS_BOUND, |
192 | DHS_RENEW, |
193 | DHS_REBIND, |
194 | DHS_REBOOT, |
195 | DHS_INFORM, |
196 | DHS_RENEW_REQUESTED, |
197 | DHS_RELEASE |
198 | }; |
199 | |
200 | struct dhcp_state { |
201 | enum DHS state; |
202 | struct bootp *sent; |
203 | size_t sent_len; |
204 | struct bootp *offer; |
205 | size_t offer_len; |
206 | struct bootp *new; |
207 | size_t new_len; |
208 | struct bootp *old; |
209 | size_t old_len; |
210 | struct dhcp_lease lease; |
211 | const char *reason; |
212 | time_t interval; |
213 | time_t nakoff; |
214 | uint32_t xid; |
215 | int socket; |
216 | |
217 | int bpf_fd; |
218 | unsigned int bpf_flags; |
219 | int udp_fd; |
220 | struct ipv4_addr *addr; |
221 | uint8_t added; |
222 | |
223 | char leasefile[sizeof(LEASEFILE) + IF_NAMESIZE + (IF_SSIDLEN * 4)]; |
224 | struct timespec started; |
225 | unsigned char *clientid; |
226 | struct authstate auth; |
227 | #ifdef ARPING |
228 | ssize_t arping_index; |
229 | #endif |
230 | }; |
231 | |
232 | #ifdef INET |
233 | #define D_STATE(ifp) \ |
234 | ((struct dhcp_state *)(ifp)->if_data[IF_DATA_DHCP]) |
235 | #define D_CSTATE(ifp) \ |
236 | ((const struct dhcp_state *)(ifp)->if_data[IF_DATA_DHCP]) |
237 | #define D_STATE_RUNNING(ifp) \ |
238 | (D_CSTATE((ifp)) && D_CSTATE((ifp))->new && D_CSTATE((ifp))->reason) |
239 | |
240 | #define IS_DHCP(b) ((b)->vend[0] == 0x63 && \ |
241 | (b)->vend[1] == 0x82 && \ |
242 | (b)->vend[2] == 0x53 && \ |
243 | (b)->vend[3] == 0x63) |
244 | |
245 | #include "dhcpcd.h" |
246 | #include "if-options.h" |
247 | |
248 | char *decode_rfc3361(const uint8_t *, size_t); |
249 | ssize_t decode_rfc3442(char *, size_t, const uint8_t *p, size_t); |
250 | |
251 | void dhcp_printoptions(const struct dhcpcd_ctx *, |
252 | const struct dhcp_opt *, size_t); |
253 | uint16_t dhcp_get_mtu(const struct interface *); |
254 | int dhcp_get_routes(struct rt_head *, struct interface *); |
255 | ssize_t dhcp_env(char **, const char *, const struct bootp *, size_t, |
256 | const struct interface *); |
257 | |
258 | void dhcp_handleifa(int, struct ipv4_addr *, pid_t pid); |
259 | void dhcp_drop(struct interface *, const char *); |
260 | void dhcp_start(struct interface *); |
261 | void dhcp_abort(struct interface *); |
262 | void dhcp_discover(void *); |
263 | void dhcp_inform(struct interface *); |
264 | void dhcp_renew(struct interface *); |
265 | void dhcp_bind(struct interface *); |
266 | void dhcp_reboot_newopts(struct interface *, unsigned long long); |
267 | void dhcp_close(struct interface *); |
268 | void dhcp_free(struct interface *); |
269 | int dhcp_dump(struct interface *); |
270 | #endif /* INET */ |
271 | |
272 | #endif /* DHCP_H */ |
273 | |