main.c revision 15248
1255570Strasz/* 2255570Strasz * Copyright (c) 1985, 1993 3255570Strasz * The Regents of the University of California. All rights reserved. 4255570Strasz * 5255570Strasz * Copyright (c) 1995 John Hay. All rights reserved. 6255570Strasz * 7255570Strasz * This file includes significant work done at Cornell University by 8255570Strasz * Bill Nesheim. That work included by permission. 9255570Strasz * 10255570Strasz * Redistribution and use in source and binary forms, with or without 11255570Strasz * modification, are permitted provided that the following conditions 12255570Strasz * are met: 13255570Strasz * 1. Redistributions of source code must retain the above copyright 14255570Strasz * notice, this list of conditions and the following disclaimer. 15255570Strasz * 2. Redistributions in binary form must reproduce the above copyright 16255570Strasz * notice, this list of conditions and the following disclaimer in the 17255570Strasz * documentation and/or other materials provided with the distribution. 18255570Strasz * 3. All advertising materials mentioning features or use of this software 19255570Strasz * must display the following acknowledgement: 20255570Strasz * This product includes software developed by the University of 21255570Strasz * California, Berkeley and its contributors. 22255570Strasz * 4. Neither the name of the University nor the names of its contributors 23255570Strasz * may be used to endorse or promote products derived from this software 24255570Strasz * without specific prior written permission. 25255570Strasz * 26255570Strasz * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27255570Strasz * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28255570Strasz * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29255570Strasz * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30255570Strasz * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31255570Strasz * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32255570Strasz * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33255570Strasz * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34255570Strasz * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35255570Strasz * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36255570Strasz * SUCH DAMAGE. 37255570Strasz * 38255570Strasz * $Id: main.c,v 1.3 1995/12/09 09:42:03 julian Exp $ 39255570Strasz */ 40255570Strasz 41255570Strasz#ifndef lint 42255570Straszstatic char copyright[] = 43255570Strasz"@(#) Copyright (c) 1985, 1993\n\ 44255570Strasz The Regents of the University of California. All rights reserved.\n"; 45255570Strasz#endif /* not lint */ 46255570Strasz 47255570Strasz#ifndef lint 48255570Straszstatic char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/5/93"; 49255570Strasz#endif /* not lint */ 50255570Strasz 51255570Strasz/* 52255570Strasz * IPX Routing Information Protocol Daemon 53255570Strasz */ 54255570Strasz#include "defs.h" 55255570Strasz#include <sys/time.h> 56255570Strasz 57255570Strasz#include <net/if.h> 58255570Strasz 59255570Strasz#include <errno.h> 60255570Strasz#include <nlist.h> 61255570Strasz#include <signal.h> 62255570Strasz#include <paths.h> 63255570Strasz#include <stdlib.h> 64255570Strasz#include <unistd.h> 65255570Strasz 66255570Strasz#define SAP_PKT 0 67255570Strasz#define RIP_PKT 1 68255570Strasz 69255570Straszstruct sockaddr_ipx addr; /* Daemon's Address */ 70255570Straszint ripsock; /* RIP Socket to listen on */ 71265498Straszint sapsock; /* SAP Socket to listen on */ 72265498Straszint kmem; 73265498Straszint install; /* if 1 call kernel */ 74265498Straszint lookforinterfaces; /* if 1 probe kernel for new up interfaces */ 75265498Straszint performnlist; /* if 1 check if /kernel has changed */ 76265498Straszint externalinterfaces; /* # of remote and local interfaces */ 77265498Straszint timeval; /* local idea of time */ 78265498Straszint noteremoterequests; /* squawk on requests from non-local nets */ 79255570Straszint r; /* Routing socket to install updates with */ 80255570Straszstruct sockaddr_ipx ipx_netmask; /* Used in installing routes */ 81255570Strasz 82255570Straszchar packet[MAXRXPACKETSIZE+1]; 83255570Strasz 84255570Straszchar **argv0; 85255570Strasz 86255570Straszint supplier = -1; /* process should supply updates */ 87255570Straszint dosap = 1; /* By default do SAP services. */ 88255570Strasz 89255570Straszstruct rip *msg = (struct rip *) &packet[sizeof (struct ipx)]; 90255570Straszstruct sap_packet *sap_msg = 91255570Strasz (struct sap_packet *) &packet[sizeof (struct ipx)]; 92255570Straszvoid hup(), fkexit(), timer(); 93255570Straszvoid process(int fd, int pkt_type); 94255570Straszint getsocket(int type, int proto, struct sockaddr_ipx *sipx); 95255570Straszvoid getinfo(); 96265495Strasz 97265495Straszint 98265495Straszmain(argc, argv) 99265495Strasz int argc; 100255570Strasz char *argv[]; 101255570Strasz{ 102255570Strasz int nfds; 103255570Strasz fd_set fdvar; 104255570Strasz 105255570Strasz argv0 = argv; 106255570Strasz argv++, argc--; 107255570Strasz while (argc > 0 && **argv == '-') { 108255570Strasz if (strcmp(*argv, "-s") == 0) { 109255570Strasz supplier = 1; 110255570Strasz argv++, argc--; 111255570Strasz continue; 112255570Strasz } 113255570Strasz if (strcmp(*argv, "-q") == 0) { 114255570Strasz supplier = 0; 115255570Strasz argv++, argc--; 116255570Strasz continue; 117255570Strasz } 118255570Strasz if (strcmp(*argv, "-R") == 0) { 119255570Strasz noteremoterequests++; 120255570Strasz argv++, argc--; 121255570Strasz continue; 122255570Strasz } 123255570Strasz if (strcmp(*argv, "-S") == 0) { 124255570Strasz dosap = 0; 125255570Strasz argv++, argc--; 126255570Strasz continue; 127255570Strasz } 128255570Strasz if (strcmp(*argv, "-t") == 0) { 129255570Strasz tracepackets++; 130255570Strasz argv++, argc--; 131255570Strasz ftrace = stderr; 132255570Strasz tracing = 1; 133255570Strasz continue; 134255570Strasz } 135255570Strasz if (strcmp(*argv, "-g") == 0) { 136255570Strasz gateway = 1; 137255570Strasz argv++, argc--; 138255570Strasz continue; 139255570Strasz } 140255570Strasz if (strcmp(*argv, "-l") == 0) { 141255570Strasz gateway = -1; 142255570Strasz argv++, argc--; 143255570Strasz continue; 144255570Strasz } 145255570Strasz fprintf(stderr, 146255570Strasz "usage: ipxrouted [ -s ] [ -q ] [ -t ] [ -g ] [ -l ]\n"); 147265488Strasz exit(1); 148255570Strasz } 149265488Strasz 150255570Strasz 151255570Strasz#ifndef DEBUG 152255570Strasz if (!tracepackets) 153265488Strasz daemon(0, 0); 154255570Strasz#endif 155265488Strasz openlog("IPXrouted", LOG_PID, LOG_DAEMON); 156255570Strasz 157255570Strasz addr.sipx_family = AF_IPX; 158255570Strasz addr.sipx_len = sizeof(addr); 159255570Strasz addr.sipx_port = htons(IPXPORT_RIP); 160255570Strasz ipx_anynet.s_net[0] = ipx_anynet.s_net[1] = -1; 161255570Strasz ipx_netmask.sipx_addr.x_net = ipx_anynet; 162255570Strasz ipx_netmask.sipx_len = 6; 163255570Strasz ipx_netmask.sipx_family = AF_IPX; 164255570Strasz r = socket(AF_ROUTE, SOCK_RAW, 0); 165255570Strasz /* later, get smart about lookingforinterfaces */ 166255570Strasz if (r) 167255570Strasz shutdown(r, 0); /* for now, don't want reponses */ 168255570Strasz else { 169255570Strasz fprintf(stderr, "IPXrouted: no routing socket\n"); 170255570Strasz exit(1); 171255570Strasz } 172255570Strasz ripsock = getsocket(SOCK_DGRAM, 0, &addr); 173255570Strasz if (ripsock < 0) 174255570Strasz exit(1); 175265488Strasz 176255570Strasz if (dosap) { 177265488Strasz addr.sipx_port = htons(IPXPORT_SAP); 178255570Strasz sapsock = getsocket(SOCK_DGRAM, 0, &addr); 179255570Strasz if (sapsock < 0) 180255570Strasz exit(1); 181255570Strasz } else 182255570Strasz sapsock = -1; 183255570Strasz 184255570Strasz /* 185255570Strasz * Any extra argument is considered 186255570Strasz * a tracing log file. 187255570Strasz */ 188255570Strasz if (argc > 0) 189255570Strasz traceon(*argv); 190255570Strasz /* 191255570Strasz * Collect an initial view of the world by 192255570Strasz * snooping in the kernel. Then, send a request packet on all 193255570Strasz * directly connected networks to find out what 194255570Strasz * everyone else thinks. 195255570Strasz */ 196255570Strasz rtinit(); 197255570Strasz sapinit(); 198255570Strasz ifinit(); 199255570Strasz if (supplier < 0) 200255570Strasz supplier = 0; 201255570Strasz /* request the state of the world */ 202255570Strasz msg->rip_cmd = htons(RIPCMD_REQUEST); 203255570Strasz msg->rip_nets[0].rip_dst = ipx_anynet; 204255570Strasz msg->rip_nets[0].rip_metric = htons(HOPCNT_INFINITY); 205255570Strasz msg->rip_nets[0].rip_ticks = htons(-1); 206255570Strasz toall(sndmsg, NULL); 207255570Strasz 208255570Strasz if (dosap) { 209255570Strasz sap_msg->sap_cmd = htons(SAP_REQ); 210255570Strasz sap_msg->sap[0].ServType = htons(SAP_WILDCARD); 211255570Strasz toall(sapsndmsg, NULL); 212255570Strasz } 213255570Strasz 214255570Strasz signal(SIGALRM, timer); 215255570Strasz signal(SIGHUP, hup); 216255570Strasz signal(SIGINT, hup); 217255570Strasz signal(SIGEMT, fkexit); 218255570Strasz signal(SIGINFO, getinfo); 219255570Strasz timer(); 220255570Strasz 221255570Strasz nfds = 1 + max(sapsock, ripsock); 222255570Strasz 223255570Strasz for (;;) { 224255570Strasz FD_ZERO(&fdvar); 225255570Strasz if (dosap) { 226255570Strasz FD_SET(sapsock, &fdvar); 227255570Strasz } 228255570Strasz FD_SET(ripsock, &fdvar); 229255570Strasz 230255570Strasz if(select(nfds, &fdvar, (fd_set *)NULL, (fd_set *)NULL, 231255570Strasz (struct timeval *)NULL) < 0) { 232255570Strasz if(errno == EINTR) 233255570Strasz continue; 234255570Strasz perror("during select"); 235255570Strasz exit(1); 236255570Strasz } 237255570Strasz 238255570Strasz if(FD_ISSET(ripsock, &fdvar)) 239255570Strasz process(ripsock, RIP_PKT); 240255570Strasz 241255570Strasz if(dosap && FD_ISSET(sapsock, &fdvar)) 242255570Strasz process(sapsock, SAP_PKT); 243255570Strasz } 244255570Strasz} 245255570Strasz 246255570Straszvoid 247255570Straszprocess(fd, pkt_type) 248255570Strasz int fd; 249255570Strasz int pkt_type; 250255570Strasz{ 251255570Strasz struct sockaddr from; 252255570Strasz int fromlen = sizeof (from), cc, omask; 253255570Strasz struct ipx *ipxdp = (struct ipx *)packet; 254255570Strasz 255255570Strasz cc = recvfrom(fd, packet, sizeof (packet), 0, &from, &fromlen); 256255570Strasz if (cc <= 0) { 257261770Strasz if (cc < 0 && errno != EINTR) 258255570Strasz syslog(LOG_ERR, "recvfrom: %m"); 259255570Strasz return; 260255570Strasz } 261255570Strasz if (tracepackets > 1 && ftrace) { 262255570Strasz fprintf(ftrace,"rcv %d bytes on %s ", 263255570Strasz cc, ipxdp_ntoa(&ipxdp->ipx_dna)); 264255570Strasz fprintf(ftrace," from %s\n", ipxdp_ntoa(&ipxdp->ipx_sna)); 265255570Strasz } 266255570Strasz 267255570Strasz if (noteremoterequests && 268255570Strasz !ipx_neteqnn(ipxdp->ipx_sna.x_net, ipx_zeronet) && 269255570Strasz !ipx_neteq(ipxdp->ipx_sna, ipxdp->ipx_dna)) 270255570Strasz { 271255570Strasz syslog(LOG_ERR, 272255570Strasz "net of interface (%s) != net on ether (%s)!\n", 273255570Strasz ipxdp_nettoa(ipxdp->ipx_dna.x_net), 274255570Strasz ipxdp_nettoa(ipxdp->ipx_sna.x_net)); 275255570Strasz } 276255570Strasz 277255570Strasz /* We get the IPX header in front of the RIF packet*/ 278255570Strasz cc -= sizeof (struct ipx); 279255570Strasz#define mask(s) (1<<((s)-1)) 280255570Strasz omask = sigblock(mask(SIGALRM)); 281255570Strasz switch(pkt_type) { 282255570Strasz case SAP_PKT: sap_input(&from, cc); 283255570Strasz break; 284255570Strasz case RIP_PKT: rip_input(&from, cc); 285255570Strasz break; 286255570Strasz } 287255570Strasz sigsetmask(omask); 288255570Strasz} 289255570Strasz 290255570Straszint 291255570Straszgetsocket(type, proto, sipx) 292255570Strasz int type, proto; 293255570Strasz struct sockaddr_ipx *sipx; 294255570Strasz{ 295255570Strasz int domain = sipx->sipx_family; 296255570Strasz int retry, s, on = 1; 297255570Strasz 298255570Strasz retry = 1; 299255570Strasz while ((s = socket(domain, type, proto)) < 0 && retry) { 300255570Strasz syslog(LOG_ERR, "socket: %m"); 301255570Strasz sleep(5 * retry); 302255570Strasz retry <<= 1; 303255570Strasz } 304255570Strasz if (retry == 0) 305255570Strasz return (-1); 306255570Strasz while (bind(s, (struct sockaddr *)sipx, sizeof (*sipx)) < 0 && retry) { 307255570Strasz syslog(LOG_ERR, "bind: %m"); 308255570Strasz sleep(5 * retry); 309255570Strasz retry <<= 1; 310255570Strasz } 311255570Strasz if (retry == 0) 312255570Strasz return (-1); 313255570Strasz if (domain==AF_IPX) { 314255570Strasz struct ipx ipxdp; 315255570Strasz if (setsockopt(s, 0, SO_HEADERS_ON_INPUT, &on, sizeof(on))) { 316255570Strasz syslog(LOG_ERR, "setsockopt SEE HEADERS: %m"); 317255570Strasz exit(1); 318255570Strasz } 319255570Strasz if (ntohs(sipx->sipx_addr.x_port) == IPXPORT_RIP) 320255570Strasz ipxdp.ipx_pt = IPXPROTO_RI; 321255570Strasz else if (ntohs(sipx->sipx_addr.x_port) == IPXPORT_SAP) 322255570Strasz ipxdp.ipx_pt = IPXPROTO_SAP; 323255570Strasz else { 324255570Strasz syslog(LOG_ERR, "port should be either RIP or SAP"); 325255570Strasz exit(1); 326255570Strasz } 327255570Strasz if (setsockopt(s, 0, SO_DEFAULT_HEADERS, &ipxdp, sizeof(ipxdp))) { 328255570Strasz syslog(LOG_ERR, "setsockopt SET HEADER: %m"); 329255570Strasz exit(1); 330255570Strasz } 331255570Strasz } 332255570Strasz if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) { 333255570Strasz syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m"); 334255570Strasz exit(1); 335255570Strasz } 336255570Strasz return (s); 337255570Strasz} 338255570Strasz 339255570Strasz/* 340255570Strasz * Fork and exit on EMT-- for profiling. 341255570Strasz */ 342261771Straszvoid 343255570Straszfkexit() 344255570Strasz{ 345255570Strasz if (fork() == 0) 346255570Strasz exit(0); 347255570Strasz} 348255570Strasz 349255570Straszvoid 350255570Straszgetinfo() 351255570Strasz{ 352255570Strasz FILE *fh; 353255570Strasz 354255570Strasz fh = fopen("/tmp/ipxrouted.dmp", "a"); 355255570Strasz if(fh == NULL) 356255570Strasz return; 357255570Strasz 358255570Strasz dumpriptable(fh); 359255570Strasz dumpsaptable(fh, sap_head); 360255570Strasz 361255570Strasz fclose(fh); 362255570Strasz} 363255570Strasz 364255570Strasz