1 1.1 pooka /* 2 1.1 pooka * dhcpcd - DHCP client daemon 3 1.1 pooka * Copyright (c) 2006-2010 Roy Marples <roy (at) marples.name> 4 1.1 pooka * All rights reserved 5 1.1 pooka 6 1.1 pooka * Redistribution and use in source and binary forms, with or without 7 1.1 pooka * modification, are permitted provided that the following conditions 8 1.1 pooka * are met: 9 1.1 pooka * 1. Redistributions of source code must retain the above copyright 10 1.1 pooka * notice, this list of conditions and the following disclaimer. 11 1.1 pooka * 2. Redistributions in binary form must reproduce the above copyright 12 1.1 pooka * notice, this list of conditions and the following disclaimer in the 13 1.1 pooka * documentation and/or other materials provided with the distribution. 14 1.1 pooka * 15 1.1 pooka * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 1.1 pooka * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 1.1 pooka * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 1.1 pooka * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 1.1 pooka * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 1.1 pooka * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 1.1 pooka * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 1.1 pooka * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 1.1 pooka * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 1.1 pooka * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 1.1 pooka * SUCH DAMAGE. 26 1.1 pooka */ 27 1.1 pooka 28 1.1 pooka #include <ctype.h> 29 1.1 pooka #include <errno.h> 30 1.1 pooka #include <fcntl.h> 31 1.1 pooka #include <stdlib.h> 32 1.1 pooka #include <string.h> 33 1.1 pooka #include <unistd.h> 34 1.1 pooka 35 1.1 pooka #include "common.h" 36 1.1 pooka #include "dhcp.h" 37 1.1 pooka 38 1.1 pooka #define REQUEST (1 << 0) 39 1.1 pooka #define UINT8 (1 << 1) 40 1.1 pooka #define UINT16 (1 << 2) 41 1.1 pooka #define SINT16 (1 << 3) 42 1.1 pooka #define UINT32 (1 << 4) 43 1.1 pooka #define SINT32 (1 << 5) 44 1.1 pooka #define IPV4 (1 << 6) 45 1.1 pooka #define STRING (1 << 7) 46 1.1 pooka #define PAIR (1 << 8) 47 1.1 pooka #define ARRAY (1 << 9) 48 1.1 pooka #define RFC3361 (1 << 10) 49 1.1 pooka #define RFC3397 (1 << 11) 50 1.1 pooka #define RFC3442 (1 << 12) 51 1.1 pooka 52 1.1 pooka #define IPV4R IPV4 | REQUEST 53 1.1 pooka 54 1.1 pooka #define DAD "Duplicate address detected" 55 1.1 pooka 56 1.1 pooka /* Our aggregate option buffer. 57 1.1 pooka * We ONLY use this when options are split, which for most purposes is 58 1.1 pooka * practically never. See RFC3396 for details. */ 59 1.1 pooka static uint8_t *opt_buffer; 60 1.1 pooka 61 1.1 pooka struct dhcp_opt { 62 1.1 pooka uint8_t option; 63 1.1 pooka int type; 64 1.1 pooka const char *var; 65 1.1 pooka }; 66 1.1 pooka 67 1.2 joerg static const struct dhcp_opt dhcp_opts[] = { 68 1.1 pooka { 1, IPV4 | REQUEST, "subnet_mask" }, 69 1.1 pooka /* RFC 3442 states that the CSR has to come before all other 70 1.1 pooka * routes. For completeness, we also specify static routes, 71 1.1 pooka * then routers. */ 72 1.1 pooka { 121, RFC3442, "classless_static_routes" }, 73 1.1 pooka { 249, RFC3442, "ms_classless_static_routes" }, 74 1.1 pooka { 33, IPV4 | ARRAY | REQUEST, "static_routes" }, 75 1.1 pooka { 3, IPV4 | ARRAY | REQUEST, "routers" }, 76 1.1 pooka { 2, UINT32, "time_offset" }, 77 1.1 pooka { 4, IPV4 | ARRAY, "time_servers" }, 78 1.1 pooka { 5, IPV4 | ARRAY, "ien116_name_servers" }, 79 1.1 pooka { 6, IPV4 | ARRAY, "domain_name_servers" }, 80 1.1 pooka { 7, IPV4 | ARRAY, "log_servers" }, 81 1.1 pooka { 8, IPV4 | ARRAY, "cookie_servers" }, 82 1.1 pooka { 9, IPV4 | ARRAY, "lpr_servers" }, 83 1.1 pooka { 10, IPV4 | ARRAY, "impress_servers" }, 84 1.1 pooka { 11, IPV4 | ARRAY, "resource_location_servers" }, 85 1.1 pooka { 12, STRING, "host_name" }, 86 1.1 pooka { 13, UINT16, "boot_size" }, 87 1.1 pooka { 14, STRING, "merit_dump" }, 88 1.1 pooka { 15, STRING, "domain_name" }, 89 1.1 pooka { 16, IPV4, "swap_server" }, 90 1.1 pooka { 17, STRING, "root_path" }, 91 1.1 pooka { 18, STRING, "extensions_path" }, 92 1.1 pooka { 19, UINT8, "ip_forwarding" }, 93 1.1 pooka { 20, UINT8, "non_local_source_routing" }, 94 1.1 pooka { 21, IPV4 | ARRAY, "policy_filter" }, 95 1.1 pooka { 22, SINT16, "max_dgram_reassembly" }, 96 1.1 pooka { 23, UINT16, "default_ip_ttl" }, 97 1.1 pooka { 24, UINT32, "path_mtu_aging_timeout" }, 98 1.1 pooka { 25, UINT16 | ARRAY, "path_mtu_plateau_table" }, 99 1.1 pooka { 26, UINT16, "interface_mtu" }, 100 1.1 pooka { 27, UINT8, "all_subnets_local" }, 101 1.1 pooka { 28, IPV4 | REQUEST, "broadcast_address" }, 102 1.1 pooka { 29, UINT8, "perform_mask_discovery" }, 103 1.1 pooka { 30, UINT8, "mask_supplier" }, 104 1.1 pooka { 31, UINT8, "router_discovery" }, 105 1.1 pooka { 32, IPV4, "router_solicitation_address" }, 106 1.1 pooka { 34, UINT8, "trailer_encapsulation" }, 107 1.1 pooka { 35, UINT32, "arp_cache_timeout" }, 108 1.1 pooka { 36, UINT16, "ieee802_3_encapsulation" }, 109 1.1 pooka { 37, UINT8, "default_tcp_ttl" }, 110 1.1 pooka { 38, UINT32, "tcp_keepalive_interval" }, 111 1.1 pooka { 39, UINT8, "tcp_keepalive_garbage" }, 112 1.1 pooka { 40, STRING, "nis_domain" }, 113 1.1 pooka { 41, IPV4 | ARRAY, "nis_servers" }, 114 1.1 pooka { 42, IPV4 | ARRAY, "ntp_servers" }, 115 1.1 pooka { 43, STRING, "vendor_encapsulated_options" }, 116 1.1 pooka { 44, IPV4 | ARRAY, "netbios_name_servers" }, 117 1.1 pooka { 45, IPV4, "netbios_dd_server" }, 118 1.1 pooka { 46, UINT8, "netbios_node_type" }, 119 1.1 pooka { 47, STRING, "netbios_scope" }, 120 1.1 pooka { 48, IPV4 | ARRAY, "font_servers" }, 121 1.1 pooka { 49, IPV4 | ARRAY, "x_display_manager" }, 122 1.1 pooka { 50, IPV4, "dhcp_requested_address" }, 123 1.1 pooka { 51, UINT32 | REQUEST, "dhcp_lease_time" }, 124 1.1 pooka { 52, UINT8, "dhcp_option_overload" }, 125 1.1 pooka { 53, UINT8, "dhcp_message_type" }, 126 1.1 pooka { 54, IPV4, "dhcp_server_identifier" }, 127 1.1 pooka { 55, UINT8 | ARRAY, "dhcp_parameter_request_list" }, 128 1.1 pooka { 56, STRING, "dhcp_message" }, 129 1.1 pooka { 57, UINT16, "dhcp_max_message_size" }, 130 1.1 pooka { 58, UINT32 | REQUEST, "dhcp_renewal_time" }, 131 1.1 pooka { 59, UINT32 | REQUEST, "dhcp_rebinding_time" }, 132 1.1 pooka { 64, STRING, "nisplus_domain" }, 133 1.1 pooka { 65, IPV4 | ARRAY, "nisplus_servers" }, 134 1.1 pooka { 66, STRING, "tftp_server_name" }, 135 1.1 pooka { 67, STRING, "bootfile_name" }, 136 1.1 pooka { 68, IPV4 | ARRAY, "mobile_ip_home_agent" }, 137 1.1 pooka { 69, IPV4 | ARRAY, "smtp_server" }, 138 1.1 pooka { 70, IPV4 | ARRAY, "pop_server" }, 139 1.1 pooka { 71, IPV4 | ARRAY, "nntp_server" }, 140 1.1 pooka { 72, IPV4 | ARRAY, "www_server" }, 141 1.1 pooka { 73, IPV4 | ARRAY, "finger_server" }, 142 1.1 pooka { 74, IPV4 | ARRAY, "irc_server" }, 143 1.1 pooka { 75, IPV4 | ARRAY, "streettalk_server" }, 144 1.1 pooka { 76, IPV4 | ARRAY, "streettalk_directory_assistance_server" }, 145 1.1 pooka { 77, STRING, "user_class" }, 146 1.1 pooka { 81, STRING | RFC3397, "fqdn_name" }, 147 1.1 pooka { 85, IPV4 | ARRAY, "nds_servers" }, 148 1.1 pooka { 86, STRING, "nds_tree_name" }, 149 1.1 pooka { 87, STRING, "nds_context" }, 150 1.1 pooka { 88, STRING | RFC3397, "bcms_controller_names" }, 151 1.1 pooka { 89, IPV4 | ARRAY, "bcms_controller_address" }, 152 1.1 pooka { 91, UINT32, "client_last_transaction_time" }, 153 1.1 pooka { 92, IPV4 | ARRAY, "associated_ip" }, 154 1.1 pooka { 98, STRING, "uap_servers" }, 155 1.1 pooka { 112, IPV4 | ARRAY, "netinfo_server_address" }, 156 1.1 pooka { 113, STRING, "netinfo_server_tag" }, 157 1.1 pooka { 114, STRING, "default_url" }, 158 1.1 pooka { 118, IPV4, "subnet_selection" }, 159 1.1 pooka { 119, STRING | RFC3397, "domain_search" }, 160 1.1 pooka { 0, 0, NULL } 161 1.1 pooka }; 162 1.1 pooka 163 1.1 pooka static int 164 1.1 pooka valid_length(uint8_t option, int dl, int *type) 165 1.1 pooka { 166 1.1 pooka const struct dhcp_opt *opt; 167 1.1 pooka ssize_t sz; 168 1.1 pooka 169 1.1 pooka if (dl == 0) 170 1.1 pooka return -1; 171 1.1 pooka 172 1.1 pooka for (opt = dhcp_opts; opt->option; opt++) { 173 1.1 pooka if (opt->option != option) 174 1.1 pooka continue; 175 1.1 pooka 176 1.1 pooka if (type) 177 1.1 pooka *type = opt->type; 178 1.1 pooka 179 1.1 pooka if (opt->type == 0 || 180 1.1 pooka opt->type & STRING || 181 1.1 pooka opt->type & RFC3442) 182 1.1 pooka return 0; 183 1.1 pooka 184 1.1 pooka sz = 0; 185 1.1 pooka if (opt->type & UINT32 || opt->type & IPV4) 186 1.1 pooka sz = sizeof(uint32_t); 187 1.1 pooka if (opt->type & UINT16) 188 1.1 pooka sz = sizeof(uint16_t); 189 1.1 pooka if (opt->type & UINT8) 190 1.1 pooka sz = sizeof(uint8_t); 191 1.1 pooka if (opt->type & IPV4 || opt->type & ARRAY) 192 1.1 pooka return dl % sz; 193 1.1 pooka return (dl == sz ? 0 : -1); 194 1.1 pooka } 195 1.1 pooka 196 1.1 pooka /* unknown option, so let it pass */ 197 1.1 pooka return 0; 198 1.1 pooka } 199 1.1 pooka 200 1.1 pooka #ifdef DEBUG_MEMORY 201 1.1 pooka static void 202 1.1 pooka free_option_buffer(void) 203 1.1 pooka { 204 1.1 pooka free(opt_buffer); 205 1.1 pooka } 206 1.1 pooka #endif 207 1.1 pooka 208 1.1 pooka #define get_option_raw(dhcp, opt) get_option(dhcp, opt, NULL, NULL) 209 1.1 pooka static const uint8_t * 210 1.1 pooka get_option(const struct dhcp_message *dhcp, uint8_t opt, int *len, int *type) 211 1.1 pooka { 212 1.1 pooka const uint8_t *p = dhcp->options; 213 1.1 pooka const uint8_t *e = p + sizeof(dhcp->options); 214 1.1 pooka uint8_t l, ol = 0; 215 1.1 pooka uint8_t o = 0; 216 1.1 pooka uint8_t overl = 0; 217 1.1 pooka uint8_t *bp = NULL; 218 1.1 pooka const uint8_t *op = NULL; 219 1.1 pooka int bl = 0; 220 1.1 pooka 221 1.1 pooka while (p < e) { 222 1.1 pooka o = *p++; 223 1.1 pooka if (o == opt) { 224 1.1 pooka if (op) { 225 1.1 pooka if (!opt_buffer) { 226 1.1 pooka opt_buffer = xmalloc(sizeof(*dhcp)); 227 1.1 pooka #ifdef DEBUG_MEMORY 228 1.1 pooka atexit(free_option_buffer); 229 1.1 pooka #endif 230 1.1 pooka } 231 1.1 pooka if (!bp) 232 1.1 pooka bp = opt_buffer; 233 1.1 pooka memcpy(bp, op, ol); 234 1.1 pooka bp += ol; 235 1.1 pooka } 236 1.1 pooka ol = *p; 237 1.1 pooka op = p + 1; 238 1.1 pooka bl += ol; 239 1.1 pooka } 240 1.1 pooka switch (o) { 241 1.1 pooka case DHO_PAD: 242 1.1 pooka continue; 243 1.1 pooka case DHO_END: 244 1.1 pooka if (overl & 1) { 245 1.1 pooka /* bit 1 set means parse boot file */ 246 1.1 pooka overl &= ~1; 247 1.1 pooka p = dhcp->bootfile; 248 1.1 pooka e = p + sizeof(dhcp->bootfile); 249 1.1 pooka } else if (overl & 2) { 250 1.1 pooka /* bit 2 set means parse server name */ 251 1.1 pooka overl &= ~2; 252 1.1 pooka p = dhcp->servername; 253 1.1 pooka e = p + sizeof(dhcp->servername); 254 1.1 pooka } else 255 1.1 pooka goto exit; 256 1.1 pooka break; 257 1.1 pooka case DHO_OPTIONSOVERLOADED: 258 1.1 pooka /* Ensure we only get this option once */ 259 1.1 pooka if (!overl) 260 1.1 pooka overl = p[1]; 261 1.1 pooka break; 262 1.1 pooka } 263 1.1 pooka l = *p++; 264 1.1 pooka p += l; 265 1.1 pooka } 266 1.1 pooka 267 1.1 pooka exit: 268 1.1 pooka if (valid_length(opt, bl, type) == -1) { 269 1.1 pooka errno = EINVAL; 270 1.1 pooka return NULL; 271 1.1 pooka } 272 1.1 pooka if (len) 273 1.1 pooka *len = bl; 274 1.1 pooka if (bp) { 275 1.1 pooka memcpy(bp, op, ol); 276 1.1 pooka return (const uint8_t *)opt_buffer; 277 1.1 pooka } 278 1.1 pooka if (op) 279 1.1 pooka return op; 280 1.1 pooka errno = ENOENT; 281 1.1 pooka return NULL; 282 1.1 pooka } 283 1.1 pooka 284 1.1 pooka int 285 1.1 pooka get_option_addr(struct in_addr *a, const struct dhcp_message *dhcp, 286 1.1 pooka uint8_t option) 287 1.1 pooka { 288 1.1 pooka const uint8_t *p = get_option_raw(dhcp, option); 289 1.1 pooka 290 1.1 pooka if (!p) 291 1.1 pooka return -1; 292 1.1 pooka memcpy(&a->s_addr, p, sizeof(a->s_addr)); 293 1.1 pooka return 0; 294 1.1 pooka } 295 1.1 pooka 296 1.1 pooka int 297 1.1 pooka get_option_uint32(uint32_t *i, const struct dhcp_message *dhcp, uint8_t option) 298 1.1 pooka { 299 1.1 pooka const uint8_t *p = get_option_raw(dhcp, option); 300 1.1 pooka uint32_t d; 301 1.1 pooka 302 1.1 pooka if (!p) 303 1.1 pooka return -1; 304 1.1 pooka memcpy(&d, p, sizeof(d)); 305 1.1 pooka *i = ntohl(d); 306 1.1 pooka return 0; 307 1.1 pooka } 308 1.1 pooka 309 1.1 pooka int 310 1.1 pooka get_option_uint16(uint16_t *i, const struct dhcp_message *dhcp, uint8_t option) 311 1.1 pooka { 312 1.1 pooka const uint8_t *p = get_option_raw(dhcp, option); 313 1.1 pooka uint16_t d; 314 1.1 pooka 315 1.1 pooka if (!p) 316 1.1 pooka return -1; 317 1.1 pooka memcpy(&d, p, sizeof(d)); 318 1.1 pooka *i = ntohs(d); 319 1.1 pooka return 0; 320 1.1 pooka } 321 1.1 pooka 322 1.1 pooka int 323 1.1 pooka get_option_uint8(uint8_t *i, const struct dhcp_message *dhcp, uint8_t option) 324 1.1 pooka { 325 1.1 pooka const uint8_t *p = get_option_raw(dhcp, option); 326 1.1 pooka 327 1.1 pooka if (!p) 328 1.1 pooka return -1; 329 1.1 pooka if (i) 330 1.1 pooka *i = *(p); 331 1.1 pooka return 0; 332 1.1 pooka } 333 1.1 pooka 334 1.1 pooka static struct rt * 335 1.1 pooka decode_rfc3442_rt(int dl, const uint8_t *data) 336 1.1 pooka { 337 1.1 pooka const uint8_t *p = data; 338 1.1 pooka const uint8_t *e; 339 1.1 pooka uint8_t cidr; 340 1.1 pooka size_t ocets; 341 1.1 pooka struct rt *routes = NULL; 342 1.1 pooka struct rt *rt = NULL; 343 1.1 pooka 344 1.1 pooka /* Minimum is 5 -first is CIDR and a router length of 4 */ 345 1.1 pooka if (dl < 5) 346 1.1 pooka return NULL; 347 1.1 pooka 348 1.1 pooka e = p + dl; 349 1.1 pooka while (p < e) { 350 1.1 pooka cidr = *p++; 351 1.1 pooka if (cidr > 32) { 352 1.1 pooka free_routes(routes); 353 1.1 pooka errno = EINVAL; 354 1.1 pooka return NULL; 355 1.1 pooka } 356 1.1 pooka 357 1.1 pooka if (rt) { 358 1.1 pooka rt->next = xzalloc(sizeof(*rt)); 359 1.1 pooka rt = rt->next; 360 1.1 pooka } else { 361 1.1 pooka routes = rt = xzalloc(sizeof(*routes)); 362 1.1 pooka } 363 1.1 pooka rt->next = NULL; 364 1.1 pooka 365 1.1 pooka ocets = (cidr + 7) / 8; 366 1.1 pooka /* If we have ocets then we have a destination and netmask */ 367 1.1 pooka if (ocets > 0) { 368 1.1 pooka memcpy(&rt->dest.s_addr, p, ocets); 369 1.1 pooka p += ocets; 370 1.1 pooka rt->net.s_addr = htonl(~0U << (32 - cidr)); 371 1.1 pooka } 372 1.1 pooka 373 1.1 pooka /* Finally, snag the router */ 374 1.1 pooka memcpy(&rt->gate.s_addr, p, 4); 375 1.1 pooka p += 4; 376 1.1 pooka } 377 1.1 pooka return routes; 378 1.1 pooka } 379 1.1 pooka 380 1.1 pooka 381 1.1 pooka /* This calculates the netmask that we should use for static routes. 382 1.1 pooka * This IS different from the calculation used to calculate the netmask 383 1.1 pooka * for an interface address. */ 384 1.1 pooka static uint32_t 385 1.1 pooka route_netmask(uint32_t ip_in) 386 1.1 pooka { 387 1.1 pooka /* used to be unsigned long - check if error */ 388 1.1 pooka uint32_t p = ntohl(ip_in); 389 1.1 pooka uint32_t t; 390 1.1 pooka 391 1.1 pooka if (IN_CLASSA(p)) 392 1.1 pooka t = ~IN_CLASSA_NET; 393 1.1 pooka else { 394 1.1 pooka if (IN_CLASSB(p)) 395 1.1 pooka t = ~IN_CLASSB_NET; 396 1.1 pooka else { 397 1.1 pooka if (IN_CLASSC(p)) 398 1.1 pooka t = ~IN_CLASSC_NET; 399 1.1 pooka else 400 1.1 pooka t = 0; 401 1.1 pooka } 402 1.1 pooka } 403 1.1 pooka 404 1.1 pooka while (t & p) 405 1.1 pooka t >>= 1; 406 1.1 pooka 407 1.1 pooka return (htonl(~t)); 408 1.1 pooka } 409 1.1 pooka 410 1.1 pooka /* We need to obey routing options. 411 1.1 pooka * If we have a CSR then we only use that. 412 1.1 pooka * Otherwise we add static routes and then routers. */ 413 1.1 pooka struct rt * 414 1.1 pooka get_option_routes(const struct dhcp_message *dhcp, 415 1.1 pooka const char *ifname, int *opts) 416 1.1 pooka { 417 1.1 pooka const uint8_t *p; 418 1.1 pooka const uint8_t *e; 419 1.1 pooka struct rt *routes = NULL; 420 1.1 pooka struct rt *route = NULL; 421 1.1 pooka int len; 422 1.1 pooka 423 1.1 pooka /* If we have CSR's then we MUST use these only */ 424 1.1 pooka p = get_option(dhcp, DHO_CSR, &len, NULL); 425 1.1 pooka /* Check for crappy MS option */ 426 1.1 pooka if (!p) 427 1.1 pooka p = get_option(dhcp, DHO_MSCSR, &len, NULL); 428 1.1 pooka if (p) { 429 1.1 pooka routes = decode_rfc3442_rt(len, p); 430 1.1 pooka if (routes && !(*opts & DHCPCD_CSR_WARNED)) { 431 1.1 pooka *opts |= DHCPCD_CSR_WARNED; 432 1.1 pooka return routes; 433 1.1 pooka } 434 1.1 pooka } 435 1.1 pooka 436 1.1 pooka /* OK, get our static routes first. */ 437 1.1 pooka p = get_option(dhcp, DHO_STATICROUTE, &len, NULL); 438 1.1 pooka if (p) { 439 1.1 pooka e = p + len; 440 1.1 pooka while (p < e) { 441 1.1 pooka if (route) { 442 1.1 pooka route->next = xmalloc(sizeof(*route)); 443 1.1 pooka route = route->next; 444 1.1 pooka } else 445 1.1 pooka routes = route = xmalloc(sizeof(*routes)); 446 1.1 pooka route->next = NULL; 447 1.1 pooka memcpy(&route->dest.s_addr, p, 4); 448 1.1 pooka p += 4; 449 1.1 pooka memcpy(&route->gate.s_addr, p, 4); 450 1.1 pooka p += 4; 451 1.1 pooka route->net.s_addr = route_netmask(route->dest.s_addr); 452 1.1 pooka } 453 1.1 pooka } 454 1.1 pooka 455 1.1 pooka /* Now grab our routers */ 456 1.1 pooka p = get_option(dhcp, DHO_ROUTER, &len, NULL); 457 1.1 pooka if (p) { 458 1.1 pooka e = p + len; 459 1.1 pooka while (p < e) { 460 1.1 pooka if (route) { 461 1.1 pooka route->next = xzalloc(sizeof(*route)); 462 1.1 pooka route = route->next; 463 1.1 pooka } else 464 1.1 pooka routes = route = xzalloc(sizeof(*route)); 465 1.1 pooka memcpy(&route->gate.s_addr, p, 4); 466 1.1 pooka p += 4; 467 1.1 pooka } 468 1.1 pooka } 469 1.1 pooka 470 1.1 pooka return routes; 471 1.1 pooka } 472 1.1 pooka 473 1.1 pooka static size_t 474 1.1 pooka encode_rfc1035(const char *src, uint8_t *dst) 475 1.1 pooka { 476 1.1 pooka uint8_t *p = dst; 477 1.1 pooka uint8_t *lp = p++; 478 1.1 pooka 479 1.1 pooka if (*src == '\0') 480 1.1 pooka return 0; 481 1.1 pooka for (; *src; src++) { 482 1.1 pooka if (*src == '\0') 483 1.1 pooka break; 484 1.1 pooka if (*src == '.') { 485 1.1 pooka /* Skip the trailing . */ 486 1.1 pooka if (src[1] == '\0') 487 1.1 pooka break; 488 1.1 pooka *lp = p - lp - 1; 489 1.1 pooka if (*lp == '\0') 490 1.1 pooka return p - dst; 491 1.1 pooka lp = p++; 492 1.1 pooka } else 493 1.1 pooka *p++ = (uint8_t)*src; 494 1.1 pooka } 495 1.1 pooka *lp = p - lp - 1; 496 1.1 pooka *p++ = '\0'; 497 1.1 pooka return p - dst; 498 1.1 pooka } 499 1.1 pooka 500 1.1 pooka #define PUTADDR(_type, _val) \ 501 1.1 pooka { \ 502 1.1 pooka *p++ = _type; \ 503 1.1 pooka *p++ = 4; \ 504 1.1 pooka memcpy(p, &_val.s_addr, 4); \ 505 1.1 pooka p += 4; \ 506 1.1 pooka } 507 1.1 pooka 508 1.1 pooka int 509 1.1 pooka dhcp_message_add_addr(struct dhcp_message *dhcp, 510 1.1 pooka uint8_t type, struct in_addr addr) 511 1.1 pooka { 512 1.1 pooka uint8_t *p; 513 1.1 pooka size_t len; 514 1.1 pooka 515 1.1 pooka p = dhcp->options; 516 1.1 pooka while (*p != DHO_END) { 517 1.1 pooka p++; 518 1.1 pooka p += *p + 1; 519 1.1 pooka } 520 1.1 pooka 521 1.1 pooka len = p - (uint8_t *)dhcp; 522 1.1 pooka if (len + 6 > sizeof(*dhcp)) { 523 1.1 pooka errno = ENOMEM; 524 1.1 pooka return -1; 525 1.1 pooka } 526 1.1 pooka 527 1.1 pooka PUTADDR(type, addr); 528 1.1 pooka *p = DHO_END; 529 1.1 pooka return 0; 530 1.1 pooka } 531 1.1 pooka 532 1.1 pooka ssize_t 533 1.1 pooka make_message(struct dhcp_message **message, 534 1.1 pooka const struct interface *iface, 535 1.1 pooka uint8_t type) 536 1.1 pooka { 537 1.1 pooka struct dhcp_message *dhcp; 538 1.1 pooka uint8_t *m, *lp, *p; 539 1.1 pooka uint8_t *n_params = NULL; 540 1.1 pooka time_t up = uptime() - iface->start_uptime; 541 1.1 pooka uint32_t ul; 542 1.1 pooka uint16_t sz; 543 1.1 pooka size_t len; 544 1.1 pooka const char *hp; 545 1.1 pooka const struct dhcp_opt *opt; 546 1.1 pooka const struct if_options *ifo = iface->state->options; 547 1.1 pooka const struct dhcp_lease *lease = &iface->state->lease; 548 1.1 pooka 549 1.1 pooka dhcp = xzalloc(sizeof (*dhcp)); 550 1.1 pooka m = (uint8_t *)dhcp; 551 1.1 pooka p = dhcp->options; 552 1.1 pooka 553 1.1 pooka if ((type == DHCP_INFORM || type == DHCP_RELEASE || 554 1.1 pooka (type == DHCP_REQUEST && 555 1.1 pooka iface->net.s_addr == lease->net.s_addr && 556 1.1 pooka (iface->state->new == NULL || 557 1.1 pooka iface->state->new->cookie == htonl(MAGIC_COOKIE))))) 558 1.1 pooka { 559 1.1 pooka dhcp->ciaddr = iface->addr.s_addr; 560 1.1 pooka /* In-case we haven't actually configured the address yet */ 561 1.1 pooka if (type == DHCP_INFORM && iface->addr.s_addr == 0) 562 1.1 pooka dhcp->ciaddr = lease->addr.s_addr; 563 1.1 pooka } 564 1.1 pooka 565 1.1 pooka dhcp->op = DHCP_BOOTREQUEST; 566 1.1 pooka dhcp->hwtype = iface->family; 567 1.1 pooka switch (iface->family) { 568 1.1 pooka case ARPHRD_ETHER: 569 1.1 pooka case ARPHRD_IEEE802: 570 1.1 pooka dhcp->hwlen = iface->hwlen; 571 1.1 pooka memcpy(&dhcp->chaddr, &iface->hwaddr, iface->hwlen); 572 1.1 pooka break; 573 1.1 pooka } 574 1.1 pooka 575 1.1 pooka if (ifo->options & DHCPCD_BROADCAST && 576 1.1 pooka dhcp->ciaddr == 0 && 577 1.1 pooka type != DHCP_DECLINE && 578 1.1 pooka type != DHCP_RELEASE) 579 1.1 pooka dhcp->flags = htons(BROADCAST_FLAG); 580 1.1 pooka 581 1.1 pooka if (type != DHCP_DECLINE && type != DHCP_RELEASE) { 582 1.1 pooka if (up < 0 || up > (time_t)UINT16_MAX) 583 1.1 pooka dhcp->secs = htons((uint16_t)UINT16_MAX); 584 1.1 pooka else 585 1.1 pooka dhcp->secs = htons(up); 586 1.1 pooka } 587 1.1 pooka dhcp->xid = iface->state->xid; 588 1.1 pooka dhcp->cookie = htonl(MAGIC_COOKIE); 589 1.1 pooka 590 1.1 pooka *p++ = DHO_MESSAGETYPE; 591 1.1 pooka *p++ = 1; 592 1.1 pooka *p++ = type; 593 1.1 pooka 594 1.1 pooka if (iface->clientid) { 595 1.1 pooka *p++ = DHO_CLIENTID; 596 1.1 pooka memcpy(p, iface->clientid, iface->clientid[0] + 1); 597 1.1 pooka p += iface->clientid[0] + 1; 598 1.1 pooka } 599 1.1 pooka 600 1.1 pooka if (lease->addr.s_addr && lease->cookie == htonl(MAGIC_COOKIE)) { 601 1.1 pooka if (type == DHCP_DECLINE || 602 1.1 pooka (type == DHCP_REQUEST && 603 1.1 pooka lease->addr.s_addr != iface->addr.s_addr)) 604 1.1 pooka { 605 1.1 pooka PUTADDR(DHO_IPADDRESS, lease->addr); 606 1.1 pooka if (lease->server.s_addr) 607 1.1 pooka PUTADDR(DHO_SERVERID, lease->server); 608 1.1 pooka } 609 1.1 pooka 610 1.1 pooka if (type == DHCP_RELEASE) { 611 1.1 pooka if (lease->server.s_addr) 612 1.1 pooka PUTADDR(DHO_SERVERID, lease->server); 613 1.1 pooka } 614 1.1 pooka } 615 1.1 pooka 616 1.1 pooka if (type == DHCP_DECLINE) { 617 1.1 pooka *p++ = DHO_MESSAGE; 618 1.1 pooka len = strlen(DAD); 619 1.1 pooka *p++ = len; 620 1.1 pooka memcpy(p, DAD, len); 621 1.1 pooka p += len; 622 1.1 pooka } 623 1.1 pooka 624 1.1 pooka if (type == DHCP_DISCOVER && ifo->options & DHCPCD_REQUEST) 625 1.1 pooka PUTADDR(DHO_IPADDRESS, ifo->req_addr); 626 1.1 pooka 627 1.1 pooka if (type == DHCP_DISCOVER || 628 1.1 pooka type == DHCP_INFORM || 629 1.1 pooka type == DHCP_REQUEST) 630 1.1 pooka { 631 1.1 pooka *p++ = DHO_MAXMESSAGESIZE; 632 1.1 pooka *p++ = 2; 633 1.1 pooka sz = get_mtu(iface->name); 634 1.1 pooka if (sz < MTU_MIN) { 635 1.1 pooka if (set_mtu(iface->name, MTU_MIN) == 0) 636 1.1 pooka sz = MTU_MIN; 637 1.1 pooka } else if (sz > MTU_MAX) { 638 1.1 pooka /* Even though our MTU could be greater than 639 1.1 pooka * MTU_MAX (1500) dhcpcd does not presently 640 1.1 pooka * handle DHCP packets any bigger. */ 641 1.1 pooka sz = MTU_MAX; 642 1.1 pooka } 643 1.1 pooka sz = htons(sz); 644 1.1 pooka memcpy(p, &sz, 2); 645 1.1 pooka p += 2; 646 1.1 pooka 647 1.1 pooka if (ifo->userclass[0]) { 648 1.1 pooka *p++ = DHO_USERCLASS; 649 1.1 pooka memcpy(p, ifo->userclass, ifo->userclass[0] + 1); 650 1.1 pooka p += ifo->userclass[0] + 1; 651 1.1 pooka } 652 1.1 pooka 653 1.1 pooka if (ifo->vendorclassid[0]) { 654 1.1 pooka *p++ = DHO_VENDORCLASSID; 655 1.1 pooka memcpy(p, ifo->vendorclassid, 656 1.1 pooka ifo->vendorclassid[0] + 1); 657 1.1 pooka p += ifo->vendorclassid[0] + 1; 658 1.1 pooka } 659 1.1 pooka 660 1.1 pooka 661 1.1 pooka if (type != DHCP_INFORM) { 662 1.1 pooka if (ifo->leasetime != 0) { 663 1.1 pooka *p++ = DHO_LEASETIME; 664 1.1 pooka *p++ = 4; 665 1.1 pooka ul = htonl(ifo->leasetime); 666 1.1 pooka memcpy(p, &ul, 4); 667 1.1 pooka p += 4; 668 1.1 pooka } 669 1.1 pooka } 670 1.1 pooka 671 1.1 pooka /* Regardless of RFC2132, we should always send a hostname 672 1.1 pooka * upto the first dot (the short hostname) as otherwise 673 1.1 pooka * confuses some DHCP servers when updating DNS. 674 1.1 pooka * The FQDN option should be used if a FQDN is required. */ 675 1.1 pooka if (ifo->options & DHCPCD_HOSTNAME && ifo->hostname[0]) { 676 1.1 pooka *p++ = DHO_HOSTNAME; 677 1.1 pooka hp = strchr(ifo->hostname, '.'); 678 1.1 pooka if (hp) 679 1.1 pooka len = hp - ifo->hostname; 680 1.1 pooka else 681 1.1 pooka len = strlen(ifo->hostname); 682 1.1 pooka *p++ = len; 683 1.1 pooka memcpy(p, ifo->hostname, len); 684 1.1 pooka p += len; 685 1.1 pooka } 686 1.1 pooka if (ifo->fqdn != FQDN_DISABLE && ifo->hostname[0]) { 687 1.1 pooka /* IETF DHC-FQDN option (81), RFC4702 */ 688 1.1 pooka *p++ = DHO_FQDN; 689 1.1 pooka lp = p; 690 1.1 pooka *p++ = 3; 691 1.1 pooka /* 692 1.1 pooka * Flags: 0000NEOS 693 1.1 pooka * S: 1 => Client requests Server to update 694 1.1 pooka * a RR in DNS as well as PTR 695 1.1 pooka * O: 1 => Server indicates to client that 696 1.1 pooka * DNS has been updated 697 1.1 pooka * E: 1 => Name data is DNS format 698 1.1 pooka * N: 1 => Client requests Server to not 699 1.1 pooka * update DNS 700 1.1 pooka */ 701 1.1 pooka *p++ = (ifo->fqdn & 0x09) | 0x04; 702 1.1 pooka *p++ = 0; /* from server for PTR RR */ 703 1.1 pooka *p++ = 0; /* from server for A RR if S=1 */ 704 1.1 pooka ul = encode_rfc1035(ifo->hostname, p); 705 1.1 pooka *lp += ul; 706 1.1 pooka p += ul; 707 1.1 pooka } 708 1.1 pooka 709 1.1 pooka /* vendor is already encoded correctly, so just add it */ 710 1.1 pooka if (ifo->vendor[0]) { 711 1.1 pooka *p++ = DHO_VENDOR; 712 1.1 pooka memcpy(p, ifo->vendor, ifo->vendor[0] + 1); 713 1.1 pooka p += ifo->vendor[0] + 1; 714 1.1 pooka } 715 1.1 pooka 716 1.1 pooka *p++ = DHO_PARAMETERREQUESTLIST; 717 1.1 pooka n_params = p; 718 1.1 pooka *p++ = 0; 719 1.1 pooka for (opt = dhcp_opts; opt->option; opt++) { 720 1.1 pooka if (!(opt->type & REQUEST || 721 1.1 pooka has_option_mask(ifo->requestmask, opt->option))) 722 1.1 pooka continue; 723 1.1 pooka if (type == DHCP_INFORM && 724 1.1 pooka (opt->option == DHO_RENEWALTIME || 725 1.1 pooka opt->option == DHO_REBINDTIME)) 726 1.1 pooka continue; 727 1.1 pooka *p++ = opt->option; 728 1.1 pooka } 729 1.1 pooka *n_params = p - n_params - 1; 730 1.1 pooka } 731 1.1 pooka *p++ = DHO_END; 732 1.1 pooka 733 1.3 andvar #ifdef BOOTP_MESSAGE_LENGTH_MIN 734 1.1 pooka /* Some crappy DHCP servers think they have to obey the BOOTP minimum 735 1.1 pooka * message length. 736 1.1 pooka * They are wrong, but we should still cater for them. */ 737 1.3 andvar while (p - m < BOOTP_MESSAGE_LENGTH_MIN) 738 1.1 pooka *p++ = DHO_PAD; 739 1.1 pooka #endif 740 1.1 pooka 741 1.1 pooka *message = dhcp; 742 1.1 pooka return p - m; 743 1.1 pooka } 744 1.1 pooka 745 1.1 pooka void 746 1.1 pooka get_lease(struct dhcp_lease *lease, const struct dhcp_message *dhcp) 747 1.1 pooka { 748 1.1 pooka struct timeval now; 749 1.1 pooka 750 1.1 pooka lease->cookie = dhcp->cookie; 751 1.1 pooka /* BOOTP does not set yiaddr for replies when ciaddr is set. */ 752 1.1 pooka if (dhcp->yiaddr) 753 1.1 pooka lease->addr.s_addr = dhcp->yiaddr; 754 1.1 pooka else 755 1.1 pooka lease->addr.s_addr = dhcp->ciaddr; 756 1.1 pooka if (get_option_addr(&lease->net, dhcp, DHO_SUBNETMASK) == -1) 757 1.1 pooka lease->net.s_addr = get_netmask(lease->addr.s_addr); 758 1.1 pooka if (get_option_addr(&lease->brd, dhcp, DHO_BROADCAST) == -1) 759 1.1 pooka lease->brd.s_addr = lease->addr.s_addr | ~lease->net.s_addr; 760 1.1 pooka if (get_option_uint32(&lease->leasetime, dhcp, DHO_LEASETIME) == 0) { 761 1.1 pooka /* Ensure that we can use the lease */ 762 1.1 pooka get_monotonic(&now); 763 1.1 pooka if (now.tv_sec + (time_t)lease->leasetime < now.tv_sec) 764 1.1 pooka lease->leasetime = ~0U; /* Infinite lease */ 765 1.1 pooka } else 766 1.1 pooka lease->leasetime = ~0U; /* Default to infinite lease */ 767 1.1 pooka if (get_option_uint32(&lease->renewaltime, dhcp, DHO_RENEWALTIME) != 0) 768 1.1 pooka lease->renewaltime = 0; 769 1.1 pooka if (get_option_uint32(&lease->rebindtime, dhcp, DHO_REBINDTIME) != 0) 770 1.1 pooka lease->rebindtime = 0; 771 1.1 pooka if (get_option_addr(&lease->server, dhcp, DHO_SERVERID) != 0) 772 1.1 pooka lease->server.s_addr = INADDR_ANY; 773 1.1 pooka } 774