Filewatcher File Search
FTP Search
  
Directory 
  
Content Search 
   
pkg://node-0.3.0-730.src.rpm:62445/node-0.3.0.tar.gz  info  downloads

node-0.3.0/ 40755    764    764           0  6740166371  10227 5ustar  tpmtpmnode-0.3.0/HISTORY100644    764    764       16340  6740166365  11437 0ustar  tpmtpm0.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 <node>
			  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.0/Makefile100644    764    764        3760  6732002040  11751 0ustar  tpmtpmall: nodeusers node

CC = gcc
LD = gcc
CFLAGS = -Wall -Wstrict-prototypes -O2
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.0/README100644    764    764        2732  6737174440  11212 0ustar  tpmtpmLinuxNode v0.3.0

Copyright (C) 1996,1997,1998,1999 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, <tomi.manninen@hut.fi>
node-0.3.0/command.c100644    764    764       37771  6726554402  12145 0ustar  tpmtpm#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <time.h>
#include <fcntl.h>
#include <sys/utsname.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include "kernel_ax25.h"
#include "kernel_rose.h"
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <netax25/axlib.h>
#include <netax25/axconfig.h>
#include <netax25/nrconfig.h>
#include <netax25/procutils.h>
#include <netax25/mheard.h>

#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 <port>");
		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[80], 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;
	}
	strcpy(fname, DATA_NODE_HELP_DIR);
	if (*argv[0] == 'i') {				/* "info"	*/
		strcpy(fname, CONF_NODE_INFO_FILE);
		node_msg("%s", VERSION);
	} else if (argc == 1) {				/* "help"	*/
		strcat(fname, "help.hlp");
	} else {					/* "help <cmd>"	*/
		if (strchr(argv[1], '/') == NULL) {
			strlwr(argv[1]);
			strcat(fname, argv[1]);
			strcat(fname, ".hlp");
		}
	}
	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 <hostname>|<ip address>");
		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 <node>" */
	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 <hessu@pspt.fi> 
 * 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.0/config.c100644    764    764       21372  6726554402  11762 0ustar  tpmtpm#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pwd.h>
#include "kernel_ax25.h"
#include "kernel_rose.h"
#include <netax25/axlib.h>
#include <netax25/axconfig.h>

#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.0/extcmd.c100644    764    764        6712  6726554402  11762 0ustar  tpmtpm#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "kernel_ax25.h"	/* axutils.h needs this...	*/
#include "kernel_rose.h"
#include <grp.h>
#include <sys/wait.h>
#include <netax25/axlib.h>
#include <netax25/axconfig.h>

#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 pid, c;
	fd_set fdset;

	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]);
		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]);
	if (fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK) == -1 ||
	    fcntl(pipe_out[0], F_SETFL, O_NONBLOCK) == -1) {
		node_perror("pipe_extcmd: fcntl - pipe_out", errno);
		goto end;
	}
	iop = axio_init(pipe_out[0], pipe_in[1], 1024, UNSPEC_EOL);
	if (iop == NULL) {
		node_perror("pipe_extcmd: Error initializing I/O", -1);
		goto end;
	}
	while (1) {
		FD_ZERO(&fdset);
		FD_SET(STDIN_FILENO, &fdset);
		FD_SET(pipe_out[0], &fdset);
		if (select(32, &fdset, 0, 0, 0) == -1) {
			node_perror("pipe_extcmd: select", errno);
			break;
		}
		if (FD_ISSET(STDIN_FILENO, &fdset)) {
			alarm(ConnTimeout);
			while((c = axio_getc(NodeIo)) != -1)
				axio_putc(c, iop);
			if (errno != EAGAIN)
				break;
		}
		if (FD_ISSET(pipe_out[0], &fdset)) {
			alarm(ConnTimeout);
			while((c = axio_getc(iop)) != -1)
				axio_putc(c, NodeIo);
			if (errno != EAGAIN) {
                                if (errno)
                                        node_msg("%s", strerror(errno));
                                break;
			}
		}
		axio_flush(NodeIo);
		axio_flush(iop);
	}
	axio_end(iop);
end:
	signal(SIGCHLD, SIG_DFL);
	kill(pid, SIGKILL);
	close(pipe_in[1]);
	close(pipe_out[0]);
	if (fcntl(STDIN_FILENO, F_SETFL, 0) == -1)
		node_perror("pipe_extcmd: fcntl - stdin", errno);
	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.0/gateway.c100644    764    764       43350  6726554402  12156 0ustar  tpmtpm#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <time.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "kernel_ax25.h"
