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> 18dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <unistd.h> 19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/uio.h> 20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/socket.h> 21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <netinet/in.h> 22dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <netinet/ip.h> 23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <netinet/udp.h> 24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <linux/if_packet.h> 25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <linux/if_ether.h> 26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <errno.h> 27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#ifdef ANDROID 29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define LOG_TAG "DHCP" 30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <cutils/log.h> 31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#else 32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdio.h> 33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <string.h> 348d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block#define ALOGD printf 35ae8b56c0d17a97aff0b98e6405c7cc9811bbbc3dSteve Block#define ALOGW printf 36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif 37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 38dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "dhcpmsg.h" 39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 40dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint fatal(); 41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 42a5db95da3801cd82df80c41996b1e6f69a9acecfEdwin Vaneint open_raw_socket(const char *ifname __attribute__((unused)), uint8_t *hwaddr, int if_index) 43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int s, flag; 45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct sockaddr_ll bindaddr; 46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if((s = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP))) < 0) { 48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return fatal("socket(PF_PACKET)"); 49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project memset(&bindaddr, 0, sizeof(bindaddr)); 52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project bindaddr.sll_family = AF_PACKET; 53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project bindaddr.sll_protocol = htons(ETH_P_IP); 54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project bindaddr.sll_halen = ETH_ALEN; 55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project memcpy(bindaddr.sll_addr, hwaddr, ETH_ALEN); 56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project bindaddr.sll_ifindex = if_index; 57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (bind(s, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) < 0) { 59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return fatal("Cannot bind raw socket to interface"); 60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return s; 63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic uint32_t checksum(void *buffer, unsigned int count, uint32_t startsum) 66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project uint16_t *up = (uint16_t *)buffer; 68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project uint32_t sum = startsum; 69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project uint32_t upper16; 70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project while (count > 1) { 72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project sum += *up++; 73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project count -= 2; 74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (count > 0) { 76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project sum += (uint16_t) *(uint8_t *)up; 77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project while ((upper16 = (sum >> 16)) != 0) { 79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project sum = (sum & 0xffff) + upper16; 80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return sum; 82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic uint32_t finish_sum(uint32_t sum) 85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return ~sum & 0xffff; 87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint send_packet(int s, int if_index, struct dhcp_msg *msg, int size, 90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project uint32_t saddr, uint32_t daddr, uint32_t sport, uint32_t dport) 91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct iphdr ip; 93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct udphdr udp; 94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct iovec iov[3]; 95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project uint32_t udpsum; 96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project uint16_t temp; 97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct msghdr msghdr; 98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct sockaddr_ll destaddr; 99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ip.version = IPVERSION; 101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ip.ihl = sizeof(ip) >> 2; 102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ip.tos = 0; 103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ip.tot_len = htons(sizeof(ip) + sizeof(udp) + size); 104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ip.id = 0; 105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ip.frag_off = 0; 106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ip.ttl = IPDEFTTL; 107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ip.protocol = IPPROTO_UDP; 108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ip.check = 0; 109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ip.saddr = saddr; 110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ip.daddr = daddr; 111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ip.check = finish_sum(checksum(&ip, sizeof(ip), 0)); 112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project udp.source = htons(sport); 114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project udp.dest = htons(dport); 115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project udp.len = htons(sizeof(udp) + size); 116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project udp.check = 0; 117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /* Calculate checksum for pseudo header */ 119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project udpsum = checksum(&ip.saddr, sizeof(ip.saddr), 0); 120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project udpsum = checksum(&ip.daddr, sizeof(ip.daddr), udpsum); 121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project temp = htons(IPPROTO_UDP); 122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project udpsum = checksum(&temp, sizeof(temp), udpsum); 123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project temp = udp.len; 124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project udpsum = checksum(&temp, sizeof(temp), udpsum); 125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /* Add in the checksum for the udp header */ 127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project udpsum = checksum(&udp, sizeof(udp), udpsum); 128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /* Add in the checksum for the data */ 130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project udpsum = checksum(msg, size, udpsum); 131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project udp.check = finish_sum(udpsum); 132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project iov[0].iov_base = (char *)&ip; 134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project iov[0].iov_len = sizeof(ip); 135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project iov[1].iov_base = (char *)&udp; 136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project iov[1].iov_len = sizeof(udp); 137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project iov[2].iov_base = (char *)msg; 138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project iov[2].iov_len = size; 139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project memset(&destaddr, 0, sizeof(destaddr)); 140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project destaddr.sll_family = AF_PACKET; 141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project destaddr.sll_protocol = htons(ETH_P_IP); 142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project destaddr.sll_ifindex = if_index; 143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project destaddr.sll_halen = ETH_ALEN; 144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project memcpy(destaddr.sll_addr, "\xff\xff\xff\xff\xff\xff", ETH_ALEN); 145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project msghdr.msg_name = &destaddr; 147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project msghdr.msg_namelen = sizeof(destaddr); 148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project msghdr.msg_iov = iov; 149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project msghdr.msg_iovlen = sizeof(iov) / sizeof(struct iovec); 150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project msghdr.msg_flags = 0; 151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project msghdr.msg_control = 0; 152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project msghdr.msg_controllen = 0; 153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return sendmsg(s, &msghdr, 0); 154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint receive_packet(int s, struct dhcp_msg *msg) 157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int nread; 159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int is_valid; 160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct dhcp_packet { 161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct iphdr ip; 162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct udphdr udp; 163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct dhcp_msg dhcp; 164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } packet; 165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int dhcp_size; 166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project uint32_t sum; 167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project uint16_t temp; 168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project uint32_t saddr, daddr; 169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project nread = read(s, &packet, sizeof(packet)); 171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (nread < 0) { 172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /* 175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * The raw packet interface gives us all packets received by the 176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * network interface. We need to filter out all packets that are 177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * not meant for us. 178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project is_valid = 0; 180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (nread < (int)(sizeof(struct iphdr) + sizeof(struct udphdr))) { 181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if VERBOSE 1828d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block ALOGD("Packet is too small (%d) to be a UDP datagram", nread); 183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif 184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else if (packet.ip.version != IPVERSION || packet.ip.ihl != (sizeof(packet.ip) >> 2)) { 185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if VERBOSE 1868d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block ALOGD("Not a valid IP packet"); 187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif 188dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else if (nread < ntohs(packet.ip.tot_len)) { 189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if VERBOSE 1908d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block ALOGD("Packet was truncated (read %d, needed %d)", nread, ntohs(packet.ip.tot_len)); 191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif 192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else if (packet.ip.protocol != IPPROTO_UDP) { 193dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if VERBOSE 1948d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block ALOGD("IP protocol (%d) is not UDP", packet.ip.protocol); 195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif 196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else if (packet.udp.dest != htons(PORT_BOOTP_CLIENT)) { 197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if VERBOSE 1988d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block ALOGD("UDP dest port (%d) is not DHCP client", ntohs(packet.udp.dest)); 199dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif 200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project is_valid = 1; 202dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 204dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (!is_valid) { 205dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 206dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 207dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 208dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /* Seems like it's probably a valid DHCP packet */ 209dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /* validate IP header checksum */ 210dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project sum = finish_sum(checksum(&packet.ip, sizeof(packet.ip), 0)); 211dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (sum != 0) { 212ae8b56c0d17a97aff0b98e6405c7cc9811bbbc3dSteve Block ALOGW("IP header checksum failure (0x%x)", packet.ip.check); 213dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 214dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 215dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /* 216dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Validate the UDP checksum. 217dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Since we don't need the IP header anymore, we "borrow" it 218dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * to construct the pseudo header used in the checksum calculation. 219dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 220dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project dhcp_size = ntohs(packet.udp.len) - sizeof(packet.udp); 221dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project saddr = packet.ip.saddr; 222dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project daddr = packet.ip.daddr; 223dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project nread = ntohs(packet.ip.tot_len); 224dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project memset(&packet.ip, 0, sizeof(packet.ip)); 225dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project packet.ip.saddr = saddr; 226dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project packet.ip.daddr = daddr; 227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project packet.ip.protocol = IPPROTO_UDP; 228dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project packet.ip.tot_len = packet.udp.len; 229dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project temp = packet.udp.check; 230dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project packet.udp.check = 0; 231dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project sum = finish_sum(checksum(&packet, nread, 0)); 232dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project packet.udp.check = temp; 233dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (temp != sum) { 234ae8b56c0d17a97aff0b98e6405c7cc9811bbbc3dSteve Block ALOGW("UDP header checksum failure (0x%x should be 0x%x)", sum, temp); 235dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 236dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 237dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project memcpy(msg, &packet.dhcp, dhcp_size); 238dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return dhcp_size; 239dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 240