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 316f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project while (p < e) { 317f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project o = *p++; 318f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (o == opt) { 319f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (op) { 320e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (!opt_buffer) { 321e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt opt_buffer = xmalloc(sizeof(*dhcp)); 322e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifdef DEBUG_MEMORY 323f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project atexit(free_option_buffer); 324e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#endif 325f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 326f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (!bp) 327e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt bp = opt_buffer; 328f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memcpy(bp, op, ol); 329f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project bp += ol; 330f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 331f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ol = *p; 332f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project op = p + 1; 333f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project bl += ol; 334f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 335f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project switch (o) { 336f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project case DHO_PAD: 337f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project continue; 338f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project case DHO_END: 339f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (overl & 1) { 340f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* bit 1 set means parse boot file */ 341f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project overl &= ~1; 342f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p = dhcp->bootfile; 343f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project e = p + sizeof(dhcp->bootfile); 344f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } else if (overl & 2) { 345f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* bit 2 set means parse server name */ 346f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project overl &= ~2; 347f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p = dhcp->servername; 348f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project e = p + sizeof(dhcp->servername); 349f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } else 350f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project goto exit; 351f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project break; 352f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project case DHO_OPTIONSOVERLOADED: 353f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* Ensure we only get this option once */ 354f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (!overl) 355f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project overl = p[1]; 356f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project break; 357f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 358f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project l = *p++; 359f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p += l; 360f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 361f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 362f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectexit: 363f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (valid_length(opt, bl, type) == -1) { 364f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project errno = EINVAL; 365f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return NULL; 366f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 367f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (len) 368f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *len = bl; 369f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (bp) { 370f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memcpy(bp, op, ol); 371e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return (const uint8_t *)opt_buffer; 372f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 373f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (op) 374f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return op; 375f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project errno = ENOENT; 376f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return NULL; 377f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 378f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 379f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectint 380938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidtget_option_addr(struct in_addr *a, const struct dhcp_message *dhcp, 381938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt uint8_t option) 382f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 383f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project const uint8_t *p = get_option_raw(dhcp, option); 384f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 385f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (!p) 386f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 387938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt memcpy(&a->s_addr, p, sizeof(a->s_addr)); 388f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 389f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 390f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 391f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectint 392f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectget_option_uint32(uint32_t *i, const struct dhcp_message *dhcp, uint8_t option) 393f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 394938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt const uint8_t *p = get_option_raw(dhcp, option); 395938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt uint32_t d; 396f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 397938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (!p) 398f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 399938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt memcpy(&d, p, sizeof(d)); 400938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt *i = ntohl(d); 401f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 402f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 403f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 404f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectint 405f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectget_option_uint16(uint16_t *i, const struct dhcp_message *dhcp, uint8_t option) 406f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 407f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project const uint8_t *p = get_option_raw(dhcp, option); 408f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint16_t d; 409f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 410f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (!p) 411f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 412f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memcpy(&d, p, sizeof(d)); 413f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *i = ntohs(d); 414f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 415f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 416f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 417f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectint 418f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectget_option_uint8(uint8_t *i, const struct dhcp_message *dhcp, uint8_t option) 419f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 420f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project const uint8_t *p = get_option_raw(dhcp, option); 421f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 422f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (!p) 423f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 424e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (i) 425e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt *i = *(p); 426f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 427f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 428f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 429f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project/* Decode an RFC3397 DNS search order option into a space 430e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * separated string. Returns length of string (including 431f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * terminating zero) or zero on error. out may be NULL 432f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * to just determine output length. */ 433a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidtssize_t 434f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectdecode_rfc3397(char *out, ssize_t len, int pl, const uint8_t *p) 435f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 436f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project const uint8_t *r, *q = p; 437f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int count = 0, l, hops; 438f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint8_t ltype; 439f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 440f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project while (q - p < pl) { 441f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project r = NULL; 442f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project hops = 0; 443f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* We check we are inside our length again incase 444f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * the data is NOT terminated correctly. */ 445f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project while ((l = *q++) && q - p < pl) { 446f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ltype = l & 0xc0; 447f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (ltype == 0x80 || ltype == 0x40) 448f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 449f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project else if (ltype == 0xc0) { /* pointer */ 450f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project l = (l & 0x3f) << 8; 451f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project l |= *q++; 452f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* save source of first jump. */ 453f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (!r) 454f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project r = q; 455f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project hops++; 456f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (hops > 255) 457f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 458f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project q = p + l; 459f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (q - p >= pl) 460f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 461f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } else { 462f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* straightforward name segment, add with '.' */ 463f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project count += l + 1; 464f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (out) { 465f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if ((ssize_t)l + 1 > len) { 466f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project errno = ENOBUFS; 467f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 468f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 469f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memcpy(out, q, l); 470f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project out += l; 471f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *out++ = '.'; 472f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project len -= l; 473f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project len--; 474f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 475f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project q += l; 476f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 477f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 478f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* change last dot to space */ 479f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (out) 480f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *(out - 1) = ' '; 481f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (r) 482f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project q = r; 483f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 484f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 485f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* change last space to zero terminator */ 486f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (out) 487f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *(out - 1) = 0; 488f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 489f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return count; 490f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 491f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 492f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic ssize_t 493f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectdecode_rfc3442(char *out, ssize_t len, int pl, const uint8_t *p) 494f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 495f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project const uint8_t *e; 496e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ssize_t b, bytes = 0, ocets; 497f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint8_t cidr; 498f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct in_addr addr; 499f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project char *o = out; 500f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 501f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* Minimum is 5 -first is CIDR and a router length of 4 */ 502f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (pl < 5) { 503f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project errno = EINVAL; 504f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 505f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 506f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 507f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project e = p + pl; 508f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project while (p < e) { 509f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project cidr = *p++; 510f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (cidr > 32) { 511f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project errno = EINVAL; 512f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 513f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 514f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ocets = (cidr + 7) / 8; 515f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (!out) { 516f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p += 4 + ocets; 517f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project bytes += ((4 * 4) * 2) + 4; 518f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project continue; 519f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 520f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if ((((4 * 4) * 2) + 4) > len) { 521f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project errno = ENOBUFS; 522f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 523f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 524f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (o != out) { 525f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *o++ = ' '; 526f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project len--; 527f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 528f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* If we have ocets then we have a destination and netmask */ 529f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (ocets > 0) { 530f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project addr.s_addr = 0; 531e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memcpy(&addr.s_addr, p, ocets); 532f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project b = snprintf(o, len, "%s/%d", inet_ntoa(addr), cidr); 533f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p += ocets; 534f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } else 535f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project b = snprintf(o, len, "0.0.0.0/0"); 536f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project o += b; 537f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project len -= b; 538f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 539f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* Finally, snag the router */ 540f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memcpy(&addr.s_addr, p, 4); 541f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p += 4; 542f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project b = snprintf(o, len, " %s", inet_ntoa(addr)); 543f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project o += b; 544f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project len -= b; 545f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 546f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 547f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (out) 548f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return o - out; 549f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return bytes; 550f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 551f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 552f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic struct rt * 553f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectdecode_rfc3442_rt(int dl, const uint8_t *data) 554f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 555f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project const uint8_t *p = data; 556f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project const uint8_t *e; 557f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint8_t cidr; 558e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt size_t ocets; 559f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct rt *routes = NULL; 560f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct rt *rt = NULL; 561f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 562f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* Minimum is 5 -first is CIDR and a router length of 4 */ 563f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (dl < 5) 564f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return NULL; 565f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 566f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project e = p + dl; 567f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project while (p < e) { 568f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project cidr = *p++; 569f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (cidr > 32) { 570f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project free_routes(routes); 571f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project errno = EINVAL; 572f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return NULL; 573f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 574f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 575f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (rt) { 576f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project rt->next = xzalloc(sizeof(*rt)); 577f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project rt = rt->next; 578f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } else { 579f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project routes = rt = xzalloc(sizeof(*routes)); 580f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 581f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project rt->next = NULL; 582f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 583f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ocets = (cidr + 7) / 8; 584f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* If we have ocets then we have a destination and netmask */ 585f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (ocets > 0) { 586e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memcpy(&rt->dest.s_addr, p, ocets); 587f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p += ocets; 588e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt rt->net.s_addr = htonl(~0U << (32 - cidr)); 589f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 590f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 591f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* Finally, snag the router */ 592f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memcpy(&rt->gate.s_addr, p, 4); 593f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p += 4; 594f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 595f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return routes; 596f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 597f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 598f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic char * 599f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectdecode_rfc3361(int dl, const uint8_t *data) 600f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 601f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint8_t enc; 602f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project unsigned int l; 603f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project char *sip = NULL; 604f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct in_addr addr; 605f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project char *p; 606f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 607f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (dl < 2) { 608f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project errno = EINVAL; 609f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 610f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 611f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 612f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project enc = *data++; 613f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project dl--; 614f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project switch (enc) { 615f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project case 0: 616f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if ((l = decode_rfc3397(NULL, 0, dl, data)) > 0) { 617f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project sip = xmalloc(l); 618f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project decode_rfc3397(sip, l, dl, data); 619f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 620f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project break; 621f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project case 1: 622f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (dl == 0 || dl % 4 != 0) { 623f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project errno = EINVAL; 624f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project break; 625f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 626f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project addr.s_addr = INADDR_BROADCAST; 627f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project l = ((dl / sizeof(addr.s_addr)) * ((4 * 4) + 1)) + 1; 628f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project sip = p = xmalloc(l); 629a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt while (dl != 0) { 630f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memcpy(&addr.s_addr, data, sizeof(addr.s_addr)); 631f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project data += sizeof(addr.s_addr); 632f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p += snprintf(p, l - (p - sip), "%s ", inet_ntoa(addr)); 633a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt dl -= sizeof(addr.s_addr); 634f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 635f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *--p = '\0'; 636f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project break; 637f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project default: 638f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project errno = EINVAL; 639f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 640f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 641f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 642f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return sip; 643f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 644f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 645a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt/* Decode an RFC5969 6rd order option into a space 646a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt * separated string. Returns length of string (including 647a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt * terminating zero) or zero on error. */ 648a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidtstatic ssize_t 649a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidtdecode_rfc5969(char *out, ssize_t len, int pl, const uint8_t *p) 650a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt{ 651a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt uint8_t ipv4masklen, ipv6prefixlen; 652a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt uint8_t ipv6prefix[16]; 653a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt uint8_t br[4]; 654a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt int i; 655a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt ssize_t b, bytes = 0; 656a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt 657a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt if (pl < 22) { 658a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt errno = EINVAL; 659a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt return 0; 660a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt } 661a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt 662a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt ipv4masklen = *p++; 663a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt pl--; 664a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt ipv6prefixlen = *p++; 665a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt pl--; 666a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt 667a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt for (i = 0; i < 16; i++) { 668a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt ipv6prefix[i] = *p++; 669a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt pl--; 670a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt } 671a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt if (out) { 672a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt b= snprintf(out, len, 673a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt "%d %d " 674a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt "%02x%02x:%02x%02x:" 675a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt "%02x%02x:%02x%02x:" 676a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt "%02x%02x:%02x%02x:" 677a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt "%02x%02x:%02x%02x", 678a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt ipv4masklen, ipv6prefixlen, 679a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt ipv6prefix[0], ipv6prefix[1], ipv6prefix[2], ipv6prefix[3], 680a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt ipv6prefix[4], ipv6prefix[5], ipv6prefix[6], ipv6prefix[7], 681a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt ipv6prefix[8], ipv6prefix[9], ipv6prefix[10],ipv6prefix[11], 682a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt ipv6prefix[12],ipv6prefix[13],ipv6prefix[14], ipv6prefix[15] 683a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt ); 684a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt 685a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt len -= b; 686a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt out += b; 687a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt bytes += b; 688a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt } else { 689a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt bytes += 16 * 2 + 8 + 2 + 1 + 2; 690a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt } 691a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt 692a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt while (pl >= 4) { 693a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt br[0] = *p++; 694a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt br[1] = *p++; 695a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt br[2] = *p++; 696a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt br[3] = *p++; 697a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt pl -= 4; 698a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt 699a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt if (out) { 700a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt b= snprintf(out, len, " %d.%d.%d.%d", 701a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt br[0], br[1], br[2], br[3]); 702a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt len -= b; 703a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt out += b; 704a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt bytes += b; 705a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt } else { 706a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt bytes += (4 * 4); 707a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt } 708a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt } 709a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt 710a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt return bytes; 711a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt} 712a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt 713f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectchar * 714f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectget_option_string(const struct dhcp_message *dhcp, uint8_t option) 715f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 716f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int type = 0; 717f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int len; 718f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project const uint8_t *p; 719f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project char *s; 720f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 721f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p = get_option(dhcp, option, &len, &type); 722f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (!p || *p == '\0') 723f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return NULL; 724f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 725f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (type & RFC3397) { 726f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project type = decode_rfc3397(NULL, 0, len, p); 727f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (!type) { 728f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project errno = EINVAL; 729f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return NULL; 730f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 731f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project s = xmalloc(sizeof(char) * type); 732f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project decode_rfc3397(s, type, len, p); 733f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return s; 734f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 735f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 736f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (type & RFC3361) 737f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return decode_rfc3361(len, p); 738f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 739f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project s = xmalloc(sizeof(char) * (len + 1)); 740f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memcpy(s, p, len); 741f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project s[len] = '\0'; 742f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return s; 743f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 744f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 745f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project/* This calculates the netmask that we should use for static routes. 746f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * This IS different from the calculation used to calculate the netmask 747f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * for an interface address. */ 748f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic uint32_t 749f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectroute_netmask(uint32_t ip_in) 750f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 751f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* used to be unsigned long - check if error */ 752f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint32_t p = ntohl(ip_in); 753f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint32_t t; 754f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 755f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (IN_CLASSA(p)) 756f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project t = ~IN_CLASSA_NET; 757f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project else { 758f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (IN_CLASSB(p)) 759f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project t = ~IN_CLASSB_NET; 760f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project else { 761f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (IN_CLASSC(p)) 762f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project t = ~IN_CLASSC_NET; 763f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project else 764f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project t = 0; 765f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 766f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 767f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 768f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project while (t & p) 769f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project t >>= 1; 770f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 771f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return (htonl(~t)); 772f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 773f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 774f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project/* We need to obey routing options. 775f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * If we have a CSR then we only use that. 776f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * Otherwise we add static routes and then routers. */ 777f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstruct rt * 778e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtget_option_routes(const struct dhcp_message *dhcp, 779a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt const char *ifname, unsigned long long *opts) 780f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 781f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project const uint8_t *p; 782f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project const uint8_t *e; 783f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct rt *routes = NULL; 784f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct rt *route = NULL; 785f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int len; 786f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 787f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* If we have CSR's then we MUST use these only */ 788f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p = get_option(dhcp, DHO_CSR, &len, NULL); 789f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* Check for crappy MS option */ 790f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (!p) 791f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p = get_option(dhcp, DHO_MSCSR, &len, NULL); 792f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (p) { 793f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project routes = decode_rfc3442_rt(len, p); 794a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt if (routes) { 795a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt if (!(*opts & DHCPCD_CSR_WARNED)) { 796a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt syslog(LOG_DEBUG, 797a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt "%s: using Classless Static Routes", 798a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt ifname); 799a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt *opts |= DHCPCD_CSR_WARNED; 800a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt } 801f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return routes; 802e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 803f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 804f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 805f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* OK, get our static routes first. */ 806f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p = get_option(dhcp, DHO_STATICROUTE, &len, NULL); 807f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (p) { 808f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project e = p + len; 809f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project while (p < e) { 810f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (route) { 811f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project route->next = xmalloc(sizeof(*route)); 812f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project route = route->next; 813f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } else 814f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project routes = route = xmalloc(sizeof(*routes)); 815f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project route->next = NULL; 816f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memcpy(&route->dest.s_addr, p, 4); 817f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p += 4; 818f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memcpy(&route->gate.s_addr, p, 4); 819f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p += 4; 820f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project route->net.s_addr = route_netmask(route->dest.s_addr); 821f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 822f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 823f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 824f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* Now grab our routers */ 825f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p = get_option(dhcp, DHO_ROUTER, &len, NULL); 826f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (p) { 827f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project e = p + len; 828f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project while (p < e) { 829f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (route) { 830f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project route->next = xzalloc(sizeof(*route)); 831f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project route = route->next; 832f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } else 833f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project routes = route = xzalloc(sizeof(*route)); 834f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memcpy(&route->gate.s_addr, p, 4); 835f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p += 4; 836f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 837f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 838f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 839f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return routes; 840f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 841f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 842f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic size_t 843938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidtencode_rfc1035(const char *src, uint8_t *dst) 844f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 845f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint8_t *p = dst; 846f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint8_t *lp = p++; 847f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 848938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (*src == '\0') 849f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 850938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt for (; *src; src++) { 851938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (*src == '\0') 852f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project break; 853938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (*src == '.') { 854f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* Skip the trailing . */ 855938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (src[1] == '\0') 856f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project break; 857f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *lp = p - lp - 1; 858f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (*lp == '\0') 859f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return p - dst; 860f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project lp = p++; 861f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } else 862938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt *p++ = (uint8_t)*src; 863f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 864f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *lp = p - lp - 1; 865f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *p++ = '\0'; 866f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return p - dst; 867f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 868f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 869e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#define PUTADDR(_type, _val) \ 870e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt { \ 871e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt *p++ = _type; \ 872e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt *p++ = 4; \ 873e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memcpy(p, &_val.s_addr, 4); \ 874e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt p += 4; \ 875e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 876e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 877e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtint 878e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtdhcp_message_add_addr(struct dhcp_message *dhcp, 879e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt uint8_t type, struct in_addr addr) 880e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 881e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt uint8_t *p; 882e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt size_t len; 883e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 884e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt p = dhcp->options; 885e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt while (*p != DHO_END) { 886e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt p++; 887e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt p += *p + 1; 888e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 889e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 890e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt len = p - (uint8_t *)dhcp; 891e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (len + 6 > sizeof(*dhcp)) { 892e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt errno = ENOMEM; 893e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return -1; 894e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 895e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 896e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt PUTADDR(type, addr); 897e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt *p = DHO_END; 898e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return 0; 899938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt} 900e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 901f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectssize_t 902f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectmake_message(struct dhcp_message **message, 903e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt const struct interface *iface, 904e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt uint8_t type) 905f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 906f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct dhcp_message *dhcp; 907f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint8_t *m, *lp, *p; 908f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint8_t *n_params = NULL; 909f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project time_t up = uptime() - iface->start_uptime; 910f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint32_t ul; 911f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint16_t sz; 912938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt size_t len; 913938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt const char *hp; 914e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt const struct dhcp_opt *opt; 915e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt const struct if_options *ifo = iface->state->options; 916e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt const struct dhcp_lease *lease = &iface->state->lease; 917f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 918f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project dhcp = xzalloc(sizeof (*dhcp)); 919f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project m = (uint8_t *)dhcp; 920f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p = dhcp->options; 921f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 922e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if ((type == DHCP_INFORM || type == DHCP_RELEASE || 923e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt (type == DHCP_REQUEST && 924e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->net.s_addr == lease->net.s_addr && 925e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt (iface->state->new == NULL || 926e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->new->cookie == htonl(MAGIC_COOKIE))))) 927f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 928f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project dhcp->ciaddr = iface->addr.s_addr; 929e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* In-case we haven't actually configured the address yet */ 930f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (type == DHCP_INFORM && iface->addr.s_addr == 0) 931f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project dhcp->ciaddr = lease->addr.s_addr; 932f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 933f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 934f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project dhcp->op = DHCP_BOOTREQUEST; 935f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project dhcp->hwtype = iface->family; 936f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project switch (iface->family) { 937f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project case ARPHRD_ETHER: 938f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project case ARPHRD_IEEE802: 939e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt dhcp->hwlen = iface->hwlen; 940e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memcpy(&dhcp->chaddr, &iface->hwaddr, iface->hwlen); 941f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project break; 942f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 943f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 944e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifo->options & DHCPCD_BROADCAST && 945e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt dhcp->ciaddr == 0 && 946e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt type != DHCP_DECLINE && 947e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt type != DHCP_RELEASE) 948e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt dhcp->flags = htons(BROADCAST_FLAG); 949e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 950938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (type != DHCP_DECLINE && type != DHCP_RELEASE) { 951938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (up < 0 || up > (time_t)UINT16_MAX) 952938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt dhcp->secs = htons((uint16_t)UINT16_MAX); 953938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt else 954938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt dhcp->secs = htons(up); 955938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt } 956e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt dhcp->xid = iface->state->xid; 957f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project dhcp->cookie = htonl(MAGIC_COOKIE); 958f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 959f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *p++ = DHO_MESSAGETYPE; 960f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *p++ = 1; 961f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *p++ = type; 962f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 963938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (iface->clientid) { 964938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt *p++ = DHO_CLIENTID; 965938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt memcpy(p, iface->clientid, iface->clientid[0] + 1); 966938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt p += iface->clientid[0] + 1; 967938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt } 968938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt 969e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (lease->addr.s_addr && lease->cookie == htonl(MAGIC_COOKIE)) { 970938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (type == DHCP_DECLINE || 971938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt (type == DHCP_REQUEST && 972e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt lease->addr.s_addr != iface->addr.s_addr)) 973938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt { 974938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt PUTADDR(DHO_IPADDRESS, lease->addr); 975938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (lease->server.s_addr) 976938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt PUTADDR(DHO_SERVERID, lease->server); 977938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt } 978e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 979e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (type == DHCP_RELEASE) { 980e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (lease->server.s_addr) 981e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt PUTADDR(DHO_SERVERID, lease->server); 982e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 983938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt } 984938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt 985938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (type == DHCP_DECLINE) { 986938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt *p++ = DHO_MESSAGE; 987938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt len = strlen(DAD); 988938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt *p++ = len; 989938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt memcpy(p, DAD, len); 990938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt p += len; 991938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt } 992938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt 993e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (type == DHCP_DISCOVER && ifo->options & DHCPCD_REQUEST) 994e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt PUTADDR(DHO_IPADDRESS, ifo->req_addr); 995938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt 996938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (type == DHCP_DISCOVER || 997938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt type == DHCP_INFORM || 998938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt type == DHCP_REQUEST) 999938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt { 1000f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *p++ = DHO_MAXMESSAGESIZE; 1001f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *p++ = 2; 1002f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project sz = get_mtu(iface->name); 1003f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (sz < MTU_MIN) { 1004f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (set_mtu(iface->name, MTU_MIN) == 0) 1005f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project sz = MTU_MIN; 1006e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } else if (sz > MTU_MAX) { 1007e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Even though our MTU could be greater than 1008e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * MTU_MAX (1500) dhcpcd does not presently 1009e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * handle DHCP packets any bigger. */ 1010e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt sz = MTU_MAX; 1011f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1012f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project sz = htons(sz); 1013f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memcpy(p, &sz, 2); 1014f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p += 2; 1015f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1016e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifo->userclass[0]) { 1017f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *p++ = DHO_USERCLASS; 1018e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memcpy(p, ifo->userclass, ifo->userclass[0] + 1); 1019e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt p += ifo->userclass[0] + 1; 1020f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1021f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1022e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifo->vendorclassid[0]) { 1023f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *p++ = DHO_VENDORCLASSID; 1024e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memcpy(p, ifo->vendorclassid, 1025e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ifo->vendorclassid[0] + 1); 1026e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt p += ifo->vendorclassid[0] + 1; 1027f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1028f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1029e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 1030938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (type != DHCP_INFORM) { 1031e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifo->leasetime != 0) { 1032938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt *p++ = DHO_LEASETIME; 1033938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt *p++ = 4; 1034e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ul = htonl(ifo->leasetime); 1035938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt memcpy(p, &ul, 4); 1036938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt p += 4; 1037938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt } 1038f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1039f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1040938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt /* Regardless of RFC2132, we should always send a hostname 1041938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt * upto the first dot (the short hostname) as otherwise 1042938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt * confuses some DHCP servers when updating DNS. 1043938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt * The FQDN option should be used if a FQDN is required. */ 1044e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifo->options & DHCPCD_HOSTNAME && ifo->hostname[0]) { 1045f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *p++ = DHO_HOSTNAME; 1046e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt hp = strchr(ifo->hostname, '.'); 1047938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (hp) 1048e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt len = hp - ifo->hostname; 1049938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt else 1050e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt len = strlen(ifo->hostname); 1051938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt *p++ = len; 1052e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memcpy(p, ifo->hostname, len); 1053938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt p += len; 1054f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1055e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifo->fqdn != FQDN_DISABLE && ifo->hostname[0]) { 1056f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* IETF DHC-FQDN option (81), RFC4702 */ 1057f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *p++ = DHO_FQDN; 1058f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project lp = p; 1059f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *p++ = 3; 1060f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* 1061f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * Flags: 0000NEOS 1062f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * S: 1 => Client requests Server to update 1063f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * a RR in DNS as well as PTR 1064f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * O: 1 => Server indicates to client that 1065f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * DNS has been updated 1066f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * E: 1 => Name data is DNS format 1067f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * N: 1 => Client requests Server to not 1068f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * update DNS 1069f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project */ 1070e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt *p++ = (ifo->fqdn & 0x09) | 0x04; 1071f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *p++ = 0; /* from server for PTR RR */ 1072f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *p++ = 0; /* from server for A RR if S=1 */ 1073e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt ul = encode_rfc1035(ifo->hostname, p); 1074f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *lp += ul; 1075f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p += ul; 1076f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1077f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1078f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* vendor is already encoded correctly, so just add it */ 1079e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (ifo->vendor[0]) { 1080f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *p++ = DHO_VENDOR; 1081e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memcpy(p, ifo->vendor, ifo->vendor[0] + 1); 1082e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt p += ifo->vendor[0] + 1; 1083f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1084f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1085f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *p++ = DHO_PARAMETERREQUESTLIST; 1086f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project n_params = p; 1087f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *p++ = 0; 1088f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project for (opt = dhcp_opts; opt->option; opt++) { 1089f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (!(opt->type & REQUEST || 1090e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt has_option_mask(ifo->requestmask, opt->option))) 1091e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt continue; 1092e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (type == DHCP_INFORM && 1093e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt (opt->option == DHO_RENEWALTIME || 1094e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt opt->option == DHO_REBINDTIME)) 1095f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project continue; 1096f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *p++ = opt->option; 1097f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1098f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *n_params = p - n_params - 1; 1099f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1100f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *p++ = DHO_END; 1101f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1102f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#ifdef BOOTP_MESSAGE_LENTH_MIN 1103f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* Some crappy DHCP servers think they have to obey the BOOTP minimum 1104f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * message length. 1105f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * They are wrong, but we should still cater for them. */ 1106f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project while (p - m < BOOTP_MESSAGE_LENTH_MIN) 1107f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *p++ = DHO_PAD; 1108f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#endif 1109f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1110f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *message = dhcp; 1111f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return p - m; 1112f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 1113f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1114f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectssize_t 1115f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectwrite_lease(const struct interface *iface, const struct dhcp_message *dhcp) 1116f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 1117f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int fd; 1118f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ssize_t bytes = sizeof(*dhcp); 1119f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project const uint8_t *p = dhcp->options; 1120f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project const uint8_t *e = p + sizeof(dhcp->options); 1121f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint8_t l; 1122f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint8_t o = 0; 1123f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1124e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* We don't write BOOTP leases */ 1125e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (is_bootp(dhcp)) { 1126f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project unlink(iface->leasefile); 1127e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return 0; 1128f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1129e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 1130e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_DEBUG, "%s: writing lease `%s'", 1131e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->name, iface->leasefile); 1132e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 1133e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt fd = open(iface->leasefile, O_WRONLY | O_CREAT | O_TRUNC, 0444); 11340545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt#ifdef ANDROID 11350545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt if (fd == -1 && errno == EACCES) { 11360545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt /* the lease file might have been created when dhcpcd was running as root */ 11370545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt unlink(iface->leasefile); 11380545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt fd = open(iface->leasefile, O_WRONLY | O_CREAT | O_TRUNC, 0444); 11390545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt } 11400545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt#endif 1141e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (fd == -1) { 1142e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "%s: open: %m", iface->name); 1143f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 1144e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 1145f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1146f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* Only write as much as we need */ 1147f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project while (p < e) { 1148f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project o = *p; 1149f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (o == DHO_END) { 1150f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project bytes = p - (const uint8_t *)dhcp; 1151f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project break; 1152f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1153f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p++; 1154f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (o != DHO_PAD) { 1155f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project l = *p++; 1156f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p += l; 1157f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1158f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1159f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project bytes = write(fd, dhcp, bytes); 1160f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project close(fd); 1161f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return bytes; 1162f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 1163f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1164f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstruct dhcp_message * 1165f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectread_lease(const struct interface *iface) 1166f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 1167f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int fd; 1168f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct dhcp_message *dhcp; 1169f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ssize_t bytes; 1170f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1171f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project fd = open(iface->leasefile, O_RDONLY); 1172e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (fd == -1) { 1173e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (errno != ENOENT) 1174e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "%s: open `%s': %m", 1175e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->name, iface->leasefile); 1176f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return NULL; 1177e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 1178e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_DEBUG, "%s: reading lease `%s'", 1179e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->name, iface->leasefile); 1180f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project dhcp = xmalloc(sizeof(*dhcp)); 1181f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memset(dhcp, 0, sizeof(*dhcp)); 1182f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project bytes = read(fd, dhcp, sizeof(*dhcp)); 1183f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project close(fd); 1184f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (bytes < 0) { 1185f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project free(dhcp); 1186f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project dhcp = NULL; 1187f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1188f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return dhcp; 1189f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 1190f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1191f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic ssize_t 1192f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectprint_string(char *s, ssize_t len, int dl, const uint8_t *data) 1193f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 1194f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint8_t c; 1195938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt const uint8_t *e, *p; 1196f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ssize_t bytes = 0; 1197f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ssize_t r; 1198f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1199f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project e = data + dl; 1200f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project while (data < e) { 1201f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project c = *data++; 1202938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (c == '\0') { 1203938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt /* If rest is all NULL, skip it. */ 1204938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt for (p = data; p < e; p++) 1205938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (*p != '\0') 1206938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt break; 1207938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (p == e) 1208938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt break; 1209938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt } 1210f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (!isascii(c) || !isprint(c)) { 1211f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (s) { 1212f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (len < 5) { 1213f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project errno = ENOBUFS; 1214f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 1215f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1216f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project r = snprintf(s, len, "\\%03o", c); 1217f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project len -= r; 1218f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project bytes += r; 1219f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project s += r; 1220f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } else 1221f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project bytes += 4; 1222f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project continue; 1223f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1224f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project switch (c) { 1225e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt case '"': /* FALLTHROUGH */ 1226e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt case '\'': /* FALLTHROUGH */ 1227e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt case '$': /* FALLTHROUGH */ 1228e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt case '`': /* FALLTHROUGH */ 1229a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt case '\\': /* FALLTHROUGH */ 1230a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt case '|': /* FALLTHROUGH */ 1231a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt case '&': 1232e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (s) { 1233e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (len < 3) { 1234e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt errno = ENOBUFS; 1235e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return -1; 1236f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1237e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt *s++ = '\\'; 1238e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt len--; 1239e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 1240e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt bytes++; 1241e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 1242f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1243f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (s) { 1244f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *s++ = c; 1245f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project len--; 1246f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1247f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project bytes++; 1248f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1249f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1250f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* NULL */ 1251f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (s) 1252f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *s = '\0'; 1253f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project bytes++; 1254f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return bytes; 1255f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 1256f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1257f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic ssize_t 1258f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectprint_option(char *s, ssize_t len, int type, int dl, const uint8_t *data) 1259f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 1260f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project const uint8_t *e, *t; 1261f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint16_t u16; 1262f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int16_t s16; 1263f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint32_t u32; 1264f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int32_t s32; 1265f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct in_addr addr; 1266f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ssize_t bytes = 0; 1267f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ssize_t l; 1268f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project char *tmp; 1269f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1270f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (type & RFC3397) { 1271f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project l = decode_rfc3397(NULL, 0, dl, data); 1272f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (l < 1) 1273f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return l; 1274f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project tmp = xmalloc(l); 1275f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project decode_rfc3397(tmp, l, dl, data); 1276f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project l = print_string(s, len, l - 1, (uint8_t *)tmp); 1277f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project free(tmp); 1278f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return l; 1279f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1280f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1281a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt if (type & RFC3361) { 1282a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt if ((tmp = decode_rfc3361(dl, data)) == NULL) 1283a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt return -1; 1284a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt l = strlen(tmp); 1285a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt l = print_string(s, len, l - 1, (uint8_t *)tmp); 1286a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt free(tmp); 1287a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt return l; 1288a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt } 1289a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt 1290f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (type & RFC3442) 1291f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return decode_rfc3442(s, len, dl, data); 1292f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1293a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt if (type & RFC5969) 1294a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt return decode_rfc5969(s, len, dl, data); 1295a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt 1296f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (type & STRING) { 1297f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* Some DHCP servers return NULL strings */ 1298f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (*data == '\0') 1299f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 1300f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return print_string(s, len, dl, data); 1301f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1302f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1303f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (!s) { 1304f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (type & UINT8) 1305f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project l = 3; 1306e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else if (type & UINT16) { 1307f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project l = 5; 1308e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt dl /= 2; 1309e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } else if (type & SINT16) { 1310f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project l = 6; 1311e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt dl /= 2; 1312e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } else if (type & UINT32) { 1313f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project l = 10; 1314e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt dl /= 4; 1315e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } else if (type & SINT32) { 1316f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project l = 11; 1317e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt dl /= 4; 1318e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } else if (type & IPV4) { 1319f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project l = 16; 1320e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt dl /= 4; 1321e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } else { 1322f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project errno = EINVAL; 1323f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 1324f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1325f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return (l + 1) * dl; 1326f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1327f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1328f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project t = data; 1329f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project e = data + dl; 1330f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project while (data < e) { 1331f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (data != t) { 1332f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *s++ = ' '; 1333f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project bytes++; 1334f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project len--; 1335f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1336f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (type & UINT8) { 1337f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project l = snprintf(s, len, "%d", *data); 1338f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project data++; 1339f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } else if (type & UINT16) { 1340f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memcpy(&u16, data, sizeof(u16)); 1341f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project u16 = ntohs(u16); 1342f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project l = snprintf(s, len, "%d", u16); 1343f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project data += sizeof(u16); 1344f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } else if (type & SINT16) { 1345f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memcpy(&s16, data, sizeof(s16)); 1346f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project s16 = ntohs(s16); 1347f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project l = snprintf(s, len, "%d", s16); 1348f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project data += sizeof(s16); 1349f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } else if (type & UINT32) { 1350f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memcpy(&u32, data, sizeof(u32)); 1351f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project u32 = ntohl(u32); 1352f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project l = snprintf(s, len, "%d", u32); 1353f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project data += sizeof(u32); 1354f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } else if (type & SINT32) { 1355f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memcpy(&s32, data, sizeof(s32)); 1356f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project s32 = ntohl(s32); 1357f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project l = snprintf(s, len, "%d", s32); 1358f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project data += sizeof(s32); 1359f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } else if (type & IPV4) { 1360f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memcpy(&addr.s_addr, data, sizeof(addr.s_addr)); 1361f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project l = snprintf(s, len, "%s", inet_ntoa(addr)); 1362f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project data += sizeof(addr.s_addr); 1363f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } else 1364f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project l = 0; 1365f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project len -= l; 1366f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project bytes += l; 1367f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project s += l; 1368f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1369f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1370f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return bytes; 1371f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 1372f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1373f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectssize_t 1374f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectconfigure_env(char **env, const char *prefix, const struct dhcp_message *dhcp, 1375e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt const struct if_options *ifo) 1376f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 1377f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project unsigned int i; 1378f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project const uint8_t *p; 1379f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int pl; 1380f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct in_addr addr; 1381f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct in_addr net; 1382f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct in_addr brd; 1383f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project char *val, *v; 1384f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project const struct dhcp_opt *opt; 1385f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ssize_t len, e = 0; 1386f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project char **ep; 1387f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project char cidr[4]; 1388f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint8_t overl = 0; 1389f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1390f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project get_option_uint8(&overl, dhcp, DHO_OPTIONSOVERLOADED); 1391f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1392f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (!env) { 1393f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project for (opt = dhcp_opts; opt->option; opt++) { 1394f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (!opt->var) 1395f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project continue; 1396e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (has_option_mask(ifo->nomask, opt->option)) 1397f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project continue; 1398f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (get_option_raw(dhcp, opt->option)) 1399f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project e++; 1400f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1401e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (dhcp->yiaddr || dhcp->ciaddr) 1402f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project e += 5; 1403f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (*dhcp->bootfile && !(overl & 1)) 1404f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project e++; 1405f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (*dhcp->servername && !(overl & 2)) 1406f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project e++; 1407f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return e; 1408f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1409f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1410f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ep = env; 1411e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (dhcp->yiaddr || dhcp->ciaddr) { 1412f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* Set some useful variables that we derive from the DHCP 1413f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * message but are not necessarily in the options */ 1414e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt addr.s_addr = dhcp->yiaddr ? dhcp->yiaddr : dhcp->ciaddr; 1415f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project setvar(&ep, prefix, "ip_address", inet_ntoa(addr)); 1416938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (get_option_addr(&net, dhcp, DHO_SUBNETMASK) == -1) { 1417f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project net.s_addr = get_netmask(addr.s_addr); 1418f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project setvar(&ep, prefix, "subnet_mask", inet_ntoa(net)); 1419f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1420f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project i = inet_ntocidr(net); 1421f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project snprintf(cidr, sizeof(cidr), "%d", inet_ntocidr(net)); 1422f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project setvar(&ep, prefix, "subnet_cidr", cidr); 1423938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (get_option_addr(&brd, dhcp, DHO_BROADCAST) == -1) { 1424f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project brd.s_addr = addr.s_addr | ~net.s_addr; 1425938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt setvar(&ep, prefix, "broadcast_address", inet_ntoa(brd)); 1426f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1427f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project addr.s_addr = dhcp->yiaddr & net.s_addr; 1428f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project setvar(&ep, prefix, "network_number", inet_ntoa(addr)); 1429f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1430f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1431f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (*dhcp->bootfile && !(overl & 1)) 1432f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project setvar(&ep, prefix, "filename", (const char *)dhcp->bootfile); 1433f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (*dhcp->servername && !(overl & 2)) 1434f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project setvar(&ep, prefix, "server_name", (const char *)dhcp->servername); 1435f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1436f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project for (opt = dhcp_opts; opt->option; opt++) { 1437f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (!opt->var) 1438f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project continue; 1439e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (has_option_mask(ifo->nomask, opt->option)) 1440f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project continue; 1441f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project val = NULL; 1442f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p = get_option(dhcp, opt->option, &pl, NULL); 1443f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (!p) 1444f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project continue; 1445f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* We only want the FQDN name */ 1446f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (opt->option == DHO_FQDN) { 1447f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p += 3; 1448f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project pl -= 3; 1449f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1450f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project len = print_option(NULL, 0, opt->type, pl, p); 1451f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (len < 0) 1452f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 1453f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project e = strlen(prefix) + strlen(opt->var) + len + 4; 1454f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project v = val = *ep++ = xmalloc(e); 1455f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project v += snprintf(val, e, "%s_%s=", prefix, opt->var); 1456f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (len != 0) 1457f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project print_option(v, len, opt->type, pl, p); 1458f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 1459f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 1460f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return ep - env; 1461f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 1462e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 1463e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid 1464e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtget_lease(struct dhcp_lease *lease, const struct dhcp_message *dhcp) 1465e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 1466e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct timeval now; 1467e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 1468e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt lease->cookie = dhcp->cookie; 1469e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* BOOTP does not set yiaddr for replies when ciaddr is set. */ 1470e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (dhcp->yiaddr) 1471e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt lease->addr.s_addr = dhcp->yiaddr; 1472e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else 1473e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt lease->addr.s_addr = dhcp->ciaddr; 1474e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (get_option_addr(&lease->net, dhcp, DHO_SUBNETMASK) == -1) 1475e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt lease->net.s_addr = get_netmask(lease->addr.s_addr); 1476e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (get_option_addr(&lease->brd, dhcp, DHO_BROADCAST) == -1) 1477e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt lease->brd.s_addr = lease->addr.s_addr | ~lease->net.s_addr; 1478e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (get_option_uint32(&lease->leasetime, dhcp, DHO_LEASETIME) == 0) { 1479e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Ensure that we can use the lease */ 1480e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt get_monotonic(&now); 1481e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (now.tv_sec + (time_t)lease->leasetime < now.tv_sec) 1482e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt lease->leasetime = ~0U; /* Infinite lease */ 1483e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } else 1484e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt lease->leasetime = ~0U; /* Default to infinite lease */ 1485e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (get_option_uint32(&lease->renewaltime, dhcp, DHO_RENEWALTIME) != 0) 1486e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt lease->renewaltime = 0; 1487e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (get_option_uint32(&lease->rebindtime, dhcp, DHO_REBINDTIME) != 0) 1488e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt lease->rebindtime = 0; 1489e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (get_option_addr(&lease->server, dhcp, DHO_SERVERID) != 0) 1490e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt lease->server.s_addr = INADDR_ANY; 1491e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 1492