/* $Id: config.c,v 1.1.1.1 2001/04/10 01:58:40 csmall Exp $ * * Copyright (c) 1996 Jörg Reuter (jreuter@poboxes.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include #include #include #include #include #include #include #include #include #include #include #include #ifdef __GLIBC__ #include #else #include #endif #include #include #include #include #include #include #include "../pathnames.h" #include "ax25rtd.h" ax25_address *asc2ax(char *call) { static ax25_address callsign; ax25_aton_entry(call, (char *)&callsign); return &callsign; } static long asc2ip(char *s) { struct in_addr addr; if (!inet_aton(s, &addr)) return 0; return addr.s_addr; } char * prepare_cmdline(char *buf) { char *p; for (p = buf; *p; p++) { if (*p == '\t') *p = ' '; *p = tolower(*p); if (*p == '\n') { *p = '\0'; break; } if (*p == '#') { *p = '\0'; break; } } return buf; } char * get_next_arg(char **p) { char *p2; if (p == NULL || *p == NULL) return NULL; p2 = *p; for (; *p2 && *p2 == ' '; p2++) ; if (!*p2) return NULL; *p = strchr(p2, ' '); if (*p != NULL) { **p = '\0'; (*p)++; } return p2; } static inline void invalid_arg(char *c, char *p) { fprintf(stderr, "%s: invalid argument %s\n", c, p); } static inline void missing_arg(char *c) { fprintf(stderr, "%s: argument missing\n", c); } static int yesno(char *arg) { if (!arg) return 0; if (!strcmp(arg, "yes") || !strcmp(arg, "1")) return 1; if (!strcmp(arg, "no") || !strcmp(arg, "0")) return 0; return -1; } static ax25_address *get_mycall(char *port) { char *addr; if ((addr = ax25_config_get_addr(port)) == NULL) return NULL; return asc2ax(addr); } void load_ports(void) { config *config, *cfg, *ncfg; char buf[1024]; struct ifconf ifc; struct ifreq ifr, *ifrp; int k, fd; if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { fprintf(stderr, "Unable to open socket\n"); exit(1); } ifc.ifc_len = sizeof(buf); ifc.ifc_buf = buf; if (ioctl(fd, SIOCGIFCONF, &ifc) < 0) { fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno)); return; } ifrp = ifc.ifc_req; for (k = ifc.ifc_len / sizeof(struct ifreq); k > 0; k--, ifrp++) { strcpy(ifr.ifr_name, ifrp->ifr_name); if (strcmp(ifr.ifr_name, "lo") == 0) continue; if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) { fprintf(stderr, "SIOCGIFFLAGS: %s\n", strerror(errno)); exit(1); } if (!(ifr.ifr_flags & IFF_UP)) continue; ioctl(fd, SIOCGIFHWADDR, &ifr); if (ifr.ifr_hwaddr.sa_family != ARPHRD_AX25) continue; for (config = Config; config; config = config->next) if (!memcmp(&config->mycalls[0], ifr.ifr_hwaddr.sa_data, AXLEN) && !*config->dev) { strcpy(config->dev, ifr.ifr_name); ioctl(fd, SIOCGIFADDR, &ifr); config->ip = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr; strcpy(ifr.ifr_name, config->dev); ioctl(fd, SIOCGIFNETMASK, &ifr); config->netmask = ((struct sockaddr_in *) &ifr.ifr_netmask)->sin_addr.s_addr; break; } } close(fd); config = cfg = Config; while(config) { if (!*config->dev) { if (config == Config) { Config = config->next; cfg = Config; } else cfg->next = config->next; ncfg = config->next; free(config); config = ncfg; } else { cfg = config; config = config->next; } } } void load_listeners(void) { config *config; char buf[1024], device[14], call[10], dcall[10]; char dummy[1024]; int k; FILE *fp; ax25_address *axcall; fp = fopen(PROC_AX25_FILE, "r"); if (fp == NULL) { fprintf(stderr, "No AX.25 in kernel. Tss, tss...\n"); exit(1); } while (fgets(buf, sizeof(buf)-1, fp) != NULL) { k = sscanf(buf, "%s %s %s %s", dummy, device, call, dcall); if (k == 4 && !strcmp(dcall, "*")) { axcall = asc2ax(call); if (!strcmp("*", device)) { for (config = Config; config; config = config->next) { if (call_is_mycall(config, axcall) || config->nmycalls > AX25_MAXCALLS) continue; memcpy(&config->mycalls[config->nmycalls++], axcall, AXLEN); } } else { config = dev_get_config(device); if (config == NULL || call_is_mycall(config, axcall) || config->nmycalls > AX25_MAXCALLS) continue; memcpy(&config->mycalls[config->nmycalls++], axcall, AXLEN); } } } fclose(fp); } void load_config() { FILE *fp; char buf[1024], *p, *cmd, *arg; config *config, *cfg; ax25_address *axcall; config = NULL; fp = fopen(CONF_AX25ROUTED_FILE, "r"); if (fp == NULL) { fprintf(stderr, "config file %s not found\n", CONF_AX25ROUTED_FILE); exit(1); } while(fgets(buf, sizeof(buf)-1, fp) != NULL) { p = prepare_cmdline(buf); if (!*p) continue; cmd = get_next_arg(&p); if (cmd == NULL) continue; arg = get_next_arg(&p); if (*cmd == '[') { cmd++; p = strrchr(cmd, ']'); if (p == NULL) { fprintf(stderr, "syntax error: [%s\n", cmd); continue; } *p = '\0'; axcall = get_mycall(cmd); if (axcall == NULL) continue; cfg = (struct config_ *) malloc(sizeof(struct config_)); if (cfg == NULL) { fprintf(stderr, "out of memory\n"); exit(1); } memset(cfg, 0, sizeof(struct config_)); if (config) config->next = cfg; else Config = cfg; cfg->next = NULL; config = cfg; strcpy(config->port, cmd); memcpy(&config->mycalls[0], axcall, AXLEN); config->nmycalls = 1; } else if (config && !strcmp(cmd, "ax25-learn-routes")) { /* ax25-learn-routes no|yes: learn digipeater path */ if (arg) { int k = yesno(arg); if (k == -1) { invalid_arg(cmd, arg); continue; } else { config->ax25_add_route = k; } } else missing_arg(cmd); } else if (config && !strcmp(cmd, "ax25-learn-only-mine")) { /* ax25-learn-only-mine no|yes: learn only if addressed to me */ if (arg) { int k = yesno(arg); if (k == -1) { invalid_arg(cmd, arg); continue; } else { config->ax25_for_me = k; } } else missing_arg(cmd); } else if (config && !strcmp(cmd, "ax25-add-path")) { /* ax25-add-path [no|]: add digis if digi-less frame rvd */ int k = 0; if (!arg || (arg && yesno(arg) == 0)) continue; config->ax25_add_default = 1; while (arg && k < AX25_MAX_DIGIS) { memcpy(&config->ax25_default_path.fsa_digipeater[k], asc2ax(arg), AXLEN); arg = get_next_arg(&p); k++; } config->ax25_default_path.fsa_ax25.sax25_ndigis = k; } else if (config && !strcmp(cmd, "ax25-more-mycalls")) { /* ax25-more-mycalls call1 call2: frames to this calls are for "me", too. */ if (arg) { while(arg && config->nmycalls < AX25_MAXCALLS) { axcall = asc2ax(arg); if (call_is_mycall(config, axcall)) { arg = get_next_arg(&p); continue; } memcpy(&config->mycalls[config->nmycalls++], axcall, AXLEN); arg = get_next_arg(&p); } } else missing_arg(cmd); } else if (config && !strcmp(cmd, "ip-learn-routes")) { /* ip-learn-routes no|yes: learn ip routes */ if (arg) { int k = yesno(arg); if (k == -1) { invalid_arg(cmd, arg); continue; } else { config->ip_add_route = k; } } else missing_arg(cmd); } else if (config && !strcmp(cmd, "irtt")) { /* irtt : new routes will get this IRTT in msec */ if (arg) { int k = atoi(arg); if (k == 0) { invalid_arg(cmd, arg); continue; } else { config->tcp_irtt = k; } } else missing_arg(cmd); } else if (config && !strcmp(cmd, "dg-mtu")) { /* dg-mtu : MTU for datagram mode routes (unused) */ if (arg) { int k = atoi(arg); if (k == 0) { invalid_arg(cmd, arg); continue; } else { config->dg_mtu = k; } } else missing_arg(cmd); } else if (config && !strcmp(cmd, "vc-mtu")) { /* vc-mtu : MTU for virtual connect mode routes (unused) */ if (arg) { int k = atoi(arg); if (k == 0) { invalid_arg(cmd, arg); continue; } else { config->vc_mtu = k; } } else missing_arg(cmd); } else if (config && !strcmp(cmd, "ip-adjust-mode")) { /* ip-adjust-mode no|yes: adjust ip-mode? (dg or vc) */ if (arg) { int k = yesno(arg); if (k == -1) { invalid_arg(cmd, arg); continue; } else { config->ip_adjust_mode = k; } } else missing_arg(cmd); } else if (config && !strcmp(cmd, "arp-add")) { /* arp-add no|yes: adjust arp table? */ if (arg) { int k = yesno(arg); if (k == -1) { invalid_arg(cmd, arg); continue; } else { config->ip_add_arp = k; } } else missing_arg(cmd); } else if (!strcmp(cmd, "ip-encaps-dev")) { if (arg) strcpy(ip_encaps_dev, arg); else missing_arg(cmd); } else if (!strcmp(cmd, "ax25-maxroutes")) { if (arg) ax25_maxroutes = atoi(arg); else missing_arg(cmd); } else if (!strcmp(cmd, "ip-maxroutes")) { if (arg) ax25_maxroutes = atoi(arg); else missing_arg(cmd); } else fprintf(stderr, "invalid command %s\n", cmd); } fclose(fp); load_ports(); load_listeners(); reload = 0; } void reload_config(void) { config *cfg, *config = Config; while(config) { cfg = config->next; free(config); config = cfg; } Config = NULL; load_config(); } /* commands: --------- add ax25