This is main.c in view mode; [Download] [Up]
/* * $Header: /disk/d/src/devel/gated/dist/src/RCS/main.c,v 2.1 92/02/24 14:12:46 jch Exp $ */ /*%Copyright%*/ /************************************************************************ * * * GateD, Release 2 * * * * Copyright (c) 1990,1991,1992 by Cornell University * * All rights reserved. * * * * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY * * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT * * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY * * AND FITNESS FOR A PARTICULAR PURPOSE. * * * * Royalty-free licenses to redistribute GateD Release * * 2 in whole or in part may be obtained by writing to: * * * * GateDaemon Project * * Information Technologies/Network Resources * * 143 Caldwell Hall * * Cornell University * * Ithaca, NY 14853-2602 * * * * GateD is based on Kirton's EGP, UC Berkeley's routing * * daemon (routed), and DCN's HELLO routing Protocol. * * Development of Release 2 has been supported by the * * National Science Foundation. * * * * Please forward bug fixes, enhancements and questions to the * * gated mailing list: gated-people@gated.cornell.edu. * * * * Authors: * * * * Jeffrey C Honig <jch@gated.cornell.edu> * * Scott W Brim <swb@gated.cornell.edu> * * * ************************************************************************* * * * Portions of this software may fall under the following * * copyrights: * * * * Copyright (c) 1988 Regents of the University of California. * * All rights reserved. * * * * Redistribution and use in source and binary forms are * * permitted provided that the above copyright notice and * * this paragraph are duplicated in all such forms and that * * any documentation, advertising materials, and other * * materials related to such distribution and use * * acknowledge that the software was developed by the * * University of California, Berkeley. The name of the * * University may not be used to endorse or promote * * products derived from this software without specific * * prior written permission. THIS SOFTWARE IS PROVIDED * * ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, * * INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * * ************************************************************************/ /* main.c * * Main function of the EGP user process. Includes packet reception, * ICMP handler and timer interrupt handler. * * Functions: main, receive_packet, icmpin, timeout, getod, quit */ /* * Software Overview: * * At start up, the controlling function, main(), first sets tracing options * based on starting command arguments. It then calls the initialization * functions described in the next section, sets up signal handlers for * termination (SIGTERM) and timer interrupt (SIGALRM) signals, calls * task_dispatch() to start periodic interrupt processing, and finally waits in a * loop to receive incoming EGP or ICMP redirect packets * * When an EGP packet is received, egpin() is called to handle it. It in turn * calls a separate function for each EGP command type, which sends the * appropriate response. When an ICMP packet is received icmpin() is called. * * The timer interrupt routine, task_dispatch(), calls egpjob() to perform periodic * EGP processing such as reachability determination, command sending and * retransmission. It in turn calls separate functions to format each command * type. task_dispatch() also periodically calls rt_time() to increment route ages * and delete routes when too old. */ #include "include.h" #include "bgp.h" #include "egp.h" #include "hello.h" #include "icmp.h" #include "rip.h" #include "parse.h" #if defined(_IBMR2) #include <time.h> #endif /* defined(_IBMR2) */ #include <sys/time.h> #ifdef SYSV #include <sys/fcntl.h> #endif /* SYSV */ #include <sys/file.h> #ifdef SYSV #include <sys/sioctl.h> #include <sys/stropts.h> #else /* SYSV */ #include <sys/ioctl.h> #endif /* SYSV */ static int conf_file_specified; /* A config file was specified */ static int no_config_file; /* No config file present */ extern void trace_mark(); #ifdef AGENT_SNMP extern void snmp_init(); #endif /* AGENT_SNMP */ #ifndef vax11c int parse_args(argc, argv) int argc; char **argv; { int arg_n, err_flag = 0; char *arg, *cp, *ap; char seen[MAXHOSTNAMELENGTH]; trace_file = (char *) 0; memset(seen, (char) 0, MAXHOSTNAMELENGTH); for (arg_n = 1; arg_n < argc; arg_n++) { arg = argv[arg_n]; if (*arg == '-') { cp = arg + 1; if (index(seen, *cp)) { (void) fprintf(stderr, "%s: duplicate switch: %s\n", my_name, arg); err_flag++; continue; } seen[strlen(seen)] = *cp; switch (*cp++) { case 'c': /* Test configuration */ test_flag++; trace_flags_save = trace_flags = TR_GEN | TR_KRT | TR_CONFIG | TR_NOSTAMP; break; case 'n': /* Don't install in kernel */ install = FALSE; break; case 't': /* Set trace flags */ if (!(trace_flags_save = trace_args(cp))) { err_flag++; } break; case 'f': /* Specify config file */ ap = arg + 2; if (*ap == (char) 0) { if (((arg_n + 1) < argc) && (*argv[arg_n + 1] != '-')) { ap = argv[++arg_n]; } } if (*ap == (char) 0) { (void) fprintf(stderr, "%s: missing argument for switch: %s\n", my_name, arg); err_flag++; break; } EGPINITFILE = ap; conf_file_specified = TRUE; break; default: (void) fprintf(stderr, "%s: invalid switch: %s\n", my_name, arg); err_flag++; } } else if (!trace_file) { trace_file = arg; } else { (void) fprintf(stderr, "%s: extraneous information on command line: %s\n", my_name, arg); err_flag++; } } if (err_flag) { (void) fprintf(stderr, "Usage: %s [-c] [-n] [-t[flags]] [-f config-file] [trace-file]\n", my_name); } return (err_flag); } #else /* vax11c */ int parse_args(argc, argv); int argc; char **argv; { int i; for (i = 1; i < argc; i++) { if (strcasecmp(argv[i], "bootfile") == 0) { if (i >= argc) { (void) printf("ERROR: No GATED boot file specified!\n"); return (1); } i++; EGPINITFILE = argv[i]; continue; } if (strcasecmp(argv[i], "trace") == 0) { trace_flags = TR_INT | TR_EXT | TR_RT | TR_EGP; continue; } if (strcasecmp(argv[i], "trace-all") == 0) { trace_flags = TR_INT | TR_EXT | TR_RT | TR_EGP | TR_UPDATE | TR_RIP | TR_HELLO; continue; } if (strcasecmp(argv[i], "trace-internal-errors") == 0) { trace_flags |= TR_INT; continue; } if (strcasecmp(argv[i], "trace-external-changes") == 0) { trace_flags |= TR_EXT; continue; } if (strcasecmp(argv[i], "trace-routing-changes") == 0) { trace_flags |= TR_RT; continue; } if (strcasecmp(argv[i], "trace-packets") == 0) { trace_flags |= TR_EGP; continue; } if (strcasecmp(argv[i], "trace-egp-updates") == 0) { trace_flags |= TR_UPDATE; continue; } if (strcasecmp(argv[i], "trace-rip-updates") == 0) { trace_flags |= TR_RIP; continue; } if (strcasecmp(argv[i], "trace-hello-updates") == 0) { trace_flags |= TR_HELLO; continue; } #if defined(AGENT_SNMP) if (strcasecmp(argv[i], "trace-snmp") == 0) { trace_flags |= TR_SNMP; continue; } #endif /* defined(AGENT_SNMP) */ (void) printf("GATED bad arg \"%s\"\n", argv[i]); return (1); } return (0); } #endif /* vax11c */ #ifndef vax11c int main(argc, argv) #else /* vax11c */ gw_main(argc, argv) #endif /* vax11c */ int argc; char *argv[]; { #ifdef vax11c int i; #endif /* vax11c */ char *cp; FILE *fp; getod(); /* start time */ if (!(my_hostname = (char *) calloc(MAXHOSTNAMELENGTH + 1, sizeof(char)))) { trace(TR_ALL, LOG_ERR, "main: calloc: %m"); quit(errno); } if (gethostname(my_hostname, MAXHOSTNAMELENGTH + 1)) { trace(TR_ALL, LOG_ERR, "main: gethostname: %m"); quit(errno); } /* check arguments for turning on tracing and a trace file */ my_name = argv[0]; if (cp = (char *) rindex(my_name, '/')) { my_name = cp + 1; } trace_flags = trace_flags_save = 0; if (parse_args(argc, argv)) { quit(0); } task_getpaths(); #ifndef vax11c if (!test_flag) { if (getuid()) { fprintf(stderr, "%s: must be root\n", my_name); exit(2); } if (!trace_flags_save || trace_file) { /* This code rearranged after reading "Unix Network Programming" */ /* by W. Richard Stevens */ int t; /* * On System V if we were started by init from /etc/inittab there * is no need to detach. * There is some ambiguity here if we were orphaned by another * process. */ if (getppid() != 1) { /* Ignore terminal signals */ #ifdef SIGTTOU signal(SIGTTOU, SIG_IGN); #endif /* SIGTTOU */ #ifdef SIGTTIN signal(SIGTTIN, SIG_IGN); #endif /* SIGTTIN */ #ifdef SIGTSTP signal(SIGTSTP, SIG_IGN); #endif /* SIGTSTP */ #ifdef sigmask /* Prevent any SIGCHLDs until we are ready for them. */ /* Note that this will hopefully prevent the SIGCHLD */ /* signals we get when we have not fork()ed any children */ sigblock(sigmask(SIGCHLD)); #endif /* sigmask */ switch (fork()) { case 0: /* Child */ break; case -1: /* Error */ perror("main: fork"); exit(1); default: /* Parent */ exit(0); } /* Remove our association with a controling tty */ #ifdef USE_SETPGRP t = setpgrp(); if (t < 0) { perror("main: setpgrp"); exit(1); } signal(SIGHUP, SIG_IGN); /* Fork again so we are not a process group leader */ switch (fork()) { case 0: /* Child */ break; case -1: /* Error */ perror("main: fork"); exit(1); default: /* Parent */ exit(0); } #else /* USE_SETPGRP */ t = setpgrp(0, getpid()); if (t < 0) { perror("main: setpgrp"); exit(1); } t = open("/dev/tty", O_RDWR, 0); if (t >= 0) { if (ioctl(t, TIOCNOTTY, (char *) 0) < 0) { perror("main: ioctl(TIOCNOTTY)"); exit(1); } (void) close(t); } #endif /* USE_SETPGRP */ } /* Close all open files */ t = getdtablesize(); do { (void) close(--t); } while (t); /* Reset umask */ umask(0); } } my_pid = my_mpid = getpid(); #if defined(LOG_DAEMON) openlog(my_name, LOG_PID | LOG_CONS | LOG_NDELAY, LOG_FACILITY); (void) setlogmask(LOG_UPTO(LOG_NOTICE)); #else /* defined(LOG_DAEMON) */ openlog(my_name, LOG_PID); #endif /* defined(LOG_DAEMON) */ if (trace_flags_save) { (void) trace_on(trace_file, TRUE); } #endif /* vax11c */ trace(TR_ALL, 0, NULL); trace(TR_ALL, LOG_NOTICE, "Start %s[%d] version %s built %s", my_name, my_pid, version, build_date); trace(TR_ALL, 0, NULL); /* open initialization file */ no_config_file = FALSE; rt_init(); /* initialize route hash tables */ control_init(); /* initialize control info tables */ if_init(); /* initialize interface tables */ krt_init(); /* Read kernel routing table */ /* * initialize the hello_default net. */ sockclear_in(&default_net); default_net.sin_addr.s_addr = htonl((u_long) DEFAULTNET); trace(TR_TASK, 0, NULL); trace(TR_TASK, 0, "main: Initializing protocols and tasks:"); if (parse_parse(EGPINITFILE)) { /* Read the config file */ quit(0); } #if defined(PROTO_ICMP) && !defined(RTM_ADD) icmp_init(); /* Initialize to catch ICMP redirects */ #endif /* defined(PROTO_ICMP) && !defined(RTM_ADD) */ #ifdef PROTO_EGP egp_init(); #endif /* PROTO_EGP */ #ifdef PROTO_BGP bgp_init(); #endif /* PROTO_BGP */ #ifdef PROTO_RIP rip_init(); #endif /* PROTO_RIP */ #ifdef PROTO_HELLO hello_init(); #endif /* PROTO_HELLO */ #ifdef AGENT_SNMP snmp_init(); #endif /* AGENT_SNMP */ (void) timer_create((task *) 0, 0, "Time.Mark", 0, (time_t) TIME_MARK, trace_mark); trace(TR_TASK, 0, NULL); if_rtinit(); /* initialize interior routes for direct nets */ if (no_config_file #ifdef PROTO_RIP && !rip_supplier #endif /* PROTO_RIP */ && rt_locate(RTS_NETROUTE, (sockaddr_un *) & default_net, RTPROTO_KERNEL)) { trace(TR_ALL, 0, NULL); trace(TR_ALL, LOG_NOTICE, "No config file, one interface and a default route, gated exiting"); trace(TR_ALL, 0, NULL); quit(0); } trace(TR_ALL, 0, NULL); trace(TR_ALL, 0, "***Routes are %sbeing installed in kernel", install ? "" : "not "); trace(TR_ALL, 0, NULL); if (test_flag) { /* Just testing configuration */ trace_dump(TRUE); quit(0); } #ifndef vax11c fp = fopen(PIDFILE, "w"); if (fp != NULL) { (void) fprintf(fp, "%d\n", my_pid); (void) fclose(fp); } fp = fopen(VERSIONFILE, "w"); if (fp != NULL) { (void) fprintf(fp, "%s version %s built %s\n\tpid %d, started %s", my_name, version, build_date, my_pid, time_full); (void) fclose(fp); } task_init(); #endif /* vax11c */ getod(); srandom((unsigned) time_sec); trace(TR_INT, 0, NULL); trace(TR_INT, LOG_NOTICE, "Commence routing updates"); trace(TR_INT, 0, NULL); task_main(); return (0); /* To keep the complier happy */ } /* * get time of day in seconds and as an ASCII string. * Called at each interrupt and saved in external variables. */ void getod() { struct timeval tp; struct timezone tzp; struct tm *tm; if (gettimeofday(&tp, &tzp)) { trace(TR_ALL, LOG_ERR, "getod: gettimeofday: %m"); } time_sec = tp.tv_sec; tm = localtime(&tp.tv_sec); (void) sprintf(time_string, "%d/%d %02d:%02d:%02d\n", tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); (void) strcpy(time_full, (char *) ctime(&tp.tv_sec)); } /* exit gated */ void quit(code) int code; { rt_default_reset(); getod(); trace(TR_ALL, 0, NULL); switch (code) { case 0: case EDESTADDRREQ: tracef("Exit %s[%d] version %s", my_name, my_pid, version); if (code) { errno = code; tracef(": %m"); } trace(TR_ALL, LOG_NOTICE, NULL); trace(TR_ALL, 0, NULL); trace_close(); break; default: errno = code; trace(TR_ALL, LOG_NOTICE, "Abort %s[%d] version %s: %m", my_name, my_pid, version); trace(TR_ALL, 0, NULL); trace_close(); chdir(DUMPDIR); abort(); break; }; exit(code); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.