Fix up new rarpd.

This includes the following changes:

- Support for poking ARP entries into the local table is now built
  in, so the arptab.c module I hacked together is no longer needed.

- rarp_process() and rarp_reply() now accept a len argument which is
  passed down from rarp_loop() which tells rarp_reply() exactly how
  long the original RARP frame was. (Usually, it's 60 bytes, which is
  the minimum.) Previously, the length was calculated using the sum
  of sizeof(struct ether_header) + sizeof(struct ether_arp) (plus the
  ethernet frame header, I think). The result was a total packet
  length of 42 bytes. Now, rarp_reply() sends out packets that are
  the same size as those it recieves (60 bytes). This agrees with the
  behavior of rarpd on SunOS (as observed with tcpdump). The unused
  extra bytes are zeroed.
This commit is contained in:
Bill Paul 1996-11-18 22:07:41 +00:00
parent 557201898b
commit 867de4336b
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=19859
4 changed files with 545 additions and 734 deletions

View File

@ -1,9 +1,10 @@
# from: @(#)Makefile 5.8 (Berkeley) 7/28/90
# $Id: Makefile,v 1.2 1995/03/03 22:20:12 wpaul Exp $
# $Id: Makefile,v 1.3 1995/04/02 01:35:53 wpaul Exp $
PROG= rarpd
MAN8= rarpd.8
SRCS= rarpd.c arptab.c
SRCS= rarpd.c
CFLAGS+= -DTFTP_DIR=\"/tftpboot\"
.include <bsd.prog.mk>

View File

