18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Copyright (c) 1982, 1986, 1988, 1993 38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * The Regents of the University of California. All rights reserved. 48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Redistribution and use in source and binary forms, with or without 68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * modification, are permitted provided that the following conditions 78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * are met: 88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 1. Redistributions of source code must retain the above copyright 98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * notice, this list of conditions and the following disclaimer. 108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright 118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * notice, this list of conditions and the following disclaimer in the 128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * documentation and/or other materials provided with the distribution. 135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 3. Neither the name of the University nor the names of its contributors 148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * may be used to endorse or promote products derived from this software 158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * without specific prior written permission. 168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * SUCH DAMAGE. 288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * @(#)ip_input.c 8.2 (Berkeley) 1/4/94 308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * ip_input.c,v 1.11 1994/11/16 10:17:08 jkh Exp 318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Changes and additions relating to SLiRP are 358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Copyright (c) 1995 Danny Gasparovski. 365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Please read the file COPYRIGHT for the 388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * terms and conditions of the copyright. 398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <slirp.h> 428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <osdep.h> 438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "ip_icmp.h" 448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef LOG_ENABLED 468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstruct ipstat ipstat; 475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstruct ipq ipq; 508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic struct ip *ip_reass(register struct ip *ip, 525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner register struct ipq *fp); 535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void ip_freef(struct ipq *fp); 545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void ip_enq(register struct ipasfrag *p, 555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner register struct ipasfrag *prev); 565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void ip_deq(register struct ipasfrag *p); 575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * IP initialization: fill in IP protocol switch table. 608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * All protocols not implemented in kernel go to raw IP protocol handler. 618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid 635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerip_init(void) 648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ipq.ip_link.next = ipq.ip_link.prev = &ipq.ip_link; 668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ip_id = tt.tv_sec & 0xffff; 678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project udp_init(); 688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcp_init(); 698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Ip input routine. Checksum and byte swap header. If fragmented 738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * try to reassemble. Process options. Pass to next level. 748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid 765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerip_input(struct mbuf *m) 778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project register struct ip *ip; 798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int hlen; 805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_CALL("ip_input"); 828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_ARG("m = %lx", (long)m); 838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_ARG("m_len = %d", m->m_len); 848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(ipstat.ips_total++); 865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (m->m_len < sizeof (struct ip)) { 885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(ipstat.ips_toosmall++); 898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ip = mtod(m, struct ip *); 935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (ip->ip_v != IPVERSION) { 955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(ipstat.ips_badvers++); 968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto bad; 978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project hlen = ip->ip_hl << 2; 1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (hlen<sizeof(struct ip ) || hlen>m->m_len) {/* min header length */ 1015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(ipstat.ips_badhlen++); /* or packet too short */ 1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto bad; 1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* keep ip header intact for ICMP reply 1065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * ip->ip_sum = cksum(m, hlen); 1075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * if (ip->ip_sum) { 1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(cksum(m,hlen)) { 1105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(ipstat.ips_badsum++); 1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto bad; 1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Convert fields to host representation. 1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 1178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project NTOHS(ip->ip_len); 1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (ip->ip_len < hlen) { 1195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(ipstat.ips_badlen++); 1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto bad; 1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project NTOHS(ip->ip_id); 1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project NTOHS(ip->ip_off); 1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Check that the amount of data in the buffers 1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * is as at least much as the IP header would have us expect. 1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Trim mbufs if longer than we expect. 1298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Drop packet if shorter than we expect. 1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (m->m_len < ip->ip_len) { 1325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(ipstat.ips_tooshort++); 1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto bad; 1348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (slirp_restrict) { 1375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (memcmp(&ip->ip_dst.s_addr, &special_addr, 3)) { 1385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ip->ip_dst.s_addr == 0xffffffff && ip->ip_p != IPPROTO_UDP) 1395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto bad; 1405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 1415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int host = ntohl(ip->ip_dst.s_addr) & 0xff; 1425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct ex_list *ex_ptr; 1435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (host == 0xff) 1455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto bad; 1465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) 1485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ex_ptr->ex_addr == host) 1495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 1505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!ex_ptr) 1525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto bad; 1535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Should drop packet if mbuf too long? hmmm... */ 1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (m->m_len > ip->ip_len) 1585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m_adj(m, ip->ip_len - m->m_len); 1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* check ip_ttl for a correct ICMP reply */ 1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(ip->ip_ttl==0 || ip->ip_ttl==1) { 1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project icmp_error(m, ICMP_TIMXCEED,ICMP_TIMXCEED_INTRANS, 0,"ttl"); 1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto bad; 1648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Process options and, if not destined for us, 1688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * ship it on. ip_dooptions returns 1 when an 1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * error was detected (causing an icmp message 1708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * to be sent and the original packet to be freed). 1718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 1728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* We do no IP options */ 1738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* if (hlen > sizeof (struct ip) && ip_dooptions(m)) 1748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * goto next; 1758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 1778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If offset or IP_MF are set, must reassemble. 1788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Otherwise, nothing need be done. 1798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * (We could look in the reassembly queue to see 1808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * if the packet was previously fragmented, 1818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * but it's not worth the time; just let them time out.) 1825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 1838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * XXX This should fail, don't fragment yet 1848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 1858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (ip->ip_off &~ IP_DF) { 1868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project register struct ipq *fp; 1875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct qlink *l; 1888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Look for queue of fragments 1908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * of this datagram. 1918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 1928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (l = ipq.ip_link.next; l != &ipq.ip_link; l = l->next) { 1935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fp = container_of(l, struct ipq, ip_link); 1945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ip->ip_id == fp->ipq_id && 1955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ip->ip_src.s_addr == fp->ipq_src.s_addr && 1965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ip->ip_dst.s_addr == fp->ipq_dst.s_addr && 1975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ip->ip_p == fp->ipq_p) 1985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto found; 1995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 2005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fp = NULL; 2018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project found: 2028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 2048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Adjust ip_len to not reflect header, 2058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * set ip_mff if more fragments are expected, 2068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * convert offset of this to bytes. 2078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 2088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ip->ip_len -= hlen; 2098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (ip->ip_off & IP_MF) 2108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ip->ip_tos |= 1; 2115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else 2128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ip->ip_tos &= ~1; 2138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ip->ip_off <<= 3; 2158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 2178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If datagram marked as having more fragments 2188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * or if this is not the first fragment, 2198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * attempt reassembly; if it succeeds, proceed. 2208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 2218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (ip->ip_tos & 1 || ip->ip_off) { 2225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(ipstat.ips_fragments++); 2238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ip = ip_reass(ip, fp); 2245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ip == NULL) 2258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 2265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(ipstat.ips_reassembled++); 2275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m = dtom(ip); 2288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else 2298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (fp) 2308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ip_freef(fp); 2318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else 2338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ip->ip_len -= hlen; 2348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 2368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Switch out to protocol's input routine. 2378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 2385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(ipstat.ips_delivered++); 2398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (ip->ip_p) { 2408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case IPPROTO_TCP: 2418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcp_input(m, hlen, (struct socket *)NULL); 2428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 2438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case IPPROTO_UDP: 2448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project udp_input(m, hlen); 2458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 2468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case IPPROTO_ICMP: 2478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project icmp_input(m, hlen); 2488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 2498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 2505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(ipstat.ips_noproto++); 2515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m_free(m); 2528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 2538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 2548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectbad: 2555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m_freem(m); 2568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 2578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 2588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define iptofrag(P) ((struct ipasfrag *)(((char*)(P)) - sizeof(struct qlink))) 2608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define fragtoip(P) ((struct ip*)(((char*)(P)) + sizeof(struct qlink))) 2618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 2628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Take incoming datagram fragment and try to 2638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * reassemble it into whole datagram. If a chain for 2648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * reassembly of this datagram already exists, then it 2658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * is given as fp; otherwise have to make a chain. 2668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 2675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic struct ip * 2685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerip_reass(register struct ip *ip, register struct ipq *fp) 2698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 2705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner register struct mbuf *m = dtom(ip); 2718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project register struct ipasfrag *q; 2728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int hlen = ip->ip_hl << 2; 2738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int i, next; 2745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_CALL("ip_reass"); 2768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_ARG("ip = %lx", (long)ip); 2778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_ARG("fp = %lx", (long)fp); 2788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_ARG("m = %lx", (long)m); 2798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 2818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Presence of header sizes in mbufs 2828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * would confuse code below. 2838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Fragment m_data is concatenated. 2848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 2858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project m->m_data += hlen; 2868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project m->m_len -= hlen; 2878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 2898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If first fragment to arrive, create a reassembly queue. 2908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 2915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (fp == NULL) { 2925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct mbuf *t; 2935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if ((t = m_get()) == NULL) goto dropfrag; 2945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fp = mtod(t, struct ipq *); 2958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project insque(&fp->ip_link, &ipq.ip_link); 2968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project fp->ipq_ttl = IPFRAGTTL; 2978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project fp->ipq_p = ip->ip_p; 2988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project fp->ipq_id = ip->ip_id; 2998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project fp->frag_link.next = fp->frag_link.prev = &fp->frag_link; 3008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project fp->ipq_src = ip->ip_src; 3015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fp->ipq_dst = ip->ip_dst; 3028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project q = (struct ipasfrag *)fp; 3038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto insert; 3048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 3055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 3078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Find a segment which begins after this one does. 3088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 3095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (q = fp->frag_link.next; q != (struct ipasfrag *)&fp->frag_link; 3105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner q = q->ipf_next) 3115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (q->ipf_off > ip->ip_off) 3125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 3135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 3158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If there is a preceding segment, it may provide some of 3168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * our data already. If so, drop the data from the incoming 3178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * segment. If it provides all of our data, drop us. 3188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 3195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (q->ipf_prev != &fp->frag_link) { 3205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct ipasfrag *pq = q->ipf_prev; 3215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner i = pq->ipf_off + pq->ipf_len - ip->ip_off; 3228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (i > 0) { 3238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (i >= ip->ip_len) 3248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto dropfrag; 3255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m_adj(dtom(ip), i); 3268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ip->ip_off += i; 3278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ip->ip_len -= i; 3288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 3298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 3308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 3328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * While we overlap succeeding segments trim them or, 3338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * if they are completely covered, dequeue them. 3348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 3355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner while (q != (struct ipasfrag*)&fp->frag_link && 3365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ip->ip_off + ip->ip_len > q->ipf_off) { 3375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner i = (ip->ip_off + ip->ip_len) - q->ipf_off; 3385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (i < q->ipf_len) { 3395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner q->ipf_len -= i; 3405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner q->ipf_off += i; 3415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m_adj(dtom(q), i); 3425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 3438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 3448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project q = q->ipf_next; 3455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m_freem(dtom(q->ipf_prev)); 3468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ip_deq(q->ipf_prev); 3478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 3488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectinsert: 3508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 3518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Stick new segment in its place; 3528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * check for complete reassembly. 3538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 3548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ip_enq(iptofrag(ip), q->ipf_prev); 3558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project next = 0; 3565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (q = fp->frag_link.next; q != (struct ipasfrag*)&fp->frag_link; 3575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner q = q->ipf_next) { 3585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (q->ipf_off != next) 3595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return NULL; 3605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner next += q->ipf_len; 3618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 3628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (((struct ipasfrag *)(q->ipf_prev))->ipf_tos & 1) 3635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return NULL; 3648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 3668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Reassembly is complete; concatenate fragments. 3678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 3685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner q = fp->frag_link.next; 3695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m = dtom(q); 3708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project q = (struct ipasfrag *) q->ipf_next; 3725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner while (q != (struct ipasfrag*)&fp->frag_link) { 3735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct mbuf *t = dtom(q); 3748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project q = (struct ipasfrag *) q->ipf_next; 3755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m_cat(m, t); 3768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 3778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 3798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Create header for new ip packet by 3808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * modifying header of first packet; 3818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * dequeue and discard fragment reassembly header. 3828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Make header visible. 3838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 3845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner q = fp->frag_link.next; 3858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 3878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If the fragments concatenated to an mbuf that's 3888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * bigger than the total size of the fragment, then and 3898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * m_ext buffer was alloced. But fp->ipq_next points to 3908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * the old buffer (in the mbuf), so we must point ip 3918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * into the new buffer. 3928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 3938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (m->m_flags & M_EXT) { 3948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int delta = (char *)q - m->m_dat; 3958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project q = (struct ipasfrag *)(m->m_ext + delta); 3968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 3978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* DEBUG_ARG("ip = %lx", (long)ip); 3998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * ip=(struct ipasfrag *)m->m_data; */ 4008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ip = fragtoip(q); 4025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ip->ip_len = next; 4038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ip->ip_tos &= ~1; 4045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ip->ip_src = fp->ipq_src; 4055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ip->ip_dst = fp->ipq_dst; 4068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project remque(&fp->ip_link); 4075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner (void) m_free(dtom(fp)); 4088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project m->m_len += (ip->ip_hl << 2); 4098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project m->m_data -= (ip->ip_hl << 2); 4108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return ip; 4128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdropfrag: 4145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(ipstat.ips_fragdropped++); 4155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m_freem(m); 4165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return NULL; 4178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 4188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 4208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Free a fragment reassembly header and all 4218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * associated datagrams. 4228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 4235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void 4245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerip_freef(struct ipq *fp) 4258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 4268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project register struct ipasfrag *q, *p; 4278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (q = fp->frag_link.next; q != (struct ipasfrag*)&fp->frag_link; q = p) { 4298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project p = q->ipf_next; 4308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ip_deq(q); 4315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m_freem(dtom(q)); 4328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 4338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project remque(&fp->ip_link); 4345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner (void) m_free(dtom(fp)); 4358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 4368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 4388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Put an ip fragment on a reassembly chain. 4398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Like insque, but pointers in middle of structure. 4408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 4415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void 4425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerip_enq(register struct ipasfrag *p, register struct ipasfrag *prev) 4438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 4448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_CALL("ip_enq"); 4458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_ARG("prev = %lx", (long)prev); 4465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner p->ipf_prev = prev; 4478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project p->ipf_next = prev->ipf_next; 4488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ((struct ipasfrag *)(prev->ipf_next))->ipf_prev = p; 4498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project prev->ipf_next = p; 4508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 4518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 4538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * To ip_enq as remque is to insque. 4548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 4555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void 4565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerip_deq(register struct ipasfrag *p) 4578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 4588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ((struct ipasfrag *)(p->ipf_prev))->ipf_next = p->ipf_next; 4598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ((struct ipasfrag *)(p->ipf_next))->ipf_prev = p->ipf_prev; 4608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 4618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 4638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * IP timer processing; 4648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * if a timer expires on a reassembly 4658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * queue, discard it. 4668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 4678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid 4685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerip_slowtimo(void) 4698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 4705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct qlink *l; 4715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_CALL("ip_slowtimo"); 4735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner l = ipq.ip_link.next; 4755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (l == NULL) 4778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 4788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner while (l != &ipq.ip_link) { 4805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct ipq *fp = container_of(l, struct ipq, ip_link); 4815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner l = l->next; 4825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (--fp->ipq_ttl == 0) { 4835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(ipstat.ips_fragtimeout++); 4848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ip_freef(fp); 4858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 4868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 4878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 4888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 4908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Do option processing on a datagram, 4918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * possibly discarding it if bad options are encountered, 4928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * or forwarding it if source-routed. 4938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Returns 1 if packet has been forwarded/freed, 4948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 0 if the packet should be processed further. 4958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 4968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef notdef 4988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint 5008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectip_dooptions(m) 5015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct mbuf *m; 5028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 5035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner register struct ip *ip = mtod(m, struct ip *); 5048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project register u_char *cp; 5058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project register struct ip_timestamp *ipt; 5068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project register struct in_ifaddr *ia; 5078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* int opt, optlen, cnt, off, code, type = ICMP_PARAMPROB, forward = 0; */ 5088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int opt, optlen, cnt, off, code, type, forward = 0; 5095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct in_addr *sin, dst; 5108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef u_int32_t n_time; 5118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project n_time ntime; 5128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project dst = ip->ip_dst; 5148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project cp = (u_char *)(ip + 1); 5158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project cnt = (ip->ip_hl << 2) - sizeof (struct ip); 5168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (; cnt > 0; cnt -= optlen, cp += optlen) { 5178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project opt = cp[IPOPT_OPTVAL]; 5188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (opt == IPOPT_EOL) 5198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 5208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (opt == IPOPT_NOP) 5218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project optlen = 1; 5228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else { 5238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project optlen = cp[IPOPT_OLEN]; 5248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (optlen <= 0 || optlen > cnt) { 5258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project code = &cp[IPOPT_OLEN] - (u_char *)ip; 5268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto bad; 5278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 5288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 5298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (opt) { 5308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 5328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 5338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 5358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Source routing with record. 5368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Find interface with current destination address. 5378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If none on this machine then drop if strictly routed, 5388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * or do nothing if loosely routed. 5398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Record interface address and bring up next address 5408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * component. If strictly routed make sure next 5418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * address is on directly accessible net. 5428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 5438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case IPOPT_LSRR: 5448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case IPOPT_SSRR: 5458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) { 5468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project code = &cp[IPOPT_OFFSET] - (u_char *)ip; 5478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto bad; 5488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 5498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ipaddr.sin_addr = ip->ip_dst; 5508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ia = (struct in_ifaddr *) 5518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ifa_ifwithaddr((struct sockaddr *)&ipaddr); 5528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (ia == 0) { 5538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (opt == IPOPT_SSRR) { 5548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project type = ICMP_UNREACH; 5558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project code = ICMP_UNREACH_SRCFAIL; 5568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto bad; 5578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 5588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 5598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Loose routing, and not at next destination 5608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * yet; nothing to do except forward. 5618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 5628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 5638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 5648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project off--; / * 0 origin * / 5658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (off > optlen - sizeof(struct in_addr)) { 5668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 5678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * End of source route. Should be for us. 5688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 5698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project save_rte(cp, ip->ip_src); 5708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 5718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 5728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 5738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * locate outgoing interface 5748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 5758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project bcopy((caddr_t)(cp + off), (caddr_t)&ipaddr.sin_addr, 5768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sizeof(ipaddr.sin_addr)); 5778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (opt == IPOPT_SSRR) { 5788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define INA struct in_ifaddr * 5798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define SA struct sockaddr * 5808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((ia = (INA)ifa_ifwithdstaddr((SA)&ipaddr)) == 0) 5818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ia = (INA)ifa_ifwithnet((SA)&ipaddr); 5828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else 5838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ia = ip_rtaddr(ipaddr.sin_addr); 5848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (ia == 0) { 5858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project type = ICMP_UNREACH; 5868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project code = ICMP_UNREACH_SRCFAIL; 5878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto bad; 5888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 5898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ip->ip_dst = ipaddr.sin_addr; 5908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project bcopy((caddr_t)&(IA_SIN(ia)->sin_addr), 5918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project (caddr_t)(cp + off), sizeof(struct in_addr)); 5928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project cp[IPOPT_OFFSET] += sizeof(struct in_addr); 5938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 5948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Let ip_intr's mcast routing check handle mcast pkts 5958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 5968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project forward = !IN_MULTICAST(ntohl(ip->ip_dst.s_addr)); 5978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 5988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case IPOPT_RR: 6008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) { 6018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project code = &cp[IPOPT_OFFSET] - (u_char *)ip; 6028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto bad; 6038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 6048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 6058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If no space remains, ignore. 6068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 6078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project off--; * 0 origin * 6088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (off > optlen - sizeof(struct in_addr)) 6098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 6108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project bcopy((caddr_t)(&ip->ip_dst), (caddr_t)&ipaddr.sin_addr, 6118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sizeof(ipaddr.sin_addr)); 6128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 6138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * locate outgoing interface; if we're the destination, 6148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * use the incoming interface (should be same). 6158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 6168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((ia = (INA)ifa_ifwithaddr((SA)&ipaddr)) == 0 && 6178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project (ia = ip_rtaddr(ipaddr.sin_addr)) == 0) { 6188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project type = ICMP_UNREACH; 6198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project code = ICMP_UNREACH_HOST; 6208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto bad; 6218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 6228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project bcopy((caddr_t)&(IA_SIN(ia)->sin_addr), 6238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project (caddr_t)(cp + off), sizeof(struct in_addr)); 6248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project cp[IPOPT_OFFSET] += sizeof(struct in_addr); 6258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 6268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case IPOPT_TS: 6288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project code = cp - (u_char *)ip; 6298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ipt = (struct ip_timestamp *)cp; 6308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (ipt->ipt_len < 5) 6318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto bad; 6328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (ipt->ipt_ptr > ipt->ipt_len - sizeof (int32_t)) { 6338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (++ipt->ipt_oflw == 0) 6348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto bad; 6358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 6368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 6378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sin = (struct in_addr *)(cp + ipt->ipt_ptr - 1); 6388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (ipt->ipt_flg) { 6398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case IPOPT_TS_TSONLY: 6418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 6428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case IPOPT_TS_TSANDADDR: 6448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (ipt->ipt_ptr + sizeof(n_time) + 6458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sizeof(struct in_addr) > ipt->ipt_len) 6468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto bad; 6478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ipaddr.sin_addr = dst; 6488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ia = (INA)ifaof_ i f p foraddr((SA)&ipaddr, 6498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project m->m_pkthdr.rcvif); 6508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (ia == 0) 6518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project continue; 6528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project bcopy((caddr_t)&IA_SIN(ia)->sin_addr, 6538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project (caddr_t)sin, sizeof(struct in_addr)); 6548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ipt->ipt_ptr += sizeof(struct in_addr); 6558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 6568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case IPOPT_TS_PRESPEC: 6588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (ipt->ipt_ptr + sizeof(n_time) + 6598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sizeof(struct in_addr) > ipt->ipt_len) 6608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto bad; 6618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project bcopy((caddr_t)sin, (caddr_t)&ipaddr.sin_addr, 6628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sizeof(struct in_addr)); 6638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (ifa_ifwithaddr((SA)&ipaddr) == 0) 6648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project continue; 6658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ipt->ipt_ptr += sizeof(struct in_addr); 6668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 6678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 6698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto bad; 6708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 6718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ntime = iptime(); 6728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project bcopy((caddr_t)&ntime, (caddr_t)cp + ipt->ipt_ptr - 1, 6738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sizeof(n_time)); 6748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ipt->ipt_ptr += sizeof(n_time); 6758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 6768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 6778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (forward) { 6788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ip_forward(m, 1); 6798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return (1); 6808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 6818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 6828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 6838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return (0); 6848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectbad: 6858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* ip->ip_len -= ip->ip_hl << 2; XXX icmp_error adds in hdr length */ 6868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Not yet */ 6888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project icmp_error(m, type, code, 0, 0); 6898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(ipstat.ips_badoptions++); 6918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return (1); 6928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 6938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif /* notdef */ 6958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 6978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Strip out IP options, at higher 6988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * level protocol in the kernel. 6998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Second argument is buffer to which options 7008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * will be moved, and return value is their length. 7018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * (XXX) should be deleted; last arg currently ignored. 7028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 7038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid 7045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerip_stripoptions(register struct mbuf *m, struct mbuf *mopt) 7058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 7068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project register int i; 7075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct ip *ip = mtod(m, struct ip *); 7088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project register caddr_t opts; 7098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int olen; 7108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project olen = (ip->ip_hl<<2) - sizeof (struct ip); 7128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project opts = (caddr_t)(ip + 1); 7138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project i = m->m_len - (sizeof (struct ip) + olen); 7148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project memcpy(opts, opts + olen, (unsigned)i); 7158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project m->m_len -= olen; 7165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 7178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ip->ip_hl = sizeof(struct ip) >> 2; 7188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 719