1f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project/* 2f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * dhcpcd - DHCP client daemon 3a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt * Copyright (c) 2006-2012 Roy Marples <roy@marples.name> 4f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * All rights reserved 5f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 6f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * Redistribution and use in source and binary forms, with or without 7f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * modification, are permitted provided that the following conditions 8f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * are met: 9f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * 1. Redistributions of source code must retain the above copyright 10f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * notice, this list of conditions and the following disclaimer. 11f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright 12f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * notice, this list of conditions and the following disclaimer in the 13f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * documentation and/or other materials provided with the distribution. 14f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * 15f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * SUCH DAMAGE. 26f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project */ 27f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 28f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <ctype.h> 29f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <errno.h> 30f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <fcntl.h> 31f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <stdlib.h> 32f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <string.h> 33e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <syslog.h> 34f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <unistd.h> 35f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 36f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include "config.h" 37f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include "common.h" 38f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include "dhcp.h" 39f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 40f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define REQUEST (1 << 0) 41f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define UINT8 (1 << 1) 42f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define UINT16 (1 << 2) 43f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define SINT16 (1 << 3) 44f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define UINT32 (1 << 4) 45f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define SINT32 (1 << 5) 46f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define IPV4 (1 << 6) 47f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define STRING (1 << 7) 48f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define PAIR (1 << 8) 49f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define ARRAY (1 << 9) 50f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define RFC3361 (1 << 10) 51f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define RFC3397 (1 << 11) 52f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define RFC3442 (1 << 12) 53a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt#define RFC5969 (1 << 13) 54f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 55f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define IPV4R IPV4 | REQUEST 56f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 57938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt#define DAD "Duplicate address detected" 58938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt 59f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project/* Our aggregate option buffer. 60f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * We ONLY use this when options are split, which for most purposes is 61f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * practically never. See RFC3396 for details. */ 62e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic uint8_t *opt_buffer; 63f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 64f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstruct dhcp_opt { 65f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint8_t option; 66f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int type; 67f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project const char *var; 68f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}; 69f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 70f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic const struct dhcp_opt const dhcp_opts[] = { 71f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 1, IPV4 | REQUEST, "subnet_mask" }, 72e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* RFC 3442 states that the CSR has to come before all other 73e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * routes. For completeness, we also specify static routes, 74e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * then routers. */ 75e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt { 121, RFC3442, "classless_static_routes" }, 76938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt { 249, RFC3442, "ms_classless_static_routes" }, 77938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt { 33, IPV4 | ARRAY | REQUEST, "static_routes" }, 78f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 3, IPV4 | ARRAY | REQUEST, "routers" }, 79938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt { 2, UINT32, "time_offset" }, 80f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 4, IPV4 | ARRAY, "time_servers" }, 81f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 5, IPV4 | ARRAY, "ien116_name_servers" }, 82ddaa48f57b54b2862b3e6dcf18a44c9647f3baaatk.mun /* Explicitly include DNS in the list of parameters requested in the DNS request. 83ddaa48f57b54b2862b3e6dcf18a44c9647f3baaatk.mun * Without this some DHCP servers may skip the DNS entries in the DHCP replies.*/ 84ddaa48f57b54b2862b3e6dcf18a44c9647f3baaatk.mun { 6, IPV4 | ARRAY | REQUEST, "domain_name_servers" }, 85f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 7, IPV4 | ARRAY, "log_servers" }, 86f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 8, IPV4 | ARRAY, "cookie_servers" }, 87f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 9, IPV4 | ARRAY, "lpr_servers" }, 88f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 10, IPV4 | ARRAY, "impress_servers" }, 89f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 11, IPV4 | ARRAY, "resource_location_servers" }, 90f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 12, STRING, "host_name" }, 91f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 13, UINT16, "boot_size" }, 92f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 14, STRING, "merit_dump" }, 93ddaa48f57b54b2862b3e6dcf18a44c9647f3baaatk.mun /* Explicitly include DNS in the list of parameters requested in the DNS request. 94ddaa48f57b54b2862b3e6dcf18a44c9647f3baaatk.mun * Without this some DHCP servers may skip the DNS entries in the DHCP replies.*/ 95ddaa48f57b54b2862b3e6dcf18a44c9647f3baaatk.mun { 15, STRING | REQUEST, "domain_name" }, 96f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 16, IPV4, "swap_server" }, 97f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 17, STRING, "root_path" }, 98f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 18, STRING, "extensions_path" }, 99f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 19, UINT8, "ip_forwarding" }, 100f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 20, UINT8, "non_local_source_routing" }, 101f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 21, IPV4 | ARRAY, "policy_filter" }, 102f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 22, SINT16, "max_dgram_reassembly" }, 103f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 23, UINT16, "default_ip_ttl" }, 104f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 24, UINT32, "path_mtu_aging_timeout" }, 105f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 25, UINT16 | ARRAY, "path_mtu_plateau_table" }, 106f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 26, UINT16, "interface_mtu" }, 107f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 27, UINT8, "all_subnets_local" }, 108f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 28, IPV4 | REQUEST, "broadcast_address" }, 109f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 29, UINT8, "perform_mask_discovery" }, 110f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 30, UINT8, "mask_supplier" }, 111f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 31, UINT8, "router_discovery" }, 112f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 32, IPV4, "router_solicitation_address" }, 113f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 34, UINT8, "trailer_encapsulation" }, 114f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 35, UINT32, "arp_cache_timeout" }, 115f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 36, UINT16, "ieee802_3_encapsulation" }, 116f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 37, UINT8, "default_tcp_ttl" }, 117f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 38, UINT32, "tcp_keepalive_interval" }, 118f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 39, UINT8, "tcp_keepalive_garbage" }, 119f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 40, STRING, "nis_domain" }, 120f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 41, IPV4 | ARRAY, "nis_servers" }, 121f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 42, IPV4 | ARRAY, "ntp_servers" }, 122f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 43, STRING, "vendor_encapsulated_options" }, 123f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 44, IPV4 | ARRAY, "netbios_name_servers" }, 124f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 45, IPV4, "netbios_dd_server" }, 125f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 46, UINT8, "netbios_node_type" }, 126f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 47, STRING, "netbios_scope" }, 127f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 48, IPV4 | ARRAY, "font_servers" }, 128f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 49, IPV4 | ARRAY, "x_display_manager" }, 129f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 50, IPV4, "dhcp_requested_address" }, 130f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 51, UINT32 | REQUEST, "dhcp_lease_time" }, 131f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 52, UINT8, "dhcp_option_overload" }, 132f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 53, UINT8, "dhcp_message_type" }, 133f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 54, IPV4, "dhcp_server_identifier" }, 134f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 55, UINT8 | ARRAY, "dhcp_parameter_request_list" }, 135f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 56, STRING, "dhcp_message" }, 136f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 57, UINT16, "dhcp_max_message_size" }, 137f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 58, UINT32 | REQUEST, "dhcp_renewal_time" }, 138f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 59, UINT32 | REQUEST, "dhcp_rebinding_time" }, 139f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 64, STRING, "nisplus_domain" }, 140f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 65, IPV4 | ARRAY, "nisplus_servers" }, 141f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 66, STRING, "tftp_server_name" }, 142f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 67, STRING, "bootfile_name" }, 143f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 68, IPV4 | ARRAY, "mobile_ip_home_agent" }, 144f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 69, IPV4 | ARRAY, "smtp_server" }, 145f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 70, IPV4 | ARRAY, "pop_server" }, 146f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 71, IPV4 | ARRAY, "nntp_server" }, 147f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 72, IPV4 | ARRAY, "www_server" }, 148f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 73, IPV4 | ARRAY, "finger_server" }, 149f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 74, IPV4 | ARRAY, "irc_server" }, 150f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 75, IPV4 | ARRAY, "streettalk_server" }, 151f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 76, IPV4 | ARRAY, "streettalk_directory_assistance_server" }, 152f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 77, STRING, "user_class" }, 153f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 81, STRING | RFC3397, "fqdn_name" }, 154f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 85, IPV4 | ARRAY, "nds_servers" }, 155f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 86, STRING, "nds_tree_name" }, 156f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 87, STRING, "nds_context" }, 157f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 88, STRING | RFC3397, "bcms_controller_names" }, 158f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 89, IPV4 | ARRAY, "bcms_controller_address" }, 159f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 91, UINT32, "client_last_transaction_time" }, 160f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 92, IPV4 | ARRAY, "associated_ip" }, 161f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 98, STRING, "uap_servers" }, 162f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 112, IPV4 | ARRAY, "netinfo_server_address" }, 163f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 113, STRING, "netinfo_server_tag" }, 164f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 114, STRING, "default_url" }, 165f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 118, IPV4, "subnet_selection" }, 166f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 119, STRING | RFC3397, "domain_search" }, 167a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt { 120, STRING | RFC3361, "sip_server" }, 168a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt { 212, RFC5969, "sixrd" }, 169f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 0, 0, NULL } 170f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}; 171f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 172e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic const char *if_params[] = { 173e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt "interface", 174e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt "reason", 175e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt "pid", 176e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt "ifmetric", 177e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt "ifwireless", 178e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt "ifflags", 179e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt "profile", 180e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt "interface_order", 181e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt NULL 182e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}; 183e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 184e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic const char *dhcp_params[] = { 185e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt "ip_address", 186e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt "subnet_cidr", 187e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt "network_number", 188e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt "ssid", 189e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt "filename", 190e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt "server_name", 191e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt NULL 192e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}; 193e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 194f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectvoid 195f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectprint_options(void) 196f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 197f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project const struct dhcp_opt *opt; 198e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt const char **p; 199e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 200e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (p = if_params; *p; p++) 201e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt printf(" - %s\n", *p); 202e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 203e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (p = dhcp_params; *p; p++) 204e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt printf(" %s\n", *p); 205f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 206f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project for (opt = dhcp_opts; opt->option; opt++) 207f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (opt->var) 208f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project printf("%03d %s\n", opt->option, opt->var); 209f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 210f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 211e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtint make_option_mask(uint8_t *mask, const char *opts, int add) 212f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 213e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt char *token, *o, *p, *t; 214f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project const struct dhcp_opt *opt; 215f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int match, n; 216f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 217e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt o = p = xstrdup(opts); 218f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project while ((token = strsep(&p, ", "))) { 219f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (*token == '\0') 220f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project continue; 221f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project for (opt = dhcp_opts; opt->option; opt++) { 222f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (!opt->var) 223f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project continue; 224f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project match = 0; 225f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (strcmp(opt->var, token) == 0) 226f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project match = 1; 227f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project else { 228f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project errno = 0; 229f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project n = strtol(token, &t, 0); 230f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (errno == 0 && !*t) 231f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (opt->option == n) 232f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project match = 1; 233f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 234e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (match) { 235e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (add == 2 && !(opt->type & IPV4)) { 236e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(o); 237e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt errno = EINVAL; 238e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return -1; 239e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 240e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (add == 1 || add == 2) 241f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project add_option_mask(mask, 242e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt opt->option); 243f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project else 244f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project del_option_mask(mask, 245e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt opt->option); 246f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project break; 247f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 248f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 249f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (!opt->option) { 250e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(o); 251f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project errno = ENOENT; 252f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 253f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 254f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 255e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(o); 256f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 257f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 258f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 259f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic int 260f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectvalid_length(uint8_t option, int dl, int *type) 261f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 262f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project const struct dhcp_opt *opt; 263f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ssize_t sz; 264f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 265f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (dl == 0) 266f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 267f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 268f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project for (opt = dhcp_opts; opt->option; opt++) { 269f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (opt->option != option) 270f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project continue; 271f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 272f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (type) 273f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *type = opt->type; 274f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 275e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (opt->type == 0 || 276a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt opt->type & (STRING | RFC3442 | RFC5969)) 277f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 278f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 279f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project sz = 0; 280a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt if (opt->type & (UINT32 | IPV4)) 281f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project sz = sizeof(uint32_t); 282f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (opt->type & UINT16) 283f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project sz = sizeof(uint16_t); 284f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (opt->type & UINT8) 285f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project sz = sizeof(uint8_t); 286a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt if (opt->type & (IPV4 | ARRAY)) 287f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return dl % sz; 288f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return (dl == sz ? 0 : -1); 289f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 290f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 291f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* unknown option, so let it pass */ 292f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 293f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 294f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 295e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifdef DEBUG_MEMORY 296f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic void 297f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectfree_option_buffer(void) 298f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 299e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(opt_buffer); 300f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 301e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#endif 302f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 303f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define get_option_raw(dhcp, opt) get_option(dhcp, opt, NULL, NULL) 304f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic const uint8_t * 305f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectget_option(const struct dhcp_message *dhcp, uint8_t opt, int *len, int *type) 306f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 307f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project const uint8_t *p = dhcp->options; 308f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project const uint8_t *e = p + sizeof(dhcp->options); 309f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint8_t l, ol = 0; 310f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint8_t o = 0; 311f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint8_t overl = 0; 312f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint8_t *bp = NULL; 313f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project const uint8_t *op = NULL; 314f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int bl = 0; 315f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 316c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline /* DHCP Options are in TLV format with T and L each being a single 317c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline * byte. In general, here we have p -> T, ol=p+1 -> L, op -> V. 318c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline * We must make sure there is enough room to read both T and L. 319c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline */ 320c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline while (p + 1 < e) { 321f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project o = *p++; 322f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (o == opt) { 323f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (op) { 324e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (!opt_buffer) { 325e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt opt_buffer = xmalloc(sizeof(*dhcp)); 326e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifdef DEBUG_MEMORY 327f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project atexit(free_option_buffer); 328e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#endif 329f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 330f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (!bp) 331e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt bp = opt_buffer; 332f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memcpy(bp, op, ol); 333f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project bp += ol; 334f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 335c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline ol = (p + *p < e) ? *p : e - (p + 1); 336f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project op = p + 1; 337f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project bl += ol; 338f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 339f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project switch (o) { 340f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project case DHO_PAD: 341f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project continue; 342f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project case DHO_END: 343f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (overl & 1) { 344f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* bit 1 set means parse boot file */ 345f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project overl &= ~1; 346f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p = dhcp->bootfile; 347f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project e = p + sizeof(dhcp->bootfile); 348f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } else if (overl & 2) { 349f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* bit 2 set means parse server name */ 350f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project overl &= ~2; 351f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p = dhcp->servername; 352f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project e = p + sizeof(dhcp->servername); 353f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } else 354f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project goto exit; 355f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project break; 356f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project case DHO_OPTIONSOVERLOADED: 357f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* Ensure we only get this option once */ 358f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (!overl) 359de806dfdb6dd3b9dec5d1d23c9029fb300799cf8Lorenzo Colitti overl = 0x80 | p[1]; 360f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project break; 361f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 362f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project l = *p++; 363f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p += l; 364f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 365f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 366f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectexit: 367f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (valid_length(opt, bl, type) == -1) { 368f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project errno = EINVAL; 369f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return NULL; 370f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 371f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (len) 372f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *len = bl; 373f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (bp) { 374f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memcpy(bp, op, ol); 375e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return (const uint8_t *)opt_buffer; 376f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 377f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (op) 378f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return op; 379f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project errno = ENOENT; 380f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return NULL; 381f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 382f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 383f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectint 384938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidtget_option_addr(struct in_addr *a, const struct dhcp_message *dhcp, 385938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt uint8_t option) 386f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 387f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project const uint8_t *p = get_option_raw(dhcp, option); 388f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 389f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (!p) 390f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 391938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt memcpy(&a->s_addr, p, sizeof(a->s_addr)); 392f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 393f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 394f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 395f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectint 396f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectget_option_uint32(uint32_t *i, const struct dhcp_message *dhcp, uint8_t option) 397f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 398938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt const uint8_t *p = get_option_raw(dhcp, option); 399938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt uint32_t d; 400f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 401938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (!p) 402f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 403938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt memcpy(&d, p, sizeof(d)); 404938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt *i = ntohl(d); 405f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 406f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 407f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 408f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectint 409f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectget_option_uint16(uint16_t *i, const struct dhcp_message *dhcp, uint8_t option) 410f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 411f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project const uint8_t *p = get_option_raw(dhcp, option); 412f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint16_t d; 413f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 414f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (!p) 415f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 416f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memcpy(&d, p, sizeof(d)); 417f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *i = ntohs(d); 418f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 419f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 420f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 421f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectint 422f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectget_option_uint8(uint8_t *i, const struct dhcp_message *dhcp, uint8_t option) 423f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 424f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project const uint8_t *p = get_option_raw(dhcp, option); 425f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 426f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (!p) 427f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 428e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (i) 429e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt *i = *(p); 430f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 431f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 432f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 433f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project/* Decode an RFC3397 DNS search order option into a space 434e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * separated string. Returns length of string (including 435f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * terminating zero) or zero on error. out may be NULL 436f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * to just determine output length. */ 437a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidtssize_t 438f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectdecode_rfc3397(char *out, ssize_t len, int pl, const uint8_t *p) 439f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 440f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project const uint8_t *r, *q = p; 441f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int count = 0, l, hops; 442f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint8_t ltype; 443f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 444f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project while (q - p < pl) { 445f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project r = NULL; 446f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project hops = 0; 447f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* We check we are inside our length again incase 448f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * the data is NOT terminated correctly. */ 449f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project while ((l = *q++) && q - p < pl) { 450f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ltype = l & 0xc0; 451f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (ltype == 0x80 || ltype == 0x40) 452f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 453f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project else if (ltype == 0xc0) { /* pointer */ 454f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project l = (l & 0x3f) << 8; 455f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project l |= *q++; 456f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* save source of first jump. */ 457f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (!r) 458f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project r = q; 459f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project hops++; 460f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (hops > 255) 461f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 462f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project q = p + l; 463f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (q - p >= pl) 464f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 465f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } else { 466f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* straightforward name segment, add with '.' */ 467f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project count += l + 1; 468f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (out) { 469f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if ((ssize_t)l + 1 > len) { 470f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project errno = ENOBUFS; 471f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 472f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 473f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memcpy(out, q, l); 474f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project out += l; 475f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *out++ = '.'; 476f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project len -= l; 477f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project len--; 478f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 479f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project q += l; 480f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 481f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 482f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* change last dot to space */ 483f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (out) 484f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *(out - 1) = ' '; 485f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (r) 486f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project q = r; 487f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 488f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 489f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* change last space to zero terminator */ 490f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (out) 491f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *(out - 1) = 0; 492f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 493f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return count; 494f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 495f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 496f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic ssize_t 497f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectdecode_rfc3442(char *out, ssize_t len, int pl, const uint8_t *p) 498f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 499f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project const uint8_t *e; 500e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ssize_t b, bytes = 0, ocets; 501f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint8_t cidr; 502f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct in_addr addr; 503f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project char *o = out; 504f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 505f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* Minimum is 5 -first is CIDR and a router length of 4 */ 506f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (pl < 5) { 507f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project errno = EINVAL; 508f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 509f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 510f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 511f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project e = p + pl; 512f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project while (p < e) { 513f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project cidr = *p++; 514f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (cidr > 32) { 515f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project errno = EINVAL; 516f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 517f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 518f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ocets = (cidr + 7) / 8; 519f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (!out) { 520f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p += 4 + ocets; 521f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project bytes += ((4 * 4) * 2) + 4; 522f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project continue; 523f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 524f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if ((((4 * 4) * 2) + 4) > len) { 525f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project errno = ENOBUFS; 526f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 527f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 528f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (o != out) { 529f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *o++ = ' '; 530f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project len--; 531f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 532f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* If we have ocets then we have a destination and netmask */ 533f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (ocets > 0) { 534f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project addr.s_addr = 0; 535e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memcpy(&addr.s_addr, p, ocets); 536f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project b = snprintf(o, len, "%s/%d", inet_ntoa(addr), cidr); 537f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p += ocets; 538f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } else 539f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project b = snprintf(o, len, "0.0.0.0/0"); 540f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project o += b; 541f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project len -= b; 542f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 543f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* Finally, snag the router */ 544f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memcpy(&addr.s_addr, p, 4); 545f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p += 4; 546f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project b = snprintf(o, len, " %s", inet_ntoa(addr)); 547f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project o += b; 548f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project len -= b; 549f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 550f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 551f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (out) 552f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return o - out; 553f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return bytes; 554f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 555f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 556f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic struct rt * 557f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectdecode_rfc3442_rt(int dl, const uint8_t *data) 558f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 559f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project const uint8_t *p = data; 560f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project const uint8_t *e; 561f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint8_t cidr; 562e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt size_t ocets; 563f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct rt *routes = NULL; 564f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct rt *rt = NULL; 565f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 566f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* Minimum is 5 -first is CIDR and a router length of 4 */ 567f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (dl < 5) 568f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return NULL; 569f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 570f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project e = p + dl; 571f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project while (p < e) { 572f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project cidr = *p++; 573f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (cidr > 32) { 574f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project free_routes(routes); 575f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project errno = EINVAL; 576f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return NULL; 577f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 578f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 579f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (rt) { 580f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project rt->next = xzalloc(sizeof(*rt)); 581f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project rt = rt->next; 582f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } else { 583f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project routes = rt = xzalloc(sizeof(*routes)); 584f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 585f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project rt->next = NULL; 586f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 587f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ocets = (cidr + 7) / 8; 588f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* If we have ocets then we have a destination and netmask */ 589f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (ocets > 0) { 590e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memcpy(&rt->dest.s_addr, p, ocets); 591f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p += ocets; 592e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rt->net.s_addr = htonl(~0U << (32 - cidr)); 593f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 594f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 595f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* Finally, snag the router */ 596f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memcpy(&rt->gate.s_addr, p, 4); 597f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p += 4; 598f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 599f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return routes; 600f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 601f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 602f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic char * 603f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectdecode_rfc3361(int dl, const uint8_t *data) 604f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 605f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint8_t enc; 606f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project unsigned int l; 607f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project char *sip = NULL; 608f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct in_addr addr; 609f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project char *p; 610f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 611f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (dl < 2) { 612f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project errno = EINVAL; 613f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 614f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 615f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 616f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project enc = *data++; 617f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project dl--; 618f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project switch (enc) { 619f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project case 0: 620f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if ((l = decode_rfc3397(NULL, 0, dl, data)) > 0) { 621f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project sip = xmalloc(l); 622f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project decode_rfc3397(sip, l, dl, data); 623f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 624f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project break; 625f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project case 1: 626f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (dl == 0 || dl % 4 != 0) { 627f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project errno = EINVAL; 628f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project break; 629f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 630f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project addr.s_addr = INADDR_BROADCAST; 631f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project l = ((dl / sizeof(addr.s_addr)) * ((4 * 4) + 1)) + 1; 632f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project sip = p = xmalloc(l); 633a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt while (dl != 0) { 634f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memcpy(&addr.s_addr, data, sizeof(addr.s_addr)); 635f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project data += sizeof(addr.s_addr); 636f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p += snprintf(p, l - (p - sip), "%s ", inet_ntoa(addr)); 637a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt dl -= sizeof(addr.s_addr); 638f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 639f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *--p = '\0'; 640f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project break; 641f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project default: 642f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project errno = EINVAL; 643f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 644f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 645f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 646f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return sip; 647f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 648f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 649a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt/* Decode an RFC5969 6rd order option into a space 650a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt * separated string. Returns length of string (including 651a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt * terminating zero) or zero on error. */ 652a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidtstatic ssize_t 653a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidtdecode_rfc5969(char *out, ssize_t len, int pl, const uint8_t *p) 654a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt{ 655a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt uint8_t ipv4masklen, ipv6prefixlen; 656a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt uint8_t ipv6prefix[16]; 657a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt uint8_t br[4]; 658a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt int i; 659a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt ssize_t b, bytes = 0; 660a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt 661a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt if (pl < 22) { 662a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt errno = EINVAL; 663a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt return 0; 664a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt } 665a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt 666a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt ipv4masklen = *p++; 667a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt pl--; 668a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt ipv6prefixlen = *p++; 669a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt pl--; 670a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt 671a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt for (i = 0; i < 16; i++) { 672a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt ipv6prefix[i] = *p++; 673a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt pl--; 674a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt } 675a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt if (out) { 676a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt b= snprintf(out, len, 677a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt "%d %d " 678a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt "%02x%02x:%02x%02x:" 679a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt "%02x%02x:%02x%02x:" 680a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt "%02x%02x:%02x%02x:" 681a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt "%02x%02x:%02x%02x", 682a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt ipv4masklen, ipv6prefixlen, 683a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt ipv6prefix[0], ipv6prefix[1], ipv6prefix[2], ipv6prefix[3], 684a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt ipv6prefix[4], ipv6prefix[5], ipv6prefix[6], ipv6prefix[7], 685a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt ipv6prefix[8], ipv6prefix[9], ipv6prefix[10],ipv6prefix[11], 686a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt ipv6prefix[12],ipv6prefix[13],ipv6prefix[14], ipv6prefix[15] 687a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt ); 688a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt 689a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt len -= b; 690a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt out += b; 691a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt bytes += b; 692a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt } else { 693a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt bytes += 16 * 2 + 8 + 2 + 1 + 2; 694a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt } 695a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt 696a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt while (pl >= 4) { 697a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt br[0] = *p++; 698a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt br[1] = *p++; 699a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt br[2] = *p++; 700a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt br[3] = *p++; 701a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt pl -= 4; 702a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt 703a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt if (out) { 704a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt b= snprintf(out, len, " %d.%d.%d.%d", 705a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt br[0], br[1], br[2], br[3]); 706a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt len -= b; 707a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt out += b; 708a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt bytes += b; 709a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt } else { 710a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt bytes += (4 * 4); 711a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt } 712a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt } 713a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt 714a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt return bytes; 715a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt} 716a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt 717f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectchar * 718f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectget_option_string(const struct dhcp_message *dhcp, uint8_t option) 719f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 720f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int type = 0; 721f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int len; 722f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project const uint8_t *p; 723f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project char *s; 724f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 725f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p = get_option(dhcp, option, &len, &type); 726f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (!p || *p == '\0') 727f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return NULL; 728f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 729f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (type & RFC3397) { 730f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project type = decode_rfc3397(NULL, 0, len, p); 731f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (!type) { 732f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project errno = EINVAL; 733f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return NULL; 734f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 735f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project s = xmalloc(sizeof(char) * type); 736f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project decode_rfc3397(s, type, len, p); 737f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return s; 738f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 739f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 740f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (type & RFC3361) 741f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return decode_rfc3361(len, p); 742f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 743f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project s = xmalloc(sizeof(char) * (len + 1)); 744f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memcpy(s, p, len); 745f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project s[len] = '\0'; 746f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return s; 747f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 748f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 749f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project/* This calculates the netmask that we should use for static routes. 750f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * This IS different from the calculation used to calculate the netmask 751f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * for an interface address. */ 752f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic uint32_t 753f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectroute_netmask(uint32_t ip_in) 754f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 755f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* used to be unsigned long - check if error */ 756f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint32_t p = ntohl(ip_in); 757f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint32_t t; 758f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 759f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (IN_CLASSA(p)) 760f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project t = ~IN_CLASSA_NET; 761f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project else { 762f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (IN_CLASSB(p)) 763f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project t = ~IN_CLASSB_NET; 764f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project else { 765f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (IN_CLASSC(p)) 766f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project t = ~IN_CLASSC_NET; 767f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project else 768f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project t = 0; 769f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 770f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 771f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 772f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project while (t & p) 773f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project t >>= 1; 774f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 775f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return (htonl(~t)); 776f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 777f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 778f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project/* We need to obey routing options. 779f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * If we have a CSR then we only use that. 780f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * Otherwise we add static routes and then routers. */ 781f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstruct rt * 782e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtget_option_routes(const struct dhcp_message *dhcp, 783a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt const char *ifname, unsigned long long *opts) 784f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 785f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project const uint8_t *p; 786f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project const uint8_t *e; 787f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct rt *routes = NULL; 788f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct rt *route = NULL; 789f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int len; 790f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 791f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* If we have CSR's then we MUST use these only */ 792f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p = get_option(dhcp, DHO_CSR, &len, NULL); 793f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* Check for crappy MS option */ 794f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (!p) 795f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p = get_option(dhcp, DHO_MSCSR, &len, NULL); 796f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (p) { 797f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project routes = decode_rfc3442_rt(len, p); 798a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt if (routes) { 799a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt if (!(*opts & DHCPCD_CSR_WARNED)) { 800a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt syslog(LOG_DEBUG, 801a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt "%s: using Classless Static Routes", 802a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt ifname); 803a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt *opts |= DHCPCD_CSR_WARNED; 804a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt } 805f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return routes; 806e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 807f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 808f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 809f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* OK, get our static routes first. */ 810f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p = get_option(dhcp, DHO_STATICROUTE, &len, NULL); 811f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (p) { 812f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project e = p + len; 813f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project while (p < e) { 814f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (route) { 815f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project route->next = xmalloc(sizeof(*route)); 816f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project route = route->next; 817f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } else 818f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project routes = route = xmalloc(sizeof(*routes)); 819f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project route->next = NULL; 820f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memcpy(&route->dest.s_addr, p, 4); 821f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p += 4; 822f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memcpy(&route->gate.s_addr, p, 4); 823f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p += 4; 824f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project route->net.s_addr = route_netmask(route->dest.s_addr); 825f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 826f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 827f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 828f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* Now grab our routers */ 829f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p = get_option(dhcp, DHO_ROUTER, &len, NULL); 830f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (p) { 831f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project e = p + len; 832f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project while (p < e) { 833f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (route) { 834f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project route->next = xzalloc(sizeof(*route)); 835f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project route = route->next; 836f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } else 837f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project routes = route = xzalloc(sizeof(*route)); 838f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memcpy(&route->gate.s_addr, p, 4); 839f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p += 4; 840f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 841f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 842f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 843f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return routes; 844f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 845f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 846f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic size_t 847938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidtencode_rfc1035(const char *src, uint8_t *dst) 848f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 849f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint8_t *p = dst; 850f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint8_t *lp = p++; 851f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 852938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (*src == '\0') 853f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 854938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt for (; *src; src++) { 855938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (*src == '\0') 856f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project break; 857938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (*src == '.') { 858f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* Skip the trailing . */ 859938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (src[1] == '\0') 860f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project break; 861f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *lp = p - lp - 1; 862f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (*lp == '\0') 863f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return p - dst; 864f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project lp = p++; 865f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } else 866938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt *p++ = (uint8_t)*src; 867f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 868f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *lp = p - lp - 1; 869f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *p++ = '\0'; 870f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return p - dst; 871f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 872f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 873e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#define PUTADDR(_type, _val) \ 874e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt { \ 875e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt *p++ = _type; \ 876e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt *p++ = 4; \ 877e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memcpy(p, &_val.s_addr, 4); \ 878e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt p += 4; \ 879e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 880e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 881e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtint 882e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtdhcp_message_add_addr(struct dhcp_message *dhcp, 883e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt uint8_t type, struct in_addr addr) 884e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 885e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt uint8_t *p; 886e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt size_t len; 887e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 888e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt p = dhcp->options; 889e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt while (*p != DHO_END) { 890e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt p++; 891e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt p += *p + 1; 892e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 893e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 894e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt len = p - (uint8_t *)dhcp; 895e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (len + 6 > sizeof(*dhcp)) { 896e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt errno = ENOMEM; 897e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return -1; 898e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 899e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 900e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt PUTADDR(type, addr); 901e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt *p = DHO_END; 902e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return 0; 903938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt} 904e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 905f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectssize_t 906f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectmake_message(struct dhcp_message **message, 907e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt const struct interface *iface, 908e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt uint8_t type) 909f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 910f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct dhcp_message *dhcp; 911f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint8_t *m, *lp, *p; 912f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint8_t *n_params = NULL; 913f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project time_t up = uptime() - iface->start_uptime; 914f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint32_t ul; 915f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint16_t sz; 916938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt size_t len; 917938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt const char *hp; 918e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt const struct dhcp_opt *opt; 919e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt const struct if_options *ifo = iface->state->options; 920e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt const struct dhcp_lease *lease = &iface->state->lease; 921f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 922f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project dhcp = xzalloc(sizeof (*dhcp)); 923f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project m = (uint8_t *)dhcp; 924f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p = dhcp->options; 925f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 926e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if ((type == DHCP_INFORM || type == DHCP_RELEASE || 927e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt (type == DHCP_REQUEST && 928e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->net.s_addr == lease->net.s_addr && 929e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt (iface->state->new == NULL || 930e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->new->cookie == htonl(MAGIC_COOKIE))))) 931f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 932f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project dhcp->ciaddr = iface->addr.s_addr; 933e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* In-case we haven't actually configured the address yet */ 934f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (type == DHCP_INFORM && iface->addr.s_addr == 0) 935f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project dhcp->ciaddr = lease->addr.s_addr; 936f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 937f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 938f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project dhcp->op = DHCP_BOOTREQUEST; 939f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project dhcp->hwtype = iface->family; 940f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project switch (iface->family) { 941f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project case ARPHRD_ETHER: 942f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project case ARPHRD_IEEE802: 943e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt dhcp->hwlen = iface->hwlen; 944e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memcpy(&dhcp->chaddr, &iface->hwaddr, iface->hwlen); 945f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project break; 946f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 947f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 948e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifo->options & DHCPCD_BROADCAST && 949e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt dhcp->ciaddr == 0 && 950e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt type != DHCP_DECLINE && 951e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt type != DHCP_RELEASE) 952e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt dhcp->flags = htons(BROADCAST_FLAG); 953e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 954938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (type != DHCP_DECLINE && type != DHCP_RELEASE) { 955938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (up < 0 || up > (time_t)UINT16_MAX) 956938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt dhcp->secs = htons((uint16_t)UINT16_MAX); 957938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt else 958938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt dhcp->secs = htons(up); 959938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt } 960e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt dhcp->xid = iface->state->xid; 961f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project dhcp->cookie = htonl(MAGIC_COOKIE); 962f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 963f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *p++ = DHO_MESSAGETYPE; 964f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *p++ = 1; 965f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *p++ = type; 966f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 967938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (iface->clientid) { 968938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt *p++ = DHO_CLIENTID; 969938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt memcpy(p, iface->clientid, iface->clientid[0] + 1); 970938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt p += iface->clientid[0] + 1; 971938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt } 972938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt 973e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (lease->addr.s_addr && lease->cookie == htonl(MAGIC_COOKIE)) { 974938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (type == DHCP_DECLINE || 975938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt (type == DHCP_REQUEST && 976e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt lease->addr.s_addr != iface->addr.s_addr)) 977938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt { 978938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt PUTADDR(DHO_IPADDRESS, lease->addr); 979938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (lease->server.s_addr) 980938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt PUTADDR(DHO_SERVERID, lease->server); 981938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt } 982e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 983e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (type == DHCP_RELEASE) { 984e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (lease->server.s_addr) 985e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt PUTADDR(DHO_SERVERID, lease->server); 986e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 987938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt } 988938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt 989938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (type == DHCP_DECLINE) { 990938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt *p++ = DHO_MESSAGE; 991938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt len = strlen(DAD); 992938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt *p++ = len; 993938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt memcpy(p, DAD, len); 994938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt p += len; 995938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt } 996938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt 997e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (type == DHCP_DISCOVER && ifo->options & DHCPCD_REQUEST) 998e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt PUTADDR(DHO_IPADDRESS, ifo->req_addr); 999938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt 1000938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (type == DHCP_DISCOVER || 1001938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt type == DHCP_INFORM || 1002938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt type == DHCP_REQUEST) 1003938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt { 1004f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *p++ = DHO_MAXMESSAGESIZE; 1005f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *p++ = 2; 1006f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project sz = get_mtu(iface->name); 1007f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (sz < MTU_MIN) { 1008f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (set_mtu(iface->name, MTU_MIN) == 0) 1009f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project sz = MTU_MIN; 1010e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } else if (sz > MTU_MAX) { 1011e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Even though our MTU could be greater than 1012e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * MTU_MAX (1500) dhcpcd does not presently 1013e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * handle DHCP packets any bigger. */ 1014e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt sz = MTU_MAX; 1015f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1016f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project sz = htons(sz); 1017f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memcpy(p, &sz, 2); 1018f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p += 2; 1019f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1020e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifo->userclass[0]) { 1021f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *p++ = DHO_USERCLASS; 1022e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memcpy(p, ifo->userclass, ifo->userclass[0] + 1); 1023e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt p += ifo->userclass[0] + 1; 1024f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1025f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1026e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifo->vendorclassid[0]) { 1027f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *p++ = DHO_VENDORCLASSID; 1028e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memcpy(p, ifo->vendorclassid, 1029e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifo->vendorclassid[0] + 1); 1030e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt p += ifo->vendorclassid[0] + 1; 1031f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1032f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1033e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 1034938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (type != DHCP_INFORM) { 1035e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifo->leasetime != 0) { 1036938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt *p++ = DHO_LEASETIME; 1037938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt *p++ = 4; 1038e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ul = htonl(ifo->leasetime); 1039938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt memcpy(p, &ul, 4); 1040938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt p += 4; 1041938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt } 1042f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1043f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1044938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt /* Regardless of RFC2132, we should always send a hostname 1045938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt * upto the first dot (the short hostname) as otherwise 1046938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt * confuses some DHCP servers when updating DNS. 1047938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt * The FQDN option should be used if a FQDN is required. */ 1048e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifo->options & DHCPCD_HOSTNAME && ifo->hostname[0]) { 1049f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *p++ = DHO_HOSTNAME; 1050e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt hp = strchr(ifo->hostname, '.'); 1051938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (hp) 1052e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt len = hp - ifo->hostname; 1053938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt else 1054e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt len = strlen(ifo->hostname); 1055938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt *p++ = len; 1056e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memcpy(p, ifo->hostname, len); 1057938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt p += len; 1058f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1059e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifo->fqdn != FQDN_DISABLE && ifo->hostname[0]) { 1060f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* IETF DHC-FQDN option (81), RFC4702 */ 1061f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *p++ = DHO_FQDN; 1062f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project lp = p; 1063f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *p++ = 3; 1064f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* 1065f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * Flags: 0000NEOS 1066f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * S: 1 => Client requests Server to update 1067f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * a RR in DNS as well as PTR 1068f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * O: 1 => Server indicates to client that 1069f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * DNS has been updated 1070f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * E: 1 => Name data is DNS format 1071f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * N: 1 => Client requests Server to not 1072f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * update DNS 1073f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project */ 1074e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt *p++ = (ifo->fqdn & 0x09) | 0x04; 1075f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *p++ = 0; /* from server for PTR RR */ 1076f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *p++ = 0; /* from server for A RR if S=1 */ 1077e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ul = encode_rfc1035(ifo->hostname, p); 1078f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *lp += ul; 1079f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p += ul; 1080f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1081f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1082f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* vendor is already encoded correctly, so just add it */ 1083e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifo->vendor[0]) { 1084f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *p++ = DHO_VENDOR; 1085e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memcpy(p, ifo->vendor, ifo->vendor[0] + 1); 1086e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt p += ifo->vendor[0] + 1; 1087f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1088f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1089f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *p++ = DHO_PARAMETERREQUESTLIST; 1090f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project n_params = p; 1091f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *p++ = 0; 1092f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project for (opt = dhcp_opts; opt->option; opt++) { 1093f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (!(opt->type & REQUEST || 1094e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt has_option_mask(ifo->requestmask, opt->option))) 1095e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt continue; 1096e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (type == DHCP_INFORM && 1097e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt (opt->option == DHO_RENEWALTIME || 1098e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt opt->option == DHO_REBINDTIME)) 1099f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project continue; 1100f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *p++ = opt->option; 1101f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1102f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *n_params = p - n_params - 1; 1103f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1104f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *p++ = DHO_END; 1105f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1106f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#ifdef BOOTP_MESSAGE_LENTH_MIN 1107f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* Some crappy DHCP servers think they have to obey the BOOTP minimum 1108f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * message length. 1109f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * They are wrong, but we should still cater for them. */ 1110f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project while (p - m < BOOTP_MESSAGE_LENTH_MIN) 1111f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *p++ = DHO_PAD; 1112f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#endif 1113f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1114f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *message = dhcp; 1115f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return p - m; 1116f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 1117f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1118f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectssize_t 1119f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectwrite_lease(const struct interface *iface, const struct dhcp_message *dhcp) 1120f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 1121f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int fd; 1122f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ssize_t bytes = sizeof(*dhcp); 1123f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project const uint8_t *p = dhcp->options; 1124f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project const uint8_t *e = p + sizeof(dhcp->options); 1125f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint8_t l; 1126f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint8_t o = 0; 1127f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1128e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* We don't write BOOTP leases */ 1129e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (is_bootp(dhcp)) { 1130f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project unlink(iface->leasefile); 1131e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return 0; 1132f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1133e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 1134e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_DEBUG, "%s: writing lease `%s'", 1135e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->name, iface->leasefile); 1136e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 1137e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt fd = open(iface->leasefile, O_WRONLY | O_CREAT | O_TRUNC, 0444); 11380545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt#ifdef ANDROID 11390545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt if (fd == -1 && errno == EACCES) { 11400545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt /* the lease file might have been created when dhcpcd was running as root */ 11410545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt unlink(iface->leasefile); 11420545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt fd = open(iface->leasefile, O_WRONLY | O_CREAT | O_TRUNC, 0444); 11430545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt } 11440545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt#endif 1145e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (fd == -1) { 1146e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "%s: open: %m", iface->name); 1147f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 1148e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 1149f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1150f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* Only write as much as we need */ 1151f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project while (p < e) { 1152f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project o = *p; 1153f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (o == DHO_END) { 1154f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project bytes = p - (const uint8_t *)dhcp; 1155f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project break; 1156f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1157f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p++; 1158f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (o != DHO_PAD) { 1159f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project l = *p++; 1160f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p += l; 1161f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1162f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1163f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project bytes = write(fd, dhcp, bytes); 1164f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project close(fd); 1165f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return bytes; 1166f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 1167f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1168f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstruct dhcp_message * 1169f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectread_lease(const struct interface *iface) 1170f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 1171f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int fd; 1172f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct dhcp_message *dhcp; 1173f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ssize_t bytes; 1174f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1175f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project fd = open(iface->leasefile, O_RDONLY); 1176e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (fd == -1) { 1177e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (errno != ENOENT) 1178e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "%s: open `%s': %m", 1179e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->name, iface->leasefile); 1180f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return NULL; 1181e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 1182e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_DEBUG, "%s: reading lease `%s'", 1183e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->name, iface->leasefile); 1184f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project dhcp = xmalloc(sizeof(*dhcp)); 1185f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memset(dhcp, 0, sizeof(*dhcp)); 1186f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project bytes = read(fd, dhcp, sizeof(*dhcp)); 1187f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project close(fd); 1188f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (bytes < 0) { 1189f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project free(dhcp); 1190f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project dhcp = NULL; 1191f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1192f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return dhcp; 1193f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 1194f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1195f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic ssize_t 1196f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectprint_string(char *s, ssize_t len, int dl, const uint8_t *data) 1197f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 1198f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint8_t c; 1199938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt const uint8_t *e, *p; 1200f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ssize_t bytes = 0; 1201f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ssize_t r; 1202f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1203f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project e = data + dl; 1204f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project while (data < e) { 1205f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project c = *data++; 1206938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (c == '\0') { 1207938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt /* If rest is all NULL, skip it. */ 1208938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt for (p = data; p < e; p++) 1209938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (*p != '\0') 1210938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt break; 1211938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (p == e) 1212938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt break; 1213938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt } 1214f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (!isascii(c) || !isprint(c)) { 1215f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (s) { 1216f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (len < 5) { 1217f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project errno = ENOBUFS; 1218f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 1219f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1220f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project r = snprintf(s, len, "\\%03o", c); 1221f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project len -= r; 1222f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project bytes += r; 1223f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project s += r; 1224f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } else 1225f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project bytes += 4; 1226f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project continue; 1227f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1228f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project switch (c) { 1229e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt case '"': /* FALLTHROUGH */ 1230e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt case '\'': /* FALLTHROUGH */ 1231e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt case '$': /* FALLTHROUGH */ 1232e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt case '`': /* FALLTHROUGH */ 1233a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt case '\\': /* FALLTHROUGH */ 1234a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt case '|': /* FALLTHROUGH */ 1235a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt case '&': 1236e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (s) { 1237e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (len < 3) { 1238e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt errno = ENOBUFS; 1239e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return -1; 1240f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1241e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt *s++ = '\\'; 1242e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt len--; 1243e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 1244e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt bytes++; 1245e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 1246f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1247f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (s) { 1248f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *s++ = c; 1249f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project len--; 1250f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1251f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project bytes++; 1252f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1253f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1254f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* NULL */ 1255f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (s) 1256f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *s = '\0'; 1257f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project bytes++; 1258f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return bytes; 1259f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 1260f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1261f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic ssize_t 1262f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectprint_option(char *s, ssize_t len, int type, int dl, const uint8_t *data) 1263f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 1264f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project const uint8_t *e, *t; 1265f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint16_t u16; 1266f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int16_t s16; 1267f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint32_t u32; 1268f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int32_t s32; 1269f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct in_addr addr; 1270f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ssize_t bytes = 0; 1271f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ssize_t l; 1272f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project char *tmp; 1273f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1274f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (type & RFC3397) { 1275f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project l = decode_rfc3397(NULL, 0, dl, data); 1276f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (l < 1) 1277f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return l; 1278f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project tmp = xmalloc(l); 1279f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project decode_rfc3397(tmp, l, dl, data); 1280f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project l = print_string(s, len, l - 1, (uint8_t *)tmp); 1281f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project free(tmp); 1282f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return l; 1283f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1284f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1285a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt if (type & RFC3361) { 1286a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt if ((tmp = decode_rfc3361(dl, data)) == NULL) 1287a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt return -1; 1288a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt l = strlen(tmp); 1289a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt l = print_string(s, len, l - 1, (uint8_t *)tmp); 1290a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt free(tmp); 1291a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt return l; 1292a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt } 1293a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt 1294f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (type & RFC3442) 1295f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return decode_rfc3442(s, len, dl, data); 1296f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1297a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt if (type & RFC5969) 1298a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt return decode_rfc5969(s, len, dl, data); 1299a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt 1300f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (type & STRING) { 1301f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* Some DHCP servers return NULL strings */ 1302f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (*data == '\0') 1303f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 1304f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return print_string(s, len, dl, data); 1305f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1306f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1307f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (!s) { 1308f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (type & UINT8) 1309f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project l = 3; 1310e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else if (type & UINT16) { 1311f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project l = 5; 1312e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt dl /= 2; 1313e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } else if (type & SINT16) { 1314f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project l = 6; 1315e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt dl /= 2; 1316e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } else if (type & UINT32) { 1317f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project l = 10; 1318e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt dl /= 4; 1319e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } else if (type & SINT32) { 1320f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project l = 11; 1321e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt dl /= 4; 1322e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } else if (type & IPV4) { 1323f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project l = 16; 1324e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt dl /= 4; 1325e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } else { 1326f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project errno = EINVAL; 1327f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 1328f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1329f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return (l + 1) * dl; 1330f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1331f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1332f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project t = data; 1333f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project e = data + dl; 1334f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project while (data < e) { 1335f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (data != t) { 1336f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *s++ = ' '; 1337f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project bytes++; 1338f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project len--; 1339f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1340f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (type & UINT8) { 1341f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project l = snprintf(s, len, "%d", *data); 1342f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project data++; 1343f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } else if (type & UINT16) { 1344f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memcpy(&u16, data, sizeof(u16)); 1345f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project u16 = ntohs(u16); 1346f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project l = snprintf(s, len, "%d", u16); 1347f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project data += sizeof(u16); 1348f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } else if (type & SINT16) { 1349f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memcpy(&s16, data, sizeof(s16)); 1350f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project s16 = ntohs(s16); 1351f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project l = snprintf(s, len, "%d", s16); 1352f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project data += sizeof(s16); 1353f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } else if (type & UINT32) { 1354f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memcpy(&u32, data, sizeof(u32)); 1355f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project u32 = ntohl(u32); 1356f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project l = snprintf(s, len, "%d", u32); 1357f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project data += sizeof(u32); 1358f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } else if (type & SINT32) { 1359f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memcpy(&s32, data, sizeof(s32)); 1360f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project s32 = ntohl(s32); 1361f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project l = snprintf(s, len, "%d", s32); 1362f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project data += sizeof(s32); 1363f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } else if (type & IPV4) { 1364f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memcpy(&addr.s_addr, data, sizeof(addr.s_addr)); 1365f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project l = snprintf(s, len, "%s", inet_ntoa(addr)); 1366f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project data += sizeof(addr.s_addr); 1367f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } else 1368f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project l = 0; 1369c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline if (len <= l) { 1370c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline bytes += len; 1371c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline break; 1372c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline } 1373f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project len -= l; 1374f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project bytes += l; 1375f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project s += l; 1376f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1377f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1378f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return bytes; 1379f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 1380f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1381f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectssize_t 1382f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectconfigure_env(char **env, const char *prefix, const struct dhcp_message *dhcp, 1383e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt const struct if_options *ifo) 1384f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 1385f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project unsigned int i; 1386f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project const uint8_t *p; 1387f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int pl; 1388f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct in_addr addr; 1389f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct in_addr net; 1390f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct in_addr brd; 1391f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project char *val, *v; 1392f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project const struct dhcp_opt *opt; 1393f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ssize_t len, e = 0; 1394f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project char **ep; 1395f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project char cidr[4]; 1396f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint8_t overl = 0; 1397f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1398f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project get_option_uint8(&overl, dhcp, DHO_OPTIONSOVERLOADED); 1399f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1400f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (!env) { 1401f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project for (opt = dhcp_opts; opt->option; opt++) { 1402f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (!opt->var) 1403f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project continue; 1404e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (has_option_mask(ifo->nomask, opt->option)) 1405f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project continue; 1406f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (get_option_raw(dhcp, opt->option)) 1407f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project e++; 1408f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1409e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (dhcp->yiaddr || dhcp->ciaddr) 1410f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project e += 5; 1411f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (*dhcp->bootfile && !(overl & 1)) 1412f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project e++; 1413f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (*dhcp->servername && !(overl & 2)) 1414f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project e++; 1415f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return e; 1416f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1417f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1418f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ep = env; 1419e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (dhcp->yiaddr || dhcp->ciaddr) { 1420f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* Set some useful variables that we derive from the DHCP 1421f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * message but are not necessarily in the options */ 1422e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt addr.s_addr = dhcp->yiaddr ? dhcp->yiaddr : dhcp->ciaddr; 1423f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project setvar(&ep, prefix, "ip_address", inet_ntoa(addr)); 1424938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (get_option_addr(&net, dhcp, DHO_SUBNETMASK) == -1) { 1425f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project net.s_addr = get_netmask(addr.s_addr); 1426f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project setvar(&ep, prefix, "subnet_mask", inet_ntoa(net)); 1427f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1428f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project i = inet_ntocidr(net); 1429f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project snprintf(cidr, sizeof(cidr), "%d", inet_ntocidr(net)); 1430f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project setvar(&ep, prefix, "subnet_cidr", cidr); 1431938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (get_option_addr(&brd, dhcp, DHO_BROADCAST) == -1) { 1432f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project brd.s_addr = addr.s_addr | ~net.s_addr; 1433938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt setvar(&ep, prefix, "broadcast_address", inet_ntoa(brd)); 1434f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1435f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project addr.s_addr = dhcp->yiaddr & net.s_addr; 1436f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project setvar(&ep, prefix, "network_number", inet_ntoa(addr)); 1437f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1438f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1439f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (*dhcp->bootfile && !(overl & 1)) 1440f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project setvar(&ep, prefix, "filename", (const char *)dhcp->bootfile); 1441f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (*dhcp->servername && !(overl & 2)) 1442f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project setvar(&ep, prefix, "server_name", (const char *)dhcp->servername); 1443f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1444f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project for (opt = dhcp_opts; opt->option; opt++) { 1445f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (!opt->var) 1446f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project continue; 1447e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (has_option_mask(ifo->nomask, opt->option)) 1448f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project continue; 1449f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project val = NULL; 1450f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p = get_option(dhcp, opt->option, &pl, NULL); 1451f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (!p) 1452f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project continue; 1453f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* We only want the FQDN name */ 1454f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (opt->option == DHO_FQDN) { 1455f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p += 3; 1456f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project pl -= 3; 1457f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1458f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project len = print_option(NULL, 0, opt->type, pl, p); 1459f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (len < 0) 1460f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 1461f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project e = strlen(prefix) + strlen(opt->var) + len + 4; 1462f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project v = val = *ep++ = xmalloc(e); 1463f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project v += snprintf(val, e, "%s_%s=", prefix, opt->var); 1464f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (len != 0) 1465f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project print_option(v, len, opt->type, pl, p); 1466f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1467f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1468f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return ep - env; 1469f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 1470e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 1471e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid 1472e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtget_lease(struct dhcp_lease *lease, const struct dhcp_message *dhcp) 1473e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 1474e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct timeval now; 1475e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 1476e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt lease->cookie = dhcp->cookie; 1477e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* BOOTP does not set yiaddr for replies when ciaddr is set. */ 1478e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (dhcp->yiaddr) 1479e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt lease->addr.s_addr = dhcp->yiaddr; 1480e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else 1481e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt lease->addr.s_addr = dhcp->ciaddr; 1482e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (get_option_addr(&lease->net, dhcp, DHO_SUBNETMASK) == -1) 1483e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt lease->net.s_addr = get_netmask(lease->addr.s_addr); 1484e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (get_option_addr(&lease->brd, dhcp, DHO_BROADCAST) == -1) 1485e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt lease->brd.s_addr = lease->addr.s_addr | ~lease->net.s_addr; 1486e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (get_option_uint32(&lease->leasetime, dhcp, DHO_LEASETIME) == 0) { 1487e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Ensure that we can use the lease */ 1488e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt get_monotonic(&now); 1489e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (now.tv_sec + (time_t)lease->leasetime < now.tv_sec) 1490e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt lease->leasetime = ~0U; /* Infinite lease */ 1491e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } else 1492e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt lease->leasetime = ~0U; /* Default to infinite lease */ 1493e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (get_option_uint32(&lease->renewaltime, dhcp, DHO_RENEWALTIME) != 0) 1494e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt lease->renewaltime = 0; 1495e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (get_option_uint32(&lease->rebindtime, dhcp, DHO_REBINDTIME) != 0) 1496e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt lease->rebindtime = 0; 1497e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (get_option_addr(&lease->server, dhcp, DHO_SERVERID) != 0) 1498e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt lease->server.s_addr = INADDR_ANY; 1499e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 1500