--- ax25ipdorig/ax25ipd.c 2009-08-24 22:48:57.000000000 +0200 +++ ax25ipd/ax25ipd.c 2006-10-04 14:51:09.000000000 +0200 @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -32,55 +33,61 @@ int opt_loglevel = 0; int opt_nofork = 0; int opt_help = 0; -char opt_configfile[PATH_MAX]; -char opt_ttydevice[PATH_MAX]; +char opt_configfile[1024]; struct option options[] = { - {"version", 0, NULL, 'v'}, - {"loglevel", 1, NULL, 'l'}, - {"help", 0, NULL, 'h'}, - {"configfile", 1, NULL, 'c'}, - {"ttydevice", 1, NULL, 'd'}, - {"nofork", 0, NULL, 'f'}, + {"version", 0, &opt_version, 1}, + {"loglevel", 1, &opt_loglevel, 1}, + {"help", 0, &opt_help, 1}, + {"configfile", 1, NULL, 0}, + {"nofork", 0, &opt_nofork, 1}, {0, 0, 0, 0} }; int main(int argc, char **argv) { + + currtime = time(0); + if (setjmp(restart_env) == 0) { signal(SIGHUP, hupper); } - *opt_configfile = 0; - *opt_ttydevice = 0; - /* set up the handler for statistics reporting */ signal(SIGUSR1, usr1_handler); signal(SIGINT, int_handler); signal(SIGTERM, term_handler); while (1) { + int option_index = 0; int c; - c = getopt_long(argc, argv, "c:d:fhl:v", options, NULL); + c = getopt_long(argc, argv, "c:fhl:v", options, &option_index); if (c == -1) break; switch (c) { - case 'c': - strncpy(opt_configfile, optarg, sizeof(opt_configfile)-1); - opt_configfile[sizeof(opt_configfile)-1] = 0; + case 0: break; - case 'd': - strncpy(opt_ttydevice, optarg, sizeof(opt_ttydevice)-1); - opt_ttydevice[sizeof(opt_ttydevice)-1] = 0; + switch (option_index) { + case 0: + break; + case 1: + opt_loglevel = atoi(optarg); + break; + case 2: + break; + case 3: + strncpy(opt_configfile, optarg, 1023); + break; + } + break; + case 'c': + strncpy(opt_configfile, optarg, 1023); break; case 'f': opt_nofork = 1; break; - case 'h': - opt_help = 1; - break; case 'v': opt_version = 1; break; @@ -89,12 +96,11 @@ break; default: opt_help = 1; - break; } } if (optind < argc) { - printf("Unknown argument '%s' ...\n\n", argv[optind++]); + printf("config %s\n", argv[optind++]); opt_help = 1; } @@ -108,16 +114,14 @@ printf("%s [flags]\n", argv[0]); printf("\nFlags:\n"); printf - (" --version, -v Print version of program\n"); - printf(" --help, -h This help screen\n"); + (" --version, -v Print version of program\n"); + printf(" --help, -h This help screen\n"); printf - (" --loglevel NUM, -l NUM Set logging level to NUM\n"); + (" --loglevel NUM, -l NUM Set logging level to NUM\n"); printf - (" --configfile FILE, -c FILE Set configuration file to FILE\n"); - printf - (" --ttydevice TTYDEV, -d TTYDEV Set device parameter to TTYDEV\n"); + (" --configfile FILE, -c FILE Set configuration file to FILE\n"); printf - (" --nofork, -f Do not put daemon in background\n"); + (" --nofork, -f Do not put daemon in background\n"); exit(0); } @@ -131,11 +135,6 @@ /* read config file */ config_read(opt_configfile); - if (opt_ttydevice[0] != '\0') { - strncpy(ttydevice, opt_ttydevice, sizeof(ttydevice)-1); - ttydevice[sizeof(ttydevice)-1] = '\0'; - } - /* print the current config and route info */ dump_config(); dump_routes(); @@ -152,17 +151,6 @@ } } - /* we need to close stdin, stdout, stderr: because otherwise - * scripting like ttyname=$(ax25ipd | tail -1) does not work - */ - if (!isatty(1)) { - fflush(stdout); - fflush(stderr); - close(0); - close(1); - close(2); - } - /* and let the games begin */ io_start(); @@ -170,7 +158,7 @@ } -void greet_world(void) +void greet_world() { printf("\nax25ipd %s / %s\n", VERS2, VERSION); printf @@ -180,7 +168,7 @@ fflush(stdout); } -void do_stats(void) +void do_stats() { int save_loglevel; @@ -204,17 +192,24 @@ printf(" not for me: %d\n", stats.kiss_not_for_me); printf(" I am destination: %d\n", stats.kiss_i_am_dest); printf(" no route found: %d\n", stats.kiss_no_ip_addr); + printf("BPQ input packets: %d\n", stats.bpq_in); printf("UDP input packets: %d\n", stats.udp_in); printf("IP input packets: %d\n", stats.ip_in); printf(" failed CRC test: %d\n", stats.ip_failed_crc); printf(" too short: %d\n", stats.ip_tooshort); printf(" not for me: %d\n", stats.ip_not_for_me); printf(" I am destination: %d\n", stats.ip_i_am_dest); + printf("IPX input packets: %d\n", stats.ipx_in); + printf(" too short: %d\n", stats.ipx_tooshort); + printf(" not for me: %d\n", stats.ipx_not_for_me); + printf(" I am destination: %d\n", stats.ipx_i_am_dest); printf("\nOutput stats:\n"); + printf("BPQ output packets: %d\n", stats.bpq_out); printf("KISS output packets: %d\n", stats.kiss_out); printf(" beacons: %d\n", stats.kiss_beacon_outs); printf("UDP output packets: %d\n", stats.udp_out); printf("IP output packets: %d\n", stats.ip_out); + printf("IPX output packets: %d\n", stats.ipx_out); printf("\n"); fflush(stdout); --- ax25ipdorig/bpqether.c 2009-04-22 23:22:01.000000000 +0200 +++ ax25ipd/bpqether.c 2009-05-17 18:15:06.000000000 +0200 @@ -1,4 +1,4 @@ -/* @(#) $Id: bpqether.c,v 1.5 2009/04/22 21:22:01 dl9sau Exp $ */ +/* @(#) $Id: bpqether.c,v 1.2 2005/10/31 02:54:27 dl9sau Exp $ */ extern int ttyfd; /* @@ -91,7 +91,7 @@ ethertap_packet.data[1] = (l + 5) / 256; l += 2; - /*send_tty(addr + offset, l + sizeof(ethertap_packet.ethernet_header) - offset);*/ + //send_tty(addr + offset, l + sizeof(ethertap_packet.ethernet_header) - offset); write(ttyfd, addr + offset, l + sizeof(ethertap_packet.ethernet_header) - offset); return l; } @@ -103,15 +103,13 @@ if ((l -= ethertap_header_len) <= 0 || (buf[ethertap_header_len-2] & 0xff) != 0x08 || (buf[ethertap_header_len-1] & 0xff) != 0xff) { - /* not a bpqether packet. - * drop silently - ethernet.ax25 is not the only protocol spoken - * on ethernet ;) - */ + // not a bpqether packet. + // drop silently - ethernet.ax25 is not the only protocol spokenon ethernet ;) return -1; } l -= 2; if (l <= 0 && buf[ethertap_header_len] + buf[ethertap_header_len] * 256 - 5 != l) { - /* length error in bpqether packet */ + // length error in bpqether packet return 0; } @@ -151,16 +149,12 @@ strcpy(dev, ifr.ifr_name); /* persist mode */ -#if 0 - if (ioctl(fd, TUNSETPERSIST, 1) < 0) - perror("TUNSETPERSIST"); -#endif + //if (ioctl(fd, TUNSETPERSIST, 1) < 0) + //perror("TUNSETPERSIST"); /* don't checksum */ -#if 0 - if (ioctl(fd, TUNSETNOCSUM, 1) < 0) - perror("TUNSETNOCSUM"); -#endif + //if (ioctl(fd, TUNSETNOCSUM, 1) < 0) + //perror("TUNSETNOCSUM"); return fd; } @@ -183,7 +177,7 @@ strncpy(devname + 5, ifname, sizeof(devname) - 5 -1); devname[sizeof(devname) -1] = 0; - /* tuntap == 0: original ethertap. works on a real character device */ + // tuntap == 0: original ethertap. works on a real character device if (!stat(devname, &statbuf)) { fd = open(devname, O_RDWR); if (fd < 0) { @@ -271,28 +265,24 @@ int skfd; int err = -1; - /* - * 1. find correspondent bpqether device in /proc (i.e. bpq0 for tap0) - * 2. set the ax25 call of bpq0 (in this example) - * 3. ifup bpq0 - */ + // 1. find correspondent bpqether device in /proc (i.e. bpq0 for tap0) + // 2. set the ax25 call of bpq0 (in this example) + // 3. ifup bpq0 if (!(fp = fopen("/proc/net/bpqether", "r"))) { perror("/proc/net/bpqether"); return -1; } - /* - * look up bpqether devce in /proc: - * dev ether destination accept from - * bpq0 tap0 FF:FF:FF:FF:FF:FF * - */ + // look up bpqether devce in /proc: + // dev ether destination accept from + // bpq0 tap0 FF:FF:FF:FF:FF:FF * drop = 1; *bpq_name = *dev_name = 0; while (fgets(buf, sizeof(buf), fp)) { if (drop) { - /* header line */ + // header line drop = 0; continue; } @@ -318,7 +308,7 @@ ifr.ifr_name[IFNAMSIZ-1] = 0; ifr.ifr_hwaddr.sa_family = PF_AX25; - memcpy(ifr.ifr_hwaddr.sa_data, mycallsign, 7); + memcpy(ifr.ifr_hwaddr.sa_data, (mycallsigns ? mycallsigns->call : "LINUX"), 7); if (ioctl(skfd, SIOCSIFHWADDR, &ifr) < 0) { perror("SIOCSIFHWADDR"); --- ax25ipdorig/config.c 2009-08-24 22:48:57.000000000 +0200 +++ ax25ipd/config.c 2009-05-17 14:20:37.000000000 +0200 @@ -8,7 +8,7 @@ /* * Modifications made for dual port TNC's - * by Michael Durrant VE3PNX and D. Jeff Dionne February 4, 1995 + * by Michael Durrant and D. Jeff Dionne February 4, 1995 */ #include @@ -20,33 +20,37 @@ #include #include #include +#include #include #include "ax25ipd.h" +struct callsign *mycallsigns = 0; +struct callsign *mycallsigns2 = 0; +struct callsign *myalias = 0; +struct callsign *myalias2 = 0; + /* Initialize the config table */ -void config_init(void) +void config_init() { - int i; - *ttydevice = '\0'; - for (i = 0; i < 7; i++) - mycallsign[i] = '\0'; - for (i = 0; i < 7; i++) - myalias[i] = '\0'; - for (i = 0; i < 7; i++) - mycallsign2[i] = '\0'; - for (i = 0; i < 7; i++) - myalias2[i] = '\0'; + strcpy(ttydevice, "none"); + mycallsigns = mycallsigns2 = 0; + myalias = myalias2 = 0; digi = 1; + isolate = 0; + autorouter = 1; ttyspeed = 9600; loglevel = 0; bc_interval = 0; bc_text[0] = '\0'; bc_every = 0; my_udp = htons(0); + my_udp_addr = INADDR_ANY; udp_mode = 0; ip_mode = 0; + ipx_mode = 0; dual_port = 0; + cmdsock_name = 0; stats.kiss_in = 0; stats.kiss_toobig = 0; @@ -65,11 +69,19 @@ stats.ip_tooshort = 0; stats.ip_not_for_me = 0; stats.ip_i_am_dest = 0; + stats.ipx_in = 0; + stats.ipx_out = 0; + stats.ipx_tooshort = 0; + stats.ipx_not_for_me = 0; + stats.ipx_i_am_dest = 0; + stats.bpq_in = 0; + stats.bpq_out = 0; } /* Open and read the config file */ -void config_read(char *f) +void config_read(f) +char *f; { FILE *cf; char buf[256], cbuf[256]; @@ -129,19 +141,19 @@ exit(1); } - if ((udp_mode == 0) && (ip_mode == 0)) { - fprintf(stderr, "Must specify ip and/or udp sockets\n"); + if ((udp_mode == 0) && (ip_mode == 0) && (ipx_mode == 0)) { + fprintf(stderr, "Must specify ip or udp or ipx sockets\n"); exit(1); } if (digi) { - if (mycallsign[0] == '\0') { + if (!mycallsigns) { fprintf(stderr, "No mycall line in config file\n"); exit(1); } } if ((digi) && (dual_port)) { - if (mycallsign2[0] == '\0') { + if (!mycallsigns2) { fprintf(stderr, "No mycall2 line in config file\n"); exit(1); @@ -151,10 +163,11 @@ } /* Process each line from the config file. The return value is encoded. */ -int parse_line(char *buf) +int parse_line(buf) +char *buf; { char *p, *q; - unsigned char tcall[7], tip[4]; + unsigned char tcall[7]; struct hostent *he; int i, j, uport; unsigned int flags; @@ -167,53 +180,102 @@ return 0; if (strcmp(p, "mycall") == 0) { + struct callsign *m; q = strtok(NULL, " \t\n\r"); if (q == NULL) return -1; - if (a_to_call(q, mycallsign) != 0) + if (!(m = (struct callsign *) malloc(sizeof(struct callsign)))) return -2; + m->match_all_ssids = 0; + { char *r = 0; + if ((r = strchr(q, '-')) && *(r+1) == '*') { + *r = 0; + m->match_all_ssids = 1; + } + } + if (a_to_call(q, m->call) != 0) { + free(m); + return -2; + } + m->next = mycallsigns; + mycallsigns = m; return 0; } else if (strcmp(p, "mycall2") == 0) { + struct callsign *m; q = strtok(NULL, " \t\n\r"); if (q == NULL) return -1; - if (a_to_call(q, mycallsign2) != 0) + if (!(m = (struct callsign *) malloc(sizeof(struct callsign)))) + return -2; + m->match_all_ssids = 0; + { char *r = 0; + if ((r = strchr(q, '-')) && *(r+1) == '*') { + *r = 0; + m->match_all_ssids = 1; + } + } + if (a_to_call(q, m->call) != 0) { + free(m); return -2; + } + m->next = mycallsigns2; + mycallsigns2 = m; return 0; } else if (strcmp(p, "myalias") == 0) { + struct callsign *m; q = strtok(NULL, " \t\n\r"); if (q == NULL) return -1; - if (a_to_call(q, myalias) != 0) + if (!(m = (struct callsign *) malloc(sizeof(struct callsign)))) + return -2; + m->match_all_ssids = 0; + { char *r = 0; + if ((r = strchr(q, '-')) && *(r+1) == '*') { + *r = 0; + m->match_all_ssids = 1; + } + } + if (a_to_call(q, m->call) != 0) { + free(m); return -2; + } + m->next = myalias; + myalias = m; dual_port = 1; - if (mycallsign2[0] == '\0') { + if (!mycallsigns2 == '\0') { dual_port = 0; } return 0; } else if (strcmp(p, "myalias2") == 0) { + struct callsign *m; q = strtok(NULL, " \t\n\r"); if (q == NULL) return -1; - if (a_to_call(q, myalias2) != 0) + if (!(m = (struct callsign *) malloc(sizeof(struct callsign)))) return -2; + m->match_all_ssids = 0; + { char *r = 0; + if ((r = strchr(q, '-')) && *(r+1) == '*') { + *r = 0; + m->match_all_ssids = 1; + } + } + if (a_to_call(q, m->call) != 0) { + free(m); + return -2; + } + m->next = myalias2; + myalias2 = m; return 0; } else if (strcmp(p, "device") == 0) { - /* already set? i.e. with commandline option, which overwrites - * the preconfigured setting. useful for systems with unix98 - * style pty's - */ - if (*ttydevice) - return 0; q = strtok(NULL, " \t\n\r"); if (q == NULL) return -1; - strncpy(ttydevice, q, sizeof(ttydevice)-1); - ttydevice[sizeof(ttydevice)-1] = 0; + strcpy(ttydevice, q); return 0; } else if (strcmp(p, "mode") == 0) { @@ -224,8 +286,15 @@ digi = 1; else if (strcmp(q, "tnc") == 0) digi = 0; + else if (strcmp(q, "bridge") == 0) + digi = 0; else return -4; + q = strtok(NULL, " \t\n\r"); + if (q != 0) { + if (strcmp(q, "isolate") == 0) + isolate = 1; + } return 0; } else if (strcmp(p, "speed") == 0) { @@ -235,6 +304,23 @@ ttyspeed = atoi(q); return 0; + } else if (strcmp(p, "cmdsock_name") == 0) { +#ifndef AX25_LOCALSTATEDIR +#define AX25_LOCALSTATEDIR "/tmp" +#endif + q = strtok(NULL, " \t\n\r"); + if (q == NULL) + return -1; + if (!(cmdsock_name = (char *) malloc((*q == '/' ? 0 : strlen(AX25_LOCALSTATEDIR)+1) + strlen(q) + 1))) { + perror("malloc"); + exit(1); + } + if (*q == '/') + strcpy(cmdsock_name, q); + else + sprintf(cmdsock_name, "%s/%s", AX25_LOCALSTATEDIR, q); + return 0; + } else if (strcmp(p, "socket") == 0) { q = strtok(NULL, " \t\n\r"); if (q == NULL) @@ -246,10 +332,29 @@ my_udp = htons(DEFAULT_UDP_PORT); q = strtok(NULL, " \t\n\r"); if (q != NULL) { + if (!isdigit(*q & 0xff) || strchr(q, '.')) { + char *r = 0; + if ((r = strchr(q, ':'))) { + struct sockaddr_in sa; + *r++ = 0; + if (inet_aton(p, &sa.sin_addr)) { + /* Address is valid */ + my_udp_addr = sa.sin_addr.s_addr; + } else { + if ((he = gethostbyname(q)) && ((struct in_addr *)(he->h_addr))->s_addr != 0L) + my_udp_addr = ((struct in_addr *)(he->h_addr))->s_addr; + } + } + q = r; + } + } + if (q != NULL) { i = atoi(q); if (i > 0) my_udp = htons(i); } + } else if (strcmp(q, "ipx") == 0) { + ipx_mode = 1; } else return -9; return 0; @@ -277,11 +382,10 @@ q = p + strlen(p) + 1; if (strlen(q) < 2) return -1; /* line ends with a \n */ - if (strlen(q) > sizeof(bc_text)) + if (strlen(q) > sizeof bc_text) return -7; q[strlen(q) - 1] = '\0'; - strncpy(bc_text, q, sizeof(bc_text)-1); - bc_text[sizeof(bc_text)-1] = 0; + strcpy(bc_text, q); return 0; } else if (strcmp(p, "loglevel") == 0) { @@ -291,38 +395,79 @@ loglevel = atoi(q); return 0; + } else if (strcmp(p, "autorouter") == 0) { + q = strtok(NULL, " \t\n\r"); + if (q == NULL) + return -1; + autorouter = atoi(q); + return 0; + } else if (strcmp(p, "route") == 0) { - uport = 0; + struct sockaddr_in inp; + struct sockaddr_in tip; + char *fqdn = 0; + unsigned long tmask = 0xffffffffUL; + char *r; + uport = (udp_mode ? my_udp : htons(0)); flags = 0; + int match_all_ssids = 0; + + memset(&tip, 0, sizeof(struct sockaddr_in)); q = strtok(NULL, " \t\n\r"); if (q == NULL) return -1; + { char *r = 0; + if ((r = strchr(q, '-')) && *(r+1) == '*') { + *r = 0; + match_all_ssids = 1; + } + } if (a_to_call(q, tcall) != 0) return -2; q = strtok(NULL, " \t\n\r"); if (q == NULL) return -1; - he = gethostbyname(q); - if (he != NULL) { - memcpy(tip, he->h_addr_list[0], 4); - } else { /* maybe user specified a numeric addr? */ - j = inet_addr(q); - if (j == -1) - return -5; /* if -1, bad deal! */ - memcpy(tip, (char *) &j, 4); + if ((r = strchr(q, '/'))) { + *r++ = 0; + if (!*r) + return -4; + if ((i = atoi(r)) < 0) + return -4; + if (i > 32) + i = 32; + if (!inet_aton(q, &inp.sin_addr)) + return -4; + /* Address is valid */ + if (i) { + tip.sin_addr.s_addr = (inp.sin_addr.s_addr & tmask); + tmask = ~0L << (32-i); + } else { + tip.sin_addr.s_addr = 0L; + tmask = 0L; + } + } else { + if (inet_aton(q, &inp.sin_addr)) { + /* Address is valid */ + tip.sin_addr.s_addr = inp.sin_addr.s_addr; + } else { + if ((he = gethostbyname(q))) + tip.sin_addr.s_addr = ((struct in_addr *)(he->h_addr))->s_addr; + else + tip.sin_addr.s_addr = 0L; /* mark to be resolved, at least once */ + fqdn = strdup(q); + } } while ((q = strtok(NULL, " \t\n\r")) != NULL) { if (strcmp(q, "udp") == 0) { - uport = DEFAULT_UDP_PORT; q = strtok(NULL, " \t\n\r"); if (q != NULL) { i = atoi(q); if (i > 0) - uport = i; + uport = htons(i); } } else { /* Test for broadcast flag */ @@ -332,11 +477,19 @@ /* Test for Default flag */ if (strchr(q, 'd')) { - flags |= AXRT_DEFAULT; + if (tmask == 0xffffffffUL) + flags |= AXRT_DEFAULT; + } + + /* Test for "permanent" flag */ + if (strchr(q, 'p')) { + flags |= AXRT_PERMANENT; } } } - route_add(tip, tcall, uport, flags); + tip.sin_family = AF_INET; + tip.sin_port = uport; + route_add(&tip, htonl(tmask), fqdn, tcall, (flags | AXRT_FORCE_LEARN | (match_all_ssids ? AXRT_MATCH_ALL_SSIDS : 0))); return 0; } else if (strcmp(p, "broadcast") == 0) { @@ -364,7 +517,9 @@ } /* Convert ascii callsign to internal format */ -int a_to_call(char *text, unsigned char *tcall) +int a_to_call(text, tcall) +char *text; +unsigned char *tcall; { int i; int ssid; @@ -398,7 +553,8 @@ } /* Convert internal callsign to printable format */ -char *call_to_a(unsigned char *tcall) +char *call_to_a(tcall) +unsigned char *tcall; { int i; int ssid; @@ -430,20 +586,25 @@ } /* print the configuration data out */ -void dump_config(void) +void dump_config() { + struct callsign *m; LOGL1("\nCurrent configuration:\n"); if (ip_mode) LOGL1(" socket ip\n"); if (udp_mode) LOGL1(" socket udp on port %d\n", ntohs(my_udp)); + if (ipx_mode) + LOGL1(" socket ipx\n"); LOGL1(" mode %s\n", digi ? "digi" : "tnc"); LOGL1(" device %s\n", ttydevice); LOGL1(" speed %d\n", ttyspeed); if (digi) - LOGL1(" mycall %s\n", call_to_a(mycallsign)); - if (digi && myalias[0]) - LOGL1(" myalias %s\n", call_to_a(myalias)); + for (m = mycallsigns; m; m = m->next) + LOGL1(" mycall %s\n", call_to_a(m->call)); + if (digi && myalias) + for (m = myalias; m; m = m->next) + LOGL1(" myalias %s\n", call_to_a(m->call)); if (bc_interval > 0) { LOGL1(" beacon %s %d\n", bc_every ? "every" : "after", bc_interval); --- ax25ipdorig/crc.c 2009-08-24 22:48:57.000000000 +0200 +++ ax25ipd/crc.c 2006-08-01 09:15:34.000000000 +0200 @@ -70,7 +70,10 @@ /* * Calculate a new fcs given the current fcs and the new data. */ -u16 pppfcs(u16 fcs, unsigned char *cp, int len) +u16 pppfcs(fcs, cp, len) +register u16 fcs; +register unsigned char *cp; +register int len; { /* ASSERT(sizeof (u16) == 2); */ /* ASSERT(((u16) -1) > 0); */ @@ -91,7 +94,9 @@ */ /* Return the computed CRC */ -unsigned short int compute_crc(unsigned char *buf, int l) +unsigned short int compute_crc(buf, l) +unsigned char *buf; +int l; { int fcs; @@ -102,7 +107,9 @@ } /* Return true if the CRC is correct */ -int ok_crc(unsigned char *buf, int l) +int ok_crc(buf, l) +unsigned char *buf; +int l; { int fcs; @@ -118,7 +125,7 @@ */ #ifdef TEST -void main(int argc, char *argv[]) +void main() { unsigned char buf[258]; int l, i; --- ax25ipdorig/io.c 2009-08-24 22:48:57.000000000 +0200 +++ ax25ipd/io.c 2008-04-12 19:45:26.000000000 +0200 @@ -17,12 +17,15 @@ #include #include #include +#include +#include #include #include #include #ifdef USE_ICMP #include #endif +#include #include #include #include @@ -31,6 +34,8 @@ #include #include +#include "routing.h" + #ifdef __bsdi__ #define USE_TERMIOS #endif @@ -59,13 +64,18 @@ int ttyfd = -1; int udpsock = -1; int sock = -1; +int ipxsock = -1; #ifdef USE_ICMP int icmpsock = -1; #endif +int cmdsock = -1; +char *cmdsock_name = 0; + struct sockaddr_in udpbind; struct sockaddr_in to; struct sockaddr_in from; -socklen_t fromlen; +struct sockaddr_ipx ipxbind; +int fromlen; time_t last_bc_time; @@ -83,6 +93,7 @@ #ifdef USE_ICMP #define ICMP_MODE 0x40 #endif +#define IPX_MODE 0x50 #ifndef FNDELAY #define FNDELAY O_NDELAY @@ -92,7 +103,7 @@ * Initialize the io variables */ -void io_init(void) +void io_init() { /* @@ -104,7 +115,6 @@ close(ttyfd); ttyfd = -1; } - if (sock >= 0) { close(sock); sock = -1; @@ -120,6 +130,15 @@ icmpsock = -1; } #endif + if (ipxsock >= 0) { + close(ttyfd); + ttyfd = -1; + } + + if (cmdsock >= 0) { + close(cmdsock); + cmdsock = -1; + } /* * The bzero is not strictly required - it simply zeros out the @@ -134,18 +153,21 @@ bzero((char *) &udpbind, sizeof(struct sockaddr)); udpbind.sin_family = AF_INET; + + bzero((char *) &ipxbind, sizeof(struct sockaddr)); + ipxbind.sipx_family = AF_IPX; + ipxbind.sipx_network=0x00L; + ipxbind.sipx_port = htons(0xCE73); + } /* * open and initialize the IO interfaces */ -void io_open(void) +void io_open() { int baudrate; - int i_am_unix98_pty_master = 0; /* unix98 ptmx support */ - char *namepts = NULL; /* name of the unix98 pts slave, which - * the client has to use */ if (ip_mode) { sock = socket(AF_INET, SOCK_RAW, IPPROTO_AX25); @@ -184,7 +206,7 @@ * Ok, the udp socket is open. Now express our interest in receiving * data destined for a particular socket. */ - udpbind.sin_addr.s_addr = INADDR_ANY; + udpbind.sin_addr.s_addr = my_udp_addr; udpbind.sin_port = my_udp; if (bind(udpsock, (struct sockaddr *) &udpbind, sizeof udpbind) < 0) { perror("binding udp socket"); @@ -192,8 +214,49 @@ } } - if (!strcmp("/dev/ptmx", ttydevice)) - i_am_unix98_pty_master = 1; + if (ipx_mode) { + int addrlen = sizeof(ipxbind); + if ((ipxsock = socket(AF_IPX, SOCK_DGRAM, PF_IPX)) < 0) { + perror("opening ipx socket"); + exit(1); + } + if (fcntl(ipxsock, F_SETFL, FNDELAY) < 0) { + perror("setting blocking I/O on IPX socket"); + exit(1); + } + if (bind(ipxsock, (struct sockaddr*) &ipxbind, sizeof(ipxbind)) < 0) { + perror("binding IPX socket"); + exit(1); + } + if (getsockname(ipxsock, (struct sockaddr *) &ipxbind, &addrlen) < 0) { + perror("getsockname(ipx)"); + exit(1); + } + } + + if (cmdsock_name) { + struct sockaddr_un addr_su; + addr_su.sun_family = AF_UNIX; + unlink(cmdsock_name); + strncpy(addr_su.sun_path, cmdsock_name, sizeof(addr_su.sun_path) -1); + addr_su.sun_path[sizeof(addr_su.sun_path)-1] = 0; + if ((cmdsock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { + perror("socket(AF_UNIX)"); + exit(1); + } + if (bind(cmdsock, (struct sockaddr *) &addr_su, sizeof(addr_su))) { + perror("bind()"); + exit(1); + } + if (listen(cmdsock, SOMAXCONN)) { + perror("listen()"); + exit(1); + } + chmod(cmdsock_name, 0660); + } + + if (!strcmp(ttydevice, "none")) + goto behind_normal_tty; ttyfd = ((ttyfd_bpq = (strchr(ttydevice, '/') ? 0 : 1)) ? open_ethertap(ttydevice) : open(ttydevice, O_RDWR, 0)); if (ttyfd < 0) { @@ -204,20 +267,6 @@ perror("setting non-blocking I/O on tty device"); exit(1); } - - if (i_am_unix98_pty_master) { - /* get name of pts-device */ - if ((namepts = ptsname(ttyfd)) == NULL) { - perror("Cannot get name of pts-device."); - exit(1); - } - /* unlock pts-device */ - if (unlockpt(ttyfd) == -1) { - perror("Cannot unlock pts-device."); - exit(1); - } - } - if (ttyfd_bpq) { set_bpq_dev_call_and_up(ttydevice); goto behind_normal_tty; @@ -313,12 +362,6 @@ if (digi) send_params(); - if (i_am_unix98_pty_master) { - /* Users await the slave pty to be referenced in the last line */ - printf("Awaiting client connects on\n%s\n", namepts); - syslog(LOG_INFO, "Bound to master pty /dev/ptmx with slave pty %s\n", namepts); - } - behind_normal_tty: last_bc_time = 0; /* force immediate id */ @@ -329,20 +372,20 @@ * run in a loop, using the select call to handle input. */ -void io_start(void) { +void io_start() { int n, nb, hdr_len; fd_set readfds; unsigned char buf[MAX_FRAME]; struct timeval wait; struct iphdr *ipptr; - time_t now; for (;;) { + currtime = time(0); + if ((bc_interval > 0) && digi) { - now = time(NULL); - if (last_bc_time + bc_interval < now) { - last_bc_time = now; + if (last_bc_time + bc_interval < currtime) { + last_bc_time = currtime; LOGL4("iostart: BEACON\n"); do_beacon(); } @@ -353,7 +396,8 @@ FD_ZERO(&readfds); - FD_SET(ttyfd, &readfds); + if (ttyfd >= 0) + FD_SET(ttyfd, &readfds); if (ip_mode) { FD_SET(sock, &readfds); @@ -362,9 +406,14 @@ #endif } - if (udp_mode) { + if (udp_mode) FD_SET(udpsock, &readfds); - } + + if (ipx_mode) + FD_SET(ipxsock, &readfds); + + if (cmdsock > 0) + FD_SET(cmdsock, &readfds); nb = select(FD_SETSIZE, &readfds, (fd_set *) 0, (fd_set *) 0, &wait); @@ -382,6 +431,42 @@ continue; } + if (cmdsock >= 0 && FD_ISSET(cmdsock, &readfds)) { + struct sockaddr addr; + int addrlen = sizeof(addr); + int fd; + if ((fd = accept(cmdsock, &addr, &addrlen)) >= 0) { + *buf = 0; + for (;;) { + char buf2[MAX_FRAME]; + int ret; + int len; + char *q; + if ((len = read(fd, buf+strlen(buf), sizeof(buf)-strlen(buf)-1)) <= 0) + break; + buf[len] = 0; + strcpy(buf2, buf); + if ((q = strchr(buf2, '\n'))) + *(q+1) = 0; + else { + LOGL1("ERROR: cmd: %s ignored", buf2); + break; + } + LOGL1("cmd: %s", buf2); + ret = parse_line(buf2); + LOGL4("cmd: returned %d", ret); + if ((q = strchr(buf, '\n'))) + strcpy(buf, q+1); + else + *buf = 0; + } + close(fd); + } + } + + if (ttyfd == -1) + goto out_ttyfd; + if (FD_ISSET(ttyfd, &readfds)) { do { n = read(ttyfd, buf, MAX_FRAME); @@ -392,10 +477,12 @@ if (!ttyfd_bpq) { assemble_kiss(buf, n); } else { - /* no crc but MAC header on bpqether */ + // no crc on bpqether. but a MAC header if (receive_bpq(buf, n) < 0) { + goto out_ttyfd; } + stats.bpq_in++; } } @@ -404,28 +491,28 @@ * we hear something on the channel. */ if (!bc_every) - last_bc_time = time(NULL); + last_bc_time = currtime; } out_ttyfd: if (udp_mode) { if (FD_ISSET(udpsock, &readfds)) { do { - fromlen = sizeof from; + fromlen = sizeof(from); n = recvfrom(udpsock, buf, MAX_FRAME, 0, (struct sockaddr *) &from, &fromlen); } while (io_error(n, buf, n, READ_MSG, UDP_MODE, __LINE__)); LOGL4("udpdata from=%s port=%d l=%d\n", (char *) inet_ntoa(from. sin_addr), ntohs(from. sin_port), n); stats.udp_in++; if (n > 0) - from_ip(buf, n); + from_ip(buf, n, &from); } } /* if udp_mode */ if (ip_mode) { if (FD_ISSET(sock, &readfds)) { do { - fromlen = sizeof from; + fromlen = sizeof(from); n = recvfrom(sock, buf, MAX_FRAME, 0, (struct sockaddr *) &from, &fromlen); } while (io_error(n, buf, n, READ_MSG, IP_MODE, __LINE__)); @@ -433,13 +520,15 @@ hdr_len = 4 * ipptr-> ihl; LOGL4("ipdata from=%s l=%d, hl=%d\n", (char *) inet_ntoa(from. sin_addr), n, hdr_len); stats.ip_in++; - if (n > hdr_len) - from_ip(buf + hdr_len, n - hdr_len); + if (n > hdr_len) { + from.sin_port = 0; + from_ip(buf + hdr_len, n - hdr_len, &from); + } } #ifdef USE_ICMP if (FD_ISSET(icmpsock, &readfds)) { do { - fromlen = sizeof from; + fromlen = sizeof(from); n = recvfrom(icmpsock, buf, MAX_FRAME, 0, (struct sockaddr *) &from, &fromlen); } while (io_error(n, buf, n, READ_MSG, ICMP_MODE, __LINE__)); @@ -450,21 +539,78 @@ #endif } /* if ip_mode */ + if (ipx_mode) { + if (FD_ISSET(ipxsock, &readfds)) { + struct sockaddr_ipx ipxaddr; + int addrlen; + do { + fromlen = sizeof(from); + n = recvfrom(ipxsock, buf, MAX_FRAME, 0, (struct sockaddr *) &ipxaddr, &addrlen); + } + while (io_error(n, buf, n, READ_MSG, IPX_MODE, __LINE__)); + /* Ignore our own frames */ + if (n > 0 && !memcmp(ipxaddr.sipx_node, ipxbind.sipx_node, IPX_NODE_LEN)) { + from_ipx(buf, n, &ipxaddr); + stats.ipx_in++; + } + } + } + /* if ipx_mode */ } /* for forever */ } + +/* Send an IPX frame */ +void send_ipx(buf, l, tp) +unsigned char *buf; +int l; +struct route_table_entry *tp; /* tp: for future implementations; currently + we only could send to the whole network, + as broadcast */ +{ + /* It was choosen to broadcast the frames to 00000000:FFFFFFFFFFFF + * It is debatable if this was a good choice, since Windows 2000 + * uses a network number of 00000000 to mean "random" for internal + * network, so if you run RAS & Routing (which enables the internal + * net) you will never receive frames... + */ + + static struct sockaddr_ipx bcaddr = { + AF_IPX, 0x73CE, 0x00L, + {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, + 25 + }; + + int n; + + if (l <= 0) + return; + do { + n = sendto(ipxsock, buf, l, 0, + (struct sockaddr *) &bcaddr, sizeof (bcaddr)); + } + while (n < 0 && errno == EINTR); + + if (n < 0) { + LOGL1("send_ipx sendto: %s (%i)",strerror(errno),errno); + return; + } + stats.ipx_out++; +} + + /* Send an IP frame */ -void send_ip(unsigned char *buf, int l, unsigned char *targetip) +void send_ip(buf, l, tp) +unsigned char *buf; +int l; +struct route_table_entry *tp; { int n; if (l <= 0) return; - memcpy((char *) &to.sin_addr, - targetip, 4); - memcpy((char *) &to.sin_port, - &targetip[4], 2); + memcpy(&to, &tp->ip_addr, sizeof(struct sockaddr_in)); LOGL4("sendipdata to=%s %s %d l=%d\n", (char *) inet_ntoa(to. sin_addr), to.sin_port ? "udp" : "ip", ntohs(to.sin_port), l); if (to.sin_port) { if (udp_mode) { @@ -483,11 +629,14 @@ while (io_error(n, buf, l, SEND_MSG, IP_MODE, __LINE__)); } } + tp->last_sent = currtime; } /* Send a kiss frame */ -void send_tty(unsigned char *buf, int l) +void send_tty(buf, l) +unsigned char *buf; +int l; { int n; unsigned char *p; @@ -495,7 +644,7 @@ if (l <= 0) return; - LOGL4("sendttydata l=%d\tsent: ", l); + LOGL4("sendttydata l=%d sent: ", l); stats.kiss_out++; p = buf; @@ -530,61 +679,61 @@ } /* process an I/O error; return true if a retry is needed */ -int io_error( - int oops, /* the error flag; < 0 indicates a problem */ - unsigned char *buf, /* the data in question */ - int bufsize, /* the size of the data buffer */ - int dir, /* the direction; input or output */ - int mode, /* the fd on which we got the error */ - int where) /* line in the code where this function was called */ +int io_error(oops, buf, bufsize, dir, mode, where) +int oops; /* the error flag; < 0 indicates a problem */ +unsigned char *buf; /* the data in question */ +int bufsize; /* the size of the data buffer */ +int dir; /* the direction; input or output */ +int mode; /* the fd on which we got the error */ +int where; /* line in the code where this function was called */ { + /* dl9sau: nobody has set fd's to O_NONBLOCK. + * thus EAGAIN (below) or EWOULDBLOCK are never be set. + * Has someone removed this behaviour previously? + * Anyway, in the current implementation, with blocking + * read/writes, a read or write of 0 bytes means EOF, + * for e.g. if the attached tty is closed. + * We have to exit then. We've currentlsy no mechanism + * for regulary reconnects. + */ /* if (oops >= 0) return 0; */ /* do we have an error ? */ - /* dl9sau: nobody has set fd's to O_NONBLOCK. - * thus EAGAIN (below) or EWOULDBLOCK are never be set. - * Has someone removed this behaviour previously? - * Anyway, in the current implementation, with blocking - * read/writes, a read or write of 0 bytes means EOF, - * for e.g. if the attached tty is closed. - * We have to exit then. We've currentlsy no mechanism - * for regulary reconnects. - */ if (oops > 0) - return 0; /* do we have an error ? */ + return 0; /* do we have an error ? */ - if (oops == 0) { - if (dir == READ_MSG && oops != TTY_MODE /* && != TCP_MODE, if we'd implement this */ ) - return 0; - fprintf(stderr, "Close event on mode 0x%2.2x (during %s). LINE %d. Terminating normaly.\n", mode, (dir == READ_MSG ? "READ" : "WRITE"), where); - exit(1); - } + if (oops == 0) { + if (dir == READ_MSG && oops != TTY_MODE /* && != TCP_MODE, if we'd implement this */ ) + return 0; + fprintf(stderr, "Close event on mode 0x%2.2x (during %s). LINE %d. Terminating normaly.\n", mode, (dir == READ_MSG ? "READ" : "WRITE"), where); + exit(1); + } #ifdef EAGAIN - if (errno == EAGAIN) { + if (errno == EAGAIN) { #ifdef notdef - /* select() said that data is available, but recvfrom sais - * EAGAIN - i really do not know what's the sense in this.. */ - if (dir == READ_MSG && oops != TTY_MODE /* && != TCP_MODE, if we'd implement this */ ) - return 0; - perror("System 5 I/O error!"); - fprintf(stderr, "A System 5 style I/O error was detected. This rogram requires BSD 4.2\n"); - fprintf(stderr, "behaviour. This is probably a result of compile-time environment.\n"); - fprintf(stderr, "Mode 0x%2.2x, LINE: %d. During %s\n", mode, where, (dir == READ_MSG ? "READ" : "WRITE")); - exit(3); + /* select() said that data is available, but recvfrom sais + * EAGAIN - i really do not know what's the sense in this.. */ + if (dir == READ_MSG && oops != TTY_MODE /* && != TCP_MODE, if we'd implement this */ ) + return 0; + perror("System 5 I/O error!"); + fprintf(stderr, "A System 5 style I/O error was detected. This program requires BSD 4.2\n"); + fprintf(stderr, "behaviour. This is probably a result of compile-time environment.\n"); + fprintf(stderr, "Mode 0x%2.2x, LINE: %d. During %s\n", mode, where, (dir == READ_MSG ? "READ" : "WRITE")); + exit(3); #else - int ret = 0; - if (dir == READ_MSG) { - LOGL4("read / recv returned -1 EAGAIN\n"); - ret = 0; - } else if (dir == SEND_MSG) { - LOGL4("write / send returned -1 EAGAIN, sleeping and retrying!\n"); - usleep(100000); - ret = 1; - } - return ret; + int ret = 0; + if (dir == READ_MSG) { + LOGL4("read / recv returned -1 EAGAIN\n"); + ret = 0; + } else if (dir == SEND_MSG) { + LOGL4("write / send returned -1 EAGAIN, sleeping and retrying!\n"); + usleep(100000); + ret = 1; + } + return ret; #endif - } + } #endif if (dir == READ_MSG) { --- ax25ipdorig/kiss.c 2009-08-24 22:48:57.000000000 +0200 +++ ax25ipd/kiss.c 2006-08-01 09:15:34.000000000 +0200 @@ -44,7 +44,7 @@ * Initialize the KISS variables */ -void kiss_init(void) +void kiss_init() { ifptr = iframe; ifcount = 0; @@ -60,7 +60,9 @@ * frame has been assembled. */ -void assemble_kiss(unsigned char *buf, int l) +void assemble_kiss(buf, l) +unsigned char *buf; +int l; { int i; unsigned char c; @@ -112,7 +114,10 @@ } /* convert a standard AX25 frame into a kiss frame */ -void send_kiss(unsigned char type, unsigned char *buf, int l) +void send_kiss(type, buf, l) +unsigned char type; +unsigned char *buf; +int l; { #define KISSEMIT(x) if(ofcount= PTABLE_SIZE) { fprintf(stderr, "param table is full; entry ignored.\n"); @@ -166,20 +173,20 @@ } /* dump the contents of the parameter table */ -void dump_params(void) +void dump_params() { int i; LOGL1("\n%d parameters\n", param_tbl_top); for (i = 0; i < param_tbl_top; i++) { - LOGL1(" %d\t%d\n", + LOGL1(" %d %d\n", param_tbl[i].parameter, param_tbl[i].value); } fflush(stdout); } /* send the parameters to the TNC */ -void send_params(void) +void send_params() { int i; unsigned char p, v; --- ax25ipdorig/process.c 2009-08-24 22:48:57.000000000 +0200 +++ ax25ipd/process.c 2009-05-17 15:38:27.000000000 +0200 @@ -9,22 +9,23 @@ */ /* - * Dual port additions by M.Durrant VE3PNX and D.J.Dionne Feb 4, 1995 + * Dual port additions by M.Durrant and D.J.Dionne Feb 4, 1995 */ #include "ax25ipd.h" +#include "routing.h" #include #include /* if dual port the upper nibble will have a value of 1 (not 0) */ #define FROM_PORT2(p) (((*(p+1))&0x10)!=0) -#define FOR_PORT2(p) (addrmatch(p,mycallsign2) || addrmatch(p,myalias2)) +#define FOR_PORT2(p) (addrmatch2(p,mycallsigns2) || addrmatch2(p,myalias2)) /* ve3djf and ve3pnx addition above */ #define IS_LAST(p) (((*(p+6))&0x01)!=0) #define NOT_LAST(p) (((*(p+6))&0x01)==0) #define REPEATED(p) (((*(p+6))&0x80)!=0) #define NOTREPEATED(p) (((*(p+6))&0x80)==0) -#define IS_ME(p) (addrmatch(p,mycallsign) || addrmatch(p,myalias) || addrmatch(p,mycallsign2) || addrmatch(p,myalias2) ) -#define NOT_ME(p) (!(addrmatch(p,mycallsign) || addrmatch(p,myalias) || addrmatch(p,mycallsign2) || addrmatch(p,myalias2) ) ) +#define IS_ME(p) (addrmatch2(p,mycallsigns) || addrmatch2(p,myalias) || addrmatch2(p,mycallsigns2) || addrmatch2(p,myalias2) ) +#define NOT_ME(p) (!(addrmatch2(p,mycallsigns) || addrmatch2(p,myalias) || addrmatch2(p,mycallsigns2) || addrmatch2(p,myalias2) ) ) #define ARE_DIGIS(f) (((*(f+13))&0x01)==0) #define NO_DIGIS(f) (((*(f+13))&0x01)!=0) #define SETREPEATED(p) (*(p+6))|=0x80 @@ -37,7 +38,7 @@ * Initialize the process variables */ -void process_init(void) +void process_init() { bclen = -1; /* flag that we need to rebuild the bctext */ } @@ -65,9 +66,12 @@ * the IP interface. */ -void from_kiss(unsigned char *buf, int l) +void from_kiss(buf, l) +unsigned char *buf; +int l; { - unsigned char *a, *ipaddr; + unsigned char *a; + struct route_table_entry *rp; if (l < 15) { LOGL2("from_kiss: dumped - length wrong!\n"); @@ -77,7 +81,7 @@ if (loglevel > 2) dump_ax25frame("from_kiss: ", buf, l); - + if (digi) { /* if we are in digi mode */ a = next_addr(buf); if (NOT_ME(a)) { @@ -104,30 +108,27 @@ #endif } /* end of tnc mode */ - /* Lookup the IP address for this route */ - ipaddr = call_to_ip(a); + if (ipx_mode) + return send_ipx(buf, l, 0); - if (ipaddr == NULL) { - if (is_call_bcast(a)) { - /* Warning - assuming buffer has room for 2 bytes */ - add_crc(buf, l); - l += 2; - send_broadcast(buf, l); - } else { - stats.kiss_no_ip_addr++; - LOGL2 - ("from_kiss: dumped - cannot figure out where to send this!\n"); - } + /* Warning - assuming buffer has room for 2 bytes */ + add_crc(buf, l); + l += 2; + + if (is_call_bcast(a)) { +//if (strstr(call_to_a(a), "DG8NGN")) +//fprintf(stderr, "sent toIP %s\n", call_to_a(a)); + send_broadcast(buf, l); return; - } else { - /* Warning - assuming buffer has room for 2 bytes */ - add_crc(buf, l); - l += 2; - send_ip(buf, l, ipaddr); - if (is_call_bcast(a)) { - send_broadcast(buf, l); - } } + + /* Lookup the IP address for this route */ + if ((rp = call_to_ip(a, 1))) + return send_ip(buf, l, rp); + + stats.kiss_no_ip_addr++; + LOGL2("from_kiss: dumped - cannot figure out where to send this!\n"); + return; } /* @@ -146,10 +147,15 @@ * We simply send the packet to the KISS send routine. */ -void from_ip(unsigned char *buf, int l) +void from_ip(buf, l, ip_addr) +unsigned char *buf; +int l; +struct sockaddr_in *ip_addr; { int port = 0; unsigned char *a; + unsigned char *f; + struct route_table_entry *rp; if (!ok_crc(buf, l)) { stats.ip_failed_crc++; @@ -184,8 +190,10 @@ port = 0x10; } SETREPEATED(a); + a = next_addr(buf); /* find who gets it after us */ } else { /* must be tnc mode */ a = next_addr(buf); +fprintf(stderr, "sent toKISS %s\n", call_to_a(a)); #ifdef TNC_FILTER if (NOT_ME(a)) { LOGL2 @@ -194,10 +202,109 @@ } #endif } /* end of tnc mode */ - if (!ttyfd_bpq) - send_kiss(port, buf, l); - else { - send_bpq(buf, l); + + f = from_addr(buf); + if (!is_call_bcast(f) && NOT_ME(f)) { + if (route_add(ip_addr, 0xffffffffUL, 0, f, 0) < 0) { +fprintf(stderr, "debug: route_add %s failed\n", call_to_a(from_addr(buf))); + return; + } +fprintf(stderr, "debug: route_add %s ok\n", call_to_a(from_addr(buf))); + } + + if (isolate || IS_ME(a)) + goto send_kiss; + if (is_call_bcast(a)) { + if (udp_mode) { + add_crc(buf, l); + l += 2; + send_broadcast(buf, l); + l -= 2; + } + goto send_kiss; + } + + if ((udp_mode || digi) && (ttyfd > -1 ? ((rp = call_to_ip(a, 0)) != NULL) : ((rp = call_to_ip(a, 1)) != NULL))) { + if (rp->ip_addr.sin_addr.s_addr != ip_addr->sin_addr.s_addr) { +//fprintf(stderr, "foo: %s %u\n", call_to_a(a), rp); + /* mode AXIP is not loop save, since everyone hears his + * own packets. + * Thus Mode Digi works. But not Mode TNC, which is like + * a bridge.. And no, we have no spanning tree protocol ;) + */ + /* Warning - assuming buffer has room for 2 bytes */ + add_crc(buf, l); + l += 2; +//if (strstr(call_to_a(a), "DG8NGN")) +fprintf(stderr, "sent toIP %s\n", call_to_a(a)); + return send_ip(buf, l, rp); + } + } +send_kiss: + if (ttyfd > -1) { + if (!ttyfd_bpq) + send_kiss(port, buf, l); + else { + send_bpq(buf, l); + stats.bpq_out++; + } + } +} + +void from_ipx(buf, l, ipx_addr) +unsigned char *buf; +int l; +struct sockaddr_ipx *ipx_addr; +{ + int port = 0; + unsigned char *a; + + if (l < 15) { + stats.ipx_tooshort++; + LOGL2("from_ipx: dumped - length wrong!\n"); + return; + } + + if (loglevel > 2) + dump_ax25frame("from_ipx: ", buf, l); + + if (digi) { /* if we are in digi mode */ + a = next_addr(buf); + if (NOT_ME(a)) { + stats.ipx_not_for_me++; + LOGL2("from_ipx: (digi) dumped - not for me!\n"); + return; + } + if (a == buf) { /* must be a digi */ + stats.ipx_i_am_dest++; + LOGL2 + ("from_ipx: (digi) dumped - I am destination!\n"); + return; + } + if (dual_port == 1 && FOR_PORT2(a)) { + port = 0x10; + } + SETREPEATED(a); + a = next_addr(buf); /* find who gets it after us */ + } else { /* must be tnc mode */ + a = next_addr(buf); +fprintf(stderr, "sent toKISS %s\n", call_to_a(a)); +#ifdef TNC_FILTER + if (NOT_ME(a)) { + LOGL2 + ("from_ipx: (tnc) dumped - I am not destination!\n"); + return; + } +#endif + } /* end of tnc mode */ + + if (ttyfd > -1) { + if (!ttyfd_bpq) + send_kiss(port, buf, l); + else { + send_bpq(buf, l); + stats.bpq_out++; + } } } @@ -205,13 +312,15 @@ * Send an ID frame out the KISS port. */ -void do_beacon(void) +void do_beacon() { int i; unsigned char *p; if (bclen == 0) return; /* nothing to do! */ + if (!mycallsigns) + return; if (bclen < 0) { /* build the id string */ p = bcbuf; @@ -224,8 +333,8 @@ *p++ = '\0' | 0x60; /* SSID, set reserved bits */ for (i = 0; i < 6; i++) - *p++ = mycallsign[i]; - *p++ = mycallsign[6] | 0x60; /* ensure reserved bits are set */ + *p++ = mycallsigns->call[i]; + *p++ = (mycallsigns->call[6] | 0x60); /* ensure reserved bits are set */ SETLAST(bcbuf + 7); /* Set the E bit -- last address */ *p++ = 0x03; /* Control field -- UI frame */ @@ -240,18 +349,25 @@ if (loglevel > 2) dump_ax25frame("do_beacon: ", bcbuf, bclen); stats.kiss_beacon_outs++; - if (!ttyfd_bpq) - send_kiss(0, bcbuf, bclen); - else { - send_bpq(bcbuf, bclen); + + if (ttyfd > -1) { + if (!ttyfd_bpq) + send_kiss(0, bcbuf, bclen); + else { + send_bpq(bcbuf, bclen); + stats.bpq_out++; + } } + send_broadcast(bcbuf, bclen); } /* * return true if the addresses supplied match * modified for wildcarding by vk5xxx */ -int addrmatch(unsigned char *a, unsigned char *b) +int addrmatch(a, b, ignore_ssid) +unsigned char *a, *b; +int ignore_ssid; { if ((*a == '\0') || (*b == '\0')) return 0; @@ -268,18 +384,36 @@ return 0; /* "S" */ if ((*a++ ^ *b++) & 0xfe) return 0; /* "B" */ +#ifdef notdef /* urgs */ if (((*b) & 0x1e) == 0) return 1; /* ssid 0 matches all ssid's */ +#endif + if (ignore_ssid) + return 1; if ((*a++ ^ *b) & 0x1e) return 0; /* ssid */ /* if((*a++^*b++)&0x1e)return 0; ssid (how it was ...) */ return 1; } +int addrmatch2(unsigned char *a, struct callsign *m) +{ + int ret; + + while (m) { + if ((ret = addrmatch(a, m->call, m->match_all_ssids)) > 0) + return ret; + m = m->next; + } + return 0; +} + + /* * return pointer to the next station to get this packet */ -unsigned char *next_addr(unsigned char *f) +unsigned char *next_addr(f) +unsigned char *f; { unsigned char *a; @@ -301,10 +435,38 @@ } /* + * return pointer to the last station this packet came from + */ +unsigned char *from_addr(f) +unsigned char *f; +{ + unsigned char *a; + + a = f + 7; +/* If no digis, return the source address */ + if (NO_DIGIS(f)) + return a; + +/* check each digi field. Go to last that has seen it */ + do + a += 7; + while (NOT_LAST(a) && REPEATED(a)); + +/* in DIGI mode: we have set REPEATED already, so the one before is it */ + if (digi || !REPEATED(a)) + a -= 7; + +/* in TNC mode: always the last is it */ + return a; +} + +/* * tack on the CRC for the frame. Note we assume the buffer is long * enough to have the two bytes tacked on. */ -void add_crc(unsigned char *buf, int l) +void add_crc(buf, l) +unsigned char *buf; +int l; { unsigned short int u; @@ -316,7 +478,10 @@ /* * Dump AX25 frame. */ -void dump_ax25frame(char *t, unsigned char *buf, int l) +void dump_ax25frame(t, buf, l) +unsigned char *buf; +char *t; +int l; { #ifdef DEBUG int i; --- ax25ipdorig/routing.c 2009-08-24 22:48:57.000000000 +0200 +++ ax25ipd/routing.c 2009-05-17 14:04:49.000000000 +0200 @@ -12,22 +12,14 @@ #include #include #include +#include "routing.h" -/* The routing table structure is not visible outside this module. */ +#define call_is_wildcard(call) ((call[0] >> 1) == '*' && ((call[1] >> 1) == ' ')) -struct route_table_entry { - unsigned char callsign[7]; /* the callsign and ssid */ - unsigned char padcall; /* always set to zero */ - unsigned char ip_addr[4]; /* the IP address */ - unsigned short udp_port; /* the port number if udp */ - unsigned char pad1; - unsigned char pad2; - unsigned int flags; /* route flags */ - struct route_table_entry *next; -}; +/* The routing table structure is not visible outside this module. */ -struct route_table_entry *route_tbl; -struct route_table_entry *default_route; +static struct route_table_entry *route_tbl; +static struct route_table_entry *default_route; /* The Broadcast address structure is not visible outside this module either */ @@ -39,53 +31,168 @@ struct bcast_table_entry *bcast_tbl; /* Initialize the routing module */ -void route_init(void) +void route_init() { route_tbl = NULL; default_route = NULL; bcast_tbl = NULL; } +struct route_table_entry *find_best_rl_match(call, ip) +unsigned char *call; +struct sockaddr_in *ip; +{ + struct route_table_entry *rl; + struct route_table_entry *best_rl_match = 0; + for (rl = route_tbl; rl; rl = rl->next) { + if (!rl->is_template) + continue; +//{ struct in_addr foo; +//fprintf(stderr, "ip %u %s; ", ip->sin_addr.s_addr, inet_ntoa(ip->sin_addr)); +//fprintf(stderr, "rl mask %u %x; ", rl->ip_netmask, rl->ip_netmask); +//foo.s_addr = netmask; +//fprintf(stderr, "his mask %u %s ", netmask, inet_ntoa(foo)); +//foo.s_addr = (ip->sin_addr.s_addr & rl->ip_netmask); +//fprintf(stderr, "result %u %s.", foo.s_addr, inet_ntoa(foo)); +//fprintf(stderr, "rl ip %u %s\n", rl->ip_addr.sin_addr.s_addr, inet_ntoa(rl->ip_addr.sin_addr)); +//} + if ((ip->sin_addr.s_addr & rl->ip_netmask) == rl->ip_addr.sin_addr.s_addr) { +//fprintf(stderr, "ok - checking %s\n", call_to_a(rl->callsign)); + if ((rl->flags & AXRT_MATCH_ALL_SSIDS) ? !addrmatch(rl->callsign, call, 1) : !addrmatch(rl->callsign, call, 0)) { + /* not me and not wildcard -> someone else.. */ + if (!call_is_wildcard(rl->callsign)) + continue; + /* not me, and best_rl_match references me already */ + if (best_rl_match && addrmatch(best_rl_match->callsign, call, 0)) + continue; + } else { + /* it's me, and best_rl_match is wildcard: wins, regardless the netmask */ + if (best_rl_match && call_is_wildcard(best_rl_match->callsign)) { + best_rl_match = rl; + continue; + } + } + /* cave: netmask is in network order */ + if (!best_rl_match || (ntohl(best_rl_match->ip_netmask) < ntohl(rl->ip_netmask))) + best_rl_match = rl; + } + } + return best_rl_match; +} + /* Add a new route entry */ -void route_add(unsigned char *ip, unsigned char *call, int udpport, - unsigned int flags) +int route_add(ip, netmask, fqdn, call, flags) +struct sockaddr_in *ip; +unsigned long netmask; +unsigned char *fqdn; +unsigned char *call; +unsigned int flags; { struct route_table_entry *rl, *rn; + struct route_table_entry *best_rl_match = 0; int i; +int debug=0; +if (!strcmp(call_to_a(call), "DG8NGN")) +debug=1; + /* Check we have an IP address */ if (ip == NULL) - return; + return -2; +if (debug) printf("ip ok\n"); /* Check we have a callsign */ if (call == NULL) - return; + return -4; +if (debug) printf("call ok\n"); - /* Find the last entry in the list */ - rl = route_tbl; - if (route_tbl) - while (rl->next) - rl = rl->next; + if (!(flags & AXRT_FORCE_LEARN)) { + /* Find entry by callsign. */ + for (rl = route_tbl; rl; rl = rl->next) { +if (debug) printf("checking rl->callsing %s\n", call_to_a(rl->callsign)); + /* sould be very fast */ + if (rl->is_template) { +if (debug) printf("no - is template %d\n", rl->is_template); + continue; + } + if ((rl->flags & AXRT_MATCH_ALL_SSIDS) ? addrmatch(call, rl->callsign, 1) : addrmatch(call, rl->callsign, 0)) { +if (debug) printf("match -> goto modify\n"); + /* Modify this entry ... */ + goto modify; + } + } + /* if ip addresses should be updated (done above: goto + * modify..), but setup is that the autorouting + * feature is not wanted, then it's here the point to + * return */ + if (!autorouter) + return 0; +fprintf(stderr, "Not found: %s\n", call_to_a(call)); + if (!(best_rl_match = find_best_rl_match(call, ip))) + return -1; +//fprintf(stderr, "best_rl_match for %s: %u\n", call_to_a(call), best_rl_match); + /* use this template */ + flags = best_rl_match->flags; + } else { + if (!call_is_wildcard(call) && (netmask == 0xffffffffUL)) { + for (rl = route_tbl; rl; rl = rl->next) { + if (rl->is_template) + continue; + if ((rl->flags & AXRT_MATCH_ALL_SSIDS) ? !addrmatch(rl->callsign, call, 1) : !addrmatch(rl->callsign, call, 0)) + continue; + rl->flags = (flags & ~AXRT_FORCE_LEARN); + memcpy(&rl->ip_addr, ip, sizeof(struct sockaddr_in)); + rl->ip_addr.sin_addr.s_addr &= netmask; + rl->udp_port_default = ip->sin_port; + rl->ip_netmask = netmask; + rl->fqdn = fqdn; + rl->fqdn_last_resolved = currtime; + rl->last_heard = currtime; + rl->last_sent = currtime; + if (flags & AXRT_DEFAULT) + default_route = rl; + /* Log this entry ... */ + LOGL4("added route: %s %s %s %d %d\n", + call_to_a(rl->callsign), + (char *) inet_ntoa(rl->ip_addr.sin_addr), + rl->ip_addr.sin_port ? "udp" : "ip", ntohs(rl->ip_addr.sin_port), flags); + return 1; + } + } + } - rn = (struct route_table_entry *) - malloc(sizeof(struct route_table_entry)); + if (!(rn = (struct route_table_entry *) malloc(sizeof(struct route_table_entry)))) + return -1; /* Build this entry ... */ + + rn->is_template = ((flags & AXRT_FORCE_LEARN) && (netmask != 0xffffffffUL || call_is_wildcard(call))) ? 1 : 0; + rn->flags = (flags & ~AXRT_FORCE_LEARN); + for (i = 0; i < 6; i++) rn->callsign[i] = call[i] & 0xfe; rn->callsign[6] = (call[6] & 0x1e) | 0x60; + +if (debug) printf("oops, fqdn?.. >%s<\n", fqdn); rn->padcall = 0; - memcpy(rn->ip_addr, ip, 4); - rn->udp_port = htons(udpport); + memcpy(&rn->ip_addr, ip, sizeof(struct sockaddr_in)); + rn->ip_addr.sin_addr.s_addr &= netmask; + rn->udp_port_default = (best_rl_match ? best_rl_match->ip_addr.sin_port : ip->sin_port); + rn->ip_netmask = netmask; + rn->fqdn = fqdn ? fqdn : (best_rl_match ? best_rl_match->fqdn : 0); + rn->fqdn_last_resolved = currtime; + rn->last_heard = currtime; + rn->last_sent = currtime; rn->pad1 = 0; rn->pad2 = 0; - rn->flags = flags; rn->next = NULL; /* Update the default_route pointer if this is a default route */ if (flags & AXRT_DEFAULT) default_route = rn; + /* Find the last entry in the list */ + for (rl = route_tbl; rl && rl->next; rl = rl->next) ; if (rl) /* ... the list is already started add the new route */ rl->next = rn; else /* ... start the list off */ @@ -94,14 +201,75 @@ /* Log this entry ... */ LOGL4("added route: %s %s %s %d %d\n", call_to_a(rn->callsign), - (char *) inet_ntoa(*(struct in_addr *) rn->ip_addr), - rn->udp_port ? "udp" : "ip", ntohs(rn->udp_port), flags); + (char *) inet_ntoa(rn->ip_addr.sin_addr), + rn->ip_addr.sin_port ? "udp" : "ip", ntohs(rn->ip_addr.sin_port), flags); + + return 1; - return; +modify: +if (debug) printf("modify..\n"); + if ((rl->flags & AXRT_PERMANENT) && rl->ip_addr.sin_addr.s_addr != 0L) { +if (debug) printf("oops, permanent?..\n"); + if (rl->ip_addr.sin_addr.s_addr == ip->sin_addr.s_addr) { + rl->last_heard = currtime; + goto end; + } +if (debug) printf("return -1 %u %u\n", rl->ip_addr.sin_addr.s_addr, ip->sin_addr.s_addr); + return -1; + } + if (rl->fqdn) { +if (debug) printf("oops, fqdn?.. >%s<\n", rl->fqdn); + /* ..still receiving packets */ + /* ..but not let this open up to infinity: if the remote + * site was quiet for DNSDELAY seconds, then drop it's + * packets until we resolve it correctly. + * We force to resolve, if last resolve is 15min ago. + * We aviod DOS attacks: we do to not resolve every packet, + * for not beeing locked due bad DNS responses. + */ + if (currtime - rl->last_heard > DNSDELAY || (currtime - rl->fqdn_last_resolved > DNSDELAY*3)) { + struct hostent *he; + rl->last_heard = rl->fqdn_last_resolved = currtime; + if ((he = gethostbyname(rl->fqdn))) { + if (ip->sin_addr.s_addr != ((struct in_addr *)(he->h_addr))->s_addr) { + /* data came not from the host the current dyndns entry points to */ + /* -> ignore + * ..but: do not resolve on every heard packet: that's why set last_heard + * and fqdn_last_resolve above */ +if (debug) fprintf(stderr, "bad host %u %u\n", ip->sin_addr.s_addr, ((struct in_addr *)(he->h_addr))->s_addr); + return -1; + } + rl->ip_addr.sin_addr.s_addr = ip->sin_addr.s_addr; + } else { + /* temporary resolver error. be unfriendly */ + return -1; + } + } + } + if (rl->ip_addr.sin_addr.s_addr != ip->sin_addr.s_addr) { + /* ip address in one of our allowed networks? */ + if (!(best_rl_match = find_best_rl_match(call, ip))) + return -1; +if (debug) printf("adjusted route..\n"); + rl->flags = (flags & ~AXRT_FORCE_LEARN); + rl->ip_addr.sin_addr.s_addr = ip->sin_addr.s_addr; + LOGL4("modified route: %s %s %s %d %d\n", + call_to_a(rl->callsign), + (char *) inet_ntoa(rl->ip_addr.sin_addr), + rl->ip_addr.sin_port ? "udp" : "ip", + ntohs(rl->ip_addr.sin_port), rl->flags); + } +//fprintf(stderr, "MAY notify: %s\n", call_to_a(call)); +end: + rl->ip_addr.sin_port = ip->sin_port; + rl->last_heard = currtime; +if (debug) printf("returning 0\n"); + return 0; } /* Add a new broadcast address entry */ -void bcast_add(unsigned char *call) +void bcast_add(call) +unsigned char *call; { struct bcast_table_entry *bl, *bn; int i; @@ -141,7 +309,8 @@ * immediately following the IP address. (UGLY coding; to be fixed later!) */ -unsigned char *call_to_ip(unsigned char *call) +struct route_table_entry *call_to_ip(call, show_default_route) +unsigned char *call; { struct route_table_entry *rp; unsigned char mycall[7]; @@ -157,26 +326,43 @@ LOGL4("lookup call %s ", call_to_a(mycall)); - rp = route_tbl; - while (rp) { - if (addrmatch(mycall, rp->callsign)) { + for (rp = route_tbl; rp; rp = rp->next) { + if (rp->is_template) + continue; + if ((rp->flags & AXRT_MATCH_ALL_SSIDS) ? addrmatch(mycall, rp->callsign, 1) : addrmatch(mycall, rp->callsign, 0)) { LOGL4("found ip addr %s\n", - (char *) inet_ntoa(*(struct in_addr *) - rp->ip_addr)); - return rp->ip_addr; + (char *) inet_ntoa(rp->ip_addr.sin_addr)); + if (rp->fqdn && (!(rp->flags & AXRT_PERMANENT) || rp->ip_addr.sin_addr.s_addr == 0L)) { + if (currtime - rp->last_sent > DNSDELAY || (currtime - rp->fqdn_last_resolved > DNSDELAY*3)) { + struct hostent *he; + rp->fqdn_last_resolved = currtime; + if ((he = gethostbyname(rp->fqdn))) + rp->ip_addr.sin_addr.s_addr = ((struct in_addr *)(he->h_addr))->s_addr; + /* else: temporary resolver error. be gentle */ + /* no packets heard? - reset udp port */ + if (currtime - rp->last_heard > DNSDELAY) + rp->ip_addr.sin_port = rp->udp_port_default; + } + } + if (rp->ip_addr.sin_addr.s_addr == 0L) { + rp->last_sent = currtime; /* in doubt, fake last_sent, in order to keep resolvings low */ + return NULL; + } + return rp; } - rp = rp->next; } + if (!show_default_route) + return(0); + /* * No match found in the routing table, use the default route if * we have one defined. */ if (default_route) { LOGL4("failed, using default ip addr %s\n", - (char *) inet_ntoa(*(struct in_addr *) - default_route->ip_addr)); - return default_route->ip_addr; + (char *) inet_ntoa(default_route->ip_addr.sin_addr)); + return default_route; } LOGL4("failed.\n"); @@ -187,7 +373,8 @@ * Accept a callsign and return true if it is a broadcast address, or false * if it is not found on the list */ -int is_call_bcast(unsigned char *call) +int is_call_bcast(call) +unsigned char *call; { struct bcast_table_entry *bp; unsigned char bccall[7]; @@ -205,7 +392,7 @@ bp = bcast_tbl; while (bp) { - if (addrmatch(bccall, bp->callsign)) { + if (addrmatch(bccall, bp->callsign, 0)) { LOGL4("found broadcast %s\n", call_to_a(bp->callsign)); return (TRUE); @@ -216,38 +403,70 @@ } /* Traverse the routing table, transmitting the packet to each bcast route */ -void send_broadcast(unsigned char *buf, int l) +void send_broadcast(buf, l) +unsigned char *buf; +int l; { struct route_table_entry *rp; - rp = route_tbl; - while (rp) { + if (ipx_mode) { + send_ipx(buf, l, 0); + return; + } + + for (rp = route_tbl; rp; rp = rp->next) { + if (rp->is_template) + continue; if (rp->flags & AXRT_BCAST) { - send_ip(buf, l, rp->ip_addr); + if (rp->fqdn && (!(rp->flags & AXRT_PERMANENT) || rp->ip_addr.sin_addr.s_addr == 0L)) { + if (currtime - rp->last_sent > DNSDELAY || (currtime - rp->fqdn_last_resolved > DNSDELAY*3)) { + struct hostent *he; + rp->fqdn_last_resolved = currtime; + if ((he = gethostbyname(rp->fqdn))) + rp->ip_addr.sin_addr.s_addr = ((struct in_addr *)(he->h_addr))->s_addr; + /* else: temporary resolver error. be gentle */ + /* no packets heard? - reset udp port */ + if (currtime - rp->last_heard > DNSDELAY) + rp->ip_addr.sin_port = rp->udp_port_default; + } + } + if (rp->ip_addr.sin_addr.s_addr != 0L) + send_ip(buf, l, rp); + else + rp->last_sent = currtime; /* in doubt, fake last_sent, in order to keep resolvings low */ } - rp = rp->next; } } /* print out the list of routes */ -void dump_routes(void) +void dump_routes() { struct route_table_entry *rp; - int i; + int i = 0; + int j = 0; - for (rp = route_tbl, i = 0; rp; rp = rp->next) - i++; + for (rp = route_tbl; rp; rp = rp->next) { + if (rp->is_template) + j++; + else + i++; + } - LOGL1("\n%d active routes.\n", i); + LOGL1("\n%d active routes, %d templates.\n", i, j); - rp = route_tbl; - while (rp) { - LOGL1(" %s\t%s\t%s\t%d\t%d\n", - call_to_a(rp->callsign), - (char *) inet_ntoa(*(struct in_addr *) rp->ip_addr), - rp->udp_port ? "udp" : "ip", - ntohs(rp->udp_port), rp->flags); - rp = rp->next; + for (i = 0; i < 2; i++) { + LOGL1("\n%s\n", (i ? "Active Routes" : "Template Routes")); + for (rp = route_tbl; rp; rp = rp->next) { + if (!i && !rp->is_template) + continue; + if (i && rp->is_template) + continue; + LOGL1(" %9.9s %15.15s %3.3s %5d %d\n", + call_to_a(rp->callsign), + (char *) inet_ntoa(rp->ip_addr.sin_addr), + rp->ip_addr.sin_port ? "udp" : "ip", + ntohs(rp->ip_addr.sin_port), rp->flags); + } } fflush(stdout); } --- ax25ipdorig/ax25ipd.h 2009-08-24 22:48:57.000000000 +0200 +++ ax25ipd/ax25ipd.h 2009-05-17 13:37:39.000000000 +0200 @@ -8,7 +8,7 @@ /* * Modifications added for dual port kiss TNC - * by Michael Durrant VE3PNX and D. Jeff Dionne Feb 4, 1995 + * by Michael Durrant and D. Jeff Dionne Feb 4, 1995 */ /* @@ -54,16 +54,15 @@ #include #include #include -#define __USE_XOPEN #include #include #include -#include #include #include #include #include #include +#include #include #include #include @@ -72,22 +71,33 @@ #include #include +struct callsign { + unsigned char call[7]; /* Call, shifted ASCII with SSID */ + int match_all_ssids; + struct callsign *next; +}; + int udp_mode; /* true if we need a UDP socket */ int ip_mode; /* true if we need the raw IP socket */ +int ipx_mode; /* true if we need the raw IPX socket */ unsigned short my_udp; /* the UDP port to use (network byte order) */ -char ttydevice[PATH_MAX]; /* the tty device for serial comms */ +in_addr_t my_udp_addr; /* bind to addr (default INADDR_ANY) */ +char ttydevice[128]; /* the tty device for serial comms */ int ttyspeed; /* The baud rate on the tty device */ -unsigned char mycallsign[7]; /* My callsign, shifted ASCII with SSID */ -unsigned char mycallsign2[7]; /* My seconds port callsign, shifted ASCII with SSID */ -unsigned char myalias[7]; /* An alias to use */ -unsigned char myalias2[7]; /* An alias for second port */ +extern struct callsign *mycallsigns; /* My callsigns, each shifted ASCII with SSID */ +extern struct callsign *mycallsigns2; /* My callsigns on second port, each shifted ASCII with SSID */ +extern struct callsign *myalias; /* My aliases, each shifted ASCII with SSID */ +extern struct callsign *myalias2; /* My aliases on second port, each shifted ASCII with SSID */ char bc_text[128]; /* The text for beacon messages */ int bc_interval; /* The interval, in seconds, between beacons */ int bc_every; /* true=every, false=after */ int digi; /* True if we are connected to a TNC */ +int isolate; /* Prohibit inter-IP-user-traffic */ +int autorouter; /* auto_routing feature */ int loglevel; /* Verbosity level */ /* addition for dual port flag */ int dual_port; +time_t currtime; /* current system time */ struct { int kiss_in; /* # packets received */ @@ -107,6 +117,13 @@ int ip_tooshort; /* packet too short to be a valid frame */ int ip_not_for_me; /* packet not for me (in digi mode) */ int ip_i_am_dest; /* I am destination (in digi mode) */ + int ipx_in; /* # packets received */ + int ipx_out; /* # packets sent */ + int ipx_tooshort; /* packet too short to be a valid frame */ + int ipx_not_for_me; /* packet not for me (in digi mode) */ + int ipx_i_am_dest; /* I am destination (in digi mode) */ + int bpq_in; /* # packets received */ + int bpq_out; /* # pckets sent */ } stats; #define MAX_FRAME 2048 @@ -118,6 +135,11 @@ #define AXRT_BCAST 1 #define AXRT_DEFAULT 2 +#define AXRT_PERMANENT 4 +#define AXRT_FORCE_LEARN 8 +#define AXRT_MATCH_ALL_SSIDS 16 + +#define DNSDELAY 300L /* start external prototypes */ /* end external prototypes */ @@ -133,9 +155,9 @@ /* routing.c */ void route_init(void); -void route_add(unsigned char *, unsigned char *, int, unsigned int); +int route_add(struct sockaddr_in *, unsigned long, unsigned char *, unsigned char *, unsigned int); void bcast_add(unsigned char *); -unsigned char *call_to_ip(unsigned char *); +struct route_table_entry *call_to_ip(unsigned char *, int); int is_call_bcast(unsigned char *); void send_broadcast(unsigned char *, int); void dump_routes(void); @@ -151,11 +173,14 @@ /* process.c */ void process_init(void); void from_kiss(unsigned char *, int); -void from_ip(unsigned char *, int); +void from_ip(unsigned char *, int, struct sockaddr_in *); +void from_ipx(unsigned char *, int, struct sockaddr_ipx *); /* void do_broadcast(void); where did this go ?? xxx */ void do_beacon(void); -int addrmatch(unsigned char *, unsigned char *); +int addrmatch2(unsigned char *, struct callsign *); +int addrmatch(unsigned char *, unsigned char *, int); unsigned char *next_addr(unsigned char *); +unsigned char *from_addr(unsigned char *); void add_crc(unsigned char *, int); void dump_ax25frame(char *, unsigned char *, int); @@ -163,13 +188,18 @@ void io_init(void); void io_open(void); void io_start(void); -void send_ip(unsigned char *, int, unsigned char *); +void send_ip(unsigned char *, int, struct route_table_entry *); +void send_ipx(unsigned char *, int, struct route_table_entry *); void send_tty(unsigned char *, int); int io_error(int, unsigned char *, int, int, int, int); +extern int ttyfd_bpq; +extern int ttyfd; +extern char *cmdsock_name; + /* crc.c */ unsigned short int compute_crc(unsigned char *, int); -unsigned short int pppfcs(unsigned short, unsigned char *, int); +unsigned short int pppfcs(register unsigned short, register unsigned char *, register int); unsigned short int compute_crc(unsigned char *, int); int ok_crc(unsigned char *, int); @@ -182,9 +212,6 @@ void int_handler(int); void term_handler(int); -/* io.c */ -extern int ttyfd_bpq; - /* bpqether.c */ int send_bpq(unsigned char *buf, int len); int receive_bpq(unsigned char *buf, int l); --- ax25ipdorig/routing.h 1970-01-01 01:00:00.000000000 +0100 +++ ax25ipd/routing.h 2006-08-01 09:15:34.000000000 +0200 @@ -0,0 +1,22 @@ + +#ifndef ROUTING_H +#define ROUTING_H + +struct route_table_entry { + unsigned char callsign[7]; /* the callsign and ssid */ + unsigned char padcall; /* always set to zero */ + struct sockaddr_in ip_addr; + unsigned short udp_port_default;/* the port number if udp */ + unsigned long ip_netmask; /* the Netmask */ + unsigned char *fqdn; /* for dyndns. May be NULL */ + time_t fqdn_last_resolved; /* time when resolved fqdn resolved */ + time_t last_heard; /* time when host was heard last */ + time_t last_sent; /* time when host was heard last */ + unsigned char pad1; + unsigned char pad2; + unsigned int flags; /* route flags */ + unsigned char is_template; + struct route_table_entry *next; +}; + +#endif --- ax25ipdorig/ax25ipd.conf 2008-10-11 20:46:36.000000000 +0200 +++ ax25ipd/ax25ipd.conf 2007-04-06 15:36:22.000000000 +0200 @@ -3,12 +3,24 @@ # # Select axip transport. 'ip' is what you want for compatibility # with most other gates ... +# socket [[bindaddr]:port] +# bindaddr: listen only on this IP address (for e.g. 127.0.0.1 for security +# reasons) # socket ip # -# Set ax25ipd mode of operation. (digi or tnc) -# -mode tnc +# Enable commands to the running ax25ipd via unix socket on path cmdsock_name: +# (if relative path given, then path defaults to AX25_LOCALSTATEDIR, for e.g. +# /var/axw25/). +#cmdsock_name ax25ipd_cmd +# +# Set ax25ipd mode of operation. (digi or tnc (bridge)) +# Optional, you could disable inter-AXIP/AXUDP-traffic (isolate) +# +mode digi +#mode digi isolate +#mode tnc +#mode bridge # # If you selected digi, you must define a callsign. If you selected # tnc mode, the callsign is currently optional, but this may change @@ -29,6 +41,8 @@ # # # Serial port, ethertap interface, or pipe connected to a kissattach in my case +# If set to "none", ax25ipd just passes ax25-packets between his axip +# or axudp partners # # alternatively, if you have the kernel module bpqether: # if you use tun/tap or ethertap instead of kissattach you may say, without @@ -41,20 +55,15 @@ # make sure you set a mycall above, or say axparms foobar -setcall te1st # note: the device will be up when you assign an ip address # _after_ starting ax25rtd (which initializes the device), start ax25d -# with bpqether or pty, you do not need to care about the speed +# with bpqether or pty, you do not need to care abt the speed # tun/tap: as descriped in /usr/src/linux/Documentatioa/networking/tuntap.txt, # make a device # like this: # crw-r--r-- 1 root root 10, 200 Nov 26 13:32 tun # with the command mknod /dev/net/tun c 10 200 -# As serial port, you could assign physical ports like ttyS0 or ptys. -# ax25ipd supports BSD-style pseudo-terminals as well as the Unix98 pty's. -# If the tty argument is "/dev/ptmx", then Unix98 behaviour -# will automaticaly take effekt. With Unix98 pty's, the slave tty name -# could not be forseen. That's why ax25ipd will print the corresponding -# slave pty name as a separate line on stdout. # #device ampr -device /dev/ttyp0 +#device /dev/ttyp0 +#device none # # # Set the device speed @@ -80,18 +89,44 @@ # broadcast QST-0 NODES-0 # +# autorouter +# ax25ipd learns how calls could be reached (via which ip). See below. +# There are environments, where you like to just pass packets from left +# to right, and vice versa. autorouter is "on" (argument "1"), and could +# be configured to be off (autorouter 0). +# Even if disabled, the routing code is capable to adjust the source +# ip address and/or source port for a configured "route" entry (if not +# set to be permanent, of course). +# # ax.25 route definition, define as many as you need. # format is route (call/wildcard) (ip host at destination) # ssid of 0 routes all ssid's # -# route [flags] +# route [|] [udp dst-port] [flags] +# +# Users behind NAT routers may hav a different source-port. # # Valid flags are: # b - allow broadcasts to be transmitted via this route # d - this route is the default route +# p - permanent # #route vk2sut-0 44.136.8.68 b #route vk5xxx 44.136.188.221 b #route vk2abc 44.1.1.1 +#route db0aaa 127.0.0.1 p +#route db0aab 10.1.2.3 udp 20005 +# For dyndns hosts: IP may change, but resolving of the hostname +# has to point to the same IP address where IP frames come from. +# If flag "p" is set, the host is static (resolved once, on startup). +#route db0abc db0abc.de +# +# Autolearn new (not configured) hosts. +# Valid flags in this case: "b", "p" (learn once). +#route * 0.0.0.0/0 b +#route * 10.1.0.0/16 +#route * 10.2.2.2/32 +# accept db0yyy only when coming vom 10.3.3.0/24 +#route db0yyy 10.3.3.0/24 # #