| 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 | |