1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* 2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Copyright 2008, The Android Open Source Project 3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * 4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * you may not use this file except in compliance with the License. 6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * You may obtain a copy of the License at 7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * 8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * 10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * See the License for the specific language governing permissions and 14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * limitations under the License. 15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdlib.h> 18a744b05984a963966cec08758ffe582d241be9d7Elliott Hughes#include <string.h> 19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <unistd.h> 20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/uio.h> 21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/socket.h> 22dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <netinet/in.h> 23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <netinet/ip.h> 24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <netinet/udp.h> 25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <linux/if_packet.h> 26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <linux/if_ether.h> 27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <errno.h> 28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#ifdef ANDROID 30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define LOG_TAG "DHCP" 31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <cutils/log.h> 32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#else 33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdio.h> 34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <string.h> 358d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block#define ALOGD printf 36ae8b56c0d17a97aff0b98e6405c7cc9811bbbc3dSteve Block#define ALOGW printf 37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif 38dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "dhcpmsg.h" 40dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint fatal(); 42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 43a5db95da3801cd82df80c41996b1e6f69a9acecfEdwin Vaneint open_raw_socket(const char *ifname __attribute__((unused)), uint8_t *hwaddr, int if_index) 44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 45a5d5d8477357078a636c7e0d1e80c128cfd25262Andreas Gampe int s; 46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct sockaddr_ll bindaddr; 47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if((s = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP))) < 0) { 49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return fatal("socket(PF_PACKET)"); 50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project memset(&bindaddr, 0, sizeof(bindaddr)); 53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project bindaddr.sll_family = AF_PACKET; 54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project bindaddr.sll_protocol = htons(ETH_P_IP); 55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project bindaddr.sll_halen = ETH_ALEN; 56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project memcpy(bindaddr.sll_addr, hwaddr, ETH_ALEN); 57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project bindaddr.sll_ifindex = if_index; 58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (bind(s, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) < 0) { 60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return fatal("Cannot bind raw socket to interface"); 61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return s; 64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic uint32_t checksum(void *buffer, unsigned int count, uint32_t startsum) 67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project uint16_t *up = (uint16_t *)buffer; 69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project uint32_t sum = startsum; 70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project uint32_t upper16; 71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project while (count > 1) { 73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project sum += *up++; 74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project count -= 2; 75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (count > 0) { 77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project sum += (uint16_t) *(uint8_t *)up; 78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project while ((upper16 = (sum >> 16)) != 0) { 80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project sum = (sum & 0xffff) + upper16; 81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return sum; 83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic uint32_t finish_sum(uint32_t sum) 86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return ~sum & 0xffff; 88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint send_packet(int s, int if_index, struct dhcp_msg *msg, int size, 91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project uint32_t saddr, uint32_t daddr, uint32_t sport, uint32_t dport) 92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct iphdr ip; 94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct udphdr udp; 95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct iovec iov[3]; 96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project uint32_t udpsum; 97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project uint16_t temp; 98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct msghdr msghdr; 99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct sockaddr_ll destaddr; 100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ip.version = IPVERSION; 102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ip.ihl = sizeof(ip) >> 2; 103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ip.tos = 0; 104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ip.tot_len = htons(sizeof(ip) + sizeof(udp) + size); 105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ip.id = 0; 106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ip.frag_off = 0; 107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ip.ttl = IPDEFTTL; 108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ip.protocol = IPPROTO_UDP; 109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ip.check = 0; 110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ip.saddr = saddr; 111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ip.daddr = daddr; 112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ip.check = finish_sum(checksum(&ip, sizeof(ip), 0)); 113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project udp.source = htons(sport); 115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project udp.dest = htons(dport); 116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project udp.len = htons(sizeof(udp) + size); 117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project udp.check = 0; 118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /* Calculate checksum for pseudo header */ 120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project udpsum = checksum(&ip.saddr, sizeof(ip.saddr), 0); 121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project udpsum = checksum(&ip.daddr, sizeof(ip.daddr), udpsum); 122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project temp = htons(IPPROTO_UDP); 123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project udpsum = checksum(&temp, sizeof(temp), udpsum); 124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project temp = udp.len; 125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project udpsum = checksum(&temp, sizeof(temp), udpsum); 126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /* Add in the checksum for the udp header */ 128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project udpsum = checksum(&udp, sizeof(udp), udpsum); 129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /* Add in the checksum for the data */ 131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project udpsum = checksum(msg, size, udpsum); 132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project udp.check = finish_sum(udpsum); 133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project iov[0].iov_base = (char *)&ip; 135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project iov[0].iov_len = sizeof(ip); 136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project iov[1].iov_base = (char *)&udp; 137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project iov[1].iov_len = sizeof(udp); 138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project iov[2].iov_base = (char *)msg; 139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project iov[2].iov_len = size; 140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project memset(&destaddr, 0, sizeof(destaddr)); 141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project destaddr.sll_family = AF_PACKET; 142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project destaddr.sll_protocol = htons(ETH_P_IP); 143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project destaddr.sll_ifindex = if_index; 144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project destaddr.sll_halen = ETH_ALEN; 145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project memcpy(destaddr.sll_addr, "\xff\xff\xff\xff\xff\xff", ETH_ALEN); 146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project msghdr.msg_name = &destaddr; 148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project msghdr.msg_namelen = sizeof(destaddr); 149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project msghdr.msg_iov = iov; 150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project msghdr.msg_iovlen = sizeof(iov) / sizeof(struct iovec); 151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project msghdr.msg_flags = 0; 152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project msghdr.msg_control = 0; 153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project msghdr.msg_controllen = 0; 154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return sendmsg(s, &msghdr, 0); 155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint receive_packet(int s, struct dhcp_msg *msg) 158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int nread; 160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int is_valid; 161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct dhcp_packet { 162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct iphdr ip; 163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct udphdr udp; 164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct dhcp_msg dhcp; 165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } packet; 166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int dhcp_size; 167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project uint32_t sum; 168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project uint16_t temp; 169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project uint32_t saddr, daddr; 170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project nread = read(s, &packet, sizeof(packet)); 172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (nread < 0) { 173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /* 176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * The raw packet interface gives us all packets received by the 177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * network interface. We need to filter out all packets that are 178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * not meant for us. 179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project is_valid = 0; 181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (nread < (int)(sizeof(struct iphdr) + sizeof(struct udphdr))) { 182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if VERBOSE 1838d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block ALOGD("Packet is too small (%d) to be a UDP datagram", nread); 184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif 185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else if (packet.ip.version != IPVERSION || packet.ip.ihl != (sizeof(packet.ip) >> 2)) { 186dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if VERBOSE 1878d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block ALOGD("Not a valid IP packet"); 188dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif 189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else if (nread < ntohs(packet.ip.tot_len)) { 190dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if VERBOSE 1918d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block ALOGD("Packet was truncated (read %d, needed %d)", nread, ntohs(packet.ip.tot_len)); 192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif 193dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else if (packet.ip.protocol != IPPROTO_UDP) { 194dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if VERBOSE 1958d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block ALOGD("IP protocol (%d) is not UDP", packet.ip.protocol); 196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif 197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else if (packet.udp.dest != htons(PORT_BOOTP_CLIENT)) { 198dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if VERBOSE 1998d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block ALOGD("UDP dest port (%d) is not DHCP client", ntohs(packet.udp.dest)); 200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif 201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 202dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project is_valid = 1; 203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 204dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 205dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (!is_valid) { 206dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 207dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 208dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 209dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /* Seems like it's probably a valid DHCP packet */ 210dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /* validate IP header checksum */ 211dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project sum = finish_sum(checksum(&packet.ip, sizeof(packet.ip), 0)); 212dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (sum != 0) { 213ae8b56c0d17a97aff0b98e6405c7cc9811bbbc3dSteve Block ALOGW("IP header checksum failure (0x%x)", packet.ip.check); 214dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 215dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 216dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /* 217dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Validate the UDP checksum. 218dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Since we don't need the IP header anymore, we "borrow" it 219dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * to construct the pseudo header used in the checksum calculation. 220dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 221dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project dhcp_size = ntohs(packet.udp.len) - sizeof(packet.udp); 222dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project saddr = packet.ip.saddr; 223dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project daddr = packet.ip.daddr; 224dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project nread = ntohs(packet.ip.tot_len); 225dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project memset(&packet.ip, 0, sizeof(packet.ip)); 226dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project packet.ip.saddr = saddr; 227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project packet.ip.daddr = daddr; 228dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project packet.ip.protocol = IPPROTO_UDP; 229dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project packet.ip.tot_len = packet.udp.len; 230dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project temp = packet.udp.check; 231dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project packet.udp.check = 0; 232dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project sum = finish_sum(checksum(&packet, nread, 0)); 233dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project packet.udp.check = temp; 2341c87ae05b337f789b2e56bbb273758dfb12fb2efAjay Dudani if (!sum) 2351c87ae05b337f789b2e56bbb273758dfb12fb2efAjay Dudani sum = finish_sum(sum); 236dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (temp != sum) { 237ae8b56c0d17a97aff0b98e6405c7cc9811bbbc3dSteve Block ALOGW("UDP header checksum failure (0x%x should be 0x%x)", sum, temp); 238dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 239dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 240dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project memcpy(msg, &packet.dhcp, dhcp_size); 241dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return dhcp_size; 242dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 243