1 /* $NetBSD: ip.c,v 1.2 2011/05/13 23:35:09 nakayama Exp $ */ 2 3 /* 4 * Copyright (c) 1992 Regents of the University of California. 5 * Copyright (c) 2010 Zoltan Arnold NAGY 6 * All rights reserved. 7 * 8 * This software was developed by the Computer Systems Engineering group 9 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 10 * contributed to Berkeley. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * This product includes software developed by the University of 23 * California, Lawrence Berkeley Laboratory and its contributors. 24 * 4. Neither the name of the University nor the names of its contributors 25 * may be used to endorse or promote products derived from this software 26 * without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 * 40 */ 41 42 #include <sys/param.h> 43 #include <sys/socket.h> 44 #include <net/if.h> 45 #include <net/if_ether.h> 46 #include <netinet/in.h> 47 #include <netinet/in_systm.h> 48 #include <netinet/ip.h> 49 #include <netinet/ip_var.h> 50 #include <netinet/udp.h> 51 #include <netinet/udp_var.h> 52 53 #ifdef _STANDALONE 54 #include <lib/libkern/libkern.h> 55 #else 56 #include <string.h> 57 #endif 58 59 #include "stand.h" 60 #include "net.h" 61 62 /* 63 * sends an IP packet, if it's alredy constructed 64 */ 65 static ssize_t 66 _sendip(struct iodesc * d, struct ip * ip, size_t len) 67 { 68 u_char *ea; 69 70 if (ip->ip_dst.s_addr == INADDR_BROADCAST || ip->ip_src.s_addr == 0 || 71 netmask == 0 || SAMENET(ip->ip_src, ip->ip_dst, netmask)) { 72 ea = arpwhohas(d, ip->ip_dst); 73 } else { 74 ea = arpwhohas(d, gateip); 75 } 76 77 return sendether(d, ip, len, ea, ETHERTYPE_IP); 78 } 79 80 /* 81 * fills out the IP header 82 * Caller must leave room for ethernet, ip and udp headers in front! 83 */ 84 ssize_t 85 sendip(struct iodesc * d, void *pkt, size_t len, u_int8_t proto) 86 { 87 ssize_t cc; 88 struct ip *ip; 89 90 ip = (struct ip *) pkt - 1; 91 len += sizeof(*ip); 92 93 (void) memset(ip, 0, sizeof(*ip)); 94 95 ip->ip_v = IPVERSION; 96 ip->ip_hl = sizeof(*ip) >> 2; 97 ip->ip_len = htons(len); 98 ip->ip_p = proto; 99 ip->ip_ttl = IPDEFTTL; 100 ip->ip_src = d->myip; 101 ip->ip_dst = d->destip; 102 ip->ip_sum = ip_cksum(ip, sizeof(*ip)); 103 104 cc = _sendip(d, ip, len); 105 106 if (cc == -1) 107 return -1; 108 if ((size_t) cc != len) 109 panic("sendip: bad write (%zd != %zu)", cc, len); 110 return (cc - (sizeof(*ip))); 111 } 112 113 /* 114 * reads an IP packet 115 * WARNING: the old version stripped the IP options, if there were 116 * any. Because we have absolutely no idea if the upper layer needs 117 * these or not, it's best to leave them there. 118 * 119 * The size returned is the size indicated in the header. 120 */ 121 ssize_t 122 readip(struct iodesc * d, void *pkt, size_t len, time_t tleft, u_int8_t proto) 123 { 124 ssize_t n; 125 size_t hlen; 126 struct ip *ip; 127 u_int16_t etype; 128 129 ip = (struct ip *) pkt - 1; 130 131 n = readether(d, ip, len + sizeof(*ip), tleft, &etype); 132 if (n == -1 || (size_t) n < sizeof(*ip)) 133 return -1; 134 135 if (etype == ETHERTYPE_ARP) { 136 struct arphdr *ah = (void *) ip; 137 if (ah->ar_op == htons(ARPOP_REQUEST)) { 138 /* Send ARP reply */ 139 arp_reply(d, ah); 140 } 141 return -1; 142 } 143 144 if (etype != ETHERTYPE_IP) { 145 #ifdef NET_DEBUG 146 if (debug) 147 printf("readip: not IP. ether_type=%x\n", etype); 148 #endif 149 return -1; 150 } 151 152 /* Check ip header */ 153 if (ip->ip_v != IPVERSION || 154 ip->ip_p != proto) { /* half char */ 155 #ifdef NET_DEBUG 156 if (debug) { 157 printf("readip: wrong IP version or wrong proto " 158 "ip_v=%d ip_p=%d\n", ip->ip_v, ip->ip_p); 159 } 160 #endif 161 return -1; 162 } 163 164 hlen = ip->ip_hl << 2; 165 if (hlen < sizeof(*ip) || ip_cksum(ip, hlen) != 0) { 166 #ifdef NET_DEBUG 167 if (debug) 168 printf("readip: short hdr or bad cksum.\n"); 169 #endif 170 return -1; 171 } 172 if (n < ntohs(ip->ip_len)) { 173 #ifdef NET_DEBUG 174 if (debug) 175 printf("readip: bad length %d < %d.\n", 176 (int) n, ntohs(ip->ip_len)); 177 #endif 178 return -1; 179 } 180 if (d->myip.s_addr && ip->ip_dst.s_addr != d->myip.s_addr) { 181 #ifdef NET_DEBUG 182 if (debug) { 183 printf("readip: bad saddr %s != ", inet_ntoa(d->myip)); 184 printf("%s\n", inet_ntoa(ip->ip_dst)); 185 } 186 #endif 187 return -1; 188 } 189 return (ntohs(ip->ip_len) - 20); 190 } 191