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

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