diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1999-04-21 09:51:03 +0200 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1999-04-21 09:51:03 +0200 |
commit | 17287576555a5c46fa23549e2e5f073660dccb70 (patch) | |
tree | 08be5f5005dad609a2803758b8b825170f6701cb /rose |
Import ax25-tools 0.0.1 from tarballax25-tools-0.0.1
Diffstat (limited to 'rose')
-rw-r--r-- | rose/Makefile.am | 19 | ||||
-rw-r--r-- | rose/Makefile.in | 471 | ||||
-rw-r--r-- | rose/rose.4 | 44 | ||||
-rw-r--r-- | rose/rsattach.8 | 33 | ||||
-rw-r--r-- | rose/rsattach.c | 219 | ||||
-rw-r--r-- | rose/rsdwnlnk.8 | 58 | ||||
-rw-r--r-- | rose/rsdwnlnk.c | 272 | ||||
-rw-r--r-- | rose/rsmemsiz.c | 204 | ||||
-rw-r--r-- | rose/rsparms.8 | 64 | ||||
-rw-r--r-- | rose/rsparms.c | 256 | ||||
-rw-r--r-- | rose/rsports | 7 | ||||
-rw-r--r-- | rose/rsports.5 | 52 | ||||
-rw-r--r-- | rose/rsuplnk.8 | 63 | ||||
-rw-r--r-- | rose/rsuplnk.c | 288 |
14 files changed, 2050 insertions, 0 deletions
diff --git a/rose/Makefile.am b/rose/Makefile.am new file mode 100644 index 0000000..3cbb2c8 --- /dev/null +++ b/rose/Makefile.am @@ -0,0 +1,19 @@ + +etcfiles = rsports +etcdir = $(sysconfdir)/ax25 + +installconf: + $(mkinstalldirs) $(DESTDIR)$(etcdir) + @list='$(etcfiles)'; for p in $$list; do \ + echo " $(INSTALL_DATA) $$p $(DESTDIR)$(etcdir)/$$p"; \ + $(INSTALL_DATA) $$p $(DESTDIR)$(etcdir)/$$p; \ + done + +sbin_PROGRAMS = rsattach rsdwnlnk rsmemsiz rsparms rsuplnk + +sbin_SCRIPTS = rsusers.sh + + +man_MANS = rose.4 rsports.5 rsattach.8 rsparms.8 rsdwnlnk.8 rsuplnk.8 + +EXTRA_DIST = $(man_MANS) $(etcfiles) diff --git a/rose/Makefile.in b/rose/Makefile.in new file mode 100644 index 0000000..0ded273 --- /dev/null +++ b/rose/Makefile.in @@ -0,0 +1,471 @@ +# Makefile.in generated automatically by automake 1.4 from Makefile.am + +# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +AWK = @AWK@ +CC = @CC@ +MAKEINFO = @MAKEINFO@ +NCURSES_LIB = @NCURSES_LIB@ +PACKAGE = @PACKAGE@ +VERSION = @VERSION@ + +etcfiles = rsports +etcdir = $(sysconfdir)/ax25 + +sbin_PROGRAMS = rsattach rsdwnlnk rsmemsiz rsparms rsuplnk + +sbin_SCRIPTS = rsusers.sh + +man_MANS = rose.4 rsports.5 rsattach.8 rsparms.8 rsdwnlnk.8 rsuplnk.8 + +EXTRA_DIST = $(man_MANS) $(etcfiles) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = ../config.h +CONFIG_CLEAN_FILES = +PROGRAMS = $(sbin_PROGRAMS) + + +DEFS = @DEFS@ -I. -I$(srcdir) -I.. +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +X_CFLAGS = @X_CFLAGS@ +X_LIBS = @X_LIBS@ +X_EXTRA_LIBS = @X_EXTRA_LIBS@ +X_PRE_LIBS = @X_PRE_LIBS@ +rsattach_SOURCES = rsattach.c +rsattach_OBJECTS = rsattach.o +rsattach_LDADD = $(LDADD) +rsattach_DEPENDENCIES = +rsattach_LDFLAGS = +rsdwnlnk_SOURCES = rsdwnlnk.c +rsdwnlnk_OBJECTS = rsdwnlnk.o +rsdwnlnk_LDADD = $(LDADD) +rsdwnlnk_DEPENDENCIES = +rsdwnlnk_LDFLAGS = +rsmemsiz_SOURCES = rsmemsiz.c +rsmemsiz_OBJECTS = rsmemsiz.o +rsmemsiz_LDADD = $(LDADD) +rsmemsiz_DEPENDENCIES = +rsmemsiz_LDFLAGS = +rsparms_SOURCES = rsparms.c +rsparms_OBJECTS = rsparms.o +rsparms_LDADD = $(LDADD) +rsparms_DEPENDENCIES = +rsparms_LDFLAGS = +rsuplnk_SOURCES = rsuplnk.c +rsuplnk_OBJECTS = rsuplnk.o +rsuplnk_LDADD = $(LDADD) +rsuplnk_DEPENDENCIES = +rsuplnk_LDFLAGS = +SCRIPTS = $(sbin_SCRIPTS) + +CFLAGS = @CFLAGS@ +COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ +man4dir = $(mandir)/man4 +man5dir = $(mandir)/man5 +man8dir = $(mandir)/man8 +MANS = $(man_MANS) + +NROFF = nroff +DIST_COMMON = Makefile.am Makefile.in + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP_ENV = --best +SOURCES = rsattach.c rsdwnlnk.c rsmemsiz.c rsparms.c rsuplnk.c +OBJECTS = rsattach.o rsdwnlnk.o rsmemsiz.o rsparms.o rsuplnk.o + +all: all-redirect +.SUFFIXES: +.SUFFIXES: .S .c .o .s +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps rose/Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + + +mostlyclean-sbinPROGRAMS: + +clean-sbinPROGRAMS: + -test -z "$(sbin_PROGRAMS)" || rm -f $(sbin_PROGRAMS) + +distclean-sbinPROGRAMS: + +maintainer-clean-sbinPROGRAMS: + +install-sbinPROGRAMS: $(sbin_PROGRAMS) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(sbindir) + @list='$(sbin_PROGRAMS)'; for p in $$list; do \ + if test -f $$p; then \ + echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(sbindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \ + $(INSTALL_PROGRAM) $$p $(DESTDIR)$(sbindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \ + else :; fi; \ + done + +uninstall-sbinPROGRAMS: + @$(NORMAL_UNINSTALL) + list='$(sbin_PROGRAMS)'; for p in $$list; do \ + rm -f $(DESTDIR)$(sbindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \ + done + +.c.o: + $(COMPILE) -c $< + +.s.o: + $(COMPILE) -c $< + +.S.o: + $(COMPILE) -c $< + +mostlyclean-compile: + -rm -f *.o core *.core + +clean-compile: + +distclean-compile: + -rm -f *.tab.c + +maintainer-clean-compile: + +rsattach: $(rsattach_OBJECTS) $(rsattach_DEPENDENCIES) + @rm -f rsattach + $(LINK) $(rsattach_LDFLAGS) $(rsattach_OBJECTS) $(rsattach_LDADD) $(LIBS) + +rsdwnlnk: $(rsdwnlnk_OBJECTS) $(rsdwnlnk_DEPENDENCIES) + @rm -f rsdwnlnk + $(LINK) $(rsdwnlnk_LDFLAGS) $(rsdwnlnk_OBJECTS) $(rsdwnlnk_LDADD) $(LIBS) + +rsmemsiz: $(rsmemsiz_OBJECTS) $(rsmemsiz_DEPENDENCIES) + @rm -f rsmemsiz + $(LINK) $(rsmemsiz_LDFLAGS) $(rsmemsiz_OBJECTS) $(rsmemsiz_LDADD) $(LIBS) + +rsparms: $(rsparms_OBJECTS) $(rsparms_DEPENDENCIES) + @rm -f rsparms + $(LINK) $(rsparms_LDFLAGS) $(rsparms_OBJECTS) $(rsparms_LDADD) $(LIBS) + +rsuplnk: $(rsuplnk_OBJECTS) $(rsuplnk_DEPENDENCIES) + @rm -f rsuplnk + $(LINK) $(rsuplnk_LDFLAGS) $(rsuplnk_OBJECTS) $(rsuplnk_LDADD) $(LIBS) + +install-sbinSCRIPTS: $(sbin_SCRIPTS) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(sbindir) + @list='$(sbin_SCRIPTS)'; for p in $$list; do \ + if test -f $$p; then \ + echo " $(INSTALL_SCRIPT) $$p $(DESTDIR)$(sbindir)/`echo $$p|sed '$(transform)'`"; \ + $(INSTALL_SCRIPT) $$p $(DESTDIR)$(sbindir)/`echo $$p|sed '$(transform)'`; \ + else if test -f $(srcdir)/$$p; then \ + echo " $(INSTALL_SCRIPT) $(srcdir)/$$p $(DESTDIR)$(sbindir)/`echo $$p|sed '$(transform)'`"; \ + $(INSTALL_SCRIPT) $(srcdir)/$$p $(DESTDIR)$(sbindir)/`echo $$p|sed '$(transform)'`; \ + else :; fi; fi; \ + done + +uninstall-sbinSCRIPTS: + @$(NORMAL_UNINSTALL) + list='$(sbin_SCRIPTS)'; for p in $$list; do \ + rm -f $(DESTDIR)$(sbindir)/`echo $$p|sed '$(transform)'`; \ + done + +install-man4: + $(mkinstalldirs) $(DESTDIR)$(man4dir) + @list='$(man4_MANS)'; \ + l2='$(man_MANS)'; for i in $$l2; do \ + case "$$i" in \ + *.4*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ + else file=$$i; fi; \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man4dir)/$$inst"; \ + $(INSTALL_DATA) $$file $(DESTDIR)$(man4dir)/$$inst; \ + done + +uninstall-man4: + @list='$(man4_MANS)'; \ + l2='$(man_MANS)'; for i in $$l2; do \ + case "$$i" in \ + *.4*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " rm -f $(DESTDIR)$(man4dir)/$$inst"; \ + rm -f $(DESTDIR)$(man4dir)/$$inst; \ + done + +install-man5: + $(mkinstalldirs) $(DESTDIR)$(man5dir) + @list='$(man5_MANS)'; \ + l2='$(man_MANS)'; for i in $$l2; do \ + case "$$i" in \ + *.5*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ + else file=$$i; fi; \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man5dir)/$$inst"; \ + $(INSTALL_DATA) $$file $(DESTDIR)$(man5dir)/$$inst; \ + done + +uninstall-man5: + @list='$(man5_MANS)'; \ + l2='$(man_MANS)'; for i in $$l2; do \ + case "$$i" in \ + *.5*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " rm -f $(DESTDIR)$(man5dir)/$$inst"; \ + rm -f $(DESTDIR)$(man5dir)/$$inst; \ + done + +install-man8: + $(mkinstalldirs) $(DESTDIR)$(man8dir) + @list='$(man8_MANS)'; \ + l2='$(man_MANS)'; for i in $$l2; do \ + case "$$i" in \ + *.8*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ + else file=$$i; fi; \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man8dir)/$$inst"; \ + $(INSTALL_DATA) $$file $(DESTDIR)$(man8dir)/$$inst; \ + done + +uninstall-man8: + @list='$(man8_MANS)'; \ + l2='$(man_MANS)'; for i in $$l2; do \ + case "$$i" in \ + *.8*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " rm -f $(DESTDIR)$(man8dir)/$$inst"; \ + rm -f $(DESTDIR)$(man8dir)/$$inst; \ + done +install-man: $(MANS) + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) install-man4 install-man5 install-man8 +uninstall-man: + @$(NORMAL_UNINSTALL) + $(MAKE) $(AM_MAKEFLAGS) uninstall-man4 uninstall-man5 uninstall-man8 + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + here=`pwd` && cd $(srcdir) \ + && mkid -f$$here/ID $$unique $(LISP) + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ + || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + -rm -f TAGS ID + +maintainer-clean-tags: + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) + +subdir = rose + +distdir: $(DISTFILES) + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + if test -d $$d/$$file; then \ + cp -pr $$/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done +rsattach.o: rsattach.c ../config.h ../pathnames.h +rsdwnlnk.o: rsdwnlnk.c ../config.h +rsmemsiz.o: rsmemsiz.c +rsparms.o: rsparms.c ../config.h ../pathnames.h +rsuplnk.o: rsuplnk.c ../config.h + +info-am: +info: info-am +dvi-am: +dvi: dvi-am +check-am: all-am +check: check-am +installcheck-am: +installcheck: installcheck-am +install-exec-am: install-sbinPROGRAMS install-sbinSCRIPTS +install-exec: install-exec-am + +install-data-am: install-man +install-data: install-data-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-am +uninstall-am: uninstall-sbinPROGRAMS uninstall-sbinSCRIPTS uninstall-man +uninstall: uninstall-am +all-am: Makefile $(PROGRAMS) $(SCRIPTS) $(MANS) +all-redirect: all-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install +installdirs: + $(mkinstalldirs) $(DESTDIR)$(sbindir) $(DESTDIR)$(sbindir) \ + $(DESTDIR)$(mandir)/man4 $(DESTDIR)$(mandir)/man5 \ + $(DESTDIR)$(mandir)/man8 + + +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: +mostlyclean-am: mostlyclean-sbinPROGRAMS mostlyclean-compile \ + mostlyclean-tags mostlyclean-generic + +mostlyclean: mostlyclean-am + +clean-am: clean-sbinPROGRAMS clean-compile clean-tags clean-generic \ + mostlyclean-am + +clean: clean-am + +distclean-am: distclean-sbinPROGRAMS distclean-compile distclean-tags \ + distclean-generic clean-am + +distclean: distclean-am + +maintainer-clean-am: maintainer-clean-sbinPROGRAMS \ + maintainer-clean-compile maintainer-clean-tags \ + maintainer-clean-generic distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +maintainer-clean: maintainer-clean-am + +.PHONY: mostlyclean-sbinPROGRAMS distclean-sbinPROGRAMS \ +clean-sbinPROGRAMS maintainer-clean-sbinPROGRAMS uninstall-sbinPROGRAMS \ +install-sbinPROGRAMS mostlyclean-compile distclean-compile \ +clean-compile maintainer-clean-compile uninstall-sbinSCRIPTS \ +install-sbinSCRIPTS install-man4 uninstall-man4 install-man5 \ +uninstall-man5 install-man8 uninstall-man8 install-man uninstall-man \ +tags mostlyclean-tags distclean-tags clean-tags maintainer-clean-tags \ +distdir info-am info dvi-am dvi check check-am installcheck-am \ +installcheck install-exec-am install-exec install-data-am install-data \ +install-am install uninstall-am uninstall all-redirect all-am all \ +installdirs mostlyclean-generic distclean-generic clean-generic \ +maintainer-clean-generic clean mostlyclean distclean maintainer-clean + + +installconf: + $(mkinstalldirs) $(DESTDIR)$(etcdir) + @list='$(etcfiles)'; for p in $$list; do \ + echo " $(INSTALL_DATA) $$p $(DESTDIR)$(etcdir)/$$p"; \ + $(INSTALL_DATA) $$p $(DESTDIR)$(etcdir)/$$p; \ + done + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/rose/rose.4 b/rose/rose.4 new file mode 100644 index 0000000..e02d3a4 --- /dev/null +++ b/rose/rose.4 @@ -0,0 +1,44 @@ +.TH ROSE 4 "27 August 1996" Linux "Linux Programmer's Manual" +.SH NAME +AF_ROSE \- Rose amateur packet radio protocol family +.SH DESCRIPTION +.LP +.B Rose +is a protocol used extensively by radio amateurs. The Linux +Rose protocol family permits access to these protocols via +the standard networking +.B socket +metaphor. +.LP +The Rose protocol layer only supports connected mode. +.LP +The only mode of operation is connected mode which is the mode used for a +socket of type SOCK_SEQPACKET (stream sockets are not available in Rose). +This requires that the user ensures output data is suitably packetised, and +that input data is read a packet at a time into a buffer of suitable size. +.LP +Rose addresses consist of 10 digits. These are encoded into a sockaddr_rose +structure which is provided to the relevant system calls. +.LP +Rose has some unusual properties. Notably in a multi-user system an AX.25 +address is often associated with a user, and some users may not have such an +association. a set of ioctl calls are provided to manage an association +table. +.LP +Rose supports the following socket options for SOL_ROSE. ROSE_T1 is the +T11/T21 timer in 1/10ths of a second, ROSE_T2 is the T12/T22 timer in +1/10ths of a second. ROSE_T3, is the T13/T23 timer in 1/10ths of a second. +It is possible for an application to request that the Rose layer return +the Rose header as well as the application data, this is done via the +ROSE_HDRINCL socket option. +.SH "SEE ALSO" +.BR call (1), +.BR socket (2), +.BR setsockopt(2), +.BR getsockopt(2), +.BR rsports (5), +.BR rsctl (8), +.BR rsparms (8). +.LP +.SH AUTHOR +Jonathan Naylor G4KLX <g4klx@g4klx.demon.co.uk> diff --git a/rose/rsattach.8 b/rose/rsattach.8 new file mode 100644 index 0000000..1a67769 --- /dev/null +++ b/rose/rsattach.8 @@ -0,0 +1,33 @@ +.TH RSATTACH 8 "27 August 1996" Linux "Linux System Managers Manual" +.SH NAME +rsattach \- Start a Rose interface +.SH SYNOPSIS +.B rsattach [-i inetaddr] [-v] port +.SH DESCRIPTION +.LP +.B Rsattach +takes many of the parameters for the port from the rsports(5) file. The port +argument is the name of a port as given in the rsports(5) file. +.LP +.B Rsattach +tries to find the free Rose device in the system. The device name checked is +rose0. If no free Rose device is available an error is generated and the +program terminates. +.SH OPTIONS +.TP 16 +.BI "\-i inetaddr" +Set the internet address of the interface. This address may either be a +dotted decimal address or a host name. +.TP 16 +.BI \-v +Display the version. +.SH "SEE ALSO" +.BR rose (4), +.BR rsparms (4), +.BR rsports (5), +.BR ifconfig (8). +.SH BUGS +The program can be run many times with the same arguments creating many +instances of the same attributes on different devices. Not a good idea. +.SH AUTHOR +Jonathan Naylor G4KLX <g4klx@g4klx.demon.co.uk> diff --git a/rose/rsattach.c b/rose/rsattach.c new file mode 100644 index 0000000..3d98858 --- /dev/null +++ b/rose/rsattach.c @@ -0,0 +1,219 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <termios.h> +#include <fcntl.h> +#include <signal.h> +#include <ctype.h> +#include <netdb.h> + +#include <sys/ioctl.h> + +#include <sys/socket.h> +/* #include <linux/netdevice.h> */ +#include <net/if.h> +#include <net/if_arp.h> +/* #include <linux/sockios.h> */ + +#include <netax25/ax25.h> +#include <netrose/rose.h> +#include <netax25/axlib.h> + +#include <config.h> + +#include "../pathnames.h" + +char *address; +int mtu = 128; + +int readconfig(char *port) +{ + FILE *fp; + char buffer[90], *s; + int n = 0; + + if ((fp = fopen(CONF_RSPORTS_FILE, "r")) == NULL) { + fprintf(stderr, "rsattach: cannot open rsports file\n"); + return FALSE; + } + + while (fgets(buffer, 90, fp) != NULL) { + n++; + + if ((s = strchr(buffer, '\n')) != NULL) + *s = '\0'; + + if (strlen(buffer) > 0 && *buffer == '#') + continue; + + if ((s = strtok(buffer, " \t\r\n")) == NULL) { + fprintf(stderr, "rsattach: unable to parse line %d of the rsports file\n", n); + return FALSE; + } + + if (strcmp(s, port) != 0) + continue; + + if ((s = strtok(NULL, " \t\r\n")) == NULL) { + fprintf(stderr, "rsattach: unable to parse line %d of the rsports file\n", n); + return FALSE; + } + + address = strdup(s); + + fclose(fp); + + return TRUE; + } + + fclose(fp); + + fprintf(stderr, "rsattach: cannot find port %s in rsports\n", port); + + return FALSE; +} + +int getfreedev(char *dev) +{ + struct ifreq ifr; + int fd; + int i; + + if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + perror("rsattach: socket"); + return FALSE; + } + + for (i = 0; i < 6; i++) { + sprintf(dev, "rose%d", i); + strcpy(ifr.ifr_name, dev); + + if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) { + perror("rsattach: SIOCGIFFLAGS"); + return FALSE; + } + + if (!(ifr.ifr_flags & IFF_UP)) { + close(fd); + return TRUE; + } + } + + close(fd); + + return FALSE; +} + +int startiface(char *dev, struct hostent *hp) +{ + struct ifreq ifr; + char addr[5]; + int fd; + + if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + perror("rsattach: socket"); + return FALSE; + } + + strcpy(ifr.ifr_name, dev); + + if (hp != NULL) { + ifr.ifr_addr.sa_family = AF_INET; + + ifr.ifr_addr.sa_data[0] = 0; + ifr.ifr_addr.sa_data[1] = 0; + ifr.ifr_addr.sa_data[2] = hp->h_addr_list[0][0]; + ifr.ifr_addr.sa_data[3] = hp->h_addr_list[0][1]; + ifr.ifr_addr.sa_data[4] = hp->h_addr_list[0][2]; + ifr.ifr_addr.sa_data[5] = hp->h_addr_list[0][3]; + ifr.ifr_addr.sa_data[6] = 0; + + if (ioctl(fd, SIOCSIFADDR, &ifr) < 0) { + perror("rsattach: SIOCSIFADDR"); + return FALSE; + } + } + + if (rose_aton(address, addr) == -1) + return FALSE; + + ifr.ifr_hwaddr.sa_family = ARPHRD_ROSE; + memcpy(ifr.ifr_hwaddr.sa_data, addr, 5); + + if (ioctl(fd, SIOCSIFHWADDR, &ifr) != 0) { + perror("rsattach: SIOCSIFHWADDR"); + return FALSE; + } + + ifr.ifr_mtu = mtu; + + if (ioctl(fd, SIOCSIFMTU, &ifr) < 0) { + perror("rsattach: SIOCSIFMTU"); + return FALSE; + } + + if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) { + perror("rsattach: SIOCGIFFLAGS"); + return FALSE; + } + + ifr.ifr_flags &= IFF_NOARP; + ifr.ifr_flags |= IFF_UP; + ifr.ifr_flags |= IFF_RUNNING; + + if (ioctl(fd, SIOCSIFFLAGS, &ifr) < 0) { + perror("rsattach: SIOCSIFFLAGS"); + return FALSE; + } + + close(fd); + + return TRUE; +} + + +int main(int argc, char *argv[]) +{ + int fd; + char dev[64]; + struct hostent *hp = NULL; + + while ((fd = getopt(argc, argv, "i:m:v")) != -1) { + switch (fd) { + case 'i': + if ((hp = gethostbyname(optarg)) == NULL) { + fprintf(stderr, "rsattach: invalid internet name/address - %s\n", optarg); + return 1; + } + break; + case 'v': + printf("rsattach: %s\n", VERSION); + return 0; + case ':': + case '?': + fprintf(stderr, "usage: rsattach [-i inetaddr] [-v] port\n"); + return 1; + } + } + + if ((argc - optind) != 1) { + fprintf(stderr, "usage: rsattach [-i inetaddr] [-v] port\n"); + return 1; + } + + if (!readconfig(argv[optind])) + return 1; + + if (!getfreedev(dev)) { + fprintf(stderr, "rsattach: cannot find free Rose device\n"); + return 1; + } + + if (!startiface(dev, hp)) + return 1; + + printf("Rose port %s bound to device %s\n", argv[optind], dev); + + return 0; +} diff --git a/rose/rsdwnlnk.8 b/rose/rsdwnlnk.8 new file mode 100644 index 0000000..f0d4c2d --- /dev/null +++ b/rose/rsdwnlnk.8 @@ -0,0 +1,58 @@ +.TH RSDWNLNK 8 "29 April 1997" Linux "Linux Programmer's Manual" +.SH NAME +rsdwnlnk \- User exit from the ROSE network. +.SH SYNOPSIS +.B rsdwnlnk <port> <call> +.SH DESCRIPTION +.LP +The +.B rdwnplnk +program allows a user to leave the ROSE network using the standard +pseudo-digipeating method. Recent Linux kernels are aware of this form of +operation and the +.B ax25d +program can create such connections. The normal mode of operation of a +ROSE switch is to have one ROSE address (ie port) per physical AX.25 port. +Therefore ROSE users coming in on a given ROSE port will come out of the +associated AX.25 port. +.LP +To use +.B rsdwnlnk +you need an entry in +.B ax25d.conf +to listen for incoming ROSE connections to any callsigns that are not +matched by the more specific ROSE entries. In the example below, I will be +listening for ROSE connections on my ROSE port rs144, the exiting AX.25 +connection will be via the associated AX.25 port, 144, using the callsign +KE4GAJ-10. Please note that the callsign should be on the same line as the +rest of the command, it may be wrapped onto the next line on your screen. +.LP +# +.br +{* VIA rs144} +.br +NOCALL * * * * * * L +.br +default * * * * * * - root /usr/sbin/rsdwnlnk rsdwnlnk 144 KE4GAJ-10 +.br +# +.LP +There would typically be one +.B rsdwnlnk +per ROSE port. The associated program for entering a ROSE network is +.B rsuplnk. +.LP +All errors generated by +.B rsdwnlnk +are written to the system debug log file. +.SH FILES +.br +/etc/ax25/axports +.SH "SEE ALSO" +.BR rose (4), +.BR ax25d.conf (5), +.BR ax25d (8), +.BR rsuplnk (8), +.BR rose_call (8). +.SH AUTHOR +Jonathan Naylor G4KLX <g4klx@g4klx.demon.co.uk> diff --git a/rose/rsdwnlnk.c b/rose/rsdwnlnk.c new file mode 100644 index 0000000..5729d99 --- /dev/null +++ b/rose/rsdwnlnk.c @@ -0,0 +1,272 @@ +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <errno.h> +#include <signal.h> +#include <syslog.h> + +#include <sys/time.h> +#include <sys/types.h> + +#include <sys/socket.h> +#include <netax25/ax25.h> +#include <netrose/rose.h> + +#include <netax25/axlib.h> +#include <netax25/axconfig.h> + +#include <config.h> + +#define AX25_HBIT 0x80 + +void alarm_handler(int sig) +{ +} + +int main(int argc, char **argv) +{ + unsigned char buffer[512], *addr; + fd_set read_fd; + int n = 0, s, addrlen, yes = 1; + struct full_sockaddr_ax25 axbind, axconnect; + struct sockaddr_rose rosesock, rosepeer; + + openlog("rsdwnlnk", LOG_PID, LOG_DAEMON); + + /* + * Arguments should be "rsdwnlnk ax25port ax25call" + */ + if (argc != 3) { + syslog(LOG_ERR, "invalid number of parameters\n"); + closelog(); + return 1; + } + + if (ax25_config_load_ports() == 0) { + syslog(LOG_ERR, "problem with axports file\n"); + closelog(); + return 1; + } + + addrlen = sizeof(struct sockaddr_rose); + + if (getsockname(STDIN_FILENO, (struct sockaddr *)&rosesock, &addrlen) == -1) { + syslog(LOG_ERR, "cannot getsockname - %s\n", strerror(errno)); + closelog(); + return 1; + } + + addrlen = sizeof(struct sockaddr_rose); + + if (getpeername(STDIN_FILENO, (struct sockaddr *)&rosepeer, &addrlen) == -1) { + syslog(LOG_ERR, "cannot getpeername - %s\n", strerror(errno)); + closelog(); + return 1; + } + + if (setsockopt(STDIN_FILENO, SOL_ROSE, ROSE_QBITINCL, &yes, sizeof(yes)) == -1) { + syslog(LOG_ERR, "cannot setsockopt(ROSE_QBITINCL) - %s\n", strerror(errno)); + closelog(); + return 1; + } + + /* + * Parse the passed values for correctness. + */ + axbind.fsa_ax25.sax25_family = AF_AX25; + axbind.fsa_ax25.sax25_ndigis = 1; + axbind.fsa_ax25.sax25_call = rosepeer.srose_call; + + if ((addr = ax25_config_get_addr(argv[1])) == NULL) { + syslog(LOG_ERR, "invalid AX.25 port name - %s\n", argv[1]); + closelog(); + return 1; + } + + if (ax25_aton_entry(addr, axbind.fsa_digipeater[0].ax25_call) == -1) { + syslog(LOG_ERR, "invalid AX.25 port callsign - %s\n", argv[1]); + closelog(); + return 1; + } + + axconnect.fsa_ax25.sax25_family = AF_AX25; + axconnect.fsa_ax25.sax25_call = rosesock.srose_call; + + /* + * The path at the far end has a digi in it. + */ + if (rosepeer.srose_ndigis == 1) { + axconnect.fsa_digipeater[n] = rosepeer.srose_digi; + axconnect.fsa_digipeater[n].ax25_call[6] |= AX25_HBIT; + n++; + } + + /* + * Incoming call has a different DNIC + */ + if (memcmp(rosepeer.srose_addr.rose_addr, rosesock.srose_addr.rose_addr, 2) != 0) { + addr = rose_ntoa(&rosepeer.srose_addr); + addr[4] = '\0'; + if (ax25_aton_entry(addr, axconnect.fsa_digipeater[n].ax25_call) == -1) { + syslog(LOG_ERR, "invalid callsign - %s\n", addr); + closelog(); + return 1; + } + axconnect.fsa_digipeater[n].ax25_call[6] |= AX25_HBIT; + n++; + } + + /* + * Put the remote address sans DNIC into the digi chain. + */ + addr = rose_ntoa(&rosepeer.srose_addr); + if (ax25_aton_entry(addr + 4, axconnect.fsa_digipeater[n].ax25_call) == -1) { + syslog(LOG_ERR, "invalid callsign - %s\n", addr + 4); + closelog(); + return 1; + } + axconnect.fsa_digipeater[n].ax25_call[6] |= AX25_HBIT; + n++; + + /* + * And my local ROSE callsign. + */ + if (ax25_aton_entry(argv[2], axconnect.fsa_digipeater[n].ax25_call) == -1) { + syslog(LOG_ERR, "invalid callsign - %s\n", argv[2]); + closelog(); + return 1; + } + axconnect.fsa_digipeater[n].ax25_call[6] |= AX25_HBIT; + n++; + + /* + * A digi has been specified for this end. + */ + if (rosesock.srose_ndigis == 1) { + axconnect.fsa_digipeater[n] = rosesock.srose_digi; + n++; + } + + axconnect.fsa_ax25.sax25_ndigis = n; + + addrlen = sizeof(struct full_sockaddr_ax25); + + /* + * Open the socket into the kernel. + */ + if ((s = socket(AF_AX25, SOCK_SEQPACKET, 0)) < 0) { + syslog(LOG_ERR, "cannot open AX.25 socket, %s\n", strerror(errno)); + closelog(); + return 1; + } +#ifdef HAVE_AX25_IAMDIGI + if (setsockopt(s, SOL_AX25, AX25_IAMDIGI, &yes, sizeof(yes)) == -1) { + syslog(LOG_ERR, "cannot setsockopt(AX25_IAMDIGI), %s\n", strerror(errno)); + close(s); + closelog(); + return 1; + } +#endif /* HAVE_AX25_IAMDIGI */ +#ifdef HAVE_AX25_PIDINCL + if (setsockopt(s, SOL_AX25, AX25_PIDINCL, &yes, sizeof(yes)) == -1) { + syslog(LOG_ERR, "cannot setsockopt(AX25_PIDINCL), %s\n", strerror(errno)); + close(s); + closelog(); + return 1; + } +#endif /* HAVE_AX25_PIDINCL */ + /* + * Set our AX.25 callsign and AX.25 port callsign accordingly. + */ + if (bind(s, (struct sockaddr *)&axbind, addrlen) != 0) { + syslog(LOG_ERR, "cannot bind AX.25 socket, %s\n", strerror(errno)); + close(s); + closelog(); + return 1; + } + + /* + * If no response in 60 seconds, go away. + */ + alarm(60); + + signal(SIGALRM, alarm_handler); + + /* + * Lets try and connect to the far end. + */ + if (connect(s, (struct sockaddr *)&axconnect, addrlen) != 0) { + switch (errno) { + case ECONNREFUSED: + strcpy(buffer, "*** Connection refused\r"); + break; + case ENETUNREACH: + strcpy(buffer, "*** No known route\r"); + break; + case EINTR: + strcpy(buffer, "*** Connection timed out\r"); + break; + default: + sprintf(buffer, "ERROR: cannot connect to AX.25 callsign, %s\r", strerror(errno)); + break; + } + + close(s); + + write(STDOUT_FILENO, buffer, strlen(buffer)); + + sleep(20); + + return 0; + } + + /* + * We got there. + */ + alarm(0); + + strcpy(buffer, "*** Connected\r"); + write(STDOUT_FILENO, buffer, strlen(buffer)); + + /* + * Loop until one end of the connection goes away. + */ + for (;;) { + FD_ZERO(&read_fd); + FD_SET(STDIN_FILENO, &read_fd); + FD_SET(s, &read_fd); + + select(s + 1, &read_fd, NULL, NULL, NULL); + + if (FD_ISSET(s, &read_fd)) { + if ((n = read(s, buffer + 2, 512)) == -1) + break; + if (buffer[2] == 0xF0) { + buffer[2] = 0; + write(STDOUT_FILENO, buffer + 2, n); + } else { + buffer[0] = 1; /* Set Q Bit on */ + buffer[1] = 0x7F; /* Q Bit escape */ + write(STDOUT_FILENO, buffer, n + 2); + } + } + + if (FD_ISSET(STDIN_FILENO, &read_fd)) { + if ((n = read(STDIN_FILENO, buffer, 512)) == -1) { + close(s); + break; + } + if (buffer[0] == 0) { /* Q Bit not set */ + buffer[0] = 0xF0; + write(s, buffer, n); + } else { + /* Lose the leading 0x7F */ + write(s, buffer + 2, n - 2); + } + } + } + + closelog(); + + return 0; +} diff --git a/rose/rsmemsiz.c b/rose/rsmemsiz.c new file mode 100644 index 0000000..6c1cec9 --- /dev/null +++ b/rose/rsmemsiz.c @@ -0,0 +1,204 @@ +#include <stdio.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <unistd.h> +#include <time.h> +#include <sys/utsname.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +enum meminfo_row { meminfo_main = 0, + meminfo_swap }; + +enum meminfo_col { meminfo_total = 0, meminfo_used, meminfo_free, + meminfo_shared, meminfo_buffers, meminfo_cached +}; + +unsigned read_total_main(void); + +/* + * This code is slightly modified from the procps package. + */ + +#define UPTIME_FILE "/proc/uptime" +#define LOADAVG_FILE "/proc/loadavg" +#define MEMINFO_FILE "/proc/meminfo" + +static char buf[300]; + +/* 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) { \ + fprintf(stdout, "ERROR: file %s, %s\r", FILE, strerror(errno)); \ + close(fd); \ + return 0; \ + } \ + lseek(fd, 0L, SEEK_SET); \ + if ((n = read(fd, buf, sizeof buf - 1)) < 0) { \ + fprintf(stdout, "ERROR: file %s, %s\r", FILE, strerror(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) { + fprintf(stdout, "ERROR: Bad data in %s\r", 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) { + fprintf(stdout, "ERROR: Bad data in %s\r", LOADAVG_FILE); + return 0; + } + SET_IF_DESIRED(av1, avg_1); + SET_IF_DESIRED(av5, avg_5); + SET_IF_DESIRED(av15, avg_15); + return 1; +} + +/* The following /proc/meminfo parsing routine assumes the following format: + [ <label> ... ] # header lines + [ <label> ] <num> [ <num> ... ] # table rows + [ repeats of above line ] + + Any lines with fewer <num>s than <label>s get trailing <num>s set to zero. + The return value is a NULL terminated unsigned** which is the table of + numbers without labels. Convenient enumeration constants for the major and + minor dimensions are available in the header file. Note that this version + requires that labels do not contain digits. It is readily extensible to + labels which do not *begin* with digits, though. +*/ + +#define MAX_ROW 3 /* these are a little liberal for flexibility */ +#define MAX_COL 7 + +unsigned** meminfo(void) { + static unsigned *row[MAX_ROW + 1]; /* row pointers */ + static unsigned num[MAX_ROW * MAX_COL]; /* number storage */ + char *p; + int i, j, k, l; + + FILE_TO_BUF(MEMINFO_FILE) + if (!row[0]) /* init ptrs 1st time through */ + for (i=0; i < MAX_ROW; i++) /* std column major order: */ + row[i] = num + MAX_COL*i; /* A[i][j] = A + COLS*i + j */ + p = buf; + for (i=0; i < MAX_ROW; i++) /* zero unassigned fields */ + for (j=0; j < MAX_COL; j++) + row[i][j] = 0; + for (i=0; i < MAX_ROW && *p; i++) { /* loop over rows */ + while(*p && !isdigit(*p)) p++; /* skip chars until a digit */ + for (j=0; j < MAX_COL && *p; j++) { /* scanf column-by-column */ + l = sscanf(p, "%u%n", row[i] + j, &k); + p += k; /* step over used buffer */ + if (*p == '\n' || l < 1) /* end of line/buffer */ + break; + } + } +/* row[i+1] = NULL; terminate the row list, currently unnecessary */ + return row; /* NULL return ==> error */ +} + + +/* + * by Heikki Hannikainen <hessu@pspt.fi> + * The following was mostly learnt from the procps package and the + * gnu sh-utils (mainly uname). + */ + +int main(int argc, char **argv) +{ + int upminutes, uphours, updays; + double uptime_secs, idle_secs; + double av[3]; + unsigned **mem; + char *p; + struct utsname name; + time_t t; + + fprintf(stdout, "Linux/ROSE 001. System parameters\r"); + + time(&t); + p = ctime(&t); + p[24] = '\r'; + fprintf(stdout, "System time: %s", p); + + if (uname(&name) == -1) + fprintf(stdout, "Cannot get system name\r"); + else { + fprintf(stdout, "Hostname: %s\r", name.nodename); + fprintf(stdout, "Operating system: %s %s (%s)\r", name.sysname, + name.release, name.machine); + } + + /* read and calculate the amount of uptime and format it nicely */ + uptime(&uptime_secs, &idle_secs); + updays = (int) uptime_secs / (60*60*24); + upminutes = (int) uptime_secs / 60; + uphours = upminutes / 60; + uphours = uphours % 24; + upminutes = upminutes % 60; + fprintf(stdout, "Uptime: "); + + if (updays) + fprintf(stdout, "%d day%s, ", updays, (updays != 1) ? "s" : ""); + + if (uphours) + fprintf(stdout, "%d hour%s ", uphours, (uphours != 1) ? "s" : ""); + fprintf(stdout, "%d minute%s\r", upminutes, (upminutes != 1) ? "s" : ""); + + loadavg(&av[0], &av[1], &av[2]); + fprintf(stdout, "Load average: %.2f, %.2f, %.2f\r", av[0], av[1], av[2]); + + if (!(mem = meminfo()) || mem[meminfo_main][meminfo_total] == 0) { + /* cannot normalize mem usage */ + fprintf(stdout, "Cannot get memory information!\r"); + } else { + fprintf(stdout, "Memory: %5d KB available, %5d KB used, %5d KB free\r", + mem[meminfo_main][meminfo_total] >> 10, + (mem[meminfo_main][meminfo_used] - + mem[meminfo_main][meminfo_buffers] - + mem[meminfo_total][meminfo_cached]) >> 10, + (mem[meminfo_main][meminfo_free] + + mem[meminfo_main][meminfo_buffers] + + mem[meminfo_total][meminfo_cached]) >> 10); + + fprintf(stdout, "Swap: %5d KB available, %5d KB used, %5d KB free\r", + mem[meminfo_swap][meminfo_total] >> 10, + mem[meminfo_swap][meminfo_used] >> 10, + mem[meminfo_swap][meminfo_free] >> 10); + } + + fprintf(stdout, "\r"); + fflush(stdout); + + while (1) { + if (read(STDIN_FILENO, av, 3) <= 0) + break; + } + + return 0; +} diff --git a/rose/rsparms.8 b/rose/rsparms.8 new file mode 100644 index 0000000..aeadc20 --- /dev/null +++ b/rose/rsparms.8 @@ -0,0 +1,64 @@ +.TH RSPARMS 8 "25 July 1997" Linux "Linux System Managers Manual" +.SH NAME +rsparms \- Configure the Rose interface. +.SH SYNOPSIS +.B rsparms -nodes add|del address[/mask] port neigh [digis...] +.LP +.B rsparms -nodes list +.LP +.B rsparms -call <callsign>|none +.LP +.B rsparms -version +.SH DESCRIPTION +.LP +This program is used to manipulate the routing tables of the Rose network +layer. To set up a new route to a Rose node in the routing tables you must +use the nodes option. All of the parameters are needed to add the node. It +is probably best to illustrate with an example: +.LP +.B rsparms -nodes add 2080192303 144 F1OAT-11 +.LP +This creates a new route to a distant node with the address 2080192303 and +the packets for that node should be sent on AX.25 port 144 to my immediate +neighbour F1OAT-11 without going through any digi-praters. For +example to set up the same node but via a digi-peater I would use: +.LP +.B rsparms -nodes add 2080192303 144 F1OAT-11 F6PRA-9 +.LP +It is also possible to remove a route to a distant node with the same +command except that the \(lqadd\(rq is replaced by a \(lqdel\(rq. The other +parameters must also be present. If the node has no other routes then the +node will be deleted, and the neighbour node that the connections go via may +also be deleted if no other node route uses it. +.LP +You may list the configured Rose routes using the following syntax: +.LP +.B rsparms -nodes list +.LP +This program may also be used to set up a common AX.25 level 2 callsign that +will be used for the ROSE node. By default no special level 2 callsign is +set, but setting it will replace any existing level 2 callsign and register +another one. Setting the callsign to \(lqnone\(rq will remove the level 2 +callsign. For example: +.LP +.B rsparms -call VK2KTJ-10 +.LP +would set the callsign used by Rose internode traffic to VK2KTJ-10. +.SH OPTIONS +.TP 10 +.BI \-version +Display the version information. +.SH FILES +.LP +/etc/ax25/axports +.br +/etc/ax25/rsports +.SH "SEE ALSO" +.BR call (1), +.BR rose (4), +.BR axports (5), +.BR rsports (5), +.BR rsctl (8), +.BR rsparms (8). +.SH AUTHOR +Jonathan Naylor G4KLX <g4klx@g4klx.demon.co.uk> diff --git a/rose/rsparms.c b/rose/rsparms.c new file mode 100644 index 0000000..86e0935 --- /dev/null +++ b/rose/rsparms.c @@ -0,0 +1,256 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <unistd.h> + +#include <sys/types.h> +#include <sys/ioctl.h> + +#include <sys/socket.h> +#include <netax25/ax25.h> +#include <netrose/rose.h> + +#include <netax25/axlib.h> +#include <netax25/axconfig.h> +#include <netax25/rsconfig.h> + +#include <config.h> + +#include "../pathnames.h" + +char nodes_usage[] = "usage: rsparms -node add|del nodeaddr[/mask] port neighbour [digis...]\n rsparms -node list\n"; + +/* print the Rose neighbour whose number is supplied */ +void printnb(char *neigh) +{ + FILE* fp; + char addr[10], callsign[10], port[10], digi[10]; + char buff[80]; + int args; + + if ((fp=fopen(PROC_RS_NEIGH_FILE,"r"))==NULL) { + fprintf(stderr,"rsparms: Couldn't open %s file\n",PROC_RS_NEIGH_FILE); + exit(1); + } + + while(fgets(buff, 80, fp)) { + addr[0]=(char)NULL; callsign[0]=(char)NULL; + port[0]=(char)NULL; digi[0]=(char)NULL; + + args=sscanf(buff,"%9s %9s %9s %*s %*s %*s %*s %*s %*s %9s",addr,callsign,port,digi); + + if (args==4) { /* We have a digi */ + if (strcmp(addr,neigh)==0) + printf("%-6s %-9s via %-9s",port,callsign,digi); + } else + if (args==3) { /* No digi */ + if (strcmp(addr,neigh)==0) + printf("%-6s %-9s",port,callsign); + } + } + fclose(fp); +} + +void nodes(int s, int argc, char *argv[]) +{ + struct rose_route_struct rs_node; + char *dev; + char *mask; + char nodeaddr[11]; + int i, n; + + FILE *fn; + char address[12], rmask[5], neigh1[10], neigh2[10], neigh3[10]; + char buff[80]; + int args; + + if (argc < 3) { + fprintf(stderr, nodes_usage); + exit(1); + } + + if (ax25_config_load_ports() == 0) { + fprintf(stderr, "rsparms: nodes: no AX.25 ports configured\n"); + exit(1); + } + + if (argv[2][0] != 'a' && argv[2][0] != 'd' && argv[2][0] != 'l') { + fprintf(stderr, "rsparms: nodes: invalid operation %s\n", argv[2]); + close(s); + exit(1); + } + + if (argv[2][0] == 'l') { + if ((fn=fopen(PROC_RS_NODES_FILE,"r"))==NULL) { + fprintf(stderr,"rsparms: Couldn't open %s file\n",PROC_RS_NODES_FILE); + exit(1); + } + + while(fgets(buff,80,fn)) { + args=sscanf(buff,"%10s %4s %*s %9s %9s %9s",address, rmask, neigh1, neigh2, neigh3); + if (strcmp(address,"address")==0) + continue; + + if (args>2) { + printf("%10s/%4s -> ",address,rmask); + printnb(neigh1); + putchar('\n'); + } + if (args>3) { + printf("%15s -> ",""); + printnb(neigh2); + putchar('\n'); + } + if (args>4) { + printf("%15s -> ",""); + printnb(neigh3); + putchar('\n'); + } + } + exit(0); + } + + if (argc < 6) { + fprintf(stderr, nodes_usage); + exit(1); + } + + if ((mask = strchr(argv[3], '/')) != NULL) { + *mask= (char)NULL; + mask++; + + if (sscanf(mask, "%hd", &rs_node.mask) != 1) { + fprintf(stderr, "rsparms: nodes: no mask supplied!\n"); + close(s); + exit(1); + } + + if (rs_node.mask > 10) { + fprintf(stderr, "rsparms: nodes: invalid mask size: %s\n", mask);; + close(s); + exit(1); + } + } else { + rs_node.mask = 10; + } + + /* Make all non significant digits equal to zero */ + strcpy(nodeaddr, argv[3]); + + for (i = rs_node.mask; i < 10; i++) + nodeaddr[i] = '0'; + + nodeaddr[i] = '\0'; + + if (rose_aton(nodeaddr, rs_node.address.rose_addr) != 0) { + fprintf(stderr, "rsparms: nodes: invalid address %s\n", nodeaddr); + close(s); + exit(1); + } + + if ((dev = ax25_config_get_dev(argv[4])) == NULL) { + fprintf(stderr, "rsparms: nodes: invalid port name - %s\n", argv[4]); + close(s); + exit(1); + } + + strcpy(rs_node.device, dev); + + if (ax25_aton_entry(argv[5], rs_node.neighbour.ax25_call) != 0) { + fprintf(stderr, "rsparms: nodes: invalid callsign %s\n", argv[5]); + close(s); + exit(1); + } + + for (i = 6, n = 0; i < argc && n < AX25_MAX_DIGIS; i++, n++) { + if (ax25_aton_entry(argv[i], rs_node.digipeaters[n].ax25_call) != 0) { + fprintf(stderr, "rsparms: nodes: invalid callsign %s\n", argv[i]); + close(s); + exit(1); + } + } + + rs_node.ndigis = n; + + if (argv[2][0] == 'a') { + if (ioctl(s, SIOCADDRT, &rs_node) == -1) { + perror("rsparms: SIOCADDRT"); + close(s); + exit(1); + } + } else { + if (ioctl(s, SIOCDELRT, &rs_node) == -1) { + perror("rsparms: SIOCDELRT"); + close(s); + exit(1); + } + } +} + + + + +int main(int argc, char *argv[]) +{ + ax25_address rose_call; + int s = 0; + + if (argc == 1) { + fprintf(stderr, "usage: rsparms -call|-nodes|-version ...\n"); + return 1; + } + + if (strncmp(argv[1], "-v", 2) == 0) { + printf("rsparms: %s\n", VERSION); + return 0; + } + + if (strncmp(argv[1], "-c", 2) == 0) { + if (argc < 3) { + fprintf(stderr, "usage: rsparms -call <callsign>|none\n"); + return 1; + } + + if (strcmp(argv[2], "none") != 0) { + if (ax25_aton_entry(argv[2], rose_call.ax25_call) == -1) { + fprintf(stderr, "rsparms: invalid callsign %s\n", argv[2]); + return 1; + } + } else { + rose_call = null_ax25_address; + } + + if ((s = socket(AF_ROSE, SOCK_SEQPACKET, 0)) < 0) { + perror("rsparms: socket"); + return 1; + } + + if (ioctl(s, SIOCRSL2CALL, &rose_call) == -1) { + perror("rsparms: ioctl"); + close(s); + return 1; + } + + close(s); + + return 0; + } + + if (strncmp(argv[1], "-n", 2) == 0) { + + if ((s = socket(AF_ROSE, SOCK_SEQPACKET, 0)) < 0) { + perror("rsparms: socket"); + return 1; + } + nodes(s, argc, argv); + close(s); + return 0; + } + + fprintf(stderr, "usage: rsparms -call|-nodes|-version ...\n"); + + close(s); + + return 1; +} diff --git a/rose/rsports b/rose/rsports new file mode 100644 index 0000000..8be51a0 --- /dev/null +++ b/rose/rsports @@ -0,0 +1,7 @@ +# /etc/ax25/rsports +# +# The format of this file is: +# +# name address description +# +rose 2080192203 Rose port diff --git a/rose/rsports.5 b/rose/rsports.5 new file mode 100644 index 0000000..44ce54e --- /dev/null +++ b/rose/rsports.5 @@ -0,0 +1,52 @@ +.TH RSPORTS 5 "27 August 1996" Linux "Linux Programmer's Manual" +.SH NAME +rsports \- Rose port configuration file. +.SH DESCRIPTION +.LP +.B Rsports +is an ASCII file that contains information about each of the Rose +ports that are to be used. When dealing with a Rose utility such as +.B call, +it takes an optional argument that is the port name. This port name is a +reference to the line within +.B rsports, +which has the same name. The information on each line contains +enough information to bind the command to a particular Rose +interface, this binding is done by matching the address on the line in +.B rsports +with the address of the port set by +.B ifconfig +or +.B rsattach. +.LP +The +.B rsports +file may contain comments that begin with a # in the first column, or a port +description in the following format, each field being delimited by white space: +.sp +.RS +name address description +.RE +.sp +The field descriptions are: +.sp +.RS +.TP 14 +.B name +this is the unique Rose port identifier. +.TP 14 +.B address +the address of the Rose interface to bind to. +.TP 14 +.B description +a free format description of this interface, this field extends to the end +of the line. It may contain spaces. +.RE +.SH FILES +.LP +/etc/ax25/rsports +.SH "SEE ALSO" +.BR call (1), +.BR rose (4), +.BR ifconfig (8), +.BR rsparms (8). diff --git a/rose/rsuplnk.8 b/rose/rsuplnk.8 new file mode 100644 index 0000000..b9a65f1 --- /dev/null +++ b/rose/rsuplnk.8 @@ -0,0 +1,63 @@ +.TH RSUPLNK 8 "29 April 1997" Linux "Linux Programmer's Manual" +.SH NAME +rsuplnk \- User entry into the ROSE network. +.SH SYNOPSIS +.B rsuplnk [-q] <port> +.SH DESCRIPTION +.LP +The +.B rsuplnk +program allows a user to gain entry into the ROSE network using the standard +pseudo-digipeating method. Recent Linux kernels are aware of this form +of operation and the +.B ax25d +program can listen for such connections. The normal mode of operation of a +ROSE switch is to have one ROSE address (ie port) per physical AX.25 port. +Therefore ROSE users coming in on a given AX.25 port will appear as if they +come from the associated ROSE port. This is the reason for the need for a +ROSE port as an argument. +.LP +To use +.B rsuplnk +you need an entry in +.B ax25d.conf +to listen for incoming connections. In the example below, I will be +listening for ROSE connections on my AX.25 port 144 using the callsign +KE4GAJ-10 and the ROSE port associated with the AX.25 port is rs144. +.LP +# +.br +[KE4GAJ-10* VIA 144] +.br +NOCALL * * * * * * L +.br +default * * * * * * - root /usr/sbin/rsuplnk rsuplnk rs144 +.br +# +.LP +There would typically be one +.B rsuplnk +per user access AX.25 port. The associated program for exiting a ROSE +network is +.B rsdwnlnk. +.LP +All errors generated by +.B rsuplnk +are written to the system debug log file. +.SH OPTIONS +.TP 8 +.BI \-q +Supresses the messages generated by +.B rsuplnk +when making the connection. +.SH FILES +.br +/etc/ax25/rsports +.SH "SEE ALSO" +.BR rose (4), +.BR ax25d.conf (5), +.BR ax25d (8), +.BR rsdwnlnk (8), +.BR rose_call (8). +.SH AUTHOR +Jonathan Naylor G4KLX <g4klx@g4klx.demon.co.uk> diff --git a/rose/rsuplnk.c b/rose/rsuplnk.c new file mode 100644 index 0000000..a024e20 --- /dev/null +++ b/rose/rsuplnk.c @@ -0,0 +1,288 @@ +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <errno.h> +#include <signal.h> +#include <syslog.h> + +#include <sys/time.h> +#include <sys/types.h> + +#include <sys/socket.h> +#include <netax25/ax25.h> +#include <netrose/rose.h> + +#include <netax25/axlib.h> +#include <netax25/axconfig.h> +#include <netax25/rsconfig.h> + +#include <config.h> + +void alarm_handler(int sig) +{ +} + +int main(int argc, char **argv) +{ + unsigned char buffer[512], *addr, *p; + char rose_address[11]; + fd_set read_fd; + int n, s, dnicindex = -1, addrindex = -1; + int addrlen, yes = 1, verbose = 1; + struct sockaddr_rose rosebind, roseconnect; + struct full_sockaddr_ax25 ax25sock, ax25peer; + + openlog("rsuplnk", LOG_PID, LOG_DAEMON); + + /* + * Arguments should be "rsuplnk [-q] roseport" + */ + if (argc > 2 && strcmp(argv[1], "-q") == 0) { + verbose = 0; + --argc; + ++argv; + } + + if (argc != 2) { + syslog(LOG_ERR, "invalid number of parameters\n"); + closelog(); + return 1; + } + + if (rs_config_load_ports() == 0) { + syslog(LOG_ERR, "problem with rsports file\n"); + closelog(); + return 1; + } + + addrlen = sizeof(struct full_sockaddr_ax25); + + if (getsockname(STDIN_FILENO, (struct sockaddr *)&ax25sock, &addrlen) == -1) { + syslog(LOG_ERR, "cannot getsockname, %s\n", strerror(errno)); + closelog(); + return 1; + } + + addrlen = sizeof(struct full_sockaddr_ax25); + + if (getpeername(STDIN_FILENO, (struct sockaddr *)&ax25peer, &addrlen) == -1) { + syslog(LOG_ERR, "cannot getpeername, %s\n", strerror(errno)); + closelog(); + return 1; + } +#ifdef HAVE_AX25_PIDINCL + if (setsockopt(STDIN_FILENO, SOL_AX25, AX25_PIDINCL, &yes, sizeof(yes)) == -1) { + syslog(LOG_ERR, "cannot setsockopt(AX25_PIDINCL) - %s\n", strerror(errno)); + closelog(); + return 1; + } +#endif /* HAVE_AX25_PIDINCL */ + roseconnect.srose_family = rosebind.srose_family = AF_ROSE; + roseconnect.srose_ndigis = rosebind.srose_ndigis = 0; + addrlen = sizeof(struct sockaddr_rose); + + if ((addr = rs_config_get_addr(argv[1])) == NULL) { + syslog(LOG_ERR, "invalid Rose port name - %s\n", argv[1]); + closelog(); + return 1; + } + + if (rose_aton(addr, rosebind.srose_addr.rose_addr) == -1) { + syslog(LOG_ERR, "invalid ROSE port address - %s\n", argv[1]); + closelog(); + return 1; + } + + /* + * Copy our DNIC in as default. + */ + memset(rose_address, 0x00, 11); + memcpy(rose_address, addr, 4); + + for (n = 0; n < ax25peer.fsa_ax25.sax25_ndigis; n++) { + addr = ax25_ntoa(&ax25peer.fsa_digipeater[n]); + + if (strspn(addr, "0123456789-") == strlen(addr)) { + if ((p = strchr(addr, '-')) != NULL) + *p = '\0'; + switch (strlen(addr)) { + case 4: + memcpy(rose_address + 0, addr, 4); + dnicindex = n; + break; + case 6: + memcpy(rose_address + 4, addr, 6); + addrindex = n; + break; + default: + break; + } + } + } + + /* + * The user didn't give an address. + */ + if (addrindex == -1) { + strcpy(buffer, "*** No ROSE address given\r"); + write(STDOUT_FILENO, buffer, strlen(buffer)); + sleep(20); + closelog(); + return 1; + } + + if (rose_aton(rose_address, roseconnect.srose_addr.rose_addr) == -1) { + syslog(LOG_ERR, "invalid Rose address - %s\n", argv[4]); + closelog(); + return 1; + } + + rosebind.srose_call = ax25peer.fsa_ax25.sax25_call; + + roseconnect.srose_call = ax25sock.fsa_ax25.sax25_call; + + /* + * A far end digipeater was specified. + */ + if (addrindex > 0) { + roseconnect.srose_ndigis = 1; + roseconnect.srose_digi = ax25peer.fsa_digipeater[addrindex - 1]; + } + + /* + * Check for a local digipeater. + */ + if (dnicindex != -1) { + if (ax25peer.fsa_ax25.sax25_ndigis - dnicindex > 2) { + rosebind.srose_ndigis = 1; + rosebind.srose_digi = ax25peer.fsa_digipeater[dnicindex + 2]; + } + } else { + if (ax25peer.fsa_ax25.sax25_ndigis - addrindex > 2) { + rosebind.srose_ndigis = 1; + rosebind.srose_digi = ax25peer.fsa_digipeater[addrindex + 2]; + } + } + + /* + * Open the socket into the kernel. + */ + if ((s = socket(AF_ROSE, SOCK_SEQPACKET, 0)) < 0) { + syslog(LOG_ERR, "cannot open ROSE socket, %s\n", strerror(errno)); + closelog(); + return 1; + } + + /* + * Set our AX.25 callsign and Rose address accordingly. + */ + if (bind(s, (struct sockaddr *)&rosebind, addrlen) != 0) { + syslog(LOG_ERR, "cannot bind ROSE socket, %s\n", strerror(errno)); + closelog(); + close(s); + return 1; + } + + if (setsockopt(s, SOL_ROSE, ROSE_QBITINCL, &yes, sizeof(yes)) == -1) { + syslog(LOG_ERR, "cannot setsockopt(ROSE_QBITINCL) - %s\n", strerror(errno)); + closelog(); + close(s); + return 1; + } + + if (verbose) { + strcpy(buffer, "*** Connection in progress\r"); + write(STDOUT_FILENO, buffer, strlen(buffer)); + } + + /* + * If no response in 5 minutes, go away. + */ + alarm(300); + + signal(SIGALRM, alarm_handler); + + /* + * Lets try and connect to the far end. + */ + if (connect(s, (struct sockaddr *)&roseconnect, addrlen) != 0) { + switch (errno) { + case ECONNREFUSED: + strcpy(buffer, "*** Disconnected - 0100 - Number Busy\r"); + break; + case ENETUNREACH: + strcpy(buffer, "*** Disconnected - 0D00 - Not Obtainable\r"); + break; + case EINTR: + strcpy(buffer, "*** Disconnected - 3900 - Ship Absent\r"); + break; + default: + sprintf(buffer, "*** Disconnected - %d - %s\r", errno, strerror(errno)); + break; + } + + close(s); + + if (verbose) { + write(STDOUT_FILENO, buffer, strlen(buffer)); + sleep(20); + } + + return 0; + } + + /* + * We got there. + */ + alarm(0); + + if (verbose) { + strcpy(buffer, "*** Connected\r"); + write(STDOUT_FILENO, buffer, strlen(buffer)); + } + + /* + * Loop until one end of the connection goes away. + */ + for (;;) { + FD_ZERO(&read_fd); + FD_SET(STDIN_FILENO, &read_fd); + FD_SET(s, &read_fd); + + select(s + 1, &read_fd, NULL, NULL, NULL); + + if (FD_ISSET(s, &read_fd)) { + if ((n = read(s, buffer, 512)) == -1) { + strcpy(buffer, "\r*** Disconnected - 0000 - DTE Originated\r"); + write(STDOUT_FILENO, buffer, strlen(buffer)); + break; + } + if (buffer[0] == 0) { /* Q Bit not set */ + buffer[0] = 0xF0; + write(STDOUT_FILENO, buffer, n); + } else { + /* Lose the leading 0x7F */ + write(STDOUT_FILENO, buffer + 2, n - 2); + } + } + + if (FD_ISSET(STDIN_FILENO, &read_fd)) { + if ((n = read(STDIN_FILENO, buffer + 2, 512)) == -1) { + close(s); + break; + } + if (buffer[2] == 0xF0) { + buffer[2] = 0; + write(s, buffer + 2, n); + } else { + buffer[0] = 1; /* Set Q bit on */ + buffer[1] = 0x7F; /* PID Escape */ + write(s, buffer, n + 2); + } + } + } + + closelog(); + + return 0; +} |