main.c revision 27244
111820Sjulian/* 211820Sjulian * Copyright (c) 1985, 1993 311820Sjulian * The Regents of the University of California. All rights reserved. 411820Sjulian * 511820Sjulian * Copyright (c) 1995 John Hay. All rights reserved. 611820Sjulian * 711820Sjulian * This file includes significant work done at Cornell University by 811820Sjulian * Bill Nesheim. That work included by permission. 911820Sjulian * 1011820Sjulian * Redistribution and use in source and binary forms, with or without 1111820Sjulian * modification, are permitted provided that the following conditions 1211820Sjulian * are met: 1311820Sjulian * 1. Redistributions of source code must retain the above copyright 1411820Sjulian * notice, this list of conditions and the following disclaimer. 1511820Sjulian * 2. Redistributions in binary form must reproduce the above copyright 1611820Sjulian * notice, this list of conditions and the following disclaimer in the 1711820Sjulian * documentation and/or other materials provided with the distribution. 1811820Sjulian * 3. All advertising materials mentioning features or use of this software 1911820Sjulian * must display the following acknowledgement: 2011820Sjulian * This product includes software developed by the University of 2111820Sjulian * California, Berkeley and its contributors. 2211820Sjulian * 4. Neither the name of the University nor the names of its contributors 2311820Sjulian * may be used to endorse or promote products derived from this software 2411820Sjulian * without specific prior written permission. 2511820Sjulian * 2611820Sjulian * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2711820Sjulian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2811820Sjulian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2911820Sjulian * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 3011820Sjulian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3111820Sjulian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3211820Sjulian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3311820Sjulian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3411820Sjulian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3511820Sjulian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3611820Sjulian * SUCH DAMAGE. 3711820Sjulian * 3827244Sjhay * $Id: main.c,v 1.6 1997/02/22 16:00:57 peter Exp $ 3911820Sjulian */ 4011820Sjulian 4111820Sjulian#ifndef lint 4211820Sjulianstatic char copyright[] = 4311820Sjulian"@(#) Copyright (c) 1985, 1993\n\ 4411820Sjulian The Regents of the University of California. All rights reserved.\n"; 4511820Sjulian#endif /* not lint */ 4611820Sjulian 4711820Sjulian#ifndef lint 4811820Sjulianstatic char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/5/93"; 4911820Sjulian#endif /* not lint */ 5011820Sjulian 5111820Sjulian/* 5211820Sjulian * IPX Routing Information Protocol Daemon 5311820Sjulian */ 5411820Sjulian#include "defs.h" 5511820Sjulian#include <sys/time.h> 5611820Sjulian 5711820Sjulian#include <net/if.h> 5811820Sjulian 5911820Sjulian#include <errno.h> 6011820Sjulian#include <nlist.h> 6111820Sjulian#include <signal.h> 6211820Sjulian#include <paths.h> 6311820Sjulian#include <stdlib.h> 6411820Sjulian#include <unistd.h> 6511820Sjulian 6611820Sjulian#define SAP_PKT 0 6711820Sjulian#define RIP_PKT 1 6811820Sjulian 6911820Sjulianstruct sockaddr_ipx addr; /* Daemon's Address */ 7011820Sjulianint ripsock; /* RIP Socket to listen on */ 7111820Sjulianint sapsock; /* SAP Socket to listen on */ 7211820Sjulianint kmem; 7311820Sjulianint install; /* if 1 call kernel */ 7411820Sjulianint lookforinterfaces; /* if 1 probe kernel for new up interfaces */ 7511820Sjulianint performnlist; /* if 1 check if /kernel has changed */ 7611820Sjulianint externalinterfaces; /* # of remote and local interfaces */ 7711820Sjulianint timeval; /* local idea of time */ 7811820Sjulianint noteremoterequests; /* squawk on requests from non-local nets */ 7911820Sjulianint r; /* Routing socket to install updates with */ 8011820Sjulianstruct sockaddr_ipx ipx_netmask; /* Used in installing routes */ 8111820Sjulian 8215248Sjhaychar packet[MAXRXPACKETSIZE+1]; 8311820Sjulian 8411820Sjulianchar **argv0; 8511820Sjulian 8611820Sjulianint supplier = -1; /* process should supply updates */ 8711820Sjulianint dosap = 1; /* By default do SAP services. */ 8827244Sjhayint dobcast = 1; /* A RIP/SAP broadcast is needed. */ 8927244Sjhaytime_t lastbcast; /* Time of last RIP/SAP broadcast */ 9011820Sjulian 9111840Sjulianstruct rip *msg = (struct rip *) &packet[sizeof (struct ipx)]; 9211820Sjulianstruct sap_packet *sap_msg = 9311840Sjulian (struct sap_packet *) &packet[sizeof (struct ipx)]; 9411820Sjulianvoid hup(), fkexit(), timer(); 9511820Sjulianvoid process(int fd, int pkt_type); 9611820Sjulianint getsocket(int type, int proto, struct sockaddr_ipx *sipx); 9715248Sjhayvoid getinfo(); 9827244Sjhayvoid catchtimer(); 9911820Sjulian 10011820Sjulianint 10111820Sjulianmain(argc, argv) 10211820Sjulian int argc; 10311820Sjulian char *argv[]; 10411820Sjulian{ 10511820Sjulian int nfds; 10611820Sjulian fd_set fdvar; 10727244Sjhay time_t ttime; 10827244Sjhay struct itimerval tval; 10911820Sjulian 11011820Sjulian argv0 = argv; 11111820Sjulian argv++, argc--; 11211820Sjulian while (argc > 0 && **argv == '-') { 11311820Sjulian if (strcmp(*argv, "-s") == 0) { 11411820Sjulian supplier = 1; 11511820Sjulian argv++, argc--; 11611820Sjulian continue; 11711820Sjulian } 11811820Sjulian if (strcmp(*argv, "-q") == 0) { 11911820Sjulian supplier = 0; 12011820Sjulian argv++, argc--; 12111820Sjulian continue; 12211820Sjulian } 12311820Sjulian if (strcmp(*argv, "-R") == 0) { 12411820Sjulian noteremoterequests++; 12511820Sjulian argv++, argc--; 12611820Sjulian continue; 12711820Sjulian } 12811820Sjulian if (strcmp(*argv, "-S") == 0) { 12911820Sjulian dosap = 0; 13011820Sjulian argv++, argc--; 13111820Sjulian continue; 13211820Sjulian } 13311820Sjulian if (strcmp(*argv, "-t") == 0) { 13411820Sjulian tracepackets++; 13511820Sjulian argv++, argc--; 13611820Sjulian ftrace = stderr; 13711820Sjulian tracing = 1; 13811820Sjulian continue; 13911820Sjulian } 14011820Sjulian if (strcmp(*argv, "-g") == 0) { 14111820Sjulian gateway = 1; 14211820Sjulian argv++, argc--; 14311820Sjulian continue; 14411820Sjulian } 14511820Sjulian if (strcmp(*argv, "-l") == 0) { 14611820Sjulian gateway = -1; 14711820Sjulian argv++, argc--; 14811820Sjulian continue; 14911820Sjulian } 15011820Sjulian fprintf(stderr, 15111820Sjulian "usage: ipxrouted [ -s ] [ -q ] [ -t ] [ -g ] [ -l ]\n"); 15211820Sjulian exit(1); 15311820Sjulian } 15411820Sjulian 15511820Sjulian 15611820Sjulian#ifndef DEBUG 15711820Sjulian if (!tracepackets) 15811820Sjulian daemon(0, 0); 15911820Sjulian#endif 16011820Sjulian openlog("IPXrouted", LOG_PID, LOG_DAEMON); 16111820Sjulian 16211820Sjulian addr.sipx_family = AF_IPX; 16311820Sjulian addr.sipx_len = sizeof(addr); 16411820Sjulian addr.sipx_port = htons(IPXPORT_RIP); 16511820Sjulian ipx_anynet.s_net[0] = ipx_anynet.s_net[1] = -1; 16611820Sjulian ipx_netmask.sipx_addr.x_net = ipx_anynet; 16711820Sjulian ipx_netmask.sipx_len = 6; 16811820Sjulian ipx_netmask.sipx_family = AF_IPX; 16911820Sjulian r = socket(AF_ROUTE, SOCK_RAW, 0); 17011820Sjulian /* later, get smart about lookingforinterfaces */ 17111820Sjulian if (r) 17211820Sjulian shutdown(r, 0); /* for now, don't want reponses */ 17311820Sjulian else { 17411820Sjulian fprintf(stderr, "IPXrouted: no routing socket\n"); 17511820Sjulian exit(1); 17611820Sjulian } 17711820Sjulian ripsock = getsocket(SOCK_DGRAM, 0, &addr); 17811820Sjulian if (ripsock < 0) 17911820Sjulian exit(1); 18011820Sjulian 18111820Sjulian if (dosap) { 18211820Sjulian addr.sipx_port = htons(IPXPORT_SAP); 18311820Sjulian sapsock = getsocket(SOCK_DGRAM, 0, &addr); 18411820Sjulian if (sapsock < 0) 18511820Sjulian exit(1); 18611820Sjulian } else 18711820Sjulian sapsock = -1; 18811820Sjulian 18911820Sjulian /* 19011820Sjulian * Any extra argument is considered 19111820Sjulian * a tracing log file. 19211820Sjulian */ 19311820Sjulian if (argc > 0) 19411820Sjulian traceon(*argv); 19511820Sjulian /* 19611820Sjulian * Collect an initial view of the world by 19711820Sjulian * snooping in the kernel. Then, send a request packet on all 19811820Sjulian * directly connected networks to find out what 19911820Sjulian * everyone else thinks. 20011820Sjulian */ 20111820Sjulian rtinit(); 20211820Sjulian sapinit(); 20311820Sjulian ifinit(); 20411820Sjulian if (supplier < 0) 20511820Sjulian supplier = 0; 20611820Sjulian /* request the state of the world */ 20711820Sjulian msg->rip_cmd = htons(RIPCMD_REQUEST); 20811820Sjulian msg->rip_nets[0].rip_dst = ipx_anynet; 20911820Sjulian msg->rip_nets[0].rip_metric = htons(HOPCNT_INFINITY); 21011820Sjulian msg->rip_nets[0].rip_ticks = htons(-1); 21127244Sjhay toall(sndmsg, NULL, 0); 21211820Sjulian 21311820Sjulian if (dosap) { 21411820Sjulian sap_msg->sap_cmd = htons(SAP_REQ); 21511820Sjulian sap_msg->sap[0].ServType = htons(SAP_WILDCARD); 21627244Sjhay toall(sapsndmsg, NULL, 0); 21711820Sjulian } 21811820Sjulian 21927244Sjhay signal(SIGALRM, catchtimer); 22011820Sjulian signal(SIGHUP, hup); 22111820Sjulian signal(SIGINT, hup); 22211820Sjulian signal(SIGEMT, fkexit); 22315248Sjhay signal(SIGINFO, getinfo); 22427244Sjhay 22527244Sjhay tval.it_interval.tv_sec = TIMER_RATE; 22627244Sjhay tval.it_interval.tv_usec = 0; 22727244Sjhay tval.it_value.tv_sec = TIMER_RATE; 22827244Sjhay tval.it_value.tv_usec = 0; 22927244Sjhay setitimer(ITIMER_REAL, &tval, NULL); 23027244Sjhay 23111820Sjulian nfds = 1 + max(sapsock, ripsock); 23211820Sjulian 23311820Sjulian for (;;) { 23427244Sjhay if (dobcast) { 23527244Sjhay dobcast = 0; 23627244Sjhay lastbcast = time(NULL); 23727244Sjhay timer(); 23827244Sjhay } 23927244Sjhay 24011820Sjulian FD_ZERO(&fdvar); 24111820Sjulian if (dosap) { 24211820Sjulian FD_SET(sapsock, &fdvar); 24311820Sjulian } 24411820Sjulian FD_SET(ripsock, &fdvar); 24511820Sjulian 24611820Sjulian if(select(nfds, &fdvar, (fd_set *)NULL, (fd_set *)NULL, 24711820Sjulian (struct timeval *)NULL) < 0) { 24812692Sjulian if(errno == EINTR) 24912692Sjulian continue; 25012692Sjulian perror("during select"); 25112692Sjulian exit(1); 25211820Sjulian } 25311820Sjulian 25411820Sjulian if(FD_ISSET(ripsock, &fdvar)) 25511820Sjulian process(ripsock, RIP_PKT); 25611820Sjulian 25711820Sjulian if(dosap && FD_ISSET(sapsock, &fdvar)) 25811820Sjulian process(sapsock, SAP_PKT); 25927244Sjhay 26027244Sjhay ttime = time(NULL); 26127244Sjhay if (ttime > (lastbcast + TIMER_RATE + (TIMER_RATE * 2 / 3))) { 26227244Sjhay dobcast = 1; 26327244Sjhay syslog(LOG_ERR, "Missed alarm"); 26427244Sjhay } 26511820Sjulian } 26611820Sjulian} 26711820Sjulian 26811820Sjulianvoid 26911820Sjulianprocess(fd, pkt_type) 27011820Sjulian int fd; 27111820Sjulian int pkt_type; 27211820Sjulian{ 27311820Sjulian struct sockaddr from; 27411820Sjulian int fromlen = sizeof (from), cc, omask; 27511840Sjulian struct ipx *ipxdp = (struct ipx *)packet; 27611820Sjulian 27711820Sjulian cc = recvfrom(fd, packet, sizeof (packet), 0, &from, &fromlen); 27811820Sjulian if (cc <= 0) { 27911820Sjulian if (cc < 0 && errno != EINTR) 28011820Sjulian syslog(LOG_ERR, "recvfrom: %m"); 28111820Sjulian return; 28211820Sjulian } 28311820Sjulian if (tracepackets > 1 && ftrace) { 28411820Sjulian fprintf(ftrace,"rcv %d bytes on %s ", 28511840Sjulian cc, ipxdp_ntoa(&ipxdp->ipx_dna)); 28611840Sjulian fprintf(ftrace," from %s\n", ipxdp_ntoa(&ipxdp->ipx_sna)); 28711820Sjulian } 28811820Sjulian 28911820Sjulian if (noteremoterequests && 29011840Sjulian !ipx_neteqnn(ipxdp->ipx_sna.x_net, ipx_zeronet) && 29111840Sjulian !ipx_neteq(ipxdp->ipx_sna, ipxdp->ipx_dna)) 29211820Sjulian { 29311820Sjulian syslog(LOG_ERR, 29411820Sjulian "net of interface (%s) != net on ether (%s)!\n", 29511840Sjulian ipxdp_nettoa(ipxdp->ipx_dna.x_net), 29611840Sjulian ipxdp_nettoa(ipxdp->ipx_sna.x_net)); 29711820Sjulian } 29811820Sjulian 29911820Sjulian /* We get the IPX header in front of the RIF packet*/ 30011840Sjulian cc -= sizeof (struct ipx); 30111820Sjulian#define mask(s) (1<<((s)-1)) 30211820Sjulian omask = sigblock(mask(SIGALRM)); 30311820Sjulian switch(pkt_type) { 30411820Sjulian case SAP_PKT: sap_input(&from, cc); 30511820Sjulian break; 30611820Sjulian case RIP_PKT: rip_input(&from, cc); 30711820Sjulian break; 30811820Sjulian } 30911820Sjulian sigsetmask(omask); 31011820Sjulian} 31111820Sjulian 31211820Sjulianint 31311820Sjuliangetsocket(type, proto, sipx) 31411820Sjulian int type, proto; 31511820Sjulian struct sockaddr_ipx *sipx; 31611820Sjulian{ 31711820Sjulian int domain = sipx->sipx_family; 31811820Sjulian int retry, s, on = 1; 31911820Sjulian 32011820Sjulian retry = 1; 32111820Sjulian while ((s = socket(domain, type, proto)) < 0 && retry) { 32211820Sjulian syslog(LOG_ERR, "socket: %m"); 32311820Sjulian sleep(5 * retry); 32411820Sjulian retry <<= 1; 32511820Sjulian } 32611820Sjulian if (retry == 0) 32711820Sjulian return (-1); 32811820Sjulian while (bind(s, (struct sockaddr *)sipx, sizeof (*sipx)) < 0 && retry) { 32911820Sjulian syslog(LOG_ERR, "bind: %m"); 33011820Sjulian sleep(5 * retry); 33111820Sjulian retry <<= 1; 33211820Sjulian } 33311820Sjulian if (retry == 0) 33411820Sjulian return (-1); 33511820Sjulian if (domain==AF_IPX) { 33611840Sjulian struct ipx ipxdp; 33711820Sjulian if (setsockopt(s, 0, SO_HEADERS_ON_INPUT, &on, sizeof(on))) { 33811820Sjulian syslog(LOG_ERR, "setsockopt SEE HEADERS: %m"); 33911820Sjulian exit(1); 34011820Sjulian } 34111820Sjulian if (ntohs(sipx->sipx_addr.x_port) == IPXPORT_RIP) 34211840Sjulian ipxdp.ipx_pt = IPXPROTO_RI; 34311820Sjulian else if (ntohs(sipx->sipx_addr.x_port) == IPXPORT_SAP) 34427244Sjhay#ifdef IPXPROTO_SAP 34511840Sjulian ipxdp.ipx_pt = IPXPROTO_SAP; 34627244Sjhay#else 34727244Sjhay ipxdp.ipx_pt = IPXPROTO_PXP; 34827244Sjhay#endif 34911820Sjulian else { 35011820Sjulian syslog(LOG_ERR, "port should be either RIP or SAP"); 35111820Sjulian exit(1); 35211820Sjulian } 35311820Sjulian if (setsockopt(s, 0, SO_DEFAULT_HEADERS, &ipxdp, sizeof(ipxdp))) { 35411820Sjulian syslog(LOG_ERR, "setsockopt SET HEADER: %m"); 35511820Sjulian exit(1); 35611820Sjulian } 35711820Sjulian } 35811820Sjulian if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) { 35911820Sjulian syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m"); 36011820Sjulian exit(1); 36111820Sjulian } 36211820Sjulian return (s); 36311820Sjulian} 36411820Sjulian 36511820Sjulian/* 36611820Sjulian * Fork and exit on EMT-- for profiling. 36711820Sjulian */ 36811820Sjulianvoid 36911820Sjulianfkexit() 37011820Sjulian{ 37111820Sjulian if (fork() == 0) 37211820Sjulian exit(0); 37311820Sjulian} 37415248Sjhay 37515248Sjhayvoid 37627244Sjhaycatchtimer() 37727244Sjhay{ 37827244Sjhay dobcast = 1; 37927244Sjhay} 38027244Sjhay 38127244Sjhayvoid 38215248Sjhaygetinfo() 38315248Sjhay{ 38415248Sjhay FILE *fh; 38515248Sjhay 38615248Sjhay fh = fopen("/tmp/ipxrouted.dmp", "a"); 38715248Sjhay if(fh == NULL) 38815248Sjhay return; 38915248Sjhay 39015248Sjhay dumpriptable(fh); 39115248Sjhay dumpsaptable(fh, sap_head); 39215248Sjhay 39315248Sjhay fclose(fh); 39415248Sjhay} 39515248Sjhay 396