main.c revision 122760
160786Sps/* 260786Sps * Copyright (c) 1985, 1993 360786Sps * The Regents of the University of California. All rights reserved. 460786Sps * 560786Sps * Copyright (c) 1995 John Hay. All rights reserved. 660786Sps * 789019Sps * This file includes significant work done at Cornell University by 860786Sps * Bill Nesheim. That work included by permission. 960786Sps * 10170256Sdelphij * Redistribution and use in source and binary forms, with or without 11170256Sdelphij * modification, are permitted provided that the following conditions 1260786Sps * are met: 1360786Sps * 1. Redistributions of source code must retain the above copyright 1460786Sps * notice, this list of conditions and the following disclaimer. 15195941Sdelphij * 2. Redistributions in binary form must reproduce the above copyright 16195941Sdelphij * notice, this list of conditions and the following disclaimer in the 17195941Sdelphij * documentation and/or other materials provided with the distribution. 18195941Sdelphij * 3. All advertising materials mentioning features or use of this software 19195941Sdelphij * must display the following acknowledgement: 20195941Sdelphij * This product includes software developed by the University of 21195941Sdelphij * California, Berkeley and its contributors. 22195941Sdelphij * 4. Neither the name of the University nor the names of its contributors 23195941Sdelphij * may be used to endorse or promote products derived from this software 24195941Sdelphij * without specific prior written permission. 25195941Sdelphij * 26195941Sdelphij * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27191930Sdelphij * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2860786Sps * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29191930Sdelphij * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30191930Sdelphij * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31191930Sdelphij * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32191930Sdelphij * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33191930Sdelphij * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34191930Sdelphij * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35191930Sdelphij * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36191930Sdelphij * SUCH DAMAGE. 37191930Sdelphij * 38191930Sdelphij * $FreeBSD: head/usr.sbin/IPXrouted/main.c 122760 2003-11-15 17:10:56Z trhodes $ 39191930Sdelphij */ 40191930Sdelphij 41191930Sdelphij#ifndef lint 42191930Sdelphijstatic const char copyright[] = 43191930Sdelphij"@(#) Copyright (c) 1985, 1993\n\ 44191930Sdelphij The Regents of the University of California. All rights reserved.\n"; 45191930Sdelphij#endif /* not lint */ 46191930Sdelphij 47191930Sdelphij#ifndef lint 48191930Sdelphijstatic const char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/5/93"; 49191930Sdelphij#endif /* not lint */ 50191930Sdelphij 51191930Sdelphij/* 52191930Sdelphij * IPX Routing Information Protocol Daemon 53191930Sdelphij */ 54191930Sdelphij#include "defs.h" 55191930Sdelphij#include <sys/time.h> 56191930Sdelphij 57191930Sdelphij#include <net/if.h> 58191930Sdelphij 59191930Sdelphij#include <errno.h> 60191930Sdelphij#include <nlist.h> 61191930Sdelphij#include <signal.h> 62191930Sdelphij#include <paths.h> 63191930Sdelphij#include <stdlib.h> 64191930Sdelphij#include <unistd.h> 65191930Sdelphij 66191930Sdelphij#define SAP_PKT 0 67191930Sdelphij#define RIP_PKT 1 68191930Sdelphij 69191930Sdelphijstruct sockaddr_ipx addr; /* Daemon's Address */ 70191930Sdelphijint ripsock; /* RIP Socket to listen on */ 71191930Sdelphijint sapsock; /* SAP Socket to listen on */ 72191930Sdelphijint kmem; 73191930Sdelphijint install; /* if 1 call kernel */ 74191930Sdelphijint lookforinterfaces; /* if 1 probe kernel for new up interfaces */ 75191930Sdelphijint performnlist; /* if 1 check if /kernel has changed */ 76191930Sdelphijint externalinterfaces; /* # of remote and local interfaces */ 77191930Sdelphijint timeval; /* local idea of time */ 78191930Sdelphijint noteremoterequests; /* squawk on requests from non-local nets */ 79191930Sdelphijint r; /* Routing socket to install updates with */ 80191930Sdelphijstruct sockaddr_ipx ipx_netmask; /* Used in installing routes */ 81191930Sdelphij 82191930Sdelphijchar packet[MAXRXPACKETSIZE+1]; 83191930Sdelphij 84173932Sdelphijchar **argv0; 85173682Sdelphij 86173682Sdelphijint supplier = -1; /* process should supply updates */ 87173682Sdelphijint dosap = 1; /* By default do SAP services. */ 88173682Sdelphijint dobcast = 1; /* A RIP/SAP broadcast is needed. */ 89173682Sdelphijtime_t lastbcast; /* Time of last RIP/SAP broadcast */ 90173682Sdelphij 91173682Sdelphijstruct rip *msg = (struct rip *) &packet[sizeof (struct ipx)]; 92173682Sdelphijstruct sap_packet *sap_msg = 93173682Sdelphij (struct sap_packet *) &packet[sizeof (struct ipx)]; 94173682Sdelphijvoid hup(), fkexit(), timer(); 95172597Sdelphijvoid process(int fd, int pkt_type); 96172468Sdelphijint getsocket(int type, int proto, struct sockaddr_ipx *sipx); 97172468Sdelphijvoid getinfo(); 98172468Sdelphijvoid catchtimer(); 99172468Sdelphij 100172468Sdelphijint 101172468Sdelphijmain(argc, argv) 102172468Sdelphij int argc; 103172468Sdelphij char *argv[]; 104172468Sdelphij{ 105172597Sdelphij int nfds; 106172597Sdelphij fd_set fdvar; 107172468Sdelphij time_t ttime; 108172468Sdelphij struct itimerval tval; 109170964Sdelphij 110170256Sdelphij argv0 = argv; 111170256Sdelphij argv++, argc--; 112170256Sdelphij while (argc > 0 && **argv == '-') { 113170256Sdelphij if (strcmp(*argv, "-s") == 0) { 114170256Sdelphij supplier = 1; 115170256Sdelphij argv++, argc--; 116170256Sdelphij continue; 117170256Sdelphij } 118170256Sdelphij if (strcmp(*argv, "-q") == 0) { 119170256Sdelphij supplier = 0; 120170256Sdelphij argv++, argc--; 121170256Sdelphij continue; 122170256Sdelphij } 123170256Sdelphij if (strcmp(*argv, "-R") == 0) { 124170256Sdelphij noteremoterequests++; 125170256Sdelphij argv++, argc--; 126170256Sdelphij continue; 127170256Sdelphij } 128170256Sdelphij if (strcmp(*argv, "-S") == 0) { 129170256Sdelphij dosap = 0; 130170256Sdelphij argv++, argc--; 131170256Sdelphij continue; 132170256Sdelphij } 133170256Sdelphij if (strcmp(*argv, "-t") == 0) { 134170256Sdelphij tracepackets++; 135170256Sdelphij argv++, argc--; 136170256Sdelphij ftrace = stderr; 137170256Sdelphij tracing = 1; 138170256Sdelphij continue; 139170256Sdelphij } 140170256Sdelphij if (strcmp(*argv, "-g") == 0) { 141170256Sdelphij gateway = 1; 142170256Sdelphij argv++, argc--; 143170256Sdelphij continue; 144170256Sdelphij } 145170256Sdelphij if (strcmp(*argv, "-l") == 0) { 146170256Sdelphij gateway = -1; 147170256Sdelphij argv++, argc--; 148170256Sdelphij continue; 149170256Sdelphij } 150170256Sdelphij if (strcmp(*argv, "-N") == 0) { 151170256Sdelphij dognreply = 0; 152170256Sdelphij argv++, argc--; 153170256Sdelphij continue; 154170256Sdelphij } 155170256Sdelphij fprintf(stderr, 156161475Sdelphij "usage: ipxrouted [ -s ] [ -q ] [ -t ] [ -g ] [ -l ] [ -N ]\n"); 157161475Sdelphij exit(1); 158161475Sdelphij } 159161475Sdelphij 160161475Sdelphij 161161475Sdelphij#ifndef DEBUG 162161475Sdelphij if (!tracepackets) 163161475Sdelphij daemon(0, 0); 164161475Sdelphij#endif 165161475Sdelphij openlog("IPXrouted", LOG_PID, LOG_DAEMON); 166161475Sdelphij 167161475Sdelphij addr.sipx_family = AF_IPX; 168161475Sdelphij addr.sipx_len = sizeof(addr); 169161475Sdelphij addr.sipx_port = htons(IPXPORT_RIP); 170161475Sdelphij ipx_anynet.s_net[0] = ipx_anynet.s_net[1] = -1; 171161475Sdelphij ipx_netmask.sipx_addr.x_net = ipx_anynet; 172161475Sdelphij ipx_netmask.sipx_len = 6; 173161475Sdelphij ipx_netmask.sipx_family = AF_IPX; 174161475Sdelphij r = socket(AF_ROUTE, SOCK_RAW, 0); 175161475Sdelphij /* later, get smart about lookingforinterfaces */ 176161475Sdelphij if (r) 177161475Sdelphij shutdown(r, 0); /* for now, don't want reponses */ 178161475Sdelphij else { 179161475Sdelphij fprintf(stderr, "IPXrouted: no routing socket\n"); 180161475Sdelphij exit(1); 181161475Sdelphij } 182161475Sdelphij ripsock = getsocket(SOCK_DGRAM, 0, &addr); 183161475Sdelphij if (ripsock < 0) 184161475Sdelphij exit(1); 185161475Sdelphij 186161475Sdelphij if (dosap) { 187161475Sdelphij addr.sipx_port = htons(IPXPORT_SAP); 188161475Sdelphij sapsock = getsocket(SOCK_DGRAM, 0, &addr); 189161475Sdelphij if (sapsock < 0) 190161475Sdelphij exit(1); 191161475Sdelphij } else 192161475Sdelphij sapsock = -1; 193161475Sdelphij 194161475Sdelphij /* 195161475Sdelphij * Any extra argument is considered 196161475Sdelphij * a tracing log file. 197161475Sdelphij */ 198161475Sdelphij if (argc > 0) 199161475Sdelphij traceon(*argv); 200161475Sdelphij /* 201161475Sdelphij * Collect an initial view of the world by 202161475Sdelphij * snooping in the kernel. Then, send a request packet on all 203161475Sdelphij * directly connected networks to find out what 204161475Sdelphij * everyone else thinks. 205161475Sdelphij */ 206161475Sdelphij rtinit(); 207161475Sdelphij sapinit(); 208161475Sdelphij ifinit(); 209161475Sdelphij if (supplier < 0) 210161475Sdelphij supplier = 0; 211161475Sdelphij /* request the state of the world */ 212128345Stjr msg->rip_cmd = htons(RIPCMD_REQUEST); 21389019Sps msg->rip_nets[0].rip_dst = ipx_anynet; 214128345Stjr msg->rip_nets[0].rip_metric = htons(HOPCNT_INFINITY); 215128345Stjr msg->rip_nets[0].rip_ticks = htons(-1); 216128345Stjr toall(sndmsg, NULL, 0); 217128345Stjr 218128345Stjr if (dosap) { 219128345Stjr sap_msg->sap_cmd = htons(SAP_REQ); 220128345Stjr sap_msg->sap[0].ServType = htons(SAP_WILDCARD); 221128345Stjr toall(sapsndmsg, NULL, 0); 222128345Stjr } 223128345Stjr 224128345Stjr signal(SIGALRM, catchtimer); 225128345Stjr signal(SIGHUP, hup); 226128345Stjr signal(SIGINT, hup); 227128345Stjr signal(SIGEMT, fkexit); 228128345Stjr signal(SIGINFO, getinfo); 229128345Stjr 230128345Stjr tval.it_interval.tv_sec = TIMER_RATE; 231128345Stjr tval.it_interval.tv_usec = 0; 232128345Stjr tval.it_value.tv_sec = TIMER_RATE; 233128345Stjr tval.it_value.tv_usec = 0; 234128345Stjr setitimer(ITIMER_REAL, &tval, NULL); 235128345Stjr 236128345Stjr nfds = 1 + max(sapsock, ripsock); 237128345Stjr 238128345Stjr for (;;) { 239128345Stjr if (dobcast) { 240128345Stjr dobcast = 0; 241128345Stjr lastbcast = time(NULL); 242128345Stjr timer(); 243128345Stjr } 244128345Stjr 24589019Sps FD_ZERO(&fdvar); 24689019Sps if (dosap) { 24789019Sps FD_SET(sapsock, &fdvar); 24889019Sps } 24989019Sps FD_SET(ripsock, &fdvar); 25089019Sps 25189019Sps if(select(nfds, &fdvar, (fd_set *)NULL, (fd_set *)NULL, 25289019Sps (struct timeval *)NULL) < 0) { 25389019Sps if(errno == EINTR) 25489019Sps continue; 25589019Sps perror("during select"); 25689019Sps exit(1); 25789019Sps } 25889019Sps 25989019Sps if(FD_ISSET(ripsock, &fdvar)) 26089019Sps process(ripsock, RIP_PKT); 26189019Sps 26289019Sps if(dosap && FD_ISSET(sapsock, &fdvar)) 26389019Sps process(sapsock, SAP_PKT); 26489019Sps 26589019Sps ttime = time(NULL); 26689019Sps if (ttime > (lastbcast + TIMER_RATE + (TIMER_RATE * 2 / 3))) { 26789019Sps dobcast = 1; 26889019Sps syslog(LOG_ERR, "Missed alarm"); 26989019Sps } 27089019Sps } 271128345Stjr} 272128345Stjr 27389019Spsvoid 274128345Stjrprocess(fd, pkt_type) 275128345Stjr int fd; 27689019Sps int pkt_type; 27789019Sps{ 27889019Sps struct sockaddr from; 27989019Sps int fromlen = sizeof (from), cc, omask; 28089019Sps struct ipx *ipxdp = (struct ipx *)packet; 28189019Sps 28289019Sps cc = recvfrom(fd, packet, sizeof (packet), 0, &from, &fromlen); 28389019Sps if (cc <= 0) { 284128345Stjr if (cc < 0 && errno != EINTR) 285128345Stjr syslog(LOG_ERR, "recvfrom: %m"); 28689019Sps return; 28789019Sps } 28889019Sps if (tracepackets > 1 && ftrace) { 28989019Sps fprintf(ftrace,"rcv %d bytes on %s ", 29089019Sps cc, ipxdp_ntoa(&ipxdp->ipx_dna)); 29189019Sps fprintf(ftrace," from %s\n", ipxdp_ntoa(&ipxdp->ipx_sna)); 29263128Sps } 29363128Sps 29463128Sps if (noteremoterequests && 29563128Sps !ipx_neteqnn(ipxdp->ipx_sna.x_net, ipx_zeronet) && 29663128Sps !ipx_neteq(ipxdp->ipx_sna, ipxdp->ipx_dna)) 29763128Sps { 29863128Sps syslog(LOG_ERR, 29963128Sps "net of interface (%s) != net on ether (%s)!\n", 30063128Sps ipxdp_nettoa(ipxdp->ipx_dna.x_net), 30163128Sps ipxdp_nettoa(ipxdp->ipx_sna.x_net)); 30263128Sps } 30363128Sps 30463128Sps /* We get the IPX header in front of the RIF packet*/ 30563128Sps cc -= sizeof (struct ipx); 30660786Sps#define mask(s) (1<<((s)-1)) 30760786Sps omask = sigblock(mask(SIGALRM)); 30860786Sps switch(pkt_type) { 30960786Sps case SAP_PKT: sap_input(&from, cc); 31060786Sps break; 31160786Sps case RIP_PKT: rip_input(&from, cc); 31260786Sps break; 31360786Sps } 31460786Sps sigsetmask(omask); 31560786Sps} 31660786Sps 31760786Spsint 31860786Spsgetsocket(type, proto, sipx) 31960786Sps int type, proto; 32060786Sps struct sockaddr_ipx *sipx; 32160786Sps{ 32260786Sps int domain = sipx->sipx_family; 32360786Sps int retry, s, on = 1; 32460786Sps 32560786Sps retry = 1; 32660786Sps while ((s = socket(domain, type, proto)) < 0 && retry) { 32760786Sps syslog(LOG_ERR, "socket: %m"); 32860786Sps sleep(5 * retry); 32960786Sps retry <<= 1; 33060786Sps } 33160786Sps if (retry == 0) 33260786Sps return (-1); 33360786Sps while (bind(s, (struct sockaddr *)sipx, sizeof (*sipx)) < 0 && retry) { 33460786Sps syslog(LOG_ERR, "bind: %m"); 33560786Sps sleep(5 * retry); 33660786Sps retry <<= 1; 33760786Sps } 33860786Sps if (retry == 0) 33960786Sps return (-1); 34060786Sps if (domain==AF_IPX) { 34160786Sps struct ipx ipxdp; 34260786Sps if (setsockopt(s, 0, SO_HEADERS_ON_INPUT, &on, sizeof(on))) { 34360786Sps syslog(LOG_ERR, "setsockopt SEE HEADERS: %m"); 34460786Sps exit(1); 34560786Sps } 34660786Sps if (ntohs(sipx->sipx_addr.x_port) == IPXPORT_RIP) 34760786Sps ipxdp.ipx_pt = IPXPROTO_RI; 34860786Sps else if (ntohs(sipx->sipx_addr.x_port) == IPXPORT_SAP) 34960786Sps#ifdef IPXPROTO_SAP 35060786Sps ipxdp.ipx_pt = IPXPROTO_SAP; 35160786Sps#else 35260786Sps ipxdp.ipx_pt = IPXPROTO_PXP; 35360786Sps#endif 35460786Sps else { 35560786Sps syslog(LOG_ERR, "port should be either RIP or SAP"); 35660786Sps exit(1); 35760786Sps } 35860786Sps if (setsockopt(s, 0, SO_DEFAULT_HEADERS, &ipxdp, sizeof(ipxdp))) { 35960786Sps syslog(LOG_ERR, "setsockopt SET HEADER: %m"); 36060786Sps exit(1); 36160786Sps } 36260786Sps } 36360786Sps if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) { 36460786Sps syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m"); 36560786Sps exit(1); 36660786Sps } 36760786Sps return (s); 36860786Sps} 36960786Sps 37060786Sps/* 37160786Sps * Fork and exit on EMT-- for profiling. 37260786Sps */ 37360786Spsvoid 37460786Spsfkexit() 37560786Sps{ 37660786Sps if (fork() == 0) 37760786Sps exit(0); 37860786Sps} 37960786Sps 38060786Spsvoid 38160786Spscatchtimer() 38260786Sps{ 38360786Sps dobcast = 1; 38460786Sps} 38560786Sps 38660786Spsvoid 38760786Spsgetinfo() 38860786Sps{ 38960786Sps FILE *fh; 39060786Sps 39160786Sps fh = fopen("/var/log/ipxrouted.dmp", "a"); 39260786Sps if(fh == NULL) 39360786Sps return; 39460786Sps 39560786Sps dumpriptable(fh); 39660786Sps dumpsaptable(fh, sap_head); 39760786Sps 39860786Sps fclose(fh); 39960786Sps} 40060786Sps 40160786Sps