home *** CD-ROM | disk | FTP | other *** search
- /*
- * cf.c
- *
- * Configuration program for PCroute 3.00 and packet drivers
- *
- * This program generates the configuration files for the various
- * components that together convert an ordinary PC into an IP router.
- * The necessary informations are taken from a master input file which
- * contains the configuration data in a special description language.
- *
- * This program was originaly developed with the gcc 2.4.5 compiler
- * under UNIX and was then compiled with TurboC 2.0. Therefore, it
- * shouldn't contain any compiler specific constructions.
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #include <stdarg.h>
- #include <mem.h>
- #include "cf.h"
-
- /* function prototypes */
- uint parse_handler(unchar *cp, void **ap);
- uint xlate_handler(unchar *cp, void **ap);
-
- uint net_handler(unchar *cp, void **ap);
- uint gateway_handler(unchar *cp, void **ap);
-
- uint ip_handler(unchar *cp, void **ap);
- uint dec_handler(unchar *cp, void **ap);
- uint hex_handler(unchar *cp, void **ap);
- uint str_handler(unchar *cp, void **ap);
- uint strlist_handler(unchar *cp, void **ap);
- uint set_handler(unchar *cp, void **ap);
- int fprint_ip(FILE *file, ip *inet);
- netip to_netip(ip address);
-
- void read_config(void);
- void parser(key *first);
- int get_cmd(unchar **keyword, unchar **remainder);
- key *get_key(unchar *keyword, key *first);
- xlate *get_xlate(unchar *keyword, xlate *first);
- uint get_interface(unchar *name);
- uint get_id(unchar *name);
- uint get_dupe(unchar *name, uint my_num);
- uint get_gateway(unchar *interface, unchar *link, uint limit);
- uint get_first_link(unchar *name);
- uint get_next_link(unchar *name, uint next);
- uint get_first_route(unchar *interface);
- uint get_next_route(unchar *interface, uint next);
- var *get_var(unchar *name);
- void fix_interfaces(void);
- void fix_routes(void);
- void fix_sources(void);
- void check_status(void);
- void traverse_status(key *kptr, uint ln);
- void complete_entries(void);
- uint make_flags(key *kptr);
- void write_pcroute_config(void);
- void write_ispa_config(void);
- void write_start_file(void);
- void expand_line(unchar *ptr, uint bufsize);
- void mklower(unchar *ptr);
- void *xmalloc(uint size);
- void eexit(uint line, unchar *fmt, ...);
-
-
- /*
- * The following arrays of structures contain most of the syntax rules
- * of the description language. They are used by the parser.
- */
- xlate priority[] = {
- {"emergency", 1},
- {"alert", 2},
- {"critical", 3},
- {"error", 4},
- {"warning", 5},
- {"notice", 6},
- {"info", 7},
- {"debug", 8},
- {NULL, 0}
- };
-
- key logsource[] = {
- {"system", T_OPTIONAL, S_NOTSET, NULL, NULL, 0},
- {"routing", T_OPTIONAL, S_NOTSET, NULL, NULL, 0},
- {"monitor", T_OPTIONAL, S_NOTSET, NULL, NULL, 0},
- {"endlogsource", T_TERMINAL, S_NOTSET, NULL, NULL, 0}
- };
-
- key syslog[] = {
- {"host", T_REQUIRED, S_NOTSET, ip_handler, NULL, 0},
- {"priority", T_REQUIRED, S_NOTSET, xlate_handler, priority, 0},
- {"logsource", T_REQUIRED, S_NOTSET, parse_handler, logsource, 0},
- {"endsyslog", T_TERMINAL, S_NOTSET, NULL, NULL, 0}
- };
-
- key global[] = {
- {"syslog", T_OPTIONAL, S_NOTSET, parse_handler, syslog, 0},
- {"bootp", T_OPTIONAL, S_NOTSET, ip_handler, NULL, 0},
- {"transitnet", T_OPTIONAL, S_NOTSET, ip_handler, NULL, 0},
- {"transitmask", T_OPTIONAL, S_NOTSET, ip_handler, NULL, 0},
- {"prefix", T_OPTIONAL, S_NOTSET, str_handler, NULL, 0},
- {"suffix", T_OPTIONAL, S_NOTSET, str_handler, NULL, 0},
- {"endglobal", T_TERMINAL, S_NOTSET, NULL, NULL, 0}
- };
-
- xlate itype[] = {
- {"ethernet", IT_ETHERNET},
- {"point2point", IT_POINT2POINT},
- {"isdn", IT_ISDN},
- {NULL, 0}
- };
-
- key iattributes[] = {
- {"send_rip", T_OPTIONAL, S_NOTSET, NULL, NULL, 0},
- {"listen_rip", T_OPTIONAL, S_NOTSET, NULL, NULL, 0},
- {"send_default_route", T_OPTIONAL, S_NOTSET, NULL, NULL, 0},
- {"listen_default_route", T_OPTIONAL, S_NOTSET, NULL, NULL, 0},
- {"poison_reverse", T_OPTIONAL, S_NOTSET, NULL, NULL, 0},
- {"no_directed_broadcast", T_OPTIONAL, S_NOTSET, NULL, NULL, 0},
- {"no_icmp_redirects", T_OPTIONAL, S_NOTSET, NULL, NULL, 0},
- {"hidden_interface", T_OPTIONAL, S_NOTSET, NULL, NULL, 0},
- {"host_route_split", T_OPTIONAL, S_NOTSET, NULL, NULL, 0},
- {"unreachable_network", T_OPTIONAL, S_NOTSET, NULL, NULL, 0},
- {"route_broadcasts", T_OPTIONAL, S_NOTSET, NULL, NULL, 0},
- {"global_broadcast", T_OPTIONAL, S_NOTSET, NULL, NULL, 0},
- {"broadcast_0", T_OPTIONAL, S_NOTSET, NULL, NULL, 0},
- {"proxy_arp", T_OPTIONAL, S_NOTSET, NULL, NULL, 0},
- {"no_reverse_check", T_OPTIONAL, S_NOTSET, NULL, NULL, 0},
- {"endattributes", T_TERMINAL, S_NOTSET, NULL, NULL, 0}
- };
-
- xlate dsyslog[] = {
- {"off", DS_OFF},
- {"on", DS_ON},
- {NULL, 0}
- };
-
- key idriver[] = {
- {"command", T_REQUIRED, S_NOTSET, str_handler, NULL, 0},
- {"controller", T_REQUIRED, S_NOTSET, dec_handler, NULL, 0},
- {"index", T_REQUIRED, S_NOTSET, dec_handler, NULL, 0},
- {"syslog", T_REQUIRED, S_NOTSET, xlate_handler, dsyslog, 0},
- {"options", T_OPTIONAL, S_NOTSET, str_handler, NULL, 0},
- {"prefix", T_OPTIONAL, S_NOTSET, str_handler, NULL, 0},
- {"suffix", T_OPTIONAL, S_NOTSET, str_handler, NULL, 0},
- {"enddriver", T_TERMINAL, S_NOTSET, NULL, NULL, 0}
- };
-
- key interface[] = {
- {"name", T_REQUIRED, S_NOTSET, str_handler, NULL, 0},
- {"routename", T_INHIBITED, S_NOTSET, str_handler, NULL, 0},
- {"type", T_REQUIRED, S_NOTSET, xlate_handler, itype, 0},
- {"address", T_REQUIRED, S_NOTSET, ip_handler, NULL, 0},
- {"gateway", T_OPTIONAL, S_NOTSET, ip_handler, NULL, 0},
- {"net", T_INHIBITED, S_NOTSET, ip_handler, NULL, 0},
- {"netmask", T_REQUIRED, S_NOTSET, ip_handler, NULL, 0},
- {"metric", T_REQUIRED, S_NOTSET, dec_handler, NULL, 0},
- {"attributes", T_OPTIONAL, S_NOTSET, parse_handler, iattributes, 0},
- {"driver", T_REQUIRED, S_NOTSET, parse_handler, idriver, 0},
- {"endinterface", T_TERMINAL, S_NOTSET, NULL, NULL, 0}
- };
-
- key rattributes[] = {
- {"hidden_route", T_OPTIONAL, S_NOTSET, NULL, NULL, 0},
- {"host_route_split", T_OPTIONAL, S_NOTSET, NULL, NULL, 0},
- {"transient_route", T_OPTIONAL, S_NOTSET, NULL, NULL, 0},
- {"unreachable_network", T_OPTIONAL, S_NOTSET, NULL, NULL, 0},
- {"endattributes", T_TERMINAL, S_NOTSET, NULL, NULL, 0}
- };
-
- key route[] = {
- {"name", T_REQUIRED, S_NOTSET, str_handler, NULL, 0},
- {"net", T_REQUIRED, S_NOTSET, net_handler, NULL, 0},
- {"netmask", T_REQUIRED, S_NOTSET, ip_handler, NULL, 0},
- {"interface", T_REQUIRED, S_NOTSET, str_handler, NULL, 0},
- {"link", T_OPTIONAL, S_NOTSET, str_handler, NULL, 0},
- {"gateway", T_REQUIRED, S_NOTSET, gateway_handler, NULL, 0},
- {"metric", T_REQUIRED, S_NOTSET, dec_handler, NULL, 0},
- {"attributes", T_OPTIONAL, S_NOTSET, parse_handler, rattributes, 0},
- {"endroute", T_TERMINAL, S_NOTSET, NULL, NULL, 0}
- };
-
- xlate droute[] = {
- {"deny", DR_DENY},
- {"permit", DR_PERMIT},
- {NULL, 0}
- };
-
- key source[] = {
- {"refer", T_REQUIRED, S_NOTSET, strlist_handler, NULL, 0},
- {"net", T_REQUIRED, S_NOTSET, net_handler, NULL, 0},
- {"netmask", T_REQUIRED, S_NOTSET, ip_handler, NULL, 0},
- {"attach", T_REQUIRED, S_NOTSET, strlist_handler, NULL, 0},
- {"route", T_REQUIRED, S_NOTSET, xlate_handler, droute, 0},
- {"endsource", T_TERMINAL, S_NOTSET, NULL, NULL, 0}
- };
-
- key link[] = {
- {"name", T_REQUIRED, S_NOTSET, str_handler, NULL, 0},
- {"address", T_REQUIRED, S_NOTSET, strlist_handler, NULL, 0},
- {"options", T_OPTIONAL, S_NOTSET, str_handler, NULL, 0},
- {"endlink", T_TERMINAL, S_NOTSET, NULL, NULL, 0}
- };
-
- key config[] = {
- {"global", T_OPTIONAL, S_NOTSET, parse_handler, global, 0},
- {"interface", T_REQUIRED, S_NOTSET, parse_handler, interface, 0},
- {"route", T_OPTIONAL, S_NOTSET, parse_handler, route, 0},
- {"source", T_OPTIONAL, S_NOTSET, parse_handler, source, 0},
- {"link", T_OPTIONAL, S_NOTSET, parse_handler, link, 0},
- {"set", T_OPTIONAL, S_NOTSET, set_handler, NULL, 0}
- };
-
- /* global variables and arrays */
- uint line = 1;
- uint num_globals = 0;
- uint num_interfaces = 0;
- uint num_routes = 0;
- uint num_internal_routes = 0;
- uint num_sources = 0;
- uint num_links = 0;
- FILE *src_file;
- unchar *prg_name;
- ip *default_ip;
- var *var_head = NULL;
-
- key globals[MAX_GLOBALS];
- key interfaces[MAX_INTERFACES];
- key routes[MAX_ROUTES];
- key sources[MAX_SOURCES];
- key links[MAX_LINKS];
- ip transit_nets[MAX_INTERFACES];
- ip_t transit_offsets[MAX_INTERFACES];
- int transit_use_default[MAX_INTERFACES];
- unchar default_ip_ascii[] = "0.0.0.0";
- unchar transit_net_ascii[] = TRANSIT_NET;
- unchar transit_mask_ascii[] = TRANSIT_MASK;
- unchar host_mask_ascii[] = "255.255.255.255";
- unchar pcr_cfg_base[] = PCR_CFG_BASE;
- unchar pcr_cfg_tail[] = PCR_CFG_TAIL;
- unchar pcr_cfg_name[sizeof pcr_cfg_base + sizeof pcr_cfg_tail];
- unchar ispa_cfg_base[] = ISPA_CFG_BASE;
- unchar ispa_cfg_tail[] = ISPA_CFG_TAIL;
- unchar ispa_cfg_name[sizeof ispa_cfg_base + sizeof ispa_cfg_tail];
- unchar start_file_name[] = START_FILE_NAME;
- unchar version[] = "@(#)cf.c 1.00";
-
-
- int main(int argc, char *argv[])
- {
- prg_name = argv[0];
-
- printf("INAR configuration compiler (version 1.00)\n");
-
- if (argc != 2) {
- fprintf(stderr, "%s: wrong number of arguments\n", prg_name);
- exit(2);
- }
-
- /* open the description file */
- if ((src_file = fopen(argv[1], "rt")) == NULL) {
- fprintf(stderr, "%s: can't open file `%s'\n", prg_name, argv[1]);
- exit(2);
- }
-
- /* read and parse the description */
- read_config();
- fclose(src_file);
-
- /* clean up the description's internal representation */
- fix_interfaces();
- fix_routes();
- fix_sources();
- check_status();
- complete_entries();
-
- /* now generate the various config files */
- write_pcroute_config();
- write_ispa_config();
- write_start_file();
-
- /* some statistics */
- printf("Globals: %u, Interfaces: %u, Routes: %u, Sources: %u, Links: %u\n",
- num_globals,
- num_interfaces,
- num_routes - num_internal_routes,
- num_sources,
- num_links);
- exit(0);
- }
-
- /*
- * Read the description file and parse it.
- */
- void read_config(void)
- {
- unchar *keyword, *remainder;
- register key *kptr;
-
- for (;;) {
- if (!get_cmd(&keyword, &remainder))
- return; /* return on EOF */
-
- if ((kptr = get_key(keyword, config)) == NULL)
- eexit(line, "illegal keyword `%s'", keyword);
-
- /* determine the root type of the entry */
- switch (kptr - config) {
- case 0: /* global */
- if (num_globals >= MAX_GLOBALS)
- eexit(line, "too many global entries");
- (void) memcpy((void *) &globals[num_globals],
- (void *) kptr, sizeof(key));
- kptr = &globals[num_globals];
- ++num_globals;
- break;
-
- case 1: /* interface */
- if (num_interfaces >= MAX_INTERFACES)
- eexit(line, "too many interface entries");
- (void) memcpy((void *) &interfaces[num_interfaces],
- (void *) kptr, sizeof(key));
- kptr = &interfaces[num_interfaces];
- ++num_interfaces;
- break;
-
- case 2: /* route */
- if (num_routes >= MAX_ROUTES)
- eexit(line, "too many route entries");
- (void) memcpy((void *) &routes[num_routes],
- (void *) kptr, sizeof(key));
- kptr = &routes[num_routes];
- ++num_routes;
- break;
-
- case 3: /* source */
- if (num_sources >= MAX_SOURCES)
- eexit(line, "too many source entries");
- (void) memcpy((void *) &sources[num_sources],
- (void *) kptr, sizeof(key));
- kptr = &sources[num_sources];
- ++num_sources;
- break;
-
- case 4: /* link */
- if (num_links >= MAX_LINKS)
- eexit(line, "too many link entries");
- (void) memcpy((void *) &links[num_links],
- (void *) kptr, sizeof(key));
- kptr = &links[num_links];
- ++num_links;
- break;
-
- case 5: /* set */
- {
- key dummy;
-
- (void) memcpy((void *) &dummy,
- (void *) kptr, sizeof(key));
- kptr = &dummy;
- }
- break;
-
- default:
- eexit(line, "impossible error");
- break;
- }
-
-
- /* fill in the root structure */
- kptr->line = line;
- kptr->status = S_SET;
-
- /*
- * If there is a handler for sub-keywords assigned this
- * will lead to recursive parsing of the entry.
- */
- if (kptr->handler)
- kptr->status = (*kptr->handler)(remainder, &kptr->arg);
- }
- }
-
- /*
- * Recursively parse the description file entries.
- */
- void parser(key *first)
- {
- unchar *keyword, *remainder;
- register key *kptr;
-
- for (;;) {
- if (!get_cmd(&keyword, &remainder))
- eexit(line, "unexpected end of file");
-
- if ((kptr = get_key(keyword, first)) == NULL)
- eexit(line, "illegal keyword `%s'", keyword);
-
- if (kptr->status != S_NOTSET)
- eexit(line, "duplicate keyword `%s'", keyword);
-
- /* fill in the current keyword's structure */
- kptr->line = line;
- kptr->status = S_SET;
-
- /*
- * Return if we've found the closing brace of this
- * recursion level.
- */
- if (kptr->type == T_TERMINAL)
- return;
-
- /*
- * If there is a handler for sub-keywords assigned this
- * will lead to recursive parsing of the entry.
- */
- if (kptr->handler)
- kptr->status = (*kptr->handler)(remainder, &kptr->arg);
- }
- }
-
- /*
- * Read the next line from the description file and return the keyword
- * and the remainder of the line. This function returns TRUE if it
- * delivers a valid line and FALSE on EOF.
- */
- int get_cmd(unchar **keyword, unchar **remainder)
- {
- static unchar inbuf[INBUF_SIZE];
- static uint lcnt = 0;
- register unchar *ptr;
- unchar *iptr;
- register uint c;
-
- iptr = inbuf;
- line += lcnt;
- lcnt = 0;
-
- for (;;) {
- /* read in the next line */
- if (fgets(iptr, &inbuf[INBUF_SIZE] - iptr, src_file) == NULL)
- return FALSE;
-
- /* skip leading white spaces */
- for (ptr = iptr; (c = *ptr) == ' ' || c == '\t'; ++ptr)
- ;
-
- if (ptr != iptr) {
- /* remove leading white spaces */
- (void) memmove(iptr, ptr, strlen(ptr) + 1);
- }
-
- /* fix newline */
- if ((ptr = strchr(iptr, '\n')) == NULL)
- if (feof(src_file))
- ptr = strchr(iptr, '\0');
- else
- eexit(line + lcnt, "line too long");
- else
- *ptr = '\0';
-
- ++lcnt;
-
- if (--ptr >= inbuf && *ptr == '\\') {
- iptr = ptr;
- continue;
- }
-
- /* special character handling */
- expand_line(inbuf, INBUF_SIZE);
-
- /* now get rid of trailing white spaces */
- for (ptr = strchr(inbuf, '\0') - 1;
- ptr >= inbuf && ((c = *ptr) == ' ' || c == '\t');
- --ptr)
- ;
- *++ptr = '\0';
-
- /* skip leading white spaces */
- for (ptr = inbuf; (c = *ptr) == ' ' || c == '\t'; ++ptr)
- ;
-
- if (c == '\0') {
- iptr = inbuf;
- line += lcnt;
- lcnt = 0;
- continue; /* line is empty */
- }
-
- *keyword = ptr;
-
- /* advance to the next white space or EOL */
- for (; (c = *ptr) != ' ' && c != '\t' && c != '\0'; ++ptr)
- *ptr = tolower(c);
- if (c == '\0') {
- *remainder = NULL; /* no remainder */
- return TRUE;
- }
- *ptr = '\0';
-
- /* skip white spaces */
- for (++ptr; (c = *ptr) == ' ' || c == '\t'; ++ptr)
- ;
-
- *remainder = ptr;
-
- return TRUE;
- }
- }
-
- /*
- * Lookup a keyword structure matching the current keyword. If one was
- * found return a pointer to it, otherwise NULL.
- */
- key *get_key(register unchar *keyword, key *first)
- {
- register key *kptr;
-
- /* lookup matching entry */
- for (kptr = first; kptr->type != T_TERMINAL; ++kptr)
- if (*kptr->keyword == *keyword
- && !strcmp(kptr->keyword, keyword))
- return kptr; /* found */
-
- /* check terminal entry */
- if (*kptr->keyword == *keyword
- && !strcmp(kptr->keyword, keyword))
- return kptr; /* found */
-
- return NULL; /* not found */
- }
-
- /*
- * Lookup an xlate structure matching the current keyword. If one was
- * found return a pointer to it, otherwise NULL.
- */
- xlate *get_xlate(register unchar *keyword, xlate *first)
- {
- register xlate *xptr;
-
- /* lookup matching entry */
- for (xptr = first; xptr->keyword; ++xptr)
- if (*xptr->keyword == *keyword
- && !strcmp(xptr->keyword, keyword))
- return xptr; /* found */
-
- return NULL; /* not found */
- }
-
- /*
- * Lookup an interface entry by its name.
- *
- * Must not be called before fix_interfaces() has done its job !!!
- */
- uint get_interface(unchar *name)
- {
- register key *kptr;
- register uint i;
-
- /* scan through the interface entries and compare the names */
- for (i = 0; i < num_interfaces; ++i) {
- kptr = get_key("name", (key *) interfaces[i].arg);
- if (*((unchar *) kptr->arg) == *name
- && !strcmp((unchar *) kptr->arg, name))
- return i;
- }
- fprintf(stderr, "%s: interface `%s' not found\n", prg_name, name);
- exit(2);
- }
-
- /*
- * Lookup an interface or route entry by its name.
- *
- * Must not be called before interface and route entries have been
- * completed in complete_entries() !!!
- */
- uint get_id(unchar *name)
- {
- register key *kptr;
- register uint i;
-
- /* scan through the interface entries and compare the names */
- for (i = 0; i < num_interfaces; ++i) {
- kptr = get_key("routename", (key *) interfaces[i].arg);
- if (kptr->arg == NULL)
- continue;
- if (*((unchar *) kptr->arg) == *name
- && !strcmp((unchar *) kptr->arg, name))
- return i;
- }
- /* scan through the route entries and compare the names */
- for (i = 0; i < num_routes; ++i) {
- kptr = get_key("name", (key *) routes[i].arg);
- if (*((unchar *) kptr->arg) == *name
- && !strcmp((unchar *) kptr->arg, name))
- return i + num_interfaces;
- }
- fprintf(stderr, "%s: interface/route `%s' not found or not valid\n",
- prg_name, name);
- exit(2);
- }
-
- /*
- * Lookup duplicate interface or route entries by name.
- *
- * Must not be called before fix_interfaces() and fix_routes() have
- * done their jobs !!!
- */
- uint get_dupe(unchar *name, uint my_num)
- {
- register key *kptr;
- register uint i;
- uint start;
-
- start = my_num + 1;
- if (start < num_interfaces) {
- /* scan through the interface entries and compare the names */
- for (i = start; i < num_interfaces; ++i) {
- kptr = get_key("name", (key *) interfaces[i].arg);
- if (*((unchar *) kptr->arg) == *name
- && !strcmp((unchar *) kptr->arg, name))
- return i;
- }
- start = 0;
- } else
- start -= num_interfaces;
-
- /* scan through the route entries and compare the names */
- for (i = start; i < num_routes; ++i) {
- kptr = get_key("name", (key *) routes[i].arg);
- if (*((unchar *) kptr->arg) == *name
- && !strcmp((unchar *) kptr->arg, name))
- return i + num_interfaces;
- }
-
- return my_num;
- }
-
- /*
- * Check whether there is already an entry in the route table with
- * the same interface and link name. Return its index if found,
- * otherwise the index limit (one past the last route entry).
- */
- uint get_gateway(unchar *interface, unchar *link, uint limit)
- {
- register key *kptr;
- key *first;
- register uint i;
-
- /* scan through the route entries and compare the names */
- for (i = 0; i < limit; ++i) {
- first = (key *) routes[i].arg;
- kptr = get_key("interface", first);
- if (*((unchar *) kptr->arg) != *interface
- || strcmp((unchar *) kptr->arg, interface))
- continue;
- kptr = get_key("link", first);
- if (kptr->status == S_SET && *((unchar *) kptr->arg) == *link
- && !strcmp((unchar *) kptr->arg, link))
- return i;
- }
- return limit;
- }
-
- /*
- * Get the first link that matches the given name.
- */
- uint get_first_link(unchar *name)
- {
- uint result;
-
- /* we just call get_next_link() with a start index of 0 */
- if ((result = get_next_link(name, 0)) < num_links)
- return result;
- fprintf(stderr, "%s: link `%s' not found\n", prg_name, name);
- exit(2);
- }
-
- /*
- * Get the next link that matches the given name, starting the lookup
- * at the specified index. Return its index if found, otherwise the
- * index limit (one past the last link entry).
- */
- uint get_next_link(unchar *name, uint next)
- {
- register key *kptr;
- register uint i;
-
- /* scan through the link entries and compare the names */
- for (i = next; i < num_links; ++i) {
- kptr = get_key("name", (key *) links[i].arg);
- if (*((unchar *) kptr->arg) == *name
- && !strcmp((unchar *) kptr->arg, name))
- return i;
- }
- return num_links;
- }
-
- /*
- * Get the first route that points to the given interface.
- */
- uint get_first_route(unchar *interface)
- {
- /* we just call get_next_route() with a start index of 0 */
- return get_next_route(interface, 0);
- }
-
- /*
- * Get the next route that points to the given interface, starting the
- * lookup at the specified index. Return its index if found, otherwise
- * the index limit (one past the last route entry).
- */
- uint get_next_route(unchar *interface, uint next)
- {
- register key *kptr;
- register uint i;
-
- /* scan through the route entries and compare the names */
- for (i = next; i < num_routes; ++i) {
- kptr = get_key("interface", (key *) routes[i].arg);
- if (*((unchar *) kptr->arg) == *interface
- && !strcmp((unchar *) kptr->arg, interface))
- return i;
- }
- return num_routes;
- }
-
- /*
- * Get the variable with the given name.
- */
- var *get_var(register unchar *name)
- {
- register var *vptr;
-
- for (vptr = var_head; vptr; vptr = vptr->next) {
- if (*vptr->name == *name && !strcmp(vptr->name, name))
- return vptr;
- }
- return NULL;
- }
-
- /*
- * The current keyword needs recursive parsing.
- */
- uint parse_handler(unchar *cp, void **ap)
- {
- register key *kptr;
- register void *mptr;
- uint len;
-
- if ((kptr = (key *) *ap) == NULL)
- eexit(line, "NULL argument pointer");
-
- /* calculate the length of the array we're about to copy */
- while ((kptr++)->type != T_TERMINAL)
- ;
- len = (unchar *) kptr - (unchar *) *ap;
- mptr = xmalloc(len);
- (void) memcpy(mptr, *ap, len);
-
- /* now we parse the entry */
- parser((key *) mptr);
- *ap = mptr;
- return S_TRAVERSE;
- }
-
- /*
- * The current keyword has a symbolic argument that needs to be
- * translated into a numeric argument.
- */
- uint xlate_handler(register unchar *cp, void **ap)
- {
- xlate *xptr;
- register void *mptr;
-
- if (cp == NULL)
- eexit(line, "missing argument");
- if (*ap == NULL)
- eexit(line, "NULL argument pointer");
- mklower(cp);
-
- /* lookup the matching entry */
- if ((xptr = get_xlate(cp, (xlate *) *ap)) == NULL)
- eexit(line, "illegal argument `%s'", cp);
- mptr = xmalloc(sizeof(uint));
- *((uint *) mptr) = xptr->val;
- *ap = mptr;
- return S_SET;
- }
-
- /*
- * The current keyword has a numeric IP address argument or one
- * symbolic argument.
- */
- uint net_handler(register unchar *cp, void **ap)
- {
- if (cp == NULL)
- eexit(line, "missing argument");
- mklower(cp);
- if (!strcmp("default", cp)) {
- *ap = NULL;
- return S_SET;
- }
- return ip_handler(cp, ap);
- }
-
- /*
- * The current keyword has a numeric IP address argument or one
- * symbolic argument.
- */
- uint gateway_handler(register unchar *cp, void **ap)
- {
- if (cp == NULL)
- eexit(line, "missing argument");
- mklower(cp);
- if (!strcmp("direct", cp)) {
- *ap = NULL;
- return S_SET;
- }
- return ip_handler(cp, ap);
- }
-
- /*
- * The current keyword has a numeric IP address argument.
- */
- uint ip_handler(unchar *cp, void **ap)
- {
- register void *mptr;
- uint bytes[4];
-
- if (cp == NULL)
- eexit(line, "missing argument");
- if (sscanf(cp, "%u.%u.%u.%u", &bytes[0], &bytes[1], &bytes[2],
- &bytes[3]) != 4)
- eexit(line, "illegal argument `%s'", cp);
- mptr = xmalloc(sizeof(ip));
- /* convert network byte order to internal byte order */
- ((unchar *) mptr)[3] = bytes[0];
- ((unchar *) mptr)[2] = bytes[1];
- ((unchar *) mptr)[1] = bytes[2];
- ((unchar *) mptr)[0] = bytes[3];
- *ap = mptr;
- return S_SET;
- }
-
- /*
- * The current keyword has a decimal argument.
- */
- uint dec_handler(unchar *cp, void **ap)
- {
- register void *mptr;
- uint val;
-
- if (cp == NULL)
- eexit(line, "missing argument");
- if (sscanf(cp, "%u", &val) != 1)
- eexit(line, "illegal argument `%s'", cp);
- mptr = xmalloc(sizeof(uint));
- *((uint *) mptr) = val;
- *ap = mptr;
- return S_SET;
- }
-
- /*
- * The current keyword has a hexadecimal argument.
- */
- uint hex_handler(unchar *cp, void **ap)
- {
- register void *mptr;
- uint val;
-
- if (cp == NULL)
- eexit(line, "missing argument");
- if (sscanf(cp, "%x", &val) != 1)
- eexit(line, "illegal argument `%s'", cp);
- mptr = xmalloc(sizeof(uint));
- *((uint *) mptr) = val;
- *ap = mptr;
- return S_SET;
- }
-
- /*
- * The current keyword has a character string argument.
- */
- uint str_handler(unchar *cp, void **ap)
- {
- register void *mptr;
- register uint len;
-
- if (cp == NULL)
- eexit(line, "missing argument");
- len = strlen(cp) + 1;
- mptr = xmalloc(len);
- memcpy(mptr, (void *) cp, len);
- *ap = mptr;
- return S_SET;
- }
-
- /*
- * The current keyword has a list of comma separated character
- * string arguments.
- */
- uint strlist_handler(unchar *cp, void **ap)
- {
- register unchar *cptr;
- unchar *bptr, *tcptr;
- unchar **lptr, **clptr;
- register uint c;
- uint i, lc;
-
- (void) str_handler(cp, (void **) &bptr);
-
- /* count the fields */
- for (cptr = bptr, i = 2; *cptr; ++cptr)
- if (*cptr == ',')
- ++i;
- clptr = lptr = (unchar **) xmalloc(sizeof(unchar *) * i);
- tcptr = bptr;
-
- do {
- /* skip leading white spaces */
- for (cptr = tcptr; (c = *cptr) == ' ' || c == '\t'; ++cptr)
- ;
- *clptr++ = bptr = cptr;
- /* find next field separator */
- for (; (c = *cptr) && c != ','; ++cptr)
- ;
- tcptr = cptr;
- lc = c;
- /* now get rid of trailing white spaces */
- for (--cptr; cptr >= bptr && ((c = *cptr) == ' ' || c == '\t');
- --cptr)
- ;
- *++cptr = '\0';
- ++tcptr;
- } while (lc);
-
- *clptr = NULL;
- *ap = (void *) lptr;
- return S_SET;
- }
-
- /*
- * The current keyword has a variable assignment argument.
- */
- uint set_handler(register unchar *cp, void **ap)
- {
- var *vptr;
- void *mptr;
- unchar *name, *val;
- register uint c;
- uint len;
-
- if (cp == NULL)
- eexit(line, "missing argument");
-
- name = cp;
-
- /* advance to the next white space or EOL */
- for (; (c = *cp) != ' ' && c != '\t' && c != '\0'; ++cp)
- ;
- if (c == '\0') {
- val = NULL; /* no value */
- } else {
- *cp = '\0';
-
- /* skip white spaces */
- for (++cp; (c = *cp) == ' ' || c == '\t'; ++cp)
- ;
-
- val = cp;
- }
-
- /* find or create a var object */
- if ((vptr = get_var(name)) == NULL) {
- vptr = (var *) xmalloc(sizeof(var));
- vptr->next = var_head;
- var_head = vptr;
- len = strlen(name) + 1;
- mptr = xmalloc(len);
- memcpy(mptr, (void *) name, len);
- vptr->name = (unchar *) mptr;
- } else if (vptr->val) {
- free(vptr->val);
- }
-
- /* assign a value to the var object */
- if (val == NULL) {
- vptr->val = NULL;
- } else {
- len = strlen(val) + 1;
- mptr = xmalloc(len);
- memcpy(mptr, (void *) val, len);
- vptr->val = (unchar *) mptr;
- }
- return S_SET;
- }
-
- /*
- * Print a numeric IP address.
- */
- int fprint_ip(FILE *file, register ip *inet)
- {
- return fprintf(file, "%u.%u.%u.%u", ((unchar *) inet)[3],
- ((unchar *) inet)[2],
- ((unchar *) inet)[1],
- ((unchar *) inet)[0]);
- }
-
- /*
- * Convert internal byte order to network byte order.
- */
- netip to_netip(ip address)
- {
- netip netaddress;
-
- netaddress.addr[3] = ((unchar *) &address)[0];
- netaddress.addr[2] = ((unchar *) &address)[1];
- netaddress.addr[1] = ((unchar *) &address)[2];
- netaddress.addr[0] = ((unchar *) &address)[3];
- return netaddress;
- }
-
- /*
- * Change the type field of certain keyword entries depending on the
- * kind of interface they belong to.
- */
- void fix_interfaces(void)
- {
- register key *kptr;
- register key *first;
- key *first1;
- uint i, ln, type;
-
- if (num_interfaces < 2) {
- fprintf(stderr, "%s: less than two interfaces defined\n",
- prg_name);
- exit(2);
- }
- for (i = 0; i < num_interfaces; ++i) {
- kptr = &interfaces[i];
- if (kptr->status != S_TRAVERSE || kptr->arg == NULL)
- eexit(kptr->line, "interface traverse error");
- first = (key *) kptr->arg;
-
- /* determine the interface type */
- kptr = get_key("type", first);
- if (kptr->status != S_SET || kptr->arg == NULL)
- eexit(interfaces[i].line, "interface type not set");
- type = *((uint *) (kptr->arg));
- ln = kptr->line;
-
- kptr = get_key("name", first);
- if (kptr->status != S_SET || kptr->arg == NULL)
- eexit(interfaces[i].line, "interface name not set");
-
- if (type != IT_POINT2POINT) {
- kptr = get_key("gateway", first);
- kptr->type = T_INHIBITED;
- }
-
- /*
- * We don't need several keywords if this is a
- * point-to-point interface. So we inhibit them.
- */
- if (type != IT_ETHERNET) {
- kptr = get_key("netmask", first);
- kptr->type = T_INHIBITED;
-
- kptr = get_key("attributes", first);
- if (kptr->status == S_TRAVERSE) {
- if (kptr->arg == NULL)
- eexit(kptr->line,
- "interface attributes traverse error");
- first1 = (key *) kptr->arg;
- kptr = get_key("no_directed_broadcast", first1);
- kptr->type = T_INHIBITED;
- kptr = get_key("no_icmp_redirects", first1);
- kptr->type = T_INHIBITED;
- kptr = get_key("hidden_interface", first1);
- kptr->type = T_INHIBITED;
- kptr = get_key("host_route_split", first1);
- kptr->type = T_INHIBITED;
- kptr = get_key("unreachable_network", first1);
- kptr->type = T_INHIBITED;
- kptr = get_key("route_broadcasts", first1);
- kptr->type = T_INHIBITED;
- kptr = get_key("global_broadcast", first1);
- kptr->type = T_INHIBITED;
- kptr = get_key("broadcast_0", first1);
- kptr->type = T_INHIBITED;
- kptr = get_key("proxy_arp", first1);
- kptr->type = T_INHIBITED;
- }
- }
-
- kptr = get_key("driver", first);
- if (kptr->status == S_TRAVERSE) {
- if (kptr->arg == NULL)
- eexit(kptr->line,
- "interface driver traverse error");
- first1 = (key *) kptr->arg;
-
- /*
- * Each interface type has its own set of driver
- * keywords. We inhibit those we don't need.
- */
- switch (type) {
- case IT_ETHERNET:
- case IT_POINT2POINT:
- kptr = get_key("controller", first1);
- kptr->type = T_INHIBITED;
- kptr = get_key("index", first1);
- kptr->type = T_INHIBITED;
- kptr = get_key("syslog", first1);
- kptr->type = T_INHIBITED;
- kptr = get_key("options", first1);
- kptr->type = T_INHIBITED;
- break;
-
- case IT_ISDN:
- kptr = get_key("command", first1);
- kptr->type = T_INHIBITED;
- break;
-
- default:
- eexit(ln, "impossible error");
- break;
- }
- }
- }
- }
-
- /*
- * Change the type field of certain keyword entries depending on the
- * kind of interface the route they belong to points to.
- */
- void fix_routes(void)
- {
- register key *kptr;
- register key *first;
- uint i, num, type;
-
- for (i = 0; i < num_routes; ++i) {
- kptr = &routes[i];
- if (kptr->status != S_TRAVERSE || kptr->arg == NULL)
- eexit(kptr->line, "route traverse error");
- first = (key *) kptr->arg;
-
- /* determine the interface type */
- kptr = get_key("interface", first);
- if (kptr->status != S_SET || kptr->arg == NULL)
- eexit(routes[i].line, "route interface name not set");
- num = get_interface((unchar *) kptr->arg);
- kptr = (key *) interfaces[num].arg;
- kptr = get_key("type", kptr);
- type = *((uint *) kptr->arg);
-
- kptr = get_key("net", first);
- if (kptr->status != S_SET)
- eexit(routes[i].line, "route net not set");
- if (kptr->arg == NULL) {
- kptr = get_key("netmask", first);
- kptr->type = T_INHIBITED;
- }
-
- kptr = get_key("gateway", first);
- if (type == IT_ETHERNET) {
- if (kptr->status != S_SET)
- eexit(routes[i].line, "route gateway not set");
- if (kptr->arg == NULL) {
- kptr = get_key("metric", first);
- kptr->type = T_INHIBITED;
- }
- } else
- kptr->type = T_INHIBITED;
-
- if (type != IT_ISDN) {
- kptr = get_key("link", first);
- kptr->type = T_INHIBITED;
- }
- }
- }
-
- /*
- * Change the type field of certain keyword entries depending on the
- * kind of network address.
- */
- void fix_sources(void)
- {
- register key *kptr;
- register key *first;
- uint i;
-
- for (i = 0; i < num_sources; ++i) {
- kptr = &sources[i];
- if (kptr->status != S_TRAVERSE || kptr->arg == NULL)
- eexit(kptr->line, "source traverse error");
- first = (key *) kptr->arg;
-
- kptr = get_key("refer", first);
- if (kptr->status == S_SET) {
- kptr = get_key("net", first);
- kptr->type = T_INHIBITED;
- kptr = get_key("netmask", first);
- kptr->type = T_INHIBITED;
- } else {
- kptr = get_key("net", first);
- if (kptr->status != S_SET)
- eexit(sources[i].line, "source net not set");
- if (kptr->arg == NULL) {
- kptr = get_key("netmask", first);
- kptr->type = T_INHIBITED;
- }
- kptr = get_key("refer", first);
- kptr->type = T_INHIBITED;
- }
- }
- }
-
- /*
- * Traverse through the various keyword structures and make a generic
- * check of entry type vs. entry status.
- */
- void check_status(void)
- {
- register key *kptr;
- register uint i;
-
- for (i = 0; i < num_globals; ++i) {
- kptr = &globals[i];
- if (kptr->status != S_TRAVERSE || kptr->arg == NULL)
- eexit(kptr->line, "%s traverse error", kptr->keyword);
- traverse_status((key *) kptr->arg, kptr->line);
- }
- for (i = 0; i < num_interfaces; ++i) {
- kptr = &interfaces[i];
- if (kptr->status != S_TRAVERSE || kptr->arg == NULL)
- eexit(kptr->line, "%s traverse error", kptr->keyword);
- traverse_status((key *) kptr->arg, kptr->line);
- }
- for (i = 0; i < num_routes; ++i) {
- kptr = &routes[i];
- if (kptr->status != S_TRAVERSE || kptr->arg == NULL)
- eexit(kptr->line, "%s traverse error", kptr->keyword);
- traverse_status((key *) kptr->arg, kptr->line);
- }
- for (i = 0; i < num_sources; ++i) {
- kptr = &sources[i];
- if (kptr->status != S_TRAVERSE || kptr->arg == NULL)
- eexit(kptr->line, "%s traverse error", kptr->keyword);
- traverse_status((key *) kptr->arg, kptr->line);
- }
- for (i = 0; i < num_links; ++i) {
- kptr = &links[i];
- if (kptr->status != S_TRAVERSE || kptr->arg == NULL)
- eexit(kptr->line, "%s traverse error", kptr->keyword);
- traverse_status((key *) kptr->arg, kptr->line);
- }
- }
-
- /*
- * Do the actual recursive check of entry type vs. entry status.
- */
- void traverse_status(register key *kptr, uint ln)
- {
- for (; kptr->type != T_TERMINAL; ++kptr) {
- switch (kptr->status) {
- case S_NOTSET:
- if (kptr->type == T_REQUIRED)
- eexit(ln, "missing keyword `%s'",
- kptr->keyword);
- break;
-
- case S_SET:
- if (kptr->type == T_INHIBITED)
- eexit(kptr->line,
- "illegal keyword `%s'",
- kptr->keyword);
- break;
-
- case S_TRAVERSE:
- if (kptr->type == T_INHIBITED)
- eexit(kptr->line,
- "illegal keyword `%s'",
- kptr->keyword);
- if (kptr->arg == NULL)
- eexit(kptr->line, "traverse error");
- traverse_status((key *) kptr->arg, kptr->line);
- break;
-
- default:
- eexit(ln, "impossible error");
- break;
- }
- }
- }
-
- /*
- * Fill in still missing keyword arguments that can be determined
- * automatically.
- */
- void complete_entries(void)
- {
- register key *kptr;
- register key *first;
- key *kptr2, *first2;
- void *mptr;
- unchar *cptr1, *cptr2;
- unchar **cpptr;
- ip *transit_net, *transit_mask, *host_mask;
- ip_t transit_net_size;
- ip tmp;
- uint i, num1, num2, type, cline;
-
- (void) ip_handler(default_ip_ascii, (void **) &default_ip);
- (void) ip_handler(transit_net_ascii, (void **) &transit_net);
- (void) ip_handler(transit_mask_ascii, (void **) &transit_mask);
- (void) ip_handler(host_mask_ascii, (void **) &host_mask);
-
- if (num_globals) {
- first = (key *) globals[0].arg;
- kptr = get_key("transitnet", first);
- if (kptr->status == S_SET && kptr->arg != NULL)
- transit_net = (ip *) kptr->arg;
- kptr = get_key("transitmask", first);
- if (kptr->status == S_SET && kptr->arg != NULL)
- transit_mask = (ip *) kptr->arg;
- }
-
- /* derive transit net size from transit net mask */
- transit_net_size = ~*transit_mask + 1;
-
- for (i = 0; i < num_interfaces; ++i) {
- first = (key *) interfaces[i].arg;
- kptr = get_key("name", first);
- num1 = get_dupe((unchar *) kptr->arg, i);
- if (num1 != i) {
- kptr = (num1 < num_interfaces)
- ? (key *) interfaces[num1].arg
- : (key *) routes[num1 - num_interfaces].arg;
- kptr = get_key("name", kptr);
- eexit(kptr->line, "duplicate interface/route name");
- }
- kptr = get_key("type", first);
- type = *((uint *) kptr->arg);
-
- if (type == IT_ETHERNET) {
- kptr = get_key("address", first);
- tmp = *((ip *) kptr->arg);
- kptr = get_key("netmask", first);
- tmp &= *((ip *) kptr->arg);
- kptr = get_key("net", first);
- mptr = xmalloc(sizeof(ip));
- *((ip *) mptr) = tmp;
- kptr->arg = mptr;
- kptr->status = S_SET;
-
- kptr = get_key("name", first);
- kptr2 = get_key("routename", first);
- kptr2->arg = kptr->arg;
- kptr->status = S_SET;
- } else {
- kptr = get_key("net", first);
- mptr = xmalloc(sizeof(ip));
- *((ip *) mptr) = *transit_net;
- kptr->arg = mptr;
- kptr->status = S_SET;
-
- kptr = get_key("netmask", first);
- mptr = xmalloc(sizeof(ip));
- *((ip *) mptr) = *transit_mask;
- kptr->arg = mptr;
- kptr->status = S_SET;
-
- /*
- * set the first transit net address for
- * each point-to-point interface.
- */
- kptr = get_key("gateway", first);
- if (kptr->status == S_SET) {
- /* only for type point2point */
- transit_nets[i] = *((ip *) kptr->arg);
- transit_offsets[i] = 0;
-
- /* construct a direct route for the gateway */
- cline = kptr->line;
- if (num_routes >= MAX_ROUTES)
- eexit(cline, "too many route entries");
- /* insert route in front of any other route */
- if (num_routes)
- (void) memmove((void *) &routes[1],
- (void *) &routes[0],
- sizeof(key)
- * num_routes);
- ++num_routes;
- ++num_internal_routes;
- kptr = &routes[0];
- (void) memcpy((void *) kptr,
- (void *) &config[2],
- sizeof(key));
-
- mptr = xmalloc(sizeof route);
- (void) memcpy(mptr, (void *) route,
- sizeof route);
- kptr->arg = mptr;
- kptr->line = cline;
- kptr->status = S_TRAVERSE;
-
- first2 = (key *) mptr;
- kptr = get_key("name", first2);
- kptr2 = get_key("name", first);
- kptr->arg = kptr2->arg;
- kptr->line = cline;
- kptr->status = S_SET;
-
- kptr = get_key("net", first2);
- mptr = xmalloc(sizeof(ip));
- *((ip *) mptr) = transit_nets[i];
- kptr->arg = mptr;
- kptr->line = cline;
- kptr->status = S_SET;
-
- kptr = get_key("netmask", first2);
- mptr = xmalloc(sizeof(ip));
- *((ip *) mptr) = *host_mask;
- kptr->arg = mptr;
- kptr->line = cline;
- kptr->status = S_SET;
-
- kptr = get_key("interface", first2);
- kptr2 = get_key("name", first);
- kptr->arg = kptr2->arg;
- kptr->line = cline;
- kptr->status = S_SET;
-
- kptr = get_key("gateway", first2);
- mptr = xmalloc(sizeof(ip));
- *((ip *) mptr) = *transit_net;
- kptr->arg = mptr;
- kptr->line = cline;
- kptr->status = S_SET;
-
- kptr = get_key("metric", first2);
- mptr = xmalloc(sizeof(uint));
- *((uint *) mptr) = 0;
- kptr->arg = mptr;
- kptr->line = cline;
- kptr->status = S_SET;
-
- kptr = get_key("attributes", first2);
- mptr = xmalloc(sizeof rattributes);
- (void) memcpy(mptr, (void *) rattributes,
- sizeof rattributes);
- kptr->arg = mptr;
- kptr->line = cline;
- kptr->status = S_TRAVERSE;
-
- first2 = (key *) mptr;
- kptr = get_key("hidden_route", first2);
- kptr->line = cline;
- kptr->status = S_SET;
- } else {
- transit_nets[i] = *transit_net;
- transit_offsets[i] = 1;
- }
- *transit_net += transit_net_size;
- }
- }
-
- for (i = 0; i < num_routes; ++i) {
- first = (key *) routes[i].arg;
- kptr = get_key("name", first);
- num1 = get_dupe((unchar *) kptr->arg, i + num_interfaces);
- if (num1 != i + num_interfaces) {
- kptr = (num1 < num_interfaces)
- ? (key *) interfaces[num1].arg
- : (key *) routes[num1 - num_interfaces].arg;
- kptr = get_key("name", kptr);
- eexit(kptr->line, "duplicate interface/route name");
- }
- kptr = get_key("interface", first);
- cptr1 = (unchar *) kptr->arg;
- num1 = get_interface(cptr1);
- kptr = get_key("type", (key *) interfaces[num1].arg);
- type = *((uint *) kptr->arg);
-
- kptr = get_key("net", first);
- if (kptr->arg == NULL) {
- kptr->arg = (void *) default_ip;
- kptr->status = S_SET;
- kptr = get_key("netmask", first);
- kptr->arg = (void *) default_ip;
- kptr->status = S_SET;
- } else {
- tmp = *((ip *) kptr->arg);
- kptr2 = get_key("netmask", first);
- tmp &= *((ip *) kptr2->arg);
- if (tmp != *((ip *) kptr->arg))
- eexit(kptr2->line,
- "netmask doesn't match route net");
- }
-
- switch (type) {
- case IT_ETHERNET:
- kptr = get_key("gateway", first);
- if (kptr->arg == NULL) {
- kptr2 = get_key("net",
- (key *) interfaces[num1].arg);
- kptr->arg = kptr2->arg;
- kptr->status = S_SET;
- kptr = get_key("metric", first);
- mptr = xmalloc(sizeof(uint));
- *((uint *) mptr) = 0;
- kptr->arg = mptr;
- kptr->status = S_SET;
- }
- break;
-
- case IT_POINT2POINT:
- kptr = get_key("gateway", first);
- if (kptr->status != S_SET) {
- mptr = xmalloc(sizeof(ip));
- *((ip *) mptr) = transit_nets[num1]
- + transit_offsets[num1];
- kptr->arg = mptr;
- kptr->status = S_SET;
- }
- break;
-
- case IT_ISDN:
- kptr = get_key("link", first);
- if (kptr->status != S_SET) {
- transit_use_default[num1] = TRUE;
- kptr = get_key("gateway", first);
- mptr = xmalloc(sizeof(ip));
- *((ip *) mptr) = transit_nets[num1] + 1;
- kptr->arg = mptr;
- kptr->status = S_SET;
- break;
- }
-
- cptr2 = (unchar *) kptr->arg;
- (void) get_first_link(cptr2);
- num2 = get_gateway(cptr1, cptr2, i);
- /*
- * Determine the transit net address for
- * this route. Calculate a new address if
- * we can't use an already existing one.
- */
- if (num2 == i) {
- /* not found */
- if (++transit_offsets[num1]
- >= (transit_net_size - 1))
- eexit(kptr->line,
- "too many links for interface `%s'",
- cptr1);
- kptr = get_key("gateway", first);
- mptr = xmalloc(sizeof(ip));
- *((ip *) mptr) = transit_nets[num1]
- + transit_offsets[num1];
- kptr->arg = mptr;
- kptr->status = S_SET;
- } else {
- /* found */
- kptr = get_key("gateway", first);
- kptr2 = get_key("gateway",
- (key *) routes[num2].arg);
- kptr->arg = kptr2->arg;
- kptr->status = S_SET;
- }
- break;
-
- default:
- eexit(routes[i].line, "impossible error");
- break;
- }
- }
-
- for (i = 0; i < num_sources; ++i) {
- first = (key *) sources[i].arg;
-
- kptr = get_key("net", first);
- if (kptr->status == S_SET) {
- if (kptr->arg == NULL) {
- kptr->arg = (void *) default_ip;
- kptr->status = S_SET;
- kptr = get_key("netmask", first);
- kptr->arg = (void *) default_ip;
- kptr->status = S_SET;
- } else {
- tmp = *((ip *) kptr->arg);
- kptr2 = get_key("netmask", first);
- tmp &= *((ip *) kptr2->arg);
- if (tmp != *((ip *) kptr->arg))
- eexit(kptr2->line,
- "netmask doesn't match source net");
- }
- }
-
- /*
- * Check whether the refered and attached interfaces/routes
- * really exist.
- */
- kptr = get_key("refer", first);
- if (kptr->status == S_SET && kptr->arg != NULL)
- for (cpptr = (unchar **) kptr->arg; *cpptr; ++cpptr)
- (void) get_id(*cpptr);
-
- kptr = get_key("attach", first);
- for (cpptr = (unchar **) kptr->arg; *cpptr; ++cpptr) {
- cptr1 = *cpptr;
- if (cptr1[0] == '+') {
- if (cptr1[1] != '\0')
- (void) get_interface(cptr1 + 1);
- } else if (cptr1[0] != '*' || cptr1[1] != '\0')
- (void) get_id(cptr1);
- }
- }
- }
-
- /*
- * Convert attribute keywords to bit flags.
- */
- uint make_flags(register key *kptr)
- {
- uint flags = 0;
- register uint mask;
-
- for (mask = 1; kptr->type != T_TERMINAL; ++kptr, mask <<= 1)
- if (kptr->status == S_SET)
- flags |= mask;
- return flags;
- }
-
- /*
- * Write the PCroute config file.
- */
- void write_pcroute_config(void)
- {
- FILE *pcroute_file;
- register key *kptr;
- register key *first;
- key *kptr1, *first1;
- unchar *cptr;
- unchar **cpptr, **cpptr1;
- uint i, type, flags, id, src_cnt, cnt;
- int refer;
- ushort count;
- pcr_header head;
- pcr_interface ifc;
- pcr_route rt;
- pcr_bootp bp;
- pcr_syslog sl;
-
- (void) sprintf(pcr_cfg_name, "%s%u%s", pcr_cfg_base, num_interfaces,
- pcr_cfg_tail);
- (void) unlink(pcr_cfg_name);
- if ((pcroute_file = fopen(pcr_cfg_name, "wb")) == NULL) {
- fprintf(stderr, "%s: can't open file `%s'\n", prg_name,
- pcr_cfg_name);
- exit(2);
- }
-
- /* interfaces */
- head.type = IF_TYPE;
- head.version = IF_VERSION;
- head.len = sizeof ifc;
-
- for (i = 0; i < num_interfaces; ++i) {
- if (fwrite((void *) &head, sizeof head, 1, pcroute_file) != 1) {
- fprintf(stderr, "%s: error writing file `%s'\n",
- prg_name, pcr_cfg_name);
- exit(2);
- }
-
- first = (key *) interfaces[i].arg;
- kptr = get_key("type", first);
- type = *((uint *) kptr->arg);
-
- kptr = get_key("address", first);
- ifc.address = to_netip(*((ip *) kptr->arg));
- kptr = get_key("net", first);
- ifc.net = to_netip(*((ip *) kptr->arg));
- kptr = get_key("netmask", first);
- ifc.netmask = to_netip(*((ip *) kptr->arg));
- kptr = get_key("metric", first);
- ifc.metric = (ushort) *((uint *) kptr->arg);
- flags = 0;
- kptr = get_key("attributes", first);
- if (kptr->status == S_TRAVERSE && kptr->arg != NULL)
- flags = make_flags((key *) kptr->arg);
- if (type != IT_ETHERNET)
- flags |= 0x2e0;
- ifc.flags = (ushort) flags;
- ifc.id = i + num_interfaces + 2;
-
- if (fwrite((void *) &ifc, sizeof ifc, 1, pcroute_file) != 1) {
- fprintf(stderr, "%s: error writing file `%s'\n",
- prg_name, pcr_cfg_name);
- exit(2);
- }
- }
-
- /* routes and sources */
- /* calculate the real number of source routes */
- src_cnt = 0;
- for (i = 0; i < num_sources; ++i) {
- first = (key *) sources[i].arg;
- kptr = get_key("refer", first);
- if (kptr->status == S_SET && kptr->arg != NULL) {
- cnt = 0;
- for (cpptr = (unchar **) kptr->arg; *cpptr; ++cpptr)
- ++cnt;
- } else
- cnt = 1;
- kptr = get_key("attach", first);
- for (cpptr = (unchar **) kptr->arg; *cpptr; ++cpptr)
- src_cnt += cnt;
- }
-
- head.type = RT_TYPE;
- head.version = RT_VERSION;
- head.len = sizeof rt * (num_routes + src_cnt) + sizeof count;
- if (fwrite((void *) &head, sizeof head, 1, pcroute_file) != 1) {
- fprintf(stderr, "%s: error writing file `%s'\n", prg_name,
- pcr_cfg_name);
- exit(2);
- }
-
- count = num_routes + src_cnt;
- if (fwrite((void *) &count, sizeof count, 1, pcroute_file) != 1) {
- fprintf(stderr, "%s: error writing file `%s'\n", prg_name,
- pcr_cfg_name);
- exit(2);
- }
-
- for (i = 0; i < num_routes; ++i) {
- first = (key *) routes[i].arg;
-
- kptr = get_key("net", first);
- rt.net = to_netip(*((ip *) kptr->arg));
- kptr = get_key("netmask", first);
- rt.netmask = to_netip(*((ip *) kptr->arg));
- kptr = get_key("gateway", first);
- rt.gateway = to_netip(*((ip *) kptr->arg));
- kptr = get_key("metric", first);
- rt.metric = (unchar) *((uint *) kptr->arg);
- flags = 0;
- kptr = get_key("attributes", first);
- if (kptr->status == S_TRAVERSE && kptr->arg != NULL)
- flags = make_flags((key *) kptr->arg);
- rt.flags = (unchar) flags;
- rt.id = i + num_interfaces * 2 + 2;
-
- if (fwrite((void *) &rt, sizeof rt, 1, pcroute_file) != 1) {
- fprintf(stderr, "%s: error writing file `%s'\n",
- prg_name, pcr_cfg_name);
- exit(2);
- }
- }
-
- for (i = 0; i < num_sources; ++i) {
- first = (key *) sources[i].arg;
-
- rt.gateway = to_netip(*((ip *) default_ip));
- rt.metric = 0;
- kptr = get_key("route", first);
- if (*((uint *) kptr->arg) == DR_DENY)
- rt.flags = 0x50;
- else
- rt.flags = 0x40;
- kptr = get_key("refer", first);
- if (kptr->status == S_SET && kptr->arg != NULL) {
- refer = TRUE;
- cpptr1 = (unchar **) kptr->arg;
- } else
- refer = FALSE;
-
- do {
- if (refer) {
- id = get_id(*cpptr1);
- if (id < num_interfaces)
- first1 = (key *) interfaces[id].arg;
- else
- first1 = (key *) routes[id
- - num_interfaces].arg;
- kptr1 = get_key("net", first1);
- rt.net = to_netip(*((ip *) kptr1->arg));
- kptr1 = get_key("netmask", first1);
- rt.netmask = to_netip(*((ip *) kptr1->arg));
- } else {
- kptr = get_key("net", first);
- rt.net = to_netip(*((ip *) kptr->arg));
- kptr = get_key("netmask", first);
- rt.netmask = to_netip(*((ip *) kptr->arg));
- }
-
- kptr = get_key("attach", first);
- for (cpptr = (unchar **) kptr->arg; *cpptr; ++cpptr) {
- cptr = *cpptr;
- if (cptr[0] == '*' && cptr[1] == '\0')
- rt.id = 0;
- else if (cptr[0] == '+') {
- if (cptr[1] == '\0')
- rt.id = 1;
- else
- rt.id = get_interface(cptr + 1)
- + 2;
- } else
- rt.id = get_id(cptr) + num_interfaces
- + 2;
-
- if (fwrite((void *) &rt, sizeof rt, 1,
- pcroute_file) != 1) {
- fprintf(stderr,
- "%s: error writing file `%s'\n",
- prg_name, pcr_cfg_name);
- exit(2);
- }
- }
- } while (refer && *++cpptr1);
- }
-
- /* bootp */
- head.type = BP_TYPE;
- head.version = BP_VERSION;
- head.len = sizeof bp;
- if (fwrite((void *) &head, sizeof head, 1, pcroute_file) != 1) {
- fprintf(stderr, "%s: error writing file `%s'\n", prg_name,
- pcr_cfg_name);
- exit(2);
- }
-
- bp.forward_address = to_netip(*default_ip);
-
- if (num_globals) {
- first = (key *) globals[0].arg;
- kptr = get_key("bootp", first);
- if (kptr->status == S_SET && kptr->arg != NULL)
- bp.forward_address = to_netip(*((ip *) kptr->arg));
- }
- if (fwrite((void *) &bp, sizeof bp, 1, pcroute_file) != 1) {
- fprintf(stderr, "%s: error writing file `%s'\n",
- prg_name, pcr_cfg_name);
- exit(2);
- }
-
- /* syslog */
- head.type = SL_TYPE;
- head.version = SL_VERSION;
- head.len = sizeof sl;
- if (fwrite((void *) &head, sizeof head, 1, pcroute_file) != 1) {
- fprintf(stderr, "%s: error writing file `%s'\n", prg_name,
- pcr_cfg_name);
- exit(2);
- }
-
- sl.log_host = to_netip(*default_ip);
- sl.log_priority = 0;
- sl.log_mask = 0xf;
-
- if (num_globals) {
- kptr = get_key("syslog", (key *) globals[0].arg);
- if (kptr->status == S_TRAVERSE && kptr->arg != NULL) {
- first = (key *) kptr->arg;
- kptr = get_key("host", first);
- sl.log_host = to_netip(*((ip *) kptr->arg));
- kptr = get_key("priority", first);
- sl.log_priority = (ushort) *((uint *) kptr->arg);
- flags = 0;
- kptr = get_key("logsource", first);
- if (kptr->status == S_TRAVERSE && kptr->arg != NULL)
- flags = make_flags((key *) kptr->arg);
- sl.log_mask = (ushort) (flags ^ 0xf);
- }
- }
- if (fwrite((void *) &sl, sizeof sl, 1, pcroute_file) != 1) {
- fprintf(stderr, "%s: error writing file `%s'\n",
- prg_name, pcr_cfg_name);
- exit(2);
- }
-
- if (fclose(pcroute_file)) {
- fprintf(stderr, "%s: can't close file `%s'\n", prg_name,
- pcr_cfg_name);
- exit(2);
- }
- }
-
- /*
- * Write the ISPA config file(s).
- */
- void write_ispa_config(void)
- {
- FILE *ispa_file;
- register key *kptr;
- register key *first;
- key *kptr2, *first2;
- ip *gptr;
- unchar *cptr;
- ip transit, transit_net;
- uint i, num, num2, inum, type, cnt;
-
- transit = 0;
- inum = 1;
- for (i = 0; i < num_interfaces; ++i) {
- first = (key *) interfaces[i].arg;
- kptr = get_key("type", first);
- type = *((uint *) kptr->arg);
- if (type != IT_ISDN)
- continue;
-
- (void) sprintf(ispa_cfg_name, "%s%u%s", ispa_cfg_base, inum,
- ispa_cfg_tail);
- (void) unlink(ispa_cfg_name);
- if ((ispa_file = fopen(ispa_cfg_name, "wt")) == NULL) {
- fprintf(stderr, "%s: can't open file `%s'\n", prg_name,
- ispa_cfg_name);
- exit(2);
- }
-
- cnt = 0;
- kptr = get_key("name", first);
- cptr = (unchar *) kptr->arg;
- if ((num = get_first_route(cptr)) != num_routes) {
- do {
- first = (key *) routes[num].arg;
- kptr = get_key("gateway", first);
- gptr = (ip *) kptr->arg;
- if (*gptr <= transit)
- continue;
- transit = *gptr;
- kptr = get_key("link", first);
- if (kptr->status != S_SET)
- continue;
- num2 = get_first_link((unchar *) kptr->arg);
- do {
- fprint_ip(ispa_file, gptr);
- first2 = (key *) links[num2].arg;
- kptr2 = get_key("address", first2);
- fprintf(ispa_file, " %s",
- ((unchar **) kptr2->arg)[0]);
- if (((unchar **) kptr2->arg)[1] != NULL)
- fprintf(ispa_file, " %s",
- ((unchar **) kptr2->arg)[1]);
- kptr2 = get_key("options", first2);
- if (kptr2->status == S_SET
- && kptr2->arg != NULL)
- fprintf(ispa_file, " %s",
- (unchar *) kptr2->arg);
- fprintf(ispa_file, "\n");
- ++cnt;
- } while ((num2 = get_next_link(
- (unchar *) kptr->arg,
- num2 + 1)) < num_links);
- } while ((num = get_next_route(cptr, num + 1))
- < num_routes);
- }
-
- if (cnt == 0) {
- /* dummy entry */
- transit_net = transit_nets[i] + 2;
- fprint_ip(ispa_file, &transit_net);
- fprintf(ispa_file, " 0000\n");
- }
-
- if (fclose(ispa_file)) {
- fprintf(stderr, "%s: can't close file `%s'\n", prg_name,
- ispa_cfg_name);
- exit(2);
- }
- ++inum;
- }
- }
-
- /*
- * Write the MS-DOS startup batch file.
- */
- void write_start_file(void)
- {
- FILE *start_file;
- register key *kptr;
- register key *first;
- key *first2;
- ip *shptr;
- uint i, type, inum;
-
- (void) unlink(start_file_name);
- if ((start_file = fopen(start_file_name, "wt")) == NULL) {
- fprintf(stderr, "%s: can't open file `%s'\n", prg_name,
- start_file_name);
- exit(2);
- }
-
- shptr = NULL;
- if (num_globals) {
- first = (key *) globals[0].arg;
- kptr = get_key("syslog", first);
- if (kptr->status == S_TRAVERSE && kptr->arg != NULL) {
- kptr = get_key("host", (key *) kptr->arg);
- shptr = (ip *) kptr->arg;
- }
- kptr = get_key("prefix", first);
- if (kptr->status == S_SET && kptr->arg != NULL) {
- fprintf(start_file, (unchar *) kptr->arg,
- num_interfaces);
- fprintf(start_file, "\n");
- }
- }
-
- /* each interface has its own packet driver invocation */
- inum = 1;
- for (i = 0; i < num_interfaces; ++i) {
- first = (key *) interfaces[i].arg;
- kptr = get_key("type", first);
- type = *((uint *) kptr->arg);
- kptr = get_key("driver", first);
- first2 = (key *) kptr->arg;
-
- kptr = get_key("prefix", first2);
- if (kptr->status == S_SET && kptr->arg != NULL) {
- fprintf(start_file, (unchar *) kptr->arg, BASE_INT + i);
- fprintf(start_file, "\n");
- }
-
- switch (type) {
- case IT_ETHERNET:
- case IT_POINT2POINT:
- kptr = get_key("command", first2);
- fprintf(start_file, (unchar *) kptr->arg,
- BASE_INT + i);
- fprintf(start_file, "\n");
- break;
-
- case IT_ISDN:
- fprintf(start_file, "%s", ISPA_NAME);
- kptr = get_key("options", first2);
- if (kptr->status == S_SET && kptr->arg != NULL)
- fprintf(start_file, " %s",
- (unchar *) kptr->arg);
- kptr = get_key("controller", first2);
- fprintf(start_file, " -c %u",
- *((uint *) kptr->arg));
- kptr = get_key("index", first2);
- fprintf(start_file, " -e %u",
- *((uint *) kptr->arg));
- if (!transit_use_default[i])
- fprintf(start_file, " -v");
- kptr = get_key("syslog", first2);
- if (*((uint *) kptr->arg) == DS_ON
- && shptr != NULL) {
- kptr = get_key("address", first);
- fprintf(start_file, " -r ");
- fprint_ip(start_file, shptr);
- fprintf(start_file, ",");
- fprint_ip(start_file, (ip *) kptr->arg);
- }
- fprintf(start_file, " 0x%x", BASE_INT + i);
- (void) sprintf(ispa_cfg_name, "%s%u%s",
- ispa_cfg_base, inum,
- ispa_cfg_tail);
- fprintf(start_file, " %s", ispa_cfg_name);
- fprintf(start_file, "\n");
- ++inum;
- break;
-
- default:
- eexit(interfaces[i].line, "impossible error");
- break;
- }
-
- kptr = get_key("suffix", first2);
- if (kptr->status == S_SET && kptr->arg != NULL) {
- fprintf(start_file, (unchar *) kptr->arg, BASE_INT + i);
- fprintf(start_file, "\n");
- }
- }
-
- if (num_globals) {
- kptr = get_key("suffix", (key *) globals[0].arg);
- if (kptr->status == S_SET && kptr->arg != NULL) {
- fprintf(start_file, (unchar *) kptr->arg,
- num_interfaces);
- fprintf(start_file, "\n");
- }
- }
-
- /*
- * Invoke the PCroute version with the necessary number
- * of interfaces.
- */
- fprintf(start_file, "p%u\n", num_interfaces);
-
- if (fclose(start_file)) {
- fprintf(stderr, "%s: can't close file `%s'\n", prg_name,
- start_file_name);
- exit(2);
- }
- }
-
- /*
- * Handle special characters in the given line.
- */
- void expand_line(register unchar *ptr, uint bufsize)
- {
- var *vptr;
- unchar *maxptr, *start, *nptr, *rptr;
- register uint c;
- uint rlen, tlen, tmp;
- states state;
-
- maxptr = &ptr[bufsize];
- state = NORMAL;
- c = 0;
- --ptr;
-
- for (;;) {
- if (c == 0 && (c = *++ptr) == 0)
- break;
-
- switch (state) {
- case NORMAL:
- switch (c) {
- case '\\':
- start = ptr;
- state = ESCAPE;
- break;
- case '$':
- start = ptr;
- state = VARC1;
- break;
- case '#':
- *ptr = '\0';
- --ptr;
- break;
- }
- c = 0;
- break;
-
- case ESCAPE:
- switch (*ptr) {
- case 'a': *ptr = '\a'; break;
- case 'b': *ptr = '\b'; break;
- case 'f': *ptr = '\f'; break;
- case 'n': *ptr = '\n'; break;
- case 'r': *ptr = '\r'; break;
- case 't': *ptr = '\t'; break;
- case 'v': *ptr = '\v'; break;
- case '0':
- case '1':
- case '2':
- case '3':
- if (*(ptr + 1) >= '0'
- && *(ptr + 1) <= '7'
- && *(ptr + 2) >= '0'
- && *(ptr + 2) <= '7') {
- (void) sscanf(ptr,
- "%3o",
- &tmp);
- ptr += 2;
- *ptr = (unchar) tmp;
- } else if (*ptr == '0')
- *ptr = '\0';
- break;
- case 'x':
- if (isxdigit(*(ptr + 1))
- && isxdigit(*(ptr + 2))) {
- (void) sscanf(ptr + 1,
- "%2x",
- &tmp);
- ptr += 2;
- *ptr = (unchar) tmp;
- }
- break;
- }
- (void) memmove((void *) start,
- (void *) ptr, strlen(ptr) + 1);
- ptr = start;
- if (*ptr == '\0')
- --ptr;
- state = NORMAL;
- c = 0;
- break;
-
- case VARC1:
- if (c == '(') {
- state = VARC2;
- c = 0;
- } else {
- state = NORMAL;
- }
- break;
-
- case VARC2:
- nptr = ptr;
- /* advance to the closing bracket or EOL */
- for (; (c = *ptr) != ')' && c != '\0'; ++ptr)
- ;
- if (c == '\0')
- eexit(line, "unexpected end of file");
- *ptr = '\0';
- ++ptr;
- tlen = strlen(ptr);
- /* get the value of the variable */
- vptr = get_var(nptr);
- if (vptr) {
- rptr = vptr->val;
- if (rptr)
- rlen = strlen(rptr);
- else
- rlen = 0;
- } else {
- rptr = NULL;
- rlen = 0;
- }
- /* check buffer size */
- if (start + rlen + tlen >= maxptr)
- eexit(line, "variable expansion too long");
- /* make room for replacement string */
- (void) memmove((void *) (start + rlen),
- (void *) ptr, tlen + 1);
- /* copy replacement string, if any */
- if (rlen) {
- (void) memcpy((void *) start,
- (void *) rptr, rlen);
- }
- ptr = start + rlen - 1;
- state = NORMAL;
- c = 0;
- break;
-
- default:
- eexit(line, "impossible error");
- break;
- }
- }
- }
-
- /*
- * Convert the given character string to lower case.
- */
- void mklower(register unchar *ptr)
- {
- register uint c;
-
- for (; (c = *ptr); ++ptr)
- *ptr = tolower(c);
- }
-
- /*
- * Allocate memory from the heap and exit if no memory is available.
- */
- void *xmalloc(uint size)
- {
- void *ptr;
-
- if ((ptr = (void *) malloc(size)) == NULL)
- eexit(line, "out of memory");
- return ptr;
- }
-
- /*
- * Print the given error message and exit.
- */
- void eexit(uint line, unchar *fmt, ...)
- {
- va_list args;
-
- va_start(args, fmt);
- fprintf(stderr, "%s: line %u: ", prg_name, line);
- vfprintf(stderr, fmt, args);
- fprintf(stderr, "\n");
- va_end(args);
- exit(2);
- }
-