home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-04-13 | 45.7 KB | 1,922 lines |
- Newsgroups: comp.sources.unix
- From: davy@ecn.purdue.edu (David A. Curry)
- Subject: v26i159: parpd1.2 - proxy arp daemon for sunos/NIT, V1.2, Part01/01
- Sender: unix-sources-moderator@vix.com
- Approved: paul@vix.com
-
- Submitted-By: davy@ecn.purdue.edu (David A. Curry)
- Posting-Number: Volume 26, Issue 159
- Archive-Name: parpd1.2/part01
-
- This is PARPD 1.2, a Proxy-ARP daemon for Sun workstations running SunOS 4.1.x.
-
- PARPD monitors all ethernet interfaces for ARP request packets requesting
- the address of a host on a different local subnet. These are sent by hosts
- which either do not understand subnets, or are misconfigured.
-
- PARPD responds to these packets with the address of the gateway host (the
- host PARPD is running on), allowing these hosts to send packets to the
- gateway (believing it's the host they want), and the gateway then forwards
- the packets as usual. PARPD logs everything it does via syslog(3) so that
- misconfigured hosts can be detected and corrected.
-
- PARPD does not require any configuration files; it reads the kernel routing
- tables and interface configuration data to determine what it should do.
-
- PARPD has been running on Sun-3 and Sun-4 (SPARC) workstations under SunOS
- 4.1.1 here for a long time now. At the time it was installed, we turned
- off all our in-kernel proxy arping code. To date, we have experienced no
- problems, and have even had fun finding misconfigured hosts that we never
- knew about before.
-
- PARPD requires SunOS 4.1.x because it makes use of the Network Interface Tap.
- It could probably be made to compile on SunOS 4.0.x with little difficulty,
- but the 4.0 NIT was pretty buggy, so no guarantees on how well it'll work.
- If you want to use PARPD on other operating systems, you'll have to write
- your own code to intercept ARP request packets, and put ARP reply packets
- back on the wire.
-
- Dave Curry
- Purdue University
- Engineering Computer Network
- 1285 Electrical Engineering Building
- West Lafayette, IN 47907-1285
- davy@ecn.purdue.edu
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 1 (of 1)."
- # Contents: MANIFEST Makefile arp.c if.c nit.c parpd.c parpd.h
- # parpd.man route.c util.c
- # Wrapped by vixie@gw.home.vix.com on Wed Apr 14 10:47:39 1993
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'MANIFEST' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'MANIFEST'\"
- else
- echo shar: Extracting \"'MANIFEST'\" \(424 characters\)
- sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
- X File Name Archive # Description
- X-----------------------------------------------------------
- X MANIFEST 1 This shipping list
- X Makefile 1
- X arp.c 1
- X if.c 1
- X nit.c 1
- X parpd.c 1
- X parpd.h 1
- X parpd.man 1
- X route.c 1
- X util.c 1
- END_OF_FILE
- if test 424 -ne `wc -c <'MANIFEST'`; then
- echo shar: \"'MANIFEST'\" unpacked with wrong size!
- fi
- # end of 'MANIFEST'
- fi
- if test -f 'Makefile' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Makefile'\"
- else
- echo shar: Extracting \"'Makefile'\" \(891 characters\)
- sed "s/^X//" >'Makefile' <<'END_OF_FILE'
- X#
- X# $Header: /usr/src/ecn/parpd/RCS/Makefile,v 1.1 92/05/08 08:43:07 davy Exp $
- X#
- X# Makefile for proxy arp daemon.
- X#
- X# David A. Curry
- X# Purdue University
- X# Engineering Computer Network
- X# 1285 Electrical Engineering Building
- X# West Lafayette, IN 47907
- X# davy@ecn.purdue.edu
- X#
- X# April, 1992
- X#
- X# $Log: Makefile,v $
- X# Revision 1.1 92/05/08 08:43:07 davy
- X# Initial revision
- X#
- X#
- X
- CFLAGS= -O
- BINDIR= /usr/ecn/etc
- MANDIR= /usr/man/man8
- MANSUFFIX= 8
- X
- LIBS= -lkvm
- X
- OBJS= arp.o if.o nit.o parpd.o route.o util.o
- X
- in.parpd: $(OBJS)
- X $(CC) -o in.parpd $(OBJS) $(LIBS)
- X
- install: in.parpd
- X install -c -s -o root -g bin -m 755 in.parpd $(BINDIR)
- X
- install.man:
- X install -c -m 444 parpd.man $(MANDIR)/in.parpd.$(MANSUFFIX)
- X
- clean:
- X rm -f \#* a.out core in.parpd *.o
- X
- arp.o: arp.c parpd.h
- if.o: if.c parpd.h
- nit.o: nit.c parpd.h
- parpd.o: parpd.c parpd.h
- route.o: route.c parpd.h
- util.o: util.c parpd.h
- END_OF_FILE
- if test 891 -ne `wc -c <'Makefile'`; then
- echo shar: \"'Makefile'\" unpacked with wrong size!
- fi
- # end of 'Makefile'
- fi
- if test -f 'arp.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'arp.c'\"
- else
- echo shar: Extracting \"'arp.c'\" \(6982 characters\)
- sed "s/^X//" >'arp.c' <<'END_OF_FILE'
- X#ifndef lint
- static char *RCSid = "$Header: /usr/src/ecn/parpd/RCS/arp.c,v 1.2 92/07/17 12:23:52 davy Exp $";
- X#endif
- X
- X/*
- X * arp.c - routines for handling arp packets
- X *
- X * David A. Curry
- X * Purdue University
- X * Engineering Computer Network
- X * 1285 Electrical Engineering Building
- X * West Lafayette, IN 47907
- X * davy@ecn.purdue.edu
- X *
- X * April, 1992
- X *
- X * $Log: arp.c,v $
- X * Revision 1.2 92/07/17 12:23:52 davy
- X * ether_ntoa takes a pointer to a struct, not a struct
- X *
- X * Revision 1.1 92/05/08 08:43:44 davy
- X * Initial revision
- X *
- X */
- X#include <sys/param.h>
- X#include <sys/socket.h>
- X#include <netinet/in.h>
- X#include <arpa/inet.h>
- X#include <net/if.h>
- X#include <netinet/if_ether.h>
- X#include <sys/stropts.h>
- X#include <string.h>
- X#include <syslog.h>
- X#include <stdio.h>
- X
- X#include "parpd.h"
- X
- X/*
- X * Receive and process an ARP request packet.
- X */
- void
- arpRecvPacket(pkt, len, ifip)
- InterfaceInfo *ifip;
- char *pkt;
- int len;
- X{
- X char src[32];
- X ARPPacket ap;
- X char *reason;
- X struct in_addr srcaddr, dstaddr, tmpaddr;
- X
- X /*
- X * Copy the part of the packet we want.
- X */
- X bcopy(pkt, (caddr_t) &ap, sizeof(ARPPacket));
- X ap.ap_len = len;
- X epochPackets++;
- X totalPackets++;
- X
- X /*
- X * Sanity checks. Should never see these, except that for some
- X * reason (probably a NIT bug), ARP requests sent by the local
- X * host seem to fail the packet length check. Fortunately, we
- X * don't care about these anyway.
- X */
- X reason = NULL;
- X len = sizeof(ap) - sizeof(ap.ap_len);
- X
- X if (ap.ap_len < len)
- X reason = "packet length";
- X else if (ntohs(ap.ap_ethernet.ether_type) != htons(ETHERTYPE_ARP))
- X reason = "packet type";
- X else if (ap.ap_arp.arp_hrd != htons(ARPHRD_ETHER))
- X reason = "hardware addr space";
- X else if (ap.ap_arp.arp_pro != htons(ETHERTYPE_IP))
- X reason = "protocol addr space";
- X else if (ap.ap_arp.arp_op != htons(ARPOP_REQUEST))
- X reason = "ARP opcode";
- X else if (ap.ap_arp.arp_hln != 6)
- X reason = "hardware addr length";
- X else if (ap.ap_arp.arp_pln != 4)
- X reason = "protocol addr length";
- X
- X if (reason != NULL) {
- X syslog(LOG_DEBUG, "%s: bad packet from %s (%s)",
- X ifip->ifi_ifname,
- X ether_ntoa(&ap.ap_ethernet.ether_shost),
- X reason);
- X badPackets++;
- X return;
- X }
- X
- X /*
- X * Copy stuff we need.
- X */
- X bcopy((caddr_t) ap.ap_arp.arp_spa, (caddr_t) &srcaddr,
- X sizeof(struct in_addr));
- X bcopy((caddr_t) ap.ap_arp.arp_tpa, (caddr_t) &dstaddr,
- X sizeof(struct in_addr));
- X strcpy(src, inet_ntoa(srcaddr));
- X
- X /*
- X * See if the request came from the local host. If so, we
- X * (obviously) shouldn't respond to it.
- X */
- X if (srcaddr.s_addr == ifip->ifi_hostaddr.sin_addr.s_addr) {
- X syslog(LOG_DEBUG, "%s: ignore arp for %s from myself",
- X ifip->ifi_ifname, inet_ntoa(dstaddr));
- X return;
- X }
- X
- X /*
- X * See if the request is for a host on the same subnet as
- X * the one we're on. If it is, then we don't do anything,
- X * and let the real host respond.
- X */
- X tmpaddr = utilGetSubNet(dstaddr, ifip->ifi_subnetmask.sin_addr);
- X
- X if (tmpaddr.s_addr == ifip->ifi_subnetaddr.sin_addr.s_addr) {
- X syslog(LOG_DEBUG, "%s: local network arp for %s from %s",
- X ifip->ifi_ifname, inet_ntoa(dstaddr), src);
- X return;
- X }
- X
- X /*
- X * This must be a packet that concerns us in some way.
- X */
- X concernPackets++;
- X
- X /*
- X * See if the request is for a host on some other IP network
- X * than the one we're on. If so, the sending host is badly
- X * confused, and we need to tell folks. But, we can't do
- X * anything to help this guy.
- X */
- X tmpaddr = utilGetIPNet(dstaddr);
- X
- X if (tmpaddr.s_addr != ifip->ifi_ipnetaddr.sin_addr.s_addr) {
- X /*
- X * If this is a host we haven't seen before, print
- X * a message.
- X */
- X if (utilAddHost(srcaddr, ifip)) {
- X syslog(LOG_WARNING,
- X "%s: non-local ip network arp for %s from %s",
- X ifip->ifi_ifname, inet_ntoa(dstaddr), src);
- X }
- X
- X return;
- X }
- X
- X /*
- X * Check to see if the destination is a broadcast address.
- X * If so, we don't want to respond, but we should log the
- X * request.
- X */
- X if (utilIsBroadcast(dstaddr, ifip)) {
- X /*
- X * If this is a host we haven't seen before, print
- X * a message.
- X */
- X if (utilAddHost(srcaddr, ifip)) {
- X syslog(LOG_WARNING,
- X "%s: arp for broadcast address (%s) from %s",
- X ifip->ifi_ifname, inet_ntoa(dstaddr), src);
- X }
- X
- X return;
- X }
- X
- X /*
- X * If we've made it to this point, then the request is for a host
- X * on the same IP network, but a different subnet, than the one
- X * we're on. This is where Proxy ARP comes in.
- X *
- X * If we haven't seen this host before, print a message.
- X */
- X if (utilAddHost(srcaddr, ifip)) {
- X syslog(LOG_WARNING, "%s: non-local subnet arp for %s from %s",
- X ifip->ifi_ifname, inet_ntoa(dstaddr), src);
- X }
- X
- X /*
- X * See if we have a route to the host or network. If we do,
- X * we make sure that the route is *not* right back out the
- X * same interface we got this packet on. If that's the
- X * case, then we are not the gateway for that route, and
- X * should let the gateway respond instead.
- X */
- X if (routeHaveRoute(dstaddr, ifip)) {
- X syslog(LOG_DEBUG, "we have a route and we're the gateway");
- X arpSendPacket(&ap, ifip);
- X return;
- X }
- X
- X /*
- X * We don't have a route, or we're not the gateway. So we
- X * do nothing.
- X */
- X syslog(LOG_DEBUG, "we don't have a route or we're not the gateway");
- X return;
- X}
- X
- X/*
- X * Send an ARP reply packet.
- X */
- void
- arpSendPacket(ap, ifip)
- InterfaceInfo *ifip;
- ARPPacket *ap;
- X{
- X struct in_addr tmp;
- X
- X /*
- X * Destination of this one is the sender of the request.
- X * Sender is us.
- X */
- X ap->ap_ethernet.ether_dhost = ap->ap_ethernet.ether_shost;
- X ap->ap_ethernet.ether_shost = ifip->ifi_etheraddr;
- X ap->ap_arp.arp_op = ARPOP_REPLY;
- X
- X /*
- X * Swap the fields around.
- X */
- X bcopy((caddr_t) &ap->ap_arp.arp_sha, (caddr_t) &ap->ap_arp.arp_tha,
- X sizeof(ap->ap_arp.arp_tha));
- X bcopy((caddr_t) &ifip->ifi_etheraddr, (caddr_t) &ap->ap_arp.arp_sha,
- X sizeof(ap->ap_arp.arp_sha));
- X
- X bcopy((caddr_t) ap->ap_arp.arp_tpa, (caddr_t) &tmp,
- X sizeof(struct in_addr));
- X bcopy((caddr_t) ap->ap_arp.arp_spa, (caddr_t) ap->ap_arp.arp_tpa,
- X sizeof(ap->ap_arp.arp_spa));
- X bcopy((caddr_t) &tmp, (caddr_t) ap->ap_arp.arp_spa,
- X sizeof(struct in_addr));
- X
- X syslog(LOG_DEBUG, "send arp reply back to %s",
- X ether_ntoa(&ap->ap_ethernet.ether_dhost));
- X
- X /*
- X * Send the packet.
- X */
- X arpWrite(ifip->ifi_fd, (caddr_t) ap, sizeof(*ap) - sizeof(ap->ap_len));
- X replyPackets++;
- X}
- X
- X/*
- X * Actually put a packet on the wire.
- X */
- void
- arpWrite(fd, buf, len)
- int fd, len;
- char *buf;
- X{
- X struct sockaddr sa;
- X struct strbuf cbuf, dbuf;
- X int offset = sizeof(sa.sa_data);
- X
- X sa.sa_family = AF_UNSPEC;
- X bcopy(buf, sa.sa_data, offset);
- X
- X cbuf.maxlen = cbuf.len = sizeof(struct sockaddr);
- X cbuf.buf = (caddr_t) &sa;
- X
- X /*
- X * NIT interface routines will put our ethernet header
- X * back on.
- X */
- X dbuf.maxlen = dbuf.len = len - offset;
- X dbuf.buf = buf + offset;
- X
- X /*
- X * Call the STREAMS write routine.
- X */
- X if (putmsg(fd, &cbuf, &dbuf, 0) < 0) {
- X syslog(LOG_ERR, "putmsg: %m");
- X exit(1);
- X }
- X}
- END_OF_FILE
- if test 6982 -ne `wc -c <'arp.c'`; then
- echo shar: \"'arp.c'\" unpacked with wrong size!
- fi
- # end of 'arp.c'
- fi
- if test -f 'if.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'if.c'\"
- else
- echo shar: Extracting \"'if.c'\" \(4326 characters\)
- sed "s/^X//" >'if.c' <<'END_OF_FILE'
- X#ifndef lint
- static char *RCSid = "$Header: /usr/src/ecn/parpd/RCS/if.c,v 1.1 92/05/08 08:43:48 davy Exp $";
- X#endif
- X
- X/*
- X * if.c - routines for dealing with network interfaces
- X *
- X * David A. Curry
- X * Purdue University
- X * Engineering Computer Network
- X * 1285 Electrical Engineering Building
- X * West Lafayette, IN 47907
- X * davy@ecn.purdue.edu
- X *
- X * April, 1992
- X *
- X * $Log: if.c,v $
- X * Revision 1.1 92/05/08 08:43:48 davy
- X * Initial revision
- X *
- X */
- X#include <sys/param.h>
- X#include <sys/socket.h>
- X#include <netinet/in.h>
- X#include <arpa/inet.h>
- X#include <sys/ioctl.h>
- X#include <net/if.h>
- X#include <netinet/if_ether.h>
- X#include <string.h>
- X#include <syslog.h>
- X#include <stdio.h>
- X
- X#include "parpd.h"
- X
- X/*
- X * Find all the network interfaces on this host.
- X */
- void
- ifGetInterfaces()
- X{
- X int n, s;
- X char buf[BUFSIZ];
- X struct ifreq ifr;
- X struct ifconf ifc;
- X InterfaceInfo *ifip;
- X struct sockaddr_in *sin;
- X register struct ifreq *ifrp;
- X
- X /*
- X * Get a socket.
- X */
- X if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
- X syslog(LOG_ERR, "ifGetInterfaces: socket: %m");
- X exit(1);
- X }
- X
- X ifc.ifc_buf = buf;
- X ifc.ifc_len = BUFSIZ;
- X
- X /*
- X * Get the list of interfaces.
- X */
- X if (ioctl(s, SIOCGIFCONF, (caddr_t) &ifc) < 0) {
- X syslog(LOG_ERR, "ifGetInterfaces: SIOCGIFCONF: %m");
- X exit(1);
- X }
- X
- X close(s);
- X
- X ifrp = ifc.ifc_req;
- X
- X /*
- X * For each interface...
- X */
- X for (n = ifc.ifc_len/sizeof(struct ifreq); n > 0; n--, ifrp++) {
- X /*
- X * Copy the interface request answers.
- X */
- X bcopy((caddr_t) ifrp, (caddr_t) &ifr, sizeof(struct ifreq));
- X
- X /*
- X * Need another socket.
- X */
- X if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
- X syslog(LOG_ERR, "ifGetInterfaces: socket: %m");
- X exit(1);
- X }
- X
- X /*
- X * Get the flags on this interface.
- X */
- X if (ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
- X syslog(LOG_ERR, "ifGetInterfaces: SIOCGIFFLAGS: %m");
- X exit(1);
- X }
- X
- X /*
- X * We only want active broadcast interfaces that aren't
- X * point-to-point and have an address resolution protcol.
- X */
- X if (((ifr.ifr_flags & IFF_UP) == 0) ||
- X ((ifr.ifr_flags & IFF_NOARP) != 0) ||
- X ((ifr.ifr_flags & IFF_LOOPBACK) != 0) ||
- X ((ifr.ifr_flags & IFF_BROADCAST) == 0) ||
- X ((ifr.ifr_flags & IFF_POINTOPOINT) != 0))
- X continue;
- X
- X /*
- X * Allocate an interface structure.
- X */
- X if (interfaces == NULL) {
- X interfaces = (InterfaceInfo *)
- X utilSafeAlloc(sizeof(InterfaceInfo));
- X ifip = interfaces;
- X }
- X else {
- X ifip->ifi_next = (InterfaceInfo *)
- X utilSafeAlloc(sizeof(InterfaceInfo));
- X ifip = ifip->ifi_next;
- X }
- X
- X /*
- X * Get the subnet mask for this interface.
- X */
- X if (ioctl(s, SIOCGIFNETMASK, (caddr_t) &ifr) < 0) {
- X syslog(LOG_ERR, "ifGetInterfaces: SIOCGIFNETMASK: %m");
- X exit(1);
- X }
- X
- X sin = (struct sockaddr_in *) &ifr.ifr_addr;
- X ifip->ifi_subnetmask.sin_addr = sin->sin_addr;
- X
- X /*
- X * Get the subnet network address for this interface.
- X */
- X if (ioctl(s, SIOCGIFADDR, &ifr) < 0) {
- X syslog(LOG_ERR, "ifGetInterfaces: SIOCGIFADDR: %m");
- X exit(1);
- X }
- X
- X sin = (struct sockaddr_in *) &ifr.ifr_addr;
- X close(s);
- X
- X /*
- X * Copy in all the information.
- X */
- X ifip->ifi_ifname = strdup(ifr.ifr_name);
- X bcopy((caddr_t) sin, (caddr_t) &ifip->ifi_hostaddr,
- X sizeof(struct sockaddr_in));
- X ifip->ifi_ipnetaddr.sin_addr = utilGetIPNet(sin->sin_addr);
- X ifip->ifi_ipnetmask.sin_addr = utilGetIPNetMask(sin->sin_addr);
- X ifip->ifi_subnetaddr.sin_addr = utilGetSubNet(sin->sin_addr,
- X ifip->ifi_subnetmask.sin_addr);
- X
- X /*
- X * Convert stuff to character strings, so we
- X * can print it out more easily.
- X */
- X ifip->ifi_ipnet =
- X strdup(inet_ntoa(ifip->ifi_ipnetaddr.sin_addr));
- X ifip->ifi_ipmask =
- X strdup(inet_ntoa(ifip->ifi_ipnetmask.sin_addr));
- X ifip->ifi_subnet =
- X strdup(inet_ntoa(ifip->ifi_subnetaddr.sin_addr));
- X ifip->ifi_submask =
- X strdup(inet_ntoa(ifip->ifi_subnetmask.sin_addr));
- X
- X syslog(LOG_DEBUG, "%s: ip %s ipmask %s sub %s submask %s",
- X ifip->ifi_ifname, ifip->ifi_ipnet, ifip->ifi_ipmask,
- X ifip->ifi_subnet, ifip->ifi_submask);
- X }
- X}
- X
- X/*
- X * Search the list of interfaces for the one with the given name.
- X */
- InterfaceInfo *
- ifFindInterface(name)
- char *name;
- X{
- X register InterfaceInfo *ifip;
- X
- X for (ifip = interfaces; ifip != NULL; ifip = ifip->ifi_next) {
- X if (strcmp(ifip->ifi_ifname, name) == 0)
- X return(ifip);
- X }
- X
- X return(NULL);
- X}
- END_OF_FILE
- if test 4326 -ne `wc -c <'if.c'`; then
- echo shar: \"'if.c'\" unpacked with wrong size!
- fi
- # end of 'if.c'
- fi
- if test -f 'nit.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'nit.c'\"
- else
- echo shar: Extracting \"'nit.c'\" \(3617 characters\)
- sed "s/^X//" >'nit.c' <<'END_OF_FILE'
- X#ifndef lint
- static char *RCSid = "$Header: /usr/src/ecn/parpd/RCS/nit.c,v 1.2 92/07/17 12:23:41 davy Exp $";
- X#endif
- X
- X/*
- X * nit.c - routines for setting up the network interface tap
- X *
- X * David A. Curry
- X * Purdue University
- X * Engineering Computer Network
- X * 1285 Electrical Engineering Building
- X * West Lafayette, IN 47907
- X * davy@ecn.purdue.edu
- X *
- X * April, 1992
- X *
- X * $Log: nit.c,v $
- X * Revision 1.2 92/07/17 12:23:41 davy
- X * ether_ntoa takes a pointer to a struct, not a struct
- X *
- X * Revision 1.1 92/05/08 08:43:52 davy
- X * Initial revision
- X *
- X */
- X#include <sys/param.h>
- X#include <sys/socket.h>
- X#include <netinet/in.h>
- X#include <arpa/inet.h>
- X#include <sys/ioctl.h>
- X#include <sys/file.h>
- X#include <sys/time.h>
- X#include <net/if.h>
- X#include <netinet/if_ether.h>
- X#include <sys/stropts.h>
- X#include <net/nit_if.h>
- X#include <net/nit_pf.h>
- X#include <net/packetfilt.h>
- X#include <syslog.h>
- X#include <string.h>
- X#include <stdio.h>
- X
- X#include "parpd.h"
- X
- X/*
- X * Set up the network interface tap to receive packets from the given
- X * interface.
- X */
- int
- nitSetup(ifip)
- InterfaceInfo *ifip;
- X{
- X int fd;
- X ARPPacket ap;
- X u_short offset;
- X struct ifreq ifr;
- X struct strioctl si;
- X struct sockaddr *sad;
- X struct packetfilt pf;
- X register u_short *fwp;
- X
- X /*
- X * Open the tap.
- X */
- X if ((fd = open(NIT_DEV, O_RDWR)) < 0) {
- X syslog(LOG_ERR, "nitSetup: open: %m");
- X exit(1);
- X }
- X
- X /*
- X * Arrange for discrete messages.
- X */
- X if (ioctl(fd, I_SRDOPT, (caddr_t) RMSGD) < 0) {
- X syslog(LOG_ERR, "nitSetup: I_SRDOPT: %m");
- X exit(1);
- X }
- X
- X /*
- X * Push and configure the filtering module.
- X */
- X if (ioctl(fd, I_PUSH, "pf") < 0) {
- X syslog(LOG_ERR, "nitSetup: I_PUSH: %m");
- X exit(1);
- X }
- X
- X /*
- X * Build the packet filter; we only want ARP-protocol
- X * ethernet packets, and only ARP_REQUESTs from those.
- X */
- X fwp = pf.Pf_Filter;
- X
- X offset = ((u_int) &ap.ap_ethernet.ether_type -
- X (u_int) &ap.ap_ethernet.ether_dhost) / sizeof(u_short);
- X
- X *fwp++ = ENF_PUSHWORD + offset;
- X *fwp++ = ENF_PUSHLIT;
- X *fwp++ = htons(ETHERTYPE_ARP);
- X *fwp++ = ENF_EQ;
- X
- X offset = (((u_int) &ap.ap_arp.arp_op - (u_int) &ap.ap_arp.arp_hrd) +
- X sizeof(struct ether_header)) / sizeof(u_short);
- X
- X *fwp++ = ENF_PUSHWORD + offset;
- X *fwp++ = ENF_PUSHLIT;
- X *fwp++ = htons(ARPOP_REQUEST);
- X *fwp++ = ENF_EQ;
- X
- X *fwp++ = ENF_AND;
- X
- X pf.Pf_FilterLen = fwp - &pf.Pf_Filter[0];
- X pf.Pf_Priority = 5;
- X
- X si.ic_cmd = NIOCSETF;
- X si.ic_timout = INFTIM;
- X si.ic_dp = (caddr_t) &pf;
- X si.ic_len = sizeof(struct packetfilt);
- X
- X if (ioctl(fd, I_STR, (caddr_t) &si) < 0) {
- X syslog(LOG_ERR, "nitSetup: NIOCSETF: %m");
- X exit(1);
- X }
- X
- X /*
- X * Bind the interface tap to the underlying interface.
- X */
- X strncpy(ifr.ifr_name, ifip->ifi_ifname, sizeof(ifr.ifr_name));
- X ifr.ifr_name[sizeof(ifr.ifr_name)-1] = '\0';
- X
- X si.ic_cmd = NIOCBIND;
- X si.ic_timout = INFTIM;
- X si.ic_dp = (caddr_t) 𝔦
- X si.ic_len = sizeof(struct ifreq);
- X
- X if (ioctl(fd, I_STR, (caddr_t) &si) < 0) {
- X syslog(LOG_ERR, "nitSetup: NIOCBIND: %m");
- X exit(1);
- X }
- X
- X /*
- X * Get the interface's ethernet address.
- X */
- X if (ioctl(fd, SIOCGIFADDR, (caddr_t) &ifr) < 0) {
- X syslog(LOG_ERR, "nitSetup: SIOCGIFADDR: %m");
- X exit(1);
- X }
- X
- X /*
- X * Copy the ethernet address.
- X */
- X sad = (struct sockaddr *) &ifr.ifr_addr;
- X bcopy((struct ether_addr *) sad->sa_data, &ifip->ifi_etheraddr,
- X sizeof(struct ether_addr));
- X ifip->ifi_ether = strdup(ether_ntoa(&ifip->ifi_etheraddr));
- X
- X syslog(LOG_DEBUG, "%s: ether %s", ifip->ifi_ifname, ifip->ifi_ether);
- X
- X return(fd);
- X}
- X
- X/*
- X * Flush all accumulated data.
- X */
- void
- nitFlush(fd)
- int fd;
- X{
- X if (ioctl(fd, I_FLUSH, (caddr_t) FLUSHR) < 0) {
- X syslog(LOG_ERR, "nitFlush: I_FLUSH: %m");
- X exit(1);
- X }
- X}
- END_OF_FILE
- if test 3617 -ne `wc -c <'nit.c'`; then
- echo shar: \"'nit.c'\" unpacked with wrong size!
- fi
- # end of 'nit.c'
- fi
- if test -f 'parpd.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'parpd.c'\"
- else
- echo shar: Extracting \"'parpd.c'\" \(3481 characters\)
- sed "s/^X//" >'parpd.c' <<'END_OF_FILE'
- X#ifndef lint
- static char *RCSid = "$Header: /usr/src/ecn/parpd/RCS/parpd.c,v 1.1 92/05/08 08:43:57 davy Exp $";
- X#endif
- X
- X/*
- X * parpd - proxy arp daemon
- X *
- X * David A. Curry
- X * Purdue University
- X * Engineering Computer Network
- X * 1285 Electrical Engineering Building
- X * West Lafayette, IN 47907
- X * davy@ecn.purdue.edu
- X *
- X * April, 1992
- X *
- X * $Log: parpd.c,v $
- X * Revision 1.1 92/05/08 08:43:57 davy
- X * Initial revision
- X *
- X */
- X#include <sys/param.h>
- X#include <sys/socket.h>
- X#include <netinet/in.h>
- X#include <arpa/inet.h>
- X#include <sys/time.h>
- X#include <net/if.h>
- X#include <netinet/if_ether.h>
- X#include <syslog.h>
- X#include <signal.h>
- X#include <errno.h>
- X#include <stdio.h>
- X
- X#include "parpd.h"
- X
- int badPackets = 0; /* # of bad packets received */
- int replyPackets = 0; /* # of arp reply packets sent */
- int totalPackets = 0; /* # of packets received total */
- int epochPackets = 0; /* # of packets over all time */
- int concernPackets = 0; /* # of packets we care about */
- X
- RouteInfo *routes = NULL; /* routing table */
- InterfaceInfo *interfaces = NULL; /* list of network interfaces */
- X
- extern int errno;
- X
- main(argc, argv)
- char **argv;
- int argc;
- X{
- X InterfaceInfo *ifip;
- X
- X /*
- X * Set up syslog.
- X */
- X openlog(*argv, LOG_PID, LOG_DAEMON);
- X setlogmask(LOG_UPTO(LOG_WARNING));
- X
- X /*
- X * Process arguments. The only one is debug mode.
- X */
- X while (--argc) {
- X if (**++argv != '-')
- X continue;
- X
- X switch (*++*argv) {
- X case 'd':
- X setlogmask(LOG_UPTO(LOG_DEBUG));
- X break;
- X }
- X }
- X
- X /*
- X * Gather interface information.
- X */
- X ifGetInterfaces();
- X
- X /*
- X * Set up the network interface tap for each interface.
- X */
- X for (ifip = interfaces; ifip != NULL; ifip = ifip->ifi_next) {
- X if ((ifip->ifi_fd = nitSetup(ifip)) < 0) {
- X syslog(LOG_ERR, "nitSetup: %s: %m", ifip->ifi_ifname);
- X exit(1);
- X }
- X }
- X
- X /*
- X * Gather initial routing information.
- X */
- X routeGetRoutes();
- X
- X /*
- X * Set up signal handlers.
- X */
- X signal(SIGUSR1, utilDumpStats);
- X signal(SIGUSR2, utilClearStats);
- X signal(SIGALRM, routeUpdateRoutes);
- X
- X alarm(ROUTE_UPDATE);
- X
- X /*
- X * Never returns.
- X */
- X parpdMainLoop();
- X}
- X
- X/*
- X * Main loop. Never returns.
- X */
- void
- parpdMainLoop()
- X{
- X fd_set readfds;
- X register int cc;
- X char buf[NIT_BUFSIZE];
- X register InterfaceInfo *ifip;
- X
- X /*
- X * Flush any junk that's accumlated while we've been setting up.
- X */
- X for (ifip = interfaces; ifip != NULL; ifip = ifip->ifi_next)
- X nitFlush(ifip->ifi_fd);
- X
- X /*
- X * For ever...
- X */
- X for (;;) {
- X FD_ZERO(&readfds);
- X
- X /*
- X * Set up the bits for select.
- X */
- X for (ifip = interfaces; ifip != NULL; ifip = ifip->ifi_next)
- X FD_SET(ifip->ifi_fd, &readfds);
- X
- X /*
- X * Wait for something to arrive on an interface.
- X */
- X cc = select(NFDBITS, &readfds, (fd_set *) 0, (fd_set *) 0,
- X (struct timeval *) 0);
- X
- X /*
- X * Interrupted syscall (routing update or user signal).
- X */
- X if ((cc < 0) && (errno != EINTR)) {
- X syslog(LOG_ERR, "select: %m");
- X exit(1);
- X }
- X
- X if (cc <= 0)
- X continue;
- X
- X /*
- X * Check the interfaces.
- X */
- X for (ifip = interfaces; ifip != NULL; ifip = ifip->ifi_next) {
- X /*
- X * Anything to read?
- X */
- X if (!FD_ISSET(ifip->ifi_fd, &readfds))
- X continue;
- X
- X /*
- X * Read it.
- X */
- X if ((cc = read(ifip->ifi_fd, buf, NIT_BUFSIZE)) <= 0)
- X continue;
- X
- X /*
- X * Interrupted syscall.
- X */
- X if ((cc < 0) && (errno != EINTR)) {
- X syslog(LOG_ERR, "read: %m");
- X exit(1);
- X }
- X
- X if (cc <= 0)
- X continue;
- X
- X /*
- X * Process the packet.
- X */
- X arpRecvPacket(buf, cc, ifip);
- X }
- X }
- X}
- END_OF_FILE
- if test 3481 -ne `wc -c <'parpd.c'`; then
- echo shar: \"'parpd.c'\" unpacked with wrong size!
- fi
- # end of 'parpd.c'
- fi
- if test -f 'parpd.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'parpd.h'\"
- else
- echo shar: Extracting \"'parpd.h'\" \(3113 characters\)
- sed "s/^X//" >'parpd.h' <<'END_OF_FILE'
- X/*
- X * $Header: /usr/src/ecn/parpd/RCS/parpd.h,v 1.1 92/05/08 08:44:01 davy Exp $
- X *
- X * parpd.h - proxy arp daemon definitions
- X *
- X * David A. Curry
- X * Purdue University
- X * Engineering Computer Network
- X * 1285 Electrical Engineering Building
- X * West Lafayette, IN 47907
- X * davy@ecn.purdue.edu
- X *
- X * April, 1992
- X *
- X * $Log: parpd.h,v $
- X * Revision 1.1 92/05/08 08:44:01 davy
- X * Initial revision
- X *
- X */
- X#define PATCHLEVEL 1.0
- X
- X#define NIT_DEV "/dev/nit" /* name of network interf tap */
- X#define NIT_BUFSIZE 8192 /* max packet size to receive */
- X#define ROUTE_UPDATE 180 /* update routes this often */
- X
- X/*
- X * An ARP packet.
- X */
- typedef struct _ap {
- X struct ether_header ap_ethernet; /* ethernet header */
- X struct ether_arp ap_arp; /* arp packet */
- X int ap_len; /* internal use only */
- X} ARPPacket;
- X
- X/*
- X * A host record, for keeping track of which hosts we've "helped".
- X */
- typedef struct _hr {
- X struct in_addr hr_address; /* address of host */
- X
- X int hr_refcnt; /* how many times helped*/
- X
- X struct _hr *hr_next; /* next entry in list */
- X} HostRecord;
- X
- X/*
- X * An interface information record, for keeping track of the interfaces
- X * we are receiving packets from.
- X */
- typedef struct _ifi {
- X int ifi_fd; /* nit file descriptor */
- X
- X char *ifi_ifname; /* interface name */
- X
- X struct sockaddr_in ifi_hostaddr; /* host ip address */
- X
- X char *ifi_ether; /* ether addr (string) */
- X struct ether_addr ifi_etheraddr; /* ethernet address */
- X
- X char *ifi_ipnet; /* ip network (string) */
- X char *ifi_ipmask; /* ip netmask (string) */
- X struct sockaddr_in ifi_ipnetaddr; /* ip network address */
- X struct sockaddr_in ifi_ipnetmask; /* ip network mask */
- X
- X char *ifi_subnet; /* subnet (string) */
- X char *ifi_submask; /* subnet mask (string) */
- X struct sockaddr_in ifi_subnetaddr; /* subnet address */
- X struct sockaddr_in ifi_subnetmask; /* subnet mask */
- X
- X HostRecord *ifi_hostlist; /* helped hosts on net */
- X
- X struct _ifi *ifi_next; /* pointer to next */
- X} InterfaceInfo;
- X
- X/*
- X * A route information record, for keeping track of network routing.
- X */
- typedef struct _ri {
- X short ri_hostroute; /* 1 if a host route */
- X
- X char *ri_dstnet; /* dest net (string) */
- X struct sockaddr_in ri_dstnetaddr; /* destination net */
- X
- X InterfaceInfo *ri_interface; /* interface of route */
- X
- X struct _ri *ri_next; /* pointer to next */
- X} RouteInfo;
- X
- extern InterfaceInfo *interfaces;
- X
- extern RouteInfo *routes;
- X
- extern int concernPackets;
- extern int epochPackets;
- extern int totalPackets;
- extern int replyPackets;
- extern int badPackets;
- X
- InterfaceInfo *ifFindInterface();
- X
- struct in_addr utilGetIPNetMask();
- struct in_addr utilGetSubNet();
- struct in_addr utilGetIPNet();
- X
- char *utilSafeAlloc();
- char *ether_ntoa();
- X
- int utilIsBroadcast();
- int routeHaveRoute();
- int utilAddHost();
- int nitSetup();
- X
- void routeUpdateRoutes();
- void ifGetInterfaces();
- void routeFreeRoutes();
- void routeGetRoutes();
- void utilClearStats();
- void arpRecvPacket();
- void arpSendPacket();
- void parpdMainLoop();
- void utilDumpStats();
- void arpWrite();
- void nitFlush();
- END_OF_FILE
- if test 3113 -ne `wc -c <'parpd.h'`; then
- echo shar: \"'parpd.h'\" unpacked with wrong size!
- fi
- # end of 'parpd.h'
- fi
- if test -f 'parpd.man' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'parpd.man'\"
- else
- echo shar: Extracting \"'parpd.man'\" \(5257 characters\)
- sed "s/^X//" >'parpd.man' <<'END_OF_FILE'
- X.TH IN.PARPD 8 "1 May 1992" "ECN"
- X.SH NAME
- in.parpd \- Proxy ARP daemon
- X.SH SYNOPSIS
- X.B in.parpd
- X[
- X.B \-d
- X]
- X.SH DESCRIPTION
- X.PP
- X.B in.parpd
- implements the ``Proxy ARP'' protocol as described in RFC1027.
- X.PP
- Some hosts with out-of-date implementations of the Internet protocols do not
- understand IP subnetting as specified in RFC950.
- XFor example,
- in the case of a subnetted Class B network,
- these hosts believe that any host whose Internet address is on the Class B
- network must be on the local network cable,
- and they will issue ARP requests for the ethernet address of any host with
- the same Class B address.
- Since most of these hosts are actually on different subnets,
- they will never see the ARP request (and hence never respond to it),
- meaning that the out-of-date host will not be able to talk to any host not
- actually connected to the same cable.
- X.PP
- Proxy ARP enables a gateway to help out these out-of-date hosts by lying to
- the confused host.
- This is done by sending an ARP reply packet with the gateway's ethernet
- address for any host not on the local subnet.
- The out-of-date host will send its traffic to the gateway (thinking that
- the gateway is the destination),
- and the gateway will forward the packet just as it forwards any other.
- X.PP
- X.BR in.parpd ,
- when invoked,
- probes for all active ethernet interfaces on the host.
- XFor each interface found,
- X.B in.parpd
- will configure the Network Interface Tap
- X(see
- X.BR nit (4P))
- to receive any ARP requests arriving on that interface.
- When an ARP request arrives,
- X.B in.parpd
- processes it as follows:
- X.IP \(bu
- Several sanity checks are performed on the packet.
- If any of these checks fail,
- the packet is silently discarded.
- X.IP \(bu
- If the request came from the host
- X.B in.parpd
- is running on,
- it is ignored.
- X.IP \(bu
- If the request is for the address of a host on the local subnet,
- it is ignored,
- allowing the real host to respond.
- X.IP \(bu
- If the request is for a host on some other IP network than the local network,
- a message is sent to
- X.BR syslogd (8)
- at the LOG_WARNING level.
- Because the host which sent this packet is badly confused,
- X.B in.parpd
- can do nothing to help it,
- so the packet is ignored.
- X.IP \(bu
- If the request is for a broadcast address,
- a message is sent to
- X.BR syslogd (8)
- at the LOG_WARNING level.
- Both the IP broadcast and the subnet broadcast are checked for,
- in both ``all ones'' and ``all zeros'' formats.
- Because there is no appropriate response to an ARP for the broadcast address,
- the packet is ignored.
- X.IP \(bu
- Having made it this far,
- the request is known to be for a host on a different subnet.
- A message is sent to
- X.BR syslogd (8)
- at the LOG_WARNING level detailing this.
- X.IP \(bu
- If the local host has a route to the subnet in the ARP request,
- and the route goes through a different interface than the one on which the
- ARP request was received,
- an ARP response with the local host's ethernet address is generated.
- If the local host does not have a route to the subnet,
- or if the route is out the same interface on which the request was received,
- no response is generated,
- since there is a more appropriate gateway that should respond instead.
- X.PP
- As mentioned above,
- when a ``confused'' host is detected,
- a message is sent to
- X.BR syslogd (8)
- at the LOG_WARNING level.
- X.B in.parpd
- maintains a record of which hosts have been identified via these messages,
- and will only identify a host the first time it is detected.
- This allows confused hosts to be noticed each time
- X.B in.parpd
- is started,
- but prevents volumes of messages being printed for ``confused but okay''
- hosts which cannot be fixed.
- X.PP
- If the
- X.B in.parpd
- process is sent a
- X.B SIGUSR1
- signal,
- it will dump several packet counters,
- and a list of all ``confused'' hosts it has detected.
- This is done by sending messages to
- X.BR syslogd (8)
- at the LOG_INFO level.
- If the
- X.B in.parpd
- process is sent a
- X.B SIGUSR2
- signal,
- it will clear the packet counters and the list of ``confused'' hosts it has
- detected.
- A message is sent to
- X.BR syslogd (8)
- at the LOG_NOTICE level when this occurs.
- This feature can be used to clear
- X.BR in.parpd 's
- memory after fixing a broken host,
- for example.
- X.PP
- X.B in.parpd
- does not need to be told about network configurations,
- as it examines the kernel routing tables to obtain information about what
- networks are accessible from the current host.
- The routing tables are examined once every three minutes;
- this time can be changed by editing the file
- X.I parpd.h
- and recompiling.
- X.PP
- If invoked with the
- X.B \-d
- option,
- X.B in.parpd
- will send debugging output to
- X.BR syslogd (8)
- at the LOG_DEBUG level.
- This output can be quite voluminous;
- it includes two lines about each interface at startup,
- a dump of the routing table every time it is obtained,
- and one or more lines about each ARP request packet received.
- X.SH SEE ALSO
- X.BR nit (4P),
- X.BR syslogd (8),
- X.I "An Ethernet Address Resolution Protocol"
- X(RFC826),
- X.I "Internet Standard Subnetting Procedure"
- X(RFC950),
- X.I "Using ARP to Implement Transparent Subnet Gateways"
- X(RFC1027)
- X.SH BUGS
- X.PP
- If vendors would get their acts together,
- this software would be unnecessary.
- X.SH AUTHOR
- X.PP
- David A. Curry, Purdue University Engineering Computer Network,
- X1285 Electrical Engineering Building,
- West Lafayette, IN 47907,
- davy@ecn.purdue.edu.
- END_OF_FILE
- if test 5257 -ne `wc -c <'parpd.man'`; then
- echo shar: \"'parpd.man'\" unpacked with wrong size!
- fi
- # end of 'parpd.man'
- fi
- if test -f 'route.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'route.c'\"
- else
- echo shar: Extracting \"'route.c'\" \(5785 characters\)
- sed "s/^X//" >'route.c' <<'END_OF_FILE'
- X#ifndef lint
- static char *RCSid = "$Header: /usr/src/ecn/parpd/RCS/route.c,v 1.2 92/07/16 14:33:11 davy Exp $";
- X#endif
- X
- X/*
- X * route.c - routines for dealing with routes
- X *
- X * David A. Curry
- X * Purdue University
- X * Engineering Computer Network
- X * 1285 Electrical Engineering Building
- X * West Lafayette, IN 47907
- X * davy@ecn.purdue.edu
- X *
- X * April, 1992
- X *
- X * $Log: route.c,v $
- X * Revision 1.2 92/07/16 14:33:11 davy
- X * Fixed a bug with a pointer pointing out in space.
- X *
- X * Revision 1.1 92/05/08 08:44:09 davy
- X * Initial revision
- X *
- X */
- X#include <sys/param.h>
- X#include <sys/socket.h>
- X#include <netinet/in.h>
- X#include <arpa/inet.h>
- X#include <sys/ioctl.h>
- X#include <net/route.h>
- X#include <sys/file.h>
- X#include <sys/mbuf.h>
- X#include <net/if.h>
- X#include <netinet/if_ether.h>
- X#include <syslog.h>
- X#include <string.h>
- X#include <stdio.h>
- X#include <nlist.h>
- X#include <kvm.h>
- X
- X#include "parpd.h"
- X
- X/*
- X * For reading routes from the kernel.
- X */
- static struct nlist nl[] = {
- X#define N_RTHASHSIZE 0
- X { "_rthashsize" },
- X#define N_RTHOST 1
- X { "_rthost" },
- X#define N_RTNET 2
- X { "_rtnet" },
- X { "" }
- X};
- X
- void
- routeGetRoutes()
- X{
- X int hashsize;
- X struct mbuf mb;
- X register int i;
- X struct ifnet ifn;
- X int firstpass = 1;
- X struct in_addr ina;
- X RouteInfo ri, *rip;
- X char buf[16], name[16];
- X struct sockaddr_in *sin;
- X struct mbuf **routehash;
- X static kvm_t *kd = NULL;
- X register struct mbuf *m;
- X register struct rtentry *rt;
- X
- X /*
- X * Open the kernel and get some addresses.
- X */
- X if (kd == NULL) {
- X kd = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL);
- X
- X if (kd == NULL) {
- X syslog(LOG_ERR, "routeGetRoutes: kvm_open: %m");
- X exit(1);
- X }
- X
- X if (kvm_nlist(kd, nl) < 0) {
- X syslog(LOG_ERR, "routeGetRoutes: no namelist");
- X exit(1);
- X }
- X }
- X
- X kvm_read(kd, nl[N_RTHASHSIZE].n_value, &hashsize, sizeof(int));
- X
- X routehash = (struct mbuf **)
- X utilSafeAlloc(hashsize * sizeof(struct mbuf *));
- X
- X kvm_read(kd, nl[N_RTHOST].n_value, routehash,
- X hashsize * sizeof(struct mbuf *));
- X
- X bzero((caddr_t) &ri, sizeof(RouteInfo));
- X
- again:
- X /*
- X * For each route...
- X */
- X for (i=0; i < hashsize; i++) {
- X if (routehash[i] == 0)
- X continue;
- X
- X m = routehash[i];
- X
- X /*
- X * For each route...
- X */
- X while (m != NULL) {
- X kvm_read(kd, m, &mb, sizeof(struct mbuf));
- X rt = mtod(&mb, struct rtentry *);
- X ri.ri_hostroute = 0;
- X
- X if (((unsigned) rt < (unsigned) &mb) ||
- X ((unsigned) rt >= (unsigned) (&mb+1))) {
- X syslog(LOG_ERR, "routeGetRoutes: bad table");
- X exit(1);
- X }
- X
- X /*
- X * Don't care about non-Internet routes.
- X */
- X if (rt->rt_dst.sa_family != AF_INET) {
- X m = mb.m_next;
- X continue;
- X }
- X
- X /*
- X * Don't care about routes with no interface.
- X */
- X if (rt->rt_ifp == NULL) {
- X m = mb.m_next;
- X continue;
- X }
- X
- X /*
- X * Copy some of the information.
- X */
- X sin = (struct sockaddr_in *) &rt->rt_dst;
- X bcopy((caddr_t) sin, (caddr_t) &ri.ri_dstnetaddr,
- X sizeof(struct sockaddr_in));
- X
- X ri.ri_dstnet =
- X strdup(inet_ntoa(ri.ri_dstnetaddr.sin_addr));
- X
- X /*
- X * Is it a host route?
- X */
- X if (rt->rt_flags & RTF_HOST)
- X ri.ri_hostroute = 1;
- X
- X /*
- X * Get the interface name.
- X */
- X kvm_read(kd, rt->rt_ifp, &ifn, sizeof(struct ifnet));
- X kvm_read(kd, ifn.if_name, buf, sizeof(buf));
- X sprintf(name, "%s%d", buf, ifn.if_unit);
- X
- X ri.ri_interface = ifFindInterface(name);
- X
- X /*
- X * If we didn't find the interface, we don't
- X * care about this route.
- X */
- X if (ri.ri_interface == NULL) {
- X free(ri.ri_dstnet);
- X m = mb.m_next;
- X continue;
- X }
- X
- X /*
- X * If this route is not for the same IP network
- X * we're on, we don't need it.
- X */
- X ina = utilGetIPNet(ri.ri_dstnetaddr.sin_addr);
- X
- X if (ri.ri_interface->ifi_ipnetaddr.sin_addr.s_addr !=
- X ina.s_addr) {
- X syslog(LOG_DEBUG, "%s: non-local %sroute: %s",
- X ri.ri_interface->ifi_ifname,
- X ri.ri_hostroute ? "host " : "net ",
- X ri.ri_dstnet);
- X free(ri.ri_dstnet);
- X m = mb.m_next;
- X continue;
- X }
- X
- X /*
- X * Allocate a route entry.
- X */
- X if (routes == NULL) {
- X routes = (RouteInfo *)
- X utilSafeAlloc(sizeof(RouteInfo));
- X rip = routes;
- X }
- X else {
- X rip->ri_next = (RouteInfo *)
- X utilSafeAlloc(sizeof(RouteInfo));
- X rip = rip->ri_next;
- X }
- X
- X /*
- X * Copy the info.
- X */
- X bcopy((caddr_t) &ri, (caddr_t) rip,
- X sizeof(RouteInfo));
- X
- X syslog(LOG_DEBUG, "%s: %sroute: %s",
- X rip->ri_interface->ifi_ifname,
- X rip->ri_hostroute ? "host " : "net ",
- X rip->ri_dstnet);
- X
- X m = mb.m_next;
- X }
- X }
- X
- X /*
- X * Still got more stuff to get.
- X */
- X if (firstpass) {
- X kvm_read(kd, nl[N_RTNET].n_value, routehash,
- X hashsize * sizeof(struct mbuf *));
- X firstpass = 0;
- X goto again;
- X }
- X
- X free(routehash);
- X}
- X
- X/*
- X * See if we have a route to dst on interface ifip.
- X */
- int
- routeHaveRoute(dst, ifip)
- InterfaceInfo *ifip;
- struct in_addr dst;
- X{
- X struct in_addr tmp;
- X register RouteInfo *rip;
- X
- X tmp = utilGetSubNet(dst, ifip->ifi_subnetmask.sin_addr);
- X
- X for (rip = routes; rip != NULL; rip = rip->ri_next) {
- X /*
- X * Not interested in routes out the incoming
- X * interface.
- X */
- X if (rip->ri_interface == ifip)
- X continue;
- X
- X /*
- X * Do we have a route?
- X */
- X if (rip->ri_hostroute) {
- X if (dst.s_addr == rip->ri_dstnetaddr.sin_addr.s_addr)
- X return(1);
- X }
- X else {
- X if (tmp.s_addr == rip->ri_dstnetaddr.sin_addr.s_addr)
- X return(1);
- X }
- X }
- X
- X return(0);
- X}
- X
- X/*
- X * Free the current list of routes.
- X */
- void
- routeFreeRoutes()
- X{
- X register RouteInfo *rip, *nrip;
- X
- X for (rip = routes; rip != NULL; rip = nrip) {
- X free(rip->ri_dstnet);
- X nrip = rip->ri_next;
- X free(rip);
- X }
- X
- X routes = NULL;
- X}
- X
- X/*
- X * Update the list of routes.
- X */
- void
- routeUpdateRoutes()
- X{
- X alarm(0);
- X
- X syslog(LOG_DEBUG, "get routing update");
- X
- X routeFreeRoutes();
- X routeGetRoutes();
- X
- X alarm(ROUTE_UPDATE);
- X}
- END_OF_FILE
- if test 5785 -ne `wc -c <'route.c'`; then
- echo shar: \"'route.c'\" unpacked with wrong size!
- fi
- # end of 'route.c'
- fi
- if test -f 'util.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'util.c'\"
- else
- echo shar: Extracting \"'util.c'\" \(5112 characters\)
- sed "s/^X//" >'util.c' <<'END_OF_FILE'
- X#ifndef lint
- static char *RCSid = "$Header: /usr/src/ecn/parpd/RCS/util.c,v 1.1 92/05/08 08:44:12 davy Exp $";
- X#endif
- X
- X/*
- X * util.c - utility routines
- X *
- X * David A. Curry
- X * Purdue University
- X * Engineering Computer Network
- X * 1285 Electrical Engineering Building
- X * West Lafayette, IN 47907
- X * davy@ecn.purdue.edu
- X *
- X * April, 1992
- X *
- X * $Log: util.c,v $
- X * Revision 1.1 92/05/08 08:44:12 davy
- X * Initial revision
- X *
- X */
- X#include <sys/param.h>
- X#include <sys/socket.h>
- X#include <netinet/in.h>
- X#include <arpa/inet.h>
- X#include <net/if.h>
- X#include <netinet/if_ether.h>
- X#include <string.h>
- X#include <syslog.h>
- X#include <stdio.h>
- X#include <netdb.h>
- X
- X#include "parpd.h"
- X
- X/*
- X * Allocate memory with error checking.
- X */
- char *
- utilSafeAlloc(size)
- int size;
- X{
- X char *malloc();
- X register char *p;
- X
- X if ((p = malloc(size)) == NULL) {
- X syslog(LOG_ERR, "utilSafeAlloc: out of memory");
- X exit(1);
- X }
- X
- X bzero(p, size);
- X return(p);
- X}
- X
- X/*
- X * Get the IP network mask for a given address.
- X */
- struct in_addr
- utilGetIPNetMask(in)
- struct in_addr in;
- X{
- X struct in_addr ina;
- X register u_long mask;
- X register u_long i = ntohl(in.s_addr);
- X
- X if (IN_CLASSA(i))
- X mask = IN_CLASSA_NET;
- X else if (IN_CLASSB(i))
- X mask = IN_CLASSB_NET;
- X else
- X mask = IN_CLASSC_NET;
- X
- X ina.s_addr = mask;
- X return(ina);
- X}
- X
- X/*
- X * Get the subnet network for a given address.
- X */
- struct in_addr
- utilGetSubNet(in, mask)
- struct in_addr in, mask;
- X{
- X struct in_addr ina;
- X
- X ina.s_addr = ntohl(in.s_addr) & ntohl(mask.s_addr);
- X return(ina);
- X}
- X
- X/*
- X * Get the IP network for a given address.
- X */
- struct in_addr
- utilGetIPNet(in)
- struct in_addr in;
- X{
- X struct in_addr ina;
- X register u_long net;
- X register u_long i = ntohl(in.s_addr);
- X
- X if (IN_CLASSA(i))
- X net = i & IN_CLASSA_NET;
- X else if (IN_CLASSB(i))
- X net = i & IN_CLASSB_NET;
- X else
- X net = i & IN_CLASSC_NET;
- X
- X ina.s_addr = net;
- X return(ina);
- X}
- X
- X/*
- X * Return whether or not dst is a broadcast address.
- X */
- int
- utilIsBroadcast(dst, ifip)
- InterfaceInfo *ifip;
- struct in_addr dst;
- X{
- X register u_long m, l;
- X
- X m = ~ifip->ifi_subnetmask.sin_addr.s_addr;
- X l = ntohl(dst.s_addr) & m;
- X
- X if ((l == (INADDR_BROADCAST & m)) || (l == (INADDR_ANY & m)))
- X return(1);
- X
- X m = ~ifip->ifi_ipnetmask.sin_addr.s_addr;
- X l = ntohl(dst.s_addr) & m;
- X
- X if ((l == (INADDR_BROADCAST & m)) || (l == (INADDR_ANY & m)))
- X return(1);
- X
- X return(0);
- X}
- X
- X/*
- X * Add a host to a list of hosts.
- X */
- int
- utilAddHost(addr, ifip)
- struct in_addr addr;
- InterfaceInfo *ifip;
- X{
- X register HostRecord *hrp, *lhrp;
- X
- X if (ifip->ifi_hostlist == NULL) {
- X syslog(LOG_DEBUG, "%s: first host (%s) on list",
- X ifip->ifi_ifname, inet_ntoa(addr));
- X
- X ifip->ifi_hostlist = (HostRecord *)
- X utilSafeAlloc(sizeof(HostRecord));
- X hrp = ifip->ifi_hostlist;
- X
- X bcopy((caddr_t) &addr, (caddr_t) &hrp->hr_address,
- X sizeof(struct in_addr));
- X hrp->hr_refcnt = 1;
- X return(1);
- X }
- X
- X for (hrp = ifip->ifi_hostlist; hrp != NULL; hrp = hrp->hr_next) {
- X lhrp = hrp;
- X
- X if (hrp->hr_address.s_addr == addr.s_addr) {
- X syslog(LOG_DEBUG, "%s: host (%s) already on list",
- X ifip->ifi_ifname, inet_ntoa(addr));
- X hrp->hr_refcnt++;
- X
- X return(0);
- X }
- X }
- X
- X syslog(LOG_DEBUG, "%s: add new host (%s) to list",
- X ifip->ifi_ifname, inet_ntoa(addr));
- X
- X lhrp->hr_next = (HostRecord *) utilSafeAlloc(sizeof(HostRecord));
- X
- X bcopy((caddr_t) &addr, (caddr_t) &lhrp->hr_address,
- X sizeof(struct in_addr));
- X lhrp->hr_refcnt = 1;
- X return(1);
- X}
- X
- X/*
- X * Dump statistics.
- X */
- void
- utilDumpStats()
- X{
- X int syslogmask;
- X struct hostent *hp;
- X register HostRecord *hrp;
- X register InterfaceInfo *ifip;
- X
- X syslogmask = setlogmask(LOG_UPTO(LOG_INFO));
- X
- X syslog(LOG_INFO, "Total packets received since start: %d",
- X epochPackets);
- X syslog(LOG_INFO, "Total packets received since reset: %d",
- X totalPackets);
- X syslog(LOG_INFO, "Bad packets received since reset: %d",
- X badPackets);
- X syslog(LOG_INFO, "Proxy-possible packets since reset: %d",
- X concernPackets);
- X syslog(LOG_INFO, "Proxy-ARP replies sent since reset: %d",
- X replyPackets);
- X
- X for (ifip = interfaces; ifip != NULL; ifip = ifip->ifi_next) {
- X syslog(LOG_INFO, "Proxy-ARPed hosts on interface %s:",
- X ifip->ifi_ifname);
- X
- X if ((hrp = ifip->ifi_hostlist) == NULL) {
- X syslog(LOG_INFO, "none.");
- X continue;
- X }
- X
- X for (; hrp != NULL; hrp = hrp->hr_next) {
- X hp = gethostbyaddr((caddr_t) &hrp->hr_address.s_addr,
- X sizeof(hrp->hr_address.s_addr),
- X AF_INET);
- X syslog(LOG_INFO, "%s (%s): %d replies sent",
- X hp ? hp->h_name : "?",
- X inet_ntoa(hrp->hr_address),
- X hrp->hr_refcnt);
- X }
- X }
- X
- X setlogmask(syslogmask);
- X}
- X
- X/*
- X * Clear statistics.
- X */
- void
- utilClearStats()
- X{
- X int syslogmask;
- X register InterfaceInfo *ifip;
- X register HostRecord *hrp, *nhrp;
- X
- X syslogmask = setlogmask(LOG_UPTO(LOG_NOTICE));
- X
- X badPackets = 0;
- X replyPackets = 0;
- X totalPackets = 0;
- X concernPackets = 0;
- X
- X for (ifip = interfaces; ifip != NULL; ifip = ifip->ifi_next) {
- X for (hrp = ifip->ifi_hostlist; hrp != NULL; hrp = nhrp) {
- X nhrp = hrp->hr_next;
- X free(hrp);
- X }
- X
- X ifip->ifi_hostlist = NULL;
- X }
- X
- X syslog(LOG_NOTICE, "statistics cleared");
- X setlogmask(syslogmask);
- X}
- END_OF_FILE
- if test 5112 -ne `wc -c <'util.c'`; then
- echo shar: \"'util.c'\" unpacked with wrong size!
- fi
- # end of 'util.c'
- fi
- echo shar: End of archive 1 \(of 1\).
- cp /dev/null ark1isdone
- MISSING=""
- for I in 1 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have the archive.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-