Samuel Tan | d7ed851 | 2015-08-13 16:11:35 -0700 | [diff] [blame] | 1 | /* |
| 2 | * dhcpcd - DHCP client daemon |
| 3 | * Copyright (c) 2006-2015 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 "arp.h" |
| 38 | #include "auth.h" |
| 39 | #include "dhcp-common.h" |
| 40 | |
| 41 | /* UDP port numbers for DHCP */ |
| 42 | #define DHCP_SERVER_PORT 67 |
| 43 | #define DHCP_CLIENT_PORT 68 |
| 44 | |
| 45 | #define MAGIC_COOKIE 0x63825363 |
| 46 | #define BROADCAST_FLAG 0x8000 |
| 47 | |
| 48 | /* DHCP message OP code */ |
| 49 | #define DHCP_BOOTREQUEST 1 |
| 50 | #define DHCP_BOOTREPLY 2 |
| 51 | |
| 52 | /* DHCP message type */ |
| 53 | #define DHCP_DISCOVER 1 |
| 54 | #define DHCP_OFFER 2 |
| 55 | #define DHCP_REQUEST 3 |
| 56 | #define DHCP_DECLINE 4 |
| 57 | #define DHCP_ACK 5 |
| 58 | #define DHCP_NAK 6 |
| 59 | #define DHCP_RELEASE 7 |
| 60 | #define DHCP_INFORM 8 |
| 61 | #define DHCP_FORCERENEW 9 |
| 62 | |
| 63 | /* Constants taken from RFC 2131. */ |
| 64 | #define T1 0.5 |
| 65 | #define T2 0.875 |
| 66 | #define DHCP_BASE 4 |
| 67 | #define DHCP_MAX 64 |
| 68 | #define DHCP_RAND_MIN -1 |
| 69 | #define DHCP_RAND_MAX 1 |
| 70 | |
| 71 | #ifdef RFC2131_STRICT |
| 72 | /* Be strictly conformant for section 4.1.1 */ |
| 73 | # define DHCP_MIN_DELAY 1 |
| 74 | # define DHCP_MAX_DELAY 10 |
| 75 | #else |
| 76 | /* or mirror the more modern IPv6RS and DHCPv6 delays */ |
| 77 | # define DHCP_MIN_DELAY 0 |
| 78 | # define DHCP_MAX_DELAY 1 |
| 79 | #endif |
| 80 | |
| 81 | /* DHCP options */ |
| 82 | enum DHO { |
| 83 | DHO_PAD = 0, |
| 84 | DHO_SUBNETMASK = 1, |
| 85 | DHO_ROUTER = 3, |
| 86 | DHO_DNSSERVER = 6, |
| 87 | DHO_HOSTNAME = 12, |
| 88 | DHO_DNSDOMAIN = 15, |
| 89 | DHO_MTU = 26, |
| 90 | DHO_BROADCAST = 28, |
| 91 | DHO_STATICROUTE = 33, |
| 92 | DHO_NISDOMAIN = 40, |
| 93 | DHO_NISSERVER = 41, |
| 94 | DHO_NTPSERVER = 42, |
| 95 | DHO_VENDOR = 43, |
| 96 | DHO_IPADDRESS = 50, |
| 97 | DHO_LEASETIME = 51, |
| 98 | DHO_OPTIONSOVERLOADED = 52, |
| 99 | DHO_MESSAGETYPE = 53, |
| 100 | DHO_SERVERID = 54, |
| 101 | DHO_PARAMETERREQUESTLIST = 55, |
| 102 | DHO_MESSAGE = 56, |
| 103 | DHO_MAXMESSAGESIZE = 57, |
| 104 | DHO_RENEWALTIME = 58, |
| 105 | DHO_REBINDTIME = 59, |
| 106 | DHO_VENDORCLASSID = 60, |
| 107 | DHO_CLIENTID = 61, |
| 108 | DHO_USERCLASS = 77, /* RFC 3004 */ |
| 109 | DHO_RAPIDCOMMIT = 80, /* RFC 4039 */ |
| 110 | DHO_FQDN = 81, |
| 111 | DHO_AUTHENTICATION = 90, /* RFC 3118 */ |
| 112 | DHO_AUTOCONFIGURE = 116, /* RFC 2563 */ |
| 113 | DHO_DNSSEARCH = 119, /* RFC 3397 */ |
| 114 | DHO_CSR = 121, /* RFC 3442 */ |
| 115 | DHO_VIVCO = 124, /* RFC 3925 */ |
| 116 | DHO_VIVSO = 125, /* RFC 3925 */ |
| 117 | DHO_FORCERENEW_NONCE = 145, /* RFC 6704 */ |
| 118 | DHO_SIXRD = 212, /* RFC 5969 */ |
| 119 | DHO_MSCSR = 249, /* MS code for RFC 3442 */ |
| 120 | DHO_END = 255 |
| 121 | }; |
| 122 | |
| 123 | /* FQDN values - lsnybble used in flags |
| 124 | * hsnybble to create order |
| 125 | * and to allow 0x00 to mean disable |
| 126 | */ |
| 127 | enum FQDN { |
| 128 | FQDN_DISABLE = 0x00, |
| 129 | FQDN_NONE = 0x18, |
| 130 | FQDN_PTR = 0x20, |
| 131 | FQDN_BOTH = 0x31 |
| 132 | }; |
| 133 | |
| 134 | /* Sizes for DHCP options */ |
| 135 | #define DHCP_CHADDR_LEN 16 |
| 136 | #define SERVERNAME_LEN 64 |
| 137 | #define BOOTFILE_LEN 128 |
| 138 | #define DHCP_UDP_LEN (14 + 20 + 8) |
| 139 | #define DHCP_FIXED_LEN (DHCP_UDP_LEN + 226) |
| 140 | #define DHCP_OPTION_LEN (MTU_MAX - DHCP_FIXED_LEN) |
| 141 | |
| 142 | /* Some crappy DHCP servers require the BOOTP minimum length */ |
| 143 | #define BOOTP_MESSAGE_LENTH_MIN 300 |
| 144 | |
Samuel Tan | 9177c6f | 2015-08-13 16:47:36 -0700 | [diff] [blame] | 145 | /* Flags for the OPTIONSOVERLOADED field. */ |
| 146 | #define OPTION_OVERLOADED_BOOT_FILE 1 |
| 147 | #define OPTION_OVERLOADED_SERVER_NAME 2 |
| 148 | |
Samuel Tan | d7ed851 | 2015-08-13 16:11:35 -0700 | [diff] [blame] | 149 | /* Don't import common.h as that defines __unused which causes problems |
| 150 | * on some Linux systems which define it as part of a structure */ |
| 151 | #if __GNUC__ > 2 || defined(__INTEL_COMPILER) |
| 152 | # ifndef __packed |
| 153 | # define __packed __attribute__((__packed__)) |
| 154 | # endif |
| 155 | #else |
| 156 | # ifndef __packed |
| 157 | # define __packed |
| 158 | # endif |
| 159 | #endif |
| 160 | |
| 161 | struct dhcp_message { |
| 162 | uint8_t op; /* message type */ |
| 163 | uint8_t hwtype; /* hardware address type */ |
| 164 | uint8_t hwlen; /* hardware address length */ |
| 165 | uint8_t hwopcount; /* should be zero in client message */ |
| 166 | uint32_t xid; /* transaction id */ |
| 167 | uint16_t secs; /* elapsed time in sec. from boot */ |
| 168 | uint16_t flags; |
| 169 | uint32_t ciaddr; /* (previously allocated) client IP */ |
| 170 | uint32_t yiaddr; /* 'your' client IP address */ |
| 171 | uint32_t siaddr; /* should be zero in client's messages */ |
| 172 | uint32_t giaddr; /* should be zero in client's messages */ |
| 173 | uint8_t chaddr[DHCP_CHADDR_LEN]; /* client's hardware address */ |
| 174 | uint8_t servername[SERVERNAME_LEN]; /* server host name */ |
| 175 | uint8_t bootfile[BOOTFILE_LEN]; /* boot file name */ |
| 176 | uint32_t cookie; |
| 177 | uint8_t options[DHCP_OPTION_LEN]; /* message options - cookie */ |
| 178 | } __packed; |
| 179 | |
Samuel Tan | 9177c6f | 2015-08-13 16:47:36 -0700 | [diff] [blame] | 180 | struct dhcp_option_iterator { |
| 181 | const struct dhcp_message *message; |
| 182 | const uint8_t *ptr; |
| 183 | const uint8_t *end; |
| 184 | uint8_t extra_option_locations; |
| 185 | uint8_t extra_option_locations_set; |
| 186 | }; |
| 187 | |
Samuel Tan | d7ed851 | 2015-08-13 16:11:35 -0700 | [diff] [blame] | 188 | struct dhcp_lease { |
| 189 | struct in_addr addr; |
| 190 | struct in_addr net; |
| 191 | struct in_addr brd; |
| 192 | uint32_t leasetime; |
| 193 | uint32_t renewaltime; |
| 194 | uint32_t rebindtime; |
| 195 | struct in_addr server; |
| 196 | uint8_t frominfo; |
| 197 | uint32_t cookie; |
| 198 | }; |
| 199 | |
Samuel Tan | f20514b | 2015-08-13 16:24:02 -0700 | [diff] [blame] | 200 | /* Extra data about servers stored in the lease file after the dhcp_message */ |
| 201 | struct dhcp_server_info { |
| 202 | uint8_t gw_hwlen; |
| 203 | unsigned char gw_hwaddr[HWADDR_LEN]; |
| 204 | }; |
| 205 | |
Samuel Tan | d7ed851 | 2015-08-13 16:11:35 -0700 | [diff] [blame] | 206 | enum DHS { |
| 207 | DHS_INIT, |
| 208 | DHS_DISCOVER, |
| 209 | DHS_REQUEST, |
| 210 | DHS_BOUND, |
| 211 | DHS_RENEW, |
| 212 | DHS_REBIND, |
| 213 | DHS_REBOOT, |
| 214 | DHS_INFORM, |
| 215 | DHS_RENEW_REQUESTED, |
| 216 | DHS_IPV4LL_BOUND, |
| 217 | DHS_PROBE |
| 218 | }; |
| 219 | |
| 220 | struct dhcp_state { |
| 221 | enum DHS state; |
| 222 | struct dhcp_message *sent; |
| 223 | struct dhcp_message *offer; |
| 224 | struct dhcp_message *new; |
| 225 | struct dhcp_message *old; |
| 226 | struct dhcp_lease lease; |
| 227 | const char *reason; |
| 228 | time_t interval; |
| 229 | time_t nakoff; |
| 230 | uint32_t xid; |
| 231 | int socket; |
| 232 | |
| 233 | int raw_fd; |
| 234 | int arp_fd; |
| 235 | size_t buffer_size, buffer_len, buffer_pos; |
| 236 | unsigned char *buffer; |
| 237 | |
| 238 | struct in_addr addr; |
| 239 | struct in_addr net; |
| 240 | struct in_addr dst; |
| 241 | uint8_t added; |
| 242 | |
Samuel Tan | a359582 | 2015-08-13 16:41:21 -0700 | [diff] [blame] | 243 | char leasefile[PATH_MAX]; |
Samuel Tan | d7ed851 | 2015-08-13 16:11:35 -0700 | [diff] [blame] | 244 | time_t start_uptime; |
| 245 | |
| 246 | unsigned char *clientid; |
| 247 | |
| 248 | struct authstate auth; |
| 249 | struct arp_statehead arp_states; |
| 250 | |
| 251 | size_t arping_index; |
| 252 | |
| 253 | struct arp_state *arp_ipv4ll; |
| 254 | unsigned int conflicts; |
Samuel Tan | 5158c9d | 2015-08-13 18:09:30 -0700 | [diff] [blame] | 255 | int nak_receive_count; |
| 256 | int failed_address_offer_count; |
| 257 | struct in_addr failed; |
Samuel Tan | d7ed851 | 2015-08-13 16:11:35 -0700 | [diff] [blame] | 258 | time_t defend; |
| 259 | char randomstate[128]; |
Samuel Tan | f20514b | 2015-08-13 16:24:02 -0700 | [diff] [blame] | 260 | struct dhcp_server_info server_info; |
Samuel Tan | d7ed851 | 2015-08-13 16:11:35 -0700 | [diff] [blame] | 261 | }; |
| 262 | |
| 263 | #define D_STATE(ifp) \ |
| 264 | ((struct dhcp_state *)(ifp)->if_data[IF_DATA_DHCP]) |
| 265 | #define D_CSTATE(ifp) \ |
| 266 | ((const struct dhcp_state *)(ifp)->if_data[IF_DATA_DHCP]) |
| 267 | #define D_STATE_RUNNING(ifp) \ |
| 268 | (D_CSTATE((ifp)) && D_CSTATE((ifp))->new && D_CSTATE((ifp))->reason) |
| 269 | |
| 270 | #include "dhcpcd.h" |
| 271 | #include "if-options.h" |
| 272 | |
| 273 | #ifdef INET |
| 274 | char *decode_rfc3361(const uint8_t *, size_t); |
| 275 | ssize_t decode_rfc3442(char *, size_t, const uint8_t *p, size_t); |
| 276 | ssize_t decode_rfc5969(char *, size_t, const uint8_t *p, size_t); |
| 277 | |
| 278 | void dhcp_printoptions(const struct dhcpcd_ctx *, |
| 279 | const struct dhcp_opt *, size_t); |
| 280 | int get_option_addr(struct dhcpcd_ctx *,struct in_addr *, |
| 281 | const struct dhcp_message *, uint8_t); |
| 282 | #define IS_BOOTP(i, m) ((m) && \ |
| 283 | !IN_LINKLOCAL(htonl((m)->yiaddr)) && \ |
| 284 | get_option_uint8((i)->ctx, NULL, (m), DHO_MESSAGETYPE) == -1) |
| 285 | struct rt_head *get_option_routes(struct interface *, |
| 286 | const struct dhcp_message *); |
| 287 | ssize_t dhcp_env(char **, const char *, const struct dhcp_message *, |
| 288 | const struct interface *); |
| 289 | |
| 290 | uint32_t dhcp_xid(const struct interface *); |
| 291 | struct dhcp_message *dhcp_message_new(const struct in_addr *addr, |
| 292 | const struct in_addr *mask); |
| 293 | int dhcp_message_add_addr(struct dhcp_message *, uint8_t, struct in_addr); |
| 294 | ssize_t make_message(struct dhcp_message **, const struct interface *, |
| 295 | uint8_t); |
| 296 | int valid_dhcp_packet(unsigned char *); |
| 297 | |
| 298 | void dhcp_handleifa(int, struct interface *, |
| 299 | const struct in_addr *, const struct in_addr *, const struct in_addr *, |
| 300 | int); |
| 301 | |
| 302 | void dhcp_drop(struct interface *, const char *); |
| 303 | void dhcp_start(struct interface *); |
| 304 | void dhcp_stop(struct interface *); |
| 305 | void dhcp_discover(void *); |
| 306 | void dhcp_inform(struct interface *); |
| 307 | void dhcp_bind(struct interface *, struct arp_state *); |
| 308 | void dhcp_reboot_newopts(struct interface *, unsigned long long); |
| 309 | void dhcp_close(struct interface *); |
| 310 | void dhcp_free(struct interface *); |
| 311 | int dhcp_dump(struct interface *); |
| 312 | #else |
| 313 | #define dhcp_drop(a, b) {} |
| 314 | #define dhcp_start(a) {} |
| 315 | #define dhcp_reboot(a, b) (b = b) |
| 316 | #define dhcp_reboot_newopts(a, b) (b = b) |
| 317 | #define dhcp_close(a) {} |
| 318 | #define dhcp_free(a) {} |
| 319 | #define dhcp_dump(a) (-1) |
| 320 | #endif |
| 321 | |
| 322 | #endif |