home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / unix / volume26 / parpd123 / part01 < prev    next >
Encoding:
Text File  |  1993-04-13  |  45.7 KB  |  1,922 lines

  1. Newsgroups: comp.sources.unix
  2. From: davy@ecn.purdue.edu (David A. Curry)
  3. Subject: v26i159: parpd1.2 - proxy arp daemon for sunos/NIT, V1.2, Part01/01
  4. Sender: unix-sources-moderator@vix.com
  5. Approved: paul@vix.com
  6.  
  7. Submitted-By: davy@ecn.purdue.edu (David A. Curry)
  8. Posting-Number: Volume 26, Issue 159
  9. Archive-Name: parpd1.2/part01
  10.  
  11. This is PARPD 1.2, a Proxy-ARP daemon for Sun workstations running SunOS 4.1.x.
  12.  
  13. PARPD monitors all ethernet interfaces for ARP request packets requesting
  14. the address of a host on a different local subnet.  These are sent by hosts
  15. which either do not understand subnets, or are misconfigured.
  16.  
  17. PARPD responds to these packets with the address of the gateway host (the
  18. host PARPD is running on), allowing these hosts to send packets to the
  19. gateway (believing it's the host they want), and the gateway then forwards
  20. the packets as usual.  PARPD logs everything it does via syslog(3) so that
  21. misconfigured hosts can be detected and corrected.
  22.  
  23. PARPD does not require any configuration files; it reads the kernel routing
  24. tables and interface configuration data to determine what it should do.
  25.  
  26. PARPD has been running on Sun-3 and Sun-4 (SPARC) workstations under SunOS
  27. 4.1.1 here for a long time now.  At the time it was installed, we turned
  28. off all our in-kernel proxy arping code.  To date, we have experienced no
  29. problems, and have even had fun finding misconfigured hosts that we never
  30. knew about before.
  31.  
  32. PARPD requires SunOS 4.1.x because it makes use of the Network Interface Tap.
  33. It could probably be made to compile on SunOS 4.0.x with little difficulty,
  34. but the 4.0 NIT was pretty buggy, so no guarantees on how well it'll work.
  35. If you want to use PARPD on other operating systems, you'll have to write
  36. your own code to intercept ARP request packets, and put ARP reply packets
  37. back on the wire.
  38.  
  39.     Dave Curry
  40.     Purdue University
  41.     Engineering Computer Network
  42.     1285 Electrical Engineering Building
  43.     West Lafayette, IN 47907-1285
  44.     davy@ecn.purdue.edu
  45.  
  46. #! /bin/sh
  47. # This is a shell archive.  Remove anything before this line, then unpack
  48. # it by saving it into a file and typing "sh file".  To overwrite existing
  49. # files, type "sh file -c".  You can also feed this as standard input via
  50. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  51. # will see the following message at the end:
  52. #        "End of archive 1 (of 1)."
  53. # Contents:  MANIFEST Makefile arp.c if.c nit.c parpd.c parpd.h
  54. #   parpd.man route.c util.c
  55. # Wrapped by vixie@gw.home.vix.com on Wed Apr 14 10:47:39 1993
  56. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  57. if test -f 'MANIFEST' -a "${1}" != "-c" ; then 
  58.   echo shar: Will not clobber existing file \"'MANIFEST'\"
  59. else
  60. echo shar: Extracting \"'MANIFEST'\" \(424 characters\)
  61. sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
  62. X   File Name        Archive #    Description
  63. X-----------------------------------------------------------
  64. X MANIFEST                   1    This shipping list
  65. X Makefile                   1    
  66. X arp.c                      1    
  67. X if.c                       1    
  68. X nit.c                      1    
  69. X parpd.c                    1    
  70. X parpd.h                    1    
  71. X parpd.man                  1    
  72. X route.c                    1    
  73. X util.c                     1    
  74. END_OF_FILE
  75. if test 424 -ne `wc -c <'MANIFEST'`; then
  76.     echo shar: \"'MANIFEST'\" unpacked with wrong size!
  77. fi
  78. # end of 'MANIFEST'
  79. fi
  80. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  81.   echo shar: Will not clobber existing file \"'Makefile'\"
  82. else
  83. echo shar: Extracting \"'Makefile'\" \(891 characters\)
  84. sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  85. X#
  86. X# $Header: /usr/src/ecn/parpd/RCS/Makefile,v 1.1 92/05/08 08:43:07 davy Exp $
  87. X#
  88. X# Makefile for proxy arp daemon.
  89. X#
  90. X# David A. Curry
  91. X# Purdue University
  92. X# Engineering Computer Network
  93. X# 1285 Electrical Engineering Building
  94. X# West Lafayette, IN 47907
  95. X# davy@ecn.purdue.edu
  96. X#
  97. X# April, 1992
  98. X#
  99. X# $Log:    Makefile,v $
  100. X# Revision 1.1  92/05/08  08:43:07  davy
  101. X# Initial revision
  102. X# 
  103. X#
  104. X
  105. CFLAGS=    -O
  106. BINDIR=    /usr/ecn/etc
  107. MANDIR=    /usr/man/man8
  108. MANSUFFIX= 8
  109. X
  110. LIBS=    -lkvm
  111. X
  112. OBJS=    arp.o if.o nit.o parpd.o route.o util.o
  113. X
  114. in.parpd: $(OBJS)
  115. X    $(CC) -o in.parpd $(OBJS) $(LIBS)
  116. X
  117. install: in.parpd
  118. X    install -c -s -o root -g bin -m 755 in.parpd $(BINDIR)
  119. X
  120. install.man:
  121. X    install -c -m 444 parpd.man $(MANDIR)/in.parpd.$(MANSUFFIX)
  122. X
  123. clean:
  124. X    rm -f \#* a.out core in.parpd *.o
  125. X
  126. arp.o:        arp.c parpd.h
  127. if.o:        if.c parpd.h
  128. nit.o:        nit.c parpd.h
  129. parpd.o:    parpd.c parpd.h
  130. route.o:    route.c parpd.h
  131. util.o:        util.c parpd.h
  132. END_OF_FILE
  133. if test 891 -ne `wc -c <'Makefile'`; then
  134.     echo shar: \"'Makefile'\" unpacked with wrong size!
  135. fi
  136. # end of 'Makefile'
  137. fi
  138. if test -f 'arp.c' -a "${1}" != "-c" ; then 
  139.   echo shar: Will not clobber existing file \"'arp.c'\"
  140. else
  141. echo shar: Extracting \"'arp.c'\" \(6982 characters\)
  142. sed "s/^X//" >'arp.c' <<'END_OF_FILE'
  143. X#ifndef lint
  144. static char *RCSid = "$Header: /usr/src/ecn/parpd/RCS/arp.c,v 1.2 92/07/17 12:23:52 davy Exp $";
  145. X#endif
  146. X
  147. X/*
  148. X * arp.c - routines for handling arp packets
  149. X *
  150. X * David A. Curry
  151. X * Purdue University
  152. X * Engineering Computer Network
  153. X * 1285 Electrical Engineering Building
  154. X * West Lafayette, IN 47907
  155. X * davy@ecn.purdue.edu
  156. X *
  157. X * April, 1992
  158. X *
  159. X * $Log:    arp.c,v $
  160. X * Revision 1.2  92/07/17  12:23:52  davy
  161. X * ether_ntoa takes a pointer to a struct, not a struct
  162. X * 
  163. X * Revision 1.1  92/05/08  08:43:44  davy
  164. X * Initial revision
  165. X * 
  166. X */
  167. X#include <sys/param.h>
  168. X#include <sys/socket.h>
  169. X#include <netinet/in.h>
  170. X#include <arpa/inet.h>
  171. X#include <net/if.h>
  172. X#include <netinet/if_ether.h>
  173. X#include <sys/stropts.h>
  174. X#include <string.h>
  175. X#include <syslog.h>
  176. X#include <stdio.h>
  177. X
  178. X#include "parpd.h"
  179. X
  180. X/*
  181. X * Receive and process an ARP request packet.
  182. X */
  183. void
  184. arpRecvPacket(pkt, len, ifip)
  185. InterfaceInfo *ifip;
  186. char *pkt;
  187. int len;
  188. X{
  189. X    char src[32];
  190. X    ARPPacket ap;
  191. X    char *reason;
  192. X    struct in_addr srcaddr, dstaddr, tmpaddr;
  193. X
  194. X    /*
  195. X     * Copy the part of the packet we want.
  196. X     */
  197. X    bcopy(pkt, (caddr_t) &ap, sizeof(ARPPacket));
  198. X    ap.ap_len = len;
  199. X    epochPackets++;
  200. X    totalPackets++;
  201. X
  202. X    /*
  203. X     * Sanity checks.  Should never see these, except that for some
  204. X     * reason (probably a NIT bug), ARP requests sent by the local
  205. X     * host seem to fail the packet length check.  Fortunately, we
  206. X     * don't care about these anyway.
  207. X     */
  208. X    reason = NULL;
  209. X    len = sizeof(ap) - sizeof(ap.ap_len);
  210. X
  211. X    if (ap.ap_len < len)
  212. X        reason = "packet length";
  213. X    else if (ntohs(ap.ap_ethernet.ether_type) != htons(ETHERTYPE_ARP))
  214. X        reason = "packet type";
  215. X    else if (ap.ap_arp.arp_hrd != htons(ARPHRD_ETHER))
  216. X        reason = "hardware addr space";
  217. X    else if (ap.ap_arp.arp_pro != htons(ETHERTYPE_IP))
  218. X        reason = "protocol addr space";
  219. X    else if (ap.ap_arp.arp_op != htons(ARPOP_REQUEST))
  220. X        reason = "ARP opcode";
  221. X    else if (ap.ap_arp.arp_hln != 6)
  222. X        reason = "hardware addr length";
  223. X    else if (ap.ap_arp.arp_pln != 4)
  224. X        reason = "protocol addr length";
  225. X
  226. X    if (reason != NULL) {
  227. X        syslog(LOG_DEBUG, "%s: bad packet from %s (%s)",
  228. X               ifip->ifi_ifname,
  229. X               ether_ntoa(&ap.ap_ethernet.ether_shost),
  230. X               reason);
  231. X        badPackets++;
  232. X        return;
  233. X    }
  234. X
  235. X    /*
  236. X     * Copy stuff we need.
  237. X     */
  238. X    bcopy((caddr_t) ap.ap_arp.arp_spa, (caddr_t) &srcaddr,
  239. X          sizeof(struct in_addr));
  240. X    bcopy((caddr_t) ap.ap_arp.arp_tpa, (caddr_t) &dstaddr,
  241. X          sizeof(struct in_addr));
  242. X    strcpy(src, inet_ntoa(srcaddr));
  243. X
  244. X    /*
  245. X     * See if the request came from the local host.  If so, we
  246. X     * (obviously) shouldn't respond to it.
  247. X     */
  248. X    if (srcaddr.s_addr == ifip->ifi_hostaddr.sin_addr.s_addr) {
  249. X        syslog(LOG_DEBUG, "%s: ignore arp for %s from myself",
  250. X               ifip->ifi_ifname, inet_ntoa(dstaddr));
  251. X        return;
  252. X    }
  253. X              
  254. X    /*
  255. X     * See if the request is for a host on the same subnet as
  256. X     * the one we're on.  If it is, then we don't do anything,
  257. X     * and let the real host respond.
  258. X     */
  259. X    tmpaddr = utilGetSubNet(dstaddr, ifip->ifi_subnetmask.sin_addr);
  260. X
  261. X    if (tmpaddr.s_addr == ifip->ifi_subnetaddr.sin_addr.s_addr) {
  262. X        syslog(LOG_DEBUG, "%s: local network arp for %s from %s",
  263. X               ifip->ifi_ifname, inet_ntoa(dstaddr), src);
  264. X        return;
  265. X    }
  266. X
  267. X    /*
  268. X     * This must be a packet that concerns us in some way.
  269. X     */
  270. X    concernPackets++;
  271. X
  272. X    /*
  273. X     * See if the request is for a host on some other IP network
  274. X     * than the one we're on.  If so, the sending host is badly
  275. X     * confused, and we need to tell folks.  But, we can't do
  276. X     * anything to help this guy.
  277. X     */
  278. X    tmpaddr = utilGetIPNet(dstaddr);
  279. X
  280. X    if (tmpaddr.s_addr != ifip->ifi_ipnetaddr.sin_addr.s_addr) {
  281. X        /*
  282. X         * If this is a host we haven't seen before, print
  283. X         * a message.
  284. X         */
  285. X        if (utilAddHost(srcaddr, ifip)) {
  286. X            syslog(LOG_WARNING,
  287. X                   "%s: non-local ip network arp for %s from %s",
  288. X                   ifip->ifi_ifname, inet_ntoa(dstaddr), src);
  289. X        }
  290. X
  291. X        return;
  292. X    }
  293. X
  294. X    /*
  295. X     * Check to see if the destination is a broadcast address.
  296. X     * If so, we don't want to respond, but we should log the
  297. X     * request.
  298. X     */
  299. X    if (utilIsBroadcast(dstaddr, ifip)) {
  300. X        /*
  301. X         * If this is a host we haven't seen before, print
  302. X         * a message.
  303. X         */
  304. X        if (utilAddHost(srcaddr, ifip)) {
  305. X            syslog(LOG_WARNING,
  306. X                   "%s: arp for broadcast address (%s) from %s",
  307. X                   ifip->ifi_ifname, inet_ntoa(dstaddr), src);
  308. X        }
  309. X
  310. X        return;
  311. X    }
  312. X
  313. X    /*
  314. X     * If we've made it to this point, then the request is for a host
  315. X     * on the same IP network, but a different subnet, than the one
  316. X     * we're on.  This is where Proxy ARP comes in.
  317. X     *
  318. X     * If we haven't seen this host before, print a message.
  319. X     */
  320. X    if (utilAddHost(srcaddr, ifip)) {
  321. X        syslog(LOG_WARNING, "%s: non-local subnet arp for %s from %s",
  322. X               ifip->ifi_ifname, inet_ntoa(dstaddr), src);
  323. X    }
  324. X
  325. X    /*
  326. X     * See if we have a route to the host or network.  If we do,
  327. X     * we make sure that the route is *not* right back out the
  328. X     * same interface we got this packet on.  If that's the
  329. X     * case, then we are not the gateway for that route, and
  330. X     * should let the gateway respond instead.
  331. X     */
  332. X    if (routeHaveRoute(dstaddr, ifip)) {
  333. X        syslog(LOG_DEBUG, "we have a route and we're the gateway");
  334. X        arpSendPacket(&ap, ifip);
  335. X        return;
  336. X    }
  337. X
  338. X    /*
  339. X     * We don't have a route, or we're not the gateway.  So we
  340. X     * do nothing.
  341. X     */
  342. X    syslog(LOG_DEBUG, "we don't have a route or we're not the gateway");
  343. X    return;
  344. X}
  345. X
  346. X/*
  347. X * Send an ARP reply packet.
  348. X */
  349. void
  350. arpSendPacket(ap, ifip)
  351. InterfaceInfo *ifip;
  352. ARPPacket *ap;
  353. X{
  354. X    struct in_addr tmp;
  355. X
  356. X    /*
  357. X     * Destination of this one is the sender of the request.
  358. X     * Sender is us.
  359. X     */
  360. X    ap->ap_ethernet.ether_dhost = ap->ap_ethernet.ether_shost;
  361. X    ap->ap_ethernet.ether_shost = ifip->ifi_etheraddr;
  362. X    ap->ap_arp.arp_op = ARPOP_REPLY;
  363. X    
  364. X    /*
  365. X     * Swap the fields around.
  366. X     */
  367. X    bcopy((caddr_t) &ap->ap_arp.arp_sha, (caddr_t) &ap->ap_arp.arp_tha,
  368. X          sizeof(ap->ap_arp.arp_tha));
  369. X    bcopy((caddr_t) &ifip->ifi_etheraddr, (caddr_t) &ap->ap_arp.arp_sha,
  370. X          sizeof(ap->ap_arp.arp_sha));
  371. X
  372. X    bcopy((caddr_t) ap->ap_arp.arp_tpa, (caddr_t) &tmp,
  373. X          sizeof(struct in_addr));
  374. X    bcopy((caddr_t) ap->ap_arp.arp_spa, (caddr_t) ap->ap_arp.arp_tpa,
  375. X          sizeof(ap->ap_arp.arp_spa));
  376. X    bcopy((caddr_t) &tmp, (caddr_t) ap->ap_arp.arp_spa,
  377. X          sizeof(struct in_addr));
  378. X
  379. X    syslog(LOG_DEBUG, "send arp reply back to %s",
  380. X           ether_ntoa(&ap->ap_ethernet.ether_dhost));
  381. X
  382. X    /*
  383. X     * Send the packet.
  384. X     */
  385. X    arpWrite(ifip->ifi_fd, (caddr_t) ap, sizeof(*ap) - sizeof(ap->ap_len));
  386. X    replyPackets++;
  387. X}
  388. X
  389. X/*
  390. X * Actually put a packet on the wire.
  391. X */
  392. void
  393. arpWrite(fd, buf, len)
  394. int fd, len;
  395. char *buf;
  396. X{
  397. X    struct sockaddr sa;
  398. X    struct strbuf cbuf, dbuf;
  399. X    int offset = sizeof(sa.sa_data);
  400. X
  401. X    sa.sa_family = AF_UNSPEC;
  402. X    bcopy(buf, sa.sa_data, offset);
  403. X
  404. X    cbuf.maxlen = cbuf.len = sizeof(struct sockaddr);
  405. X    cbuf.buf = (caddr_t) &sa;
  406. X
  407. X    /*
  408. X     * NIT interface routines will put our ethernet header
  409. X     * back on.
  410. X     */
  411. X    dbuf.maxlen = dbuf.len = len - offset;
  412. X    dbuf.buf = buf + offset;
  413. X
  414. X    /*
  415. X     * Call the STREAMS write routine.
  416. X     */
  417. X    if (putmsg(fd, &cbuf, &dbuf, 0) < 0) {
  418. X        syslog(LOG_ERR, "putmsg: %m");
  419. X        exit(1);
  420. X    }
  421. X}
  422. END_OF_FILE
  423. if test 6982 -ne `wc -c <'arp.c'`; then
  424.     echo shar: \"'arp.c'\" unpacked with wrong size!
  425. fi
  426. # end of 'arp.c'
  427. fi
  428. if test -f 'if.c' -a "${1}" != "-c" ; then 
  429.   echo shar: Will not clobber existing file \"'if.c'\"
  430. else
  431. echo shar: Extracting \"'if.c'\" \(4326 characters\)
  432. sed "s/^X//" >'if.c' <<'END_OF_FILE'
  433. X#ifndef lint
  434. static char *RCSid = "$Header: /usr/src/ecn/parpd/RCS/if.c,v 1.1 92/05/08 08:43:48 davy Exp $";
  435. X#endif
  436. X
  437. X/*
  438. X * if.c - routines for dealing with network interfaces
  439. X *
  440. X * David A. Curry
  441. X * Purdue University
  442. X * Engineering Computer Network
  443. X * 1285 Electrical Engineering Building
  444. X * West Lafayette, IN 47907
  445. X * davy@ecn.purdue.edu
  446. X *
  447. X * April, 1992
  448. X *
  449. X * $Log:    if.c,v $
  450. X * Revision 1.1  92/05/08  08:43:48  davy
  451. X * Initial revision
  452. X * 
  453. X */
  454. X#include <sys/param.h>
  455. X#include <sys/socket.h>
  456. X#include <netinet/in.h>
  457. X#include <arpa/inet.h>
  458. X#include <sys/ioctl.h>
  459. X#include <net/if.h>
  460. X#include <netinet/if_ether.h>
  461. X#include <string.h>
  462. X#include <syslog.h>
  463. X#include <stdio.h>
  464. X
  465. X#include "parpd.h"
  466. X
  467. X/*
  468. X * Find all the network interfaces on this host.
  469. X */
  470. void
  471. ifGetInterfaces()
  472. X{
  473. X    int n, s;
  474. X    char buf[BUFSIZ];
  475. X    struct ifreq ifr;
  476. X    struct ifconf ifc;
  477. X    InterfaceInfo *ifip;
  478. X    struct sockaddr_in *sin;
  479. X    register struct ifreq *ifrp;
  480. X
  481. X    /*
  482. X     * Get a socket.
  483. X     */
  484. X    if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
  485. X        syslog(LOG_ERR, "ifGetInterfaces: socket: %m");
  486. X        exit(1);
  487. X    }
  488. X
  489. X    ifc.ifc_buf = buf;
  490. X    ifc.ifc_len = BUFSIZ;
  491. X
  492. X    /*
  493. X     * Get the list of interfaces.
  494. X     */
  495. X    if (ioctl(s, SIOCGIFCONF, (caddr_t) &ifc) < 0) {
  496. X        syslog(LOG_ERR, "ifGetInterfaces: SIOCGIFCONF: %m");
  497. X        exit(1);
  498. X    }
  499. X
  500. X    close(s);
  501. X
  502. X    ifrp = ifc.ifc_req;
  503. X
  504. X    /*
  505. X     * For each interface...
  506. X     */
  507. X    for (n = ifc.ifc_len/sizeof(struct ifreq); n > 0; n--, ifrp++) {
  508. X        /*
  509. X         * Copy the interface request answers.
  510. X         */
  511. X        bcopy((caddr_t) ifrp, (caddr_t) &ifr, sizeof(struct ifreq));
  512. X
  513. X        /*
  514. X         * Need another socket.
  515. X         */
  516. X        if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
  517. X            syslog(LOG_ERR, "ifGetInterfaces: socket: %m");
  518. X            exit(1);
  519. X        }
  520. X
  521. X        /*
  522. X         * Get the flags on this interface.
  523. X         */
  524. X        if (ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
  525. X            syslog(LOG_ERR, "ifGetInterfaces: SIOCGIFFLAGS: %m");
  526. X            exit(1);
  527. X        }
  528. X
  529. X        /*
  530. X         * We only want active broadcast interfaces that aren't
  531. X         * point-to-point and have an address resolution protcol.
  532. X         */
  533. X        if (((ifr.ifr_flags & IFF_UP) == 0) ||
  534. X            ((ifr.ifr_flags & IFF_NOARP) != 0) ||
  535. X            ((ifr.ifr_flags & IFF_LOOPBACK) != 0) ||
  536. X            ((ifr.ifr_flags & IFF_BROADCAST) == 0) ||
  537. X            ((ifr.ifr_flags & IFF_POINTOPOINT) != 0))
  538. X            continue;
  539. X
  540. X        /*
  541. X         * Allocate an interface structure.
  542. X         */
  543. X        if (interfaces == NULL) {
  544. X            interfaces = (InterfaceInfo *)
  545. X                utilSafeAlloc(sizeof(InterfaceInfo));
  546. X            ifip = interfaces;
  547. X        }
  548. X        else {
  549. X            ifip->ifi_next = (InterfaceInfo *)
  550. X                utilSafeAlloc(sizeof(InterfaceInfo));
  551. X            ifip = ifip->ifi_next;
  552. X        }
  553. X
  554. X        /*
  555. X         * Get the subnet mask for this interface.
  556. X         */
  557. X        if (ioctl(s, SIOCGIFNETMASK, (caddr_t) &ifr) < 0) {
  558. X            syslog(LOG_ERR, "ifGetInterfaces: SIOCGIFNETMASK: %m");
  559. X            exit(1);
  560. X        }
  561. X
  562. X        sin = (struct sockaddr_in *) &ifr.ifr_addr;
  563. X        ifip->ifi_subnetmask.sin_addr = sin->sin_addr;
  564. X
  565. X        /*
  566. X         * Get the subnet network address for this interface.
  567. X         */
  568. X        if (ioctl(s, SIOCGIFADDR, &ifr) < 0) {
  569. X            syslog(LOG_ERR, "ifGetInterfaces: SIOCGIFADDR: %m");
  570. X            exit(1);
  571. X        }
  572. X
  573. X        sin = (struct sockaddr_in *) &ifr.ifr_addr;
  574. X        close(s);
  575. X
  576. X        /*
  577. X         * Copy in all the information.
  578. X         */
  579. X        ifip->ifi_ifname = strdup(ifr.ifr_name);
  580. X        bcopy((caddr_t) sin, (caddr_t) &ifip->ifi_hostaddr,
  581. X              sizeof(struct sockaddr_in));
  582. X        ifip->ifi_ipnetaddr.sin_addr = utilGetIPNet(sin->sin_addr);
  583. X        ifip->ifi_ipnetmask.sin_addr = utilGetIPNetMask(sin->sin_addr);
  584. X        ifip->ifi_subnetaddr.sin_addr = utilGetSubNet(sin->sin_addr,
  585. X                            ifip->ifi_subnetmask.sin_addr);
  586. X
  587. X        /*
  588. X         * Convert stuff to character strings, so we
  589. X         * can print it out more easily.
  590. X         */
  591. X        ifip->ifi_ipnet =
  592. X            strdup(inet_ntoa(ifip->ifi_ipnetaddr.sin_addr));
  593. X        ifip->ifi_ipmask =
  594. X            strdup(inet_ntoa(ifip->ifi_ipnetmask.sin_addr));
  595. X        ifip->ifi_subnet =
  596. X            strdup(inet_ntoa(ifip->ifi_subnetaddr.sin_addr));
  597. X        ifip->ifi_submask =
  598. X            strdup(inet_ntoa(ifip->ifi_subnetmask.sin_addr));
  599. X
  600. X        syslog(LOG_DEBUG, "%s: ip %s ipmask %s sub %s submask %s",
  601. X               ifip->ifi_ifname, ifip->ifi_ipnet, ifip->ifi_ipmask,
  602. X               ifip->ifi_subnet, ifip->ifi_submask);
  603. X    }
  604. X}
  605. X
  606. X/*
  607. X * Search the list of interfaces for the one with the given name.
  608. X */
  609. InterfaceInfo *
  610. ifFindInterface(name)
  611. char *name;
  612. X{
  613. X    register InterfaceInfo *ifip;
  614. X
  615. X    for (ifip = interfaces; ifip != NULL; ifip = ifip->ifi_next) {
  616. X        if (strcmp(ifip->ifi_ifname, name) == 0)
  617. X            return(ifip);
  618. X    }
  619. X
  620. X    return(NULL);
  621. X}
  622. END_OF_FILE
  623. if test 4326 -ne `wc -c <'if.c'`; then
  624.     echo shar: \"'if.c'\" unpacked with wrong size!
  625. fi
  626. # end of 'if.c'
  627. fi
  628. if test -f 'nit.c' -a "${1}" != "-c" ; then 
  629.   echo shar: Will not clobber existing file \"'nit.c'\"
  630. else
  631. echo shar: Extracting \"'nit.c'\" \(3617 characters\)
  632. sed "s/^X//" >'nit.c' <<'END_OF_FILE'
  633. X#ifndef lint
  634. static char *RCSid = "$Header: /usr/src/ecn/parpd/RCS/nit.c,v 1.2 92/07/17 12:23:41 davy Exp $";
  635. X#endif
  636. X
  637. X/*
  638. X * nit.c - routines for setting up the network interface tap
  639. X *
  640. X * David A. Curry
  641. X * Purdue University
  642. X * Engineering Computer Network
  643. X * 1285 Electrical Engineering Building
  644. X * West Lafayette, IN 47907
  645. X * davy@ecn.purdue.edu
  646. X *
  647. X * April, 1992
  648. X *
  649. X * $Log:    nit.c,v $
  650. X * Revision 1.2  92/07/17  12:23:41  davy
  651. X * ether_ntoa takes a pointer to a struct, not a struct
  652. X * 
  653. X * Revision 1.1  92/05/08  08:43:52  davy
  654. X * Initial revision
  655. X * 
  656. X */
  657. X#include <sys/param.h>
  658. X#include <sys/socket.h>
  659. X#include <netinet/in.h>
  660. X#include <arpa/inet.h>
  661. X#include <sys/ioctl.h>
  662. X#include <sys/file.h>
  663. X#include <sys/time.h>
  664. X#include <net/if.h>
  665. X#include <netinet/if_ether.h>
  666. X#include <sys/stropts.h>
  667. X#include <net/nit_if.h>
  668. X#include <net/nit_pf.h>
  669. X#include <net/packetfilt.h>
  670. X#include <syslog.h>
  671. X#include <string.h>
  672. X#include <stdio.h>
  673. X
  674. X#include "parpd.h"
  675. X
  676. X/*
  677. X * Set up the network interface tap to receive packets from the given
  678. X * interface.
  679. X */
  680. int
  681. nitSetup(ifip)
  682. InterfaceInfo *ifip;
  683. X{
  684. X    int fd;
  685. X    ARPPacket ap;
  686. X    u_short offset;
  687. X    struct ifreq ifr;
  688. X    struct strioctl si;
  689. X    struct sockaddr *sad;
  690. X    struct packetfilt pf;
  691. X    register u_short *fwp;
  692. X
  693. X    /*
  694. X     * Open the tap.
  695. X     */
  696. X    if ((fd = open(NIT_DEV, O_RDWR)) < 0) {
  697. X        syslog(LOG_ERR, "nitSetup: open: %m");
  698. X        exit(1);
  699. X    }
  700. X
  701. X    /*
  702. X     * Arrange for discrete messages.
  703. X     */
  704. X    if (ioctl(fd, I_SRDOPT, (caddr_t) RMSGD) < 0) {
  705. X        syslog(LOG_ERR, "nitSetup: I_SRDOPT: %m");
  706. X        exit(1);
  707. X    }
  708. X
  709. X    /*
  710. X     * Push and configure the filtering module.
  711. X     */
  712. X    if (ioctl(fd, I_PUSH, "pf") < 0) {
  713. X        syslog(LOG_ERR, "nitSetup: I_PUSH: %m");
  714. X        exit(1);
  715. X    }
  716. X
  717. X    /*
  718. X     * Build the packet filter; we only want ARP-protocol
  719. X     * ethernet packets, and only ARP_REQUESTs from those.
  720. X     */
  721. X    fwp = pf.Pf_Filter;
  722. X
  723. X    offset = ((u_int) &ap.ap_ethernet.ether_type -
  724. X          (u_int) &ap.ap_ethernet.ether_dhost) / sizeof(u_short);
  725. X
  726. X    *fwp++ = ENF_PUSHWORD + offset;
  727. X    *fwp++ = ENF_PUSHLIT;
  728. X    *fwp++ = htons(ETHERTYPE_ARP);
  729. X    *fwp++ = ENF_EQ;
  730. X
  731. X    offset = (((u_int) &ap.ap_arp.arp_op - (u_int) &ap.ap_arp.arp_hrd) +
  732. X          sizeof(struct ether_header)) / sizeof(u_short);
  733. X
  734. X    *fwp++ = ENF_PUSHWORD + offset;
  735. X    *fwp++ = ENF_PUSHLIT;
  736. X    *fwp++ = htons(ARPOP_REQUEST);
  737. X    *fwp++ = ENF_EQ;
  738. X
  739. X    *fwp++ = ENF_AND;
  740. X
  741. X    pf.Pf_FilterLen = fwp - &pf.Pf_Filter[0];
  742. X    pf.Pf_Priority = 5;
  743. X
  744. X    si.ic_cmd = NIOCSETF;
  745. X    si.ic_timout = INFTIM;
  746. X    si.ic_dp = (caddr_t) &pf;
  747. X    si.ic_len = sizeof(struct packetfilt);
  748. X
  749. X    if (ioctl(fd, I_STR, (caddr_t) &si) < 0) {
  750. X        syslog(LOG_ERR, "nitSetup: NIOCSETF: %m");
  751. X        exit(1);
  752. X    }
  753. X
  754. X    /*
  755. X     * Bind the interface tap to the underlying interface.
  756. X     */
  757. X    strncpy(ifr.ifr_name, ifip->ifi_ifname, sizeof(ifr.ifr_name));
  758. X    ifr.ifr_name[sizeof(ifr.ifr_name)-1] = '\0';
  759. X
  760. X    si.ic_cmd = NIOCBIND;
  761. X    si.ic_timout = INFTIM;
  762. X    si.ic_dp = (caddr_t) 𝔦
  763. X    si.ic_len = sizeof(struct ifreq);
  764. X
  765. X    if (ioctl(fd, I_STR, (caddr_t) &si) < 0) {
  766. X        syslog(LOG_ERR, "nitSetup: NIOCBIND: %m");
  767. X        exit(1);
  768. X    }
  769. X
  770. X    /*
  771. X     * Get the interface's ethernet address.
  772. X     */
  773. X    if (ioctl(fd, SIOCGIFADDR, (caddr_t) &ifr) < 0) {
  774. X        syslog(LOG_ERR, "nitSetup: SIOCGIFADDR: %m");
  775. X        exit(1);
  776. X    }
  777. X
  778. X    /*
  779. X     * Copy the ethernet address.
  780. X     */
  781. X    sad = (struct sockaddr *) &ifr.ifr_addr;
  782. X    bcopy((struct ether_addr *) sad->sa_data, &ifip->ifi_etheraddr,
  783. X          sizeof(struct ether_addr));
  784. X    ifip->ifi_ether = strdup(ether_ntoa(&ifip->ifi_etheraddr));
  785. X
  786. X    syslog(LOG_DEBUG, "%s: ether %s", ifip->ifi_ifname, ifip->ifi_ether);
  787. X
  788. X    return(fd);    
  789. X}
  790. X
  791. X/*
  792. X * Flush all accumulated data.
  793. X */
  794. void
  795. nitFlush(fd)
  796. int fd;
  797. X{
  798. X    if (ioctl(fd, I_FLUSH, (caddr_t) FLUSHR) < 0) {
  799. X        syslog(LOG_ERR, "nitFlush: I_FLUSH: %m");
  800. X        exit(1);
  801. X    }
  802. X}
  803. END_OF_FILE
  804. if test 3617 -ne `wc -c <'nit.c'`; then
  805.     echo shar: \"'nit.c'\" unpacked with wrong size!
  806. fi
  807. # end of 'nit.c'
  808. fi
  809. if test -f 'parpd.c' -a "${1}" != "-c" ; then 
  810.   echo shar: Will not clobber existing file \"'parpd.c'\"
  811. else
  812. echo shar: Extracting \"'parpd.c'\" \(3481 characters\)
  813. sed "s/^X//" >'parpd.c' <<'END_OF_FILE'
  814. X#ifndef lint
  815. static char *RCSid = "$Header: /usr/src/ecn/parpd/RCS/parpd.c,v 1.1 92/05/08 08:43:57 davy Exp $";
  816. X#endif
  817. X
  818. X/*
  819. X * parpd - proxy arp daemon
  820. X *
  821. X * David A. Curry
  822. X * Purdue University
  823. X * Engineering Computer Network
  824. X * 1285 Electrical Engineering Building
  825. X * West Lafayette, IN 47907
  826. X * davy@ecn.purdue.edu
  827. X *
  828. X * April, 1992
  829. X *
  830. X * $Log:    parpd.c,v $
  831. X * Revision 1.1  92/05/08  08:43:57  davy
  832. X * Initial revision
  833. X * 
  834. X */
  835. X#include <sys/param.h>
  836. X#include <sys/socket.h>
  837. X#include <netinet/in.h>
  838. X#include <arpa/inet.h>
  839. X#include <sys/time.h>
  840. X#include <net/if.h>
  841. X#include <netinet/if_ether.h>
  842. X#include <syslog.h>
  843. X#include <signal.h>
  844. X#include <errno.h>
  845. X#include <stdio.h>
  846. X
  847. X#include "parpd.h"
  848. X
  849. int        badPackets = 0;        /* # of bad packets received    */
  850. int        replyPackets = 0;    /* # of arp reply packets sent    */
  851. int        totalPackets = 0;    /* # of packets received total    */
  852. int        epochPackets = 0;    /* # of packets over all time    */
  853. int        concernPackets = 0;    /* # of packets we care about    */
  854. X
  855. RouteInfo    *routes = NULL;        /* routing table        */
  856. InterfaceInfo    *interfaces = NULL;    /* list of network interfaces    */
  857. X
  858. extern int    errno;
  859. X
  860. main(argc, argv)
  861. char **argv;
  862. int argc;
  863. X{
  864. X    InterfaceInfo *ifip;
  865. X
  866. X    /*
  867. X     * Set up syslog.
  868. X     */
  869. X    openlog(*argv, LOG_PID, LOG_DAEMON);
  870. X    setlogmask(LOG_UPTO(LOG_WARNING));
  871. X
  872. X    /*
  873. X     * Process arguments.  The only one is debug mode.
  874. X     */
  875. X    while (--argc) {
  876. X        if (**++argv != '-')
  877. X            continue;
  878. X
  879. X        switch (*++*argv) {
  880. X        case 'd':
  881. X            setlogmask(LOG_UPTO(LOG_DEBUG));
  882. X            break;
  883. X        }
  884. X    }
  885. X
  886. X    /*
  887. X     * Gather interface information.
  888. X     */
  889. X    ifGetInterfaces();
  890. X
  891. X    /*
  892. X     * Set up the network interface tap for each interface.
  893. X     */
  894. X    for (ifip = interfaces; ifip != NULL; ifip = ifip->ifi_next) {
  895. X        if ((ifip->ifi_fd = nitSetup(ifip)) < 0) {
  896. X            syslog(LOG_ERR, "nitSetup: %s: %m", ifip->ifi_ifname);
  897. X            exit(1);
  898. X        }
  899. X    }
  900. X
  901. X    /*
  902. X     * Gather initial routing information.
  903. X     */
  904. X    routeGetRoutes();
  905. X
  906. X    /*
  907. X     * Set up signal handlers.
  908. X     */
  909. X    signal(SIGUSR1, utilDumpStats);
  910. X    signal(SIGUSR2, utilClearStats);
  911. X    signal(SIGALRM, routeUpdateRoutes);
  912. X
  913. X    alarm(ROUTE_UPDATE);
  914. X
  915. X    /*
  916. X     * Never returns.
  917. X     */
  918. X    parpdMainLoop();
  919. X}
  920. X
  921. X/*
  922. X * Main loop.  Never returns.
  923. X */
  924. void
  925. parpdMainLoop()
  926. X{
  927. X    fd_set readfds;
  928. X    register int cc;
  929. X    char buf[NIT_BUFSIZE];
  930. X    register InterfaceInfo *ifip;
  931. X
  932. X    /*
  933. X     * Flush any junk that's accumlated while we've been setting up.
  934. X     */
  935. X    for (ifip = interfaces; ifip != NULL; ifip = ifip->ifi_next)
  936. X        nitFlush(ifip->ifi_fd);
  937. X
  938. X    /*
  939. X     * For ever...
  940. X     */
  941. X    for (;;) {
  942. X        FD_ZERO(&readfds);
  943. X
  944. X        /*
  945. X         * Set up the bits for select.
  946. X         */
  947. X        for (ifip = interfaces; ifip != NULL; ifip = ifip->ifi_next)
  948. X            FD_SET(ifip->ifi_fd, &readfds);
  949. X
  950. X        /*
  951. X         * Wait for something to arrive on an interface.
  952. X         */
  953. X        cc = select(NFDBITS, &readfds, (fd_set *) 0, (fd_set *) 0,
  954. X                (struct timeval *) 0);
  955. X
  956. X        /*
  957. X         * Interrupted syscall (routing update or user signal).
  958. X         */
  959. X        if ((cc < 0) && (errno != EINTR)) {
  960. X            syslog(LOG_ERR, "select: %m");
  961. X            exit(1);
  962. X        }
  963. X
  964. X        if (cc <= 0)
  965. X            continue;
  966. X
  967. X        /*
  968. X         * Check the interfaces.
  969. X         */
  970. X        for (ifip = interfaces; ifip != NULL; ifip = ifip->ifi_next) {
  971. X            /*
  972. X             * Anything to read?
  973. X             */
  974. X            if (!FD_ISSET(ifip->ifi_fd, &readfds))
  975. X                continue;
  976. X
  977. X            /*
  978. X             * Read it.
  979. X             */
  980. X            if ((cc = read(ifip->ifi_fd, buf, NIT_BUFSIZE)) <= 0)
  981. X                continue;
  982. X
  983. X            /*
  984. X             * Interrupted syscall.
  985. X             */
  986. X            if ((cc < 0) && (errno != EINTR)) {
  987. X                syslog(LOG_ERR, "read: %m");
  988. X                exit(1);
  989. X            }
  990. X
  991. X            if (cc <= 0)
  992. X                continue;
  993. X
  994. X            /*
  995. X             * Process the packet.
  996. X             */
  997. X            arpRecvPacket(buf, cc, ifip);
  998. X        }
  999. X    }
  1000. X}
  1001. END_OF_FILE
  1002. if test 3481 -ne `wc -c <'parpd.c'`; then
  1003.     echo shar: \"'parpd.c'\" unpacked with wrong size!
  1004. fi
  1005. # end of 'parpd.c'
  1006. fi
  1007. if test -f 'parpd.h' -a "${1}" != "-c" ; then 
  1008.   echo shar: Will not clobber existing file \"'parpd.h'\"
  1009. else
  1010. echo shar: Extracting \"'parpd.h'\" \(3113 characters\)
  1011. sed "s/^X//" >'parpd.h' <<'END_OF_FILE'
  1012. X/*
  1013. X * $Header: /usr/src/ecn/parpd/RCS/parpd.h,v 1.1 92/05/08 08:44:01 davy Exp $
  1014. X *
  1015. X * parpd.h - proxy arp daemon definitions
  1016. X *
  1017. X * David A. Curry
  1018. X * Purdue University
  1019. X * Engineering Computer Network
  1020. X * 1285 Electrical Engineering Building
  1021. X * West Lafayette, IN 47907
  1022. X * davy@ecn.purdue.edu
  1023. X *
  1024. X * April, 1992
  1025. X *
  1026. X * $Log:    parpd.h,v $
  1027. X * Revision 1.1  92/05/08  08:44:01  davy
  1028. X * Initial revision
  1029. X * 
  1030. X */
  1031. X#define PATCHLEVEL    1.0
  1032. X
  1033. X#define NIT_DEV        "/dev/nit"    /* name of network interf tap    */
  1034. X#define NIT_BUFSIZE    8192        /* max packet size to receive    */
  1035. X#define ROUTE_UPDATE    180        /* update routes this often    */
  1036. X
  1037. X/*
  1038. X * An ARP packet.
  1039. X */
  1040. typedef struct _ap {
  1041. X    struct ether_header    ap_ethernet;    /* ethernet header    */
  1042. X    struct ether_arp    ap_arp;        /* arp packet        */
  1043. X    int            ap_len;        /* internal use only    */
  1044. X} ARPPacket;
  1045. X
  1046. X/*
  1047. X * A host record, for keeping track of which hosts we've "helped".
  1048. X */
  1049. typedef struct _hr {
  1050. X    struct in_addr         hr_address;    /* address of host    */
  1051. X
  1052. X    int             hr_refcnt;    /* how many times helped*/
  1053. X
  1054. X    struct _hr        *hr_next;    /* next entry in list    */
  1055. X} HostRecord;
  1056. X
  1057. X/*
  1058. X * An interface information record, for keeping track of the interfaces
  1059. X * we are receiving packets from.
  1060. X */
  1061. typedef struct _ifi {
  1062. X    int             ifi_fd;    /* nit file descriptor    */
  1063. X
  1064. X    char            *ifi_ifname;    /* interface name    */
  1065. X
  1066. X    struct sockaddr_in     ifi_hostaddr;    /* host ip address    */
  1067. X
  1068. X    char            *ifi_ether;    /* ether addr (string)    */
  1069. X    struct ether_addr     ifi_etheraddr;    /* ethernet address    */
  1070. X
  1071. X    char            *ifi_ipnet;    /* ip network (string)    */
  1072. X    char            *ifi_ipmask;    /* ip netmask (string)    */
  1073. X    struct sockaddr_in     ifi_ipnetaddr;    /* ip network address    */
  1074. X    struct sockaddr_in     ifi_ipnetmask;    /* ip network mask    */
  1075. X
  1076. X    char            *ifi_subnet;    /* subnet (string)    */
  1077. X    char            *ifi_submask;    /* subnet mask (string) */
  1078. X    struct sockaddr_in     ifi_subnetaddr; /* subnet address    */
  1079. X    struct sockaddr_in     ifi_subnetmask; /* subnet mask        */
  1080. X
  1081. X    HostRecord        *ifi_hostlist;    /* helped hosts on net    */
  1082. X
  1083. X    struct _ifi        *ifi_next;    /* pointer to next    */
  1084. X} InterfaceInfo;
  1085. X
  1086. X/*
  1087. X * A route information record, for keeping track of network routing.
  1088. X */
  1089. typedef struct _ri {
  1090. X    short             ri_hostroute;    /* 1 if a host route    */
  1091. X
  1092. X    char            *ri_dstnet;    /* dest net (string)    */
  1093. X    struct sockaddr_in     ri_dstnetaddr;    /* destination net    */
  1094. X
  1095. X    InterfaceInfo        *ri_interface;    /* interface of route    */
  1096. X
  1097. X    struct _ri        *ri_next;    /* pointer to next    */
  1098. X} RouteInfo;
  1099. X
  1100. extern InterfaceInfo        *interfaces;
  1101. X
  1102. extern RouteInfo        *routes;
  1103. X
  1104. extern int            concernPackets;
  1105. extern int            epochPackets;
  1106. extern int            totalPackets;
  1107. extern int            replyPackets;
  1108. extern int            badPackets;
  1109. X
  1110. InterfaceInfo            *ifFindInterface();
  1111. X
  1112. struct in_addr            utilGetIPNetMask();
  1113. struct in_addr            utilGetSubNet();
  1114. struct in_addr            utilGetIPNet();
  1115. X
  1116. char                *utilSafeAlloc();
  1117. char                *ether_ntoa();
  1118. X
  1119. int                utilIsBroadcast();
  1120. int                routeHaveRoute();
  1121. int                utilAddHost();
  1122. int                nitSetup();
  1123. X
  1124. void                routeUpdateRoutes();
  1125. void                ifGetInterfaces();
  1126. void                routeFreeRoutes();
  1127. void                routeGetRoutes();
  1128. void                utilClearStats();
  1129. void                arpRecvPacket();
  1130. void                arpSendPacket();
  1131. void                parpdMainLoop();
  1132. void                utilDumpStats();
  1133. void                arpWrite();
  1134. void                nitFlush();
  1135. END_OF_FILE
  1136. if test 3113 -ne `wc -c <'parpd.h'`; then
  1137.     echo shar: \"'parpd.h'\" unpacked with wrong size!
  1138. fi
  1139. # end of 'parpd.h'
  1140. fi
  1141. if test -f 'parpd.man' -a "${1}" != "-c" ; then 
  1142.   echo shar: Will not clobber existing file \"'parpd.man'\"
  1143. else
  1144. echo shar: Extracting \"'parpd.man'\" \(5257 characters\)
  1145. sed "s/^X//" >'parpd.man' <<'END_OF_FILE'
  1146. X.TH IN.PARPD 8 "1 May 1992" "ECN"
  1147. X.SH NAME
  1148. in.parpd \- Proxy ARP daemon
  1149. X.SH SYNOPSIS
  1150. X.B in.parpd
  1151. X[
  1152. X.B \-d
  1153. X]
  1154. X.SH DESCRIPTION
  1155. X.PP
  1156. X.B in.parpd
  1157. implements the ``Proxy ARP'' protocol as described in RFC1027.
  1158. X.PP
  1159. Some hosts with out-of-date implementations of the Internet protocols do not
  1160. understand IP subnetting as specified in RFC950.
  1161. XFor example,
  1162. in the case of a subnetted Class B network,
  1163. these hosts believe that any host whose Internet address is on the Class B
  1164. network must be on the local network cable,
  1165. and they will issue ARP requests for the ethernet address of any host with
  1166. the same Class B address.
  1167. Since most of these hosts are actually on different subnets,
  1168. they will never see the ARP request (and hence never respond to it),
  1169. meaning that the out-of-date host will not be able to talk to any host not
  1170. actually connected to the same cable.
  1171. X.PP
  1172. Proxy ARP enables a gateway to help out these out-of-date hosts by lying to
  1173. the confused host.
  1174. This is done by sending an ARP reply packet with the gateway's ethernet
  1175. address for any host not on the local subnet.
  1176. The out-of-date host will send its traffic to the gateway (thinking that
  1177. the gateway is the destination),
  1178. and the gateway will forward the packet just as it forwards any other.
  1179. X.PP
  1180. X.BR in.parpd ,
  1181. when invoked,
  1182. probes for all active ethernet interfaces on the host.
  1183. XFor each interface found,
  1184. X.B in.parpd
  1185. will configure the Network Interface Tap
  1186. X(see
  1187. X.BR nit (4P))
  1188. to receive any ARP requests arriving on that interface.
  1189. When an ARP request arrives,
  1190. X.B in.parpd
  1191. processes it as follows:
  1192. X.IP \(bu
  1193. Several sanity checks are performed on the packet.
  1194. If any of these checks fail,
  1195. the packet is silently discarded.
  1196. X.IP \(bu
  1197. If the request came from the host
  1198. X.B in.parpd
  1199. is running on,
  1200. it is ignored.
  1201. X.IP \(bu
  1202. If the request is for the address of a host on the local subnet,
  1203. it is ignored,
  1204. allowing the real host to respond.
  1205. X.IP \(bu
  1206. If the request is for a host on some other IP network than the local network,
  1207. a message is sent to
  1208. X.BR syslogd (8)
  1209. at the LOG_WARNING level.
  1210. Because the host which sent this packet is badly confused,
  1211. X.B in.parpd
  1212. can do nothing to help it,
  1213. so the packet is ignored.
  1214. X.IP \(bu
  1215. If the request is for a broadcast address,
  1216. a message is sent to
  1217. X.BR syslogd (8)
  1218. at the LOG_WARNING level.
  1219. Both the IP broadcast and the subnet broadcast are checked for,
  1220. in both ``all ones'' and ``all zeros'' formats.
  1221. Because there is no appropriate response to an ARP for the broadcast address,
  1222. the packet is ignored.
  1223. X.IP \(bu
  1224. Having made it this far,
  1225. the request is known to be for a host on a different subnet.
  1226. A message is sent to
  1227. X.BR syslogd (8)
  1228. at the LOG_WARNING level detailing this.
  1229. X.IP \(bu
  1230. If the local host has a route to the subnet in the ARP request,
  1231. and the route goes through a different interface than the one on which the
  1232. ARP request was received,
  1233. an ARP response with the local host's ethernet address is generated.
  1234. If the local host does not have a route to the subnet,
  1235. or if the route is out the same interface on which the request was received,
  1236. no response is generated,
  1237. since there is a more appropriate gateway that should respond instead.
  1238. X.PP
  1239. As mentioned above,
  1240. when a ``confused'' host is detected,
  1241. a message is sent to
  1242. X.BR syslogd (8)
  1243. at the LOG_WARNING level.
  1244. X.B in.parpd
  1245. maintains a record of which hosts have been identified via these messages,
  1246. and will only identify a host the first time it is detected.
  1247. This allows confused hosts to be noticed each time
  1248. X.B in.parpd
  1249. is started,
  1250. but prevents volumes of messages being printed for ``confused but okay''
  1251. hosts which cannot be fixed.
  1252. X.PP
  1253. If the
  1254. X.B in.parpd
  1255. process is sent a
  1256. X.B SIGUSR1
  1257. signal,
  1258. it will dump several packet counters,
  1259. and a list of all ``confused'' hosts it has detected.
  1260. This is done by sending messages to
  1261. X.BR syslogd (8)
  1262. at the LOG_INFO level.
  1263. If the
  1264. X.B in.parpd
  1265. process is sent a
  1266. X.B SIGUSR2
  1267. signal,
  1268. it will clear the packet counters and the list of ``confused'' hosts it has
  1269. detected.
  1270. A message is sent to
  1271. X.BR syslogd (8)
  1272. at the LOG_NOTICE level when this occurs.
  1273. This feature can be used to clear
  1274. X.BR in.parpd 's
  1275. memory after fixing a broken host,
  1276. for example.
  1277. X.PP
  1278. X.B in.parpd
  1279. does not need to be told about network configurations,
  1280. as it examines the kernel routing tables to obtain information about what
  1281. networks are accessible from the current host.
  1282. The routing tables are examined once every three minutes;
  1283. this time can be changed by editing the file
  1284. X.I parpd.h
  1285. and recompiling.
  1286. X.PP
  1287. If invoked with the
  1288. X.B \-d
  1289. option,
  1290. X.B in.parpd
  1291. will send debugging output to
  1292. X.BR syslogd (8)
  1293. at the LOG_DEBUG level.
  1294. This output can be quite voluminous;
  1295. it includes two lines about each interface at startup,
  1296. a dump of the routing table every time it is obtained,
  1297. and one or more lines about each ARP request packet received.
  1298. X.SH SEE ALSO
  1299. X.BR nit (4P),
  1300. X.BR syslogd (8),
  1301. X.I "An Ethernet Address Resolution Protocol"
  1302. X(RFC826),
  1303. X.I "Internet Standard Subnetting Procedure"
  1304. X(RFC950),
  1305. X.I "Using ARP to Implement Transparent Subnet Gateways"
  1306. X(RFC1027)
  1307. X.SH BUGS
  1308. X.PP
  1309. If vendors would get their acts together,
  1310. this software would be unnecessary.
  1311. X.SH AUTHOR
  1312. X.PP
  1313. David A. Curry, Purdue University Engineering Computer Network,
  1314. X1285 Electrical Engineering Building,
  1315. West Lafayette, IN 47907,
  1316. davy@ecn.purdue.edu.
  1317. END_OF_FILE
  1318. if test 5257 -ne `wc -c <'parpd.man'`; then
  1319.     echo shar: \"'parpd.man'\" unpacked with wrong size!
  1320. fi
  1321. # end of 'parpd.man'
  1322. fi
  1323. if test -f 'route.c' -a "${1}" != "-c" ; then 
  1324.   echo shar: Will not clobber existing file \"'route.c'\"
  1325. else
  1326. echo shar: Extracting \"'route.c'\" \(5785 characters\)
  1327. sed "s/^X//" >'route.c' <<'END_OF_FILE'
  1328. X#ifndef lint
  1329. static char *RCSid = "$Header: /usr/src/ecn/parpd/RCS/route.c,v 1.2 92/07/16 14:33:11 davy Exp $";
  1330. X#endif
  1331. X
  1332. X/*
  1333. X * route.c - routines for dealing with routes
  1334. X *
  1335. X * David A. Curry
  1336. X * Purdue University
  1337. X * Engineering Computer Network
  1338. X * 1285 Electrical Engineering Building
  1339. X * West Lafayette, IN 47907
  1340. X * davy@ecn.purdue.edu
  1341. X *
  1342. X * April, 1992
  1343. X *
  1344. X * $Log:    route.c,v $
  1345. X * Revision 1.2  92/07/16  14:33:11  davy
  1346. X * Fixed a bug with a pointer pointing out in space.
  1347. X * 
  1348. X * Revision 1.1  92/05/08  08:44:09  davy
  1349. X * Initial revision
  1350. X * 
  1351. X */
  1352. X#include <sys/param.h>
  1353. X#include <sys/socket.h>
  1354. X#include <netinet/in.h>
  1355. X#include <arpa/inet.h>
  1356. X#include <sys/ioctl.h>
  1357. X#include <net/route.h>
  1358. X#include <sys/file.h>
  1359. X#include <sys/mbuf.h>
  1360. X#include <net/if.h>
  1361. X#include <netinet/if_ether.h>
  1362. X#include <syslog.h>
  1363. X#include <string.h>
  1364. X#include <stdio.h>
  1365. X#include <nlist.h>
  1366. X#include <kvm.h>
  1367. X
  1368. X#include "parpd.h"
  1369. X
  1370. X/*
  1371. X * For reading routes from the kernel.
  1372. X */
  1373. static struct nlist nl[] = {
  1374. X#define N_RTHASHSIZE    0
  1375. X    { "_rthashsize" },
  1376. X#define N_RTHOST    1
  1377. X    { "_rthost" },
  1378. X#define N_RTNET        2
  1379. X    { "_rtnet" },
  1380. X    { "" }
  1381. X};
  1382. X
  1383. void
  1384. routeGetRoutes()
  1385. X{
  1386. X    int hashsize;
  1387. X    struct mbuf mb;
  1388. X    register int i;
  1389. X    struct ifnet ifn;
  1390. X    int firstpass = 1;
  1391. X    struct in_addr ina;
  1392. X    RouteInfo ri, *rip;
  1393. X    char buf[16], name[16];
  1394. X    struct sockaddr_in *sin;
  1395. X    struct mbuf **routehash;
  1396. X    static kvm_t *kd = NULL;
  1397. X    register struct mbuf *m;
  1398. X    register struct rtentry *rt;
  1399. X
  1400. X    /*
  1401. X     * Open the kernel and get some addresses.
  1402. X     */
  1403. X    if (kd == NULL) {
  1404. X        kd = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL);
  1405. X
  1406. X        if (kd == NULL) {
  1407. X            syslog(LOG_ERR, "routeGetRoutes: kvm_open: %m");
  1408. X            exit(1);
  1409. X        }
  1410. X
  1411. X        if (kvm_nlist(kd, nl) < 0) {
  1412. X            syslog(LOG_ERR, "routeGetRoutes: no namelist");
  1413. X            exit(1);
  1414. X        }
  1415. X    }
  1416. X
  1417. X    kvm_read(kd, nl[N_RTHASHSIZE].n_value, &hashsize, sizeof(int));
  1418. X
  1419. X    routehash = (struct mbuf **)
  1420. X        utilSafeAlloc(hashsize * sizeof(struct mbuf *));
  1421. X
  1422. X    kvm_read(kd, nl[N_RTHOST].n_value, routehash,
  1423. X         hashsize * sizeof(struct mbuf *));
  1424. X
  1425. X    bzero((caddr_t) &ri, sizeof(RouteInfo));
  1426. X
  1427. again:
  1428. X    /*
  1429. X     * For each route...
  1430. X     */
  1431. X    for (i=0; i < hashsize; i++) {
  1432. X        if (routehash[i] == 0)
  1433. X            continue;
  1434. X
  1435. X        m = routehash[i];
  1436. X
  1437. X        /*
  1438. X         * For each route...
  1439. X         */
  1440. X        while (m != NULL) {
  1441. X            kvm_read(kd, m, &mb, sizeof(struct mbuf));
  1442. X            rt = mtod(&mb, struct rtentry *);
  1443. X            ri.ri_hostroute = 0;
  1444. X
  1445. X            if (((unsigned) rt < (unsigned) &mb) ||
  1446. X                ((unsigned) rt >= (unsigned) (&mb+1))) {
  1447. X                syslog(LOG_ERR, "routeGetRoutes: bad table");
  1448. X                exit(1);
  1449. X            }
  1450. X
  1451. X            /*
  1452. X             * Don't care about non-Internet routes.
  1453. X             */
  1454. X            if (rt->rt_dst.sa_family != AF_INET) {
  1455. X                m = mb.m_next;
  1456. X                continue;
  1457. X            }
  1458. X
  1459. X            /*
  1460. X             * Don't care about routes with no interface.
  1461. X             */
  1462. X            if (rt->rt_ifp == NULL) {
  1463. X                m = mb.m_next;
  1464. X                continue;
  1465. X            }
  1466. X
  1467. X            /*
  1468. X             * Copy some of the information.
  1469. X             */
  1470. X            sin = (struct sockaddr_in *) &rt->rt_dst;
  1471. X            bcopy((caddr_t) sin, (caddr_t) &ri.ri_dstnetaddr,
  1472. X                  sizeof(struct sockaddr_in));
  1473. X
  1474. X            ri.ri_dstnet =
  1475. X                strdup(inet_ntoa(ri.ri_dstnetaddr.sin_addr));
  1476. X
  1477. X            /*
  1478. X             * Is it a host route?
  1479. X             */
  1480. X            if (rt->rt_flags & RTF_HOST)
  1481. X                ri.ri_hostroute = 1;
  1482. X
  1483. X            /*
  1484. X             * Get the interface name.
  1485. X             */
  1486. X            kvm_read(kd, rt->rt_ifp, &ifn, sizeof(struct ifnet));
  1487. X            kvm_read(kd, ifn.if_name, buf, sizeof(buf));
  1488. X            sprintf(name, "%s%d", buf, ifn.if_unit);
  1489. X
  1490. X            ri.ri_interface = ifFindInterface(name);
  1491. X
  1492. X            /*
  1493. X             * If we didn't find the interface, we don't
  1494. X             * care about this route.
  1495. X             */
  1496. X            if (ri.ri_interface == NULL) {
  1497. X                free(ri.ri_dstnet);
  1498. X                m = mb.m_next;
  1499. X                continue;
  1500. X            }
  1501. X
  1502. X            /*
  1503. X             * If this route is not for the same IP network
  1504. X             * we're on, we don't need it.
  1505. X             */
  1506. X            ina = utilGetIPNet(ri.ri_dstnetaddr.sin_addr);
  1507. X
  1508. X            if (ri.ri_interface->ifi_ipnetaddr.sin_addr.s_addr !=
  1509. X                ina.s_addr) {
  1510. X                syslog(LOG_DEBUG, "%s: non-local %sroute: %s",
  1511. X                       ri.ri_interface->ifi_ifname,
  1512. X                       ri.ri_hostroute ? "host " : "net  ",
  1513. X                       ri.ri_dstnet);
  1514. X                free(ri.ri_dstnet);
  1515. X                m = mb.m_next;
  1516. X                continue;
  1517. X            }
  1518. X
  1519. X            /*
  1520. X             * Allocate a route entry.
  1521. X             */
  1522. X            if (routes == NULL) {
  1523. X                routes = (RouteInfo *)
  1524. X                    utilSafeAlloc(sizeof(RouteInfo));
  1525. X                rip = routes;
  1526. X            }
  1527. X            else {
  1528. X                rip->ri_next = (RouteInfo *)
  1529. X                    utilSafeAlloc(sizeof(RouteInfo));
  1530. X                rip = rip->ri_next;
  1531. X            }
  1532. X
  1533. X            /*
  1534. X             * Copy the info.
  1535. X             */
  1536. X            bcopy((caddr_t) &ri, (caddr_t) rip,
  1537. X                  sizeof(RouteInfo));
  1538. X
  1539. X            syslog(LOG_DEBUG, "%s: %sroute: %s",
  1540. X                   rip->ri_interface->ifi_ifname,
  1541. X                   rip->ri_hostroute ? "host " : "net  ",
  1542. X                   rip->ri_dstnet);
  1543. X
  1544. X            m = mb.m_next;
  1545. X        }
  1546. X    }
  1547. X
  1548. X    /*
  1549. X     * Still got more stuff to get.
  1550. X     */
  1551. X    if (firstpass) {
  1552. X        kvm_read(kd, nl[N_RTNET].n_value, routehash,
  1553. X             hashsize * sizeof(struct mbuf *));
  1554. X        firstpass = 0;
  1555. X        goto again;
  1556. X    }
  1557. X
  1558. X    free(routehash);
  1559. X}
  1560. X
  1561. X/*
  1562. X * See if we have a route to dst on interface ifip.
  1563. X */
  1564. int
  1565. routeHaveRoute(dst, ifip)
  1566. InterfaceInfo *ifip;
  1567. struct in_addr dst;
  1568. X{
  1569. X    struct in_addr tmp;
  1570. X    register RouteInfo *rip;
  1571. X
  1572. X    tmp = utilGetSubNet(dst, ifip->ifi_subnetmask.sin_addr);
  1573. X
  1574. X    for (rip = routes; rip != NULL; rip = rip->ri_next) {
  1575. X        /*
  1576. X         * Not interested in routes out the incoming
  1577. X         * interface.
  1578. X         */
  1579. X        if (rip->ri_interface == ifip)
  1580. X            continue;
  1581. X
  1582. X        /*
  1583. X         * Do we have a route?
  1584. X         */
  1585. X        if (rip->ri_hostroute) {
  1586. X            if (dst.s_addr == rip->ri_dstnetaddr.sin_addr.s_addr)
  1587. X                return(1);
  1588. X        }
  1589. X        else {
  1590. X            if (tmp.s_addr == rip->ri_dstnetaddr.sin_addr.s_addr)
  1591. X                return(1);
  1592. X        }
  1593. X    }
  1594. X
  1595. X    return(0);
  1596. X}
  1597. X
  1598. X/*
  1599. X * Free the current list of routes.
  1600. X */
  1601. void
  1602. routeFreeRoutes()
  1603. X{
  1604. X    register RouteInfo *rip, *nrip;
  1605. X
  1606. X    for (rip = routes; rip != NULL; rip = nrip) {
  1607. X        free(rip->ri_dstnet);
  1608. X        nrip = rip->ri_next;
  1609. X        free(rip);
  1610. X    }
  1611. X
  1612. X    routes = NULL;
  1613. X}
  1614. X
  1615. X/*
  1616. X * Update the list of routes.
  1617. X */
  1618. void
  1619. routeUpdateRoutes()
  1620. X{
  1621. X    alarm(0);
  1622. X
  1623. X    syslog(LOG_DEBUG, "get routing update");
  1624. X
  1625. X    routeFreeRoutes();
  1626. X    routeGetRoutes();
  1627. X
  1628. X    alarm(ROUTE_UPDATE);
  1629. X}
  1630. END_OF_FILE
  1631. if test 5785 -ne `wc -c <'route.c'`; then
  1632.     echo shar: \"'route.c'\" unpacked with wrong size!
  1633. fi
  1634. # end of 'route.c'
  1635. fi
  1636. if test -f 'util.c' -a "${1}" != "-c" ; then 
  1637.   echo shar: Will not clobber existing file \"'util.c'\"
  1638. else
  1639. echo shar: Extracting \"'util.c'\" \(5112 characters\)
  1640. sed "s/^X//" >'util.c' <<'END_OF_FILE'
  1641. X#ifndef lint
  1642. static char *RCSid = "$Header: /usr/src/ecn/parpd/RCS/util.c,v 1.1 92/05/08 08:44:12 davy Exp $";
  1643. X#endif
  1644. X
  1645. X/*
  1646. X * util.c - utility routines
  1647. X *
  1648. X * David A. Curry
  1649. X * Purdue University
  1650. X * Engineering Computer Network
  1651. X * 1285 Electrical Engineering Building
  1652. X * West Lafayette, IN 47907
  1653. X * davy@ecn.purdue.edu
  1654. X *
  1655. X * April, 1992
  1656. X *
  1657. X * $Log:    util.c,v $
  1658. X * Revision 1.1  92/05/08  08:44:12  davy
  1659. X * Initial revision
  1660. X * 
  1661. X */
  1662. X#include <sys/param.h>
  1663. X#include <sys/socket.h>
  1664. X#include <netinet/in.h>
  1665. X#include <arpa/inet.h>
  1666. X#include <net/if.h>
  1667. X#include <netinet/if_ether.h>
  1668. X#include <string.h>
  1669. X#include <syslog.h>
  1670. X#include <stdio.h>
  1671. X#include <netdb.h>
  1672. X
  1673. X#include "parpd.h"
  1674. X
  1675. X/*
  1676. X * Allocate memory with error checking.
  1677. X */
  1678. char *
  1679. utilSafeAlloc(size)
  1680. int size;
  1681. X{
  1682. X    char *malloc();
  1683. X    register char *p;
  1684. X
  1685. X    if ((p = malloc(size)) == NULL) {
  1686. X        syslog(LOG_ERR, "utilSafeAlloc: out of memory");
  1687. X        exit(1);
  1688. X    }
  1689. X
  1690. X    bzero(p, size);
  1691. X    return(p);
  1692. X}
  1693. X
  1694. X/*
  1695. X * Get the IP network mask for a given address.
  1696. X */
  1697. struct in_addr
  1698. utilGetIPNetMask(in)
  1699. struct in_addr in;
  1700. X{
  1701. X    struct in_addr ina;
  1702. X    register u_long mask;
  1703. X    register u_long i = ntohl(in.s_addr);
  1704. X
  1705. X    if (IN_CLASSA(i))
  1706. X        mask = IN_CLASSA_NET;
  1707. X    else if (IN_CLASSB(i))
  1708. X        mask = IN_CLASSB_NET;
  1709. X    else
  1710. X        mask = IN_CLASSC_NET;
  1711. X
  1712. X    ina.s_addr = mask;
  1713. X    return(ina);
  1714. X}
  1715. X
  1716. X/*
  1717. X * Get the subnet network for a given address.
  1718. X */
  1719. struct in_addr
  1720. utilGetSubNet(in, mask)
  1721. struct in_addr in, mask;
  1722. X{
  1723. X    struct in_addr ina;
  1724. X
  1725. X    ina.s_addr = ntohl(in.s_addr) & ntohl(mask.s_addr);
  1726. X    return(ina);
  1727. X}
  1728. X
  1729. X/*
  1730. X * Get the IP network for a given address.
  1731. X */
  1732. struct in_addr
  1733. utilGetIPNet(in)
  1734. struct in_addr in;
  1735. X{
  1736. X    struct in_addr ina;
  1737. X    register u_long net;
  1738. X    register u_long i = ntohl(in.s_addr);
  1739. X
  1740. X    if (IN_CLASSA(i))
  1741. X        net = i & IN_CLASSA_NET;
  1742. X    else if (IN_CLASSB(i))
  1743. X        net = i & IN_CLASSB_NET;
  1744. X    else
  1745. X        net = i & IN_CLASSC_NET;
  1746. X
  1747. X    ina.s_addr = net;
  1748. X    return(ina);
  1749. X}
  1750. X
  1751. X/*
  1752. X * Return whether or not dst is a broadcast address.
  1753. X */
  1754. int
  1755. utilIsBroadcast(dst, ifip)
  1756. InterfaceInfo *ifip;
  1757. struct in_addr dst;
  1758. X{
  1759. X    register u_long m, l;
  1760. X
  1761. X    m = ~ifip->ifi_subnetmask.sin_addr.s_addr;
  1762. X    l = ntohl(dst.s_addr) & m;
  1763. X
  1764. X    if ((l == (INADDR_BROADCAST & m)) || (l == (INADDR_ANY & m)))
  1765. X        return(1);
  1766. X
  1767. X    m = ~ifip->ifi_ipnetmask.sin_addr.s_addr;
  1768. X    l = ntohl(dst.s_addr) & m;
  1769. X
  1770. X    if ((l == (INADDR_BROADCAST & m)) || (l == (INADDR_ANY & m)))
  1771. X        return(1);
  1772. X
  1773. X    return(0);
  1774. X}
  1775. X
  1776. X/*
  1777. X * Add a host to a list of hosts.
  1778. X */
  1779. int
  1780. utilAddHost(addr, ifip)
  1781. struct in_addr addr;
  1782. InterfaceInfo *ifip;
  1783. X{
  1784. X    register HostRecord *hrp, *lhrp;
  1785. X
  1786. X    if (ifip->ifi_hostlist == NULL) {
  1787. X        syslog(LOG_DEBUG, "%s: first host (%s) on list",
  1788. X               ifip->ifi_ifname, inet_ntoa(addr));
  1789. X
  1790. X        ifip->ifi_hostlist = (HostRecord *)
  1791. X            utilSafeAlloc(sizeof(HostRecord));
  1792. X        hrp = ifip->ifi_hostlist;
  1793. X
  1794. X        bcopy((caddr_t) &addr, (caddr_t) &hrp->hr_address,
  1795. X              sizeof(struct in_addr));
  1796. X        hrp->hr_refcnt = 1;
  1797. X        return(1);
  1798. X    }
  1799. X
  1800. X    for (hrp = ifip->ifi_hostlist; hrp != NULL; hrp = hrp->hr_next) {
  1801. X        lhrp = hrp;
  1802. X
  1803. X        if (hrp->hr_address.s_addr == addr.s_addr) {
  1804. X            syslog(LOG_DEBUG, "%s: host (%s) already on list",
  1805. X                   ifip->ifi_ifname, inet_ntoa(addr));
  1806. X            hrp->hr_refcnt++;
  1807. X
  1808. X            return(0);
  1809. X        }
  1810. X    }
  1811. X
  1812. X    syslog(LOG_DEBUG, "%s: add new host (%s) to list",
  1813. X           ifip->ifi_ifname, inet_ntoa(addr));
  1814. X
  1815. X    lhrp->hr_next = (HostRecord *) utilSafeAlloc(sizeof(HostRecord));
  1816. X
  1817. X    bcopy((caddr_t) &addr, (caddr_t) &lhrp->hr_address,
  1818. X          sizeof(struct in_addr));
  1819. X    lhrp->hr_refcnt = 1;
  1820. X    return(1);
  1821. X}
  1822. X
  1823. X/*
  1824. X * Dump statistics.
  1825. X */
  1826. void
  1827. utilDumpStats()
  1828. X{
  1829. X    int syslogmask;
  1830. X    struct hostent *hp;
  1831. X    register HostRecord *hrp;
  1832. X    register InterfaceInfo *ifip;
  1833. X
  1834. X    syslogmask = setlogmask(LOG_UPTO(LOG_INFO));
  1835. X
  1836. X    syslog(LOG_INFO, "Total packets received since start: %d",
  1837. X           epochPackets);
  1838. X    syslog(LOG_INFO, "Total packets received since reset: %d",
  1839. X           totalPackets);
  1840. X    syslog(LOG_INFO, "Bad packets received since reset:   %d",
  1841. X           badPackets);
  1842. X    syslog(LOG_INFO, "Proxy-possible packets since reset: %d",
  1843. X           concernPackets);
  1844. X    syslog(LOG_INFO, "Proxy-ARP replies sent since reset: %d",
  1845. X           replyPackets);
  1846. X
  1847. X    for (ifip = interfaces; ifip != NULL; ifip = ifip->ifi_next) {
  1848. X        syslog(LOG_INFO, "Proxy-ARPed hosts on interface %s:",
  1849. X               ifip->ifi_ifname);
  1850. X
  1851. X        if ((hrp = ifip->ifi_hostlist) == NULL) {
  1852. X            syslog(LOG_INFO, "none.");
  1853. X            continue;
  1854. X        }
  1855. X
  1856. X        for (; hrp != NULL; hrp = hrp->hr_next) {
  1857. X            hp = gethostbyaddr((caddr_t) &hrp->hr_address.s_addr,
  1858. X                       sizeof(hrp->hr_address.s_addr),
  1859. X                       AF_INET);
  1860. X            syslog(LOG_INFO, "%s (%s): %d replies sent",
  1861. X                   hp ? hp->h_name : "?",
  1862. X                   inet_ntoa(hrp->hr_address),
  1863. X                   hrp->hr_refcnt);
  1864. X        }
  1865. X    }
  1866. X
  1867. X    setlogmask(syslogmask);
  1868. X}
  1869. X
  1870. X/*
  1871. X * Clear statistics.
  1872. X */
  1873. void
  1874. utilClearStats()
  1875. X{
  1876. X    int syslogmask;
  1877. X    register InterfaceInfo *ifip;
  1878. X    register HostRecord *hrp, *nhrp;
  1879. X
  1880. X    syslogmask = setlogmask(LOG_UPTO(LOG_NOTICE));
  1881. X
  1882. X    badPackets = 0;
  1883. X    replyPackets = 0;
  1884. X    totalPackets = 0;
  1885. X    concernPackets = 0;
  1886. X
  1887. X    for (ifip = interfaces; ifip != NULL; ifip = ifip->ifi_next) {
  1888. X        for (hrp = ifip->ifi_hostlist; hrp != NULL; hrp = nhrp) {
  1889. X            nhrp = hrp->hr_next;
  1890. X            free(hrp);
  1891. X        }
  1892. X
  1893. X        ifip->ifi_hostlist = NULL;
  1894. X    }
  1895. X
  1896. X    syslog(LOG_NOTICE, "statistics cleared");
  1897. X    setlogmask(syslogmask);
  1898. X}
  1899. END_OF_FILE
  1900. if test 5112 -ne `wc -c <'util.c'`; then
  1901.     echo shar: \"'util.c'\" unpacked with wrong size!
  1902. fi
  1903. # end of 'util.c'
  1904. fi
  1905. echo shar: End of archive 1 \(of 1\).
  1906. cp /dev/null ark1isdone
  1907. MISSING=""
  1908. for I in 1 ; do
  1909.     if test ! -f ark${I}isdone ; then
  1910.     MISSING="${MISSING} ${I}"
  1911.     fi
  1912. done
  1913. if test "${MISSING}" = "" ; then
  1914.     echo You have the archive.
  1915.     rm -f ark[1-9]isdone
  1916. else
  1917.     echo You still need to unpack the following archives:
  1918.     echo "        " ${MISSING}
  1919. fi
  1920. ##  End of shell archive.
  1921. exit 0
  1922.