#include "kernel_rose.h"
#include <netinet/ip_icmp.h>
#include <netinet/ip.h>

#include <netax25/axlib.h>
#include <netax25/axconfig.h>
#include <netax25/nrconfig.h>
#include <netax25/rsconfig.h>
#include <netax25/procutils.h>

#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...
	 */
	if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1) {
		node_perror("connect_to: fcntl - fd", errno);
		close(fd);
		return NULL;
	}
	if (fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK) == -1) {
		node_perror("connect_to: fcntl - stdin", errno);
		close(fd);
		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("Trying %s... Type <RETURN> to abort", print_dl(&User));
	axio_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(STDIN_FILENO, &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("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(STDIN_FILENO, &read_fdset)) {
			if (axio_getline(NodeIo) != NULL) {
				node_msg("Aborted");
				close(fd);
				return NULL;
			} else if (errno != EAGAIN) {
				close(fd);
				return NULL;
			}
		}
	}
	if (escape == -1)
		node_msg("Connected to %s", print_dl(&User));
	else
		node_msg("Connected to %s (Escape: %s%c)",
			 print_dl(&User),
			 escape < 32 ? "CTRL-" : "",
			 escape < 32 ? (escape + 'A' - 1) : escape);

	axio_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("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;
	fd_set fdset;
	char *connstr = NULL;

	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 <host> [<port>] [d|s]");
		else
			node_msg("Usage: connect [<port>] <call> [via <call1> ...] [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) {
		if (fcntl(STDIN_FILENO, F_SETFL, 0) == -1)
			node_perror("do_connect: fcntl - stdin", errno);
		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);
	}
	while (1) {
		FD_ZERO(&fdset);
		FD_SET(riop->ifd, &fdset);
		FD_SET(STDIN_FILENO, &fdset);
		if (select(32, &fdset, 0, 0, 0) == -1) {
			node_perror("do_connect: select", errno);
			break;
		}
		if (FD_ISSET(riop->ifd, &fdset)) {
			alarm(ConnTimeout);
			while((c = axio_getc(riop)) != -1)
				axio_putc(c, NodeIo);
			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("Decompression error");
					break;
				default:
					node_msg("%s", strerror(errno));
					break;
				}
				break;
			}
		}
		if (FD_ISSET(STDIN_FILENO, &fdset)) {
			alarm(ConnTimeout);
			while((c = axio_getc(NodeIo)) != -1) {
				if (escape != -1 && c == escape)
					break;
				axio_putc(c, riop);
			}
			if (escape != -1 && c == escape) {
				axio_eolmode(NodeIo, EOLMODE_TEXT);
				axio_getline(NodeIo);
				break;
			}
			if (errno != EAGAIN) {
				stay = 0;
				break;
			}
		}
		axio_flush(riop);
		axio_flush(NodeIo);
	}
	axio_end(riop);
	log(L_GW, "Disconnected from %s", print_dl(&User));
	if (stay) {
		axio_eolmode(NodeIo, EOLMODE_TEXT);
		if (fcntl(STDIN_FILENO, F_SETFL, 0) == -1)
			node_perror("do_connect: fcntl - stdin", errno);
		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);
	if (riop != NULL) {
		if (fcntl(riop->ifd, F_SETFL, 0) == -1)
			node_perror("do_finger: fcntl - fd", errno);
		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);
	}
	axio_eolmode(NodeIo, EOLMODE_TEXT);
	if (fcntl(STDIN_FILENO, F_SETFL, 0) == -1)
		node_perror("do_finger: fcntl - stdin", errno);
	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;
}

