main.c revision 50306
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 * 3850306Sjhay * $Id: main.c,v 1.8 1999/04/24 09:18:48 jhay 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 } 15045988Sjhay if (strcmp(*argv, "-N") == 0) { 15145988Sjhay dognreply = 0; 15245988Sjhay argv++, argc--; 15345988Sjhay continue; 15445988Sjhay } 15511820Sjulian fprintf(stderr, 15645988Sjhay "usage: ipxrouted [ -s ] [ -q ] [ -t ] [ -g ] [ -l ] [ -N ]\n"); 15711820Sjulian exit(1); 15811820Sjulian } 15911820Sjulian 16011820Sjulian 16111820Sjulian#ifndef DEBUG 16211820Sjulian if (!tracepackets) 16311820Sjulian daemon(0, 0); 16411820Sjulian#endif 16511820Sjulian openlog("IPXrouted", LOG_PID, LOG_DAEMON); 16611820Sjulian 16711820Sjulian addr.sipx_family = AF_IPX; 16811820Sjulian addr.sipx_len = sizeof(addr); 16911820Sjulian addr.sipx_port = htons(IPXPORT_RIP); 17011820Sjulian ipx_anynet.s_net[0] = ipx_anynet.s_net[1] = -1; 17111820Sjulian ipx_netmask.sipx_addr.x_net = ipx_anynet; 17211820Sjulian ipx_netmask.sipx_len = 6; 17311820Sjulian ipx_netmask.sipx_family = AF_IPX; 17411820Sjulian r = socket(AF_ROUTE, SOCK_RAW, 0); 17511820Sjulian /* later, get smart about lookingforinterfaces */ 17611820Sjulian if (r) 17711820Sjulian shutdown(r, 0); /* for now, don't want reponses */ 17811820Sjulian else { 17911820Sjulian fprintf(stderr, "IPXrouted: no routing socket\n"); 18011820Sjulian exit(1); 18111820Sjulian } 18211820Sjulian ripsock = getsocket(SOCK_DGRAM, 0, &addr); 18311820Sjulian if (ripsock < 0) 18411820Sjulian exit(1); 18511820Sjulian 18611820Sjulian if (dosap) { 18711820Sjulian addr.sipx_port = htons(IPXPORT_SAP); 18811820Sjulian sapsock = getsocket(SOCK_DGRAM, 0, &addr); 18911820Sjulian if (sapsock < 0) 19011820Sjulian exit(1); 19111820Sjulian } else 19211820Sjulian sapsock = -1; 19311820Sjulian 19411820Sjulian /* 19511820Sjulian * Any extra argument is considered 19611820Sjulian * a tracing log file. 19711820Sjulian */ 19811820Sjulian if (argc > 0) 19911820Sjulian traceon(*argv); 20011820Sjulian /* 20111820Sjulian * Collect an initial view of the world by 20211820Sjulian * snooping in the kernel. Then, send a request packet on all 20311820Sjulian * directly connected networks to find out what 20411820Sjulian * everyone else thinks. 20511820Sjulian */ 20611820Sjulian rtinit(); 20711820Sjulian sapinit(); 20811820Sjulian ifinit(); 20911820Sjulian if (supplier < 0) 21011820Sjulian supplier = 0; 21111820Sjulian /* request the state of the world */ 21211820Sjulian msg->rip_cmd = htons(RIPCMD_REQUEST); 21311820Sjulian msg->rip_nets[0].rip_dst = ipx_anynet; 21411820Sjulian msg->rip_nets[0].rip_metric = htons(HOPCNT_INFINITY); 21511820Sjulian msg->rip_nets[0].rip_ticks = htons(-1); 21627244Sjhay toall(sndmsg, NULL, 0); 21711820Sjulian 21811820Sjulian if (dosap) { 21911820Sjulian sap_msg->sap_cmd = htons(SAP_REQ); 22011820Sjulian sap_msg->sap[0].ServType = htons(SAP_WILDCARD); 22127244Sjhay toall(sapsndmsg, NULL, 0); 22211820Sjulian } 22311820Sjulian 22427244Sjhay signal(SIGALRM, catchtimer); 22511820Sjulian signal(SIGHUP, hup); 22611820Sjulian signal(SIGINT, hup); 22711820Sjulian signal(SIGEMT, fkexit); 22815248Sjhay signal(SIGINFO, getinfo); 22927244Sjhay 23027244Sjhay tval.it_interval.tv_sec = TIMER_RATE; 23127244Sjhay tval.it_interval.tv_usec = 0; 23227244Sjhay tval.it_value.tv_sec = TIMER_RATE; 23327244Sjhay tval.it_value.tv_usec = 0; 23427244Sjhay setitimer(ITIMER_REAL, &tval, NULL); 23527244Sjhay 23611820Sjulian nfds = 1 + max(sapsock, ripsock); 23711820Sjulian 23811820Sjulian for (;;) { 23927244Sjhay if (dobcast) { 24027244Sjhay dobcast = 0; 24127244Sjhay lastbcast = time(NULL); 24227244Sjhay timer(); 24327244Sjhay } 24427244Sjhay 24511820Sjulian FD_ZERO(&fdvar); 24611820Sjulian if (dosap) { 24711820Sjulian FD_SET(sapsock, &fdvar); 24811820Sjulian } 24911820Sjulian FD_SET(ripsock, &fdvar); 25011820Sjulian 25111820Sjulian if(select(nfds, &fdvar, (fd_set *)NULL, (fd_set *)NULL, 25211820Sjulian (struct timeval *)NULL) < 0) { 25312692Sjulian if(errno == EINTR) 25412692Sjulian continue; 25512692Sjulian perror("during select"); 25612692Sjulian exit(1); 25711820Sjulian } 25811820Sjulian 25911820Sjulian if(FD_ISSET(ripsock, &fdvar)) 26011820Sjulian process(ripsock, RIP_PKT); 26111820Sjulian 26211820Sjulian if(dosap && FD_ISSET(sapsock, &fdvar)) 26311820Sjulian process(sapsock, SAP_PKT); 26427244Sjhay 26527244Sjhay ttime = time(NULL); 26627244Sjhay if (ttime > (lastbcast + TIMER_RATE + (TIMER_RATE * 2 / 3))) { 26727244Sjhay dobcast = 1; 26827244Sjhay syslog(LOG_ERR, "Missed alarm"); 26927244Sjhay } 27011820Sjulian } 27111820Sjulian} 27211820Sjulian 27311820Sjulianvoid 27411820Sjulianprocess(fd, pkt_type) 27511820Sjulian int fd; 27611820Sjulian int pkt_type; 27711820Sjulian{ 27811820Sjulian struct sockaddr from; 27911820Sjulian int fromlen = sizeof (from), cc, omask; 28011840Sjulian struct ipx *ipxdp = (struct ipx *)packet; 28111820Sjulian 28211820Sjulian cc = recvfrom(fd, packet, sizeof (packet), 0, &from, &fromlen); 28311820Sjulian if (cc <= 0) { 28411820Sjulian if (cc < 0 && errno != EINTR) 28511820Sjulian syslog(LOG_ERR, "recvfrom: %m"); 28611820Sjulian return; 28711820Sjulian } 28811820Sjulian if (tracepackets > 1 && ftrace) { 28911820Sjulian fprintf(ftrace,"rcv %d bytes on %s ", 29011840Sjulian cc, ipxdp_ntoa(&ipxdp->ipx_dna)); 29111840Sjulian fprintf(ftrace," from %s\n", ipxdp_ntoa(&ipxdp->ipx_sna)); 29211820Sjulian } 29311820Sjulian 29411820Sjulian if (noteremoterequests && 29511840Sjulian !ipx_neteqnn(ipxdp->ipx_sna.x_net, ipx_zeronet) && 29611840Sjulian !ipx_neteq(ipxdp->ipx_sna, ipxdp->ipx_dna)) 29711820Sjulian { 29811820Sjulian syslog(LOG_ERR, 29911820Sjulian "net of interface (%s) != net on ether (%s)!\n", 30011840Sjulian ipxdp_nettoa(ipxdp->ipx_dna.x_net), 30111840Sjulian ipxdp_nettoa(ipxdp->ipx_sna.x_net)); 30211820Sjulian } 30311820Sjulian 30411820Sjulian /* We get the IPX header in front of the RIF packet*/ 30511840Sjulian cc -= sizeof (struct ipx); 30611820Sjulian#define mask(s) (1<<((s)-1)) 30711820Sjulian omask = sigblock(mask(SIGALRM)); 30811820Sjulian switch(pkt_type) { 30911820Sjulian case SAP_PKT: sap_input(&from, cc); 31011820Sjulian break; 31111820Sjulian case RIP_PKT: rip_input(&from, cc); 31211820Sjulian break; 31311820Sjulian } 31411820Sjulian sigsetmask(omask); 31511820Sjulian} 31611820Sjulian 31711820Sjulianint 31811820Sjuliangetsocket(type, proto, sipx) 31911820Sjulian int type, proto; 32011820Sjulian struct sockaddr_ipx *sipx; 32111820Sjulian{ 32211820Sjulian int domain = sipx->sipx_family; 32311820Sjulian int retry, s, on = 1; 32411820Sjulian 32511820Sjulian retry = 1; 32611820Sjulian while ((s = socket(domain, type, proto)) < 0 && retry) { 32711820Sjulian syslog(LOG_ERR, "socket: %m"); 32811820Sjulian sleep(5 * retry); 32911820Sjulian retry <<= 1; 33011820Sjulian } 33111820Sjulian if (retry == 0) 33211820Sjulian return (-1); 33311820Sjulian while (bind(s, (struct sockaddr *)sipx, sizeof (*sipx)) < 0 && retry) { 33411820Sjulian syslog(LOG_ERR, "bind: %m"); 33511820Sjulian sleep(5 * retry); 33611820Sjulian retry <<= 1; 33711820Sjulian } 33811820Sjulian if (retry == 0) 33911820Sjulian return (-1); 34011820Sjulian if (domain==AF_IPX) { 34111840Sjulian struct ipx ipxdp; 34211820Sjulian if (setsockopt(s, 0, SO_HEADERS_ON_INPUT, &on, sizeof(on))) { 34311820Sjulian syslog(LOG_ERR, "setsockopt SEE HEADERS: %m"); 34411820Sjulian exit(1); 34511820Sjulian } 34611820Sjulian if (ntohs(sipx->sipx_addr.x_port) == IPXPORT_RIP) 34711840Sjulian ipxdp.ipx_pt = IPXPROTO_RI; 34811820Sjulian else if (ntohs(sipx->sipx_addr.x_port) == IPXPORT_SAP) 34927244Sjhay#ifdef IPXPROTO_SAP 35011840Sjulian ipxdp.ipx_pt = IPXPROTO_SAP; 35127244Sjhay#else 35227244Sjhay ipxdp.ipx_pt = IPXPROTO_PXP; 35327244Sjhay#endif 35411820Sjulian else { 35511820Sjulian syslog(LOG_ERR, "port should be either RIP or SAP"); 35611820Sjulian exit(1); 35711820Sjulian } 35811820Sjulian if (setsockopt(s, 0, SO_DEFAULT_HEADERS, &ipxdp, sizeof(ipxdp))) { 35911820Sjulian syslog(LOG_ERR, "setsockopt SET HEADER: %m"); 36011820Sjulian exit(1); 36111820Sjulian } 36211820Sjulian } 36311820Sjulian if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) { 36411820Sjulian syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m"); 36511820Sjulian exit(1); 36611820Sjulian } 36711820Sjulian return (s); 36811820Sjulian} 36911820Sjulian 37011820Sjulian/* 37111820Sjulian * Fork and exit on EMT-- for profiling. 37211820Sjulian */ 37311820Sjulianvoid 37411820Sjulianfkexit() 37511820Sjulian{ 37611820Sjulian if (fork() == 0) 37711820Sjulian exit(0); 37811820Sjulian} 37915248Sjhay 38015248Sjhayvoid 38127244Sjhaycatchtimer() 38227244Sjhay{ 38327244Sjhay dobcast = 1; 38427244Sjhay} 38527244Sjhay 38627244Sjhayvoid 38715248Sjhaygetinfo() 38815248Sjhay{ 38915248Sjhay FILE *fh; 39015248Sjhay 39150306Sjhay fh = fopen("/var/log/ipxrouted.dmp", "a"); 39215248Sjhay if(fh == NULL) 39315248Sjhay return; 39415248Sjhay 39515248Sjhay dumpriptable(fh); 39615248Sjhay dumpsaptable(fh, sap_head); 39715248Sjhay 39815248Sjhay fclose(fh); 39915248Sjhay} 40015248Sjhay 401