1 1.34 christos /* $NetBSD: rarp.c,v 1.34 2019/04/05 20:09:29 christos Exp $ */ 2 1.4 cgd 3 1.3 brezak /* 4 1.3 brezak * Copyright (c) 1992 Regents of the University of California. 5 1.3 brezak * All rights reserved. 6 1.3 brezak * 7 1.3 brezak * This software was developed by the Computer Systems Engineering group 8 1.3 brezak * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 9 1.3 brezak * contributed to Berkeley. 10 1.3 brezak * 11 1.3 brezak * Redistribution and use in source and binary forms, with or without 12 1.3 brezak * modification, are permitted provided that the following conditions 13 1.3 brezak * are met: 14 1.3 brezak * 1. Redistributions of source code must retain the above copyright 15 1.3 brezak * notice, this list of conditions and the following disclaimer. 16 1.3 brezak * 2. Redistributions in binary form must reproduce the above copyright 17 1.3 brezak * notice, this list of conditions and the following disclaimer in the 18 1.3 brezak * documentation and/or other materials provided with the distribution. 19 1.3 brezak * 3. All advertising materials mentioning features or use of this software 20 1.3 brezak * must display the following acknowledgement: 21 1.3 brezak * This product includes software developed by the University of 22 1.3 brezak * California, Lawrence Berkeley Laboratory and its contributors. 23 1.3 brezak * 4. Neither the name of the University nor the names of its contributors 24 1.3 brezak * may be used to endorse or promote products derived from this software 25 1.3 brezak * without specific prior written permission. 26 1.3 brezak * 27 1.3 brezak * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 28 1.3 brezak * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 1.3 brezak * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30 1.3 brezak * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 31 1.3 brezak * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32 1.3 brezak * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33 1.3 brezak * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 1.3 brezak * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 1.3 brezak * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36 1.3 brezak * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37 1.3 brezak * SUCH DAMAGE. 38 1.3 brezak * 39 1.4 cgd * @(#) Header: arp.c,v 1.5 93/07/15 05:52:26 leres Exp (LBL) 40 1.3 brezak */ 41 1.1 brezak #include <sys/param.h> 42 1.1 brezak #include <sys/socket.h> 43 1.1 brezak #include <net/if.h> 44 1.16 drochner #include <net/if_ether.h> 45 1.1 brezak #include <netinet/in.h> 46 1.1 brezak 47 1.1 brezak #include <netinet/in_systm.h> 48 1.19 thorpej 49 1.19 thorpej #ifdef _STANDALONE 50 1.19 thorpej #include <lib/libkern/libkern.h> 51 1.19 thorpej #else 52 1.19 thorpej #include <string.h> 53 1.19 thorpej #endif 54 1.1 brezak 55 1.1 brezak #include "stand.h" 56 1.1 brezak #include "net.h" 57 1.16 drochner 58 1.16 drochner 59 1.16 drochner /* 60 1.16 drochner * Ethernet Address Resolution Protocol. 61 1.16 drochner * 62 1.16 drochner * See RFC 826 for protocol description. Structure below is adapted 63 1.23 perry * to resolving internet addresses. Field names used correspond to 64 1.16 drochner * RFC 826. 65 1.16 drochner */ 66 1.26 isaki struct ether_arp { 67 1.16 drochner struct arphdr ea_hdr; /* fixed-size header */ 68 1.16 drochner u_int8_t arp_sha[ETHER_ADDR_LEN]; /* sender hardware address */ 69 1.16 drochner u_int8_t arp_spa[4]; /* sender protocol address */ 70 1.16 drochner u_int8_t arp_tha[ETHER_ADDR_LEN]; /* target hardware address */ 71 1.16 drochner u_int8_t arp_tpa[4]; /* target protocol address */ 72 1.16 drochner }; 73 1.16 drochner #define arp_hrd ea_hdr.ar_hrd 74 1.16 drochner #define arp_pro ea_hdr.ar_pro 75 1.16 drochner #define arp_hln ea_hdr.ar_hln 76 1.16 drochner #define arp_pln ea_hdr.ar_pln 77 1.16 drochner #define arp_op ea_hdr.ar_op 78 1.1 brezak 79 1.30 tsutsui static ssize_t rarpsend(struct iodesc *, void *, size_t); 80 1.30 tsutsui static ssize_t rarprecv(struct iodesc *, void *, size_t, saseconds_t); 81 1.1 brezak 82 1.1 brezak /* 83 1.1 brezak * Ethernet (Reverse) Address Resolution Protocol (see RFC 903, and 826). 84 1.1 brezak */ 85 1.9 pk int 86 1.26 isaki rarp_getipaddress(int sock) 87 1.1 brezak { 88 1.1 brezak struct iodesc *d; 89 1.20 augustss struct ether_arp *ap; 90 1.1 brezak struct { 91 1.31 zoltan u_char header[ETHERNET_HEADER_SIZE]; 92 1.6 gwr struct { 93 1.6 gwr struct ether_arp arp; 94 1.6 gwr u_char pad[18]; /* 60 - sizeof(arp) */ 95 1.6 gwr } data; 96 1.1 brezak } wbuf; 97 1.5 mycroft struct { 98 1.31 zoltan u_char header[ETHERNET_HEADER_SIZE]; 99 1.6 gwr struct { 100 1.6 gwr struct ether_arp arp; 101 1.6 gwr u_char pad[24]; /* extra space */ 102 1.6 gwr } data; 103 1.1 brezak } rbuf; 104 1.1 brezak 105 1.1 brezak #ifdef RARP_DEBUG 106 1.1 brezak if (debug) 107 1.33 christos printf("%s: socket=%d\n", __func__, sock); 108 1.1 brezak #endif 109 1.1 brezak if (!(d = socktodesc(sock))) { 110 1.33 christos printf("%s: bad socket. %d\n", __func__, sock); 111 1.26 isaki return -1; 112 1.1 brezak } 113 1.1 brezak #ifdef RARP_DEBUG 114 1.1 brezak if (debug) 115 1.33 christos printf("%s: d=%p\n", __func__, d); 116 1.1 brezak #endif 117 1.5 mycroft 118 1.27 christos (void)memset(&wbuf.data, 0, sizeof(wbuf.data)); 119 1.6 gwr ap = &wbuf.data.arp; 120 1.1 brezak ap->arp_hrd = htons(ARPHRD_ETHER); 121 1.1 brezak ap->arp_pro = htons(ETHERTYPE_IP); 122 1.1 brezak ap->arp_hln = sizeof(ap->arp_sha); /* hardware address length */ 123 1.1 brezak ap->arp_pln = sizeof(ap->arp_spa); /* protocol address length */ 124 1.6 gwr ap->arp_op = htons(ARPOP_REVREQUEST); 125 1.32 jakllsch (void)memcpy(ap->arp_sha, d->myea, ETHER_ADDR_LEN); 126 1.32 jakllsch (void)memcpy(ap->arp_tha, d->myea, ETHER_ADDR_LEN); 127 1.1 brezak 128 1.1 brezak if (sendrecv(d, 129 1.6 gwr rarpsend, &wbuf.data, sizeof(wbuf.data), 130 1.10 gwr rarprecv, &rbuf.data, sizeof(rbuf.data)) < 0) 131 1.10 gwr { 132 1.13 christos printf("No response for RARP request\n"); 133 1.26 isaki return -1; 134 1.1 brezak } 135 1.1 brezak 136 1.10 gwr ap = &rbuf.data.arp; 137 1.27 christos (void)memcpy(&myip, ap->arp_tpa, sizeof(myip)); 138 1.10 gwr #if 0 139 1.10 gwr /* XXX - Can NOT assume this is our root server! */ 140 1.27 christos (void)memcpy(&rootip, ap->arp_spa, sizeof(rootip)); 141 1.10 gwr #endif 142 1.10 gwr 143 1.10 gwr /* Compute our "natural" netmask. */ 144 1.10 gwr if (IN_CLASSA(myip.s_addr)) 145 1.10 gwr netmask = IN_CLASSA_NET; 146 1.10 gwr else if (IN_CLASSB(myip.s_addr)) 147 1.10 gwr netmask = IN_CLASSB_NET; 148 1.10 gwr else 149 1.10 gwr netmask = IN_CLASSC_NET; 150 1.10 gwr 151 1.10 gwr d->myip = myip; 152 1.26 isaki return 0; 153 1.1 brezak } 154 1.1 brezak 155 1.1 brezak /* 156 1.1 brezak * Broadcast a RARP request (i.e. who knows who I am) 157 1.1 brezak */ 158 1.8 pk static ssize_t 159 1.26 isaki rarpsend(struct iodesc *d, void *pkt, size_t len) 160 1.1 brezak { 161 1.5 mycroft 162 1.1 brezak #ifdef RARP_DEBUG 163 1.1 brezak if (debug) 164 1.33 christos printf("%s: called\n", __func__); 165 1.1 brezak #endif 166 1.5 mycroft 167 1.26 isaki return sendether(d, pkt, len, bcea, ETHERTYPE_REVARP); 168 1.1 brezak } 169 1.1 brezak 170 1.1 brezak /* 171 1.10 gwr * Returns 0 if this is the packet we're waiting for 172 1.10 gwr * else -1 (and errno == 0) 173 1.1 brezak */ 174 1.8 pk static ssize_t 175 1.29 tsutsui rarprecv(struct iodesc *d, void *pkt, size_t len, saseconds_t tleft) 176 1.1 brezak { 177 1.20 augustss ssize_t n; 178 1.20 augustss struct ether_arp *ap; 179 1.7 thorpej u_int16_t etype; /* host order */ 180 1.1 brezak 181 1.1 brezak #ifdef RARP_DEBUG 182 1.1 brezak if (debug) 183 1.33 christos printf("%s: ", __func__); 184 1.1 brezak #endif 185 1.1 brezak 186 1.8 pk n = readether(d, pkt, len, tleft, &etype); 187 1.10 gwr errno = 0; /* XXX */ 188 1.22 fvdl if (n == -1 || (size_t)n < sizeof(struct ether_arp)) { 189 1.6 gwr #ifdef RARP_DEBUG 190 1.6 gwr if (debug) 191 1.28 tsutsui printf("bad len=%d\n", (int)n); 192 1.6 gwr #endif 193 1.26 isaki return -1; 194 1.6 gwr } 195 1.5 mycroft 196 1.7 thorpej if (etype != ETHERTYPE_REVARP) { 197 1.6 gwr #ifdef RARP_DEBUG 198 1.6 gwr if (debug) 199 1.34 christos printf("bad type=0x%x\n", etype); 200 1.6 gwr #endif 201 1.26 isaki return -1; 202 1.6 gwr } 203 1.1 brezak 204 1.5 mycroft ap = (struct ether_arp *)pkt; 205 1.10 gwr if (ap->arp_hrd != htons(ARPHRD_ETHER) || 206 1.10 gwr ap->arp_pro != htons(ETHERTYPE_IP) || 207 1.10 gwr ap->arp_hln != sizeof(ap->arp_sha) || 208 1.10 gwr ap->arp_pln != sizeof(ap->arp_spa) ) 209 1.10 gwr { 210 1.6 gwr #ifdef RARP_DEBUG 211 1.6 gwr if (debug) 212 1.13 christos printf("bad hrd/pro/hln/pln\n"); 213 1.6 gwr #endif 214 1.26 isaki return -1; 215 1.6 gwr } 216 1.6 gwr 217 1.10 gwr if (ap->arp_op != htons(ARPOP_REVREPLY)) { 218 1.6 gwr #ifdef RARP_DEBUG 219 1.6 gwr if (debug) 220 1.34 christos printf("bad op=0x%x\n", ntohs(ap->arp_op)); 221 1.6 gwr #endif 222 1.26 isaki return -1; 223 1.6 gwr } 224 1.6 gwr 225 1.10 gwr /* Is the reply for our Ethernet address? */ 226 1.32 jakllsch if (memcmp(ap->arp_tha, d->myea, ETHER_ADDR_LEN)) { 227 1.6 gwr #ifdef RARP_DEBUG 228 1.6 gwr if (debug) 229 1.13 christos printf("unwanted address\n"); 230 1.6 gwr #endif 231 1.26 isaki return -1; 232 1.6 gwr } 233 1.1 brezak 234 1.10 gwr /* We have our answer. */ 235 1.6 gwr #ifdef RARP_DEBUG 236 1.10 gwr if (debug) 237 1.13 christos printf("got it\n"); 238 1.6 gwr #endif 239 1.26 isaki return n; 240 1.1 brezak } 241