Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[dragonfly.git] / usr.sbin / IPXrouted / main.c
1 /*
2  * Copyright (c) 1985, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Copyright (c) 1995 John Hay.  All rights reserved.
6  *
7  * This file includes significant work done at Cornell University by
8  * Bill Nesheim.  That work included by permission.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *      This product includes software developed by the University of
21  *      California, Berkeley and its contributors.
22  * 4. Neither the name of the University nor the names of its contributors
23  *    may be used to endorse or promote products derived from this software
24  *    without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  *
38  * $FreeBSD: src/usr.sbin/IPXrouted/main.c,v 1.10 1999/08/28 01:15:03 peter Exp $
39  * $DragonFly: src/usr.sbin/IPXrouted/main.c,v 1.2 2003/06/17 04:29:52 dillon Exp $
40  *
41  * @(#) Copyright (c) 1985, 1993 The Regents of the University of California.  All rights reserved.
42  * @(#)main.c   8.1 (Berkeley) 6/5/93
43  */
44
45 /*
46  * IPX Routing Information Protocol Daemon
47  */
48 #include "defs.h"
49 #include <sys/time.h>
50
51 #include <net/if.h>
52
53 #include <errno.h>
54 #include <nlist.h>
55 #include <signal.h>
56 #include <paths.h>
57 #include <stdlib.h>
58 #include <unistd.h>
59
60 #define SAP_PKT         0
61 #define RIP_PKT         1
62
63 struct  sockaddr_ipx addr;      /* Daemon's Address */
64 int     ripsock;                /* RIP Socket to listen on */
65 int     sapsock;                /* SAP Socket to listen on */
66 int     kmem;
67 int     install;                /* if 1 call kernel */
68 int     lookforinterfaces;      /* if 1 probe kernel for new up interfaces */
69 int     performnlist;           /* if 1 check if /kernel has changed */
70 int     externalinterfaces;     /* # of remote and local interfaces */
71 int     timeval;                /* local idea of time */
72 int     noteremoterequests;     /* squawk on requests from non-local nets */
73 int     r;                      /* Routing socket to install updates with */
74 struct  sockaddr_ipx ipx_netmask;       /* Used in installing routes */
75
76 char    packet[MAXRXPACKETSIZE+1];
77
78 char    **argv0;
79
80 int     supplier = -1;          /* process should supply updates */
81 int     dosap = 1;              /* By default do SAP services. */
82 int     dobcast = 1;            /* A RIP/SAP broadcast is needed. */
83 time_t  lastbcast;              /* Time of last RIP/SAP broadcast */
84
85 struct  rip *msg = (struct rip *) &packet[sizeof (struct ipx)]; 
86 struct  sap_packet *sap_msg = 
87                 (struct sap_packet *) &packet[sizeof (struct ipx)]; 
88 void    hup(), fkexit(), timer();
89 void    process(int fd, int pkt_type);
90 int     getsocket(int type, int proto, struct sockaddr_ipx *sipx);
91 void    getinfo();
92 void    catchtimer();
93
94 int
95 main(argc, argv)
96         int argc;
97         char *argv[];
98 {
99         int nfds;
100         fd_set fdvar;
101         time_t ttime;
102         struct itimerval tval;
103
104         argv0 = argv;
105         argv++, argc--;
106         while (argc > 0 && **argv == '-') {
107                 if (strcmp(*argv, "-s") == 0) {
108                         supplier = 1;
109                         argv++, argc--;
110                         continue;
111                 }
112                 if (strcmp(*argv, "-q") == 0) {
113                         supplier = 0;
114                         argv++, argc--;
115                         continue;
116                 }
117                 if (strcmp(*argv, "-R") == 0) {
118                         noteremoterequests++;
119                         argv++, argc--;
120                         continue;
121                 }
122                 if (strcmp(*argv, "-S") == 0) {
123                         dosap = 0;
124                         argv++, argc--;
125                         continue;
126                 }
127                 if (strcmp(*argv, "-t") == 0) {
128                         tracepackets++;
129                         argv++, argc--;
130                         ftrace = stderr;
131                         tracing = 1; 
132                         continue;
133                 }
134                 if (strcmp(*argv, "-g") == 0) {
135                         gateway = 1;
136                         argv++, argc--;
137                         continue;
138                 }
139                 if (strcmp(*argv, "-l") == 0) {
140                         gateway = -1;
141                         argv++, argc--;
142                         continue;
143                 }
144                 if (strcmp(*argv, "-N") == 0) {
145                         dognreply = 0;
146                         argv++, argc--;
147                         continue;
148                 }
149                 fprintf(stderr,
150                         "usage: ipxrouted [ -s ] [ -q ] [ -t ] [ -g ] [ -l ] [ -N ]\n");
151                 exit(1);
152         }
153         
154         
155 #ifndef DEBUG
156         if (!tracepackets)
157                 daemon(0, 0);
158 #endif
159         openlog("IPXrouted", LOG_PID, LOG_DAEMON);
160
161         addr.sipx_family = AF_IPX;
162         addr.sipx_len = sizeof(addr);
163         addr.sipx_port = htons(IPXPORT_RIP);
164         ipx_anynet.s_net[0] = ipx_anynet.s_net[1] = -1;
165         ipx_netmask.sipx_addr.x_net = ipx_anynet;
166         ipx_netmask.sipx_len = 6;
167         ipx_netmask.sipx_family = AF_IPX;
168         r = socket(AF_ROUTE, SOCK_RAW, 0);
169         /* later, get smart about lookingforinterfaces */
170         if (r)
171                 shutdown(r, 0); /* for now, don't want reponses */
172         else {
173                 fprintf(stderr, "IPXrouted: no routing socket\n");
174                 exit(1);
175         }
176         ripsock = getsocket(SOCK_DGRAM, 0, &addr);
177         if (ripsock < 0)
178                 exit(1);
179
180         if (dosap) {
181                 addr.sipx_port = htons(IPXPORT_SAP);
182                 sapsock = getsocket(SOCK_DGRAM, 0, &addr);
183                 if (sapsock < 0)
184                         exit(1);
185         } else
186                 sapsock = -1;
187
188         /*
189          * Any extra argument is considered
190          * a tracing log file.
191          */
192         if (argc > 0)
193                 traceon(*argv);
194         /*
195          * Collect an initial view of the world by
196          * snooping in the kernel.  Then, send a request packet on all
197          * directly connected networks to find out what
198          * everyone else thinks.
199          */
200         rtinit();
201         sapinit();
202         ifinit();
203         if (supplier < 0)
204                 supplier = 0;
205         /* request the state of the world */
206         msg->rip_cmd = htons(RIPCMD_REQUEST);
207         msg->rip_nets[0].rip_dst = ipx_anynet;
208         msg->rip_nets[0].rip_metric =  htons(HOPCNT_INFINITY);
209         msg->rip_nets[0].rip_ticks =  htons(-1);
210         toall(sndmsg, NULL, 0);
211
212         if (dosap) {
213                 sap_msg->sap_cmd = htons(SAP_REQ);
214                 sap_msg->sap[0].ServType = htons(SAP_WILDCARD);
215                 toall(sapsndmsg, NULL, 0);
216         }
217
218         signal(SIGALRM, catchtimer);
219         signal(SIGHUP, hup);
220         signal(SIGINT, hup);
221         signal(SIGEMT, fkexit);
222         signal(SIGINFO, getinfo);
223  
224         tval.it_interval.tv_sec = TIMER_RATE;
225         tval.it_interval.tv_usec = 0;
226         tval.it_value.tv_sec = TIMER_RATE;
227         tval.it_value.tv_usec = 0;
228         setitimer(ITIMER_REAL, &tval, NULL);
229
230         nfds = 1 + max(sapsock, ripsock);
231
232         for (;;) {
233                 if (dobcast) {
234                         dobcast = 0;
235                         lastbcast = time(NULL);
236                         timer();
237                 }
238
239                 FD_ZERO(&fdvar);
240                 if (dosap) {
241                         FD_SET(sapsock, &fdvar);
242                 }
243                 FD_SET(ripsock, &fdvar);
244
245                 if(select(nfds, &fdvar, (fd_set *)NULL, (fd_set *)NULL, 
246                    (struct timeval *)NULL) < 0) {
247                         if(errno == EINTR)
248                                 continue;
249                         perror("during select");
250                         exit(1);
251                 }
252
253                 if(FD_ISSET(ripsock, &fdvar))
254                         process(ripsock, RIP_PKT);
255
256                 if(dosap && FD_ISSET(sapsock, &fdvar))
257                         process(sapsock, SAP_PKT);
258
259                 ttime = time(NULL);
260                 if (ttime > (lastbcast + TIMER_RATE + (TIMER_RATE * 2 / 3))) {
261                         dobcast = 1;
262                         syslog(LOG_ERR, "Missed alarm");
263                 }
264         }
265 }
266
267 void
268 process(fd, pkt_type)
269         int fd;
270         int pkt_type;
271 {
272         struct sockaddr from;
273         int fromlen = sizeof (from), cc, omask;
274         struct ipx *ipxdp = (struct ipx *)packet;
275
276         cc = recvfrom(fd, packet, sizeof (packet), 0, &from, &fromlen);
277         if (cc <= 0) {
278                 if (cc < 0 && errno != EINTR)
279                         syslog(LOG_ERR, "recvfrom: %m");
280                 return;
281         }
282         if (tracepackets > 1 && ftrace) {
283             fprintf(ftrace,"rcv %d bytes on %s ", 
284                     cc, ipxdp_ntoa(&ipxdp->ipx_dna));
285             fprintf(ftrace," from %s\n", ipxdp_ntoa(&ipxdp->ipx_sna));
286         }
287         
288         if (noteremoterequests && 
289             !ipx_neteqnn(ipxdp->ipx_sna.x_net, ipx_zeronet) &&
290             !ipx_neteq(ipxdp->ipx_sna, ipxdp->ipx_dna))
291         {
292                 syslog(LOG_ERR,
293                        "net of interface (%s) != net on ether (%s)!\n",
294                        ipxdp_nettoa(ipxdp->ipx_dna.x_net),
295                        ipxdp_nettoa(ipxdp->ipx_sna.x_net));
296         }
297                         
298         /* We get the IPX header in front of the RIF packet*/
299         cc -= sizeof (struct ipx);
300 #define mask(s) (1<<((s)-1))
301         omask = sigblock(mask(SIGALRM));
302         switch(pkt_type) {
303                 case SAP_PKT: sap_input(&from, cc);
304                                 break;
305                 case RIP_PKT: rip_input(&from, cc);
306                                 break;
307         }
308         sigsetmask(omask);
309 }
310
311 int
312 getsocket(type, proto, sipx)
313         int type, proto; 
314         struct sockaddr_ipx *sipx;
315 {
316         int domain = sipx->sipx_family;
317         int retry, s, on = 1;
318
319         retry = 1;
320         while ((s = socket(domain, type, proto)) < 0 && retry) {
321                 syslog(LOG_ERR, "socket: %m");
322                 sleep(5 * retry);
323                 retry <<= 1;
324         }
325         if (retry == 0)
326                 return (-1);
327         while (bind(s, (struct sockaddr *)sipx, sizeof (*sipx)) < 0 && retry) {
328                 syslog(LOG_ERR, "bind: %m");
329                 sleep(5 * retry);
330                 retry <<= 1;
331         }
332         if (retry == 0)
333                 return (-1);
334         if (domain==AF_IPX) {
335                 struct ipx ipxdp;
336                 if (setsockopt(s, 0, SO_HEADERS_ON_INPUT, &on, sizeof(on))) {
337                         syslog(LOG_ERR, "setsockopt SEE HEADERS: %m");
338                         exit(1);
339                 }
340                 if (ntohs(sipx->sipx_addr.x_port) == IPXPORT_RIP)
341                         ipxdp.ipx_pt = IPXPROTO_RI;
342                 else if (ntohs(sipx->sipx_addr.x_port) == IPXPORT_SAP)
343 #ifdef IPXPROTO_SAP
344                         ipxdp.ipx_pt = IPXPROTO_SAP;
345 #else
346                         ipxdp.ipx_pt = IPXPROTO_PXP;
347 #endif
348                 else {
349                         syslog(LOG_ERR, "port should be either RIP or SAP");
350                         exit(1);
351                 }
352                 if (setsockopt(s, 0, SO_DEFAULT_HEADERS, &ipxdp, sizeof(ipxdp))) {
353                         syslog(LOG_ERR, "setsockopt SET HEADER: %m");
354                         exit(1);
355                 }
356         }
357         if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) {
358                 syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m");
359                 exit(1);
360         }
361         return (s);
362 }
363
364 /*
365  * Fork and exit on EMT-- for profiling.
366  */
367 void
368 fkexit()
369 {
370         if (fork() == 0)
371                 exit(0);
372 }
373
374 void
375 catchtimer()
376 {
377         dobcast = 1;
378 }
379
380 void
381 getinfo()
382 {
383         FILE *fh;
384
385         fh = fopen("/var/log/ipxrouted.dmp", "a");
386         if(fh == NULL)
387                 return;
388
389         dumpriptable(fh);
390         dumpsaptable(fh, sap_head);
391
392         fclose(fh);
393 }
394