int do_ping(int argc, char **argv)
{
	static int sequence = 0;
	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;
	struct iphdr *ip;
	fd_set fdset;
	int fd, i, id, len = sizeof(struct icmphdr);
	int salen = sizeof(struct sockaddr);

	if (argc < 2) {
		node_msg("Usage: ping <host> [<size>]");
		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 <RETURN> 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.
	 */
	id = getpid() & 0xffff;
	icp = (struct icmphdr *)buf;
	icp->type = ICMP_ECHO;
	icp->code = 0;
	icp->checksum = 0;
	icp->un.echo.id = id;
	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).
	 */
	if (fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK) == -1) {
		node_perror("do_ping: fcntl - stdin", errno);
		close(fd);
		return 0;
	}
	while (1) {
		FD_ZERO(&fdset);
		FD_SET(fd, &fdset);
		FD_SET(STDIN_FILENO, &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);
			ip = (struct iphdr *)buf;
			/* Is it long enough? */
			if (len >= (ip->ihl << 2) + sizeof(struct icmphdr)) {
				len -= ip->ihl << 2;
				icp = (struct icmphdr *)(buf + (ip->ihl << 2));
				/* Is it ours? */
				if (icp->type == ICMP_ECHOREPLY && icp->un.echo.id == id && icp->un.echo.sequence == sequence - 1) {
					node_msg("%s rtt: %ldms (ttl=%d)", inet_ntoa(from.sin_addr), calc_rtt(tv2, tv1), ip->ttl);
					break;
				}
			}
		}
		if (FD_ISSET(STDIN_FILENO, &fdset)) {
			if (axio_getline(NodeIo) != NULL) {
				node_msg("Aborted");
				break;
			} else if (errno != EAGAIN) {
				break;
			}
		}
	}
	if (fcntl(STDIN_FILENO, F_SETFL, 0) == -1)
		node_perror("do_ping: fcntl - stdin", errno);
	close(fd);
	return 0;
}

node-0.3.0/COPYING100644    764    764       43076  6724612641  11407 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.

    <one line to give the program's name and a brief idea of what it does.>
    Copyright (C) 19yy  <name of author>

    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.

  <signature of Ty Coon>, 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.0/node.c100644    764    764       15143  6726554402  11441 0ustar  tpmtpm#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <signal.h>
#include <time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include "kernel_ax25.h"
#include "kernel_rose.h"
#include <netax25/axlib.h>
#include <netax25/axconfig.h>
#include <netax25/nrconfig.h>
#include <netax25/rsconfig.h>
#include <netax25/procutils.h>

#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);
	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);
	}
	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.0/cmdparse.c100644    764    764       14302  6731775251  12311 0ustar  tpmtpm#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <time.h>
#include <sys/socket.h>
#include "kernel_ax25.h"
#include "kernel_rose.h"
#include <netax25/axlib.h>

#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);
			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);
	argc = parse_args(argv, cmdbuf);
	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.0/node.h100644    764    764        7561  6740156731  11432 0ustar  tpmtpm#include <sys/types.h>
#include <errno.h>

#include "config.h"

#include <netax25/ax25io.h>

#define VERSION		"LinuxNode v0.3.0"

#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)

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 int nputs(const char *);
extern int nprintf(const char *, ...);
extern void node_msg(const char *, ...);
extern void node_perror(char *, int);
extern char *print_node(const char *, const char *);
extern char *print_dl(struct user *);
extern void 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.0/nodeusers.c100644    764    764        3344  6726554402  12503 0ustar  tpmtpm#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <time.h>
#include <sys/file.h>
#include <sys/socket.h>
#include <signal.h>
#include <syslog.h>
#include "kernel_ax25.h"
#include "kernel_rose.h"
#include <netax25/axlib.h>
#include <netax25/procutils.h>

#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; }

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.0/sysinfo.c100644    764    764        4102  6707433465  12163 0ustar  tpmtpm#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <fcntl.h>

#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[512];

