node-0.3.2/0040755000076400007640000000000007722715450010650 5ustar tpmtpmnode-0.3.2/HISTORY0100644000076400007640000001715507722207356011743 0ustar tpmtpm0.3.2 23 Aug 2003 - Security fixes. Thanks SM6TKY. - Fixed buffer overflow in expand_string() - Receiving a talk message didn't flush output buffers immediately - Don't switch to binary mode when asking a password. 0.3.1 16 Mar 2003 - Fixed non-blocking response for new libax25io. (thanks Jeroen, PE1RXQ) - Fixed installation of man pages - Fixed sysinfo 0.3.0 05 Jul 1999 - Initial version using the new dynamic libax25. - Moved the IO code to libax25. 0.2.6 04 Feb 1999 - "Links *" doesn't crash anymore if someone is listening on all ports. - Added zlib based stream compression to the io library. See -c option, zconnect command and ztelnet command in node(8). - Added signal handlers for SIGINT, SIGQUIT and SIGSEGV. - Node should now compile with glibc. - Plugged a major security hole. - Node sends a Goodbye message at logout. - Adapted Links command for 2.1.x changes. 0.2.5 17 Nov 1997 - Small changes in the IO library. Connection trough multiple LinuxNodes with mixed protocols should now really be 8 bit clean. - Added ResolveAddrs configuration command. - French help files. Tnx Gerard (f6fgz). - Added NLinks user command. - Adapted for changes in procutils that permit connecting to oneself. - Added some #ifdef HAVExxx conditionals to the code. - Memory display might now work with later 2.1.xx kernels. - Small bug fixed (read_perms() now closes the file). - Nodeusers uses standard out for output. - Some restructuring in nodeusers.c. - Telnet and ax.25 port is printed and logged in gateway connects. - Added TTL to ping command output. - Added sysop configurable prompt (see node.conf(5)). - Rethink of the command parser. %-escapes and C-style character literals (\n, \x1f etc.) are now always parsed except when inside single quotes ('). Alias and ExtCmd syntax has to be slightly changed in node.conf (see the example files). - Added new %-escapes: %f, %h, %i. - Added PIDs to mheard command output. 0.2.4 xx May 1997 - Added a user command Escape to set (or disable) the escape character. Also EscapeChar config command has now slightly different syntax. - Added syslogging to nodeusers 0.2.3 02 May 1997 - Hopefully fixed the "could not get IPC channel" bug (SIGPIPE is now ignored). - Not getting an IPC channel is no longer a fatal error. - Added a reconnect flag to extcmds. If flag is set, user gets a prompt after the extcmd is completed. - The reason for program termination is now logged. - Added an escape mechanism to abort the current gateway connection. - NrPort now defaults to NULL ie. the first netrom port. - Extensive rewrite of the command parser. - Aliases and ExtCmds now take positional parameters. See node.conf(5). - Telnet command now takes an optional third argument that is sent to the remote host right after the connection is established. - Removed CAllbook command. It can now be defined as an alias. See the supplied sample configuration file. - The DNIC part of a ROSE address now defaults to the local DNIC in outgoing connects. Tnx Jean-Paul (f6fbb). - "nodeusers -i" now waits for a newline before sending anything. 0.2.2 10 Feb 1997 - Fixed inverting of ssid (port name not case sensitive anymore) - Info file now in /etc/ax25/node.info - Added installhelp target to the makefile. 0.2.1 29 Jan 1997 - Links command behaviour changed (by default don't list listening sockets) - A Talk command from Hessu (oh7lzb) - Loggedin file size is tested at startup 0.2.0 05 Jan 1997 - Added separate nodeusers(1) program - Added HOst and Status command (see node(8)) - General cleanup here and there - Telnet command works even if written in upper case... - Mheard output format changed - Logging. See LogLevel command in node.conf(5) and the README file!!! - Rose support (tnx Jonathan) - Added NodeId command (see node.conf(5)) - HiddenPorts probably didn't work. It should now. - Behaviour of getsockopt(...SOL_SOCKET,SO_ERROR...) seems to have been changed again... - The error message given when a connection fails looks now more like the message given by thenet and BPQ nodes (always contains the word "Failure"). - Node now sends /etc/ax25/node.motd after login if it exists - Correct paclen is now used also when node isn't on the first netrom device - NrPort command (see node.conf(5)) is now used to define the port that is used for outgoing netrom connects 0.1.12 21 Aug 1996 - Node doesn't need port name anymore (kernel version 2.0.12 or later is needed for this to work) - Added support for g4klx mheardd (mheard works again) 0.1.11 06 Aug 1996 - SSID is now inverted only in outgoing AX.25 connections. - find_link() now checks port too (procutils.c) - Small bug in connect_to() fixed. - First attempt at external command support - User logging code slightly changed. - Added "pinging" and "extcmd" states to "users" command. - "struct fdset" -> "fdset" - Paclen defaults to 128 and port name to "unknown" if no port or invalid port is given in node command line (AX.25 only). 0.1.10 02 Jun 1996 - Bug in password routine fixed - Changed syntax of node.perms - Mheard, Links and Routes won't display hidden ports anymore - Added SIGTERM handler - Some cleaning up in nodeuser.c (login_user() now uses first free slot found in loggedin file) - Removed "speed" field from Ports command (it isn't necessarily the speed of the radio channel) - Added "d" flag to Connect and Telnet commands (useful for forward scripts). - Wrote man pages. (node(8), node.conf(5) and node.perms(5)) 0.1.9 22 May 1996 - Argh. A typo in Routes fixed... - More help texts (tnx Hessu OH7LZB) - Fixed bug in alias handling 0.1.8 19 May 1996 - Routes shows active link also if the link is recovering - Small changes in procutils.c - Behaviour of getsockopt(...SOL_SOCKET,SO_ERROR...) seems to have been changed. A small fix in connect_to() - Empty node alias field now allowed (needs a kernel patch to work) 0.1.7 16 May 1996 - Some polishing here and there - Added "which" field to Nodes command 0.1.6 15 May 1996 - A small fix in procutils.c - Added more comments in the sample configuration files 0.1.5 14 May 1996 - Changed do_ports() to be compatible with ax25-utils-2.0-ALPHA2 - Implemented hidden ports - loopback network (127.xx.xx.xx) is now always counted as "local" network 0.1.4 12 May 1996 - Typo in do_links() fixed - Updated Links command for new kernels - Extracted all /proc/net reading routines into a separate procutils.c file 0.1.3 09 May 1996 - Adapted for the config changes in ax25-utils-2.0-ALPHA1 - Added callsign validity check at login - The ping bug _seems_ to be fixed now 0.1.2 08 May 1996 - Bug in do_nodes() with no known nodes fixed - Small changes in io.c - Some more comments added - A few Makefile changes - An obscure bug in do_ping found but not yet fixed 0.1.1 May 1996 - Incoming/outgoing telnet support added - Aliases added - User priviledges per /usr/local/node/node.perms added - Finger and Callbook clients added - LinuxNode can now be called from command line - Links command added 0.1 Jan 1996 - First release version (not really released) - Basic functionality -- Tomi Manninen OH2BNS@OH2RBI.FIN.EU tomi.manninen@hut.fi node-0.3.2/Makefile0100644000076400007640000000376307721674717012327 0ustar tpmtpmall: nodeusers node CC = gcc LD = gcc CFLAGS = -Wall -Wstrict-prototypes -O2 -g LDFLAGS = LIBS = -lax25 -lax25io include Makefile.include COMMON_SRC = user.c util.c NODE_SRC = node.c cmdparse.c config.c command.c \ gateway.c extcmd.c sysinfo.c ipc.c NODEUSERS_SRC = nodeusers.c COMMON_OBJS = $(COMMON_SRC:.c=.o) NODE_OBJS = $(NODE_SRC:.c=.o) NODEUSERS_OBJS = $(NODEUSERS_SRC:.c=.o) .c.o: $(CC) $(CFLAGS) -c $< install: installbin installman installhelp install -m 755 -o root -g root -d $(VAR_DIR)/node install -m 644 -o root -g root etc/loggedin $(VAR_DIR)/node @rm -f /usr/bin/node @rm -f /usr/bin/nodeusers installbin: all install -m 4755 -s -o root -g root node $(SBIN_DIR) install -m 755 -s -o root -g root nodeusers $(SBIN_DIR) installhelp: install -m 755 -o root -g root -d $(LIB_DIR)/ax25/node/help install -m 644 -o root -g root etc/help/*.hlp $(LIB_DIR)/ax25/node/help installconf: installhelp install -m 755 -o root -g root -d $(ETC_DIR) install -m 600 -o root -g root etc/node.conf $(ETC_DIR) install -m 600 -o root -g root etc/node.perms $(ETC_DIR) install -m 600 -o root -g root etc/node.motd $(ETC_DIR) installman: install -m 644 -o bin -g bin man/nodeusers.1 $(MAN_DIR)/man1 install -m 644 -o bin -g bin man/node.conf.5 $(MAN_DIR)/man5 install -m 644 -o bin -g bin man/node.perms.5 $(MAN_DIR)/man5 install -m 644 -o bin -g bin man/node.8 $(MAN_DIR)/man8 clean: rm -f *.o *~ *.bak *.orig rm -f etc/*~ etc/*.bak etc/*.orig rm -f etc/help/*~ etc/help/*.bak etc/help/*.orig distclean: clean rm -f .depend Makefile.include config.h rm -f node nodeusers depend: $(CC) $(CFLAGS) -M $(COMMON_SRC) $(NODE_SRC) $(NODEUSERS_SRC) > .depend node: $(COMMON_OBJS) $(NODE_OBJS) $(LD) $(LDFLAGS) -o node $(COMMON_OBJS) $(NODE_OBJS) $(LIBS) $(ZLIB) nodeusers: $(COMMON_OBJS) $(NODEUSERS_OBJS) $(LD) $(LDFLAGS) -o nodeusers $(COMMON_OBJS) $(NODEUSERS_OBJS) $(LIBS) $(ZLIB) ifeq (.depend,$(wildcard .depend)) include .depend endif node-0.3.2/README0100644000076400007640000000272007721670101011516 0ustar tpmtpmLinuxNode v0.3.2 Copyright (C) 1996-2003 by Tomi Manninen. This is a simple node frontend for Linux kernel AX.25, NETROM, ROSE and TCP. It's based on pms.c by Alan Cox (GW4PTS) but has been heavily modified since. It's probably not very well tested, not pretty, not very flexible and it is certainly not ready! However I think it's already somewhat usable. The installation instructions are in the file INSTALL. 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. TODO: The manual pages need some work, some things have changed. LocalNets should be a list of subnets, not one subnet plus 127/8. Syslog facility and level should be configurable. An option to sort the nodes listing by the callsign. Lots of things (I suppose. Does anyone have any suggestions?). -- Tomi Manninen OH2BNS, node-0.3.2/command.c0100644000076400007640000004004007721673362012431 0ustar tpmtpm#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "node.h" #include "sysinfo.h" struct cmd *Nodecmds = NULL; void init_nodecmds(void) { add_internal_cmd(&Nodecmds, "?", 1, do_help); add_internal_cmd(&Nodecmds, "Bye", 1, do_bye); add_internal_cmd(&Nodecmds, "Connect", 1, do_connect); add_internal_cmd(&Nodecmds, "Escape", 1, do_escape); add_internal_cmd(&Nodecmds, "Finger", 1, do_finger); add_internal_cmd(&Nodecmds, "Help", 1, do_help); add_internal_cmd(&Nodecmds, "HOst", 2, do_host); add_internal_cmd(&Nodecmds, "Info", 1, do_help); add_internal_cmd(&Nodecmds, "Links", 1, do_links); add_internal_cmd(&Nodecmds, "Mheard", 1, do_mheard); #ifdef HAVE_NETROM add_internal_cmd(&Nodecmds, "NLinks", 2, do_nlinks); add_internal_cmd(&Nodecmds, "Nodes", 1, do_nodes); #endif add_internal_cmd(&Nodecmds, "PIng", 2, do_ping); add_internal_cmd(&Nodecmds, "Ports", 1, do_ports); #ifdef HAVE_NETROM add_internal_cmd(&Nodecmds, "Routes", 1, do_routes); #endif add_internal_cmd(&Nodecmds, "Status", 1, do_status); add_internal_cmd(&Nodecmds, "TAlk", 2, do_talk); add_internal_cmd(&Nodecmds, "Telnet", 1, do_connect); add_internal_cmd(&Nodecmds, "Users", 1, do_users); #ifdef HAVE_ZLIB_H add_internal_cmd(&Nodecmds, "ZConnect", 1, do_connect); add_internal_cmd(&Nodecmds, "ZTelnet", 1, do_connect); #endif }; void logout(char *reason) { axio_end_all(); logout_user(); ipc_close(); log(L_LOGIN, "%s @ %s logged out: %s", User.call, User.ul_name, reason); free_cmdlist(Nodecmds); Nodecmds = NULL; exit(0); } int do_bye(int argc, char **argv) { node_msg("Goodbye"); logout("Bye"); return 0; /* Keep gcc happy */ } int do_escape(int argc, char **argv) { int now = 0; if (argc > 1) { EscChar = get_escape(argv[1]); now = 1; } if (EscChar < -1 || EscChar > 255) { node_msg("Invalid escape character: %s", argv[1]); return 0; } if (EscChar == -1) { node_msg("The escape mechanism is %sdisabled", now ? "now " : ""); return 0; } node_msg("The escape character is %s%s%c", now ? "now " : "", EscChar < 32 ? "CTRL-" : "", EscChar < 32 ? (EscChar + 'A' - 1) : EscChar); return 0; } struct mheard_list { struct mheard_struct data; struct mheard_list *next; }; int do_mheard(int argc, char **argv) { FILE *fp; struct mheard_struct mh; struct mheard_list *list, *new, *tmp, *p; char *s, *t, *u; long ti; if (argc < 2) { node_msg("Usage: mheard "); return 0; } if (ax25_config_get_dev(argv[1]) == NULL || (check_perms(PERM_HIDDEN, 0) == -1 && is_hidden(argv[1]))) { node_msg("Invalid port"); return 0; } if ((fp = fopen(DATA_MHEARD_FILE, "r")) == NULL) { node_perror(DATA_MHEARD_FILE, errno); return 0; } list = NULL; while (fread(&mh, sizeof(struct mheard_struct), 1, fp) == 1) { if (strcmp(argv[1], mh.portname)) continue; if ((new = calloc(1, sizeof(struct mheard_list))) == NULL) { node_perror("do_mheard: calloc", errno); break; } new->data = mh; if (list == NULL || mh.last_heard > list->data.last_heard) { tmp = list; list = new; new->next = tmp; } else { for (p = list; p->next != NULL; p = p->next) if (mh.last_heard > p->next->data.last_heard) break; tmp = p->next; p->next = new; new->next = tmp; } } fclose(fp); node_msg("Heard list for port %s:", argv[1]); nputs("Callsign Frames Last heard Pids\n"); while (list != NULL) { s = ctime(&list->data.last_heard); s[19] = 0; s += 4; t = ax25_ntoa(&list->data.from_call); if ((u = strstr(t, "-0")) != NULL) *u = '\0'; nprintf("%-9s %-8ld %s (", t, list->data.count, s); ti = time(NULL) - list->data.last_heard; if (ti < 60L) nprintf(" %2lds", ti); else if (ti < 3600L) nprintf("%2ldm %2lds", ti / 60L, ti % 60L); else if (ti < 86400L) nprintf("%2ldh %2ldm", ti / 3600L, (ti % 3600L) / 60L); else nprintf("%2ldd %2ldh", ti / 86400L, (ti % 86400L) / 3600L); nputs(" ago) "); if (list->data.mode & MHEARD_MODE_ARP) nprintf(" ARP"); if (list->data.mode & MHEARD_MODE_FLEXNET) nprintf(" FlexNet"); if (list->data.mode & MHEARD_MODE_IP_DG) nprintf(" IP-DG"); if (list->data.mode & MHEARD_MODE_IP_VC) nprintf(" IP-VC"); if (list->data.mode & MHEARD_MODE_NETROM) nprintf(" NET/ROM"); if (list->data.mode & MHEARD_MODE_ROSE) nprintf(" Rose"); if (list->data.mode & MHEARD_MODE_SEGMENT) nprintf(" Segment"); if (list->data.mode & MHEARD_MODE_TEXNET) nprintf(" TexNet"); if (list->data.mode & MHEARD_MODE_TEXT) nprintf(" Text"); if (list->data.mode & MHEARD_MODE_PSATFT) nprintf(" PacsatFT"); if (list->data.mode & MHEARD_MODE_PSATPB) nprintf(" PacsatPB"); if (list->data.mode & MHEARD_MODE_UNKNOWN) nprintf(" Unknown"); nputs("\n"); tmp = list; list = list->next; free(tmp); } return 0; } int do_help(int argc, char **argv) { FILE *fp; char fname[256], line[256]; struct cmd *cmdp; int i = 0; if (*argv[0] == '?') { /* "?" */ node_msg("Commands:"); for (cmdp = Nodecmds; cmdp != NULL; cmdp = cmdp->next) { nprintf("%s%s", i ? ", " : "", cmdp->name); if (++i == 10) { nprintf("\n"); i = 0; } } if (i) nprintf("\n"); return 0; } if (argv[1] && strchr(argv[1], '/')) { node_msg("Invalid command %s", argv[1]); return 0; } if (*argv[0] == 'i') { /* "info" */ strcpy(fname, CONF_NODE_INFO_FILE); node_msg("%s", VERSION); } else if (!argv[1]) { /* "help" */ strcpy(fname, DATA_NODE_HELP_DIR "help.hlp"); } else { /* "help " */ strlwr(argv[1]); snprintf(fname, sizeof(fname), DATA_NODE_HELP_DIR "%s.hlp", argv[1]); fname[sizeof(fname) - 1] = 0; } if ((fp = fopen(fname, "r")) == NULL) { if (*argv[0] != 'i') node_msg("No help for command %s", argv[1] ? argv[1] : "help"); return 0; } if (*argv[0] != 'i') node_msg("Help for command %s", argv[1] ? argv[1] : "help"); while (fgets(line, 256, fp) != NULL) nputs(line); nputs("\n-- \n"); fclose(fp); return 0; } int do_host(int argc, char **argv) { struct hostent *h; struct in_addr addr; char **p; if (argc < 2) { node_msg("Usage: host |"); return 0; } if (inet_aton(argv[1], &addr) != 0) h = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET); else h = gethostbyname(argv[1]); if (h == NULL) { node_msg("%s", strherror(h_errno)); return 0; } node_msg("Host name information for %s:", argv[1]); nprintf("Hostname: %s\n", h->h_name); nputs("Aliases: "); p = h->h_aliases; while (*p != NULL) { nprintf(" %s", *p); p++; } nputs("\nAddress(es):"); p = h->h_addr_list; while (*p != NULL) { addr.s_addr = ((struct in_addr *)(*p))->s_addr; nprintf(" %s", inet_ntoa(addr)); p++; } nputs("\n"); return 0; } int do_ports(int argc, char **argv) { char *cp = NULL; node_msg("Ports:\nPort Description"); while ((cp = ax25_config_get_next(cp)) != NULL) { if (is_hidden(cp) && check_perms(PERM_HIDDEN, 0L) == -1) continue; nprintf("%-6s %s\n", cp, ax25_config_get_desc(cp)); } return 0; } int do_links(int argc, char **argv) { struct proc_ax25 *p, *list; char *cp; node_msg("AX.25 Link Status:"); if ((list = read_proc_ax25()) == NULL) { if (errno) node_perror("do_links: read_proc_ax25:", errno); return 0; } nprintf("Port Remote Local State Unack T1 Retr Rtt Snd-Q Rcv-Q\n"); for (p = list; p != NULL; p = p->next) { if (argc > 1 && strcasecmp(argv[1], "*") && strcasecmp(p->dest_addr, argv[1]) && strcasecmp(p->src_addr, argv[1])) continue; if ((argc < 2) && !strcmp(p->dest_addr, "*")) continue; if (strcmp(p->dev, "???") != 0) { cp = ax25_config_get_name(p->dev); if (is_hidden(cp) && check_perms(PERM_HIDDEN, 0L) == -1) continue; } else cp = "*"; nprintf("%-6s ", cp); nprintf("%-9s %-9s ", p->dest_addr, p->src_addr); #if 0 nprintf("%-9s", p->dest_addr); for (i = 0; i < p->ndigi; i++) { if (i == 0) nprintf(" via "); else nprintf(","); nprintf("%s", p->digi_addr[i]); } nprintf(" %-9s ", p->src_addr); #endif if (!strcmp(p->dest_addr, "*")) { nprintf("Listening\n"); continue; } switch (p->st) { case 0: nputs("Disconnected "); break; case 1: nputs("Conn pending "); break; case 2: nputs("Disc pending "); break; case 3: nputs("Connected "); break; case 4: nputs("Recovery "); break; default: nputs("Unknown "); break; } nprintf("%02d/%02d %03d/%03d %02d/%02d %-3d %-5d %-5d\n", p->vs < p->va ? p->vs - p->va + 8 : p->vs - p->va, p->window, p->t1timer, p->t1, p->n2count, p->n2, p->rtt, p->sndq, p->rcvq); } free_proc_ax25(list); return 0; } #ifdef HAVE_NETROM int do_nlinks(int argc, char **argv) { struct proc_nr *p, *list; char *cp; node_msg("NET/ROM Link Status:"); if ((list = read_proc_nr()) == NULL) { if (errno) node_perror("do_links: read_proc_nr:", errno); return 0; } nprintf("User Remote Local State My id Ur id Unack T1 N2 Snd-Q\n"); for (p = list; p != NULL; p = p->next) { cp = nr_config_get_name(p->dev); if (is_hidden(cp) && check_perms(PERM_HIDDEN, 0L) == -1) continue; nprintf("%-9s %-9s %-9s ", p->user_addr, p->dest_node, p->src_node); if (!strcmp(p->user_addr, "*")) { nprintf("Listening\n"); continue; } switch (p->st) { case 0: nputs("Disconnected "); break; case 1: nputs("Conn pending "); break; case 2: nputs("Disc pending "); break; case 3: nputs("Connected "); break; default: nputs("Unknown "); break; } nprintf("%s %s ", p->my_circuit, p->ur_circuit); nprintf("%02d/%02d %03d/%03d %d/%d %-5d\n", p->vs < p->va ? p->vs - p->va + 256 : p->vs - p->va, p->window, p->t1timer, p->t1, p->n2count, p->n2, p->sndq); } free_proc_nr(list); return 0; } int do_routes(int argc, char **argv) { struct proc_nr_neigh *p, *list; struct proc_ax25 *ap; char *cp; int link; node_msg("Routes:\nLink Port Callsign Quality Destinations Lock"); if ((list = read_proc_nr_neigh()) == NULL) { if (errno) node_perror("do_routes: read_proc_nr_neigh", errno); return 0; } for (p = list; p != NULL; p = p->next) { cp = ax25_config_get_name(p->dev); if (is_hidden(cp) && check_perms(PERM_HIDDEN, 0L) == -1) continue; if ((ap = find_link(nr_config_get_addr(NULL), p->call, p->dev)) != NULL && ap->st >= 3) link = 1; else link = 0; nprintf("%c %-6s %-9s %-7d %-12d %c\n", link == 1 ? '>' : ' ', cp, p->call, p->qual, p->cnt, p->lock == 1 ? '!' : ' '); } free_proc_nr_neigh(list); return 0; } int do_nodes(int argc, char **argv) { struct proc_nr_nodes *p, *list; struct proc_nr_neigh *np, *nlist; int i = 0; if ((list = read_proc_nr_nodes()) == NULL) { if (errno) node_perror("do_nodes: read_proc_nr_nodes", errno); else node_msg("No known nodes"); return 0; } /* "nodes" */ if (argc == 1) { node_msg("Nodes:"); for (p = list; p != NULL; p = p->next) { nprintf("%-16.16s %c", print_node(p->alias, p->call), (++i % 4) ? ' ' : '\n'); } if ((i % 4) != 0) nprintf("\n"); free_proc_nr_nodes(list); return 0; } if ((nlist = read_proc_nr_neigh()) == NULL) { node_perror("do_nodes: read_proc_nr_neigh", errno); return 0; } /* "nodes *" */ if (*argv[1] == '*') { node_msg("Nodes:"); nprintf("Node Quality Obsolescence Port Neighbour\n"); for (p = list; p != NULL; p = p->next) { nprintf("%-16.16s ", print_node(p->alias, p->call)); /* * p->n == 0 indicates a local node with no routes. */ if (p->n > 0 && (np = find_neigh(p->addr1, nlist)) != NULL) { nprintf("%-7d %-12d %-6s %s", p->qual1, p->obs1, ax25_config_get_name(np->dev), np->call); } nprintf("\n"); if (p->n > 1 && (np = find_neigh(p->addr2, nlist)) != NULL) { nprintf(" "); nprintf("%-7d %-12d %-6s %s\n", p->qual2, p->obs2, ax25_config_get_name(np->dev), np->call); } if (p->n > 2 && (np = find_neigh(p->addr3, nlist)) != NULL) { nprintf(" "); nprintf("%-7d %-12d %-6s %s\n", p->qual3, p->obs3, ax25_config_get_name(np->dev), np->call); } } free_proc_nr_nodes(list); free_proc_nr_neigh(nlist); return 0; } /* "nodes " */ p = find_node(argv[1], list); if (p != NULL && p->n == 0) { node_msg("%s is a local node", print_node(p->alias, p->call)); } else if (p != NULL) { node_msg("Routes to: %s", print_node(p->alias, p->call)); nprintf("Which Quality Obsolescence Port Neighbour\n"); if (p->n > 0 && (np = find_neigh(p->addr1, nlist)) != NULL) { nprintf("%c %-7d %-12d %-6s %s\n", p->w == 1 ? '>' : ' ', p->qual1, p->obs1, ax25_config_get_name(np->dev), np->call); } if (p->n > 1 && (np = find_neigh(p->addr2, nlist)) != NULL) { nprintf("%c %-7d %-12d %-6s %s\n", p->w == 2 ? '>' : ' ', p->qual2, p->obs2, ax25_config_get_name(np->dev), np->call); } if (p->n > 1 && (np = find_neigh(p->addr3, nlist)) != NULL) { nprintf("%c %-7d %-12d %-6s %s\n", p->w == 3 ? '>' : ' ', p->qual3, p->obs3, ax25_config_get_name(np->dev), np->call); } } else { node_msg("No such node"); } free_proc_nr_nodes(list); free_proc_nr_neigh(nlist); return 0; } #endif /* HAVE_NETROM */ /* * by Heikki Hannikainen * The following was mostly learnt from the procps package and the * gnu sh-utils (mainly uname). */ int do_status(int argc, char **argv) { int upminutes, uphours, updays; double uptime_secs; double av[3]; struct utsname name; time_t t; #ifdef HAVE_NETROM struct proc_nr_nodes *nop, *nolist; struct proc_nr_neigh *nep, *nelist; int n; #endif node_msg("Status:"); time(&t); nprintf("System time: %s", ctime(&t)); if (uname(&name) == -1) nprintf("Cannot get system name\n"); else { nprintf("Hostname: %s\n", name.nodename); nprintf("Operating system: %s %s (%s)\n", name.sysname, name.release, name.machine); } /* read and calculate the amount of uptime and format it nicely */ uptime(&uptime_secs, NULL); updays = (int) uptime_secs / (60*60*24); upminutes = (int) uptime_secs / 60; uphours = upminutes / 60; uphours = uphours % 24; upminutes = upminutes % 60; nprintf("Uptime: "); if (updays) nprintf("%d day%s, ", updays, (updays != 1) ? "s" : ""); if(uphours) nprintf("%d hour%s ", uphours, (uphours != 1) ? "s" : ""); nprintf("%d minute%s\n", upminutes, (upminutes != 1) ? "s" : ""); loadavg(&av[0], &av[1], &av[2]); nprintf("Load average: %.2f, %.2f, %.2f\n", av[0], av[1], av[2]); if (load_meminfo()) { nputs("Memory: "); nprintf("%5d KB available, %5d KB used, %5d KB free\n", meminfo("memtotal"), meminfo("memtotal") - meminfo("memfree") - meminfo("buffers") - meminfo("cached"), meminfo("memfree") + meminfo("buffers") + meminfo("cached")); nputs("Swap: "); nprintf("%5d KB available, %5d KB used, %5d KB free\n", meminfo("swaptotal"), meminfo("swaptotal") - meminfo("swapfree"), meminfo("swapfree")); } #ifdef HAVE_NETROM if ((nolist = read_proc_nr_nodes()) == NULL && errno != 0) node_perror("do_status: read_proc_nr_nodes", errno); n = 0; for (nop = nolist; nop != NULL; nop = nop->next) n++; free_proc_nr_nodes(nolist); nprintf("Nodes: %d\n", n); if ((nelist = read_proc_nr_neigh()) == NULL && errno != 0) node_perror("do_status: read_proc_nr_neigh", errno); n = 0; for (nep = nelist; nep != NULL; nep = nep->next) n++; free_proc_nr_neigh(nelist); nprintf("Routes: %d\n", n); #endif return 0; } node-0.3.2/config.c0100644000076400007640000002131007631711757012260 0ustar tpmtpm#include #include #include #include #include #include #include #include #include #include #include "node.h" long IdleTimeout = 900L; /* default to 15 mins */ long ConnTimeout = 3600L; /* default to 60 mins */ int ReConnectTo = 0; int ResolveAddrs = 0; int LogLevel = L_ERROR; int EscChar = 20; /* CTRL-T */ char *HostName = NULL; char *NodeId = "LinuxNode}"; char *NodePrompt = "\n"; char *NrPort = NULL; /* first netrom port */ static unsigned long Permissions = 0L; static unsigned long LocalNet = 0L; static unsigned long LocalMask = ~0L; static char *HiddenPorts[32] = {0}; /* * Return non-zero if `port' is a hidden port. */ int is_hidden(const char *port) { int i; for (i = 0; HiddenPorts[i] != NULL && i < 31; i++) if (!strcmp(port, HiddenPorts[i])) return 1; return 0; } /* * Return non-zero if peer is on "local" or loopback network. */ static int is_local(unsigned long peer) { return ((peer & LocalMask) == LocalNet) || ((peer & 0xff) == 127); } /* * Return non-zero if peer is on amprnet. */ static int is_ampr(unsigned long peer) { return ((peer & 0xff) == 44); } /* * Convert NOS style width to a netmask in network byte order. */ static unsigned long bits_to_mask(int bits) { return htonl(~0L << (32 - bits)); } int check_perms(int what, unsigned long peer) { if (what == PERM_TELNET) { if (is_local(peer)) { if (Permissions & PERM_TELNET_LOCAL) return 0; } else if (is_ampr(peer)) { if (Permissions & PERM_TELNET_AMPR) return 0; } else { if (Permissions & PERM_TELNET_INET) return 0; } return -1; } if ((Permissions & what) == 0) { return -1; } return 0; } /* * Read permissions file and return a password if needed or "*" if not. * If user access is denied return NULL. */ char *read_perms(struct user *up, unsigned long peer) { FILE *fp; char line[256], *argv[32], *cp, *pw; int argc, n = 0; if ((fp = fopen(CONF_NODE_PERMS_FILE, "r")) == NULL) { node_perror(CONF_NODE_PERMS_FILE, errno); return NULL; } if ((cp = strchr(up->call, '-')) != NULL) *cp = 0; pw = NULL; while (fgets(line, 256, fp) != NULL) { n++; argc = parse_args(argv, line); if (argc == 0 || *argv[0] == '#') continue; if (argc != 5) { node_msg("Configuration error"); log(L_ERROR, "Syntax error in permission file at line %d", n); break; } if (strcmp(argv[0], "*") && strcasecmp(argv[0], up->call)) continue; switch (up->ul_type) { case AF_AX25: if (!strcmp(argv[1], "*")) break; if (!strcasecmp(argv[1], "ax25")) break; continue; case AF_NETROM: if (!strcmp(argv[1], "*")) break; if (!strcasecmp(argv[1], "netrom")) break; continue; case AF_ROSE: if (!strcmp(argv[1], "*")) break; if (!strcasecmp(argv[1], "rose")) break; continue; case AF_INET: if (!strcmp(argv[1], "*")) break; if (!strcasecmp(argv[1], "local") && is_local(peer)) break; if (!strcasecmp(argv[1], "ampr") && is_ampr(peer)) break; if (!strcasecmp(argv[1], "inet") && !is_local(peer) && !is_ampr(peer)) break; continue; case AF_UNSPEC: if (!strcmp(argv[1], "*")) break; if (!strcasecmp(argv[1], "host")) break; continue; } if (up->ul_type == AF_AX25) { if (strcmp(argv[2], "*") && strcmp(argv[2], up->ul_name)) continue; } if (cp != NULL) *cp = '-'; if ((Permissions = strtoul(argv[4], NULL, 10)) != 0) pw = strdup(argv[3]); break; } fclose(fp); return pw; } static int do_alias(int argc, char **argv) { struct cmd *new; int len = 0; if (argc < 3) return -1; if ((new = calloc(1, sizeof(struct cmd))) == NULL) { node_perror("do_alias: malloc", errno); return -2; } new->name = strdup(argv[1]); while (isupper(new->name[len])) len++; /* Ok. So they can't read... */ if (len == 0) { strupr(new->name); len = strlen(new->name); } new->len = len; new->command = strdup(argv[2]); new->type = CMD_ALIAS; insert_cmd(&Nodecmds, new); return 0; } static int do_loglevel(int argc, char **argv) { if (argc < 2) return -1; LogLevel = atoi(argv[1]); return 0; } int get_escape(char *s) { int escape; char *endptr[1]; if (isdigit(*s)) { escape = strtol(s, endptr, 0); if (**endptr) return -2; else return escape; } if (strlen(s) == 1) return *s; if (strlen(s) == 2 && *s == '^') return (toupper(*++s) - 'A' + 1); if (strcasecmp(s, "off") == 0 || strcmp(s, "-1") == 0) return -1; return -2; } static int do_escapechar(int argc, char **argv) { if (argc < 2) return -1; EscChar = get_escape(argv[1]); if (EscChar < -1 || EscChar > 255) { node_msg("Configuration error"); log(L_ERROR, "do_escapechar: Invalid escape character %s", argv[1]); return -2; } return 0; } static int do_idletimeout(int argc, char **argv) { if (argc < 2) return -1; IdleTimeout = atol(argv[1]); return 0; } static int do_conntimeout(int argc, char **argv) { if (argc < 2) return -1; ConnTimeout = atol(argv[1]); return 0; } static int do_hostname(int argc, char **argv) { if (argc < 2) return -1; HostName = strdup(argv[1]); return 0; } static int do_localnet(int argc, char **argv) { char *cp; if (argc < 2) return -1; if ((cp = strchr(argv[1], '/')) != NULL) { *cp = 0; LocalMask = bits_to_mask(atoi(++cp)); } LocalNet = inet_addr(argv[1]); LocalNet &= LocalMask; return 0; } static int do_reconnect(int argc, char **argv) { if (argc < 2) return -1; if (!strcasecmp(argv[1], "on")) ReConnectTo = 1; else ReConnectTo = 0; return 0; } static int do_resolveaddrs(int argc, char **argv) { if (argc < 2) return -1; if (!strcasecmp(argv[1], "on")) ResolveAddrs = 1; else ResolveAddrs = 0; return 0; } static int do_hiddenports(int argc, char **argv) { int i; if (argc < 2) return -1; for (i = 1; i < argc && i < 31; i++) { if (ax25_config_get_dev(argv[i]) == NULL) { node_msg("Configuration error"); log(L_ERROR, "do_hiddenports: invalid port %s", argv[i]); return -2; } HiddenPorts[i - 1] = strdup(argv[i]); } HiddenPorts[i - 1] = NULL; return 0; } static int do_extcmd(int argc, char **argv) { struct cmd *new; struct passwd *pw; char buf[1024]; int i, len; if (argc < 6) return -1; if ((new = calloc(1, sizeof(struct cmd))) == NULL) { node_perror("do_extcmd: malloc", errno); return -2; } new->name = strdup(argv[1]); len = 0; while (isupper(new->name[len])) len++; /* Ok. So they can't read... */ if (len == 0) { strupr(new->name); len = strlen(new->name); } new->len = len; new->flags = atoi(argv[2]); if ((pw = getpwnam(argv[3])) == NULL) { node_msg("Configuration error"); log(L_ERROR, "do_extcmd: Unknown user %s", argv[3]); return -2; } new->uid = pw->pw_uid; new->gid = pw->pw_gid; new->path = strdup(argv[4]); len = 0; for (i = 0; argv[i + 5] != NULL; i++) len += sprintf(&buf[len], "\"%s\" ", argv[i + 5]); new->command = strdup(buf); new->type = CMD_EXTERNAL; insert_cmd(&Nodecmds, new); return 0; } static int do_nodeid(int argc, char **argv) { if (argc < 2) return -1; NodeId = strdup(argv[1]); return 0; } static int do_nodeprompt(int argc, char **argv) { if (argc < 2) return -1; NodePrompt = strdup(argv[1]); return 0; } static int do_nrport(int argc, char **argv) { if (argc < 2) return -1; NrPort = strdup(argv[1]); return 0; } int read_config(void) { struct cmd *cfg_cmds = NULL; FILE *fp; char line[256]; int ret, n = 0; add_internal_cmd(&cfg_cmds, "alias", 0, do_alias); add_internal_cmd(&cfg_cmds, "conntimeout", 0, do_conntimeout); add_internal_cmd(&cfg_cmds, "escapechar", 0, do_escapechar); add_internal_cmd(&cfg_cmds, "extcmd", 0, do_extcmd); add_internal_cmd(&cfg_cmds, "hiddenports", 0, do_hiddenports); add_internal_cmd(&cfg_cmds, "hostname", 0, do_hostname); add_internal_cmd(&cfg_cmds, "idletimeout", 0, do_idletimeout); add_internal_cmd(&cfg_cmds, "localnet", 0, do_localnet); add_internal_cmd(&cfg_cmds, "loglevel", 0, do_loglevel); add_internal_cmd(&cfg_cmds, "nodeid", 0, do_nodeid); add_internal_cmd(&cfg_cmds, "nodeprompt", 0, do_nodeprompt); add_internal_cmd(&cfg_cmds, "nrport", 0, do_nrport); add_internal_cmd(&cfg_cmds, "reconnect", 0, do_reconnect); add_internal_cmd(&cfg_cmds, "resolveaddrs", 0, do_resolveaddrs); if ((fp = fopen(CONF_NODE_FILE, "r")) == NULL) { node_perror(CONF_NODE_FILE, errno); return -1; } while (fgets(line, 256, fp) != NULL) { n++; ret = cmdparse(cfg_cmds, line); if (ret == -1) { node_msg("Configuration error"); log(L_ERROR, "Syntax error in config file at line %d: %s", n, line); } if (ret < 0) { fclose(fp); return -1; } } fclose(fp); free_cmdlist(cfg_cmds); cfg_cmds = NULL; return 0; } node-0.3.2/extcmd.c0100644000076400007640000001036307631735043012277 0ustar tpmtpm#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "node.h" #define ECMD_PIPE 1 /* Run through pipe */ #define ECMD_RECONN 2 /* */ static int norm_extcmd(struct cmd *cmdp, char **argv) { int pid; alarm(0L); pid = fork(); if (pid == -1) { /* fork error */ node_perror("norm_extcmd: fork", errno); return 0; } if (pid == 0) { /* child */ setgroups(0, NULL); setgid(cmdp->gid); setuid(cmdp->uid); execve(cmdp->path, argv, NULL); node_perror("norm_extcmd: execve", errno); exit(1); } /* parent */ waitpid(pid, NULL, 0); return 0; } static int pipe_extcmd(struct cmd *cmdp, char **argv) { ax25io *iop; int pipe_in[2], pipe_out[2]; int maxfd, pid, c; fd_set rdfdset, wrfdset; int pend_nodew = -1, pend_pipew = -1; if (pipe(pipe_in) == -1) { node_perror("pipe_extcmd: pipe_in", errno); return 0; } if (pipe(pipe_out) == -1) { node_perror("pipe_extcmd: pipe_out", errno); return 0; } signal(SIGCHLD, SIG_IGN); pid = fork(); if (pid == -1) { /* fork error */ node_perror("pipe_extcmd: fork", errno); signal(SIGCHLD, SIG_DFL); return 0; } if (pid == 0) { /* child */ /* * Redirect childs output to the pipes closing * stdin/out/err as we go. */ dup2(pipe_in[0], STDIN_FILENO); dup2(pipe_out[1], STDOUT_FILENO); dup2(pipe_out[1], STDERR_FILENO); /* Close the other ends */ close(pipe_in[1]); close(pipe_out[0]); /* Set uid, gid and supplementary groups */ setgroups(0, NULL); setgid(cmdp->gid); setuid(cmdp->uid); execve(cmdp->path, argv, NULL); perror("pipe_extcmd: execve"); exit(1); } /* parent */ close(pipe_in[0]); close(pipe_out[1]); iop = axio_init(pipe_out[0], pipe_in[1], 1024, UNSPEC_EOL); if (iop == NULL) { node_perror("pipe_extcmd: Error initializing I/O", -1); signal(SIGCHLD, SIG_DFL); kill(pid, SIGKILL); return 0; } node_set_nonblock(NodeIo, 1); node_set_nonblock(iop, 1); maxfd = NodeIo->ifd; maxfd = MAX(maxfd, NodeIo->ofd); maxfd = MAX(maxfd, iop->ifd); maxfd = MAX(maxfd, iop->ofd); maxfd++; while (1) { FD_ZERO(&rdfdset); FD_ZERO(&wrfdset); FD_SET(NodeIo->ifd, &rdfdset); FD_SET(iop->ifd, &rdfdset); if (pend_nodew != -1) FD_SET(NodeIo->ofd, &wrfdset); if (pend_pipew != -1) FD_SET(iop->ofd, &wrfdset); if (select(maxfd, &rdfdset, &wrfdset, NULL, NULL) == -1) { node_perror("pipe_extcmd: select", errno); break; } /* Try to write pending char to pipe */ if (pend_pipew != -1) { if (axio_putc(pend_pipew, iop) != -1) pend_pipew = -1; else if (errno != EAGAIN) break; } /* If nothing is pending we can try to get new data */ if (pend_pipew == -1) { while ((c = axio_getc(NodeIo)) != -1) { alarm(ConnTimeout); if (axio_putc(c, iop) == -1) { pend_pipew = c; break; } } if (errno != EAGAIN) break; } /* Try to write pending char to node connection */ if (pend_nodew != -1) { if (axio_putc(pend_nodew, NodeIo) != -1) pend_nodew = -1; else if (errno != EAGAIN) break; } /* If nothing is pending we can try to get new data */ if (pend_nodew == -1) { while ((c = axio_getc(iop)) != -1) { alarm(ConnTimeout); if (axio_putc(c, NodeIo) == -1) { pend_nodew = c; break; } } if (errno != EAGAIN) { if (errno) node_msg("%s", strerror(errno)); break; } } /* blocking flush */ if (node_flush(NodeIo) == -1) break; if (node_flush(iop) == -1) break; } node_set_nonblock(NodeIo, 0); node_set_nonblock(iop, 0); axio_end(iop); signal(SIGCHLD, SIG_DFL); kill(pid, SIGKILL); return 0; } int extcmd(struct cmd *cmdp, char **argv) { int ret; User.state = STATE_EXTCMD; User.dl_type = AF_UNSPEC; strcpy(User.dl_name, cmdp->name); strupr(User.dl_name); update_user(); if (cmdp->flags & ECMD_PIPE) ret = pipe_extcmd(cmdp, argv); else ret = norm_extcmd(cmdp, argv); if (cmdp->flags & ECMD_RECONN) node_msg("Reconnected to %s", HostName); return ret; } node-0.3.2/gateway.c0100644000076400007640000004462007631734633012463 0ustar tpmtpm#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "node.h" static void invert_ssid(char *out, char *in) { char *cp; if ((cp = strchr(in, '-')) != NULL) { *cp = 0; sprintf(out, "%s-%d", in, 15 - atoi(cp + 1)); *cp = '-'; } else { sprintf(out, "%s-15", in); } } /* * Initiate a AX.25, NET/ROM, ROSE or TCP connection to the host * specified by `address'. */ static ax25io *connect_to(char **addr, int family, int escape, int compr) { int fd; ax25io *riop; fd_set read_fdset; fd_set write_fdset; int salen; union { struct full_sockaddr_ax25 ax; struct sockaddr_rose rs; struct sockaddr_in in; } sa; struct in_addr inaddr; char call[10], path[20], *cp, *eol; int ret, retlen = sizeof(int); int paclen; struct hostent *hp; struct servent *sp; #ifdef HAVE_NETROM struct proc_nr_nodes *np; #endif /* HAVE_NETROM */ strcpy(call, User.call); /* * Fill in protocol spesific stuff. */ switch (family) { #ifdef HAVE_ROSE case AF_ROSE: if (check_perms(PERM_ROSE, 0L) == -1) { node_msg("Permission denied"); log(L_GW, "Permission denied: rose"); return NULL; } if ((fd = socket(AF_ROSE, SOCK_SEQPACKET, 0)) < 0) { node_perror("connect_to: socket", errno); return NULL; } sa.rs.srose_family = AF_ROSE; sa.rs.srose_ndigis = 0; ax25_aton_entry(call, sa.rs.srose_call.ax25_call); rose_aton(rs_config_get_addr(NULL), sa.rs.srose_addr.rose_addr); salen = sizeof(struct sockaddr_rose); if (bind(fd, (struct sockaddr *)&sa, salen) < 0) { node_perror("connect_to: bind", errno); close(fd); return NULL; } memset(path, 0, 11); memcpy(path, rs_config_get_addr(NULL), 4); salen = strlen(addr[1]); if ((salen != 6) && (salen != 10)) { node_msg("Invalid ROSE address"); return NULL; } memcpy(path + (10-salen), addr[1], salen); sprintf(User.dl_name, "%s @ %s", addr[0], path); sa.rs.srose_family = AF_ROSE; sa.rs.srose_ndigis = 0; if (ax25_aton_entry(addr[0], sa.rs.srose_call.ax25_call) < 0) { close(fd); return NULL; } if (rose_aton(path, sa.rs.srose_addr.rose_addr) < 0) { close(fd); return NULL; } if (addr[2] != NULL) { if (ax25_aton_entry(addr[2], sa.rs.srose_digi.ax25_call) < 0) { close(fd); return NULL; } sa.rs.srose_ndigis = 1; } salen = sizeof(struct sockaddr_rose); paclen = rs_config_get_paclen(NULL); eol = ROSE_EOL; break; #endif /* HAVE_ROSE */ #ifdef HAVE_NETROM case AF_NETROM: if (check_perms(PERM_NETROM, 0L) == -1) { node_msg("Permission denied"); log(L_GW, "Permission denied: netrom"); return NULL; } if ((fd = socket(AF_NETROM, SOCK_SEQPACKET, 0)) < 0) { node_perror("connect_to: socket", errno); return NULL; } /* Why on earth is this different from ax.25 ????? */ sprintf(path, "%s %s", nr_config_get_addr(NrPort), call); ax25_aton(path, &sa.ax); sa.ax.fsa_ax25.sax25_family = AF_NETROM; salen = sizeof(struct full_sockaddr_ax25); if (bind(fd, (struct sockaddr *)&sa, salen) == -1) { node_perror("connect_to: bind", errno); close(fd); return NULL; } if ((np = find_node(addr[0], NULL)) == NULL) { node_msg("No such node"); return NULL; } strcpy(User.dl_name, print_node(np->alias, np->call)); if (ax25_aton(np->call, &sa.ax) == -1) { close(fd); return NULL; } sa.ax.fsa_ax25.sax25_family = AF_NETROM; salen = sizeof(struct sockaddr_ax25); paclen = nr_config_get_paclen(NrPort); eol = NETROM_EOL; break; #endif /* HAVE_NETROM */ case AF_AX25: if (check_perms(PERM_AX25, 0L) == -1 || (is_hidden(addr[0]) && check_perms(PERM_HIDDEN, 0L) == -1)) { node_msg("Permission denied"); log(L_GW, "Permission denied: ax.25 port %s", addr[0]); return NULL; } if (ax25_config_get_addr(addr[0]) == NULL) { node_msg("Invalid port"); return NULL; } if ((fd = socket(AF_AX25, SOCK_SEQPACKET, 0)) < 0) { node_perror("connect_to: socket", errno); return NULL; } /* * Invert the SSID only if user is coming in with AX.25 * and going out on the same port he is coming in via. */ if (User.ul_type == AF_AX25 && !strcasecmp(addr[0], User.ul_name)) invert_ssid(call, User.call); sprintf(path, "%s %s", call, ax25_config_get_addr(addr[0])); ax25_aton(path, &sa.ax); sa.ax.fsa_ax25.sax25_family = AF_AX25; salen = sizeof(struct full_sockaddr_ax25); if (bind(fd, (struct sockaddr *)&sa, salen) < 0) { node_perror("connect_to: bind", errno); close(fd); return NULL; } if (ax25_aton_arglist((const char **)addr+1, &sa.ax) < 0) { close(fd); return NULL; } strcpy(User.dl_name, strupr(addr[1])); strcpy(User.dl_port, strupr(addr[0])); sa.ax.fsa_ax25.sax25_family = AF_AX25; salen = sizeof(struct full_sockaddr_ax25); paclen = ax25_config_get_paclen(addr[0]); eol = AX25_EOL; break; case AF_INET: if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { node_perror("connect_to: socket", errno); return NULL; } hp = NULL; if (ResolveAddrs && inet_aton(addr[0], &inaddr) != 0) hp = gethostbyaddr((char *)&inaddr, sizeof(inaddr), AF_INET); if (hp == NULL) hp = gethostbyname(addr[0]); if (hp == NULL) { node_msg("Unknown host %s", addr[0]); close(fd); return NULL; } sa.in.sin_family = AF_INET; sa.in.sin_addr.s_addr = ((struct in_addr *)(hp->h_addr))->s_addr; sp = NULL; if (addr[1] == NULL) { if ((sp = getservbyname("telnet", "tcp")) != NULL) sa.in.sin_port = sp->s_port; else sa.in.sin_port = htons(IPPORT_TELNET); } else { sa.in.sin_port = htons(atoi(addr[1])); if ((sp = getservbyname(addr[1], "tcp")) != NULL || (sp = getservbyport(sa.in.sin_port, "tcp")) != NULL) sa.in.sin_port = sp->s_port; } if (sa.in.sin_port == 0) { node_msg("Unknown service %s", addr[1]); close(fd); return NULL; } strncpy(User.dl_name, hp->h_name, 31); User.dl_name[31] = 0; if (sp != NULL) strcpy(User.dl_port, sp->s_name); else sprintf(User.dl_port, "%d", ntohs(sa.in.sin_port)); salen = sizeof(struct sockaddr_in); paclen = 1024; eol = INET_EOL; if (check_perms(PERM_TELNET, sa.in.sin_addr.s_addr) == -1) { node_msg("Permission denied"); log(L_GW, "Permission denied: telnet %s", print_dl(&User)); close(fd); return NULL; } break; default: node_msg("Unsupported address family: %d", family); return NULL; } /* * Ok. Now set up a non-blocking connect... */ node_set_nonblock(NodeIo, 1); if (fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK) == -1) { node_perror("connect_to: fcntl", errno); return NULL; } if (connect(fd, (struct sockaddr *)&sa, salen) == -1 && errno != EINPROGRESS) { node_perror("connect_to: connect", errno); close(fd); return NULL; } User.dl_type = family; node_msg_block("Trying %s... Type to abort", print_dl(&User)); node_flush(NodeIo); User.state = STATE_TRYING; update_user(); /* * ... and wait for it to finish (or user to abort). */ while (1) { FD_ZERO(&read_fdset); FD_ZERO(&write_fdset); FD_SET(fd, &write_fdset); FD_SET(NodeIo->ifd, &read_fdset); if (select(fd + 1, &read_fdset, &write_fdset, 0, 0) == -1) { node_perror("connect_to: select", errno); break; } if (FD_ISSET(fd, &write_fdset)) { /* See if we got connected or if this was an error */ getsockopt(fd, SOL_SOCKET, SO_ERROR, &ret, &retlen); if (ret != 0) { /* * This is STUPID !!!! * FBB interprets "Connection refused" as * success because it contains the string * "Connect"... * But I'm NOT going to toss away valuable * information (the strerror() info). * Fortunately (???) FBB is case sensitive * when examining the return string so * simply converting the strerror() message * to lower case fixes the problem. Ugly * but it _should_ work. */ cp = strdup(strerror(ret)); strlwr(cp); node_msg_block("Failure with %s: %s", print_dl(&User), cp); log(L_GW, "Failure with %s: %s", print_dl(&User), cp); free(cp); close(fd); return NULL; } break; } if (FD_ISSET(NodeIo->ifd, &read_fdset)) { if (axio_getline(NodeIo) != NULL) { node_msg_block("Aborted"); close(fd); return NULL; } else if (errno != EAGAIN) { close(fd); return NULL; } } } if (escape == -1) node_msg_block("Connected to %s", print_dl(&User)); else node_msg_block("Connected to %s (Escape: %s%c)", print_dl(&User), escape < 32 ? "CTRL-" : "", escape < 32 ? (escape + 'A' - 1) : escape); node_flush(NodeIo); log(L_GW, "Connected to %s", print_dl(&User)); if ((riop = axio_init(fd, fd, paclen, eol)) == NULL) { node_perror("connect_to: Initializing I/O failed", errno); close(fd); return NULL; } if (compr && axio_compr(riop, compr) < 0) node_msg_block("connect_to: axio_compr failed"); User.state = STATE_CONNECTED; update_user(); return riop; } int do_connect(int argc, char **argv) { ax25io *riop; int c, family, stay, escape, compress, maxfd; fd_set rdfdset, wrfdset; char *connstr = NULL; int pend_nodew = -1, pend_pipew = -1; stay = ReConnectTo; if (!strcasecmp(argv[argc - 1], "s")) { stay = 1; argv[--argc] = NULL; } else if (!strcasecmp(argv[argc - 1], "d")) { stay = 0; argv[--argc] = NULL; } compress = 0; c = argv[0][0]; #ifdef HAVE_ZLIB_H if (*argv[0] == 'z') { compress = 1; c = argv[0][1]; } #endif if (argc < 2) { if (c == 't') node_msg("Usage: telnet [] [d|s]"); else node_msg("Usage: connect [] [via ...] [d|s]"); return 0; } if (c == 't') family = AF_INET; else #ifdef HAVE_NETROM if (argc == 2) family = AF_NETROM; else #endif #ifdef HAVE_ROSE if (strspn(argv[2], "0123456789") == strlen(argv[2])) family = AF_ROSE; else #endif family = AF_AX25; if (family == AF_INET && argc > 3) connstr = argv[3]; escape = (check_perms(PERM_NOESC, 0L) == 0) ? -1 : EscChar; riop = connect_to(++argv, family, escape, compress); if (riop == NULL) { node_set_nonblock(NodeIo, 0); return 0; } if (family == AF_INET) axio_tnmode(riop, 1); if (connstr) { axio_printf(riop, "%s\n", connstr); axio_flush(riop); } /* * If eol conventions are compatible, switch to binary mode, * else switch to special gateway mode. */ if (axio_cmpeol(riop, NodeIo) == 0) { axio_eolmode(riop, EOLMODE_BINARY); axio_eolmode(NodeIo, EOLMODE_BINARY); } else { axio_eolmode(riop, EOLMODE_GW); axio_eolmode(NodeIo, EOLMODE_GW); } maxfd = NodeIo->ifd; maxfd = MAX(maxfd, NodeIo->ofd); maxfd = MAX(maxfd, riop->ifd); maxfd = MAX(maxfd, riop->ofd); maxfd++; while (1) { FD_ZERO(&rdfdset); FD_ZERO(&wrfdset); FD_SET(NodeIo->ifd, &rdfdset); FD_SET(riop->ifd, &rdfdset); if (pend_nodew != -1) FD_SET(NodeIo->ofd, &wrfdset); if (pend_pipew != -1) FD_SET(riop->ofd, &wrfdset); if (select(maxfd, &rdfdset, &wrfdset, NULL, NULL) == -1) { node_perror("do_connect: select", errno); break; } /* Try to write pending char to node connection */ if (pend_nodew != -1) { if (axio_putc(pend_nodew, NodeIo) != -1) pend_nodew = -1; else if (errno != EAGAIN) break; } /* If nothing is pending we can try to get new data */ if (pend_nodew == -1) { while ((c = axio_getc(riop)) != -1) { alarm(ConnTimeout); if (axio_putc(c, NodeIo) == -1) { pend_nodew = c; break; } } if (errno != EAGAIN) { switch (errno) { case 0: case ENOTCONN: break; case ZERR_STREAM_END: case ZERR_STREAM_ERROR: case ZERR_UNKNOWN: case ZERR_DATA_ERROR: case ZERR_MEM_ERROR: case ZERR_BUF_ERROR: node_msg_block("Decompression error"); break; default: node_msg_block("%s", strerror(errno)); break; } break; } } /* Try to write pending char to pipe */ if (pend_pipew != -1) { if (axio_putc(pend_pipew, riop) != -1) pend_pipew = -1; else if (errno != EAGAIN) break; } /* If nothing is pending we can try to get new data */ if (pend_pipew == -1) { while ((c = axio_getc(NodeIo)) != -1) { alarm(ConnTimeout); if (escape != -1 && c == escape) break; if (axio_putc(c, riop) == -1) { pend_pipew = c; break; } } if (escape != -1 && c == escape) { node_set_nonblock(NodeIo, 0); axio_eolmode(NodeIo, EOLMODE_TEXT); axio_getline(NodeIo); break; } if (errno != EAGAIN) { stay = 0; break; } } /* blocking flush */ if (node_flush(NodeIo) == -1) break; if (node_flush(riop) == -1) break; } axio_end(riop); log(L_GW, "Disconnected from %s", print_dl(&User)); if (stay) { axio_eolmode(NodeIo, EOLMODE_TEXT); node_set_nonblock(NodeIo, 0); node_msg("Reconnected to %s", HostName); } else logout("No reconnect"); return 0; } int do_finger(int argc, char **argv) { ax25io *riop; int c; char *name, *addr[3], *cp; if (argc < 2) { name = ""; addr[0] = "localhost"; } else if ((cp = strchr(argv[1], '@')) != NULL) { *cp = 0; name = argv[1]; addr[0] = ++cp; } else { name = argv[1]; addr[0] = "localhost"; } addr[1] = "finger"; addr[2] = NULL; riop = connect_to(addr, AF_INET, -1, 0); /* connect_to() leaves the sockets non-blocking */ node_set_nonblock(NodeIo, 0); node_set_nonblock(riop, 0); if (riop != NULL) { axio_printf(riop, "%s\n", name); axio_flush(riop); while ((c = axio_getc(riop)) != -1) axio_putc(c, NodeIo); axio_end(riop); node_msg("Reconnected to %s", HostName); } return 0; } /* * Returns difference of tv1 and tv2 in milliseconds. */ static long calc_rtt(struct timeval tv1, struct timeval tv2) { struct timeval tv; tv.tv_usec = tv1.tv_usec - tv2.tv_usec; tv.tv_sec = tv1.tv_sec - tv2.tv_sec; if (tv.tv_usec < 0) { tv.tv_sec -= 1L; tv.tv_usec += 1000000L; } return ((tv.tv_sec * 1000L) + (tv.tv_usec / 1000L)); } /* * Checksum routine for Internet Protocol family headers (C Version) */ static unsigned short in_cksum(unsigned char *addr, int len) { register int nleft = len; register unsigned char *w = addr; register unsigned int sum = 0; unsigned short answer = 0; /* * Our algorithm is simple, using a 32 bit accumulator (sum), we add * sequential 16 bit words to it, and at the end, fold back all the * carry bits from the top 16 bits into the lower 16 bits. */ while (nleft > 1) { sum += (*(w + 1) << 8) + *(w); w += 2; nleft -= 2; } /* mop up an odd byte, if necessary */ if (nleft == 1) { sum += *w; } /* add back carry outs from top 16 bits to low 16 bits */ sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ sum += (sum >> 16); /* add carry */ answer = ~sum; /* truncate to 16 bits */ return answer; } static int sequence = 0; static int check_icmp(char *buf, int len, struct sockaddr_in *from, long rtt) { struct iphdr *ip = (struct iphdr *) buf; struct icmphdr *icp; char *addr; /* Is it long enough? */ if (len < (ip->ihl << 2) + sizeof(struct icmphdr)) return 0; len -= ip->ihl << 2; icp = (struct icmphdr *)(buf + (ip->ihl << 2)); if (icp->type != ICMP_ECHOREPLY) return 0; if (icp->un.echo.id != (getpid() & 0xffff)) return 0; if (icp->un.echo.sequence != sequence - 1) return 0; addr = inet_ntoa(from->sin_addr); node_msg_block("%s rtt: %ldms (ttl=%d)", addr, rtt, ip->ttl); return 1; } int do_ping(int argc, char **argv) { unsigned char buf[256]; struct hostent *hp; struct sockaddr_in to, from; struct in_addr inaddr; struct protoent *prot; struct icmphdr *icp; struct timeval tv1, tv2; fd_set fdset; int fd, i, len = sizeof(struct icmphdr); int salen = sizeof(struct sockaddr); if (argc < 2) { node_msg("Usage: ping []"); return 0; } if (argc > 2) { len = atoi(argv[2]) + sizeof(struct icmphdr); if (len > 256) { node_msg("Maximum length is %d", 256 - sizeof(struct icmphdr)); return 0; } } hp = NULL; if (ResolveAddrs && inet_aton(argv[1], &inaddr) != 0) hp = gethostbyaddr((char *)&inaddr, sizeof(inaddr), AF_INET); if (hp == NULL) hp = gethostbyname(argv[1]); if (hp == NULL) { node_msg("Unknown host %s", argv[1]); return 0; } memset(&to, 0, sizeof(to)); to.sin_family = AF_INET; to.sin_addr.s_addr = ((struct in_addr *)(hp->h_addr))->s_addr; if ((prot = getprotobyname("icmp")) == NULL) { node_msg("Unknown protocol icmp"); return 0; } if ((fd = socket(AF_INET, SOCK_RAW, prot->p_proto)) == -1) { node_perror("do_ping: socket", errno); return 0; } node_msg("Pinging %s... Type to abort", inet_ntoa(to.sin_addr)); axio_flush(NodeIo); strncpy(User.dl_name, hp->h_name, 31); User.dl_name[31] = 0; User.dl_type = AF_INET; User.state = STATE_PINGING; update_user(); /* * Fill the data portion (if any) with some garbage. */ for (i = sizeof(struct icmphdr); i < len; i++) buf[i] = (i - sizeof(struct icmphdr)) & 0xff; /* * Fill in the icmp header. */ icp = (struct icmphdr *)buf; icp->type = ICMP_ECHO; icp->code = 0; icp->checksum = 0; icp->un.echo.id = getpid() & 0xffff; icp->un.echo.sequence = sequence++; /* * Calculate checksum. */ icp->checksum = in_cksum(buf, len); /* * Take the time and send the packet. */ gettimeofday(&tv1, NULL); if (sendto(fd, buf, len, 0, (struct sockaddr *)&to, salen) != len) { node_perror("do_ping: sendto", errno); close(fd); return 0; } /* * Now wait for it to come back (or user to abort). */ while (1) { FD_ZERO(&fdset); FD_SET(fd, &fdset); FD_SET(NodeIo->ifd, &fdset); if (select(fd + 1, &fdset, 0, 0, 0) == -1) { node_perror("do_ping: select", errno); break; } if (FD_ISSET(fd, &fdset)) { if ((len = recvfrom(fd, buf, 256, 0, (struct sockaddr *)&from, &salen)) == -1) { node_perror("do_ping: recvfrom", errno); break; } gettimeofday(&tv2, NULL); if (check_icmp(buf, len, &from, calc_rtt(tv2, tv1))) break; } if (FD_ISSET(NodeIo->ifd, &fdset)) { if (axio_getline(NodeIo) != NULL) { node_msg("Aborted"); break; } else if (errno != EAGAIN) { break; } } } close(fd); return 0; } node-0.3.2/COPYING0100644000076400007640000004307606724612641011711 0ustar tpmtpm GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy 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. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. node-0.3.2/node.c0100644000076400007640000001531207722207102011726 0ustar tpmtpm#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "node.h" ax25io *NodeIo = NULL; /* * Do some validity checking for callsign pointed to by `s'. */ static int check_call(const char *s) { int len = 0; int nums = 0; int ssid = 0; char *p[1]; if (s == NULL) return -1; while (*s && *s != '-') { if (!isalnum(*s)) return -1; if (isdigit(*s)) nums++; len++; s++; } if (*s == '-') { if (!isdigit(*++s)) return -1; ssid = strtol(s, p, 10); if (**p) return -1; } if (len < 4 || len > 6 || !nums || nums > 2 || ssid < 0 || ssid > 15) return -1; return 0; } static void signal_handler(int sig) { axio_eolmode(NodeIo, EOLMODE_TEXT); node_set_nonblock(NodeIo, 0); switch (sig) { case SIGALRM: nputs("\n"); node_msg("Timeout! Disconnecting..."); logout("Timeout"); case SIGTERM: nputs("\n"); node_msg("System going down! Disconnecting..."); logout("SIGTERM"); case SIGINT: logout("SIGINT"); case SIGQUIT: logout("SIGQUIT"); case SIGSEGV: nputs("\n"); node_msg("Caught SIGSEGV"); logout("SIGSEGV"); default: logout("unknown signal"); } } int main(int argc, char *argv[]) { union { struct full_sockaddr_ax25 sax; struct sockaddr_rose srose; struct sockaddr_in sin; } saddr; int slen = sizeof(saddr); char *p, buf[256], *pw; int paclen; FILE *fp; int invalid_cmds = 0; signal(SIGALRM, signal_handler); signal(SIGTERM, signal_handler); signal(SIGINT, signal_handler); signal(SIGQUIT, signal_handler); signal(SIGSEGV, signal_handler); signal(SIGPIPE, SIG_IGN); if (ax25_config_load_ports() == 0) { log(L_ERROR, "No AX.25 port data configured"); return 1; } nr_config_load_ports(); rs_config_load_ports(); if (getpeername(STDOUT_FILENO, (struct sockaddr *)&saddr, &slen) == -1) { if (errno != ENOTSOCK) { log(L_ERROR, "getpeername: %s", strerror(errno)); return 1; } User.ul_type = AF_UNSPEC; } else User.ul_type = saddr.sax.fsa_ax25.sax25_family; switch (User.ul_type) { case AF_AX25: strcpy(User.call, ax25_ntoa(&saddr.sax.fsa_ax25.sax25_call)); if (getsockname(STDOUT_FILENO, (struct sockaddr *)&saddr.sax, &slen) == -1) { log(L_ERROR, "getsockname: %s", strerror(errno)); return 1; } strcpy(User.ul_name, ax25_config_get_port(&saddr.sax.fsa_digipeater[0])); paclen = ax25_config_get_paclen(User.ul_name); p = AX25_EOL; break; case AF_NETROM: strcpy(User.call, ax25_ntoa(&saddr.sax.fsa_ax25.sax25_call)); strcpy(User.ul_name, ax25_ntoa(&saddr.sax.fsa_digipeater[0])); if (getsockname(STDOUT_FILENO, (struct sockaddr *)&saddr.sax, &slen) == -1) { log(L_ERROR, "getsockname: %s", strerror(errno)); return 1; } strcpy(User.ul_port, nr_config_get_port(&saddr.sax.fsa_ax25.sax25_call)); paclen = nr_config_get_paclen(User.ul_port); p = NETROM_EOL; break; case AF_ROSE: strcpy(User.call, ax25_ntoa(&saddr.srose.srose_call)); strcpy(User.ul_name, rose_ntoa(&saddr.srose.srose_addr)); paclen = rs_config_get_paclen(NULL); p = ROSE_EOL; break; case AF_INET: strcpy(User.ul_name, inet_ntoa(saddr.sin.sin_addr)); paclen = 1024; p = INET_EOL; break; case AF_UNSPEC: strcpy(User.ul_name, "local"); if ((p = get_call(getuid())) == NULL) { log(L_ERROR, "No uid->callsign association found", -1); return 1; } strcpy(User.call, p); paclen = 1024; p = UNSPEC_EOL; break; default: log(L_ERROR, "Unsupported address family %d", User.ul_type); return 1; } NodeIo = axio_init(STDIN_FILENO, STDOUT_FILENO, paclen, p); if (NodeIo == NULL) { log(L_ERROR, "Error initializing I/O"); return 1; } #ifdef HAVE_ZLIB_H if (argc > 1 && strcmp(argv[1], "-c") == 0) axio_compr(NodeIo, 1); #endif if (User.ul_type == AF_INET) { axio_tnmode(NodeIo, 1); axio_tn_do_linemode(NodeIo); } /* Make sure the user connection is blocking */ node_set_nonblock(NodeIo, 0); init_nodecmds(); if (read_config() == -1) { axio_end(NodeIo); return 1; } if (ResolveAddrs && User.ul_type == AF_INET) { struct hostent *hp; hp = gethostbyaddr((char *)&saddr.sin.sin_addr, sizeof(struct in_addr), AF_INET); if (hp != NULL) { strncpy(User.ul_name, hp->h_name, 31); User.ul_name[31] = 0; } else log(L_ERROR, "gethostbyaddr: %s", strherror(h_errno)); } User.state = STATE_LOGIN; login_user(); if (User.call[0] == 0) { nprintf("\n%s (%s)\n\nlogin: ", VERSION, HostName); axio_flush(NodeIo); alarm(300L); /* 5 min timeout */ if ((p = axio_getline(NodeIo)) == NULL) logout("User disconnected"); alarm(0L); strncpy(User.call, p, 9); User.call[9] = 0; strlwr(User.call); } if ((p = strstr(User.call, "-0")) != NULL) *p = 0; if (check_call(User.call) == -1) { node_msg("Invalid callsign"); log(L_LOGIN, "Invalid callsign %s @ %s", User.call, User.ul_name); logout("Invalid callsign"); } if ((pw = read_perms(&User, saddr.sin.sin_addr.s_addr)) == NULL) { node_msg("Sorry, I'm not allowed to talk to you..."); log(L_LOGIN, "Login denied for %s @ %s", User.call, User.ul_name); logout("Login denied"); } else if (strcmp(pw, "*") != 0) { nputs("Password: "); if (User.ul_type == AF_INET) { axio_tn_will_echo(NodeIo); /* axio_eolmode(NodeIo, EOLMODE_BINARY); */ } axio_flush(NodeIo); p = axio_getline(NodeIo); if (User.ul_type == AF_INET) { axio_tn_wont_echo(NodeIo); /* axio_eolmode(NodeIo, EOLMODE_TEXT); */ nputs("\n"); } if (p == NULL || strcmp(p, pw) != 0) { nputs("\n"); node_msg("Login failed"); log(L_LOGIN, "Login failed for %s @ %s", User.call, User.ul_name); logout("Login failed"); } } free(pw); ipc_open(); node_msg("Welcome to %s network node", HostName); if ((fp = fopen(CONF_NODE_MOTD_FILE, "r")) != NULL) { while (fgets(buf, 256, fp) != NULL) nputs(buf); nputs("--\n"); } put_prompt(); log(L_LOGIN, "%s @ %s logged in", User.call, User.ul_name); while (1) { axio_flush(NodeIo); User.state = STATE_IDLE; time(&User.cmdtime); update_user(); alarm(IdleTimeout); if ((p = axio_getline(NodeIo)) == NULL) { if (errno == EINTR) continue; logout("User disconnected"); } alarm(IdleTimeout); time(&User.cmdtime); update_user(); if (cmdparse(Nodecmds, p) == -1) { if (++invalid_cmds < 3) { node_msg("Unknown command. Type ? for a list"); } else { node_msg("Too many invalid commands. Disconnecting..."); logout("Too many invalid commands"); } } else invalid_cmds = 0; put_prompt(); } logout("Out of main loop !?!?!?"); } node-0.3.2/cmdparse.c0100644000076400007640000001431707722000136012601 0ustar tpmtpm#include #include #include #include #include #include #include #include "node.h" #define safe_strcpy(a, b) strncpy(a, b, sizeof(a)); a[sizeof(a)-1] = 0; static unsigned char parsechr(char *str, char **endptr) { switch (*str) { case 'n': *endptr = ++str; return '\n'; case 't': *endptr = ++str; return '\t'; case 'v': *endptr = ++str; return '\v'; case 'b': *endptr = ++str; return '\b'; case 'r': *endptr = ++str; return '\r'; case 'f': *endptr = ++str; return '\f'; case 'a': *endptr = ++str; return '\007'; case '\\': *endptr = ++str; return '\\'; case '\"': *endptr = ++str; return '\"'; case 'x': return strtoul(str, endptr, 16); case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': return strtoul(str, endptr, 8); case '\0': return 0; default: *endptr = str + 1; return *str; } /* NOTREACHED */ return 0; } static char *parsestr(char *str, char **endptr, int argc, char **argv) { static char buf[256]; char def[256]; char *p; int n, skip; time_t t; skip = 1; buf[0] = 0; def[0] = 0; if (*str == '{') { str++; if ((p = strchr(str, '}')) != NULL) { skip = p - str + 1; p = str + 1; if (*p == ':') { p++; n = min(skip - 3, sizeof(def) - 1); strncpy(def, p, n); def[n] = 0; } } } switch (*str) { case 'n': case 'N': safe_strcpy(buf, NodeId); break; case 'i': case 'I': time(&t); p = ctime(&t); strncpy(buf, p + 11, 8); buf[8] = 0; break; case 'h': case 'H': safe_strcpy(buf, HostName); if ((p = strchr(buf, '.'))) *p = 0; break; case 'f': case 'F': safe_strcpy(buf, HostName); break; case 'u': case 'U': safe_strcpy(buf, User.call); if ((p = strrchr(buf, '-'))) *p = 0; break; case 's': case 'S': safe_strcpy(buf, User.call); break; case 'p': case 'P': safe_strcpy(buf, User.ul_name); if ((p = strrchr(buf, '-'))) *p = 0; break; case 'r': case 'R': safe_strcpy(buf, User.ul_name); break; case 't': case 'T': switch (User.ul_type) { case AF_AX25: strcpy(buf, "ax25"); break; case AF_NETROM: strcpy(buf, "netrom"); break; case AF_ROSE: strcpy(buf, "rose"); break; case AF_INET: strcpy(buf, "inet"); break; case AF_UNSPEC: strcpy(buf, "host"); break; } break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': n = *str - '0'; if (argv == NULL || n > argc - 1) strcpy(buf, def); else safe_strcpy(buf, argv[n]); break; default: strcpy(buf, "%"); break; } if (isalpha(*str)) { if (isupper(*str)) strupr(buf); else strlwr(buf); } *endptr = str + skip; return buf; } char *expand_string(char *str, int argc, char **argv) { char buf[1024]; char *p, *src, *dst; int len, buflen; if (strcspn(str, "%\\\'") == strlen(str)) return strdup(str); src = str; dst = buf; len = 0; buflen = sizeof(buf) - 8; /* Slightly on the safe side... */ while (*src && (len < buflen)) { switch (*src) { case '\'': *dst++ = *src++; len++; while (*src && (*src != '\'') && (len < buflen)) { *dst++ = *src++; len++; } if (*src) { *dst++ = '\''; len++; } break; case '\\': src++; *dst++ = parsechr(src, &src); len++; break; case '%': src++; p = parsestr(src, &src, argc, argv); strncpy(dst, p, min(strlen(p), buflen - len)); dst += min(strlen(p), buflen - len); len += min(strlen(p), buflen - len); break; default: *dst++ = *src++; len++; break; } } *dst = 0; return strdup(buf); } int parse_args(char **argv, char *cmd) { int ct = 0; char quote; char *p; while (ct < 31) { while (*cmd && isspace(*cmd)) cmd++; if (*cmd == 0) break; argv[ct++] = cmd; quote = 0; p = cmd; while (*cmd) { if (quote == 0) { if (isspace(*cmd)) break; if (*cmd == '\"' || *cmd == '\'') quote = *cmd; else *p++ = *cmd; } else { if (*cmd == quote) quote = 0; else *p++ = *cmd; } cmd++; } if (*cmd == 0) { *p = 0; break; } *p = 0; *cmd++ = 0; } argv[ct] = NULL; return ct; } int cmdparse(struct cmd *list, char *cmdline) { struct cmd *cmdp; int ret, argc; char *argv[32]; char *cmdbuf = NULL; char *aliasbuf = NULL; while (*cmdline && isspace(*cmdline)) cmdline++; if (*cmdline == 0 || *cmdline == '#') return 0; cmdbuf = expand_string(cmdline, 0, NULL); if ((argc = parse_args(argv, cmdbuf)) == 0) return 0; for (cmdp = list; cmdp != NULL; cmdp = cmdp->next) { if (strlen(argv[0]) < cmdp->len || strlen(argv[0]) > strlen(cmdp->name)) continue; if (strncasecmp(cmdp->name, argv[0], strlen(argv[0])) == 0) break; } if (cmdp == NULL) { free(cmdbuf); return -1; } strlwr(argv[0]); switch (cmdp->type) { case CMD_INTERNAL: ret = (*cmdp->function)(argc, argv); break; case CMD_ALIAS: aliasbuf = expand_string(cmdp->command, argc, argv); ret = cmdparse(list, aliasbuf); break; case CMD_EXTERNAL: aliasbuf = expand_string(cmdp->command, argc, argv); argc = parse_args(argv, aliasbuf); ret = extcmd(cmdp, argv); break; default: ret = -1; break; } free(cmdbuf); free(aliasbuf); return ret; } void insert_cmd(struct cmd **list, struct cmd *new) { struct cmd *tmp, *p; if (*list == NULL || strcasecmp(new->name, (*list)->name) < 0) { tmp = *list; *list = new; new->next = tmp; } else { for (p = *list; p->next != NULL; p = p->next) if (strcasecmp(new->name, p->next->name) < 0) break; tmp = p->next; p->next = new; new->next = tmp; } } int add_internal_cmd(struct cmd **list, char *name, int len, int (*function) (int argc, char **argv)) { struct cmd *new; if ((new = calloc(1, sizeof(struct cmd))) == NULL) { node_perror("add_internal_cmd: calloc", errno); return -1; } new->name = strdup(name); new->len = len ? len : strlen(name); new->type = CMD_INTERNAL; new->function = function; insert_cmd(list, new); return 0; } void free_cmdlist(struct cmd *list) { struct cmd *tmp; while (list != NULL) { free(list->name); free(list->command); free(list->path); tmp = list; list = list->next; free(tmp); } } node-0.3.2/node.h0100644000076400007640000001017507721670113011742 0ustar tpmtpm#include #include #include "config.h" #include #define VERSION "LinuxNode v0.3.2" #define STATE_IDLE 0 #define STATE_TRYING 1 #define STATE_CONNECTED 2 #define STATE_PINGING 3 #define STATE_EXTCMD 4 #define STATE_LOGIN 5 #define L_NONE 0 #define L_ERROR 1 #define L_LOGIN 2 #define L_GW 3 #define L_DEBUG 4 #define PERM_LOGIN 1 /* Permit login */ #define PERM_AX25 2 /* AX.25 gatewaying */ #define PERM_NETROM 4 /* NETROM gatewaying */ #define PERM_TELNET_LOCAL 8 /* Telnet to "local" hosts */ #define PERM_TELNET_AMPR 16 /* Telnet to 44.xx.xx.xx hosts */ #define PERM_TELNET_INET 32 /* Telnet to other hosts */ #define PERM_HIDDEN 64 /* Use hidden ports */ #define PERM_ROSE 128 /* ROSE gatewaying */ #define PERM_NOESC 256 /* No escape character */ #define PERM_TELNET (PERM_TELNET_LOCAL & PERM_TELNET_AMPR & PERM_TELNET_INET) #ifndef MAX #define MAX(a,b) ((a) > (b) ? (a) : (b)) #endif #ifndef MIN #define MIN(a,b) ((a) < (b) ? (a) : (b)) #endif struct user { pid_t pid; key_t ipc_key; time_t logintime; time_t cmdtime; unsigned char state; char call[10]; unsigned short ul_type; unsigned short dl_type; char ul_name[32]; char dl_name[32]; char ul_port[32]; char dl_port[32]; char unused[92]; }; extern struct user User; extern ax25io *NodeIo; /* our own stdin and stdout */ extern long IdleTimeout; extern long ConnTimeout; extern int ReConnectTo; extern int ResolveAddrs; extern int LogLevel; extern int EscChar; extern char *HostName; extern char *NodeId; extern char *NodePrompt; extern char *NrPort; #define CMD_INTERNAL 1 #define CMD_ALIAS 2 #define CMD_EXTERNAL 3 struct cmd { char *name; int len; int type; int (*function) (int argc, char **argv); char *command; int flags; int uid; int gid; char *path; struct cmd *next; }; extern struct cmd *Nodecmds; #define min(a,b) ((a) < (b) ? (a) : (b)) #define max(a,b) ((a) > (b) ? (a) : (b)) /* in cmdparse.c */ void free_cmdlist(struct cmd *list); extern void insert_cmd(struct cmd **list, struct cmd *new); extern int add_internal_cmd(struct cmd **list, char *name, int len, int (*function) (int argc, char **argv)); extern char *expand_string(char *str, int argc, char **argv); extern int parse_args(char **argv, char *cmd); extern int cmdparse(struct cmd *cmdp, char *cmdline); /* in util.c */ extern void node_set_nonblock(ax25io *io, int flag); extern int node_flush(ax25io *io); extern int nputs(const char *); extern int nprintf(const char *, ...); extern int node_msg(const char *, ...); extern int node_msg_block(const char *, ...); extern void node_perror(char *, int); extern char *print_node(const char *, const char *); extern char *print_dl(struct user *); extern int put_prompt(void); extern void log(int, const char *, ...); extern char *strherror(int); /* in user.c */ extern void login_user(void); extern void logout_user(void); extern void update_user(void); extern int do_users(int argc, char **argv); extern int user_list(int verbose); extern int user_count(void); /* in config.c */ extern int is_hidden(const char *port); extern int check_perms(int what, unsigned long peer); extern char *read_perms(struct user *up, unsigned long peer); extern int read_config(void); extern int get_escape(char *s); /* in command.c */ void init_nodecmds(void); extern void logout(char *reason); extern int do_bye(int argc, char **argv); extern int do_escape(int argc, char **argv); extern int do_mheard(int argc, char **argv); extern int do_help(int argc, char **argv); extern int do_host(int argc, char **argv); extern int do_ports(int argc, char **argv); extern int do_links(int argc, char **argv); extern int do_nlinks(int argc, char **argv); extern int do_routes(int argc, char **argv); extern int do_nodes(int argc, char **argv); extern int do_status(int argc, char **argv); /* in gateway.c */ extern int do_connect(int argc, char **argv); extern int do_finger(int argc, char **argv); extern int do_ping(int argc, char **argv); /* in ipc.c */ extern int ipc_open(void); extern int ipc_close(void); extern int do_talk(int argc, char **argv); /* in extcmd.c */ extern int extcmd(struct cmd *cmdp, char **argv); node-0.3.2/nodeusers.c0100644000076400007640000000332407631711733013021 0ustar tpmtpm#include #include #include #include #include #include #include #include #include #include #include #include #include "node.h" /* * These are needed for util.c to link */ int LogLevel = L_NONE; char *NodeId = "Nodeusers:"; char *NodePrompt = "\n"; char *expand_string(char *str, int argc, char **argv) { return str; } void logout(char *s) { exit(1); } ax25io *NodeIo = NULL; static int logging = 0; static void pipe_handler(int sig) { if (logging) syslog(LOG_ERR, "received SIGPIPE"); axio_end(NodeIo); exit(1); } int main(int argc, char **argv) { int n, len = 1024; char *cp = UNSPEC_EOL; int inet = 0; while ((n = getopt(argc, argv, "ail")) != -1) { switch (n) { case 'a': cp = AX25_EOL; len = 128; break; case 'i': cp = INET_EOL; inet = 1; break; case 'l': logging = 1; break; default: fprintf(stderr, "usage: nodeusers [-a] [-i] [-l]\r\n"); return 1; } } if (logging) openlog("nodeusers", LOG_PID, LOG_DAEMON); signal(SIGPIPE, pipe_handler); NodeIo = axio_init(STDIN_FILENO, STDOUT_FILENO, len, cp); if (NodeIo == NULL) { fprintf(stderr, "nodeusers: axio_init failed\r\n"); return 1; } if (inet && axio_getline(NodeIo) == NULL) { if (logging) syslog(LOG_ERR, "axio_getline: %m"); axio_end(NodeIo); return 1; } n = user_count(); nprintf("\n%s - %d user%s.\n\n", VERSION, n, n == 1 ? "" : "s"); user_list(1); if (n > 0) nputs("\n"); if (axio_flush(NodeIo) == -1 && logging) syslog(LOG_ERR, "axio_flush: %m"); axio_end(NodeIo); usleep(500000L); closelog(); return 0; } node-0.3.2/sysinfo.c0100644000076400007640000000410307631724067012504 0ustar tpmtpm#include #include #include #include #include #include #include "node.h" #include "sysinfo.h" /* * This code is heavily modified from the procps package. */ #define UPTIME_FILE "/proc/uptime" #define LOADAVG_FILE "/proc/loadavg" #define MEMINFO_FILE "/proc/meminfo" static char buf[4096]; /* This macro opens FILE only if necessary and seeks to 0 so that successive calls to the functions are more efficient. It also reads the current contents of the file into the global buf. */ #define FILE_TO_BUF(FILE) { \ static int n, fd = -1; \ if (fd == -1 && (fd = open(FILE, O_RDONLY)) == -1) { \ node_perror(FILE, errno); \ close(fd); \ return 0; \ } \ lseek(fd, 0L, SEEK_SET); \ if ((n = read(fd, buf, sizeof buf - 1)) < 0) { \ node_perror(FILE, errno); \ close(fd); \ fd = -1; \ return 0; \ } \ buf[n] = '\0'; \ } #define SET_IF_DESIRED(x,y) if (x) *(x) = (y) /* evals 'x' twice */ int uptime(double *uptime_secs, double *idle_secs) { double up=0, idle=0; FILE_TO_BUF(UPTIME_FILE) if (sscanf(buf, "%lf %lf", &up, &idle) < 2) { node_msg("Bad data in " UPTIME_FILE ); return 0; } SET_IF_DESIRED(uptime_secs, up); SET_IF_DESIRED(idle_secs, idle); return up; /* assume never be zero seconds in practice */ } int loadavg(double *av1, double *av5, double *av15) { double avg_1=0, avg_5=0, avg_15=0; FILE_TO_BUF(LOADAVG_FILE) if (sscanf(buf, "%lf %lf %lf", &avg_1, &avg_5, &avg_15) < 3) { node_msg("Bad data in " LOADAVG_FILE ); return 0; } SET_IF_DESIRED(av1, avg_1); SET_IF_DESIRED(av5, avg_5); SET_IF_DESIRED(av15, avg_15); return 1; } int load_meminfo(void) { FILE_TO_BUF(MEMINFO_FILE) return 1; } int meminfo(const char *s) { char *cp; int len; len = strlen(s); cp = buf; while (1) { if (strncasecmp(cp, s, len) == 0) { cp += len; if (*cp == ':') return atoi(++cp); } if ((cp = strchr(cp, '\n')) == NULL) break; cp++; } return -1; } node-0.3.2/sysinfo.h0100644000076400007640000000027206414236572012511 0ustar tpmtpmextern int loadavg(double *av1, double *av5, double *av15); extern int uptime (double *uptime_secs, double *idle_secs); extern int load_meminfo(void); extern int meminfo(const char *s); node-0.3.2/user.c0100644000076400007640000001267406707433513012000 0ustar tpmtpm#include #include #include #include #include #include #include #include #include #include #include #include "node.h" struct user User = {0}; static long CallerPos = -1L; void login_user(void) { FILE *f; struct user u; long pos = 0L; long free = -1L; struct stat statbuf; time(&User.logintime); User.cmdtime = User.logintime; User.pid = getpid(); if ((f = fopen(DATA_NODE_LOGIN_FILE, "r+")) == NULL) { node_perror("login_user: fopen: " DATA_NODE_LOGIN_FILE, errno); return; } if (stat(DATA_NODE_LOGIN_FILE, &statbuf) == -1) { node_perror("login_user: stat: " DATA_NODE_LOGIN_FILE, errno); fclose(f); return; } if (statbuf.st_size % sizeof(struct user) != 0) { node_msg("%s: Incorrect size", DATA_NODE_LOGIN_FILE); log(L_ERROR, "%s: Incorrect size", DATA_NODE_LOGIN_FILE); fclose(f); return; } if (flock(fileno(f), LOCK_EX) == -1) { node_perror("login_user: flock", errno); fclose(f); return; } while (fread(&u, sizeof(u), 1, f) == 1) { if (u.pid == -1 || (kill(u.pid, 0) == -1 && errno == ESRCH)) { free = pos; break; } pos += sizeof(u); } if (free != -1L && fseek(f, free, 0L) == -1) { node_perror("login_user: fseek", errno); flock(fileno(f), LOCK_UN); fclose(f); return; } fflush(f); CallerPos = ftell(f); fwrite(&User, sizeof(User), 1, f); fflush(f); flock(fileno(f), LOCK_UN); fclose(f); } void logout_user(void) { FILE *f; if (CallerPos == -1L) return; if ((f = fopen(DATA_NODE_LOGIN_FILE, "r+")) == NULL) { node_perror(DATA_NODE_LOGIN_FILE, errno); return; } if (fseek(f, CallerPos, 0) == -1) { node_perror("logout_user: fseek", errno); fclose(f); return; } User.pid = -1; fwrite(&User, sizeof(User), 1, f); fclose(f); } void update_user(void) { FILE *f; if (CallerPos == -1L) return; if ((f = fopen(DATA_NODE_LOGIN_FILE, "r+")) == NULL) { node_perror(DATA_NODE_LOGIN_FILE, errno); return; } if (fseek(f, CallerPos, 0) == -1) { node_perror("update_user: fseek", errno); fclose(f); return; } fwrite(&User, sizeof(User), 1, f); fclose(f); } int do_users(int argc, char **argv) { node_msg("Users:"); if (user_list(0) == -1) node_perror(DATA_NODE_LOGIN_FILE, errno); return 0; } int user_list(int verbose) { FILE *f; struct user u; struct tm *tp; struct proc_nr_nodes *np; char buf[80]; char *cp; long l; if ((f = fopen(DATA_NODE_LOGIN_FILE, "r")) == NULL) return -1; while (fread(&u, sizeof(u), 1, f) == 1) { if (u.pid == -1 || (kill(u.pid, 0) == -1 && errno == ESRCH)) continue; switch (u.ul_type) { case AF_AX25: sprintf(buf, "Uplink (%.9s on port %.10s)", u.call, u.ul_name); break; case AF_NETROM: if ((np = find_node(u.ul_name, NULL)) != NULL) { sprintf(buf, "Circuit (%.9s %.18s)", u.call, print_node(np->alias, np->call)); } else { sprintf(buf, "Circuit (%.9s %.18s)", u.call, u.ul_name); } break; case AF_ROSE: sprintf(buf, "ROSE (%.9s %.18s)", u.call, u.ul_name); break; case AF_INET: if (!verbose && (cp = strstr(u.ul_name, ".ampr.org")) != NULL) *cp = 0; sprintf(buf, "Telnet (%.9s @ %.16s)", u.call, u.ul_name); break; case AF_UNSPEC: sprintf(buf, "Host (%.9s on local)", u.call); break; default: /* something strange... */ sprintf(buf, "?????? (%.9s %.18s)", u.call, u.ul_name); break; } nprintf("%-37.37s ", buf); switch (u.state) { case STATE_LOGIN: nputs(" -> Logging in"); break; case STATE_IDLE: time(&l); l -= u.cmdtime; tp = gmtime(&l); nprintf(" -> Idle (%d:%02d:%02d:%02d)", tp->tm_yday, tp->tm_hour, tp->tm_min, tp->tm_sec); break; case STATE_TRYING: switch (u.dl_type) { case AF_AX25: nprintf(" -> Trying (%s on port %s)", u.dl_name, u.dl_port); break; case AF_NETROM: nprintf(" -> Trying (%s)", u.dl_name); break; case AF_ROSE: nprintf(" -> Trying (%s)", u.dl_name); break; case AF_INET: if (!verbose && (cp = strstr(u.dl_name, ".ampr.org")) != NULL) *cp = 0; nprintf(" -> Trying (%s:%s)", u.dl_name, u.dl_port); break; default: nputs(" -> ???"); break; } break; case STATE_CONNECTED: switch (u.dl_type) { case AF_AX25: nprintf("<--> Downlink (%s on port %s)", u.dl_name, u.dl_port); break; case AF_NETROM: nprintf("<--> Circuit (%s)", u.dl_name); break; case AF_ROSE: nprintf("<--> ROSE (%s)", u.dl_name); break; case AF_INET: if (!verbose && (cp = strstr(u.dl_name, ".ampr.org")) != NULL) *cp = 0; nprintf("<--> Telnet (%s:%s)", u.dl_name, u.dl_port); break; default: nprintf("<--> ???"); break; } break; case STATE_PINGING: if (!verbose && (cp = strstr(u.dl_name, ".ampr.org")) != NULL) *cp = 0; nprintf("<--> Pinging (%s)", u.dl_name); break; case STATE_EXTCMD: nprintf("<--> Extcmd (%s)", u.dl_name); break; default: /* something strange... */ nputs(" -> ??????"); break; } nputs("\n"); } fclose(f); return 0; } int user_count(void) { FILE *f; struct user u; int cnt = 0; if ((f = fopen(DATA_NODE_LOGIN_FILE, "r")) == NULL) { node_perror(DATA_NODE_LOGIN_FILE, errno); return 0; } while (fread(&u, sizeof(u), 1, f) == 1) if (u.pid != -1 && (kill(u.pid, 0) != -1 || errno != ESRCH)) cnt++; fclose(f); return cnt; } node-0.3.2/util.c0100644000076400007640000001075707721670515012001 0ustar tpmtpm#include #include #include #include #include #include #include #include #include #include #include "node.h" static char buf[4096]; static char fmt[256]; /* ---------------------------------------------------------------------- */ static int set_nonblock(int fd, int flag) { long oldflags = fcntl(fd, F_GETFL); long newflags; if (flag) newflags = oldflags | O_NONBLOCK; else newflags = oldflags & ~((long) O_NONBLOCK); // fprintf(stderr, "fd=%d flag=%d 0%lo -> 0%lo\n", fd, flag, oldflags, newflags); if (fcntl(fd, F_SETFL, newflags) == -1) { log(LOG_ERR, "node_set_nonblock: fnctl(%lo,%lo): %m", fd, newflags); logout("fcntl failed"); } return oldflags; } static int set_fd_flags(int fd, int flags) { if (fcntl(fd, F_SETFL, flags) == -1) { log(LOG_ERR, "node_set_fd_flags: fnctl(%d,&d): %m", fd, flags); logout("fcntl failed"); } return 0; } /* ---------------------------------------------------------------------- */ void node_set_nonblock(ax25io *io, int flag) { if (io == NULL) return; if (io->ifd != io->ofd) set_nonblock(io->ifd, flag); set_nonblock(io->ofd, flag); } int node_flush(ax25io *io) { int flags, ret; /* make it block */ flags = set_nonblock(NodeIo->ofd, 0); ret = axio_flush(io); /* return original state */ set_fd_flags(NodeIo->ofd, flags); return ret; } /* ---------------------------------------------------------------------- */ int nputs(const char *str) { return axio_puts(str, NodeIo); } int nprintf(const char *format, ...) { va_list args; va_start(args, format); vsprintf(buf, format, args); va_end(args); return nputs(buf); } int node_msg(const char *format, ...) { va_list args; snprintf(fmt, sizeof(fmt), "%s %s\n", NodeId, format); va_start(args, format); vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); return nputs(buf); } int node_msg_block(const char *format, ...) { va_list args; int flags, err; /* make it block */ flags = set_nonblock(NodeIo->ofd, 0); snprintf(fmt, sizeof(fmt), "%s %s\n", NodeId, format); va_start(args, format); vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); err = nputs(buf); /* return original state */ set_fd_flags(NodeIo->ofd, flags); return err; } void node_perror(char *str, int err) { int oldmode, flags; buf[0] = 0; if (str) strcpy(buf, str); if (str && err != -1) strcat(buf, ": "); if (err != -1) strcat(buf, strerror(err)); /* make it block */ flags = set_nonblock(NodeIo->ofd, 0); /* set text mode */ oldmode = axio_eolmode(NodeIo, EOLMODE_TEXT); nputs(NodeId); nputs(" "); nputs(buf); nputs("\n"); /* return original end-of-line mode */ axio_eolmode(NodeIo, oldmode); axio_flush(NodeIo); /* return original blocking state */ set_fd_flags(NodeIo->ofd, flags); log(L_ERROR, buf); } char *print_node(const char *alias, const char *call) { static char node[17]; sprintf(node, "%s%s%s", !strcmp(alias, "*") ? "" : alias, !strcmp(alias, "*") ? "" : ":", call); return node; } char *print_dl(struct user *u) { static char buf[64]; switch (u->dl_type) { case AF_AX25: sprintf(buf, "%s on port %s", u->dl_name, u->dl_port); break; case AF_NETROM: case AF_ROSE: sprintf(buf, "%s", u->dl_name); break; case AF_INET: sprintf(buf, "%s:%s", u->dl_name, u->dl_port); break; } return buf; } int put_prompt(void) { int err; char *p; if (strchr(NodePrompt, '%') == NULL) err = nputs(NodePrompt); else { p = expand_string(NodePrompt, 0, NULL); err = nputs(p); free(p); } return err; } void log(int loglevel, const char *fmt, ...) { static int opened = 0; va_list args; int pri; if (LogLevel < loglevel) return; if (!opened) { openlog("node", LOG_PID, LOG_LOCAL7); opened = 1; } switch (loglevel) { case L_ERROR: pri = LOG_ERR; break; case L_LOGIN: pri = LOG_NOTICE; break; case L_GW: pri = LOG_INFO; break; default: pri = LOG_INFO; break; } va_start(args, fmt); vsnprintf(buf, sizeof(buf), fmt, args); buf[sizeof(buf) - 1] = 0; va_end(args); syslog(pri, "%s", buf); } char *strherror(int err) { static char buf[64]; switch (err) { case HOST_NOT_FOUND: strcpy(buf, "Unknown host"); break; case TRY_AGAIN: strcpy(buf, "Temporary name server error"); break; case NO_RECOVERY: strcpy(buf, "Non-recoverable name server error"); break; case NO_ADDRESS: strcpy(buf, "No address"); break; default: strcpy(buf, "Unknown error"); break; } return buf; } node-0.3.2/etc/0040755000076400007640000000000006740167127011424 5ustar tpmtpmnode-0.3.2/etc/loggedin0100644000076400007640000000000006266456343013126 0ustar tpmtpmnode-0.3.2/etc/node.conf0100644000076400007640000000312506740167036013215 0ustar tpmtpm# /etc/ax25/node.conf - LinuxNode configuration file # # see node.conf(5) # Idle timeout (seconds). # IdleTimeout 900 # Timeout when gatewaying (seconds). # ConnTimeout 14400 # Visible hostname. Will be shown at telnet login. # HostName oh2bns.ampr.org # Node ID. # NodeId #BNSNR:OH2BNS-10} #NodeId \033[01;31m***\033[0m # ReConnect flag. # ReConnect on # "Local" network. # LocalNet 44.139.0.0/16 # Command aliases. # Alias CAllbook 'telnet %{2:jazz.oh7lzb.ampr.org} 1235 %1' Alias CONVers 'telnet %{2:hydra.carleton.ca} 3600 "/n %u %{1:32768}\n/w *"' Alias CLuster 'c hkiclh' # Hidden ports. # #HiddenPorts 2 # External commands # # Flags: 1 Run command through pipe # 2 Reconnect prompt # ExtCmd PMS 3 root /usr/sbin/pms pms -u \%U -o OH2BNS #ExtCmd PS 1 nobody /bin/ps ps ax #ExtCmd TPM 1 nobody /usr/bin/finger finger tpm #ExtCmd Vpaiva 1 nobody /home/tpm/bin/vpaiva vpaiva #ExtCmd NOde 0 root /usr/local/bin/node node ExtCmd ECho 1 nobody /bin/echo echo \%U\%u \%S\%s \%P\%p \%R\%r \%T\%t \%\% \%0 \%1 \%2 \%3 \%4 \%5 \%6 \%7 \%8 \%9 #ExtCmd ECho 1 nobody /bin/echo echo foo\%{1:***}bar \%{U}\%{0:foo}\%{1:bar}\%{2:huu}\%{3:haa} ExtCmd TIme 1 nobody /bin/echo echo %N Node session started at %I, current time is \%I. # Netrom port name. This port is used for outgoing netrom connects. # NrPort netrom # Logging level # LogLevel 3 # The escape character (CTRL-T) # EscapeChar ^T # Resolve ip numbers to addresses? # ResolveAddrs off # Node prompt. # NodePrompt "\n" #NodePrompt "\n%s@%h \%i> " #NodePrompt "\033[36m%U\033[0m de \033[01;35m#LNODE\033[0m:\033[01;31mOH2BNS-10\033[0m> " node-0.3.2/etc/node.perms0100644000076400007640000000064306330424573013415 0ustar tpmtpm# /etc/ax25/node.perms - LinuxNode permissions file # # see node.perms(5) # user type port passwd perms # User oh2bns can login without password from anywhere else but 'inet'. # oh2bns inet * qwerty 95 oh2bns * * * 95 # OH2RBI is a bbs so it needs escape disabled. # oh2rbi * * * 287 # Default permissions per connection type. # * ax25 * * 31 * netrom * * 31 * local * * 31 * ampr * * 31 * inet * * 0 * host * * 31 node-0.3.2/etc/help/0040755000076400007640000000000006425201307012341 5ustar tpmtpmnode-0.3.2/etc/help/bye.hlp0100644000076400007640000000011006266456343013631 0ustar tpmtpm USAGE bye DESCRIPTION Disconnects you from this node. node-0.3.2/etc/help/connect.hlp0100644000076400007640000000174606266456343014523 0ustar tpmtpm USAGE connect [via ...] [s|d] For AX.25 connect [s|d] For NET/ROM connect
[] [d|s] For ROSE DESCRIPTION Initiates an AX.25, NET/ROM or ROSE connection to a remote host. If more than two parameters are entered and the second parameter is ten charachers in length then it is interpreted as a ROSE connection, otherwise the first parameter is interpreted as a port name and AX.25 is used to make the connection via that port. If only one parameter is given the connection is made using NET/ROM. If a single `s' is entered as the last parameter, then when the remote host disconnects you will be returned to this node. If a single `d' is entered as the last parameter, you will be disconnected from this node too. Default behaviour (neither `s' nor `d' entered) depends on sysop configuration. node-0.3.2/etc/help/help.hlp0100644000076400007640000000036206266456343014013 0ustar tpmtpm USAGE help [] DESCRIPTION Gives help for the specified command or this text if no command is specified. Commands can not be abbreviated. Use the "?" command to retrieve a list of available commands. node-0.3.2/etc/help/info.hlp0100644000076400007640000000033106300553463014000 0ustar tpmtpm USAGE info DESCRIPTION Displays the version information and the contents of the /etc/ax25/node.info file, which describes those aspects of the system that the sysop likes to brag about. node-0.3.2/etc/help/mheard.hlp0100644000076400007640000000026006266456343014320 0ustar tpmtpm USAGE mheard DESCRIPTION Gives a list of heard AX.25 stations on the specified port. Use the "Ports" command to get a list of available ports. node-0.3.2/etc/help/finger.hlp0100644000076400007640000000057006266456343014336 0ustar tpmtpm USAGE finger [][@] DESCRIPTION Retrieves information about users of a system. If the user name is omitted, shows the users currently logged on the host. If the hostname is omitted, defaults to the local host. EXAMPLES finger @soul.oh7rba.ampr.org finger oh7lzb@soul.oh7rba.ampr.org finger oh7lzb node-0.3.2/etc/help/links.hlp0100644000076400007640000000053706270751314014176 0ustar tpmtpm USAGE links [* | ] DESCRIPTION Gives a list of active AX.25 connections to and from the local host. With an asterisk (*) as an argument shows also AX.25 sockets in listening state. With a callsign as an argument gives a list of all connections with either source or destination callsign . node-0.3.2/etc/help/nodes.hlp0100644000076400007640000000121706266456343014173 0ustar tpmtpm USAGE nodes [*|] DESCRIPTION Shows the NET/ROM node table of the local host. The nodes on this list can be reached using the Connect command without knowing the actual network path used (assuming the network is OK). The optional parameter * toggles verbose mode, showing the Obsolescence counter, relative path quality and the port and neighbour node used to reach each node. You can also specify a node callsign to get the verbose information for a single node. In that case a "which" field that tells what route the kernel will use to reach the node is shown. node-0.3.2/etc/help/ping.hlp0100644000076400007640000000073506266456343014024 0ustar tpmtpm USAGE ping [] DESCRIPTION Checks if a host can be reached trough the network by sending an ICMP Echo Request packet to the host and waiting for it to reply. If a reply is received the round-trip-time (RTT) between the local and remote hosts is shown. If an optional length is specified the data portion of the packet is filled with length number of bytes. EXAMPLE ping soul.oh7rba.ampr.org node-0.3.2/etc/help/ports.hlp0100644000076400007640000000064106266456343014232 0ustar tpmtpm USAGE ports DESCRIPTION Shows the available AX.25 ports. Shown are the port name, the speed of the port (in bits/sec) and a short description for the port. The port name is used when using the Connect command to connect to an user or service not running NET/ROM (eg. not visible in the Nodes list). The port name is also visible in the Route and Link lists. node-0.3.2/etc/help/routes.hlp0100644000076400007640000000121606266456343014403 0ustar tpmtpm USAGE routes DESCRIPTION Shows the NET/ROM route table of the local host (eg. the nodes which the local node directly talks with). These nodes are used to reach the other nodes on the node table. Fields shown are: Link - Is there an AX.25 connection active to this node Port - Which port is this route on Callsign - The callsign of the neighbour node Quality - A relative quality for the path (0-255) Destinations - Number of other nodes reached via this route Lock - Is the quality of this route locked by the operator node-0.3.2/etc/help/telnet.hlp0100644000076400007640000000174406266456343014363 0ustar tpmtpm USAGE telnet [] [s|d] DESCRIPTION Initiates a telnet session to a remote host using TCP/IP. You might not be able to connect to a given host due to the local operator's policy of using this node, or simply because the host is unreachable due to a network failure. You can use the ping command to check if a host is reachable. By default, the telnet command connects to the TCP port 23 (allocated for telnet). You can specify another TCP port or a TCP port name. If a single `s' is entered as the last parameter, then when the remote host disconnects you will be returned to this node. If a single `d' is entered as the last parameter, you will be disconnected from this node too. Default behaviour (neither `s' nor `d' entered) depends on sysop configuration. EXAMPLES telnet soul.oh7rba.ampr.org telnet soul.oh7rba 7 telnet 44.139.39.8 echo node-0.3.2/etc/help/users.hlp0100644000076400007640000000027706266456343014231 0ustar tpmtpm USAGE users DESCRIPTION Shows a list of users currently connected to the local node, where the users are coming from, and what are they doing at the moment. node-0.3.2/etc/help/status.hlp0100644000076400007640000000102306266456343014401 0ustar tpmtpm USAGE status DESCRIPTION Returns information about the status of the Linux system which this LinuxNode runs on. All information is taken directly from the operating system. The "load average" values indicate the average amount of processes waiting for processor time during the last 1, 5 and 15 minutes. Load average of 1.0 would mean that the all of the processor time is used by the processes, and all processes still get all of the time they can use. node-0.3.2/etc/help/host.hlp0100644000076400007640000000061706266456343014043 0ustar tpmtpm USAGE host | DESCRIPTION Tells information about an Internet host. The host can be identified using a host name (for example, zone.oh7rba.ampr.org) or an IP address (for example, 44.139.39.6). Returns the host name, IP addresses and known aliases for the host. The information is gathered from the DNS (domain name service). node-0.3.2/etc/help/talk.hlp0100644000076400007640000000075406272432644014016 0ustar tpmtpm USAGE talk DESCRIPTION Sends a one-line message to another user of the node. The user in question must be in idle state (ie. not connected/connecting anywhere or running a program). If the user has an SSID other than zero, the SSID must be specified. If multiple users are logged in with the same callsign/SSID pair, those who are in idle state, get the message. EXAMPLES talk oh7lzb-3 Good evening, Hessu! node-0.3.2/etc/help/escape.hlp0100644000076400007640000000110106404550267014305 0ustar tpmtpm USAGE escape DESCRIPTION Sets the character will be treated as the signal to close down any open connection made from the node. You can specify the escape character in a number of ways. They are: the actual binary character ^T to set it to Control-T (or any other control character) 0xNN to set it to hexadecimal value NN 0NNN to set it to Octal value NNN NNN to set it to decimal value NNN (no leading zero!) off to disable the escape character node-0.3.2/etc/help/nlinks.hlp0100644000076400007640000000021306425171026014341 0ustar tpmtpm USAGE nlinks DESCRIPTION Gives a list of both active NET/ROM connections and NET/ROM sockets in listening state. node-0.3.2/etc/help_french/0040755000076400007640000000000006404550637013700 5ustar tpmtpmnode-0.3.2/etc/help_french/bbs.hlp0100644000076400007640000000010206402074460015132 0ustar tpmtpm USAGE bbs DESCRIPTION Connexion au BBS F8KAE-1. node-0.3.2/etc/help_french/bye.hlp0100644000076400007640000000010106402074460015142 0ustar tpmtpm USAGE bye DESCRIPTION Deconnexion de ce noeud. node-0.3.2/etc/help_french/connect.hlp0100644000076400007640000000205506402074460016026 0ustar tpmtpm USAGE connect [via ...] [s|d] Pour AX.25 connect [s|d] Pour NET/ROM connect [] [d|s] Pour ROSE DESCRIPTION Ouvre une connexion AX.25, NET/ROM ou ROSE sur un hote eloigne. Si plus de deux parametres sont entres et que le deuxieme parametre fait dix caracteres, alors c'est interprete comme une connexion ROSE, autrement le premier parametre est interprete en tant que nom de port et AX.25 est utilise pour faire la connexion via ce port. Si un seul parametre est entre la connexion est faite en utilisant NET/ROM. Si un simple `s' est entre comme dernier parametre, alors quand l'hote eloigne fera une deconnexion, vous reviendrez sur ce noeud. Si un simple `d' est entre comme dernier parametre, alors vous serez egalement deconnecte de ce noeud. Le comportement par defaut (ni `s' ni `d' entres) depend de la configuration par le sysop. node-0.3.2/etc/help_french/dx.hlp0100644000076400007640000000011106402074460014777 0ustar tpmtpm USAGE dx DESCRIPTION Connexion au PacketCluster F6BEE. node-0.3.2/etc/help_french/escape.hlp0100644000076400007640000000120306402074460015627 0ustar tpmtpm USAGE escape DESCRIPTION Defini le caractere qui sera traite comme le signal de fermeture de n'importe quelle connexion ouverte a partir du noeud. Vous pouvez specifier le caractere d'echappement de differentes facons. Les voici: le veritable caractere binaire ^T Pour le definir en Controle-T (ou n'importe quel autre caractere de controle) 0xNN Pour le definir en valeur Hexadecimale NN 0NNN Pour le definir en valeur Octale NNN NNN Pour le definir en valeur Decimale NNN (sans zero avant !) node-0.3.2/etc/help_french/finger.hlp0100644000076400007640000000062206402074460015645 0ustar tpmtpm USAGE finger [][@] DESCRIPTION Informe sur les utilisateurs d'un systeme. Si le nom de l'utilisateur est omis, affiche les utilisateurs actuellement enregistres sur le serveur. Si le nom du serveur est omis, le defaut est le serveur local. EXEMPLES finger @f6fgz.ampr.org finger f5suy@f6fgz.ampr.org finger f5suy node-0.3.2/etc/help_french/help.hlp0100644000076400007640000000042606402074460015325 0ustar tpmtpm USAGE help [] DESCRIPTION Aide pour la commande specifiee ou ce texte si aucune commande n'est specifiee. Les commandes ne peuvent pas etre abregees. Utilisez la commande "?" pour retrouver la liste des commandes disponibles. node-0.3.2/etc/help_french/host.hlp0100644000076400007640000000064106402074460015351 0ustar tpmtpm USAGE host | DESCRIPTION Informe sur un serveur Internet. Le serveur peut etre identifie par un nom (par exemple, f6fgz.ampr.org) ou par une adresse IP (par exemple, 44.151.78.19). Renvoie le nom du serveur, les adresses IP et les alias connus pour le serveur. L'information est recueillie a partir du serveur DNS (domain name service). node-0.3.2/etc/help_french/info.hlp0100644000076400007640000000032506402074460015326 0ustar tpmtpm USAGE info DESCRIPTION Affiche l'information de version ainsi que le contenu du fichier /etc/ax25/node.info, qui decrit ces aspects du systeme dont les sysops aiment a se vanter. node-0.3.2/etc/help_french/links.hlp0100644000076400007640000000060306402074460015512 0ustar tpmtpm USAGE links [* | ] DESCRIPTION Liste les connexions AX.25 actives depuis et vers le serveur local. Avec un asterisque (*) comme argument, affiche aussi les prises AX.25 en etat d'ecoute. Avec un indicatif comme argument, liste toutes les connexions avec soit l'indicatif en source soit l'indicatif en destination . node-0.3.2/etc/help_french/mheard.hlp0100644000076400007640000000030306402074460015627 0ustar tpmtpm USAGE mheard DESCRIPTION Liste les stations AX.25 entendues sur le port specifie. Utilisez la commande "Ports" pour avoir la liste des ports disponibles. node-0.3.2/etc/help_french/nodes.hlp0100644000076400007640000000142406402074460015504 0ustar tpmtpm USAGE nodes [*|] DESCRIPTION Affiche la table des noeuds NET/ROM sur le serveur local. Les noeuds sur cette liste peuvent etre atteints en utilisant la commande Connect sans connaitre le veritable cheminement utilise dans le reseau (en supposant que le reseau est OK). Le parameter optionnel * alterne le mode verbeux, affichant le compteur d'obsolescence, la qualite relative du chemin ainsi que le port et le noeud voisin utilise pour atteindre chaque noeud. Vous pouvez aussi specifier un indicatif de noeud pour obtenir l'information verbeuse pour un simple noeud. Dans ce cas, un champ "which" est affiche pour dire quelle route le noyau utilisera pour atteindre le noeud. node-0.3.2/etc/help_french/ping.hlp0100644000076400007640000000103306402074460015325 0ustar tpmtpm USAGE ping [] DESCRIPTION Verifie si un serveur peut etre atteint au travers du reseau en envoyant un paquet demande d'echo ICMP vers le serveur et en attendant sa reponse. Si une reponse est recue, le temps d'aller-retour (round-trip-time RTT) entre le serveur distant et local, est affiche. Si une longueur facultative est specifiee, la portion de donnees du paquet est remplie du nombre d'octets de la longueur. EXEMPLE ping f6fgz.ampr.org node-0.3.2/etc/help_french/ports.hlp0100644000076400007640000000073506402074460015547 0ustar tpmtpm USAGE ports DESCRIPTION Affiche les ports AX.25 disponibles. Sont affiches le nom du port, la vitesse du port (en bits/sec) et une courte description pour le port. Le nom du port est utilise en utilisant la commande Connect pour se connecter vers un utilisateur ou un service n'utilisant pas NET/ROM (c.a.d. non visible dans la liste des Noeuds). Le nom du port est aussi visible dans les listes Route et Link. node-0.3.2/etc/help_french/routes.hlp0100644000076400007640000000135406402074460015717 0ustar tpmtpm USAGE routes DESCRIPTION Affiche la table de routage NET/ROM du serveur local (c.a.d. les noeuds pour lesquels le noeud local dialogue directement). Ces noeuds sont utilises pour atteindre les autres noeuds dans la table des noeuds. Les champs affiches sont: Link - Si il y a une connexion AX.25 active vers ce noeud Port - Sur quel port est cette route Callsign - L'indicatif du noeud voisin Quality - Une qualite relative pour le chemin (0-255) Destinations - Nombre des autres noeuds atteints via cette route Lock - Si la qualite de cette route est verrouillee par l'operateur node-0.3.2/etc/help_french/status.hlp0100644000076400007640000000110706402074460015715 0ustar tpmtpm USAGE status DESCRIPTION Renvoie l'information de l'etat du systeme Linux sur lequel ce LinuxNode fonctionne. Toutes les informations sont prises directement depuis le systeme d'operation. La valeur de la "charge moyenne" (load average) indique la quantite moyenne des taches attendant du temps CPU durant les 1, 5 et 15 dernieres minutes. Une charge moyenne de 1.0 signifierait que tout le temps CPU est utilise par les taches, et que toutes les taches obtiennent encore le temps qu'elles peuvent utiliser. node-0.3.2/etc/help_french/talk.hlp0100644000076400007640000000103706402074460015327 0ustar tpmtpm USAGE talk DESCRIPTION Envoie un message d'une ligne vers un autre utilisateur du noeud. L'utilisateur en question doit etre inoccupe (idle)(ex. ni connecte/connectant quelque part ou utilisant un programme). Si l'utilisateur a un SSID autre que zero, le SSID doit etre specifie. Si de multiples utilisateurs sont enregistres avec la meme paire indicatif/SSID, ceux qui sont inoccupes recoivent le message. EXEMPLE talk f5suy-3 Bonsoir, Yvan! node-0.3.2/etc/help_french/telnet.hlp0100644000076400007640000000213506402074460015667 0ustar tpmtpm USAGE telnet [] [s|d] DESCRIPTION Ouvre une session telnet vers un serveur distant utilisant TCP/IP. Vous pourriez ne pas connecter un serveur donne a cause de la politique d'utilisation de ce noeud par l'operateur local, ou simplement parce que le serveur n'est pas atteint a cause d'une panne de reseau. Vous pouvez utiliser la commande Ping pour verifier si on peut atteindre un serveur. Par defaut, la commande Telnet connecte sur le port TCP 23 (alloue pour telnet). Vous pouvez specifier un autre port TCP ou un nom de port TCP. Si un simple `s' est entre comme dernier parametre, alors quand l'hote eloigne fera une deconnexion, vous reviendrez sur ce noeud. Si un simple `d' est entre comme dernier parametre, alors vous serez egalement deconnecte de ce noeud. Le comportement par defaut (ni `s' ni `d' entres) depend de la configuration par le sysop. EXEMPLES telnet f6fgz.ampr.org telnet f6fgz.ampr.org 41112 telnet 44.151.78.19 echo node-0.3.2/etc/help_french/users.hlp0100644000076400007640000000030206402074460015527 0ustar tpmtpm USAGE users DESCRIPTION Affiche une liste d'utilisateurs actuellement connectes au noeud local, d'ou les utilisateurs viennent, et ce qu'ils font en ce moment. node-0.3.2/etc/node.motd0100644000076400007640000000013606732001755013226 0ustar tpmtpm Type ? for a list of commands. help gives a description of the named command. node-0.3.2/ipc.c0100644000076400007640000000605507721746467011605 0ustar tpmtpm#include #include #include #include #include #include #include #include #include "node.h" /* * This one (c) 1996 by Heikki Hannikainen, OH7LZB */ #define FIRST_KEY (3694 - 1) /* Where to start looking for a key */ #define LAST_KEY (FIRST_KEY + 200) /* How far to search */ #define M_LEN 1024 /* Largest message transferred */ struct nmsgbuf { long mtype; /* message type, must be > 0 */ char mtext[M_LEN]; /* message data */ }; static int ipc_id = -1; static void usr2_handler(int sig) { struct nmsgbuf buf; if (msgrcv(ipc_id, (struct msgbuf *)&buf, M_LEN, 0, IPC_NOWAIT|MSG_NOERROR) != -1) { nprintf("\n%s %s\n", NodeId, buf.mtext); node_flush(NodeIo); } else log(L_ERROR, "usr2_handler: Caught SIGUSR2, but couldn't receive a message"); signal(SIGUSR2, usr2_handler); /* Restore handler */ } int ipc_send(key_t key, long mtype, char *mtext) { struct nmsgbuf buf; int id; if ((id = msgget(key, S_IRWXU)) == -1) { node_perror("ipc_send: Could not get transmit channel", errno); return -1; } buf.mtype = mtype; strncpy(buf.mtext, mtext, M_LEN); if (msgsnd(id, (struct msgbuf *)&buf, M_LEN, 0) == -1) { node_perror("ipc_send: Could not send message", errno); return -1; } return 0; } int ipc_open(void) { key_t key = FIRST_KEY; do { key++; ipc_id = msgget(key, S_IRWXU | IPC_CREAT | IPC_EXCL); } while ((ipc_id == -1) && (key != LAST_KEY)); if (ipc_id == -1) node_perror("ipc_open: Could not get an IPC channel", errno); #if 0 node_msg("debug: ipc_id=%d key=%d", ipc_id, key); #endif User.ipc_key = key; if (key != -1) signal(SIGUSR2, usr2_handler); else signal(SIGUSR2, SIG_IGN); return 0; } int ipc_close(void) { struct msqid_ds buf; if (ipc_id != -1) /* Remove the IPC channel */ if (msgctl(ipc_id, IPC_RMID, &buf) == -1) { log(L_ERROR, "ipc_close: Could not remove IPC channel: %s", strerror(errno)); return -1; } return 0; } int do_talk(int argc, char **argv) { FILE *f; struct user u; char call[10]; char mtext[M_LEN]; int i, hits = 0, sent = 0; if (argc < 3) { node_msg("Usage: talk "); return 0; } if ((f = fopen(DATA_NODE_LOGIN_FILE, "r")) == NULL) { node_perror(DATA_NODE_LOGIN_FILE, errno); return 0; } sprintf(mtext, "Message from %s:\n", User.call); for (i = 2; i < argc; i++) { strncat(mtext, argv[i], M_LEN - strlen(mtext)); strncat(mtext, " ", M_LEN - strlen(mtext)); } strncat(mtext, "\n--", M_LEN - strlen(mtext)); mtext[M_LEN - 1] = 0; strncpy(call, argv[1], 9); call[9] = 0; while (fread(&u, sizeof(u), 1, f) == 1) { if (u.pid == -1 || (kill(u.pid, 0) == -1 && errno == ESRCH)) continue; if (!strcasecmp(u.call, call)) { hits++; if (u.ipc_key != -1 && u.state == STATE_IDLE) { ipc_send(u.ipc_key, 1, mtext); kill(u.pid, SIGUSR2); sent++; } } } fclose(f); if (hits == 0) node_msg("No such user %s", call); else if (sent == 0) node_msg("%s is busy, cannot talk to him right now.", call); return 0; } node-0.3.2/telnet.h0100644000076400007640000000274606454011245012312 0ustar tpmtpm/* Telnet command characters */ #define TN_SE 240 /* End of subnegotiation parameters */ #define TN_NOP 241 /* No operation */ #define TN_DM 242 /* Data Mark */ #define TN_BRK 243 /* NVT character BRK */ #define TN_IP 244 /* Interrupt Process */ #define TN_AO 245 /* Abort output */ #define TN_AYT 246 /* Are You There */ #define TN_EC 247 /* Erase character */ #define TN_EL 248 /* Erase Line */ #define TN_GA 249 /* Go ahead */ #define TN_SB 250 /* Start of of subnegotiation params */ #define TN_WILL 251 #define TN_WONT 252 #define TN_DO 253 #define TN_DONT 254 #define TN_IAC 255 /* Interpret as command */ /* Linemode extensions to telnet command characters */ #define TN_EOF 236 /* End Of File */ #define TN_SUSP 237 /* Suspend */ #define TN_ABORT 238 /* Abort */ /* Telnet options */ #define TN_TRANS_BINARY 0 /* Binary Transmission */ #define TN_ECHO 1 /* Echo */ #define TN_SUPPRESS_GA 3 /* Suppress Go Ahead */ #define TN_STATUS 5 /* Status */ #define TN_TIMING_MARK 6 /* Timing Mark */ #define TN_LINEMODE 34 /* Linemode */ /* Linemode options */ #define TN_LINEMODE_MODE 1 #define TN_LINEMODE_MODE_EDIT 1 /* Local edit */ #define TN_LINEMODE_MODE_TRAPSIG 2 /* Trap signals */ #define TN_LINEMODE_MODE_MODEACK 4 /* Acknowledge mode */ #define TN_LINEMODE_MODE_SOFTTAB 8 /* Soft Tab */ #define TN_LINEMODE_MODE_LITECHO 16 /* Literal Echo */ #define TN_LINEMODE_FORWARDMASK 2 #define TN_LINEMODE_SLC 3 node-0.3.2/AUTHORS0100644000076400007640000000062107631662447011722 0ustar tpmtpmLinuxNode is based on the original pms.c by Alan Cox GW4PTS, but has been mostly rewritten by me since. Also at least the following people have conributed code: Jonathan Naylor G4KLX Heikki Hannikainen OH7LZB Jean-Paul Roubelat F6FBB Terry Dawson VK2KTJ Jeroen Vreeken PE1RXQ If you were accidentally left out, don't hesitate to email me. -- Tomi Manninen OH2BNS, node-0.3.2/man/0040755000076400007640000000000006732000003011400 5ustar tpmtpmnode-0.3.2/man/node.80100644000076400007640000002025506731773020012436 0ustar tpmtpm.TH NODE 8 "16 June 1999" Linux "Linux System Managers Manual" .SH NAME node \- Node front end for AX.25, NET/ROM, Rose and TCP .SH SYNOPSIS .B node [-c] .SH DESCRIPTION .LP .B Node is a simple node front end, modelled after the node shells of TheNet and G8BPQ nodes. .SH OPTIONS .TP 14 .BI \-c Enable compression. With this option it is assumed that the incoming call is using Zlib based compression (modified Lempel-Ziv 1977). Currently no negotiation is done so the caller must be aware of this. You probably want to set up a separate AX.25, NET/ROM or ROSE callsign in ax25d.conf or a separate TCP port in inetd.conf to listen to compressed connects. .sp 1 At the moment I know only two implementations compatible with this compression method, namely LinuxNode and Clussed. .SH NODE COMMANDS The following commands are supported for users of .B node: .TP 14 .BI ? Give short list of available commands. .TP 14 .BI Bye Disconnect user from the node. .TP 14 .BI "Connect [via ...] [d|s] For AX.25" .TP 14 .BI "Connect [d|s] For NET/ROM" .TP 14 .BI "Connect
[] [d|s] For ROSE" .sp 1 Initiate an AX.25, NET/ROM or ROSE connection to a remote host. If only one argument is supplied then the connection is assumed to be a NET/ROM connection and the argument specifies the callsign of alias of a NET/ROM node. If more than one argument is supplied and the second parameter is composed of numeric characters only then the connection is assumed to be a ROSE connection. Any other combination is assumed to be an AX.25 connection with the first argument being the AX25 port to use for the connection. .sp For a ROSE connection the
part must be exactly six or ten digits. If only six digits are supplied, the DNIC (first four digits) default to the local DNIC. The local DNIC is assumed to be that of the first configured Rose port in /etc/ax25/rsports. .sp The user may optionally supply as the last argument a single character which modifies the default behaviour on disconnection of the connection. If a single `s' is entered as the last argument, then when the remote host disconnects you will be returned to this node. If a single `d' is entered as the last argument, you will be disconnected from this node too. The Default behaviour (neither `s' nor `d' entered) is configured in the node configuration file and depends on the sysop preference. .TP 14 .BI "Escape []" Override the sysop configured default escape character setting. If the Escape command is given without an argument then the current escape character setting is returned to the user. The escape string may be specified using any of the well known codings: .IP .BI "" to enter the escape character in its binary form. .IP .BI "^C" to enter the escape character as a control character value. .IP .BI "NNN" to set the escape character to a Decimal value. .IP .BI "0xNN" to set the escape character to a HexaDecimal value. .IP .BI "0NNN" to set the escape character to an Octal value. .IP .BI "off" to disable the escape character. .TP 14 .BI "Finger [][@]" Retrieve information about users of a system. If the user name is omitted, shows the users currently logged on the host. If the hostname is omitted, defaults to the local host. .TP 14 .BI "Help []" Give help for the specified command or this text if no command is specified. Commands can not be abbreviated. Use the "?" command to retrieve a list of available commands. .TP 14 .BI "HOst | " Give the Domain Name Service host name information about or . .TP 14 .BI Info Display the version information and the contents of the /etc/ax25/node.info file, which should describe any aspects of your system that you would like to brag about. .TP 14 .BI "Links [* | ]" Give a list of active AX.25 connections to and from the local host. With an optional argument * list also AX.25 sockets in state listening. A callsign as argument gives a list of all connections with as source or destination address. .TP 14 .BI "Mheard " Give a list of heard AX.25 stations on the specified port. .TP 14 .BI "NLinks" Give a list of active NET/ROM connections to and from the local host. .TP 14 .BI "Nodes [* | ]" Show the NET/ROM node table of the local host. The nodes on this list can be reached using the Connect command without knowing the actual network path used (assuming the network is OK). .sp The optional argument '*' toggles verbose mode, showing the Obsolescence counter, relative path quality and the port and neighbour node used to reach each node. You can also specify a node callsign to get the verbose information for a single node. In that case a "which" field that tells what route the kernel will use to reach the node is also shown. .TP 14 .BI Ports Show the available AX.25 ports. Shown are the port name and a short description for the port. The port name is used when using the Connect command to connect to an user or service not running NET/ROM (eg. not visible in the Nodes list). .TP 14 .BI "PIng []" Check if a host can be reached trough the network by sending an ICMP Echo Request packet to the host and waiting for it to reply. If a reply is received the round-trip-time (RTT) between the local and remote hosts is shown. .sp If an optional length is specified the data portion of the packet is filled with length number of bytes. .TP 14 .BI Routes Show the NET/ROM neighbour table of the local host (ie. the nodes which the local node directly talks with). These nodes are used to reach the other nodes on the node table. .TP 14 .BI Status Give some more or less useful information about the system. .TP 14 .BI "Telnet [] [] [d|s]" Initiate a telnet session to a remote host using TCP/IP. By default, the telnet command connects to the TCP port 23 (allocated for telnet). You can specify another TCP port or a TCP port name. .sp If an optional third argument is given, that string, followed by a CRLF is sent to the remote host right after the connection is established. This is mainly useful for command aliases. .sp If a single `s' is entered as the last parameter, then when the remote host disconnects you will be returned to this node. If a single `d' is entered as the last parameter, you will be disconnected from this node too. Default behaviour (neither `s' nor `d' entered) depends on sysop configuration. .TP 14 .BI "TAlk " Send a message to another user of the node. The user in question must be in idle state (ie. not connected/connecting anywhere or running a program). .sp If the user has an SSID other than zero, the SSID must be specified. If multiple users are logged in with the same callsign/SSID pair, those who are in idle state, get the message. .TP 14 .BI Users Show a list of users currently connected to the local node, where the users are coming from, and what are they doing at the moment. .TP 14 .BI "ZConnect" Initiate a compressed AX.25, NET/ROM or ROSE connection. The command arguments are the same as in .B "Connect" command. Note that the other end must be expecting a compressed connection (a LinuxNode started with the -c command line option). No negotiation of compression is done. .TP 14 .BI "ZTelnet" Initiate a compressed telnet session. The command arguments are the same as in .B "Telnet" command. Note that the other end must be expecting a compressed connection (a LinuxNode started with the -c command line option). No negotiation of compression is done. .SH FILES .LP .TP 5 .B /etc/ax25/node.conf LinuxNode configuration file. .br .TP 5 .B /etc/ax25/node.perms LinuxNode permissions file. .br .TP 5 .B /etc/ax25/node.motd LinuxNode message of the day file. .br .TP 5 .B /etc/ax25/node.info The response to the 'info' command. This file should be edited to reflect the local configuration. .br .TP 5 .B /var/ax25/node/loggedin Database of current users. .br .TP 5 .B /var/ax25/mheard/mheard.dat Information about AX.25 stations heard. .br .TP 5 .B /usr/lib/ax25/node/help/*.hlp The online help files. .SH "SEE ALSO" .BR node.conf (5), .BR node.perms (5), .BR axports (5), .BR ax25d (8), .BR mheardd (8). .SH AUTHOR Tomi Manninen OH2BNS .br Alan Cox GW4PTS node-0.3.2/man/node.conf.50100644000076400007640000002365306731777230013373 0ustar tpmtpm.TH NODE.CONF 5 "16 June 1999" Linux "Linux Programmer's Manual" .SH NAME node.conf \- LinuxNode configuration file. .SH DESCRIPTION .LP .B Node.conf file is read by LinuxNode at program startup and is used to modify the behaviour of the node. .LP The lines within .B node.conf must either be a comment line, which starts with a # in the first column, or one of the commands listed below. Commands and arguments are delimited by white space. Arguments can contain white space if they are enclosed in single or double quotes. C style character literals are not parsed and parameter expansion (see below) is not done inside single quotes. .sp Available configuration commands are: .TP 14 .B Alias ' []' Sets up a command alias. The number of uppercase characters at the beginning of specifies how much the user may abbreviate the command. The uppercase part should be long enough to separate the command from other commands starting with the same letters. If there are no uppercase letters in the beginning, the whole name is converted to upper case and user can not abbreviate the command. Note that certain %-escapes (positional parameters, current time) have a reasonable meaning only when the alias is actually executed and thus they should not be parsed at the time the configuration file is read. This can be achieved by enclosing the command and argument part in single quotes. Another possibility is to use double quotes and escape the percent sign with a backslash (eg. \\%1) .TP 14 .B ConnTimeout When user is connected to another system via this system and the connection is idle (no data flowing in either direction) for seconds the connection is dropped and user disconnected from node. Default is 3600 seconds (1 hour). .TP 14 .B EscapeChar Specifies the escape character. The escape string may be specified using any of the well known codings: .IP .BI "" to enter the escape character in its binary form. .IP .BI "^C" to enter the escape character as a control character value. .IP .BI "NNN" to set the escape character to a Decimal value. .IP .BI "0xNN" to set the escape character to a HexaDecimal value. .IP .BI "0NNN" to set the escape character to an Octal value. .IP .BI "off" to disable the escape character. .sp The default is CTRL-T (^T). .sp Note that the escape mechanism breaks 8-bit transparency of LinuxNode and you should either disable it or set the no-escape flag in node.perms for the forwarding stations if (compressed) forward is run trough LinuxNode. Also the Escape user command can be used in a forward script to disable the escape (see node(8)). .TP 14 .B ExtCmd Sets up an external command. .RS .TP 10 .B NAme This is the name under which the command appears at nodes command list. The number of uppercase characters at the beginning of specifies how much the user may abbreviate the command. The uppercase part should be long enough to separate the command from other commands starting with the same letters. If there are no uppercase letters in the beginning, the whole name is converted to upper case and user can not abbreviate the command. .TP 10 .B flags This is a sum of flags that control the way the external command is executed. Currently two flags are implemented: .RS .TP 5 .B 1 Run command through pipe. Without this flag node just fork()s and exec()s the specified command and then waits for it to terminate. The command must it self be aware about the underlying protocol. It must handle packetising and any end of line conversions. With this flag however node sets up a pipe between it self and the command and handles packetising and end of line conversions for it. .TP 5 .B 2 Reconnected to flag. If this flag is set, the user gets a reconnected to prompt after the external command is finished. .RE .TP 10 .B uid This is the userid that the following command should run under when executing. .TP 10 .B exec This is the executable that should be executed. .TP 10 .B args... These are the optional arguments that are passed to the executable. The first argument is the command name that is passed to the program (argv[0]). It is usually the executable name without path. See the Alias command for a discussion about the command arguments and %-escapes (parameter expansion). .RE .TP 14 .B HiddenPorts ... Marks the AX.25 port as hidden. Hidden ports are not shown to users in Links, Mheard, Ports and Routes commands and can not be used to make AX.25 downlink connections unless user is specially permitted to do so (see node.perms(5)). Up to 32 hidden ports can be specified with this command. .TP 14 .B HostName This is the visible hostname of the node. It will be shown at telnet login and in the node welcome message. .TP 14 .B IdleTimeout After seconds of inactivity while waiting for a command user is disconnected from node. Default is 900 seconds (15 mins). .TP 14 .B LocalNet Defines a "local" network. Users telneting from hosts in this network are treated separately (see node.perms(5)). is a KA9Q NOS style network address consisting of a dotted-quad IP address of the network and a number of significant bits separated by a slash. Note that 127.0.0.0/8 (loopback net) is also considered "local" by default. .TP 14 .B LogLevel Specifies what node should log. The available levels are: .RS .TP 5 .B 0 Don't log anything. .TP 5 .B 1 Log only critical errors. .TP 5 .B 2 Log errors and logins/logouts. .TP 5 .B 3 Log errors, logins/logouts and all gateway commands. .LP Default is to log only critical errors. .RE .TP 14 .B NodeId This is the id that is shown in every message from node. Default is "LinuxNode}". .TP 14 .B NodePrompt Sets the prompt string. The prompt string is evaluated every time it is printed so what was previously said about %-escapes (parameter expansion) in Alias command is valid here also. .TP 14 .B NrPort This is the name of the netrom port that is used when making outgoing netrom connects. Normally it should match the portname that is used in ax25d.conf to listen for incoming netrom calls. Default is the first netrom port. .TP 14 .B ReConnect on|off ReConnect flag. If enabled, users gatewaying to another host get reconnected to this node after the remote host closes connection. If it's off connection to the user will also be closed. User can override the default behaviour with a single `s' or `d' at the end of the gatewaying command (connect or telnet). Default is off. .TP 14 .B ResolveAddrs on|off If enabled, dotted-quad IP addresses are resolved to symbolic names when pinging or telneting out. Also, the domain name of the peer is resolved for telnet logins. Default is off. .SH CHARACTER LITERALS .LP C style character literals are parsed when reading the configuration file. The following formats are expanded: .TP 14 \\n This is substituted with Line Feed .TP 14 \\t This is substituted with Horizontal Tab .TP 14 \\v This is substituted with Vertical Tab .TP 14 \\b This is substituted with Backspace .TP 14 \\r This is substituted with Carriage Return .TP 14 \\f This is substituted with Form Feed .TP 14 \\a This is substituted with Alert (BELL) .TP 14 \\\\ This is substituted with Backslash (\\) .TP 14 \\" This is substituted with double quote (") .TP 14 \\' This is substituted with single quote (') .TP 14 \\xNN This is substituted with the character corresponding to the code value of NN interpreted as a hexadecimal number. .TP 14 \\0NN This is substituted with the character corresponding to the code value of NN interpreted as an octal number. .TP 14 \\0 This is substituted with the NUL character (ascii 0) .SH PARAMETER EXPANSION .LP While reading the configuration file a word starting with a % is expanded. The following formats are expanded: .TP 14 .B %parameter This is substituted with the value of .B parameter . .TP 14 .B %{parameter} The same as above. .TP 14 .B %{parameter:default} If .B parameter is defined this is susbtituted with the value of it. If not, the default value is substituted. This currently applies only to positional parameters 0...9. .LP The following parameters are defined: .LP .TP 8 .B 0...9 The positional parameters. Positional parameters are not meaningful while reading the node.conf so the default value (if present) is always substituted. .TP 8 .B F The full hostname in upper case. .TP 8 .B f The full hostname in lower case. .TP 8 .B H The hostname in upper case. .TP 8 .B h The hostname in lower case. .TP 8 .B I or i Current time (HH:MM:SS). .TP 8 .B N or n The node ID as set with the NodeId command. .TP 8 .B U The username (callsign) of the remote station in upper case without the SSID. .TP 8 .B u The username (callsign) of the remote station in lower case without the SSID. .TP 8 .B S The username (callsign) of the remote station in upper case with the SSID. .TP 8 .B s The username (callsign) of the remote station in lower case with the SSID. .TP 8 .B P The nodename (callsign) of the remote station (NET/ROM), the portname the user is coming in via (AX.25) or the ip address of the remote host (TCP). In upper case without the SSID. .TP 8 .B p The nodename (callsign) of the remote station (NET/ROM), the portname the user is coming in via (AX.25) or the ip address of the remote host (TCP). In lower case without the SSID. .TP 8 .B R The nodename (callsign) of the remote station (NET/ROM), the portname the user is coming in via (AX.25) or the ip address of the remote host (TCP). In upper case with the SSID. .TP 8 .B r The nodename (callsign) of the remote station (NET/ROM), the portname the user is coming in via (AX.25) or the ip address of the remote host (TCP). In lower case with the SSID. .TP 8 .B t The type of the user connection (ax25, netrom, rose, inet, host) in lower case. .TP 8 .B T The type of the user connection (ax25, netrom, rose, inet, host) in upper case. .LP Anything else after a % is substituted with a %. .SH FILES .LP /etc/ax25/node.conf .SH "SEE ALSO" .BR node (8), .BR node.perms (5), .BR axports (5), .BR ax25 (4). node-0.3.2/man/node.perms.50100644000076400007640000000526006731773313013564 0ustar tpmtpm.TH NODE.PERMS 5 "16 June 1999" Linux "Linux Programmer's Manual" .SH NAME node.perms \- LinuxNode permissions file. .SH DESCRIPTION .LP .B Node.perms file is read at program startup with the knowledge of users username (call), connection type (AX.25, NET/ROM, ROSE, TCP/IP), peers IP address (for TCP/IP) and port name (for AX.25). The first entry matching this information is taken and user is asked for password and given permissions according to it. .LP The lines within .B node.perms must either be a comment line, which starts with a # in the first column, or a permission entry in the following format, each field being delimited by white space: .sp .RS username type portname password permissions .RE .sp The field descriptions are: .sp .TP 14 .B username This is matched against users username (call) without SSID. An asterisk (*) matches any username. .TP 14 .B type This is matched against the type of the connection to user. Possible values for this field are: .RS 14 .TP .B * matches any type of connection. .TP .B ax25 matches users coming in with AX.25. .TP .B netrom matches users coming in with NET/ROM. .TP .B rose matches users coming in with ROSE. .TP .B local matches TCP/IP connections where users host is in "local" network as defined in node.conf(5). .TP .B ampr matches TCP/IP connections where users host is in amprnet (44.0.0.0/8). .TP .B inet matches TCP/IP connections where users host is neither in "local" network nor in amprnet. .TP .B host matches users starting LinuxNode from shell. .RE .TP 14 .B portname If user is coming in with AX.25 this field is matched against the local port name the user is coming in via. An asterisk (*) matches any port name. .TP 14 .B password If the previous tree fields match and this field is not a single asterisk (*) the user is asked for a password. The password is then matched against this field. .TP 14 .B permissions This field represents a a bitmask of operations the user is permitted to do. It is a sum of the values listed here: .RS 14 .TP .B 1 permits logging in even if no other permissions are given. .TP .B 2 permits outgoing AX.25 connects. .TP .B 4 permits outgoing NET/ROM connects. .TP .B 8 permits telneting to hosts in the "local" network as defined in node.conf(5). .TP .B 16 permits telneting to hosts in amprnet. .TP .B 32 permits telneting to hosts neither in the "local" network nor in amprnet. .TP .B 64 permits using hidden ports in outgoing AX.25 connections. (See HiddenPorts command in node.conf(5).) .TP .B 128 permits outgoing ROSE connects. .TP .B 256 The no-escape flag. Disables the escape mechanism for this user. .RE .SH FILES .LP /etc/ax25/node.perms .SH "SEE ALSO" .BR node (8), .BR node.conf (5), .BR axports (5), .BR ax25 (4). node-0.3.2/man/nodeusers.10100644000076400007640000000157306731773510013517 0ustar tpmtpm.TH NODEUSERS 1 "16 June 1999" Linux "Linux Programmer's Manual" .SH NAME nodeusers \- LinuxNode user information lookup program .SH SYNOPSIS .B nodeusers [-a] [-i] [-l] .SH DESCRIPTION .LP .B Nodeusers displays information about current LinuxNode users. .SH OPTIONS .TP 10 .BI \-a Tells nodeusers to use a plain as end-of-line. This is usefull if nodeusers is called from ax25d. .TP 10 .BI \-i Tells nodeusers to use a pair as end-of-line sequence and also to wait for one line of input before sending the user data. This should be used if nodeusers is used in an internet environment (eg. as a fingerd replacement). The received line is ignored. .TP 10 .BI \-l Enables logging of errors to the system logging facility. .SH FILES .LP .TP 5 .B /var/ax25/node/loggedin Database of current users. .SH "SEE ALSO" .BR node (8) .SH AUTHOR Tomi Manninen OH2BNS node-0.3.2/configure0100755000076400007640000000406507631712502012553 0ustar tpmtpm#!/bin/sh ETC_DIR=/etc/ax25 SBIN_DIR=/usr/sbin BIN_DIR=/usr/bin LIB_DIR=/usr/lib VAR_DIR=/var/ax25 echo -n "Your machine architecture is ... " ARCH=`uname -m` echo $ARCH echo -n "Checking man directory... " MAN_DIR="" for mandir in /usr/share/man /usr/man do if [ -d $mandir ] then echo $mandir MAN_DIR=$mandir fi done echo -n "Checking for the existence of the Zlib headers... " ZLIB="" HAVEZLIB="#undef" for zlibdir in /usr/include /usr/local/include do if [ -f $zlibdir/zlib.h ] then echo $zlibdir/zlib.h ZLIB="-lz" HAVEZLIB="#define" fi done if [ -z "$ZLIB" ] then echo "not found." echo " Without Zlib Node will lack compression support" echo " See INSTALL for more information." echo fi # Global protocol definition symbols for programmers that want to conditionally # compile HAVEAX25="#undef" HAVENETROM="#undef" HAVEROSE="#undef" echo -n "Include support for the AX.25 protocol ? [Y/n]: "; read answer if [ "$answer" = "Y" -o "$answer" = "y" -o "$answer" = "" ] then HAVEAX25="#define" fi # echo -n "Include support for the NetRom protocol ? [Y/n]: "; read answer if [ "$answer" = "Y" -o "$answer" = "y" -o "$answer" = "" ] then HAVEAX25="#define" HAVENETROM="#define" fi # echo -n "Include support for the Rose protocol ? [Y/n]: "; read answer if [ "$answer" = "Y" -o "$answer" = "y" -o "$answer" = "" ] then HAVEAX25="#define" HAVEROSE="#define" fi echo "Creating Makefile.include" sed -e "s~@ARCH@~$ARCH~g; \ s~@ETC_DIR@~$ETC_DIR~g; \ s~@LIB_DIR@~$LIB_DIR~g; \ s~@SBIN_DIR@~$SBIN_DIR~g; \ s~@BIN_DIR@~$BIN_DIR~g; \ s~@VAR_DIR@~$VAR_DIR~g; \ s~@MAN_DIR@~$MAN_DIR~g; \ s~@ZLIB@~$ZLIB~g" Makefile.include echo "Creating config.h" sed -e "s~@ETC_DIR@~$ETC_DIR~g; \ s~@LIB_DIR@~$LIB_DIR~g; \ s~@SBIN_DIR@~$SBIN_DIR~g; \ s~@BIN_DIR@~$BIN_DIR~g; \ s~@VAR_DIR@~$VAR_DIR~g; \ s~@MAN_DIR@~$MAN_DIR~g; \ s~@HAVEAX25@~$HAVEAX25~g; \ s~@HAVENETROM@~$HAVENETROM~g; \ s~@HAVEROSE@~$HAVEROSE~g; \ s~@HAVEZLIB@~$HAVEZLIB~g" config.h echo "Configuration successful" exit 0 node-0.3.2/config.h.in0100644000076400007640000000124706705224610012665 0ustar tpmtpm#ifndef CONFIG_H #define CONFIG_H /* * Some global #defines for programmers to use for conditional compilation */ @HAVEAX25@ HAVE_AX25 1 @HAVEROSE@ HAVE_ROSE 1 @HAVENETROM@ HAVE_NETROM 1 @HAVEZLIB@ HAVE_ZLIB_H 1 /* * mheard specific (we need to get this out of here!!!!) */ #define DATA_MHEARD_FILE "@VAR_DIR@/mheard/mheard.dat" /* * node specific */ #define CONF_NODE_FILE "@ETC_DIR@/node.conf" #define CONF_NODE_PERMS_FILE "@ETC_DIR@/node.perms" #define CONF_NODE_MOTD_FILE "@ETC_DIR@/node.motd" #define CONF_NODE_INFO_FILE "@ETC_DIR@/node.info" #define DATA_NODE_LOGIN_FILE "@VAR_DIR@/node/loggedin" #define DATA_NODE_HELP_DIR "@LIB_DIR@/ax25/node/help/" #endif node-0.3.2/Makefile.include.in0100644000076400007640000000032606705224713014332 0ustar tpmtpm# Processor architecture ARCH = @ARCH@ # Paths ETC_DIR = @ETC_DIR@ SBIN_DIR = @SBIN_DIR@ BIN_DIR = @BIN_DIR@ LIB_DIR = @LIB_DIR@ MAN_DIR = @MAN_DIR@ VAR_DIR = @VAR_DIR@ # Is Zlib available? ZLIB = @ZLIB@ node-0.3.2/INSTALL0100644000076400007640000000621406737174372011710 0ustar tpmtpm1. COMPILING and INSTALLING To compile and run LinuxNode you will need to have libax25-0.0.4 or newer installed on your system. LinuxNode is currently only tested on RedHat 6.0 with Linux kernel 2.2.9. It should work on any platform where libax25 can be compiled and installed but there is no guarantee on that (well, there isn't any guarantee on anything with a GPL licence...). Note however that it will NOT work with 2.0.x kernels. To install you should first run: ./configure and answer to the questions it makes. If `configure´ complains about missing Zlib headers, it means that neither incoming nor outgoing compression support will be built into the binary, that is the "-c" command line argument won't work and "zconnect" and "ztelnet" node commands will be left out. Otherwise everything should work. Next you run: make depend make make install Optionally you may want to run also: make installconf to install the default configuration files. Note however that this WILL overwrite any existing files you might have. After that you need to edit the files /etc/ax25/node.conf and /etc/ax25/node.perms to suit your system. The manual pages for node.conf(5) and node.perms(5) should give an idea of what to put into these files. The AX25-HOWTO is a must read also. 2. RUNNING Node is intended to be called from ax25d or inetd. It doesn't need any command line arguments but there is one to support incoming compressed connects. See the node(8) manual page. To run LinuxNode from ax25d, /etc/ax25/ax25d.conf should have something like this in it: # AX.25 [OH2BNS VIA 144] default * * * * * * - root /usr/bin/node node # NETROM default * * * * * * - root /usr/bin/node node /etc/inetd.conf could have something like this in it: # Set up LinuxNode to listen at telnet port telnet stream tcp nowait root /usr/bin/node node Note that LinuxNode should always be run as root. Otherwise outgoing connects won't work. Also ping needs a raw socket which requires root priviledges. LinuxNode can also be called from command line. It then uses kernel axassociation table to find a call associated to the user. Again for outgoing connects (and ping) to work LinuxNode needs to be installed setuid root (make install does that by default). 3. LOGGING LinuxNode uses the LOG_LOCAL7 syslog facility to log its messages to the system log. In my RedHat distribution almost all syslog messages are by default forwarded to /var/log/messages file. If LinuxNode is used in a busy multiport environment and with LogLevel set to log everything, it can produce quite a lot of output to the system logs. I therefore forward all messages from LinuxNode to a separate file. This can be done in /etc/syslog.conf with something like this: # Log anything (except mail) of level info or higher. # Don't log private authentication messages! # Don't log LinuxNode messages either. *.info;mail.none;authpriv.none;local7.none /var/log/messages # LinuxNode messages local7.* /var/log/node Remember to create the logfile and to send a SIGHUP to syslogd after you make the changes (killall -HUP syslogd). -- Tomi Manninen OH2BNS,