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: stable/11/stand/libsa/rarp.c 330898 2018-03-14 03:30:34Z kevans $");
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);
57330898Skevansstatic ssize_t rarprecv(struct iodesc *, void **, void **, time_t, void *);
5838451Smsmith
5938451Smsmith/*
6038451Smsmith * Ethernet (Reverse) Address Resolution Protocol (see RFC 903, and 826).
6138451Smsmith */
6238451Smsmithint
63329100Skevansrarp_getipaddress(int sock)
6438451Smsmith{
6538451Smsmith	struct iodesc *d;
6692913Sobrien	struct ether_arp *ap;
67329100Skevans	void *pkt;
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
7638451Smsmith#ifdef RARP_DEBUG
7738451Smsmith 	if (debug)
7838451Smsmith		printf("rarp: socket=%d\n", sock);
7938451Smsmith#endif
8038451Smsmith	if (!(d = socktodesc(sock))) {
8138451Smsmith		printf("rarp: bad socket. %d\n", sock);
8238451Smsmith		return (-1);
8338451Smsmith	}
8438451Smsmith#ifdef RARP_DEBUG
8538451Smsmith 	if (debug)
8638451Smsmith		printf("rarp: d=%x\n", (u_int)d);
8738451Smsmith#endif
8838451Smsmith
8938451Smsmith	bzero((char*)&wbuf.data, sizeof(wbuf.data));
9038451Smsmith	ap = &wbuf.data.arp;
9138451Smsmith	ap->arp_hrd = htons(ARPHRD_ETHER);
9238451Smsmith	ap->arp_pro = htons(ETHERTYPE_IP);
9338451Smsmith	ap->arp_hln = sizeof(ap->arp_sha); /* hardware address length */
9438451Smsmith	ap->arp_pln = sizeof(ap->arp_spa); /* protocol address length */
9538451Smsmith	ap->arp_op = htons(ARPOP_REVREQUEST);
9638451Smsmith	bcopy(d->myea, ap->arp_sha, 6);
9738451Smsmith	bcopy(d->myea, ap->arp_tha, 6);
98329100Skevans	pkt = NULL;
9938451Smsmith
10038451Smsmith	if (sendrecv(d,
10138451Smsmith	    rarpsend, &wbuf.data, sizeof(wbuf.data),
102330898Skevans	    rarprecv, &pkt, (void *)&ap, NULL) < 0) {
10338451Smsmith		printf("No response for RARP request\n");
10438451Smsmith		return (-1);
10538451Smsmith	}
10638451Smsmith
10738451Smsmith	bcopy(ap->arp_tpa, (char *)&myip, sizeof(myip));
10838451Smsmith#if 0
10938451Smsmith	/* XXX - Can NOT assume this is our root server! */
11038451Smsmith	bcopy(ap->arp_spa, (char *)&rootip, sizeof(rootip));
11138451Smsmith#endif
112329100Skevans	free(pkt);
11338451Smsmith
11438451Smsmith	/* Compute our "natural" netmask. */
11538451Smsmith	if (IN_CLASSA(myip.s_addr))
11638451Smsmith		netmask = IN_CLASSA_NET;
11738451Smsmith	else if (IN_CLASSB(myip.s_addr))
11838451Smsmith		netmask = IN_CLASSB_NET;
11938451Smsmith	else
12038451Smsmith		netmask = IN_CLASSC_NET;
12138451Smsmith
12238451Smsmith	d->myip = myip;
12338451Smsmith	return (0);
12438451Smsmith}
12538451Smsmith
12638451Smsmith/*
12738451Smsmith * Broadcast a RARP request (i.e. who knows who I am)
12838451Smsmith */
12938451Smsmithstatic ssize_t
130329100Skevansrarpsend(struct iodesc *d, void *pkt, size_t len)
13138451Smsmith{
13238451Smsmith
13338451Smsmith#ifdef RARP_DEBUG
13438451Smsmith 	if (debug)
13538451Smsmith		printf("rarpsend: called\n");
13638451Smsmith#endif
13738451Smsmith
13838451Smsmith	return (sendether(d, pkt, len, bcea, ETHERTYPE_REVARP));
13938451Smsmith}
14038451Smsmith
14138451Smsmith/*
14238451Smsmith * Returns 0 if this is the packet we're waiting for
14338451Smsmith * else -1 (and errno == 0)
14438451Smsmith */
14538451Smsmithstatic ssize_t
146330898Skevansrarprecv(struct iodesc *d, void **pkt, void **payload, time_t tleft,
147330898Skevans    void *extra)
14838451Smsmith{
14992913Sobrien	ssize_t n;
15092913Sobrien	struct ether_arp *ap;
151329100Skevans	void *ptr = NULL;
152329100Skevans	uint16_t etype;		/* host order */
15338451Smsmith
15438451Smsmith#ifdef RARP_DEBUG
15538451Smsmith 	if (debug)
15638451Smsmith		printf("rarprecv: ");
15738451Smsmith#endif
15838451Smsmith
159329100Skevans	n = readether(d, &ptr, (void **)&ap, tleft, &etype);
16038451Smsmith	errno = 0;	/* XXX */
16138451Smsmith	if (n == -1 || n < sizeof(struct ether_arp)) {
16238451Smsmith#ifdef RARP_DEBUG
16338451Smsmith		if (debug)
16438451Smsmith			printf("bad len=%d\n", n);
16538451Smsmith#endif
166329100Skevans		free(ptr);
16738451Smsmith		return (-1);
16838451Smsmith	}
16938451Smsmith
17038451Smsmith	if (etype != ETHERTYPE_REVARP) {
17138451Smsmith#ifdef RARP_DEBUG
17238451Smsmith		if (debug)
17338451Smsmith			printf("bad type=0x%x\n", etype);
17438451Smsmith#endif
175329100Skevans		free(ptr);
17638451Smsmith		return (-1);
17738451Smsmith	}
17838451Smsmith
17938451Smsmith	if (ap->arp_hrd != htons(ARPHRD_ETHER) ||
18038451Smsmith	    ap->arp_pro != htons(ETHERTYPE_IP) ||
18138451Smsmith	    ap->arp_hln != sizeof(ap->arp_sha) ||
18238451Smsmith	    ap->arp_pln != sizeof(ap->arp_spa) )
18338451Smsmith	{
18438451Smsmith#ifdef RARP_DEBUG
18538451Smsmith		if (debug)
18638451Smsmith			printf("bad hrd/pro/hln/pln\n");
18738451Smsmith#endif
188329100Skevans		free(ptr);
18938451Smsmith		return (-1);
19038451Smsmith	}
19138451Smsmith
19238451Smsmith	if (ap->arp_op != htons(ARPOP_REVREPLY)) {
19338451Smsmith#ifdef RARP_DEBUG
19438451Smsmith		if (debug)
19538451Smsmith			printf("bad op=0x%x\n", ntohs(ap->arp_op));
19638451Smsmith#endif
197329100Skevans		free(ptr);
19838451Smsmith		return (-1);
19938451Smsmith	}
20038451Smsmith
20138451Smsmith	/* Is the reply for our Ethernet address? */
20238451Smsmith	if (bcmp(ap->arp_tha, d->myea, 6)) {
20338451Smsmith#ifdef RARP_DEBUG
20438451Smsmith		if (debug)
20538451Smsmith			printf("unwanted address\n");
20638451Smsmith#endif
207329100Skevans		free(ptr);
20838451Smsmith		return (-1);
20938451Smsmith	}
21038451Smsmith
21138451Smsmith	/* We have our answer. */
21238451Smsmith#ifdef RARP_DEBUG
21338451Smsmith 	if (debug)
21438451Smsmith		printf("got it\n");
21538451Smsmith#endif
216329100Skevans	*pkt = ptr;
217329100Skevans	*payload = ap;
21838451Smsmith	return (n);
21938451Smsmith}
220