/* 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.0/sysinfo.h100644    764    764         272  6414236572  12147 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.0/user.c100644    764    764       12674  6707433513  11476 0ustar  tpmtpm#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <time.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <sys/socket.h>
#include <signal.h>
#include <netax25/procutils.h>

#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.0/util.c100644    764    764        5043  6707433523  11446 0ustar  tpmtpm#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
#include <syslog.h>
#include <string.h>
#include <time.h>
#include <sys/file.h>
#include <netdb.h>
#include <sys/socket.h>

#include "node.h"

static char buf[4096];

int nputs(const char *str)
{
	return axio_puts(str, NodeIo);
}

int nprintf(const char *fmt, ...)
{
	va_list args;

	va_start(args, fmt);
	vsprintf(buf, fmt, args);
	va_end(args);

	return nputs(buf);
}

void node_msg(const char *fmt, ...)
{
	va_list args;
	
	va_start(args, fmt);
	vsprintf(buf, fmt, args);
	va_end(args);

	nputs(NodeId);
	nputs(" ");
	nputs(buf);
	nputs("\n");
}

void node_perror(char *str, int err)
{
	int oldmode;

	oldmode = axio_eolmode(NodeIo, EOLMODE_TEXT);
	buf[0] = 0;
	if (str)
		strcpy(buf, str);
	if (str && err != -1)
		strcat(buf, ": ");
	if (err != -1)
		strcat(buf, strerror(err));

	nputs(NodeId);
	nputs(" ");
	nputs(buf);
	nputs("\n");

	axio_flush(NodeIo);
	axio_eolmode(NodeIo, oldmode);
	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;
}

void put_prompt(void)
{
	char *p;

	if (strchr(NodePrompt, '%') == NULL) {
		nputs(NodePrompt);
		return;
	}
	p = expand_string(NodePrompt, 0, NULL);
	nputs(p);
	free(p);
}

void log(int loglevel, const char *fmt, ...)
{
	va_list args;
	int pri;
	static int opened = 0;

	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);
	vsprintf(buf, fmt, args);
	syslog(pri, buf);
	va_end(args);
}

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.0/etc/ 40755    764    764           0  6740167127  11002 5ustar  tpmtpmnode-0.3.0/etc/loggedin100644    764    764           0  6266456343  12524 0ustar  tpmtpmnode-0.3.0/etc/node.conf100644    764    764        3125  6740167036  12673 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.0/etc/node.perms100644    764    764         643  6330424573  13053 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.0/etc/help/ 40755    764    764           0  6425201307  11717 5ustar  tpmtpmnode-0.3.0/etc/help/bye.hlp100644    764    764         110  6266456343  13267 0ustar  tpmtpm
USAGE
        bye

DESCRIPTION
        Disconnects you from this node.
node-0.3.0/etc/help/connect.hlp100644    764    764        1746  6266456343  14201 0ustar  tpmtpm
USAGE
        connect <port> <call> [via <digi1> ...] [s|d]    For AX.25
        connect <call | alias> [s|d]                     For NET/ROM
	connect <call> <address> [<digi>] [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.0/etc/help/help.hlp100644    764    764         362  6266456343  13451 0ustar  tpmtpm
USAGE
        help [<command>]

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.0/etc/help/info.hlp100644    764    764         331  6300553463  13436 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.0/etc/help/mheard.hlp100644    764    764         260  6266456343  13756 0ustar  tpmtpm
USAGE
        mheard <port>

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.0/etc/help/finger.hlp100644    764    764         570  6266456343  13774 0ustar  tpmtpm
USAGE
        finger [<username>][@<hostname>]

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.0/etc/help/links.hlp100644    764    764         537  6270751314  13634 0ustar  tpmtpm
USAGE
        links [* | <call>]

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 <call>.
node-0.3.0/etc/help/nodes.hlp100644    764    764        1217  6266456343  13651 0ustar  tpmtpm
USAGE
        nodes [*|<nodecall>]

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.0/etc/help/ping.hlp100644    764    764         735  6266456343  13462 0ustar  tpmtpm
USAGE
        ping <hostname> [<length>]

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.0/etc/help/ports.hlp100644    764    764         641  6266456343  13670 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.0/etc/help/routes.hlp100644    764    764        1216  6266456343  14061 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.0/etc/help/telnet.hlp100644    764    764        1744  6266456343  14041 0ustar  tpmtpm
USAGE
        telnet <host> [<port>] [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.0/etc/help/users.hlp100644    764    764         277  6266456343  13667 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.0/etc/help/status.hlp100644    764    764        1023  6266456343  14057 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.0/etc/help/host.hlp100644    764    764         617  6266456343  13501 0ustar  tpmtpm
USAGE
        host <hostname>|<ip address>

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.0/etc/help/talk.hlp100644    764    764         754  6272432644  13454 0ustar  tpmtpm
USAGE
        talk <user> <message>

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.0/etc/help/escape.hlp100644    764    764        1101  6404550267  13763 0ustar  tpmtpm
USAGE
        escape <escape char>

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:

           <char> 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.0/etc/help/nlinks.hlp100644    764    764         213  6425171026  13777 0ustar  tpmtpm
USAGE
        nlinks

DESCRIPTION
        Gives a list of both active NET/ROM connections and NET/ROM
        sockets in listening state.
node-0.3.0/etc/help_french/ 40775    764    764           0  6404550637  13260 5ustar  tpmtpmnode-0.3.0/etc/help_french/bbs.hlp100644    764    764         102  6402074460  14570 0ustar  tpmtpm
USAGE
        bbs

DESCRIPTION
        Connexion au BBS F8KAE-1.
node-0.3.0/etc/help_french/bye.hlp100644    764    764         101  6402074460  14600 0ustar  tpmtpm
USAGE
        bye

DESCRIPTION
        Deconnexion de ce noeud.
node-0.3.0/etc/help_french/connect.hlp100644    764    764        2055  6402074460  15504 0ustar  tpmtpm
USAGE
        connect <port> <indicatif> [via <digi1> ...] [s|d]    Pour AX.25
        connect <indicatif | alias> [s|d]                     Pour NET/ROM
	connect <indicatif> <adresse> [<digi>] [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.0/etc/help_french/dx.hlp100644    764    764         111  6402074460  14435 0ustar  tpmtpm
USAGE
        dx

DESCRIPTION
        Connexion au PacketCluster F6BEE.
node-0.3.0/etc/help_french/escape.hlp100644    764    764        1203  6402074460  15305 0ustar  tpmtpm
USAGE
        escape <escape car>

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:

           <char> 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.0/etc/help_french/finger.hlp100644    764    764         622  6402074460  15303 0ustar  tpmtpm
USAGE
        finger [<utilisateur>][@<serveur>]

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.0/etc/help_french/help.hlp100644    764    764         426  6402074460  14763 0ustar  tpmtpm
USAGE
        help [<commande>]

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.0/etc/help_french/host.hlp100644    764    764         641  6402074460  15007 0ustar  tpmtpm
USAGE
        host <serveur>|<adresse ip>

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.0/etc/help_french/info.hlp100644    764    764         325  6402074460  14764 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.0/etc/help_french/links.hlp100644    764    764         603  6402074460  15150 0ustar  tpmtpm
USAGE
        links [* | <indicatif>]

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 <indicatif>.
node-0.3.0/etc/help_french/mheard.hlp100644    764    764         303  6402074460  15265 0ustar  tpmtpm
USAGE
        mheard <port>

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.0/etc/help_french/nodes.hlp100644    764    764        1424  6402074460  15162 0ustar  tpmtpm
USAGE
        nodes [*|<indicatif>]

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.0/etc/help_french/ping.hlp100644    764    764        1033  6402074460  15003 0ustar  tpmtpm
USAGE
        ping <serveur> [<longueur>]

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.0/etc/help_french/ports.hlp100644    764    764         735  6402074460  15205 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.0/etc/help_french/routes.hlp100644    764    764        1354  6402074460  15375 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.0/etc/help_french/status.hlp100644    764    764        1107  6402074460  15373 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.0/etc/help_french/talk.hlp100644    764    764        1037  6402074460  15005 0ustar  tpmtpm
USAGE
        talk <utilisateur> <message>

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.0/etc/help_french/telnet.hlp100644    764    764        2135  6402074460  15345 0ustar  tpmtpm
USAGE
        telnet <serveur> [<port>] [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.0/etc/help_french/users.hlp100644    764    764         302  6402074460  15165 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.0/etc/node.motd100644    764    764         136  6732001755  12664 0ustar  tpmtpm
Type ? for a list of commands. help <commandname> gives a description
of the named command.

node-0.3.0/ipc.c100644    764    764        5713  6707433742  11253 0ustar  tpmtpm#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>

#include "node.h"

/*
 * This one (c) 1996 by Heikki Hannikainen, OH7LZB <hessu@pspt.fi>
 */