@ -1,219 +0,0 @@
/*
* Copyright (c) 1984, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Sun Microsystems, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef lint
static char copyright[] =
"@(#) Copyright (c) 1984, 1993\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#ifndef lint
static char sccsid[] = "@(#)arp.c 8.2 (Berkeley) 1/2/94";
#endif /* not lint */
/*
* set arp table entries
*/
#include <sys/param.h>
#include <sys/file.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
#include <net/if.h>
#include <net/if_dl.h>
#include <net/if_types.h>
#include <net/route.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>
#include <nlist.h>
#include <stdio.h>
#include <paths.h>
#include <syslog.h>
extern int errno;
static int pid;
static int s = -1;
getsocket() {
if (s < 0) {
s = socket(PF_ROUTE, SOCK_RAW, 0);
if (s < 0) {
perror("arp: socket");
exit(1);
}
}
}
struct sockaddr_in so_mask = {8, 0, 0, { 0xffffffff}};
struct sockaddr_inarp blank_sin = {sizeof(blank_sin), AF_INET }, sin_m;
struct sockaddr_dl blank_sdl = {sizeof(blank_sdl), AF_LINK }, sdl_m;
int expire_time, flags, export_only, doing_proxy;
struct {
struct rt_msghdr m_rtm;
char m_space[512];
} m_rtmsg;
/*
* Set an individual arp entry
*/
arptab_set(eaddr, host)
u_char *eaddr;
u_long host;
{
register struct sockaddr_inarp *sin = &sin_m;
register struct sockaddr_dl *sdl;
register struct rt_msghdr *rtm = &(m_rtmsg.m_rtm);
struct timeval time;
getsocket();
pid = getpid();
sdl_m = blank_sdl;
sin_m = blank_sin;
sin->sin_addr.s_addr = host;
bcopy((char *)eaddr, (u_char *)LLADDR(&sdl_m), 6);
sdl_m.sdl_alen = 6;
doing_proxy = flags = export_only = expire_time = 0;
gettimeofday(&time, 0);
expire_time = time.tv_sec + 20 * 60;
tryagain:
if (rtmsg(RTM_GET) < 0) {
syslog(LOG_ERR,"%s: %m", inet_ntoa(sin->sin_addr));
return (1);
}
sin = (struct sockaddr_inarp *)(rtm + 1);
sdl = (struct sockaddr_dl *)(sin->sin_len + (char *)sin);
if (sin->sin_addr.s_addr == sin_m.sin_addr.s_addr) {
if (sdl->sdl_family == AF_LINK &&
(rtm->rtm_flags & RTF_LLINFO) &&
!(rtm->rtm_flags & RTF_GATEWAY)) switch (sdl->sdl_type) {
case IFT_ETHER: case IFT_FDDI: case IFT_ISO88023:
case IFT_ISO88024: case IFT_ISO88025:
goto overwrite;
}
if (doing_proxy == 0) {
syslog(LOG_ERR, "arptab_set: can only proxy for %s\n", inet_ntoa(sin->sin_addr));
return (1);
}
if (sin_m.sin_other & SIN_PROXY) {
syslog(LOG_ERR,"arptab_set: proxy entry exists for non 802 device\n");
return(1);
}
sin_m.sin_other = SIN_PROXY;
export_only = 1;
goto tryagain;
}
overwrite:
if (sdl->sdl_family != AF_LINK) {
syslog(LOG_ERR,"arptab_set: cannot intuit interface index and type for %s\n", inet_ntoa(sin->sin_addr));
return (1);
}
sdl_m.sdl_type = sdl->sdl_type;
sdl_m.sdl_index = sdl->sdl_index;
return (rtmsg(RTM_ADD));
}
rtmsg(cmd)
{
static int seq;
int rlen;
register struct rt_msghdr *rtm = &m_rtmsg.m_rtm;
register char *cp = m_rtmsg.m_space;
register int l;
errno = 0;
if (cmd == RTM_DELETE)
goto doit;
bzero((char *)&m_rtmsg, sizeof(m_rtmsg));
rtm->rtm_flags = flags;
rtm->rtm_version = RTM_VERSION;
switch (cmd) {
default:
syslog(LOG_ERR, "arptap_set: internal wrong cmd\n");
exit(1);
case RTM_ADD:
rtm->rtm_addrs |= RTA_GATEWAY;
rtm->rtm_rmx.rmx_expire = expire_time;
rtm->rtm_inits = RTV_EXPIRE;
rtm->rtm_flags |= (RTF_HOST | RTF_STATIC);
sin_m.sin_other = 0;
if (doing_proxy) {
if (export_only)
sin_m.sin_other = SIN_PROXY;
else {
rtm->rtm_addrs |= RTA_NETMASK;
rtm->rtm_flags &= ~RTF_HOST;
}
}
/* FALLTHROUGH */
case RTM_GET:
rtm->rtm_addrs |= RTA_DST;
}
#define NEXTADDR(w, s) \
if (rtm->rtm_addrs & (w)) { \
bcopy((char *)&s, cp, sizeof(s)); cp += sizeof(s);}
NEXTADDR(RTA_DST, sin_m);
NEXTADDR(RTA_GATEWAY, sdl_m);
NEXTADDR(RTA_NETMASK, so_mask);
rtm->rtm_msglen = cp - (char *)&m_rtmsg;
doit:
l = rtm->rtm_msglen;
rtm->rtm_seq = ++seq;
rtm->rtm_type = cmd;
if ((rlen = write(s, (char *)&m_rtmsg, l)) < 0) {
if (errno != ESRCH && errno != EEXIST) {
syslog(LOG_ERR, "writing to routing socket: %m");
return (-1);
}
}
do {
l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg));
} while (l > 0 && (rtm->rtm_seq != seq || rtm->rtm_pid != pid));
if (l < 0)
syslog(LOG_ERR, "arptab_set: read from routing socket: %m");
return (0);
}

View File

