rarp.c revision 256281
1228753Smm/*	$NetBSD: rarp.c,v 1.16 1997/07/07 15:52:52 drochner Exp $	*/
2228753Smm
3228753Smm/*
4228753Smm * Copyright (c) 1992 Regents of the University of California.
5228753Smm * All rights reserved.
6228753Smm *
7228753Smm * This software was developed by the Computer Systems Engineering group
8228753Smm * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
9228753Smm * contributed to Berkeley.
10228753Smm *
11228753Smm * Redistribution and use in source and binary forms, with or without
12228753Smm * modification, are permitted provided that the following conditions
13228753Smm * are met:
14228753Smm * 1. Redistributions of source code must retain the above copyright
15228753Smm *    notice, this list of conditions and the following disclaimer.
16228753Smm * 2. Redistributions in binary form must reproduce the above copyright
17228753Smm *    notice, this list of conditions and the following disclaimer in the
18228753Smm *    documentation and/or other materials provided with the distribution.
19228753Smm * 4. Neither the name of the University nor the names of its contributors
20228753Smm *    may be used to endorse or promote products derived from this software
21228753Smm *    without specific prior written permission.
22228753Smm *
23228753Smm * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24228753Smm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25228753Smm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26228753Smm * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27228753Smm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28228753Smm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29228753Smm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30228753Smm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31228753Smm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32228753Smm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33228753Smm * SUCH DAMAGE.
34228753Smm *
35228753Smm * @(#) Header: arp.c,v 1.5 93/07/15 05:52:26 leres Exp  (LBL)
36228753Smm */
37228753Smm
38228753Smm#include <sys/cdefs.h>
39228753Smm__FBSDID("$FreeBSD: stable/10/lib/libstand/rarp.c 165906 2007-01-09 01:02:06Z imp $");
40228753Smm
41228753Smm#include <sys/param.h>
42228753Smm#include <sys/socket.h>
43228753Smm#include <net/if.h>
44228753Smm#include <netinet/in.h>
45228753Smm#include <netinet/if_ether.h>
46228753Smm
47228753Smm#include <netinet/in_systm.h>
48228753Smm
49228753Smm#include <string.h>
50228753Smm
51228753Smm#include "stand.h"
52228753Smm#include "net.h"
53228753Smm#include "netif.h"
54228753Smm
55228753Smm
56228753Smmstatic ssize_t rarpsend(struct iodesc *, void *, size_t);
57228753Smmstatic ssize_t rarprecv(struct iodesc *, void *, size_t, time_t);
58228753Smm
59228753Smm/*
60228753Smm * Ethernet (Reverse) Address Resolution Protocol (see RFC 903, and 826).
61228753Smm */
62228753Smmint
63228753Smmrarp_getipaddress(sock)
64228753Smm	int sock;
65228753Smm{
66228753Smm	struct iodesc *d;
67228753Smm	struct ether_arp *ap;
68228753Smm	struct {
69228753Smm		u_char header[ETHER_SIZE];
70228753Smm		struct {
71228753Smm			struct ether_arp arp;
72228753Smm			u_char pad[18]; 	/* 60 - sizeof(arp) */
73228753Smm		} data;
74228753Smm	} wbuf;
75228753Smm	struct {
76228753Smm		u_char header[ETHER_SIZE];
77228753Smm		struct {
78228753Smm			struct ether_arp arp;
79228753Smm			u_char pad[24]; 	/* extra space */
80228753Smm		} data;
81228753Smm	} rbuf;
82228753Smm
83228753Smm#ifdef RARP_DEBUG
84228753Smm 	if (debug)
85228753Smm		printf("rarp: socket=%d\n", sock);
86228753Smm#endif
87228753Smm	if (!(d = socktodesc(sock))) {
88228753Smm		printf("rarp: bad socket. %d\n", sock);
89228753Smm		return (-1);
90228753Smm	}
91228753Smm#ifdef RARP_DEBUG
92228753Smm 	if (debug)
93228753Smm		printf("rarp: d=%x\n", (u_int)d);
94228753Smm#endif
95228753Smm
96228753Smm	bzero((char*)&wbuf.data, sizeof(wbuf.data));
97228753Smm	ap = &wbuf.data.arp;
98228753Smm	ap->arp_hrd = htons(ARPHRD_ETHER);
99228753Smm	ap->arp_pro = htons(ETHERTYPE_IP);
100228753Smm	ap->arp_hln = sizeof(ap->arp_sha); /* hardware address length */
101228753Smm	ap->arp_pln = sizeof(ap->arp_spa); /* protocol address length */
102228753Smm	ap->arp_op = htons(ARPOP_REVREQUEST);
103228753Smm	bcopy(d->myea, ap->arp_sha, 6);
104228753Smm	bcopy(d->myea, ap->arp_tha, 6);
105228753Smm
106228753Smm	if (sendrecv(d,
107228753Smm	    rarpsend, &wbuf.data, sizeof(wbuf.data),
108228753Smm	    rarprecv, &rbuf.data, sizeof(rbuf.data)) < 0)
109228753Smm	{
110228753Smm		printf("No response for RARP request\n");
111228753Smm		return (-1);
112228753Smm	}
113228753Smm
114228753Smm	ap = &rbuf.data.arp;
115228753Smm	bcopy(ap->arp_tpa, (char *)&myip, sizeof(myip));
116228753Smm#if 0
117228753Smm	/* XXX - Can NOT assume this is our root server! */
118228753Smm	bcopy(ap->arp_spa, (char *)&rootip, sizeof(rootip));
119228753Smm#endif
120228753Smm
121228753Smm	/* Compute our "natural" netmask. */
122228753Smm	if (IN_CLASSA(myip.s_addr))
123228753Smm		netmask = IN_CLASSA_NET;
124228753Smm	else if (IN_CLASSB(myip.s_addr))
125228753Smm		netmask = IN_CLASSB_NET;
126228753Smm	else
127228753Smm		netmask = IN_CLASSC_NET;
128228753Smm
129228753Smm	d->myip = myip;
130228753Smm	return (0);
131228753Smm}
132228753Smm
133228753Smm/*
134228753Smm * Broadcast a RARP request (i.e. who knows who I am)
135228753Smm */
136228753Smmstatic ssize_t
137228753Smmrarpsend(d, pkt, len)
138228753Smm	struct iodesc *d;
139228753Smm	void *pkt;
140228753Smm	size_t len;
141228753Smm{
142228753Smm
143228753Smm#ifdef RARP_DEBUG
144228753Smm 	if (debug)
145228753Smm		printf("rarpsend: called\n");
146228753Smm#endif
147228753Smm
148228753Smm	return (sendether(d, pkt, len, bcea, ETHERTYPE_REVARP));
149228753Smm}
150228753Smm
151228753Smm/*
152228753Smm * Returns 0 if this is the packet we're waiting for
153228753Smm * else -1 (and errno == 0)
154228753Smm */
155228753Smmstatic ssize_t
156228753Smmrarprecv(d, pkt, len, tleft)
157228753Smm	struct iodesc *d;
158228753Smm	void *pkt;
159228753Smm	size_t len;
160228753Smm	time_t tleft;
161228753Smm{
162228753Smm	ssize_t n;
163228753Smm	struct ether_arp *ap;
164228753Smm	u_int16_t etype;	/* host order */
165228753Smm
166228753Smm#ifdef RARP_DEBUG
167228753Smm 	if (debug)
168228753Smm		printf("rarprecv: ");
169228753Smm#endif
170228753Smm
171228753Smm	n = readether(d, pkt, len, tleft, &etype);
172228753Smm	errno = 0;	/* XXX */
173228753Smm	if (n == -1 || n < sizeof(struct ether_arp)) {
174228753Smm#ifdef RARP_DEBUG
175228753Smm		if (debug)
176228753Smm			printf("bad len=%d\n", n);
177228753Smm#endif
178228753Smm		return (-1);
179228753Smm	}
180228753Smm
181228753Smm	if (etype != ETHERTYPE_REVARP) {
182228753Smm#ifdef RARP_DEBUG
183228753Smm		if (debug)
184228753Smm			printf("bad type=0x%x\n", etype);
185228753Smm#endif
186228753Smm		return (-1);
187228753Smm	}
188228753Smm
189228753Smm	ap = (struct ether_arp *)pkt;
190228753Smm	if (ap->arp_hrd != htons(ARPHRD_ETHER) ||
191228753Smm	    ap->arp_pro != htons(ETHERTYPE_IP) ||
192228753Smm	    ap->arp_hln != sizeof(ap->arp_sha) ||
193228753Smm	    ap->arp_pln != sizeof(ap->arp_spa) )
194228753Smm	{
195228753Smm#ifdef RARP_DEBUG
196228753Smm		if (debug)
197228753Smm			printf("bad hrd/pro/hln/pln\n");
198228753Smm#endif
199228753Smm		return (-1);
200228753Smm	}
201228753Smm
202228753Smm	if (ap->arp_op != htons(ARPOP_REVREPLY)) {
203228753Smm#ifdef RARP_DEBUG
204228753Smm		if (debug)
205228753Smm			printf("bad op=0x%x\n", ntohs(ap->arp_op));
206228753Smm#endif
207228753Smm		return (-1);
208228753Smm	}
209228753Smm
210228753Smm	/* Is the reply for our Ethernet address? */
211228753Smm	if (bcmp(ap->arp_tha, d->myea, 6)) {
212228753Smm#ifdef RARP_DEBUG
213228753Smm		if (debug)
214228753Smm			printf("unwanted address\n");
215228753Smm#endif
216228753Smm		return (-1);
217228753Smm	}
218228753Smm
219228753Smm	/* We have our answer. */
220228753Smm#ifdef RARP_DEBUG
221228753Smm 	if (debug)
222228753Smm		printf("got it\n");
223228753Smm#endif
224228753Smm	return (n);
225228753Smm}
226228753Smm