1f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <stdio.h> 2f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <stdlib.h> 3f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <errno.h> 4f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <fcntl.h> 5f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 6f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include "dhcp.h" 7f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include "config.h" 8f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 9e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifndef DEFAULT_LEASETIME 10e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#define DEFAULT_LEASETIME 3600 /* 1 hour */ 11e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#endif 12e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 13f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define REQUEST (1 << 0) 14f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define UINT8 (1 << 1) 15f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define UINT16 (1 << 2) 16f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define SINT16 (1 << 3) 17f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define UINT32 (1 << 4) 18f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define SINT32 (1 << 5) 19f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define IPV4 (1 << 6) 20f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define STRING (1 << 7) 21f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define PAIR (1 << 8) 22f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define ARRAY (1 << 9) 23f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define RFC3361 (1 << 10) 24f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define RFC3397 (1 << 11) 25f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define RFC3442 (1 << 12) 26f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 27f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstruct dhcp_opt { 28f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint8_t option; 29f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int type; 30f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project const char *var; 31f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}; 32f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 33f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic const struct dhcp_opt const dhcp_opts[] = { 34f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 1, IPV4 | REQUEST, "subnet_mask" }, 35f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 2, UINT32, "time_offset" }, 36f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 3, IPV4 | ARRAY | REQUEST, "routers" }, 37f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 4, IPV4 | ARRAY, "time_servers" }, 38f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 5, IPV4 | ARRAY, "ien116_name_servers" }, 39f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 6, IPV4 | ARRAY, "domain_name_servers" }, 40f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 7, IPV4 | ARRAY, "log_servers" }, 41f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 8, IPV4 | ARRAY, "cookie_servers" }, 42f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 9, IPV4 | ARRAY, "lpr_servers" }, 43f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 10, IPV4 | ARRAY, "impress_servers" }, 44f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 11, IPV4 | ARRAY, "resource_location_servers" }, 45f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 12, STRING, "host_name" }, 46f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 13, UINT16, "boot_size" }, 47f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 14, STRING, "merit_dump" }, 48f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 15, STRING, "domain_name" }, 49f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 16, IPV4, "swap_server" }, 50f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 17, STRING, "root_path" }, 51f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 18, STRING, "extensions_path" }, 52f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 19, UINT8, "ip_forwarding" }, 53f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 20, UINT8, "non_local_source_routing" }, 54f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 21, IPV4 | ARRAY, "policy_filter" }, 55f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 22, SINT16, "max_dgram_reassembly" }, 56f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 23, UINT16, "default_ip_ttl" }, 57f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 24, UINT32, "path_mtu_aging_timeout" }, 58f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 25, UINT16 | ARRAY, "path_mtu_plateau_table" }, 59f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 26, UINT16, "interface_mtu" }, 60f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 27, UINT8, "all_subnets_local" }, 61f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 28, IPV4 | REQUEST, "broadcast_address" }, 62f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 29, UINT8, "perform_mask_discovery" }, 63f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 30, UINT8, "mask_supplier" }, 64f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 31, UINT8, "router_discovery" }, 65f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 32, IPV4, "router_solicitation_address" }, 66f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 33, IPV4 | ARRAY | REQUEST, "static_routes" }, 67f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 34, UINT8, "trailer_encapsulation" }, 68f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 35, UINT32, "arp_cache_timeout" }, 69f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 36, UINT16, "ieee802_3_encapsulation" }, 70f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 37, UINT8, "default_tcp_ttl" }, 71f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 38, UINT32, "tcp_keepalive_interval" }, 72f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 39, UINT8, "tcp_keepalive_garbage" }, 73f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 40, STRING, "nis_domain" }, 74f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 41, IPV4 | ARRAY, "nis_servers" }, 75f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 42, IPV4 | ARRAY, "ntp_servers" }, 76f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 43, STRING, "vendor_encapsulated_options" }, 77f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 44, IPV4 | ARRAY, "netbios_name_servers" }, 78f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 45, IPV4, "netbios_dd_server" }, 79f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 46, UINT8, "netbios_node_type" }, 80f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 47, STRING, "netbios_scope" }, 81f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 48, IPV4 | ARRAY, "font_servers" }, 82f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 49, IPV4 | ARRAY, "x_display_manager" }, 83f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 50, IPV4, "dhcp_requested_address" }, 84f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 51, UINT32 | REQUEST, "dhcp_lease_time" }, 85f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 52, UINT8, "dhcp_option_overload" }, 86f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 53, UINT8, "dhcp_message_type" }, 87f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 54, IPV4, "dhcp_server_identifier" }, 88f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 55, UINT8 | ARRAY, "dhcp_parameter_request_list" }, 89f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 56, STRING, "dhcp_message" }, 90f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 57, UINT16, "dhcp_max_message_size" }, 91f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 58, UINT32 | REQUEST, "dhcp_renewal_time" }, 92f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 59, UINT32 | REQUEST, "dhcp_rebinding_time" }, 93f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 64, STRING, "nisplus_domain" }, 94f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 65, IPV4 | ARRAY, "nisplus_servers" }, 95f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 66, STRING, "tftp_server_name" }, 96f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 67, STRING, "bootfile_name" }, 97f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 68, IPV4 | ARRAY, "mobile_ip_home_agent" }, 98f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 69, IPV4 | ARRAY, "smtp_server" }, 99f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 70, IPV4 | ARRAY, "pop_server" }, 100f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 71, IPV4 | ARRAY, "nntp_server" }, 101f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 72, IPV4 | ARRAY, "www_server" }, 102f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 73, IPV4 | ARRAY, "finger_server" }, 103f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 74, IPV4 | ARRAY, "irc_server" }, 104f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 75, IPV4 | ARRAY, "streettalk_server" }, 105f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 76, IPV4 | ARRAY, "streettalk_directory_assistance_server" }, 106f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 77, STRING, "user_class" }, 107f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 85, IPV4 | ARRAY, "nds_servers" }, 108f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 86, STRING, "nds_tree_name" }, 109f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 87, STRING, "nds_context" }, 110f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 88, STRING | RFC3397, "bcms_controller_names" }, 111f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 89, IPV4 | ARRAY, "bcms_controller_address" }, 112f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 91, UINT32, "client_last_transaction_time" }, 113f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 92, IPV4 | ARRAY, "associated_ip" }, 114f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 98, STRING, "uap_servers" }, 115f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 112, IPV4 | ARRAY, "netinfo_server_address" }, 116f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 113, STRING, "netinfo_server_tag" }, 117f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 114, STRING, "default_url" }, 118f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 118, IPV4, "subnet_selection" }, 119f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 119, STRING | RFC3397, "domain_search" }, 120f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 121, RFC3442 | REQUEST, "classless_static_routes" }, 121f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 249, RFC3442, "ms-classless_static_routes" }, 122f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project { 0, 0, NULL } 123f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}; 124f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 125f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstruct dhcp_message * 126e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtget_lease_from_file(const char *leasefile) 127f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 128f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int fd; 129f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct dhcp_message *dhcp; 130f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ssize_t bytes; 131f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 132f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project fd = open(leasefile, O_RDONLY); 133f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (fd == -1) 134f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return NULL; 135f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project dhcp = malloc(sizeof(*dhcp)); 136f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memset(dhcp, 0, sizeof(*dhcp)); 137f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project bytes = read(fd, dhcp, sizeof(*dhcp)); 138f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project close(fd); 139f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (bytes < 0) { 140f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project free(dhcp); 141f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project dhcp = NULL; 142f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 143f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return dhcp; 144f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 145f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 146f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic uint8_t *dhcp_opt_buffer = NULL; 147f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 148f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic int 149f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectvalid_length(uint8_t option, int dl, int *type) 150f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 151f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project const struct dhcp_opt *opt; 152f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ssize_t sz; 153f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 154f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (dl == 0) 155f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 156f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 157f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project for (opt = dhcp_opts; opt->option; opt++) { 158f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (opt->option != option) 159f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project continue; 160f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 161f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (type) 162f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *type = opt->type; 163f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 164f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (opt->type == 0 || opt->type & STRING || opt->type & RFC3442) 165f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 166f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 167f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project sz = 0; 168f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (opt->type & UINT32 || opt->type & IPV4) 169f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project sz = sizeof(uint32_t); 170f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (opt->type & UINT16) 171f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project sz = sizeof(uint16_t); 172f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (opt->type & UINT8) 173f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project sz = sizeof(uint8_t); 174f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (opt->type & IPV4 || opt->type & ARRAY) 175f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return dl % sz; 176f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return (dl == sz ? 0 : -1); 177f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 178f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 179f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* unknown option, so let it pass */ 180f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 181f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 182f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 183f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic void 184f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectfree_option_buffer(void) 185f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 186f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project free(dhcp_opt_buffer); 187f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 188f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 189f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 190f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define get_option_raw(dhcp, opt) get_option(dhcp, opt, NULL, NULL) 191f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic const uint8_t * 192f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectget_option(const struct dhcp_message *dhcp, uint8_t opt, int *len, int *type) 193f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 194f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project const uint8_t *p = dhcp->options; 195f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project const uint8_t *e = p + sizeof(dhcp->options); 196f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint8_t l, ol = 0; 197f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint8_t o = 0; 198f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint8_t overl = 0; 199f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint8_t *bp = NULL; 200f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project const uint8_t *op = NULL; 201f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project int bl = 0; 202f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 203f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project while (p < e) { 204f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project o = *p++; 205f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (o == opt) { 206f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (op) { 207f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (!dhcp_opt_buffer) { 208f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project dhcp_opt_buffer = malloc(sizeof(struct dhcp_message)); 209f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project atexit(free_option_buffer); 210f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 211f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (!bp) 212f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project bp = dhcp_opt_buffer; 213f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memcpy(bp, op, ol); 214f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project bp += ol; 215f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 216f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project ol = *p; 217f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project op = p + 1; 218f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project bl += ol; 219f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 220f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project switch (o) { 221f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project case DHO_PAD: 222f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project continue; 223f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project case DHO_END: 224f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (overl & 1) { 225f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* bit 1 set means parse boot file */ 226f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project overl &= ~1; 227f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p = dhcp->bootfile; 228f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project e = p + sizeof(dhcp->bootfile); 229f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } else if (overl & 2) { 230f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* bit 2 set means parse server name */ 231f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project overl &= ~2; 232f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p = dhcp->servername; 233f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project e = p + sizeof(dhcp->servername); 234f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } else 235f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project goto exit; 236f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project break; 237f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project case DHO_OPTIONSOVERLOADED: 238f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* Ensure we only get this option once */ 239f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (!overl) 240f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project overl = p[1]; 241f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project break; 242f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 243f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project l = *p++; 244f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project p += l; 245f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 246f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 247f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectexit: 248f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (valid_length(o, bl, type) == -1) { 249f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project errno = EINVAL; 250f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return NULL; 251f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 252f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (len) 253f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *len = bl; 254f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (bp) { 255f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memcpy(bp, op, ol); 256f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return (const uint8_t *)&dhcp_opt_buffer; 257f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 258f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (op) 259f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return op; 260f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project errno = ENOENT; 261f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return NULL; 262f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 263f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 264f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectint 265938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidtget_option_addr32(uint32_t *a, const struct dhcp_message *dhcp, uint8_t option) 266f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 267f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project const uint8_t *p = get_option_raw(dhcp, option); 268f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 269f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (!p) 270f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 271f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project memcpy(a, p, sizeof(*a)); 272f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 273f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 274f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 275f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectint 276f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectget_option_uint32(uint32_t *i, const struct dhcp_message *dhcp, uint8_t option) 277f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 278f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint32_t a; 279f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 280938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (get_option_addr32(&a, dhcp, option) == -1) 281f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return -1; 282f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 283f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *i = ntohl(a); 284f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 285f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 286f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 287f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectuint32_t 288f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectget_netmask(uint32_t addr) 289f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 290f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project uint32_t dst; 291f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 292f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (addr == 0) 293f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 294f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 295f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project dst = htonl(addr); 296f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (IN_CLASSA(dst)) 297f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return ntohl(IN_CLASSA_NET); 298f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (IN_CLASSB (dst)) 299f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return ntohl(IN_CLASSB_NET); 300f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (IN_CLASSC (dst)) 301f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return ntohl(IN_CLASSC_NET); 302f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 303f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 304f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 305f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 306f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectvoid showlease(struct dhcp_lease *lease) 307f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 308f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project printf("addr: %s\n", inet_ntoa(lease->addr)); 309f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project printf("net: %s\n", inet_ntoa(lease->net)); 310f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project printf("leasetime: %d\n", lease->leasetime); 311f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project printf("renew: %d\n", lease->renewaltime); 312f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project printf("rebind: %d\n", lease->rebindtime); 313f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project printf("server: %s\n", inet_ntoa(lease->server)); 314f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 315f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define MAX_LEASETIME 2147460 316f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 317f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectint 318f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectmain(int argc, char *argv[]) 319f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{ 320f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct dhcp_message *dhcp; 321f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project struct dhcp_lease *lease; 322f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project char leasefile[PATH_MAX]; 323f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 324f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (argc < 2) { 325f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project fprintf(stderr, "Usage: %s <interface>\n", argv[0]); 326f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project exit(1); 327f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 328f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project snprintf(leasefile, PATH_MAX, LEASEFILE, argv[1]); 329e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if ((dhcp = get_lease_from_file(leasefile)) == NULL) { 330f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project fprintf(stderr, "Couldn't read lease file: %s\n", strerror(errno)); 331f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project exit(1); 332f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project } 333f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project lease = malloc(sizeof(*lease)); 334f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project lease->frominfo = 0; 335f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project lease->addr.s_addr = dhcp->yiaddr; 336f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project 337938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt if (get_option_addr32(&lease->net.s_addr, dhcp, DHO_SUBNETMASK) == -1) 338f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project lease->net.s_addr = get_netmask(dhcp->yiaddr); 339f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (get_option_uint32(&lease->leasetime, dhcp, DHO_LEASETIME) != 0) 340f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project lease->leasetime = DEFAULT_LEASETIME; 341938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt get_option_addr32(&lease->server.s_addr, dhcp, DHO_SERVERID); 342f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project /* Dm: limit lease time value to avoid negative numbers when 343f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project converting to milliseconds */ 344f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if ((lease->leasetime != ~0U) && (lease->leasetime > MAX_LEASETIME)) 345f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project lease->leasetime = MAX_LEASETIME; 346f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (get_option_uint32(&lease->renewaltime, dhcp, DHO_RENEWALTIME) != 0) 347f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project lease->renewaltime = 0; 348f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project if (get_option_uint32(&lease->rebindtime, dhcp, DHO_REBINDTIME) != 0) 349f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project lease->rebindtime = 0; 350f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project showlease(lease); 351f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project free(lease); 352f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project return 0; 353f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project} 354