1 /* $NetBSD: ip.c,v 1.4 2019/03/31 20:08:45 christos 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 #include <sys/param.h> 42 #include <sys/socket.h> 43 #include <net/if.h> 44 #include <net/if_ether.h> 45 #include <netinet/in.h> 46 #include <netinet/in_systm.h> 47 #include <netinet/ip.h> 48 #include <netinet/ip_var.h> 49 #include <netinet/udp.h> 50 #include <netinet/udp_var.h> 51 52 #ifdef _STANDALONE 53 #include <lib/libkern/libkern.h> 54 #else 55 #include <string.h> 56 #endif 57 58 #include "stand.h" 59 #include "net.h" 60 61 /* 62 * sends an IP packet, if it's alredy constructed 63 */ 64 static ssize_t 65 _sendip(struct iodesc *d, struct ip *ip, size_t len) 66 { 67 u_char *ea; 68 69 if (ip->ip_dst.s_addr == INADDR_BROADCAST || ip->ip_src.s_addr == 0 || 70 netmask == 0 || SAMENET(ip->ip_src, ip->ip_dst, netmask)) { 71 ea = arpwhohas(d, ip->ip_dst); 72 } else { 73 ea = arpwhohas(d, gateip); 74 } 75 76 return sendether(d, ip, len, ea, ETHERTYPE_IP); 77 } 78 79 /* 80 * fills out the IP header 81 * Caller must leave room for ethernet, ip and udp headers in front! 82 */ 83 ssize_t 84 sendip(struct iodesc *d, void *pkt, size_t len, u_int8_t proto) 85 { 86 ssize_t cc; 87 struct ip *ip; 88 89 ip = (struct ip *)pkt - 1; 90 len += sizeof(*ip); 91 92 memset(ip, 0, sizeof(*ip)); 93 94 ip->ip_v = IPVERSION; 95 ip->ip_hl = sizeof(*ip) >> 2; 96 ip->ip_len = htons(len); 97 ip->ip_p = proto; 98 ip->ip_ttl = IPDEFTTL; 99 ip->ip_src = d->myip; 100 ip->ip_dst = d->destip; 101 ip->ip_sum = ip_cksum(ip, sizeof(*ip)); 102 103 cc = _sendip(d, ip, len); 104 105 if (cc == -1) 106 return -1; 107 if ((size_t)cc != len) 108 panic("%s: bad write (%zd != %zu)", __func__, cc, len); 109 return (cc - (sizeof(*ip))); 110 } 111 112 /* 113 * reads an IP packet 114 * WARNING: the old version stripped the IP options, if there were 115 * any. Because we have absolutely no idea if the upper layer needs 116 * these or not, it's best to leave them there. 117 * 118 * The size returned is the size indicated in the header. 119 */ 120 ssize_t 121 readip(struct iodesc *d, void *pkt, size_t len, time_t tleft, u_int8_t proto) 122 { 123 ssize_t n; 124 size_t hlen; 125 struct ip *ip; 126 u_int16_t etype; 127 128 ip = (struct ip *)pkt - 1; 129 130 n = readether(d, ip, len + sizeof(*ip), tleft, &etype); 131 if (n == -1 || (size_t)n < sizeof(*ip)) 132 return -1; 133 134 if (etype == ETHERTYPE_ARP) { 135 struct arphdr *ah = (void *)ip; 136 if (n < (ssize_t)(sizeof(*ah) + 2 * (ah->ar_hln + ah->ar_pln))) { 137 return -1; 138 } 139 if (ah->ar_op == htons(ARPOP_REQUEST)) { 140 /* Send ARP reply */ 141 arp_reply(d, ah); 142 } 143 return -1; 144 } 145 if (etype != ETHERTYPE_IP) { 146 return -1; 147 } 148 149 if (ip->ip_v != IPVERSION || ip->ip_p != proto) { 150 return -1; 151 } 152 153 hlen = ip->ip_hl << 2; 154 if (hlen != sizeof(*ip) || ip_cksum(ip, hlen) != 0) { 155 return -1; 156 } 157 if (ntohs(ip->ip_len) < hlen) { 158 return -1; 159 } 160 if (n < ntohs(ip->ip_len)) { 161 return -1; 162 } 163 if (d->myip.s_addr && ip->ip_dst.s_addr != d->myip.s_addr) { 164 return -1; 165 } 166 167 return (ntohs(ip->ip_len) - hlen); 168 } 169