summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/rarpd/rarpd.c161
1 files changed, 86 insertions, 75 deletions
diff --git a/usr.sbin/rarpd/rarpd.c b/usr.sbin/rarpd/rarpd.c
index a2e3e67453d..f870c467a76 100644
--- a/usr.sbin/rarpd/rarpd.c
+++ b/usr.sbin/rarpd/rarpd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rarpd.c,v 1.26 1999/08/09 16:55:57 niklas Exp $ */
+/* $OpenBSD: rarpd.c,v 1.27 1999/10/29 07:27:40 niklas Exp $ */
/* $NetBSD: rarpd.c,v 1.25 1998/04/23 02:48:33 mrg Exp $ */
/*
@@ -28,7 +28,7 @@ char copyright[] =
#endif /* not lint */
#ifndef lint
-static char rcsid[] = "$OpenBSD: rarpd.c,v 1.26 1999/08/09 16:55:57 niklas Exp $";
+static char rcsid[] = "$OpenBSD: rarpd.c,v 1.27 1999/10/29 07:27:40 niklas Exp $";
#endif
@@ -66,14 +66,19 @@ static char rcsid[] = "$OpenBSD: rarpd.c,v 1.26 1999/08/09 16:55:57 niklas Exp $
#define NONFATAL 0 /* non fatal error occurred */
/*
- * The structure for each interface.
+ * The structures for each interface.
*/
+struct if_addr {
+ in_addr_t ia_ipaddr; /* IP address of this interface */
+ in_addr_t ia_netmask; /* subnet or net mask */
+ struct if_addr *ia_next;
+};
+
struct if_info {
int ii_fd; /* BPF file descriptor */
char ii_name[IFNAMSIZ]; /* if name, e.g. "en0" */
- u_char ii_eaddr[6]; /* Ethernet address of this interface */
- u_int32_t ii_ipaddr; /* IP address of this interface */
- u_int32_t ii_netmask; /* subnet or net mask */
+ u_char ii_eaddr[6]; /* Ethernet address of this iface */
+ struct if_addr *ii_addrs; /* Networks this interface is on */
struct if_info *ii_next;
};
/*
@@ -86,12 +91,11 @@ int rarp_open __P((char *));
void init_one __P((char *));
void init_all __P((void));
void rarp_loop __P((void));
-void lookup_eaddr __P((char *, u_char *));
-void lookup_ipaddr __P((char *, u_int32_t *, u_int32_t *));
+void lookup_addrs __P((char *, struct if_info *));
void usage __P((void));
void rarp_process __P((struct if_info *, u_char *));
-void rarp_reply __P((struct if_info *, struct ether_header *, u_int32_t,
- struct hostent *));
+void rarp_reply __P((struct if_info *, struct if_addr *,
+ struct ether_header *, u_int32_t, struct hostent *));
void update_arptab __P((u_char *, u_int32_t));
void err __P((int, const char *,...));
void debug __P((const char *,...));
@@ -209,7 +213,7 @@ init_one(ifname)
int fd;
/* first check to see if this "if" was already opened? */
- for(p = iflist; p; p = p->ii_next)
+ for (p = iflist; p; p = p->ii_next)
if (!strncmp(p->ii_name, ifname, IFNAMSIZ))
return;
@@ -228,8 +232,8 @@ init_one(ifname)
p->ii_fd = fd;
strncpy(p->ii_name, ifname, IFNAMSIZ);
- lookup_eaddr(ifname, p->ii_eaddr);
- lookup_ipaddr(ifname, &p->ii_ipaddr, &p->ii_netmask);
+ p->ii_addrs = NULL;
+ lookup_addrs(ifname, p);
}
/*
* Initialize all "candidate" interfaces that are in the system
@@ -597,6 +601,7 @@ rarp_process(ii, pkt)
u_int32_t target_ipaddr;
char ename[MAXHOSTNAMELEN];
struct in_addr in;
+ struct if_addr *ia;
ep = (struct ether_header *) pkt;
ea = (struct ether_addr *) &ep->ether_shost;
@@ -616,36 +621,44 @@ rarp_process(ii, pkt)
err(FATAL, "cannot handle non IP addresses");
/* NOTREACHED */
}
- target_ipaddr = choose_ipaddr((u_int32_t **) hp->h_addr_list,
- ii->ii_ipaddr & ii->ii_netmask, ii->ii_netmask);
+ for (target_ipaddr = 0, ia = ii->ii_addrs; target_ipaddr == 0 && ia;
+ ia = ia->ia_next)
+ target_ipaddr = choose_ipaddr((u_int32_t **) hp->h_addr_list,
+ ia->ia_ipaddr & ia->ia_netmask, ia->ia_netmask);
if (target_ipaddr == 0) {
- in.s_addr = ii->ii_ipaddr & ii->ii_netmask;
- err(NONFATAL, "cannot find %s on net %s",
- ename, inet_ntoa(in));
+ for (ia = ii->ii_addrs; ia; ia = ia->ia_next) {
+ in.s_addr = ia->ia_ipaddr & ia->ia_netmask;
+ err(NONFATAL, "cannot find %s on net %s",
+ ename, inet_ntoa(in));
+ }
return;
}
#ifdef REQUIRE_TFTPBOOT
if (rarp_bootable(htonl(target_ipaddr)))
#endif
- rarp_reply(ii, ep, target_ipaddr, hp);
+ rarp_reply(ii, ia, ep, target_ipaddr, hp);
debug("reply sent");
}
+
/*
* Lookup the ethernet address of the interface attached to the BPF
* file descriptor 'fd'; return it in 'eaddr'.
*/
void
-lookup_eaddr(ifname, eaddr)
+lookup_addrs(ifname, p)
char *ifname;
- u_char *eaddr;
+ struct if_info *p;
{
+ u_char *eaddr = p->ii_eaddr;
+ struct if_addr *ia, **iap = &p->ii_addrs;
char *inbuf = NULL, *ninbuf;
struct ifconf ifc;
- struct ifreq *ifr;
+ struct ifreq *ifr, ifr_mask;
+ struct in_addr in;
struct sockaddr_dl *sdl;
int fd;
- int i, len, inlen = 8192;
+ int i, len, inlen = 8192, found = 0;
/* We cannot use SIOCGIFADDR on the BPF descriptor.
We must instead get all the interfaces with SIOCGIFCONF
@@ -664,14 +677,14 @@ lookup_eaddr(ifname, eaddr)
if (inbuf)
free(inbuf);
close(fd);
- err(FATAL, "lookup_eaddr: malloc: %s",
+ err(FATAL, "lookup_addrs: malloc: %s",
strerror(errno));
}
ifc.ifc_buf = inbuf = ninbuf;
if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0) {
(void) close(fd);
free(inbuf);
- err(FATAL, "lookup_eaddr: SIOCGIFCONF: %s",
+ err(FATAL, "lookup_addrs: SIOCGIFCONF: %s",
strerror(errno));
/* NOTREACHED */
}
@@ -686,59 +699,56 @@ lookup_eaddr(ifname, eaddr)
len = sizeof(ifr->ifr_name) +
(ifr->ifr_addr.sa_len > sizeof(struct sockaddr) ?
ifr->ifr_addr.sa_len : sizeof(struct sockaddr));
- sdl = (struct sockaddr_dl *)&ifr->ifr_addr;
- if (sdl->sdl_family != AF_LINK || sdl->sdl_type != IFT_ETHER ||
- sdl->sdl_alen != 6)
- continue;
if (!strncmp(ifr->ifr_name, ifname, sizeof(ifr->ifr_name))) {
- memcpy((caddr_t)eaddr, (caddr_t)LLADDR(sdl), 6);
- if (dflag)
- fprintf(stderr, "%s: %x:%x:%x:%x:%x:%x\n",
- ifr->ifr_name, eaddr[0], eaddr[1],
- eaddr[2], eaddr[3], eaddr[4], eaddr[5]);
- free(inbuf);
- return;
+ sdl = (struct sockaddr_dl *) & ifr->ifr_addr;
+ if (sdl->sdl_family == AF_LINK &&
+ sdl->sdl_type == IFT_ETHER && sdl->sdl_alen == 6) {
+ memcpy((caddr_t)eaddr, (caddr_t)LLADDR(sdl),
+ 6);
+ if (dflag)
+ fprintf(stderr,
+ "%s: %x:%x:%x:%x:%x:%x\n",
+ ifr->ifr_name,
+ eaddr[0], eaddr[1], eaddr[2],
+ eaddr[3], eaddr[4], eaddr[5]);
+ found = 1;
+ } else if (sdl->sdl_family == AF_INET) {
+ ia = malloc (sizeof (struct if_addr));
+ if (ia == NULL)
+ err(FATAL, "lookup_addrs: malloc: %s",
+ strerror(errno));
+ ia->ia_next = NULL;
+ ia->ia_ipaddr =
+ ((struct sockaddr_in *) sdl)->
+ sin_addr.s_addr;
+ memcpy(&ifr_mask, ifr, sizeof(*ifr));
+ if (ioctl(fd, SIOCGIFNETMASK,
+ (char *) &ifr_mask) < 0)
+ err(FATAL, "SIOCGIFNETMASK: %s",
+ strerror(errno));
+ ia->ia_netmask =
+ ((struct sockaddr_in *)
+ & ifr_mask.ifr_addr)->sin_addr.s_addr;
+ /* If SIOCGIFNETMASK didn't work,
+ figure out a mask from the IP
+ address class. */
+ if (ia->ia_netmask == 0)
+ ia->ia_netmask =
+ ipaddrtonetmask(ia->ia_ipaddr);
+ if (dflag) {
+ in.s_addr = ia->ia_ipaddr;
+ fprintf(stderr, "\t%s\n",
+ inet_ntoa(in));
+ }
+ *iap = ia;
+ iap = &ia->ia_next;
+ }
}
}
free(inbuf);
- err(FATAL, "lookup_eaddr: Never saw interface `%s'!", ifname);
-}
-/*
- * Lookup the IP address and network mask of the interface named 'ifname'.
- */
-void
-lookup_ipaddr(ifname, addrp, netmaskp)
- char *ifname;
- u_int32_t *addrp;
- u_int32_t *netmaskp;
-{
- int fd;
- struct ifreq ifr;
-
- /* Use datagram socket to get IP address. */
- if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
- err(FATAL, "socket: %s", strerror(errno));
- /* NOTREACHED */
- }
- (void) strncpy(ifr.ifr_name, ifname, sizeof ifr.ifr_name);
- if (ioctl(fd, SIOCGIFADDR, (char *) &ifr) < 0) {
- err(FATAL, "SIOCGIFADDR: %s", strerror(errno));
- /* NOTREACHED */
- }
- *addrp = ((struct sockaddr_in *) & ifr.ifr_addr)->sin_addr.s_addr;
- if (ioctl(fd, SIOCGIFNETMASK, (char *) &ifr) < 0) {
- perror("SIOCGIFNETMASK");
- unlink(_PATH_RARPDPID);
- exit(1);
- }
- *netmaskp = ((struct sockaddr_in *) & ifr.ifr_addr)->sin_addr.s_addr;
- /* If SIOCGIFNETMASK didn't work, figure out a mask from the IP
- * address class. */
- if (*netmaskp == 0)
- *netmaskp = ipaddrtonetmask(*addrp);
-
- (void) close(fd);
+ if (!found)
+ err(FATAL, "lookup_addrs: Never saw interface `%s'!", ifname);
}
int arptab_set __P((u_char *eaddr, u_int32_t host));
@@ -821,8 +831,9 @@ update_arptab(ep, ipaddr)
* ARP request.
*/
void
-rarp_reply(ii, ep, ipaddr, hp)
+rarp_reply(ii, ia, ep, ipaddr, hp)
struct if_info *ii;
+ struct if_addr *ia;
struct ether_header *ep;
u_int32_t ipaddr;
struct hostent *hp;
@@ -845,7 +856,7 @@ rarp_reply(ii, ep, ipaddr, hp)
memcpy((char *) ap->arp_tpa, (char *) &ipaddr, 4);
/* Target hardware is unchanged. */
- memcpy((char *) ap->arp_spa, (char *) &ii->ii_ipaddr, 4);
+ memcpy((char *) ap->arp_spa, (char *) &ia->ia_ipaddr, 4);
if (lflag) {
struct ether_addr ea;