main.c revision 122760
1147999Semax/* 2147999Semax * Copyright (c) 1985, 1993 3147999Semax * The Regents of the University of California. All rights reserved. 4147999Semax * 5147999Semax * Copyright (c) 1995 John Hay. All rights reserved. 6147999Semax * 7147999Semax * This file includes significant work done at Cornell University by 8147999Semax * Bill Nesheim. That work included by permission. 9147999Semax * 10147999Semax * Redistribution and use in source and binary forms, with or without 11147999Semax * modification, are permitted provided that the following conditions 12147999Semax * are met: 13147999Semax * 1. Redistributions of source code must retain the above copyright 14147999Semax * notice, this list of conditions and the following disclaimer. 15147999Semax * 2. Redistributions in binary form must reproduce the above copyright 16147999Semax * notice, this list of conditions and the following disclaimer in the 17147999Semax * documentation and/or other materials provided with the distribution. 18147999Semax * 3. All advertising materials mentioning features or use of this software 19147999Semax * must display the following acknowledgement: 20147999Semax * This product includes software developed by the University of 21147999Semax * California, Berkeley and its contributors. 22147999Semax * 4. Neither the name of the University nor the names of its contributors 23147999Semax * may be used to endorse or promote products derived from this software 24147999Semax * without specific prior written permission. 25147999Semax * 26147999Semax * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27147999Semax * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28147999Semax * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29147999Semax * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30147999Semax * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31147999Semax * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32147999Semax * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33147999Semax * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34162711Sru * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35147999Semax * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36297685Semaste * SUCH DAMAGE. 37147999Semax * 38147999Semax * $FreeBSD: head/usr.sbin/IPXrouted/main.c 122760 2003-11-15 17:10:56Z trhodes $ 39156167Semax */ 40147999Semax 41147999Semax#ifndef lint 42147999Semaxstatic const char copyright[] = 43147999Semax"@(#) Copyright (c) 1985, 1993\n\ 44147999Semax The Regents of the University of California. All rights reserved.\n"; 45147999Semax#endif /* not lint */ 46147999Semax 47147999Semax#ifndef lint 48147999Semaxstatic const char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/5/93"; 49147999Semax#endif /* not lint */ 50147999Semax 51147999Semax/* 52147999Semax * IPX Routing Information Protocol Daemon 53147999Semax */ 54147999Semax#include "defs.h" 55147999Semax#include <sys/time.h> 56147999Semax 57147999Semax#include <net/if.h> 58297685Semaste 59297685Semaste#include <errno.h> 60297685Semaste#include <nlist.h> 61297685Semaste#include <signal.h> 62297685Semaste#include <paths.h> 63297685Semaste#include <stdlib.h> 64297685Semaste#include <unistd.h> 65147999Semax 66147999Semax#define SAP_PKT 0 67147999Semax#define RIP_PKT 1 68147999Semax 69147999Semaxstruct sockaddr_ipx addr; /* Daemon's Address */ 70147999Semaxint ripsock; /* RIP Socket to listen on */ 71147999Semaxint sapsock; /* SAP Socket to listen on */ 72147999Semaxint kmem; 73147999Semaxint install; /* if 1 call kernel */ 74147999Semaxint lookforinterfaces; /* if 1 probe kernel for new up interfaces */ 75147999Semaxint performnlist; /* if 1 check if /kernel has changed */ 76147999Semaxint externalinterfaces; /* # of remote and local interfaces */ 77147999Semaxint timeval; /* local idea of time */ 78147999Semaxint noteremoterequests; /* squawk on requests from non-local nets */ 79147999Semaxint r; /* Routing socket to install updates with */ 80147999Semaxstruct sockaddr_ipx ipx_netmask; /* Used in installing routes */ 81147999Semax 82147999Semaxchar packet[MAXRXPACKETSIZE+1]; 83147999Semax 84147999Semaxchar **argv0; 85147999Semax 86147999Semaxint supplier = -1; /* process should supply updates */ 87147999Semaxint dosap = 1; /* By default do SAP services. */ 88147999Semaxint dobcast = 1; /* A RIP/SAP broadcast is needed. */ 89147999Semaxtime_t lastbcast; /* Time of last RIP/SAP broadcast */ 90147999Semax 91147999Semaxstruct rip *msg = (struct rip *) &packet[sizeof (struct ipx)]; 92147999Semaxstruct sap_packet *sap_msg = 93147999Semax (struct sap_packet *) &packet[sizeof (struct ipx)]; 94147999Semaxvoid hup(), fkexit(), timer(); 95147999Semaxvoid process(int fd, int pkt_type); 96147999Semaxint getsocket(int type, int proto, struct sockaddr_ipx *sipx); 97147999Semaxvoid getinfo(); 98147999Semaxvoid catchtimer(); 99147999Semax 100147999Semaxint 101147999Semaxmain(argc, argv) 102147999Semax int argc; 103147999Semax char *argv[]; 104147999Semax{ 105147999Semax int nfds; 106147999Semax fd_set fdvar; 107147999Semax time_t ttime; 108147999Semax struct itimerval tval; 109147999Semax 110147999Semax argv0 = argv; 111147999Semax argv++, argc--; 112147999Semax while (argc > 0 && **argv == '-') { 113147999Semax if (strcmp(*argv, "-s") == 0) { 114190857Semax supplier = 1; 115190857Semax argv++, argc--; 116190857Semax continue; 117190857Semax } 118147999Semax if (strcmp(*argv, "-q") == 0) { 119147999Semax supplier = 0; 120147999Semax argv++, argc--; 121147999Semax continue; 122147999Semax } 123147999Semax if (strcmp(*argv, "-R") == 0) { 124147999Semax noteremoterequests++; 125147999Semax argv++, argc--; 126147999Semax continue; 127147999Semax } 128147999Semax if (strcmp(*argv, "-S") == 0) { 129147999Semax dosap = 0; 130147999Semax argv++, argc--; 131147999Semax continue; 132147999Semax } 133147999Semax if (strcmp(*argv, "-t") == 0) { 134147999Semax tracepackets++; 135147999Semax argv++, argc--; 136147999Semax ftrace = stderr; 137147999Semax tracing = 1; 138147999Semax continue; 139147999Semax } 140147999Semax if (strcmp(*argv, "-g") == 0) { 141147999Semax gateway = 1; 142147999Semax argv++, argc--; 143147999Semax continue; 144193512Sed } 145193512Sed if (strcmp(*argv, "-l") == 0) { 146193512Sed gateway = -1; 147147999Semax argv++, argc--; 148147999Semax continue; 149147999Semax } 150147999Semax if (strcmp(*argv, "-N") == 0) { 151147999Semax dognreply = 0; 152147999Semax argv++, argc--; 153147999Semax continue; 154147999Semax } 155147999Semax fprintf(stderr, 156147999Semax "usage: ipxrouted [ -s ] [ -q ] [ -t ] [ -g ] [ -l ] [ -N ]\n"); 157147999Semax exit(1); 158147999Semax } 159147999Semax 160147999Semax 161147999Semax#ifndef DEBUG 162147999Semax if (!tracepackets) 163147999Semax daemon(0, 0); 164147999Semax#endif 165147999Semax openlog("IPXrouted", LOG_PID, LOG_DAEMON); 166147999Semax 167147999Semax addr.sipx_family = AF_IPX; 168147999Semax addr.sipx_len = sizeof(addr); 169147999Semax addr.sipx_port = htons(IPXPORT_RIP); 170147999Semax ipx_anynet.s_net[0] = ipx_anynet.s_net[1] = -1; 171147999Semax ipx_netmask.sipx_addr.x_net = ipx_anynet; 172147999Semax ipx_netmask.sipx_len = 6; 173147999Semax ipx_netmask.sipx_family = AF_IPX; 174147999Semax r = socket(AF_ROUTE, SOCK_RAW, 0); 175147999Semax /* later, get smart about lookingforinterfaces */ 176147999Semax if (r) 177147999Semax shutdown(r, 0); /* for now, don't want reponses */ 178147999Semax else { 179193512Sed fprintf(stderr, "IPXrouted: no routing socket\n"); 180193512Sed exit(1); 181193512Sed } 182193512Sed ripsock = getsocket(SOCK_DGRAM, 0, &addr); 183193512Sed if (ripsock < 0) 184193512Sed exit(1); 185193512Sed 186193512Sed if (dosap) { 187193512Sed addr.sipx_port = htons(IPXPORT_SAP); 188193512Sed sapsock = getsocket(SOCK_DGRAM, 0, &addr); 189193512Sed if (sapsock < 0) 190193512Sed exit(1); 191193512Sed } else 192193752Sed sapsock = -1; 193193512Sed 194193512Sed /* 195193752Sed * Any extra argument is considered 196193512Sed * a tracing log file. 197193512Sed */ 198193512Sed if (argc > 0) 199193512Sed traceon(*argv); 200193512Sed /* 201193512Sed * Collect an initial view of the world by 202193512Sed * snooping in the kernel. Then, send a request packet on all 203193512Sed * directly connected networks to find out what 204193512Sed * everyone else thinks. 205193512Sed */ 206193512Sed rtinit(); 207147999Semax sapinit(); 208147999Semax ifinit(); 209147999Semax if (supplier < 0) 210147999Semax supplier = 0; 211147999Semax /* request the state of the world */ 212147999Semax msg->rip_cmd = htons(RIPCMD_REQUEST); 213147999Semax msg->rip_nets[0].rip_dst = ipx_anynet; 214147999Semax msg->rip_nets[0].rip_metric = htons(HOPCNT_INFINITY); 215147999Semax msg->rip_nets[0].rip_ticks = htons(-1); 216174984Swkoszek toall(sndmsg, NULL, 0); 217147999Semax 218147999Semax if (dosap) { 219147999Semax sap_msg->sap_cmd = htons(SAP_REQ); 220147999Semax sap_msg->sap[0].ServType = htons(SAP_WILDCARD); 221147999Semax toall(sapsndmsg, NULL, 0); 222147999Semax } 223147999Semax 224147999Semax signal(SIGALRM, catchtimer); 225147999Semax signal(SIGHUP, hup); 226147999Semax signal(SIGINT, hup); 227147999Semax signal(SIGEMT, fkexit); 228147999Semax signal(SIGINFO, getinfo); 229147999Semax 230147999Semax tval.it_interval.tv_sec = TIMER_RATE; 231147999Semax tval.it_interval.tv_usec = 0; 232147999Semax tval.it_value.tv_sec = TIMER_RATE; 233147999Semax tval.it_value.tv_usec = 0; 234147999Semax setitimer(ITIMER_REAL, &tval, NULL); 235147999Semax 236147999Semax nfds = 1 + max(sapsock, ripsock); 237147999Semax 238147999Semax for (;;) { 239147999Semax if (dobcast) { 240147999Semax dobcast = 0; 241147999Semax lastbcast = time(NULL); 242147999Semax timer(); 243147999Semax } 244147999Semax 245193512Sed FD_ZERO(&fdvar); 246147999Semax if (dosap) { 247147999Semax FD_SET(sapsock, &fdvar); 248147999Semax } 249147999Semax FD_SET(ripsock, &fdvar); 250147999Semax 251147999Semax if(select(nfds, &fdvar, (fd_set *)NULL, (fd_set *)NULL, 252147999Semax (struct timeval *)NULL) < 0) { 253147999Semax if(errno == EINTR) 254147999Semax continue; 255147999Semax perror("during select"); 256147999Semax exit(1); 257147999Semax } 258147999Semax 259147999Semax if(FD_ISSET(ripsock, &fdvar)) 260147999Semax process(ripsock, RIP_PKT); 261147999Semax 262147999Semax if(dosap && FD_ISSET(sapsock, &fdvar)) 263147999Semax process(sapsock, SAP_PKT); 264147999Semax 265147999Semax ttime = time(NULL); 266147999Semax if (ttime > (lastbcast + TIMER_RATE + (TIMER_RATE * 2 / 3))) { 267156013Semax dobcast = 1; 268156013Semax syslog(LOG_ERR, "Missed alarm"); 269156013Semax } 270156013Semax } 271156013Semax} 272156013Semax 273156013Semaxvoid 274156013Semaxprocess(fd, pkt_type) 275156013Semax int fd; 276156013Semax int pkt_type; 277174984Swkoszek{ 278174984Swkoszek struct sockaddr from; 279147999Semax int fromlen = sizeof (from), cc, omask; 280156010Semax struct ipx *ipxdp = (struct ipx *)packet; 281147999Semax 282147999Semax cc = recvfrom(fd, packet, sizeof (packet), 0, &from, &fromlen); 283147999Semax if (cc <= 0) { 284147999Semax if (cc < 0 && errno != EINTR) 285147999Semax syslog(LOG_ERR, "recvfrom: %m"); 286193512Sed return; 287147999Semax } 288147999Semax if (tracepackets > 1 && ftrace) { 289147999Semax fprintf(ftrace,"rcv %d bytes on %s ", 290193512Sed cc, ipxdp_ntoa(&ipxdp->ipx_dna)); 291147999Semax fprintf(ftrace," from %s\n", ipxdp_ntoa(&ipxdp->ipx_sna)); 292147999Semax } 293147999Semax 294147999Semax if (noteremoterequests && 295147999Semax !ipx_neteqnn(ipxdp->ipx_sna.x_net, ipx_zeronet) && 296147999Semax !ipx_neteq(ipxdp->ipx_sna, ipxdp->ipx_dna)) 297147999Semax { 298147999Semax syslog(LOG_ERR, 299147999Semax "net of interface (%s) != net on ether (%s)!\n", 300147999Semax ipxdp_nettoa(ipxdp->ipx_dna.x_net), 301147999Semax ipxdp_nettoa(ipxdp->ipx_sna.x_net)); 302147999Semax } 303147999Semax 304147999Semax /* We get the IPX header in front of the RIF packet*/ 305147999Semax cc -= sizeof (struct ipx); 306147999Semax#define mask(s) (1<<((s)-1)) 307147999Semax omask = sigblock(mask(SIGALRM)); 308147999Semax switch(pkt_type) { 309147999Semax case SAP_PKT: sap_input(&from, cc); 310147999Semax break; 311147999Semax case RIP_PKT: rip_input(&from, cc); 312147999Semax break; 313147999Semax } 314147999Semax sigsetmask(omask); 315147999Semax} 316147999Semax 317147999Semaxint 318147999Semaxgetsocket(type, proto, sipx) 319147999Semax int type, proto; 320147999Semax struct sockaddr_ipx *sipx; 321147999Semax{ 322147999Semax int domain = sipx->sipx_family; 323147999Semax int retry, s, on = 1; 324147999Semax 325147999Semax retry = 1; 326147999Semax while ((s = socket(domain, type, proto)) < 0 && retry) { 327147999Semax syslog(LOG_ERR, "socket: %m"); 328147999Semax sleep(5 * retry); 329147999Semax retry <<= 1; 330147999Semax } 331147999Semax if (retry == 0) 332147999Semax return (-1); 333147999Semax while (bind(s, (struct sockaddr *)sipx, sizeof (*sipx)) < 0 && retry) { 334147999Semax syslog(LOG_ERR, "bind: %m"); 335147999Semax sleep(5 * retry); 336147999Semax retry <<= 1; 337147999Semax } 338147999Semax if (retry == 0) 339147999Semax return (-1); 340147999Semax if (domain==AF_IPX) { 341147999Semax struct ipx ipxdp; 342147999Semax if (setsockopt(s, 0, SO_HEADERS_ON_INPUT, &on, sizeof(on))) { 343147999Semax syslog(LOG_ERR, "setsockopt SEE HEADERS: %m"); 344147999Semax exit(1); 345147999Semax } 346147999Semax if (ntohs(sipx->sipx_addr.x_port) == IPXPORT_RIP) 347147999Semax ipxdp.ipx_pt = IPXPROTO_RI; 348147999Semax else if (ntohs(sipx->sipx_addr.x_port) == IPXPORT_SAP) 349147999Semax#ifdef IPXPROTO_SAP 350147999Semax ipxdp.ipx_pt = IPXPROTO_SAP; 351147999Semax#else 352147999Semax ipxdp.ipx_pt = IPXPROTO_PXP; 353147999Semax#endif 354147999Semax else { 355147999Semax syslog(LOG_ERR, "port should be either RIP or SAP"); 356147999Semax exit(1); 357147999Semax } 358147999Semax if (setsockopt(s, 0, SO_DEFAULT_HEADERS, &ipxdp, sizeof(ipxdp))) { 359147999Semax syslog(LOG_ERR, "setsockopt SET HEADER: %m"); 360147999Semax exit(1); 361147999Semax } 362147999Semax } 363147999Semax if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) { 364147999Semax syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m"); 365147999Semax exit(1); 366147999Semax } 367147999Semax return (s); 368147999Semax} 369147999Semax 370147999Semax/* 371147999Semax * Fork and exit on EMT-- for profiling. 372147999Semax */ 373147999Semaxvoid 374147999Semaxfkexit() 375147999Semax{ 376147999Semax if (fork() == 0) 377147999Semax exit(0); 378147999Semax} 379147999Semax 380147999Semaxvoid 381147999Semaxcatchtimer() 382147999Semax{ 383147999Semax dobcast = 1; 384147999Semax} 385147999Semax 386147999Semaxvoid 387147999Semaxgetinfo() 388147999Semax{ 389241885Seadler FILE *fh; 390241885Seadler 391156167Semax fh = fopen("/var/log/ipxrouted.dmp", "a"); 392147999Semax if(fh == NULL) 393147999Semax return; 394147999Semax 395147999Semax dumpriptable(fh); 396147999Semax dumpsaptable(fh, sap_head); 397147999Semax 398147999Semax fclose(fh); 399147999Semax} 400147999Semax 401147999Semax