#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) {
		node_msg(buf.mtext);
	} else
		log(L_ERROR, "usr2_handler: Catched 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, 7)) == -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, 7 | 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 <user> <message>");
		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));
	
	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.0/telnet.h100644    764    764        2746  6454011245  11770 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.0/AUTHORS100644    764    764         571  6724621236  11355 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

If you were accidentally left out, don't hesitate to email me.

-- 
Tomi Manninen OH2BNS, <tomi.manninen@hut.fi>
node-0.3.0/man/ 40755    764    764           0  6732000003  10756 5ustar  tpmtpmnode-0.3.0/man/node.8100644    764    764       20255  6731773020  12134 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 <port> <call> [via <call1> ...] [d|s]  For AX.25"
.TP 14
.BI "Connect <call | alias> [d|s]                   For NET/ROM"
.TP 14
.BI "Connect <call> <address> [<digi>] [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 <address> 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 [<escape string>]"
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 "<char>"
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 [<username>][@<hostname>]"
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 [<command>]"
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 <hostname> | <ip address>"
Give the Domain Name Service host name information about <hostname> or
<ip address>.
.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 [* | <call>]"
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 <call> as
source or destination address.
.TP 14
.BI "Mheard <portname>"
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 [* | <node>]"
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 <host> [<size>]"
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 <host> [<port>] [<string>] [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 <string> 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 <user> <message>"
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 <tpmannin@cc.hut.fi>
.br
Alan Cox GW4PTS <gw4pts@gw4pts.ampr.org>
node-0.3.0/man/node.conf.5100644    764    764       23653  6731777230  13071 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 <NAme> '<command> [<args...>]'
Sets up a command alias. The number of uppercase characters at the
beginning of <NAme> 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 <timeout>
When user is connected to another system via this system and the
connection is idle (no data flowing in either direction) for <timeout>
seconds the connection is dropped and user disconnected from node.
Default is 3600 seconds
(1 hour).
.TP 14
.B EscapeChar <escape string>
Specifies the escape character.
The escape string may be specified using any of the
well known codings:
.IP
.BI "<char>"
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 <NAme> <flags> <uid> <exec> <args...>
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 <NAme> 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 <portname> ...
Marks the AX.25 port <portname> 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 <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 <timeout>
After <timeout> seconds of inactivity while waiting for a command user
is disconnected from node. Default is 900 seconds (15 mins).
.TP 14
.B LocalNet <network>
Defines a "local" network. Users telneting from hosts in this network
are treated separately (see node.perms(5)). <network> 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 <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 <id>
This is the id that is shown in every message from node. Default
is "LinuxNode}".
.TP 14
.B NodePrompt <prompt>
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 <portname>
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.0/man/node.perms.5100644    764    764        5260  6731773313  13242 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.0/man/nodeusers.1100644    764    764        1573  6731773510  13175 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 <CR> as end-of-line. This is usefull
if nodeusers is called from ax25d.
.TP 10
.BI \-i
Tells nodeusers to use a <CR><LF> 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 <tpmannin@cc.hut.fi>
node-0.3.0/kernel_ax25.h100644    764    764       11420  6713361556  12634 0ustar  tpmtpm/* Copyright (C) 1997 Free Software Foundation, Inc.
   This file is part of the GNU C Library.

   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public License as
   published by the Free Software Foundation; either version 2 of the
   License, or (at your option) any later version.

   The GNU C Library 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
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public
   License along with the GNU C Library; see the file COPYING.LIB.  If not,
   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.  */

#ifndef _NETAX25_AX25_H
#define _NETAX25_AX25_H	1

#include <features.h>
#include <bits/sockaddr.h>

/* Setsockoptions(2) level.  Thanks to BSD these must match IPPROTO_xxx.  */
#define SOL_AX25	257

/* AX.25 flags: */
#define AX25_WINDOW	1
#define AX25_T1		2
#define AX25_T2		5
#define AX25_T3		4
#define AX25_N2		3
#define AX25_BACKOFF	6
#define AX25_EXTSEQ	7
#define AX25_IDLE	9
#define	AX25_PACLEN	10
#define AX25_IPMAXQUEUE 11
#define AX25_IAMDIGI	12
#define AX25_KILL	99

/* AX.25 socket ioctls: */
#define SIOCAX25GETUID		(SIOCPROTOPRIVATE)
#define SIOCAX25ADDUID		(SIOCPROTOPRIVATE+1)
#define SIOCAX25DELUID		(SIOCPROTOPRIVATE+2)
#define SIOCAX25NOUID		(SIOCPROTOPRIVATE+3)
#define SIOCAX25BPQADDR		(SIOCPROTOPRIVATE+4)
#define SIOCAX25GETPARMS	(SIOCPROTOPRIVATE+5)
#define SIOCAX25SETPARMS	(SIOCPROTOPRIVATE+6)
#define SIOCAX25OPTRT		(SIOCPROTOPRIVATE+7)
#define SIOCAX25CTLCON		(SIOCPROTOPRIVATE+8)
#define SIOCAX25GETINFO		(SIOCPROTOPRIVATE+9)
#define SIOCAX25ADDFWD		(SIOCPROTOPRIVATE+10)
#define SIOCAX25DELFWD		(SIOCPROTOPRIVATE+11)

/* unknown: */
#define AX25_NOUID_DEFAULT	0
#define AX25_NOUID_BLOCK	1
#define AX25_SET_RT_IPMODE	2

/* Digipeating flags: */
#define AX25_DIGI_INBAND	0x01	/* Allow digipeating within port */
#define AX25_DIGI_XBAND		0x02	/* Allow digipeating across ports */

/* Maximim number of digipeaters: */
#define AX25_MAX_DIGIS 8


typedef struct
  {
    char ax25_call[7];		/* 6 call + SSID (shifted ascii) */
  }
ax25_address;

struct sockaddr_ax25
  {
    sa_family_t sax25_family;
    ax25_address sax25_call;
    int sax25_ndigis;
  };

/*
 * The sockaddr struct with the digipeater adresses:
 */
struct full_sockaddr_ax25
  {
    struct sockaddr_ax25 fsa_ax25;
    ax25_address fsa_digipeater[AX25_MAX_DIGIS];
  };
#define sax25_uid	sax25_ndigis

struct ax25_routes_struct
  {
    ax25_address port_addr;
    ax25_address dest_addr;
    unsigned char digi_count;
    ax25_address digi_addr[AX25_MAX_DIGIS];
  };

/* The AX.25 ioctl structure: */
struct ax25_ctl_struct
  {
    ax25_address port_addr;
    ax25_address source_addr;
    ax25_address dest_addr;
    unsigned int cmd;
    unsigned long arg;
    unsigned char digi_count;
    ax25_address digi_addr[AX25_MAX_DIGIS];
  };

struct ax25_info_struct 
  {
    unsigned int  n2, n2count;
    unsigned int t1, t1timer;
    unsigned int t2, t2timer;
    unsigned int t3, t3timer;
    unsigned int idle, idletimer;
    unsigned int state;
    unsigned int rcv_q, snd_q;
  };

struct ax25_fwd_struct 
  {
    ax25_address port_from;
    ax25_address port_to;
  };

/* AX.25 route structure: */
struct ax25_route_opt_struct
  {
    ax25_address port_addr;
    ax25_address dest_addr;
    int cmd;
    int arg;
  };

/* AX.25 BPQ stuff: */
struct ax25_bpqaddr_struct
  {
    char dev[16];
    ax25_address addr;
  };

/* Definitions for the AX.25 `values' fields: */
#define	AX25_VALUES_IPDEFMODE	0	/* 'D'=DG 'V'=VC */
#define	AX25_VALUES_AXDEFMODE	1	/* 8=Normal 128=Extended Seq Nos */
#define	AX25_VALUES_NETROM	2	/* Allow NET/ROM  - 0=No 1=Yes */
#define	AX25_VALUES_TEXT	3	/* Allow PID=Text - 0=No 1=Yes */
#define	AX25_VALUES_BACKOFF	4	/* 'E'=Exponential 'L'=Linear */
#define	AX25_VALUES_CONMODE	5	/* Allow connected modes - 0=No 1=Yes */
#define	AX25_VALUES_WINDOW	6	/* Default window size for standard AX.25 */
#define	AX25_VALUES_EWINDOW	7	/* Default window size for extended AX.25 */
#define	AX25_VALUES_T1		8	/* Default T1 timeout value */
#define	AX25_VALUES_T2		9	/* Default T2 timeout value */
#define	AX25_VALUES_T3		10	/* Default T3 timeout value */
#define	AX25_VALUES_N2		11	/* Default N2 value */
#define	AX25_VALUES_DIGI	12	/* Digipeat mode */
#define AX25_VALUES_IDLE	13	/* mode vc idle timer */
#define AX25_VALUES_PACLEN	14	/* AX.25 MTU */
#define AX25_VALUES_IPMAXQUEUE  15	/* Maximum number of buffers enqueued */
#define	AX25_MAX_VALUES		20

struct ax25_parms_struct
  {
    ax25_address port_addr;
    unsigned 
Results 1 - 1
Help - FTP Sites List - Software Dir.
Searching half a billion files worldwide
© 1997-2009 MARUHN Internet Solutions