rarp.c revision 84221
138451Smsmith/*	$NetBSD: rarp.c,v 1.16 1997/07/07 15:52:52 drochner Exp $	*/
238451Smsmith
338451Smsmith/*
438451Smsmith * Copyright (c) 1992 Regents of the University of California.
538451Smsmith * All rights reserved.
638451Smsmith *
738451Smsmith * This software was developed by the Computer Systems Engineering group
838451Smsmith * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
938451Smsmith * contributed to Berkeley.
1038451Smsmith *
1138451Smsmith * Redistribution and use in source and binary forms, with or without
1238451Smsmith * modification, are permitted provided that the following conditions
1338451Smsmith * are met:
1438451Smsmith * 1. Redistributions of source code must retain the above copyright
1538451Smsmith *    notice, this list of conditions and the following disclaimer.
1638451Smsmith * 2. Redistributions in binary form must reproduce the above copyright
1738451Smsmith *    notice, this list of conditions and the following disclaimer in the
1838451Smsmith *    documentation and/or other materials provided with the distribution.
1938451Smsmith * 3. All advertising materials mentioning features or use of this software
2038451Smsmith *    must display the following acknowledgement:
2138451Smsmith *	This product includes software developed by the University of
2238451Smsmith *	California, Lawrence Berkeley Laboratory and its contributors.
2338451Smsmith * 4. Neither the name of the University nor the names of its contributors
2438451Smsmith *    may be used to endorse or promote products derived from this software
2538451Smsmith *    without specific prior written permission.
2638451Smsmith *
2738451Smsmith * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2838451Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2938451Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3038451Smsmith * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
3138451Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3238451Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3338451Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3438451Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3538451Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3638451Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3738451Smsmith * SUCH DAMAGE.
3838451Smsmith *
3938451Smsmith * @(#) Header: arp.c,v 1.5 93/07/15 05:52:26 leres Exp  (LBL)
4038451Smsmith */
4184221Sdillon
4284221Sdillon#include <sys/cdefs.h>
4384221Sdillon__FBSDID("$FreeBSD: head/lib/libstand/rarp.c 84221 2001-09-30 22:28:01Z dillon $");
4484221Sdillon
4538451Smsmith#include <sys/param.h>
4638451Smsmith#include <sys/socket.h>
4738451Smsmith#include <net/if.h>
4838451Smsmith#include <netinet/in.h>
4938451Smsmith#include <netinet/if_ether.h>
5038451Smsmith
5138451Smsmith#include <netinet/in_systm.h>
5238451Smsmith
5338451Smsmith#include <string.h>
5438451Smsmith
5538451Smsmith#include "stand.h"
5638451Smsmith#include "net.h"
5738451Smsmith#include "netif.h"
5838451Smsmith
5938451Smsmith
6038451Smsmithstatic ssize_t rarpsend(struct iodesc *, void *, size_t);
6138451Smsmithstatic ssize_t rarprecv(struct iodesc *, void *, size_t, time_t);
6238451Smsmith
6338451Smsmith/*
6438451Smsmith * Ethernet (Reverse) Address Resolution Protocol (see RFC 903, and 826).
6538451Smsmith */
6638451Smsmithint
6738451Smsmithrarp_getipaddress(sock)
6838451Smsmith	int sock;
6938451Smsmith{
7038451Smsmith	struct iodesc *d;
7138451Smsmith	register struct ether_arp *ap;
7238451Smsmith	struct {
7338451Smsmith		u_char header[ETHER_SIZE];
7438451Smsmith		struct {
7538451Smsmith			struct ether_arp arp;
7638451Smsmith			u_char pad[18]; 	/* 60 - sizeof(arp) */
7738451Smsmith		} data;
7838451Smsmith	} wbuf;
7938451Smsmith	struct {
8038451Smsmith		u_char header[ETHER_SIZE];
8138451Smsmith		struct {
8238451Smsmith			struct ether_arp arp;
8338451Smsmith			u_char pad[24]; 	/* extra space */
8438451Smsmith		} data;
8538451Smsmith	} rbuf;
8638451Smsmith
8738451Smsmith#ifdef RARP_DEBUG
8838451Smsmith 	if (debug)
8938451Smsmith		printf("rarp: socket=%d\n", sock);
9038451Smsmith#endif
9138451Smsmith	if (!(d = socktodesc(sock))) {
9238451Smsmith		printf("rarp: bad socket. %d\n", sock);
9338451Smsmith		return (-1);
9438451Smsmith	}
9538451Smsmith#ifdef RARP_DEBUG
9638451Smsmith 	if (debug)
9738451Smsmith		printf("rarp: d=%x\n", (u_int)d);
9838451Smsmith#endif
9938451Smsmith
10038451Smsmith	bzero((char*)&wbuf.data, sizeof(wbuf.data));
10138451Smsmith	ap = &wbuf.data.arp;
10238451Smsmith	ap->arp_hrd = htons(ARPHRD_ETHER);
10338451Smsmith	ap->arp_pro = htons(ETHERTYPE_IP);
10438451Smsmith	ap->arp_hln = sizeof(ap->arp_sha); /* hardware address length */
10538451Smsmith	ap->arp_pln = sizeof(ap->arp_spa); /* protocol address length */
10638451Smsmith	ap->arp_op = htons(ARPOP_REVREQUEST);
10738451Smsmith	bcopy(d->myea, ap->arp_sha, 6);
10838451Smsmith	bcopy(d->myea, ap->arp_tha, 6);
10938451Smsmith
11038451Smsmith	if (sendrecv(d,
11138451Smsmith	    rarpsend, &wbuf.data, sizeof(wbuf.data),
11238451Smsmith	    rarprecv, &rbuf.data, sizeof(rbuf.data)) < 0)
11338451Smsmith	{
11438451Smsmith		printf("No response for RARP request\n");
11538451Smsmith		return (-1);
11638451Smsmith	}
11738451Smsmith
11838451Smsmith	ap = &rbuf.data.arp;
11938451Smsmith	bcopy(ap->arp_tpa, (char *)&myip, sizeof(myip));
12038451Smsmith#if 0
12138451Smsmith	/* XXX - Can NOT assume this is our root server! */
12238451Smsmith	bcopy(ap->arp_spa, (char *)&rootip, sizeof(rootip));
12338451Smsmith#endif
12438451Smsmith
12538451Smsmith	/* Compute our "natural" netmask. */
12638451Smsmith	if (IN_CLASSA(myip.s_addr))
12738451Smsmith		netmask = IN_CLASSA_NET;
12838451Smsmith	else if (IN_CLASSB(myip.s_addr))
12938451Smsmith		netmask = IN_CLASSB_NET;
13038451Smsmith	else
13138451Smsmith		netmask = IN_CLASSC_NET;
13238451Smsmith
13338451Smsmith	d->myip = myip;
13438451Smsmith	return (0);
13538451Smsmith}
13638451Smsmith
13738451Smsmith/*
13838451Smsmith * Broadcast a RARP request (i.e. who knows who I am)
13938451Smsmith */
14038451Smsmithstatic ssize_t
14138451Smsmithrarpsend(d, pkt, len)
14238451Smsmith	register struct iodesc *d;
14338451Smsmith	register void *pkt;
14438451Smsmith	register size_t len;
14538451Smsmith{
14638451Smsmith
14738451Smsmith#ifdef RARP_DEBUG
14838451Smsmith 	if (debug)
14938451Smsmith		printf("rarpsend: called\n");
15038451Smsmith#endif
15138451Smsmith
15238451Smsmith	return (sendether(d, pkt, len, bcea, ETHERTYPE_REVARP));
15338451Smsmith}
15438451Smsmith
15538451Smsmith/*
15638451Smsmith * Returns 0 if this is the packet we're waiting for
15738451Smsmith * else -1 (and errno == 0)
15838451Smsmith */
15938451Smsmithstatic ssize_t
16038451Smsmithrarprecv(d, pkt, len, tleft)
16138451Smsmith	register struct iodesc *d;
16238451Smsmith	register void *pkt;
16338451Smsmith	register size_t len;
16438451Smsmith	time_t tleft;
16538451Smsmith{
16638451Smsmith	register ssize_t n;
16738451Smsmith	register struct ether_arp *ap;
16838451Smsmith	u_int16_t etype;	/* host order */
16938451Smsmith
17038451Smsmith#ifdef RARP_DEBUG
17138451Smsmith 	if (debug)
17238451Smsmith		printf("rarprecv: ");
17338451Smsmith#endif
17438451Smsmith
17538451Smsmith	n = readether(d, pkt, len, tleft, &etype);
17638451Smsmith	errno = 0;	/* XXX */
17738451Smsmith	if (n == -1 || n < sizeof(struct ether_arp)) {
17838451Smsmith#ifdef RARP_DEBUG
17938451Smsmith		if (debug)
18038451Smsmith			printf("bad len=%d\n", n);
18138451Smsmith#endif
18238451Smsmith		return (-1);
18338451Smsmith	}
18438451Smsmith
18538451Smsmith	if (etype != ETHERTYPE_REVARP) {
18638451Smsmith#ifdef RARP_DEBUG
18738451Smsmith		if (debug)
18838451Smsmith			printf("bad type=0x%x\n", etype);
18938451Smsmith#endif
19038451Smsmith		return (-1);
19138451Smsmith	}
19238451Smsmith
19338451Smsmith	ap = (struct ether_arp *)pkt;
19438451Smsmith	if (ap->arp_hrd != htons(ARPHRD_ETHER) ||
19538451Smsmith	    ap->arp_pro != htons(ETHERTYPE_IP) ||
19638451Smsmith	    ap->arp_hln != sizeof(ap->arp_sha) ||
19738451Smsmith	    ap->arp_pln != sizeof(ap->arp_spa) )
19838451Smsmith	{
19938451Smsmith#ifdef RARP_DEBUG
20038451Smsmith		if (debug)
20138451Smsmith			printf("bad hrd/pro/hln/pln\n");
20238451Smsmith#endif
20338451Smsmith		return (-1);
20438451Smsmith	}
20538451Smsmith
20638451Smsmith	if (ap->arp_op != htons(ARPOP_REVREPLY)) {
20738451Smsmith#ifdef RARP_DEBUG
20838451Smsmith		if (debug)
20938451Smsmith			printf("bad op=0x%x\n", ntohs(ap->arp_op));
21038451Smsmith#endif
21138451Smsmith		return (-1);
21238451Smsmith	}
21338451Smsmith
21438451Smsmith	/* Is the reply for our Ethernet address? */
21538451Smsmith	if (bcmp(ap->arp_tha, d->myea, 6)) {
21638451Smsmith#ifdef RARP_DEBUG
21738451Smsmith		if (debug)
21838451Smsmith			printf("unwanted address\n");
21938451Smsmith#endif
22038451Smsmith		return (-1);
22138451Smsmith	}
22238451Smsmith
22338451Smsmith	/* We have our answer. */
22438451Smsmith#ifdef RARP_DEBUG
22538451Smsmith 	if (debug)
22638451Smsmith		printf("got it\n");
22738451Smsmith#endif
22838451Smsmith	return (n);
22938451Smsmith}
230