diff options
| author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:29:04 -0800 |
|---|---|---|
| committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:29:04 -0800 |
| commit | e54eebbf1a908d65ee8cf80bab62821c05666d70 (patch) | |
| tree | 4b825dc642cb6eb9a060e54bf8d69288fbee4904 /libnetutils | |
| parent | a1e1c1b106423de09bc918502e7a51d4ffe5a4ae (diff) | |
| download | system_core-e54eebbf1a908d65ee8cf80bab62821c05666d70.tar.gz system_core-e54eebbf1a908d65ee8cf80bab62821c05666d70.tar.bz2 system_core-e54eebbf1a908d65ee8cf80bab62821c05666d70.zip | |
auto import from //depot/cupcake/@135843
Diffstat (limited to 'libnetutils')
| -rw-r--r-- | libnetutils/Android.mk | 23 | ||||
| -rw-r--r-- | libnetutils/dhcp_utils.c | 207 | ||||
| -rw-r--r-- | libnetutils/dhcpclient.c | 562 | ||||
| -rw-r--r-- | libnetutils/dhcpmsg.c | 100 | ||||
| -rw-r--r-- | libnetutils/dhcpmsg.h | 106 | ||||
| -rw-r--r-- | libnetutils/ifc_utils.c | 428 | ||||
| -rw-r--r-- | libnetutils/ifc_utils.h | 35 | ||||
| -rw-r--r-- | libnetutils/packet.c | 239 | ||||
| -rw-r--r-- | libnetutils/packet.h | 25 |
9 files changed, 0 insertions, 1725 deletions
diff --git a/libnetutils/Android.mk b/libnetutils/Android.mk deleted file mode 100644 index 46102d55..00000000 --- a/libnetutils/Android.mk +++ /dev/null @@ -1,23 +0,0 @@ -LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_SRC_FILES:= \ - dhcpclient.c \ - dhcpmsg.c \ - dhcp_utils.c \ - ifc_utils.c \ - packet.c - -LOCAL_SHARED_LIBRARIES := \ - libcutils - -# need "-lrt" on Linux simulator to pick up clock_gettime -ifeq ($(TARGET_SIMULATOR),true) - ifeq ($(HOST_OS),linux) - LOCAL_LDLIBS += -lrt -lpthread - endif -endif - -LOCAL_MODULE:= libnetutils - -include $(BUILD_SHARED_LIBRARY) diff --git a/libnetutils/dhcp_utils.c b/libnetutils/dhcp_utils.c deleted file mode 100644 index bad2e2ff..00000000 --- a/libnetutils/dhcp_utils.c +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright 2008, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* Utilities for managing the dhcpcd DHCP client daemon */ - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <arpa/inet.h> -#include <netinet/in.h> - -#include <cutils/properties.h> - -static const char DAEMON_NAME[] = "dhcpcd"; -static const char DAEMON_PROP_NAME[] = "init.svc.dhcpcd"; -static const char DHCP_PROP_NAME_PREFIX[] = "dhcp"; -static const int NAP_TIME = 1; /* wait for 1 second at a time */ - /* when polling for property values */ -static char errmsg[100]; - -/* - * Wait for a system property to be assigned a specified value. - * If desired_value is NULL, then just wait for the property to - * be created with any value. maxwait is the maximum amount of - * time in seconds to wait before giving up. - */ -static int wait_for_property(const char *name, const char *desired_value, int maxwait) -{ - char value[PROPERTY_VALUE_MAX] = {'\0'}; - int maxnaps = maxwait / NAP_TIME; - - if (maxnaps < 1) { - maxnaps = 1; - } - - while (maxnaps-- > 0) { - usleep(1000000); - if (property_get(name, value, NULL)) { - if (desired_value == NULL || - strcmp(value, desired_value) == 0) { - return 0; - } - } - } - return -1; /* failure */ -} - -static void fill_ip_info(const char *interface, - in_addr_t *ipaddr, - in_addr_t *gateway, - in_addr_t *mask, - in_addr_t *dns1, - in_addr_t *dns2, - in_addr_t *server, - uint32_t *lease) -{ - char prop_name[PROPERTY_KEY_MAX]; - char prop_value[PROPERTY_VALUE_MAX]; - struct in_addr addr; - in_addr_t iaddr; - - snprintf(prop_name, sizeof(prop_name), "%s.%s.ipaddress", DHCP_PROP_NAME_PREFIX, interface); - if (property_get(prop_name, prop_value, NULL) && inet_aton(prop_value, &addr)) { - *ipaddr = addr.s_addr; - } else { - *ipaddr = 0; - } - snprintf(prop_name, sizeof(prop_name), "%s.%s.gateway", DHCP_PROP_NAME_PREFIX, interface); - if (property_get(prop_name, prop_value, NULL) && inet_aton(prop_value, &addr)) { - *gateway = addr.s_addr; - } else { - *gateway = 0; - } - snprintf(prop_name, sizeof(prop_name), "%s.%s.mask", DHCP_PROP_NAME_PREFIX, interface); - if (property_get(prop_name, prop_value, NULL) && inet_aton(prop_value, &addr)) { - *mask = addr.s_addr; - } else { - *mask = 0; - } - snprintf(prop_name, sizeof(prop_name), "%s.%s.dns1", DHCP_PROP_NAME_PREFIX, interface); - if (property_get(prop_name, prop_value, NULL) && inet_aton(prop_value, &addr)) { - *dns1 = addr.s_addr; - } else { - *dns1 = 0; - } - snprintf(prop_name, sizeof(prop_name), "%s.%s.dns2", DHCP_PROP_NAME_PREFIX, interface); - if (property_get(prop_name, prop_value, NULL) && inet_aton(prop_value, &addr)) { - *dns2 = addr.s_addr; - } else { - *dns2 = 0; - } - snprintf(prop_name, sizeof(prop_name), "%s.%s.server", DHCP_PROP_NAME_PREFIX, interface); - if (property_get(prop_name, prop_value, NULL) && inet_aton(prop_value, &addr)) { - *server = addr.s_addr; - } else { - *server = 0; - } - snprintf(prop_name, sizeof(prop_name), "%s.%s.leasetime", DHCP_PROP_NAME_PREFIX, interface); - if (property_get(prop_name, prop_value, NULL)) { - *lease = atol(prop_value); - } -} - -/* - * Start the dhcp client daemon, and wait for it to finish - * configuring the interface. - */ -int dhcp_do_request(const char *interface, - in_addr_t *ipaddr, - in_addr_t *gateway, - in_addr_t *mask, - in_addr_t *dns1, - in_addr_t *dns2, - in_addr_t *server, - uint32_t *lease) -{ - char result_prop_name[PROPERTY_KEY_MAX]; - char prop_value[PROPERTY_VALUE_MAX] = {'\0'}; - const char *ctrl_prop = "ctl.start"; - const char *desired_status = "running"; - - snprintf(result_prop_name, sizeof(result_prop_name), "%s.%s.result", - DHCP_PROP_NAME_PREFIX, - interface); - /* Erase any previous setting of the dhcp result property */ - property_set(result_prop_name, ""); - - /* Start the daemon and wait until it's ready */ - property_set(ctrl_prop, DAEMON_NAME); - if (wait_for_property(DAEMON_PROP_NAME, desired_status, 10) < 0) { - snprintf(errmsg, sizeof(errmsg), "%s", "Timed out waiting for dhcpcd to start"); - return -1; - } - - /* Wait for the daemon to return a result */ - if (wait_for_property(result_prop_name, NULL, 30) < 0) { - snprintf(errmsg, sizeof(errmsg), "%s", "Timed out waiting for DHCP to finish"); - return -1; - } - - if (!property_get(result_prop_name, prop_value, NULL)) { - /* shouldn't ever happen, given the success of wait_for_property() */ - snprintf(errmsg, sizeof(errmsg), "%s", "DHCP result property was not set"); - return -1; - } - if (strcmp(prop_value, "ok") == 0) { - fill_ip_info(interface, ipaddr, gateway, mask, dns1, dns2, server, lease); - return 0; - } else { - snprintf(errmsg, sizeof(errmsg), "DHCP result was %s", prop_value); - return -1; - } -} - -/** - * Stop the DHCP client daemon. - */ -int dhcp_stop(const char *interface) -{ - char result_prop_name[PROPERTY_KEY_MAX]; - const char *ctrl_prop = "ctl.stop"; - const char *desired_status = "stopped"; - - snprintf(result_prop_name, sizeof(result_prop_name), "%s.%s.result", - DHCP_PROP_NAME_PREFIX, - interface); - /* Stop the daemon and wait until it's reported to be stopped */ - property_set(ctrl_prop, DAEMON_NAME); - if (wait_for_property(DAEMON_PROP_NAME, desired_status, 5) < 0) { - return -1; - } - property_set(result_prop_name, "failed"); - return 0; -} - -/** - * Release the current DHCP client lease. - */ -int dhcp_release_lease(const char *interface) -{ - const char *ctrl_prop = "ctl.stop"; - const char *desired_status = "stopped"; - - /* Stop the daemon and wait until it's reported to be stopped */ - property_set(ctrl_prop, DAEMON_NAME); - if (wait_for_property(DAEMON_PROP_NAME, desired_status, 5) < 0) { - return -1; - } - return 0; -} - -char *dhcp_get_errmsg() { - return errmsg; -} diff --git a/libnetutils/dhcpclient.c b/libnetutils/dhcpclient.c deleted file mode 100644 index 45e392a6..00000000 --- a/libnetutils/dhcpclient.c +++ /dev/null @@ -1,562 +0,0 @@ -/* - * Copyright 2008, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <stdio.h> -#include <stdarg.h> -#include <stdlib.h> -#include <unistd.h> -#include <errno.h> -#include <string.h> - -#include <time.h> -#include <sys/time.h> -#include <poll.h> - -#include <sys/socket.h> -#include <sys/select.h> -#include <sys/types.h> -#include <netinet/in.h> - -#include <cutils/properties.h> -#define LOG_TAG "DHCP" -#include <cutils/log.h> - -#include <dirent.h> - -#include "dhcpmsg.h" -#include "ifc_utils.h" -#include "packet.h" - -#define VERBOSE 2 - -static int verbose = 1; -static char errmsg[2048]; - -typedef unsigned long long msecs_t; -#if VERBOSE -void dump_dhcp_msg(); -#endif - -msecs_t get_msecs(void) -{ - struct timespec ts; - - if (clock_gettime(CLOCK_MONOTONIC, &ts)) { - return 0; - } else { - return (((msecs_t) ts.tv_sec) * ((msecs_t) 1000)) + - (((msecs_t) ts.tv_nsec) / ((msecs_t) 1000000)); - } -} - -void printerr(char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - vsnprintf(errmsg, sizeof(errmsg), fmt, ap); - va_end(ap); - - LOGD(errmsg); -} - -const char *dhcp_lasterror() -{ - return errmsg; -} - -int fatal(const char *reason) -{ - printerr("%s: %s\n", reason, strerror(errno)); - return -1; -// exit(1); -} - -const char *ipaddr(uint32_t addr) -{ - static char buf[32]; - - sprintf(buf,"%d.%d.%d.%d", - addr & 255, - ((addr >> 8) & 255), - ((addr >> 16) & 255), - (addr >> 24)); - return buf; -} - -typedef struct dhcp_info dhcp_info; - -struct dhcp_info { - uint32_t type; - - uint32_t ipaddr; - uint32_t gateway; - uint32_t netmask; - - uint32_t dns1; - uint32_t dns2; - - uint32_t serveraddr; - uint32_t lease; -}; - -dhcp_info last_good_info; - -void get_dhcp_info(uint32_t *ipaddr, uint32_t *gateway, uint32_t *mask, - uint32_t *dns1, uint32_t *dns2, uint32_t *server, - uint32_t *lease) -{ - *ipaddr = last_good_info.ipaddr; - *gateway = last_good_info.gateway; - *mask = last_good_info.netmask; - *dns1 = last_good_info.dns1; - *dns2 = last_good_info.dns2; - *server = last_good_info.serveraddr; - *lease = last_good_info.lease; -} - -static int ifc_configure(const char *ifname, dhcp_info *info) -{ - char dns_prop_name[PROPERTY_KEY_MAX]; - - if (ifc_set_addr(ifname, info->ipaddr)) { - printerr("failed to set ipaddr %s: %s\n", ipaddr(info->ipaddr), strerror(errno)); - return -1; - } - if (ifc_set_mask(ifname, info->netmask)) { - printerr("failed to set netmask %s: %s\n", ipaddr(info->netmask), strerror(errno)); - return -1; - } - if (ifc_create_default_route(ifname, info->gateway)) { - printerr("failed to set default route %s: %s\n", ipaddr(info->gateway), strerror(errno)); - return -1; - } - - snprintf(dns_prop_name, sizeof(dns_prop_name), "net.%s.dns1", ifname); - property_set(dns_prop_name, info->dns1 ? ipaddr(info->dns1) : ""); - snprintf(dns_prop_name, sizeof(dns_prop_name), "net.%s.dns2", ifname); - property_set(dns_prop_name, info->dns2 ? ipaddr(info->dns2) : ""); - - last_good_info = *info; - - return 0; -} - -static const char *dhcp_type_to_name(uint32_t type) -{ - switch(type) { - case DHCPDISCOVER: return "discover"; - case DHCPOFFER: return "offer"; - case DHCPREQUEST: return "request"; - case DHCPDECLINE: return "decline"; - case DHCPACK: return "ack"; - case DHCPNAK: return "nak"; - case DHCPRELEASE: return "release"; - case DHCPINFORM: return "inform"; - default: return "???"; - } -} - -void dump_dhcp_info(dhcp_info *info) -{ - char addr[20], gway[20], mask[20]; - LOGD("--- dhcp %s (%d) ---", - dhcp_type_to_name(info->type), info->type); - strcpy(addr, ipaddr(info->ipaddr)); - strcpy(gway, ipaddr(info->gateway)); - strcpy(mask, ipaddr(info->netmask)); - LOGD("ip %s gw %s mask %s", addr, gway, mask); - if (info->dns1) LOGD("dns1: %s", ipaddr(info->dns1)); - if (info->dns2) LOGD("dns2: %s", ipaddr(info->dns2)); - LOGD("server %s, lease %d seconds", - ipaddr(info->serveraddr), info->lease); -} - - -int decode_dhcp_msg(dhcp_msg *msg, int len, dhcp_info *info) -{ - uint8_t *x; - unsigned int opt; - int optlen; - - memset(info, 0, sizeof(dhcp_info)); - if (len < (DHCP_MSG_FIXED_SIZE + 4)) return -1; - - len -= (DHCP_MSG_FIXED_SIZE + 4); - - if (msg->options[0] != OPT_COOKIE1) return -1; - if (msg->options[1] != OPT_COOKIE2) return -1; - if (msg->options[2] != OPT_COOKIE3) return -1; - if (msg->options[3] != OPT_COOKIE4) return -1; - - x = msg->options + 4; - - while (len > 2) { - opt = *x++; - if (opt == OPT_PAD) { - len--; - continue; - } - if (opt == OPT_END) { - break; - } - optlen = *x++; - len -= 2; - if (optlen > len) { - break; - } - switch(opt) { - case OPT_SUBNET_MASK: - if (optlen >= 4) memcpy(&info->netmask, x, 4); - break; - case OPT_GATEWAY: - if (optlen >= 4) memcpy(&info->gateway, x, 4); - break; - case OPT_DNS: - if (optlen >= 4) memcpy(&info->dns1, x + 0, 4); - if (optlen >= 8) memcpy(&info->dns2, x + 4, 4); - break; - case OPT_LEASE_TIME: - if (optlen >= 4) { - memcpy(&info->lease, x, 4); - info->lease = ntohl(info->lease); - } - break; - case OPT_SERVER_ID: - if (optlen >= 4) memcpy(&info->serveraddr, x, 4); - break; - case OPT_MESSAGE_TYPE: - info->type = *x; - break; - default: - break; - } - x += optlen; - len -= optlen; - } - - info->ipaddr = msg->yiaddr; - - return 0; -} - -#if VERBOSE - -static void hex2str(char *buf, const unsigned char *array, int len) -{ - int i; - char *cp = buf; - - for (i = 0; i < len; i++) { - cp += sprintf(cp, " %02x ", array[i]); - } -} - -void dump_dhcp_msg(dhcp_msg *msg, int len) -{ - unsigned char *x; - unsigned int n,c; - int optsz; - const char *name; - char buf[2048]; - - LOGD("===== DHCP message:"); - if (len < DHCP_MSG_FIXED_SIZE) { - LOGD("Invalid length %d, should be %d", len, DHCP_MSG_FIXED_SIZE); - return; - } - - len -= DHCP_MSG_FIXED_SIZE; - - if (msg->op == OP_BOOTREQUEST) - name = "BOOTREQUEST"; - else if (msg->op == OP_BOOTREPLY) - name = "BOOTREPLY"; - else - name = "????"; - LOGD("op = %s (%d), htype = %d, hlen = %d, hops = %d", - name, msg->op, msg->htype, msg->hlen, msg->hops); - LOGD("xid = 0x%08x secs = %d, flags = 0x%04x optlen = %d", - ntohl(msg->xid), ntohs(msg->secs), ntohs(msg->flags), len); - LOGD("ciaddr = %s", ipaddr(msg->ciaddr)); - LOGD("yiaddr = %s", ipaddr(msg->yiaddr)); - LOGD("siaddr = %s", ipaddr(msg->siaddr)); - LOGD("giaddr = %s", ipaddr(msg->giaddr)); - - c = msg->hlen > 16 ? 16 : msg->hlen; - hex2str(buf, msg->chaddr, c); - LOGD("chaddr = {%s}", buf); - - for (n = 0; n < 64; n++) { - if ((msg->sname[n] < ' ') || (msg->sname[n] > 127)) { - if (msg->sname[n] == 0) break; - msg->sname[n] = '.'; - } - } - msg->sname[63] = 0; - - for (n = 0; n < 128; n++) { - if ((msg->file[n] < ' ') || (msg->file[n] > 127)) { - if (msg->file[n] == 0) break; - msg->file[n] = '.'; - } - } - msg->file[127] = 0; - - LOGD("sname = '%s'", msg->sname); - LOGD("file = '%s'", msg->file); - - if (len < 4) return; - len -= 4; - x = msg->options + 4; - - while (len > 2) { - if (*x == 0) { - x++; - len--; - continue; - } - if (*x == OPT_END) { - break; - } - len -= 2; - optsz = x[1]; - if (optsz > len) break; - if (x[0] == OPT_DOMAIN_NAME || x[0] == OPT_MESSAGE) { - if ((unsigned int)optsz < sizeof(buf) - 1) { - n = optsz; - } else { - n = sizeof(buf) - 1; - } - memcpy(buf, &x[2], n); - buf[n] = '\0'; - } else { - hex2str(buf, &x[2], optsz); - } - if (x[0] == OPT_MESSAGE_TYPE) - name = dhcp_type_to_name(x[2]); - else - name = NULL; - LOGD("op %d len %d {%s} %s", x[0], optsz, buf, name == NULL ? "" : name); - len -= optsz; - x = x + optsz + 2; - } -} - -#endif - -static int send_message(int sock, int if_index, dhcp_msg *msg, int size) -{ -#if VERBOSE > 1 - dump_dhcp_msg(msg, size); -#endif - return send_packet(sock, if_index, msg, size, INADDR_ANY, INADDR_BROADCAST, - PORT_BOOTP_CLIENT, PORT_BOOTP_SERVER); -} - -static int is_valid_reply(dhcp_msg *msg, dhcp_msg *reply, int sz) -{ - if (sz < DHCP_MSG_FIXED_SIZE) { - if (verbose) LOGD("netcfg: Wrong size %d != %d\n", sz, DHCP_MSG_FIXED_SIZE); - return 0; - } - if (reply->op != OP_BOOTREPLY) { - if (verbose) LOGD("netcfg: Wrong Op %d != %d\n", reply->op, OP_BOOTREPLY); - return 0; - } - if (reply->xid != msg->xid) { - if (verbose) LOGD("netcfg: Wrong Xid 0x%x != 0x%x\n", ntohl(reply->xid), - ntohl(msg->xid)); - return 0; - } - if (reply->htype != msg->htype) { - if (verbose) LOGD("netcfg: Wrong Htype %d != %d\n", reply->htype, msg->htype); - return 0; - } - if (reply->hlen != msg->hlen) { - if (verbose) LOGD("netcfg: Wrong Hlen %d != %d\n", reply->hlen, msg->hlen); - return 0; - } - if (memcmp(msg->chaddr, reply->chaddr, msg->hlen)) { - if (verbose) LOGD("netcfg: Wrong chaddr %x != %x\n", *(reply->chaddr),*(msg->chaddr)); - return 0; - } - return 1; -} - -#define STATE_SELECTING 1 -#define STATE_REQUESTING 2 - -#define TIMEOUT_INITIAL 4000 -#define TIMEOUT_MAX 32000 - -int dhcp_init_ifc(const char *ifname) -{ - dhcp_msg discover_msg; - dhcp_msg request_msg; - dhcp_msg reply; - dhcp_msg *msg; - dhcp_info info; - int s, r, size; - int valid_reply; - uint32_t xid; - unsigned char hwaddr[6]; - struct pollfd pfd; - unsigned int state; - unsigned int timeout; - int if_index; - - xid = (uint32_t) get_msecs(); - - if (ifc_get_hwaddr(ifname, hwaddr)) { - return fatal("cannot obtain interface address"); - } - if (ifc_get_ifindex(ifname, &if_index)) { - return fatal("cannot obtain interface index"); - } - - s = open_raw_socket(ifname, hwaddr, if_index); - - timeout = TIMEOUT_INITIAL; - state = STATE_SELECTING; - info.type = 0; - goto transmit; - - for (;;) { - pfd.fd = s; - pfd.events = POLLIN; - pfd.revents = 0; - r = poll(&pfd, 1, timeout); - - if (r == 0) { -#if VERBOSE - printerr("TIMEOUT\n"); -#endif - if (timeout >= TIMEOUT_MAX) { - printerr("timed out\n"); - if ( info.type == DHCPOFFER ) { - printerr("no acknowledgement from DHCP server\nconfiguring %s with offered parameters\n", ifname); - return ifc_configure(ifname, &info); - } - errno = ETIME; - close(s); - return -1; - } - timeout = timeout * 2; - - transmit: - size = 0; - msg = NULL; - switch(state) { - case STATE_SELECTING: - msg = &discover_msg; - size = init_dhcp_discover_msg(msg, hwaddr, xid); - break; - case STATE_REQUESTING: - msg = &request_msg; - size = init_dhcp_request_msg(msg, hwaddr, xid, info.ipaddr, info.serveraddr); - break; - default: - r = 0; - } - if (size != 0) { - r = send_message(s, if_index, msg, size); - if (r < 0) { - printerr("error sending dhcp msg: %s\n", strerror(errno)); - } - } - continue; - } - - if (r < 0) { - if ((errno == EAGAIN) || (errno == EINTR)) { - continue; - } - return fatal("poll failed"); - } - - errno = 0; - r = receive_packet(s, &reply); - if (r < 0) { - if (errno != 0) { - LOGD("receive_packet failed (%d): %s", r, strerror(errno)); - if (errno == ENETDOWN || errno == ENXIO) { - return -1; - } - } - continue; - } - -#if VERBOSE > 1 - dump_dhcp_msg(&reply, r); -#endif - decode_dhcp_msg(&reply, r, &info); - - if (state == STATE_SELECTING) { - valid_reply = is_valid_reply(&discover_msg, &reply, r); - } else { - valid_reply = is_valid_reply(&request_msg, &reply, r); - } - if (!valid_reply) { - printerr("invalid reply\n"); - continue; - } - - if (verbose) dump_dhcp_info(&info); - - switch(state) { - case STATE_SELECTING: - if (info.type == DHCPOFFER) { - state = STATE_REQUESTING; - timeout = TIMEOUT_INITIAL; - xid++; - goto transmit; - } - break; - case STATE_REQUESTING: - if (info.type == DHCPACK) { - printerr("configuring %s\n", ifname); - close(s); - return ifc_configure(ifname, &info); - } else if (info.type == DHCPNAK) { - printerr("configuration request denied\n"); - close(s); - return -1; - } else { - printerr("ignoring %s message in state %d\n", - dhcp_type_to_name(info.type), state); - } - break; - } - } - close(s); - return 0; -} - -int do_dhcp(char *iname) -{ - if (ifc_set_addr(iname, 0)) { - printerr("failed to set ip addr for %s to 0.0.0.0: %s\n", iname, strerror(errno)); - return -1; - } - - if (ifc_up(iname)) { - printerr("failed to bring up interface %s: %s\n", iname, strerror(errno)); - return -1; - } - - return dhcp_init_ifc(iname); -} diff --git a/libnetutils/dhcpmsg.c b/libnetutils/dhcpmsg.c deleted file mode 100644 index 1e0a233f..00000000 --- a/libnetutils/dhcpmsg.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright 2008, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <stdio.h> -#include <stdarg.h> -#include <string.h> -#include <netinet/in.h> - -#include "dhcpmsg.h" - -static void *init_dhcp_msg(dhcp_msg *msg, int type, void *hwaddr, uint32_t xid) -{ - uint8_t *x; - - memset(msg, 0, sizeof(dhcp_msg)); - - msg->op = OP_BOOTREQUEST; - msg->htype = HTYPE_ETHER; - msg->hlen = 6; - msg->hops = 0; - - msg->flags = htons(FLAGS_BROADCAST); - - msg->xid = xid; - - memcpy(msg->chaddr, hwaddr, 6); - - x = msg->options; - - *x++ = OPT_COOKIE1; - *x++ = OPT_COOKIE2; - *x++ = OPT_COOKIE3; - *x++ = OPT_COOKIE4; - - *x++ = OPT_MESSAGE_TYPE; - *x++ = 1; - *x++ = type; - - return x; -} - -int init_dhcp_discover_msg(dhcp_msg *msg, void *hwaddr, uint32_t xid) -{ - uint8_t *x; - - x = init_dhcp_msg(msg, DHCPDISCOVER, hwaddr, xid); - - *x++ = OPT_PARAMETER_LIST; - *x++ = 4; - *x++ = OPT_SUBNET_MASK; - *x++ = OPT_GATEWAY; - *x++ = OPT_DNS; - *x++ = OPT_BROADCAST_ADDR; - - *x++ = OPT_END; - - return DHCP_MSG_FIXED_SIZE + (x - msg->options); -} - -int init_dhcp_request_msg(dhcp_msg *msg, void *hwaddr, uint32_t xid, - uint32_t ipaddr, uint32_t serveraddr) -{ - uint8_t *x; - - x = init_dhcp_msg(msg, DHCPREQUEST, hwaddr, xid); - - *x++ = OPT_PARAMETER_LIST; - *x++ = 4; - *x++ = OPT_SUBNET_MASK; - *x++ = OPT_GATEWAY; - *x++ = OPT_DNS; - *x++ = OPT_BROADCAST_ADDR; - - *x++ = OPT_REQUESTED_IP; - *x++ = 4; - memcpy(x, &ipaddr, 4); - x += 4; - - *x++ = OPT_SERVER_ID; - *x++ = 4; - memcpy(x, &serveraddr, 4); - x += 4; - - *x++ = OPT_END; - - return DHCP_MSG_FIXED_SIZE + (x - msg->options); -} diff --git a/libnetutils/dhcpmsg.h b/libnetutils/dhcpmsg.h deleted file mode 100644 index c86e400d..00000000 --- a/libnetutils/dhcpmsg.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2008, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _WIFI_DHCP_H_ -#define _WIFI_DHCP_H_ - -#include <sys/types.h> - -#define PORT_BOOTP_SERVER 67 -#define PORT_BOOTP_CLIENT 68 - -/* RFC 2131 p 9 */ -typedef struct dhcp_msg dhcp_msg; - -#define OP_BOOTREQUEST 1 -#define OP_BOOTREPLY 2 - -#define FLAGS_BROADCAST 0x8000 - -#define HTYPE_ETHER 1 - -struct dhcp_msg -{ - uint8_t op; /* BOOTREQUEST / BOOTREPLY */ - uint8_t htype; /* hw addr type */ - uint8_t hlen; /* hw addr len */ - uint8_t hops; /* client set to 0 */ - - uint32_t xid; /* transaction id */ - - uint16_t secs; /* seconds since start of acq */ - uint16_t flags; - - uint32_t ciaddr; /* client IP addr */ - uint32_t yiaddr; /* your (client) IP addr */ - uint32_t siaddr; /* ip addr of next server */ - /* (DHCPOFFER and DHCPACK) */ - uint32_t giaddr; /* relay agent IP addr */ - - uint8_t chaddr[16]; /* client hw addr */ - char sname[64]; /* asciiz server hostname */ - char file[128]; /* asciiz boot file name */ - - uint8_t options[1024]; /* optional parameters */ -}; - -#define DHCP_MSG_FIXED_SIZE 236 - -/* first four bytes of options are a cookie to indicate that -** the payload are DHCP options as opposed to some other BOOTP -** extension. -*/ -#define OPT_COOKIE1 0x63 -#define OPT_COOKIE2 0x82 -#define OPT_COOKIE3 0x53 -#define OPT_COOKIE4 0x63 - -/* BOOTP/DHCP options - see RFC 2132 */ -#define OPT_PAD 0 - -#define OPT_SUBNET_MASK 1 /* 4 <ipaddr> */ -#define OPT_TIME_OFFSET 2 /* 4 <seconds> */ -#define OPT_GATEWAY 3 /* 4*n <ipaddr> * n */ -#define OPT_DNS 6 /* 4*n <ipaddr> * n */ -#define OPT_DOMAIN_NAME 15 /* n <domainnamestring> */ -#define OPT_BROADCAST_ADDR 28 /* 4 <ipaddr> */ - -#define OPT_REQUESTED_IP 50 /* 4 <ipaddr> */ -#define OPT_LEASE_TIME 51 /* 4 <seconds> */ -#define OPT_MESSAGE_TYPE 53 /* 1 <msgtype> */ -#define OPT_SERVER_ID 54 /* 4 <ipaddr> */ -#define OPT_PARAMETER_LIST 55 /* n <optcode> * n */ -#define OPT_MESSAGE 56 /* n <errorstring> */ -#define OPT_CLASS_ID 60 /* n <opaque> */ -#define OPT_CLIENT_ID 61 /* n <opaque> */ -#define OPT_END 255 - -/* DHCP message types */ -#define DHCPDISCOVER 1 -#define DHCPOFFER 2 -#define DHCPREQUEST 3 -#define DHCPDECLINE 4 -#define DHCPACK 5 -#define DHCPNAK 6 -#define DHCPRELEASE 7 -#define DHCPINFORM 8 - -int init_dhcp_discover_msg(dhcp_msg *msg, void *hwaddr, uint32_t xid); - -int init_dhcp_request_msg(dhcp_msg *msg, void *hwaddr, uint32_t xid, - uint32_t ipaddr, uint32_t serveraddr); - -#endif diff --git a/libnetutils/ifc_utils.c b/libnetutils/ifc_utils.c deleted file mode 100644 index 88635d96..00000000 --- a/libnetutils/ifc_utils.c +++ /dev/null @@ -1,428 +0,0 @@ -/* - * Copyright 2008, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <errno.h> - -#include <sys/socket.h> -#include <sys/select.h> -#include <sys/types.h> -#include <netinet/in.h> -#include <arpa/inet.h> - -#include <linux/if.h> -#include <linux/sockios.h> -#include <linux/route.h> -#include <linux/wireless.h> - -#ifdef ANDROID -#define LOG_TAG "NetUtils" -#include <cutils/log.h> -#include <cutils/properties.h> -#else -#include <stdio.h> -#include <string.h> -#define LOGD printf -#define LOGW printf -#endif - -static int ifc_ctl_sock = -1; -void printerr(char *fmt, ...); - -static const char *ipaddr_to_string(uint32_t addr) -{ - struct in_addr in_addr; - - in_addr.s_addr = addr; - return inet_ntoa(in_addr); -} - -int ifc_init(void) -{ - if (ifc_ctl_sock == -1) { - ifc_ctl_sock = socket(AF_INET, SOCK_DGRAM, 0); - if (ifc_ctl_sock < 0) { - printerr("socket() failed: %s\n", strerror(errno)); - } - } - return ifc_ctl_sock < 0 ? -1 : 0; -} - -void ifc_close(void) -{ - if (ifc_ctl_sock != -1) { - (void)close(ifc_ctl_sock); - ifc_ctl_sock = -1; - } -} - -static void ifc_init_ifr(const char *name, struct ifreq *ifr) -{ - memset(ifr, 0, sizeof(struct ifreq)); - strncpy(ifr->ifr_name, name, IFNAMSIZ); - ifr->ifr_name[IFNAMSIZ - 1] = 0; -} - -int ifc_get_hwaddr(const char *name, void *ptr) -{ - int r; - struct ifreq ifr; - ifc_init_ifr(name, &ifr); - - r = ioctl(ifc_ctl_sock, SIOCGIFHWADDR, &ifr); - if(r < 0) return -1; - - memcpy(ptr, &ifr.ifr_hwaddr.sa_data, 6); - return 0; -} - -int ifc_get_ifindex(const char *name, int *if_indexp) -{ - int r; - struct ifreq ifr; - ifc_init_ifr(name, &ifr); - - r = ioctl(ifc_ctl_sock, SIOCGIFINDEX, &ifr); - if(r < 0) return -1; - - *if_indexp = ifr.ifr_ifindex; - return 0; -} - -static int ifc_set_flags(const char *name, unsigned set, unsigned clr) -{ - struct ifreq ifr; - ifc_init_ifr(name, &ifr); - - if(ioctl(ifc_ctl_sock, SIOCGIFFLAGS, &ifr) < 0) return -1; - ifr.ifr_flags = (ifr.ifr_flags & (~clr)) | set; - return ioctl(ifc_ctl_sock, SIOCSIFFLAGS, &ifr); -} - -int ifc_up(const char *name) -{ - return ifc_set_flags(name, IFF_UP, 0); -} - -int ifc_down(const char *name) -{ - return ifc_set_flags(name, 0, IFF_UP); -} - -static void init_sockaddr_in(struct sockaddr *sa, in_addr_t addr) -{ - struct sockaddr_in *sin = (struct sockaddr_in *) sa; - sin->sin_family = AF_INET; - sin->sin_port = 0; - sin->sin_addr.s_addr = addr; -} - -int ifc_set_addr(const char *name, in_addr_t addr) -{ - struct ifreq ifr; - - ifc_init_ifr(name, &ifr); - init_sockaddr_in(&ifr.ifr_addr, addr); - - return ioctl(ifc_ctl_sock, SIOCSIFADDR, &ifr); -} - -int ifc_set_mask(const char *name, in_addr_t mask) -{ - struct ifreq ifr; - - ifc_init_ifr(name, &ifr); - init_sockaddr_in(&ifr.ifr_addr, mask); - - return ioctl(ifc_ctl_sock, SIOCSIFNETMASK, &ifr); -} - -int ifc_get_info(const char *name, in_addr_t *addr, in_addr_t *mask, unsigned *flags) -{ - struct ifreq ifr; - ifc_init_ifr(name, &ifr); - - if (addr != NULL) { - if(ioctl(ifc_ctl_sock, SIOCGIFADDR, &ifr) < 0) { - *addr = 0; - } else { - *addr = ((struct sockaddr_in*) &ifr.ifr_addr)->sin_addr.s_addr; - } - } - - if (mask != NULL) { - if(ioctl(ifc_ctl_sock, SIOCGIFNETMASK, &ifr) < 0) { - *mask = 0; - } else { - *mask = ((struct sockaddr_in*) &ifr.ifr_addr)->sin_addr.s_addr; - } - } - - if (flags != NULL) { - if(ioctl(ifc_ctl_sock, SIOCGIFFLAGS, &ifr) < 0) { - *flags = 0; - } else { - *flags = ifr.ifr_flags; - } - } - - return 0; -} - - -int ifc_create_default_route(const char *name, in_addr_t addr) -{ - struct rtentry rt; - - memset(&rt, 0, sizeof(rt)); - - rt.rt_dst.sa_family = AF_INET; - rt.rt_flags = RTF_UP | RTF_GATEWAY; - rt.rt_dev = (void*) name; - init_sockaddr_in(&rt.rt_genmask, 0); - init_sockaddr_in(&rt.rt_gateway, addr); - - return ioctl(ifc_ctl_sock, SIOCADDRT, &rt); -} - -int ifc_add_host_route(const char *name, in_addr_t addr) -{ - struct rtentry rt; - int result; - - memset(&rt, 0, sizeof(rt)); - - rt.rt_dst.sa_family = AF_INET; - rt.rt_flags = RTF_UP | RTF_HOST; - rt.rt_dev = (void*) name; - init_sockaddr_in(&rt.rt_dst, addr); - init_sockaddr_in(&rt.rt_genmask, 0); - init_sockaddr_in(&rt.rt_gateway, 0); - - ifc_init(); - result = ioctl(ifc_ctl_sock, SIOCADDRT, &rt); - if (result < 0 && errno == EEXIST) { - result = 0; - } - ifc_close(); - return result; -} - -int ifc_disable(const char *ifname) -{ - int result; - - ifc_init(); - result = ifc_down(ifname); - ifc_set_addr(ifname, 0); - ifc_close(); - return result; -} - -int ifc_reset_connections(const char *ifname) -{ -#ifdef HAVE_ANDROID_OS - int result; - in_addr_t myaddr; - struct ifreq ifr; - - ifc_init(); - ifc_get_info(ifname, &myaddr, NULL, NULL); - ifc_init_ifr(ifname, &ifr); - init_sockaddr_in(&ifr.ifr_addr, myaddr); - result = ioctl(ifc_ctl_sock, SIOCKILLADDR, &ifr); - ifc_close(); - - return result; -#else - return 0; -#endif -} - -/* - * Remove the routes associated with the named interface. - */ -int ifc_remove_host_routes(const char *name) -{ - char ifname[64]; - in_addr_t dest, gway, mask; - int flags, refcnt, use, metric, mtu, win, irtt; - struct rtentry rt; - FILE *fp; - struct in_addr addr; - - fp = fopen("/proc/net/route", "r"); - if (fp == NULL) - return -1; - /* Skip the header line */ - if (fscanf(fp, "%*[^\n]\n") < 0) { - fclose(fp); - return -1; - } - ifc_init(); - for (;;) { - int nread = fscanf(fp, "%63s%X%X%X%d%d%d%X%d%d%d\n", - ifname, &dest, &gway, &flags, &refcnt, &use, &metric, &mask, - &mtu, &win, &irtt); - if (nread != 11) { - break; - } - if ((flags & (RTF_UP|RTF_HOST)) != (RTF_UP|RTF_HOST) - || strcmp(ifname, name) != 0) { - continue; - } - memset(&rt, 0, sizeof(rt)); - rt.rt_dev = (void *)name; - init_sockaddr_in(&rt.rt_dst, dest); - init_sockaddr_in(&rt.rt_gateway, gway); - init_sockaddr_in(&rt.rt_genmask, mask); - addr.s_addr = dest; - if (ioctl(ifc_ctl_sock, SIOCDELRT, &rt) < 0) { - LOGD("failed to remove route for %s to %s: %s", - ifname, inet_ntoa(addr), strerror(errno)); - } - } - fclose(fp); - ifc_close(); - return 0; -} - -/* - * Return the address of the default gateway - * - * TODO: factor out common code from this and remove_host_routes() - * so that we only scan /proc/net/route in one place. - */ -int ifc_get_default_route(const char *ifname) -{ - char name[64]; - in_addr_t dest, gway, mask; - int flags, refcnt, use, metric, mtu, win, irtt; - int result; - FILE *fp; - - fp = fopen("/proc/net/route", "r"); - if (fp == NULL) - return 0; - /* Skip the header line */ - if (fscanf(fp, "%*[^\n]\n") < 0) { - fclose(fp); - return 0; - } - ifc_init(); - result = 0; - for (;;) { - int nread = fscanf(fp, "%63s%X%X%X%d%d%d%X%d%d%d\n", - name, &dest, &gway, &flags, &refcnt, &use, &metric, &mask, - &mtu, &win, &irtt); - if (nread != 11) { - break; - } - if ((flags & (RTF_UP|RTF_GATEWAY)) == (RTF_UP|RTF_GATEWAY) - && dest == 0 - && strcmp(ifname, name) == 0) { - result = gway; - break; - } - } - fclose(fp); - ifc_close(); - return result; -} - -/* - * Sets the specified gateway as the default route for the named interface. - */ -int ifc_set_default_route(const char *ifname, in_addr_t gateway) -{ - struct in_addr addr; - int result; - - ifc_init(); - addr.s_addr = gateway; - if ((result = ifc_create_default_route(ifname, gateway)) < 0) { - LOGD("failed to add %s as default route for %s: %s", - inet_ntoa(addr), ifname, strerror(errno)); - } - ifc_close(); - return result; -} - -/* - * Removes the default route for the named interface. - */ -int ifc_remove_default_route(const char *ifname) -{ - struct rtentry rt; - int result; - - ifc_init(); - memset(&rt, 0, sizeof(rt)); - rt.rt_dev = (void *)ifname; - rt.rt_flags = RTF_UP|RTF_GATEWAY; - init_sockaddr_in(&rt.rt_dst, 0); - if ((result = ioctl(ifc_ctl_sock, SIOCDELRT, &rt)) < 0) { - LOGD("failed to remove default route for %s: %s", ifname, strerror(errno)); - } - ifc_close(); - return result; -} - -int -ifc_configure(const char *ifname, - in_addr_t address, - in_addr_t netmask, - in_addr_t gateway, - in_addr_t dns1, - in_addr_t dns2) { - - char dns_prop_name[PROPERTY_KEY_MAX]; - - ifc_init(); - - if (ifc_up(ifname)) { - printerr("failed to turn on interface %s: %s\n", ifname, strerror(errno)); - ifc_close(); - return -1; - } - if (ifc_set_addr(ifname, address)) { - printerr("failed to set ipaddr %s: %s\n", ipaddr_to_string(address), strerror(errno)); - ifc_close(); - return -1; - } - if (ifc_set_mask(ifname, netmask)) { - printerr("failed to set netmask %s: %s\n", ipaddr_to_string(netmask), strerror(errno)); - ifc_close(); - return -1; - } - if (ifc_create_default_route(ifname, gateway)) { - printerr("failed to set default route %s: %s\n", ipaddr_to_string(gateway), strerror(errno)); - ifc_close(); - return -1; - } - - ifc_close(); - - snprintf(dns_prop_name, sizeof(dns_prop_name), "dhcp.%s.dns1", ifname); - property_set(dns_prop_name, dns1 ? ipaddr_to_string(dns1) : ""); - snprintf(dns_prop_name, sizeof(dns_prop_name), "dhcp.%s.dns2", ifname); - property_set(dns_prop_name, dns2 ? ipaddr_to_string(dns2) : ""); - - return 0; -} diff --git a/libnetutils/ifc_utils.h b/libnetutils/ifc_utils.h deleted file mode 100644 index 49b8747a..00000000 --- a/libnetutils/ifc_utils.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2008, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _IFC_UTILS_H_ -#define _IFC_UTILS_H_ - -int ifc_init(void); - -int ifc_get_ifindex(const char *name, int *if_indexp); -int ifc_get_hwaddr(const char *name, void *ptr); - -int ifc_up(const char *name); -int ifc_down(const char *name); - -int ifc_set_addr(const char *name, unsigned addr); -int ifc_set_mask(const char *name, unsigned mask); - -int ifc_create_default_route(const char *name, unsigned addr); - -int ifc_get_info(const char *name, unsigned *addr, unsigned *mask, unsigned *flags); - -#endif diff --git a/libnetutils/packet.c b/libnetutils/packet.c deleted file mode 100644 index 9388345c..00000000 --- a/libnetutils/packet.c +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Copyright 2008, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <stdlib.h> -#include <unistd.h> -#include <sys/uio.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <netinet/ip.h> -#include <netinet/udp.h> -#include <linux/if_packet.h> -#include <linux/if_ether.h> -#include <errno.h> - -#ifdef ANDROID -#define LOG_TAG "DHCP" -#include <cutils/log.h> -#else -#include <stdio.h> -#include <string.h> -#define LOGD printf -#define LOGW printf -#endif - -#include "dhcpmsg.h" - -int fatal(); - -int open_raw_socket(const char *ifname, uint8_t *hwaddr, int if_index) -{ - int s, flag; - struct sockaddr_ll bindaddr; - - if((s = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP))) < 0) { - return fatal("socket(PF_PACKET)"); - } - - memset(&bindaddr, 0, sizeof(bindaddr)); - bindaddr.sll_family = AF_PACKET; - bindaddr.sll_protocol = htons(ETH_P_IP); - bindaddr.sll_halen = ETH_ALEN; - memcpy(bindaddr.sll_addr, hwaddr, ETH_ALEN); - bindaddr.sll_ifindex = if_index; - - if (bind(s, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) < 0) { - return fatal("Cannot bind raw socket to interface"); - } - - return s; -} - -static uint32_t checksum(void *buffer, unsigned int count, uint32_t startsum) -{ - uint16_t *up = (uint16_t *)buffer; - uint32_t sum = startsum; - uint32_t upper16; - - while (count > 1) { - sum += *up++; - count -= 2; - } - if (count > 0) { - sum += (uint16_t) *(uint8_t *)up; - } - while ((upper16 = (sum >> 16)) != 0) { - sum = (sum & 0xffff) + upper16; - } - return sum; -} - -static uint32_t finish_sum(uint32_t sum) -{ - return ~sum & 0xffff; -} - -int send_packet(int s, int if_index, struct dhcp_msg *msg, int size, - uint32_t saddr, uint32_t daddr, uint32_t sport, uint32_t dport) -{ - struct iphdr ip; - struct udphdr udp; - struct iovec iov[3]; - uint32_t udpsum; - uint16_t temp; - struct msghdr msghdr; - struct sockaddr_ll destaddr; - - ip.version = IPVERSION; - ip.ihl = sizeof(ip) >> 2; - ip.tos = 0; - ip.tot_len = htons(sizeof(ip) + sizeof(udp) + size); - ip.id = 0; - ip.frag_off = 0; - ip.ttl = IPDEFTTL; - ip.protocol = IPPROTO_UDP; - ip.check = 0; - ip.saddr = saddr; - ip.daddr = daddr; - ip.check = finish_sum(checksum(&ip, sizeof(ip), 0)); - - udp.source = htons(sport); - udp.dest = htons(dport); - udp.len = htons(sizeof(udp) + size); - udp.check = 0; - - /* Calculate checksum for pseudo header */ - udpsum = checksum(&ip.saddr, sizeof(ip.saddr), 0); - udpsum = checksum(&ip.daddr, sizeof(ip.daddr), udpsum); - temp = htons(IPPROTO_UDP); - udpsum = checksum(&temp, sizeof(temp), udpsum); - temp = udp.len; - udpsum = checksum(&temp, sizeof(temp), udpsum); - - /* Add in the checksum for the udp header */ - udpsum = checksum(&udp, sizeof(udp), udpsum); - - /* Add in the checksum for the data */ - udpsum = checksum(msg, size, udpsum); - udp.check = finish_sum(udpsum); - - iov[0].iov_base = (char *)&ip; - iov[0].iov_len = sizeof(ip); - iov[1].iov_base = (char *)&udp; - iov[1].iov_len = sizeof(udp); - iov[2].iov_base = (char *)msg; - iov[2].iov_len = size; - memset(&destaddr, 0, sizeof(destaddr)); - destaddr.sll_family = AF_PACKET; - destaddr.sll_protocol = htons(ETH_P_IP); - destaddr.sll_ifindex = if_index; - destaddr.sll_halen = ETH_ALEN; - memcpy(destaddr.sll_addr, "\xff\xff\xff\xff\xff\xff", ETH_ALEN); - - msghdr.msg_name = &destaddr; - msghdr.msg_namelen = sizeof(destaddr); - msghdr.msg_iov = iov; - msghdr.msg_iovlen = sizeof(iov) / sizeof(struct iovec); - msghdr.msg_flags = 0; - msghdr.msg_control = 0; - msghdr.msg_controllen = 0; - return sendmsg(s, &msghdr, 0); -} - -int receive_packet(int s, struct dhcp_msg *msg) -{ - int nread; - int is_valid; - struct dhcp_packet { - struct iphdr ip; - struct udphdr udp; - struct dhcp_msg dhcp; - } packet; - int dhcp_size; - uint32_t sum; - uint16_t temp; - uint32_t saddr, daddr; - - nread = read(s, &packet, sizeof(packet)); - if (nread < 0) { - return -1; - } - /* - * The raw packet interface gives us all packets received by the - * network interface. We need to filter out all packets that are - * not meant for us. - */ - is_valid = 0; - if (nread < (int)(sizeof(struct iphdr) + sizeof(struct udphdr))) { -#if VERBOSE - LOGD("Packet is too small (%d) to be a UDP datagram", nread); -#endif - } else if (packet.ip.version != IPVERSION || packet.ip.ihl != (sizeof(packet.ip) >> 2)) { -#if VERBOSE - LOGD("Not a valid IP packet"); -#endif - } else if (nread < ntohs(packet.ip.tot_len)) { -#if VERBOSE - LOGD("Packet was truncated (read %d, needed %d)", nread, ntohs(packet.ip.tot_len)); -#endif - } else if (packet.ip.protocol != IPPROTO_UDP) { -#if VERBOSE - LOGD("IP protocol (%d) is not UDP", packet.ip.protocol); -#endif - } else if (packet.udp.dest != htons(PORT_BOOTP_CLIENT)) { -#if VERBOSE - LOGD("UDP dest port (%d) is not DHCP client", ntohs(packet.udp.dest)); -#endif - } else { - is_valid = 1; - } - - if (!is_valid) { - return -1; - } - - /* Seems like it's probably a valid DHCP packet */ - /* validate IP header checksum */ - sum = finish_sum(checksum(&packet.ip, sizeof(packet.ip), 0)); - if (sum != 0) { - LOGW("IP header checksum failure (0x%x)", packet.ip.check); - return -1; - } - /* - * Validate the UDP checksum. - * Since we don't need the IP header anymore, we "borrow" it - * to construct the pseudo header used in the checksum calculation. - */ - dhcp_size = ntohs(packet.udp.len) - sizeof(packet.udp); - saddr = packet.ip.saddr; - daddr = packet.ip.daddr; - nread = ntohs(packet.ip.tot_len); - memset(&packet.ip, 0, sizeof(packet.ip)); - packet.ip.saddr = saddr; - packet.ip.daddr = daddr; - packet.ip.protocol = IPPROTO_UDP; - packet.ip.tot_len = packet.udp.len; - temp = packet.udp.check; - packet.udp.check = 0; - sum = finish_sum(checksum(&packet, nread, 0)); - packet.udp.check = temp; - if (temp != sum) { - LOGW("UDP header checksum failure (0x%x should be 0x%x)", sum, temp); - return -1; - } - memcpy(msg, &packet.dhcp, dhcp_size); - return dhcp_size; -} diff --git a/libnetutils/packet.h b/libnetutils/packet.h deleted file mode 100644 index aade392d..00000000 --- a/libnetutils/packet.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2008, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _WIFI_PACKET_H_ -#define _WIFI_PACKET_H_ - -int open_raw_socket(const char *ifname, uint8_t *hwaddr, int if_index); -int send_packet(int s, int if_index, struct dhcp_msg *msg, int size, - uint32_t saddr, uint32_t daddr, uint32_t sport, uint32_t dport); -int receive_packet(int s, struct dhcp_msg *msg); - -#endif |