@ -1,224 +0,0 @@
/*
* Copyright (c) 1990, 1993 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the University of California,
* Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
* the University nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior
* written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifndef lint
static char rcsid[] =
"@(#) $Header: etherent.c,v 1.4 96/06/14 20:34:25 leres Exp $ (LBL)";
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#ifndef ETHERS_FILE
#define ETHERS_FILE "/etc/ethers"
#endif
struct etherent {
u_char addr[6];
char name[122];
};
static FILE *ether_fp = NULL;
/* Hex digit to integer. */
static inline int
xdtoi(c)
int c;
{
if (isdigit(c))
return c - '0';
else if (islower(c))
return c - 'a' + 10;
else
return c - 'A' + 10;
}
static inline int
skip_space(f)
FILE *f;
{
int c;
do {
c = getc(f);
} while (isspace(c) && c != '\n');
return c;
}
static inline int
skip_line(f)
FILE *f;
{
int c;
do
c = getc(f);
while (c != '\n' && c != EOF);
return c;
}
static struct etherent *
next_etherent(fp)
FILE *fp;
{
register int c, d, i;
char *bp;
static struct etherent e;
static int nline = 1;
top:
while (nline) {
/* Find addr */
c = skip_space(fp);
if (c == '\n')
continue;
/* If this is a comment, or first thing on line
cannot be etehrnet address, skip the line. */
else if (!isxdigit(c))
c = skip_line(fp);
else {
/* must be the start of an address */
for (i = 0; i < 6; i += 1) {
d = xdtoi(c);
c = getc(fp);
if (c != ':') {
d <<= 4;
d |= xdtoi(c);
c = getc(fp);
}
e.addr[i] = d;
if (c != ':')
break;
c = getc(fp);
}
nline = 0;
}
if (c == EOF)
return NULL;
}
/* If we started a new line, 'c' holds the char past the ether addr,
which we assume is white space. If we are continuing a line,
'c' is garbage. In either case, we can throw it away. */
c = skip_space(fp);
if (c == '\n') {
nline = 1;
goto top;
}
else if (c == '#') {
(void)skip_line(fp);
nline = 1;
goto top;
}
else if (c == EOF)
return NULL;
/* Must be a name. */
bp = e.name;
/* Use 'd' to prevent buffer overflow. */
d = sizeof(e.name) - 1;
do {
*bp++ = c;
c = getc(fp);
} while (!isspace(c) && c != EOF && --d > 0);
*bp = '\0';
if (c == '\n')
nline = 1;
return &e;
}
/* Open/rewind the ethers files; returns 1 if file was reopened */
int
ether_rewind()
{
struct stat st;
static long mtime = 0, ctime = 0;
if (ether_fp != NULL) {
if (fstat(fileno(ether_fp), &st) < 0 ||
mtime != st.st_mtime || ctime != st.st_ctime ||
fseek(ether_fp, 0L, SEEK_SET) < 0) {
fclose(ether_fp);
ether_fp = NULL;
}
}
if (ether_fp == NULL) {
ether_fp = fopen(ETHERS_FILE, "r");
if (ether_fp == NULL)
return (-1);
if (fstat(fileno(ether_fp), &st) < 0) {
fclose(ether_fp);
ether_fp = NULL;
return (-1);
}
mtime = st.st_mtime;
ctime = st.st_ctime;
return (1);
}
return (0);
}
/* Map an ethernet address to a name; returns 0 on success, else 1. */
int
ether_ntohost(name, ea)
register char *name;
register u_char *ea;
{
register struct etherent *ep;
if (ether_rewind() < 0)
return (1);
while ((ep = next_etherent(ether_fp)) != NULL)
if (bcmp(ep->addr, ea, 6) == 0) {
strcpy(name, ep->name);
return (0);
}
return (1);
}
/* Map an ethernet name to an address; returns 0 on success, else 1. */
int
ether_hostton(name, ea)
register char *name;
register u_char *ea;
{
register struct etherent *ep;
if (ether_rewind() < 0)
return (1);
while ((ep = next_etherent(ether_fp)) != NULL)
if (strcmp(ep->name, name) == 0) {
bcopy(ep->addr, ea, 6);
return (0);
}
return (1);
}

File diff suppressed because it is too large Load Diff