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 * 4. Neither the name of the University nor the names of its contributors
2038451Smsmith *    may be used to endorse or promote products derived from this software
2138451Smsmith *    without specific prior written permission.
2238451Smsmith *
2338451Smsmith * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2438451Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2538451Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2638451Smsmith * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2738451Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2838451Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2938451Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3038451Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3138451Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3238451Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3338451Smsmith * SUCH DAMAGE.
3438451Smsmith *
3538451Smsmith * @(#) Header: arp.c,v 1.5 93/07/15 05:52:26 leres Exp  (LBL)
3638451Smsmith */
3784221Sdillon
3884221Sdillon#include <sys/cdefs.h>
3984221Sdillon__FBSDID("$FreeBSD$");
4084221Sdillon
4138451Smsmith#include <sys/param.h>
4238451Smsmith#include <sys/socket.h>
4338451Smsmith#include <net/if.h>
4438451Smsmith#include <netinet/in.h>
4538451Smsmith#include <netinet/if_ether.h>
4638451Smsmith
4738451Smsmith#include <netinet/in_systm.h>
4838451Smsmith
4938451Smsmith#include <string.h>
5038451Smsmith
5138451Smsmith#include "stand.h"
5238451Smsmith#include "net.h"
5338451Smsmith#include "netif.h"
5438451Smsmith
5538451Smsmith
5638451Smsmithstatic ssize_t rarpsend(struct iodesc *, void *, size_t);
5738451Smsmithstatic ssize_t rarprecv(struct iodesc *, void *, size_t, time_t);
5838451Smsmith
5938451Smsmith/*
6038451Smsmith * Ethernet (Reverse) Address Resolution Protocol (see RFC 903, and 826).
6138451Smsmith */
6238451Smsmithint
6338451Smsmithrarp_getipaddress(sock)
6438451Smsmith	int sock;
6538451Smsmith{
6638451Smsmith	struct iodesc *d;
6792913Sobrien	struct ether_arp *ap;
6838451Smsmith	struct {
6938451Smsmith		u_char header[ETHER_SIZE];
7038451Smsmith		struct {
7138451Smsmith			struct ether_arp arp;
7238451Smsmith			u_char pad[18]; 	/* 60 - sizeof(arp) */
7338451Smsmith		} data;
7438451Smsmith	} wbuf;
7538451Smsmith	struct {
7638451Smsmith		u_char header[ETHER_SIZE];
7738451Smsmith		struct {
7838451Smsmith			struct ether_arp arp;
7938451Smsmith			u_char pad[24]; 	/* extra space */
8038451Smsmith		} data;
8138451Smsmith	} rbuf;
8238451Smsmith
8338451Smsmith#ifdef RARP_DEBUG
8438451Smsmith 	if (debug)
8538451Smsmith		printf("rarp: socket=%d\n", sock);
8638451Smsmith#endif
8738451Smsmith	if (!(d = socktodesc(sock))) {
8838451Smsmith		printf("rarp: bad socket. %d\n", sock);
8938451Smsmith		return (-1);
9038451Smsmith	}
9138451Smsmith#ifdef RARP_DEBUG
9238451Smsmith 	if (debug)
9338451Smsmith		printf("rarp: d=%x\n", (u_int)d);
9438451Smsmith#endif
9538451Smsmith
9638451Smsmith	bzero((char*)&wbuf.data, sizeof(wbuf.data));
9738451Smsmith	ap = &wbuf.data.arp;
9838451Smsmith	ap->arp_hrd = htons(ARPHRD_ETHER);
9938451Smsmith	ap->arp_pro = htons(ETHERTYPE_IP);
10038451Smsmith	ap->arp_hln = sizeof(ap->arp_sha); /* hardware address length */
10138451Smsmith	ap->arp_pln = sizeof(ap->arp_spa); /* protocol address length */
10238451Smsmith	ap->arp_op = htons(ARPOP_REVREQUEST);
10338451Smsmith	bcopy(d->myea, ap->arp_sha, 6);
10438451Smsmith	bcopy(d->myea, ap->arp_tha, 6);
10538451Smsmith
10638451Smsmith	if (sendrecv(d,
10738451Smsmith	    rarpsend, &wbuf.data, sizeof(wbuf.data),
10838451Smsmith	    rarprecv, &rbuf.data, sizeof(rbuf.data)) < 0)
10938451Smsmith	{
11038451Smsmith		printf("No response for RARP request\n");
11138451Smsmith		return (-1);
11238451Smsmith	}
11338451Smsmith
11438451Smsmith	ap = &rbuf.data.arp;
11538451Smsmith	bcopy(ap->arp_tpa, (char *)&myip, sizeof(myip));
11638451Smsmith#if 0
11738451Smsmith	/* XXX - Can NOT assume this is our root server! */
11838451Smsmith	bcopy(ap->arp_spa, (char *)&rootip, sizeof(rootip));
11938451Smsmith#endif
12038451Smsmith
12138451Smsmith	/* Compute our "natural" netmask. */
12238451Smsmith	if (IN_CLASSA(myip.s_addr))
12338451Smsmith		netmask = IN_CLASSA_NET;
12438451Smsmith	else if (IN_CLASSB(myip.s_addr))
12538451Smsmith		netmask = IN_CLASSB_NET;
12638451Smsmith	else
12738451Smsmith		netmask = IN_CLASSC_NET;
12838451Smsmith
12938451Smsmith	d->myip = myip;
13038451Smsmith	return (0);
13138451Smsmith}
13238451Smsmith
13338451Smsmith/*
13438451Smsmith * Broadcast a RARP request (i.e. who knows who I am)
13538451Smsmith */
13638451Smsmithstatic ssize_t
13738451Smsmithrarpsend(d, pkt, len)
13892913Sobrien	struct iodesc *d;
13992913Sobrien	void *pkt;
14092913Sobrien	size_t len;
14138451Smsmith{
14238451Smsmith
14338451Smsmith#ifdef RARP_DEBUG
14438451Smsmith 	if (debug)
14538451Smsmith		printf("rarpsend: called\n");
14638451Smsmith#endif
14738451Smsmith
14838451Smsmith	return (sendether(d, pkt, len, bcea, ETHERTYPE_REVARP));
14938451Smsmith}
15038451Smsmith
15138451Smsmith/*
15238451Smsmith * Returns 0 if this is the packet we're waiting for
15338451Smsmith * else -1 (and errno == 0)
15438451Smsmith */
15538451Smsmithstatic ssize_t
15638451Smsmithrarprecv(d, pkt, len, tleft)
15792913Sobrien	struct iodesc *d;
15892913Sobrien	void *pkt;
15992913Sobrien	size_t len;
16038451Smsmith	time_t tleft;
16138451Smsmith{
16292913Sobrien	ssize_t n;
16392913Sobrien	struct ether_arp *ap;
16438451Smsmith	u_int16_t etype;	/* host order */
16538451Smsmith
16638451Smsmith#ifdef RARP_DEBUG
16738451Smsmith 	if (debug)
16838451Smsmith		printf("rarprecv: ");
16938451Smsmith#endif
17038451Smsmith
17138451Smsmith	n = readether(d, pkt, len, tleft, &etype);
17238451Smsmith	errno = 0;	/* XXX */
17338451Smsmith	if (n == -1 || n < sizeof(struct ether_arp)) {
17438451Smsmith#ifdef RARP_DEBUG
17538451Smsmith		if (debug)
17638451Smsmith			printf("bad len=%d\n", n);
17738451Smsmith#endif
17838451Smsmith		return (-1);
17938451Smsmith	}
18038451Smsmith
18138451Smsmith	if (etype != ETHERTYPE_REVARP) {
18238451Smsmith#ifdef RARP_DEBUG
18338451Smsmith		if (debug)
18438451Smsmith			printf("bad type=0x%x\n", etype);
18538451Smsmith#endif
18638451Smsmith		return (-1);
18738451Smsmith	}
18838451Smsmith
18938451Smsmith	ap = (struct ether_arp *)pkt;
19038451Smsmith	if (ap->arp_hrd != htons(ARPHRD_ETHER) ||
19138451Smsmith	    ap->arp_pro != htons(ETHERTYPE_IP) ||
19238451Smsmith	    ap->arp_hln != sizeof(ap->arp_sha) ||
19338451Smsmith	    ap->arp_pln != sizeof(ap->arp_spa) )
19438451Smsmith	{
19538451Smsmith#ifdef RARP_DEBUG
19638451Smsmith		if (debug)
19738451Smsmith			printf("bad hrd/pro/hln/pln\n");
19838451Smsmith#endif
19938451Smsmith		return (-1);
20038451Smsmith	}
20138451Smsmith
20238451Smsmith	if (ap->arp_op != htons(ARPOP_REVREPLY)) {
20338451Smsmith#ifdef RARP_DEBUG
20438451Smsmith		if (debug)
20538451Smsmith			printf("bad op=0x%x\n", ntohs(ap->arp_op));
20638451Smsmith#endif
20738451Smsmith		return (-1);
20838451Smsmith	}
20938451Smsmith
21038451Smsmith	/* Is the reply for our Ethernet address? */
21138451Smsmith	if (bcmp(ap->arp_tha, d->myea, 6)) {
21238451Smsmith#ifdef RARP_DEBUG
21338451Smsmith		if (debug)
21438451Smsmith			printf("unwanted address\n");
21538451Smsmith#endif
21638451Smsmith		return (-1);
21738451Smsmith	}
21838451Smsmith
21938451Smsmith	/* We have our answer. */
22038451Smsmith#ifdef RARP_DEBUG
22138451Smsmith 	if (debug)
22238451Smsmith		printf("got it\n");
22338451Smsmith#endif
22438451Smsmith	return (n);
22538451Smsmith}
226