xref: /openbsd-src/sys/lib/libsa/rarp.c (revision eb76c208173c67d7ebbeb2537785e4cca078f06d)
1*eb76c208Smpi /*	$OpenBSD: rarp.c,v 1.11 2014/07/13 15:31:20 mpi Exp $	*/
279dbd5ceSniklas /*	$NetBSD: rarp.c,v 1.13 1996/10/13 02:29:05 christos Exp $	*/
3df930be7Sderaadt 
4df930be7Sderaadt /*
5df930be7Sderaadt  * Copyright (c) 1992 Regents of the University of California.
6df930be7Sderaadt  * All rights reserved.
7df930be7Sderaadt  *
8df930be7Sderaadt  * This software was developed by the Computer Systems Engineering group
9df930be7Sderaadt  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
10df930be7Sderaadt  * contributed to Berkeley.
11df930be7Sderaadt  *
12df930be7Sderaadt  * Redistribution and use in source and binary forms, with or without
13df930be7Sderaadt  * modification, are permitted provided that the following conditions
14df930be7Sderaadt  * are met:
15df930be7Sderaadt  * 1. Redistributions of source code must retain the above copyright
16df930be7Sderaadt  *    notice, this list of conditions and the following disclaimer.
17df930be7Sderaadt  * 2. Redistributions in binary form must reproduce the above copyright
18df930be7Sderaadt  *    notice, this list of conditions and the following disclaimer in the
19df930be7Sderaadt  *    documentation and/or other materials provided with the distribution.
20df930be7Sderaadt  * 3. All advertising materials mentioning features or use of this software
21df930be7Sderaadt  *    must display the following acknowledgement:
22df930be7Sderaadt  *	This product includes software developed by the University of
23df930be7Sderaadt  *	California, Lawrence Berkeley Laboratory and its contributors.
24df930be7Sderaadt  * 4. Neither the name of the University nor the names of its contributors
25df930be7Sderaadt  *    may be used to endorse or promote products derived from this software
26df930be7Sderaadt  *    without specific prior written permission.
27df930be7Sderaadt  *
28df930be7Sderaadt  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29df930be7Sderaadt  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30df930be7Sderaadt  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31df930be7Sderaadt  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32df930be7Sderaadt  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33df930be7Sderaadt  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34df930be7Sderaadt  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35df930be7Sderaadt  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36df930be7Sderaadt  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37df930be7Sderaadt  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38df930be7Sderaadt  * SUCH DAMAGE.
39df930be7Sderaadt  *
40df930be7Sderaadt  * @(#) Header: arp.c,v 1.5 93/07/15 05:52:26 leres Exp  (LBL)
41df930be7Sderaadt  */
42df930be7Sderaadt #include <sys/param.h>
43df930be7Sderaadt #include <sys/socket.h>
44df930be7Sderaadt #include <net/if.h>
45df930be7Sderaadt #include <netinet/in.h>
46df930be7Sderaadt 
47df930be7Sderaadt #include <netinet/if_ether.h>
48df930be7Sderaadt 
49df930be7Sderaadt #include "stand.h"
50df930be7Sderaadt #include "net.h"
51df930be7Sderaadt #include "netif.h"
52df930be7Sderaadt 
53c4071fd1Smillert static ssize_t rarpsend(struct iodesc *, void *, size_t);
54c4071fd1Smillert static ssize_t rarprecv(struct iodesc *, void *, size_t, time_t);
55df930be7Sderaadt 
56df930be7Sderaadt /*
57df930be7Sderaadt  * Ethernet (Reverse) Address Resolution Protocol (see RFC 903, and 826).
58df930be7Sderaadt  */
59df930be7Sderaadt int
rarp_getipaddress(int sock)60599546b3Sderaadt rarp_getipaddress(int sock)
61df930be7Sderaadt {
62df930be7Sderaadt 	struct iodesc *d;
63599546b3Sderaadt 	struct ether_arp *ap;
64df930be7Sderaadt 	struct {
65df930be7Sderaadt 		u_char header[ETHER_SIZE];
66df930be7Sderaadt 		struct {
67df930be7Sderaadt 			struct ether_arp arp;
68df930be7Sderaadt 			u_char pad[18];		/* 60 - sizeof(arp) */
69df930be7Sderaadt 		} data;
70df930be7Sderaadt 	} wbuf;
71df930be7Sderaadt 	struct {
72df930be7Sderaadt 		u_char header[ETHER_SIZE];
73df930be7Sderaadt 		struct {
74df930be7Sderaadt 			struct ether_arp arp;
75df930be7Sderaadt 			u_char pad[24];		/* extra space */
76df930be7Sderaadt 		} data;
77df930be7Sderaadt 	} rbuf;
78df930be7Sderaadt 
79df930be7Sderaadt #ifdef RARP_DEBUG
80df930be7Sderaadt 	if (debug)
81df930be7Sderaadt 		printf("rarp: socket=%d\n", sock);
82df930be7Sderaadt #endif
83df930be7Sderaadt 	if (!(d = socktodesc(sock))) {
84df930be7Sderaadt 		printf("rarp: bad socket. %d\n", sock);
85df930be7Sderaadt 		return (-1);
86df930be7Sderaadt 	}
87df930be7Sderaadt #ifdef RARP_DEBUG
88df930be7Sderaadt 	if (debug)
89df930be7Sderaadt 		printf("rarp: d=%x\n", (u_int)d);
90df930be7Sderaadt #endif
91df930be7Sderaadt 
92df930be7Sderaadt 	bzero((char *)&wbuf.data, sizeof(wbuf.data));
93df930be7Sderaadt 	ap = &wbuf.data.arp;
94df930be7Sderaadt 	ap->arp_hrd = htons(ARPHRD_ETHER);
95df930be7Sderaadt 	ap->arp_pro = htons(ETHERTYPE_IP);
96df930be7Sderaadt 	ap->arp_hln = sizeof(ap->arp_sha); /* hardware address length */
97df930be7Sderaadt 	ap->arp_pln = sizeof(ap->arp_spa); /* protocol address length */
98df930be7Sderaadt 	ap->arp_op = htons(ARPOP_REVREQUEST);
99df930be7Sderaadt 	bcopy(d->myea, ap->arp_sha, 6);
100df930be7Sderaadt 	bcopy(d->myea, ap->arp_tha, 6);
101df930be7Sderaadt 
102df930be7Sderaadt 	if (sendrecv(d,
103df930be7Sderaadt 	    rarpsend, &wbuf.data, sizeof(wbuf.data),
104df930be7Sderaadt 	    rarprecv, &rbuf.data, sizeof(rbuf.data)) < 0)
105df930be7Sderaadt 	{
106df930be7Sderaadt 		printf("No response for RARP request\n");
107df930be7Sderaadt 		return (-1);
108df930be7Sderaadt 	}
109df930be7Sderaadt 
110df930be7Sderaadt 	ap = &rbuf.data.arp;
111df930be7Sderaadt 	bcopy(ap->arp_tpa, (char *)&myip, sizeof(myip));
112df930be7Sderaadt #if 0
113df930be7Sderaadt 	/* XXX - Can NOT assume this is our root server! */
114df930be7Sderaadt 	bcopy(ap->arp_spa, (char *)&rootip, sizeof(rootip));
115df930be7Sderaadt #endif
116df930be7Sderaadt 
117df930be7Sderaadt 	/* Compute our "natural" netmask. */
118df930be7Sderaadt 	if (IN_CLASSA(myip.s_addr))
119df930be7Sderaadt 		netmask = IN_CLASSA_NET;
120df930be7Sderaadt 	else if (IN_CLASSB(myip.s_addr))
121df930be7Sderaadt 		netmask = IN_CLASSB_NET;
122df930be7Sderaadt 	else
123df930be7Sderaadt 		netmask = IN_CLASSC_NET;
124df930be7Sderaadt 
125df930be7Sderaadt 	d->myip = myip;
126df930be7Sderaadt 	return (0);
127df930be7Sderaadt }
128df930be7Sderaadt 
129df930be7Sderaadt /*
130df930be7Sderaadt  * Broadcast a RARP request (i.e. who knows who I am)
131df930be7Sderaadt  */
132df930be7Sderaadt static ssize_t
rarpsend(struct iodesc * d,void * pkt,size_t len)133599546b3Sderaadt rarpsend(struct iodesc *d, void *pkt, size_t len)
134df930be7Sderaadt {
135df930be7Sderaadt 
136df930be7Sderaadt #ifdef RARP_DEBUG
137df930be7Sderaadt 	if (debug)
138df930be7Sderaadt 		printf("rarpsend: called\n");
139df930be7Sderaadt #endif
140df930be7Sderaadt 
141df930be7Sderaadt 	return (sendether(d, pkt, len, bcea, ETHERTYPE_REVARP));
142df930be7Sderaadt }
143df930be7Sderaadt 
144df930be7Sderaadt /*
145df930be7Sderaadt  * Returns 0 if this is the packet we're waiting for
146df930be7Sderaadt  * else -1 (and errno == 0)
147df930be7Sderaadt  */
148df930be7Sderaadt static ssize_t
rarprecv(struct iodesc * d,void * pkt,size_t len,time_t tleft)149599546b3Sderaadt rarprecv(struct iodesc *d, void *pkt, size_t len, time_t tleft)
150df930be7Sderaadt {
151599546b3Sderaadt 	ssize_t n;
152599546b3Sderaadt 	struct ether_arp *ap;
153df930be7Sderaadt 	u_int16_t etype;	/* host order */
154df930be7Sderaadt 
155df930be7Sderaadt #ifdef RARP_DEBUG
156df930be7Sderaadt 	if (debug)
157df930be7Sderaadt 		printf("rarprecv: ");
158df930be7Sderaadt #endif
159df930be7Sderaadt 
160df930be7Sderaadt 	n = readether(d, pkt, len, tleft, &etype);
161df930be7Sderaadt 	errno = 0;	/* XXX */
162bfcf73bfSniklas 	if (n < 0 || (size_t)n < sizeof(struct ether_arp)) {
163df930be7Sderaadt #ifdef RARP_DEBUG
164df930be7Sderaadt 		if (debug)
165df930be7Sderaadt 			printf("bad len=%d\n", n);
166df930be7Sderaadt #endif
167df930be7Sderaadt 		return (-1);
168df930be7Sderaadt 	}
169df930be7Sderaadt 
170df930be7Sderaadt 	if (etype != ETHERTYPE_REVARP) {
171df930be7Sderaadt #ifdef RARP_DEBUG
172df930be7Sderaadt 		if (debug)
173df930be7Sderaadt 			printf("bad type=0x%x\n", etype);
174df930be7Sderaadt #endif
175df930be7Sderaadt 		return (-1);
176df930be7Sderaadt 	}
177df930be7Sderaadt 
178df930be7Sderaadt 	ap = (struct ether_arp *)pkt;
179df930be7Sderaadt 	if (ap->arp_hrd != htons(ARPHRD_ETHER) ||
180df930be7Sderaadt 	    ap->arp_pro != htons(ETHERTYPE_IP) ||
181df930be7Sderaadt 	    ap->arp_hln != sizeof(ap->arp_sha) ||
182df930be7Sderaadt 	    ap->arp_pln != sizeof(ap->arp_spa) )
183df930be7Sderaadt 	{
184df930be7Sderaadt #ifdef RARP_DEBUG
185df930be7Sderaadt 		if (debug)
186eb273968Smickey 			printf("bad hrd/pro/hln/pln\n");
187df930be7Sderaadt #endif
188df930be7Sderaadt 		return (-1);
189df930be7Sderaadt 	}
190df930be7Sderaadt 
191df930be7Sderaadt 	if (ap->arp_op != htons(ARPOP_REVREPLY)) {
192df930be7Sderaadt #ifdef RARP_DEBUG
193df930be7Sderaadt 		if (debug)
194df930be7Sderaadt 			printf("bad op=0x%x\n", ntohs(ap->arp_op));
195df930be7Sderaadt #endif
196df930be7Sderaadt 		return (-1);
197df930be7Sderaadt 	}
198df930be7Sderaadt 
199df930be7Sderaadt 	/* Is the reply for our Ethernet address? */
200df930be7Sderaadt 	if (bcmp(ap->arp_tha, d->myea, 6)) {
201df930be7Sderaadt #ifdef RARP_DEBUG
202df930be7Sderaadt 		if (debug)
203df930be7Sderaadt 			printf("unwanted address\n");
204df930be7Sderaadt #endif
205df930be7Sderaadt 		return (-1);
206df930be7Sderaadt 	}
207df930be7Sderaadt 
208df930be7Sderaadt 	/* We have our answer. */
209df930be7Sderaadt #ifdef RARP_DEBUG
210df930be7Sderaadt 	if (debug)
211df930be7Sderaadt 		printf("got it\n");
212df930be7Sderaadt #endif
213df930be7Sderaadt 	return (n);
214df930be7Sderaadt }
215