main.c revision 45988
114125Speter/* 214125Speter * Copyright (c) 1985, 1993 314125Speter * The Regents of the University of California. All rights reserved. 414125Speter * 514125Speter * Copyright (c) 1995 John Hay. All rights reserved. 614125Speter * 714125Speter * This file includes significant work done at Cornell University by 814125Speter * Bill Nesheim. That work included by permission. 914125Speter * 1014125Speter * Redistribution and use in source and binary forms, with or without 1114125Speter * modification, are permitted provided that the following conditions 1214125Speter * are met: 1314125Speter * 1. Redistributions of source code must retain the above copyright 1414125Speter * notice, this list of conditions and the following disclaimer. 1514125Speter * 2. Redistributions in binary form must reproduce the above copyright 1614125Speter * notice, this list of conditions and the following disclaimer in the 1714125Speter * documentation and/or other materials provided with the distribution. 1814125Speter * 3. All advertising materials mentioning features or use of this software 1914125Speter * must display the following acknowledgement: 2014125Speter * This product includes software developed by the University of 2114125Speter * California, Berkeley and its contributors. 2214125Speter * 4. Neither the name of the University nor the names of its contributors 2314125Speter * may be used to endorse or promote products derived from this software 2414125Speter * without specific prior written permission. 2514125Speter * 2614125Speter * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2714125Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2814125Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2914125Speter * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 3014125Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3114125Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3274499Salfred * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3374499Salfred * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3414125Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3514125Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3630376Scharnier * SUCH DAMAGE. 3730376Scharnier * 3830376Scharnier * $Id: main.c,v 1.7 1997/07/06 07:38:30 jhay Exp $ 39180025Sdfr */ 4014125Speter 4130376Scharnier#ifndef lint 4214125Speterstatic char copyright[] = 4314125Speter"@(#) Copyright (c) 1985, 1993\n\ 4414125Speter The Regents of the University of California. All rights reserved.\n"; 4514125Speter#endif /* not lint */ 4614125Speter 4799786Salfred#ifndef lint 4814125Speterstatic char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/5/93"; 4914125Speter#endif /* not lint */ 5014125Speter 5114125Speter/* 5214125Speter * IPX Routing Information Protocol Daemon 5314125Speter */ 5414125Speter#include "defs.h" 5514125Speter#include <sys/time.h> 5614125Speter 5714125Speter#include <net/if.h> 5814125Speter 5914125Speter#include <errno.h> 6014125Speter#include <nlist.h> 6114125Speter#include <signal.h> 6214125Speter#include <paths.h> 6314125Speter#include <stdlib.h> 6414125Speter#include <unistd.h> 6514125Speter 6614125Speter#define SAP_PKT 0 6714125Speter#define RIP_PKT 1 6814125Speter 6914125Speterstruct sockaddr_ipx addr; /* Daemon's Address */ 7014125Speterint ripsock; /* RIP Socket to listen on */ 7114125Speterint sapsock; /* SAP Socket to listen on */ 7214125Speterint kmem; 7314125Speterint install; /* if 1 call kernel */ 7414125Speterint lookforinterfaces; /* if 1 probe kernel for new up interfaces */ 7514125Speterint performnlist; /* if 1 check if /kernel has changed */ 7614125Speterint externalinterfaces; /* # of remote and local interfaces */ 7714125Speterint timeval; /* local idea of time */ 7814125Speterint noteremoterequests; /* squawk on requests from non-local nets */ 7914125Speterint r; /* Routing socket to install updates with */ 8014125Speterstruct sockaddr_ipx ipx_netmask; /* Used in installing routes */ 8114125Speter 82180025Sdfrchar packet[MAXRXPACKETSIZE+1]; 8314125Speter 8414125Speterchar **argv0; 85180025Sdfr 86180025Sdfrint supplier = -1; /* process should supply updates */ 8714125Speterint dosap = 1; /* By default do SAP services. */ 8814125Speterint dobcast = 1; /* A RIP/SAP broadcast is needed. */ 8914125Spetertime_t lastbcast; /* Time of last RIP/SAP broadcast */ 9014125Speter 9114125Speterstruct rip *msg = (struct rip *) &packet[sizeof (struct ipx)]; 9214125Speterstruct sap_packet *sap_msg = 9314125Speter (struct sap_packet *) &packet[sizeof (struct ipx)]; 94180025Sdfrvoid hup(), fkexit(), timer(); 95180025Sdfrvoid process(int fd, int pkt_type); 96180025Sdfrint getsocket(int type, int proto, struct sockaddr_ipx *sipx); 97180025Sdfrvoid getinfo(); 98180025Sdfrvoid catchtimer(); 99180025Sdfr 100180025Sdfrint 101180025Sdfrmain(argc, argv) 102180025Sdfr int argc; 103180025Sdfr char *argv[]; 104180025Sdfr{ 105180025Sdfr int nfds; 106180025Sdfr fd_set fdvar; 107180025Sdfr time_t ttime; 108180025Sdfr struct itimerval tval; 109180025Sdfr 110180025Sdfr argv0 = argv; 111180025Sdfr argv++, argc--; 112180025Sdfr while (argc > 0 && **argv == '-') { 113180025Sdfr if (strcmp(*argv, "-s") == 0) { 114180025Sdfr supplier = 1; 115180025Sdfr argv++, argc--; 116180025Sdfr continue; 117180025Sdfr } 11814125Speter if (strcmp(*argv, "-q") == 0) { 11914125Speter supplier = 0; 12014125Speter argv++, argc--; 121180025Sdfr continue; 122180025Sdfr } 12314125Speter if (strcmp(*argv, "-R") == 0) { 12414125Speter noteremoterequests++; 12514125Speter argv++, argc--; 12614125Speter continue; 12714125Speter } 12814125Speter if (strcmp(*argv, "-S") == 0) { 12914125Speter dosap = 0; 13014125Speter argv++, argc--; 13114125Speter continue; 13214125Speter } 13314125Speter if (strcmp(*argv, "-t") == 0) { 13414125Speter tracepackets++; 13514125Speter argv++, argc--; 13614125Speter ftrace = stderr; 13714125Speter tracing = 1; 13814125Speter continue; 13914125Speter } 14014125Speter if (strcmp(*argv, "-g") == 0) { 14114125Speter gateway = 1; 14214125Speter argv++, argc--; 14314125Speter continue; 14414125Speter } 14514125Speter if (strcmp(*argv, "-l") == 0) { 14614125Speter gateway = -1; 14714125Speter argv++, argc--; 14814125Speter continue; 14914125Speter } 15014125Speter if (strcmp(*argv, "-N") == 0) { 15114125Speter dognreply = 0; 15214125Speter argv++, argc--; 15314125Speter continue; 15414125Speter } 15514125Speter fprintf(stderr, 15614125Speter "usage: ipxrouted [ -s ] [ -q ] [ -t ] [ -g ] [ -l ] [ -N ]\n"); 15714125Speter exit(1); 15814125Speter } 15914125Speter 16014125Speter 16114125Speter#ifndef DEBUG 16214125Speter if (!tracepackets) 16314125Speter daemon(0, 0); 16414125Speter#endif 16514125Speter openlog("IPXrouted", LOG_PID, LOG_DAEMON); 16614125Speter 16714125Speter addr.sipx_family = AF_IPX; 16814125Speter addr.sipx_len = sizeof(addr); 16914125Speter addr.sipx_port = htons(IPXPORT_RIP); 17099798Salfred ipx_anynet.s_net[0] = ipx_anynet.s_net[1] = -1; 17114125Speter ipx_netmask.sipx_addr.x_net = ipx_anynet; 17214125Speter ipx_netmask.sipx_len = 6; 17314125Speter ipx_netmask.sipx_family = AF_IPX; 17414125Speter r = socket(AF_ROUTE, SOCK_RAW, 0); 17514125Speter /* later, get smart about lookingforinterfaces */ 17614125Speter if (r) 17714125Speter shutdown(r, 0); /* for now, don't want reponses */ 17814125Speter else { 17914125Speter fprintf(stderr, "IPXrouted: no routing socket\n"); 18014125Speter exit(1); 18114125Speter } 18214125Speter ripsock = getsocket(SOCK_DGRAM, 0, &addr); 18314125Speter if (ripsock < 0) 18430376Scharnier exit(1); 18514125Speter 18614125Speter if (dosap) { 18714125Speter addr.sipx_port = htons(IPXPORT_SAP); 18814125Speter sapsock = getsocket(SOCK_DGRAM, 0, &addr); 18914125Speter if (sapsock < 0) 19014125Speter exit(1); 19121786Salex } else 192171816Struckman sapsock = -1; 19314125Speter 19414125Speter /* 19514125Speter * Any extra argument is considered 19614125Speter * a tracing log file. 19714125Speter */ 19814125Speter if (argc > 0) 19914125Speter traceon(*argv); 20014125Speter /* 20114125Speter * Collect an initial view of the world by 20214125Speter * snooping in the kernel. Then, send a request packet on all 20330376Scharnier * directly connected networks to find out what 20414125Speter * everyone else thinks. 20514125Speter */ 20614125Speter rtinit(); 20714125Speter sapinit(); 20814125Speter ifinit(); 20914125Speter if (supplier < 0) 21014125Speter supplier = 0; 21114125Speter /* request the state of the world */ 21214125Speter msg->rip_cmd = htons(RIPCMD_REQUEST); 21314125Speter msg->rip_nets[0].rip_dst = ipx_anynet; 21414125Speter msg->rip_nets[0].rip_metric = htons(HOPCNT_INFINITY); 21514125Speter msg->rip_nets[0].rip_ticks = htons(-1); 21614125Speter toall(sndmsg, NULL, 0); 21714125Speter 21814125Speter if (dosap) { 21914125Speter sap_msg->sap_cmd = htons(SAP_REQ); 22014125Speter sap_msg->sap[0].ServType = htons(SAP_WILDCARD); 22114125Speter toall(sapsndmsg, NULL, 0); 22214125Speter } 22314125Speter 22414125Speter signal(SIGALRM, catchtimer); 22514125Speter signal(SIGHUP, hup); 22614125Speter signal(SIGINT, hup); 22714125Speter signal(SIGEMT, fkexit); 22814125Speter signal(SIGINFO, getinfo); 22914125Speter 23014125Speter tval.it_interval.tv_sec = TIMER_RATE; 23114125Speter tval.it_interval.tv_usec = 0; 23214125Speter tval.it_value.tv_sec = TIMER_RATE; 23314125Speter tval.it_value.tv_usec = 0; 23414125Speter setitimer(ITIMER_REAL, &tval, NULL); 23514125Speter 23614125Speter nfds = 1 + max(sapsock, ripsock); 23714125Speter 23814125Speter for (;;) { 23914125Speter if (dobcast) { 24014125Speter dobcast = 0; 24114125Speter lastbcast = time(NULL); 24214125Speter timer(); 24314125Speter } 24414125Speter 24514125Speter FD_ZERO(&fdvar); 24614125Speter if (dosap) { 24714125Speter FD_SET(sapsock, &fdvar); 24814125Speter } 24914125Speter FD_SET(ripsock, &fdvar); 25014125Speter 25114125Speter if(select(nfds, &fdvar, (fd_set *)NULL, (fd_set *)NULL, 25214125Speter (struct timeval *)NULL) < 0) { 25314125Speter if(errno == EINTR) 25414125Speter continue; 25514125Speter perror("during select"); 25614125Speter exit(1); 25714125Speter } 25814125Speter 25914125Speter if(FD_ISSET(ripsock, &fdvar)) 26014125Speter process(ripsock, RIP_PKT); 26114125Speter 26214125Speter if(dosap && FD_ISSET(sapsock, &fdvar)) 26314125Speter process(sapsock, SAP_PKT); 26414125Speter 26514125Speter ttime = time(NULL); 26614125Speter if (ttime > (lastbcast + TIMER_RATE + (TIMER_RATE * 2 / 3))) { 26714125Speter dobcast = 1; 26814125Speter syslog(LOG_ERR, "Missed alarm"); 26914125Speter } 27014125Speter } 27114125Speter} 272121560Speter 273121560Spetervoid 27414125Speterprocess(fd, pkt_type) 27514125Speter int fd; 27614125Speter int pkt_type; 27714125Speter{ 27814125Speter struct sockaddr from; 27914125Speter int fromlen = sizeof (from), cc, omask; 28014125Speter struct ipx *ipxdp = (struct ipx *)packet; 28114125Speter 28214125Speter cc = recvfrom(fd, packet, sizeof (packet), 0, &from, &fromlen); 28314125Speter if (cc <= 0) { 28414125Speter if (cc < 0 && errno != EINTR) 28514125Speter syslog(LOG_ERR, "recvfrom: %m"); 28614125Speter return; 28714125Speter } 28814125Speter if (tracepackets > 1 && ftrace) { 28914125Speter fprintf(ftrace,"rcv %d bytes on %s ", 29014125Speter cc, ipxdp_ntoa(&ipxdp->ipx_dna)); 29114125Speter fprintf(ftrace," from %s\n", ipxdp_ntoa(&ipxdp->ipx_sna)); 29214125Speter } 29314125Speter 29414125Speter if (noteremoterequests && 29514125Speter !ipx_neteqnn(ipxdp->ipx_sna.x_net, ipx_zeronet) && 29614125Speter !ipx_neteq(ipxdp->ipx_sna, ipxdp->ipx_dna)) 29714125Speter { 29814125Speter syslog(LOG_ERR, 29914125Speter "net of interface (%s) != net on ether (%s)!\n", 30014125Speter ipxdp_nettoa(ipxdp->ipx_dna.x_net), 30114125Speter ipxdp_nettoa(ipxdp->ipx_sna.x_net)); 30214125Speter } 30314125Speter 30414125Speter /* We get the IPX header in front of the RIF packet*/ 30514125Speter cc -= sizeof (struct ipx); 30614125Speter#define mask(s) (1<<((s)-1)) 30714125Speter omask = sigblock(mask(SIGALRM)); 30814125Speter switch(pkt_type) { 30914125Speter case SAP_PKT: sap_input(&from, cc); 31014125Speter break; 31114125Speter case RIP_PKT: rip_input(&from, cc); 31214125Speter break; 31314125Speter } 31414125Speter sigsetmask(omask); 31514125Speter} 31614125Speter 31714125Speterint 31814125Spetergetsocket(type, proto, sipx) 31914125Speter int type, proto; 32014125Speter struct sockaddr_ipx *sipx; 32114125Speter{ 32214125Speter int domain = sipx->sipx_family; 32314125Speter int retry, s, on = 1; 32414125Speter 32514125Speter retry = 1; 32614125Speter while ((s = socket(domain, type, proto)) < 0 && retry) { 32714125Speter syslog(LOG_ERR, "socket: %m"); 32814125Speter sleep(5 * retry); 32914125Speter retry <<= 1; 33014125Speter } 33114125Speter if (retry == 0) 33214125Speter return (-1); 33314125Speter while (bind(s, (struct sockaddr *)sipx, sizeof (*sipx)) < 0 && retry) { 33414125Speter syslog(LOG_ERR, "bind: %m"); 33514125Speter sleep(5 * retry); 33614125Speter retry <<= 1; 33714125Speter } 33814125Speter if (retry == 0) 33914125Speter return (-1); 34014125Speter if (domain==AF_IPX) { 34114125Speter struct ipx ipxdp; 34214125Speter if (setsockopt(s, 0, SO_HEADERS_ON_INPUT, &on, sizeof(on))) { 34314125Speter syslog(LOG_ERR, "setsockopt SEE HEADERS: %m"); 34414125Speter exit(1); 34514125Speter } 34614125Speter if (ntohs(sipx->sipx_addr.x_port) == IPXPORT_RIP) 34714125Speter ipxdp.ipx_pt = IPXPROTO_RI; 34814125Speter else if (ntohs(sipx->sipx_addr.x_port) == IPXPORT_SAP) 34914125Speter#ifdef IPXPROTO_SAP 35014125Speter ipxdp.ipx_pt = IPXPROTO_SAP; 35114125Speter#else 35214125Speter ipxdp.ipx_pt = IPXPROTO_PXP; 35314125Speter#endif 35414125Speter else { 35514125Speter syslog(LOG_ERR, "port should be either RIP or SAP"); 35614125Speter exit(1); 35714125Speter } 35814125Speter if (setsockopt(s, 0, SO_DEFAULT_HEADERS, &ipxdp, sizeof(ipxdp))) { 35914125Speter syslog(LOG_ERR, "setsockopt SET HEADER: %m"); 36014125Speter exit(1); 36114125Speter } 362 } 363 if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) { 364 syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m"); 365 exit(1); 366 } 367 return (s); 368} 369 370/* 371 * Fork and exit on EMT-- for profiling. 372 */ 373void 374fkexit() 375{ 376 if (fork() == 0) 377 exit(0); 378} 379 380void 381catchtimer() 382{ 383 dobcast = 1; 384} 385 386void 387getinfo() 388{ 389 FILE *fh; 390 391 fh = fopen("/tmp/ipxrouted.dmp", "a"); 392 if(fh == NULL) 393 return; 394 395 dumpriptable(fh); 396 dumpsaptable(fh, sap_head); 397 398 fclose(fh); 399} 400 401