summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1999-04-21 09:51:03 +0200
committerRalf Baechle <ralf@linux-mips.org>1999-04-21 09:51:03 +0200
commit17287576555a5c46fa23549e2e5f073660dccb70 (patch)
tree08be5f5005dad609a2803758b8b825170f6701cb
Import ax25-tools 0.0.1 from tarballax25-tools-0.0.1
-rw-r--r--AUTHORS23
-rw-r--r--COPYING340
-rw-r--r--ChangeLog4
-rw-r--r--INSTALL18
-rw-r--r--Makefile.am11
-rw-r--r--Makefile.in358
-rw-r--r--NEWS3
-rw-r--r--README17
-rw-r--r--acconfig.h10
-rw-r--r--aclocal.m4127
-rw-r--r--ax25/Makefile.am38
-rw-r--r--ax25/Makefile.in563
-rw-r--r--ax25/ax25.477
-rw-r--r--ax25/ax25.profile2
-rw-r--r--ax25/ax25d.846
-rw-r--r--ax25/ax25d.c1195
-rw-r--r--ax25/ax25d.conf45
-rw-r--r--ax25/ax25d.conf.5269
-rw-r--r--ax25/axctl.867
-rw-r--r--ax25/axctl.c92
-rw-r--r--ax25/axparms.8119
-rw-r--r--ax25/axparms.c442
-rw-r--r--ax25/axports.562
-rw-r--r--ax25/axspawn.852
-rw-r--r--ax25/axspawn.c911
-rw-r--r--ax25/axspawn.conf25
-rw-r--r--ax25/axspawn.conf.575
-rw-r--r--ax25/beacon.851
-rw-r--r--ax25/beacon.c163
-rw-r--r--ax25/bpqparms.837
-rw-r--r--ax25/bpqparms.c146
-rw-r--r--ax25/mheard.174
-rw-r--r--ax25/mheard.c374
-rw-r--r--ax25/mheard.dat0
-rw-r--r--ax25/mheardd.842
-rw-r--r--ax25/mheardd.c436
-rw-r--r--ax25/rxecho.838
-rw-r--r--ax25/rxecho.c376
-rw-r--r--ax25/rxecho.conf12
-rw-r--r--ax25/rxecho.conf.522
-rw-r--r--config.h.in124
-rwxr-xr-xconfigure3654
-rw-r--r--configure.in58
-rw-r--r--hdlcutil/Makefile.am31
-rw-r--r--hdlcutil/Makefile.in403
-rw-r--r--hdlcutil/hdrvcomm.c663
-rw-r--r--hdlcutil/hdrvcomm.h109
-rw-r--r--hdlcutil/setcrystal.c136
-rw-r--r--hdlcutil/sethdlc.c598
-rw-r--r--hdlcutil/smdiag.c434
-rw-r--r--hdlcutil/smmixer.c781
-rw-r--r--hdlcutil/usersmdiag.h118
-rwxr-xr-xinstall-sh251
-rw-r--r--kiss/Makefile.am8
-rw-r--r--kiss/Makefile.in367
-rw-r--r--kiss/kissattach.c289
-rw-r--r--kiss/kissnetd.c257
-rw-r--r--kiss/kissparms.c221
-rw-r--r--kiss/mkiss.c512
-rw-r--r--kiss/net2kiss.c643
-rwxr-xr-xmissing190
-rwxr-xr-xmkinstalldirs40
-rw-r--r--netrom/Makefile.am26
-rw-r--r--netrom/Makefile.in452
-rw-r--r--netrom/netrom.451
-rw-r--r--netrom/netromd.897
-rw-r--r--netrom/netromd.c254
-rw-r--r--netrom/netromd.h41
-rw-r--r--netrom/netromr.c164
-rw-r--r--netrom/netromt.c268
-rw-r--r--netrom/nodesave.831
-rw-r--r--netrom/nodesave.c101
-rw-r--r--netrom/nrattach.839
-rw-r--r--netrom/nrattach.c240
-rw-r--r--netrom/nrbroadcast8
-rw-r--r--netrom/nrbroadcast.549
-rw-r--r--netrom/nrparms.876
-rw-r--r--netrom/nrparms.c239
-rw-r--r--netrom/nrports7
-rw-r--r--netrom/nrports.556
-rw-r--r--netrom/nrsdrv.844
-rw-r--r--netrom/nrsdrv.c457
-rw-r--r--rose/Makefile.am19
-rw-r--r--rose/Makefile.in471
-rw-r--r--rose/rose.444
-rw-r--r--rose/rsattach.833
-rw-r--r--rose/rsattach.c219
-rw-r--r--rose/rsdwnlnk.858
-rw-r--r--rose/rsdwnlnk.c272
-rw-r--r--rose/rsmemsiz.c204
-rw-r--r--rose/rsparms.864
-rw-r--r--rose/rsparms.c256
-rw-r--r--rose/rsports7
-rw-r--r--rose/rsports.552
-rw-r--r--rose/rsuplnk.863
-rw-r--r--rose/rsuplnk.c288
-rw-r--r--stamp-h.in1
-rw-r--r--tcpip/Makefile.am23
-rw-r--r--tcpip/Makefile.in386
-rw-r--r--tcpip/rip98.conf1
-rw-r--r--tcpip/rip98.conf.519
-rw-r--r--tcpip/rip98d.859
-rw-r--r--tcpip/rip98d.c360
-rw-r--r--tcpip/rip98d.h58
-rw-r--r--tcpip/rip98r.c255
-rw-r--r--tcpip/rip98t.c76
-rw-r--r--tcpip/ttylinkd.853
-rw-r--r--tcpip/ttylinkd.c719
-rw-r--r--tcpip/ttylinkd.conf10
-rw-r--r--tcpip/ttylinkd.conf.522
-rw-r--r--user_call/Makefile.am10
-rw-r--r--user_call/Makefile.in349
-rw-r--r--user_call/README59
-rw-r--r--user_call/ax25_call.c156
-rw-r--r--user_call/netrom_call.c165
-rw-r--r--user_call/rose_call.c162
116 files changed, 24342 insertions, 0 deletions
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..e71e95a
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,23 @@
+axspawn Joerg Reuter DL1BKE <jreuter@poboxes.com>
+ax25ipd Rob Mayfield VK5XXX <mayfieldrob@mail.dec.com>
+ax25rtd Klaus Kudielka <oe1kib@oe1xtu.ampr.org>
+bpqparms Joerg Reuter DL1BKE <jreuter@poboxes.com>
+call Alexander Tietzel DG6XA <tietze_a@etech.fh-hamburg.de>
+mkiss Tomi Manninen OH2BNS <tpmannin@cc.hut.fi>
+kissnetd Frederic Rible F1OAT <frible@teaser.fr>
+listen Heikki Hannikainen OH7LZB <hessu@pspt.fi>
+net2kiss Thomas Sailer HB9JNX <sailer@ife.ee.ethz.ch>
+node Tomi Manninen OH2BNS <tpmannin@cc.hut.fi>
+nodesave Tomi Manninen OH2BNS <tpmannin@cc.hut.fi>
+nrsdrv Dave Brown N2RJT <dcb@vectorbd.com>
+piconfig John Paul Morrison VE7JPM <jmorriso@bogomips.com>
+pms David Brown N2RJT <dcb@vectorbd.com>
+rxecho Tomi Manninen OH2BNS <tpmannin@cc.hut.fi>
+setcrystal Thomas Sailer HB9JNX <sailer@ife.ee.ethz.ch>
+sethdlc Thomas Sailer HB9JNX <sailer@ife.ee.ethz.ch>
+smdiag Thomas Sailer HB9JNX <sailer@ife.ee.ethz.ch>
+smmixer Thomas Sailer HB9JNX <sailer@ife.ee.ethz.ch>
+ttylinkd Craig Small VK2XLZ <csmall@small.dropbear.id.au>
+
+All others Jonathon Naylor G4KLX <g4klx@g4klx.demon.co.uk>
+
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..d60c31a
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 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
+
+ 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) <year> <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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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) year 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.
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..c154a78
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,4 @@
+1999-04-21 Craig Small <csmall@small.dropbear.id.au>
+
+ * Initial version from Terry Dawson's code, split from the old
+ ax25-utils package. Uses new ntoa aton calls.
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..e1fab66
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,18 @@
+Installation Instructions for AX.25 Tools
+=========================================
+
+To make this library you will need the following:
+ glibc2.1
+ A Modern kernel
+ libtool
+ ax25-lib 0.0.2 or better
+
+To build it you type:
+ ./configure
+ make
+ make install
+
+By default, it will install the files in /usr/local. To change this
+so that binaries go in /usr and the conf files go in /etc
+type 'make install prefix=/usr'
+
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..68f5e15
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,11 @@
+
+installconf:
+ @echo "**** WARNING - This will overwrite any existing files ****"
+ @echo "**** WARNING - This will overwrite any existing files ****"
+ @echo "**** WARNING - This will overwrite any existing files ****"
+ @echo
+ @echo Hit the return key to proceed, or ^C to exit.
+ @read
+ @for app in $(SUBDIRS); do $(MAKE) -C $$app installconf; done
+
+SUBDIRS = ax25 hdlcutil kiss netrom rose tcpip user_call
diff --git a/Makefile.in b/Makefile.in
new file mode 100644
index 0000000..dcdcc0e
--- /dev/null
+++ b/Makefile.in
@@ -0,0 +1,358 @@
+# 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@
+
+SUBDIRS = ax25 hdlcutil kiss netrom rose tcpip user_call
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = config.h
+CONFIG_CLEAN_FILES =
+DIST_COMMON = README ./stamp-h.in AUTHORS COPYING ChangeLog INSTALL \
+Makefile.am Makefile.in NEWS acconfig.h aclocal.m4 config.h.in \
+configure configure.in install-sh missing mkinstalldirs
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = tar
+GZIP_ENV = --best
+all: all-redirect
+.SUFFIXES:
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+ cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps Makefile
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) \
+ && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+$(ACLOCAL_M4): configure.in
+ cd $(srcdir) && $(ACLOCAL)
+
+config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ $(SHELL) ./config.status --recheck
+$(srcdir)/configure: $(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES)
+ cd $(srcdir) && $(AUTOCONF)
+
+config.h: stamp-h
+ @if test ! -f $@; then \
+ rm -f stamp-h; \
+ $(MAKE) stamp-h; \
+ else :; fi
+stamp-h: $(srcdir)/config.h.in $(top_builddir)/config.status
+ cd $(top_builddir) \
+ && CONFIG_FILES= CONFIG_HEADERS=config.h \
+ $(SHELL) ./config.status
+ @echo timestamp > stamp-h 2> /dev/null
+$(srcdir)/config.h.in: $(srcdir)/stamp-h.in
+ @if test ! -f $@; then \
+ rm -f $(srcdir)/stamp-h.in; \
+ $(MAKE) $(srcdir)/stamp-h.in; \
+ else :; fi
+$(srcdir)/stamp-h.in: $(top_srcdir)/configure.in $(ACLOCAL_M4) acconfig.h
+ cd $(top_srcdir) && $(AUTOHEADER)
+ @echo timestamp > $(srcdir)/stamp-h.in 2> /dev/null
+
+mostlyclean-hdr:
+
+clean-hdr:
+
+distclean-hdr:
+ -rm -f config.h
+
+maintainer-clean-hdr:
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+# (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+
+@SET_MAKE@
+
+all-recursive install-data-recursive install-exec-recursive \
+installdirs-recursive install-recursive uninstall-recursive \
+check-recursive installcheck-recursive info-recursive dvi-recursive:
+ @set fnord $(MAKEFLAGS); amf=$$2; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+mostlyclean-recursive clean-recursive distclean-recursive \
+maintainer-clean-recursive:
+ @set fnord $(MAKEFLAGS); amf=$$2; \
+ dot_seen=no; \
+ rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \
+ rev="$$subdir $$rev"; \
+ test "$$subdir" = "." && dot_seen=yes; \
+ done; \
+ test "$$dot_seen" = "no" && rev=". $$rev"; \
+ target=`echo $@ | sed s/-recursive//`; \
+ for subdir in $$rev; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
+ done && test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ done
+
+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: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ 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)config.h.in$$unique$(LISP)$$tags" \
+ || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags config.h.in $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+ -rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(PACKAGE)-$(VERSION)
+top_distdir = $(distdir)
+
+# This target untars the dist file and tries a VPATH configuration. Then
+# it guarantees that the distribution is self-contained by making another
+# tarfile.
+distcheck: dist
+ -rm -rf $(distdir)
+ GZIP=$(GZIP_ENV) $(TAR) zxf $(distdir).tar.gz
+ mkdir $(distdir)/=build
+ mkdir $(distdir)/=inst
+ dc_install_base=`cd $(distdir)/=inst && pwd`; \
+ cd $(distdir)/=build \
+ && ../configure --srcdir=.. --prefix=$$dc_install_base \
+ && $(MAKE) $(AM_MAKEFLAGS) \
+ && $(MAKE) $(AM_MAKEFLAGS) dvi \
+ && $(MAKE) $(AM_MAKEFLAGS) check \
+ && $(MAKE) $(AM_MAKEFLAGS) install \
+ && $(MAKE) $(AM_MAKEFLAGS) installcheck \
+ && $(MAKE) $(AM_MAKEFLAGS) dist
+ -rm -rf $(distdir)
+ @banner="$(distdir).tar.gz is ready for distribution"; \
+ dashes=`echo "$$banner" | sed s/./=/g`; \
+ echo "$$dashes"; \
+ echo "$$banner"; \
+ echo "$$dashes"
+dist: distdir
+ -chmod -R a+r $(distdir)
+ GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir)
+ -rm -rf $(distdir)
+dist-all: distdir
+ -chmod -R a+r $(distdir)
+ GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir)
+ -rm -rf $(distdir)
+distdir: $(DISTFILES)
+ -rm -rf $(distdir)
+ mkdir $(distdir)
+ -chmod 777 $(distdir)
+ @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
+ for subdir in $(SUBDIRS); do \
+ if test "$$subdir" = .; then :; else \
+ test -d $(distdir)/$$subdir \
+ || mkdir $(distdir)/$$subdir \
+ || exit 1; \
+ chmod 777 $(distdir)/$$subdir; \
+ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir=../$(distdir) distdir=../$(distdir)/$$subdir distdir) \
+ || exit 1; \
+ fi; \
+ done
+info-am:
+info: info-recursive
+dvi-am:
+dvi: dvi-recursive
+check-am: all-am
+check: check-recursive
+installcheck-am:
+installcheck: installcheck-recursive
+all-recursive-am: config.h
+ $(MAKE) $(AM_MAKEFLAGS) all-recursive
+
+install-exec-am:
+install-exec: install-exec-recursive
+
+install-data-am:
+install-data: install-data-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-recursive
+uninstall-am:
+uninstall: uninstall-recursive
+all-am: Makefile config.h
+all-redirect: all-recursive-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+installdirs: installdirs-recursive
+installdirs-am:
+
+
+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-hdr mostlyclean-tags mostlyclean-generic
+
+mostlyclean: mostlyclean-recursive
+
+clean-am: clean-hdr clean-tags clean-generic mostlyclean-am
+
+clean: clean-recursive
+
+distclean-am: distclean-hdr distclean-tags distclean-generic clean-am
+
+distclean: distclean-recursive
+ -rm -f config.status
+
+maintainer-clean-am: maintainer-clean-hdr 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-recursive
+ -rm -f config.status
+
+.PHONY: mostlyclean-hdr distclean-hdr clean-hdr maintainer-clean-hdr \
+install-data-recursive uninstall-data-recursive install-exec-recursive \
+uninstall-exec-recursive installdirs-recursive uninstalldirs-recursive \
+all-recursive check-recursive installcheck-recursive info-recursive \
+dvi-recursive mostlyclean-recursive distclean-recursive clean-recursive \
+maintainer-clean-recursive tags tags-recursive mostlyclean-tags \
+distclean-tags clean-tags maintainer-clean-tags distdir info-am info \
+dvi-am dvi check check-am installcheck-am installcheck all-recursive-am \
+install-exec-am install-exec install-data-am install-data install-am \
+install uninstall-am uninstall all-redirect all-am all installdirs-am \
+installdirs mostlyclean-generic distclean-generic clean-generic \
+maintainer-clean-generic clean mostlyclean distclean maintainer-clean
+
+
+installconf:
+ @echo "**** WARNING - This will overwrite any existing files ****"
+ @echo "**** WARNING - This will overwrite any existing files ****"
+ @echo "**** WARNING - This will overwrite any existing files ****"
+ @echo
+ @echo Hit the return key to proceed, or ^C to exit.
+ @read
+ @for app in $(SUBDIRS); do $(MAKE) -C $$app installconf; 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/NEWS b/NEWS
new file mode 100644
index 0000000..51c9a85
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,3 @@
+This is some news about ax25-tools
+
+
diff --git a/README b/README
new file mode 100644
index 0000000..0a8e484
--- /dev/null
+++ b/README
@@ -0,0 +1,17 @@
+AX25 Tools
+==========
+
+THESE TOOLS ARE ALPHA CODE AND IS ONLY BEEN RELEASE FOR DEVELOPERS FOR
+DEBUGGING.
+
+This means if you are only installing this because it is the latest
+and greatest and you don't understand how to diagnose bugs, then you
+should probably not run it and go back to the ax25-utils-2*
+packages.
+
+You are supposed to use glibc 2.1 (libc6 unstable libraries) for this
+package. I have attempted to cater for glibc 2.0 users here.
+
+ - Craig Small <csmall@small.dropbear.id.au>
+
+
diff --git a/acconfig.h b/acconfig.h
new file mode 100644
index 0000000..4498431
--- /dev/null
+++ b/acconfig.h
@@ -0,0 +1,10 @@
+
+#undef HAVE_AX25_FWD_STRUCT
+
+#undef HAVE_AX25_IAMDIGI
+#undef HAVE_AX25_PIDINCL
+
+/* #undef PACKAGE */
+/* #undef VERSION */
+
+
diff --git a/aclocal.m4 b/aclocal.m4
new file mode 100644
index 0000000..f23ba29
--- /dev/null
+++ b/aclocal.m4
@@ -0,0 +1,127 @@
+dnl aclocal.m4 generated automatically by aclocal 1.4
+
+dnl Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+dnl PARTICULAR PURPOSE.
+
+# Do all the work for Automake. This macro actually does too much --
+# some checks are only needed if your package does certain things.
+# But this isn't really a big deal.
+
+# serial 1
+
+dnl Usage:
+dnl AM_INIT_AUTOMAKE(package,version, [no-define])
+
+AC_DEFUN(AM_INIT_AUTOMAKE,
+[AC_REQUIRE([AC_PROG_INSTALL])
+PACKAGE=[$1]
+AC_SUBST(PACKAGE)
+VERSION=[$2]
+AC_SUBST(VERSION)
+dnl test to see if srcdir already configured
+if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then
+ AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
+fi
+ifelse([$3],,
+AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
+AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package]))
+AC_REQUIRE([AM_SANITY_CHECK])
+AC_REQUIRE([AC_ARG_PROGRAM])
+dnl FIXME This is truly gross.
+missing_dir=`cd $ac_aux_dir && pwd`
+AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir)
+AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir)
+AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir)
+AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir)
+AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir)
+AC_REQUIRE([AC_PROG_MAKE_SET])])
+
+#
+# Check to make sure that the build environment is sane.
+#
+
+AC_DEFUN(AM_SANITY_CHECK,
+[AC_MSG_CHECKING([whether build environment is sane])
+# Just in case
+sleep 1
+echo timestamp > conftestfile
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments. Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+ set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null`
+ if test "[$]*" = "X"; then
+ # -L didn't work.
+ set X `ls -t $srcdir/configure conftestfile`
+ fi
+ if test "[$]*" != "X $srcdir/configure conftestfile" \
+ && test "[$]*" != "X conftestfile $srcdir/configure"; then
+
+ # If neither matched, then we have a broken ls. This can happen
+ # if, for instance, CONFIG_SHELL is bash and it inherits a
+ # broken ls alias from the environment. This has actually
+ # happened. Such a system could not be considered "sane".
+ AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken
+alias in your environment])
+ fi
+
+ test "[$]2" = conftestfile
+ )
+then
+ # Ok.
+ :
+else
+ AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+rm -f conftest*
+AC_MSG_RESULT(yes)])
+
+dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY)
+dnl The program must properly implement --version.
+AC_DEFUN(AM_MISSING_PROG,
+[AC_MSG_CHECKING(for working $2)
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf. Sigh.
+if ($2 --version) < /dev/null > /dev/null 2>&1; then
+ $1=$2
+ AC_MSG_RESULT(found)
+else
+ $1="$3/missing $2"
+ AC_MSG_RESULT(missing)
+fi
+AC_SUBST($1)])
+
+# Like AC_CONFIG_HEADER, but automatically create stamp file.
+
+AC_DEFUN(AM_CONFIG_HEADER,
+[AC_PREREQ([2.12])
+AC_CONFIG_HEADER([$1])
+dnl When config.status generates a header, we must update the stamp-h file.
+dnl This file resides in the same directory as the config header
+dnl that is generated. We must strip everything past the first ":",
+dnl and everything past the last "/".
+AC_OUTPUT_COMMANDS(changequote(<<,>>)dnl
+ifelse(patsubst(<<$1>>, <<[^ ]>>, <<>>), <<>>,
+<<test -z "<<$>>CONFIG_HEADERS" || echo timestamp > patsubst(<<$1>>, <<^\([^:]*/\)?.*>>, <<\1>>)stamp-h<<>>dnl>>,
+<<am_indx=1
+for am_file in <<$1>>; do
+ case " <<$>>CONFIG_HEADERS " in
+ *" <<$>>am_file "*<<)>>
+ echo timestamp > `echo <<$>>am_file | sed -e 's%:.*%%' -e 's%[^/]*$%%'`stamp-h$am_indx
+ ;;
+ esac
+ am_indx=`expr "<<$>>am_indx" + 1`
+done<<>>dnl>>)
+changequote([,]))])
+
diff --git a/ax25/Makefile.am b/ax25/Makefile.am
new file mode 100644
index 0000000..55dc33d
--- /dev/null
+++ b/ax25/Makefile.am
@@ -0,0 +1,38 @@
+
+etcfiles = ax25.profile ax25d.conf axspawn.conf rxecho.conf
+varfiles = mheard.dat
+
+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
+ $(mkinstalldirs) $(DESTDIR)$(vardir)
+ @list='$(varfiles)'; for p in $$list; do \
+ echo " $(INSTALL_DATA) $$p $(DESTDIR)$(vardir)/$$p"; \
+ $(INSTALL_DATA) $$p $(DESTDIR)$(vardir)/$$p; \
+ done
+
+
+sbin_PROGRAMS = ax25d axctl axparms axspawn beacon bpqparms mheardd rxecho
+
+bin_PROGRAMS = mheard
+
+man_MANS = ax25.4 ax25d.conf.5 axports.5 axspawn.conf.5 rxecho.conf.5 \
+ ax25d.8 axctl.8 axparms.8 axspawn.8 beacon.8 bpqparms.8 \
+ mheard.1 mheardd.8 rxecho.8
+
+
+
+EXTRA_DIST = $(man_MANS) $(etcfiles) $(varfiles)
+
+ax25d_SOURCES = ax25d.c
+axctl_SOURCES = axctl.c
+axparms_SOURCES = axparms.c
+axspawn_SOURCES = axspawn.c
+beacon_SOURCES = beacon.c
+bpqparms_SOURCES = bpqparms.c
+mheard_SOURCES = mheard.c
+mheardd_SOURCES = mheardd.c
+rxecho_SOURCES = rxecho.c
diff --git a/ax25/Makefile.in b/ax25/Makefile.in
new file mode 100644
index 0000000..ef14c64
--- /dev/null
+++ b/ax25/Makefile.in
@@ -0,0 +1,563 @@
+# 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 = ax25.profile ax25d.conf axspawn.conf rxecho.conf
+varfiles = mheard.dat
+
+sbin_PROGRAMS = ax25d axctl axparms axspawn beacon bpqparms mheardd rxecho
+
+bin_PROGRAMS = mheard
+
+man_MANS = ax25.4 ax25d.conf.5 axports.5 axspawn.conf.5 rxecho.conf.5 ax25d.8 axctl.8 axparms.8 axspawn.8 beacon.8 bpqparms.8 mheard.1 mheardd.8 rxecho.8
+
+
+EXTRA_DIST = $(man_MANS) $(etcfiles) $(varfiles)
+
+ax25d_SOURCES = ax25d.c
+axctl_SOURCES = axctl.c
+axparms_SOURCES = axparms.c
+axspawn_SOURCES = axspawn.c
+beacon_SOURCES = beacon.c
+bpqparms_SOURCES = bpqparms.c
+mheard_SOURCES = mheard.c
+mheardd_SOURCES = mheardd.c
+rxecho_SOURCES = rxecho.c
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../config.h
+CONFIG_CLEAN_FILES =
+PROGRAMS = $(bin_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@
+mheard_OBJECTS = mheard.o
+mheard_LDADD = $(LDADD)
+mheard_DEPENDENCIES =
+mheard_LDFLAGS =
+ax25d_OBJECTS = ax25d.o
+ax25d_LDADD = $(LDADD)
+ax25d_DEPENDENCIES =
+ax25d_LDFLAGS =
+axctl_OBJECTS = axctl.o
+axctl_LDADD = $(LDADD)
+axctl_DEPENDENCIES =
+axctl_LDFLAGS =
+axparms_OBJECTS = axparms.o
+axparms_LDADD = $(LDADD)
+axparms_DEPENDENCIES =
+axparms_LDFLAGS =
+axspawn_OBJECTS = axspawn.o
+axspawn_LDADD = $(LDADD)
+axspawn_DEPENDENCIES =
+axspawn_LDFLAGS =
+beacon_OBJECTS = beacon.o
+beacon_LDADD = $(LDADD)
+beacon_DEPENDENCIES =
+beacon_LDFLAGS =
+bpqparms_OBJECTS = bpqparms.o
+bpqparms_LDADD = $(LDADD)
+bpqparms_DEPENDENCIES =
+bpqparms_LDFLAGS =
+mheardd_OBJECTS = mheardd.o
+mheardd_LDADD = $(LDADD)
+mheardd_DEPENDENCIES =
+mheardd_LDFLAGS =
+rxecho_OBJECTS = rxecho.o
+rxecho_LDADD = $(LDADD)
+rxecho_DEPENDENCIES =
+rxecho_LDFLAGS =
+CFLAGS = @CFLAGS@
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+man1dir = $(mandir)/man1
+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 = $(mheard_SOURCES) $(ax25d_SOURCES) $(axctl_SOURCES) $(axparms_SOURCES) $(axspawn_SOURCES) $(beacon_SOURCES) $(bpqparms_SOURCES) $(mheardd_SOURCES) $(rxecho_SOURCES)
+OBJECTS = $(mheard_OBJECTS) $(ax25d_OBJECTS) $(axctl_OBJECTS) $(axparms_OBJECTS) $(axspawn_OBJECTS) $(beacon_OBJECTS) $(bpqparms_OBJECTS) $(mheardd_OBJECTS) $(rxecho_OBJECTS)
+
+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 ax25/Makefile
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-binPROGRAMS:
+
+clean-binPROGRAMS:
+ -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+
+distclean-binPROGRAMS:
+
+maintainer-clean-binPROGRAMS:
+
+install-binPROGRAMS: $(bin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ $(mkinstalldirs) $(DESTDIR)$(bindir)
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
+ if test -f $$p; then \
+ echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \
+ $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+ else :; fi; \
+ done
+
+uninstall-binPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ list='$(bin_PROGRAMS)'; for p in $$list; do \
+ rm -f $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+ done
+
+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:
+
+mheard: $(mheard_OBJECTS) $(mheard_DEPENDENCIES)
+ @rm -f mheard
+ $(LINK) $(mheard_LDFLAGS) $(mheard_OBJECTS) $(mheard_LDADD) $(LIBS)
+
+ax25d: $(ax25d_OBJECTS) $(ax25d_DEPENDENCIES)
+ @rm -f ax25d
+ $(LINK) $(ax25d_LDFLAGS) $(ax25d_OBJECTS) $(ax25d_LDADD) $(LIBS)
+
+axctl: $(axctl_OBJECTS) $(axctl_DEPENDENCIES)
+ @rm -f axctl
+ $(LINK) $(axctl_LDFLAGS) $(axctl_OBJECTS) $(axctl_LDADD) $(LIBS)
+
+axparms: $(axparms_OBJECTS) $(axparms_DEPENDENCIES)
+ @rm -f axparms
+ $(LINK) $(axparms_LDFLAGS) $(axparms_OBJECTS) $(axparms_LDADD) $(LIBS)
+
+axspawn: $(axspawn_OBJECTS) $(axspawn_DEPENDENCIES)
+ @rm -f axspawn
+ $(LINK) $(axspawn_LDFLAGS) $(axspawn_OBJECTS) $(axspawn_LDADD) $(LIBS)
+
+beacon: $(beacon_OBJECTS) $(beacon_DEPENDENCIES)
+ @rm -f beacon
+ $(LINK) $(beacon_LDFLAGS) $(beacon_OBJECTS) $(beacon_LDADD) $(LIBS)
+
+bpqparms: $(bpqparms_OBJECTS) $(bpqparms_DEPENDENCIES)
+ @rm -f bpqparms
+ $(LINK) $(bpqparms_LDFLAGS) $(bpqparms_OBJECTS) $(bpqparms_LDADD) $(LIBS)
+
+mheardd: $(mheardd_OBJECTS) $(mheardd_DEPENDENCIES)
+ @rm -f mheardd
+ $(LINK) $(mheardd_LDFLAGS) $(mheardd_OBJECTS) $(mheardd_LDADD) $(LIBS)
+
+rxecho: $(rxecho_OBJECTS) $(rxecho_DEPENDENCIES)
+ @rm -f rxecho
+ $(LINK) $(rxecho_LDFLAGS) $(rxecho_OBJECTS) $(rxecho_LDADD) $(LIBS)
+
+install-man1:
+ $(mkinstalldirs) $(DESTDIR)$(man1dir)
+ @list='$(man1_MANS)'; \
+ l2='$(man_MANS)'; for i in $$l2; do \
+ case "$$i" in \
+ *.1*) 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)$(man1dir)/$$inst"; \
+ $(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst; \
+ done
+
+uninstall-man1:
+ @list='$(man1_MANS)'; \
+ l2='$(man_MANS)'; for i in $$l2; do \
+ case "$$i" in \
+ *.1*) 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)$(man1dir)/$$inst"; \
+ rm -f $(DESTDIR)$(man1dir)/$$inst; \
+ 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-man1 install-man4 install-man5 \
+ install-man8
+uninstall-man:
+ @$(NORMAL_UNINSTALL)
+ $(MAKE) $(AM_MAKEFLAGS) uninstall-man1 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 = ax25
+
+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
+ax25d.o: ax25d.c ../config.h ../pathnames.h
+axctl.o: axctl.c ../config.h
+axparms.o: axparms.c ../config.h ../pathnames.h
+axspawn.o: axspawn.c ../pathnames.h
+beacon.o: beacon.c ../config.h
+bpqparms.o: bpqparms.c ../config.h
+mheard.o: mheard.c ../config.h ../pathnames.h
+mheardd.o: mheardd.c ../config.h ../pathnames.h
+rxecho.o: rxecho.c ../config.h ../pathnames.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-binPROGRAMS install-sbinPROGRAMS
+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-binPROGRAMS uninstall-sbinPROGRAMS uninstall-man
+uninstall: uninstall-am
+all-am: Makefile $(PROGRAMS) $(MANS)
+all-redirect: all-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+installdirs:
+ $(mkinstalldirs) $(DESTDIR)$(bindir) $(DESTDIR)$(sbindir) \
+ $(DESTDIR)$(mandir)/man1 $(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-binPROGRAMS mostlyclean-sbinPROGRAMS \
+ mostlyclean-compile mostlyclean-tags \
+ mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am: clean-binPROGRAMS clean-sbinPROGRAMS clean-compile clean-tags \
+ clean-generic mostlyclean-am
+
+clean: clean-am
+
+distclean-am: distclean-binPROGRAMS distclean-sbinPROGRAMS \
+ distclean-compile distclean-tags distclean-generic \
+ clean-am
+
+distclean: distclean-am
+
+maintainer-clean-am: maintainer-clean-binPROGRAMS \
+ 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-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \
+maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \
+mostlyclean-sbinPROGRAMS distclean-sbinPROGRAMS clean-sbinPROGRAMS \
+maintainer-clean-sbinPROGRAMS uninstall-sbinPROGRAMS \
+install-sbinPROGRAMS mostlyclean-compile distclean-compile \
+clean-compile maintainer-clean-compile install-man1 uninstall-man1 \
+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
+ $(mkinstalldirs) $(DESTDIR)$(vardir)
+ @list='$(varfiles)'; for p in $$list; do \
+ echo " $(INSTALL_DATA) $$p $(DESTDIR)$(vardir)/$$p"; \
+ $(INSTALL_DATA) $$p $(DESTDIR)$(vardir)/$$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/ax25/ax25.4 b/ax25/ax25.4
new file mode 100644
index 0000000..6456971
--- /dev/null
+++ b/ax25/ax25.4
@@ -0,0 +1,77 @@
+.TH AX25 4 "15 October 1996" Linux "Linux Programmer's Manual"
+.SH NAME
+AF_AX25 \- AX.25 amateur packet radio protocol family
+.SH DESCRIPTION
+.LP
+.B AX.25
+is a protocol used extensively by radio amateurs. The Linux AX.25 protocol
+family permits access to these protocols via the standard networking
+.B socket
+metaphor.
+.LP
+The AX.25 protocol layer supports both connected mode and datagram (UI)
+frame modes. IP traffic may be stacked on top of AX.25 frames for IP
+transmission over the AX.25 medium.
+.LP
+The primary mode of operation is connected mode which is the mode used for a
+socket of type SOCK_SEQPACKET (stream sockets are not available in AX.25).
+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.
+The Linux AX.25 protocol layer can operate in standard AX.25 mode with three
+bit sequence numbers or in PE1CHL extended AX.25 mode which uses seven bit
+sequence numbers. The protocol passed to the socket is used for all outgoing
+frames. Passing 0 causes the normal AX.25 Text PID to be used.
+.LP
+SOCK_DGRAM gives access to AX.25 UI frames. For access to special frames (of
+any form) SOCK_RAW can be used. There is no SOCK_PACKET support under AX.25.
+Instead an AF_INET socket of type SOCK_PACKET should be used.
+.LP
+AX.25 addresses consist of 6 ascii characters and a number called the SSID.
+These are encoded into a sockaddr_ax25 structure which is provided to the
+relevant system calls. When digipeaters are included a callsign path can be
+much more complex. When this is the case a struct full_sockaddr_ax25 should
+be passed to the system calls.
+.LP
+AX.25 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, and in addition the superuser may use an arbitary callsign by binding
+to the callsign desired and specifying the port to use as a first digipeated
+hop.
+.LP
+AX.25 supports the following socket options for SOL_AX25. AX25_T1 is the T1
+timer in 1/10ths of a second, AX25_T2 is the T2 timer in 1/10ths of a
+second, AX25_T3 is the T3 timer. The window is settable with AX25_WINDOW.
+AX25_N2, the retry counter is also configurable. There is no 'infinite
+retry' option supported however. The method of backoff for retries is
+configurable via the socket option AX25_BACKOFF, a value of true indicates
+the use of exponential backoff and false simple linear backoff. The mode of
+a connection made be altered to be either standard AX.25 or extended AX.25
+via AX25_EXTSEQ. It is possible to have the complete AX.25 header returned
+to the application by setting AX25_HDRINCL to true, programs must be aware
+of the internal structure of AX.25 frames to use this option. Note that if
+AX.25 fragmentation is encountered, only the control information of the
+first frame is returned along with the defragmented data.
+.SH "SEE ALSO"
+.BR call (1),
+.BR socket (2),
+.BR setsockopt (2),
+.BR getsockopt (2),
+.BR axctl (8),
+.BR axparms (5),
+.BR axassociate (8),
+.BR axparms (8),
+.BR kissattach (8).
+.LP
+.SH BUGS
+.LP
+Too numerous to list in full currently.
+.TP 3
+\(bu
+Minor protocol violations exist.
+.SH AUTHOR
+.nf
+Alan Cox GW4PTS <alan@cymru.net>
+.br
+Jonathan Naylor G4KLX <g4klx@g4klx.demon.co.uk>
+.fi
diff --git a/ax25/ax25.profile b/ax25/ax25.profile
new file mode 100644
index 0000000..dbb2c5c
--- /dev/null
+++ b/ax25/ax25.profile
@@ -0,0 +1,2 @@
+#! /bin/bash
+echo "/char ibmpc ibmpc" >.conversrc
diff --git a/ax25/ax25d.8 b/ax25/ax25d.8
new file mode 100644
index 0000000..96ceec4
--- /dev/null
+++ b/ax25/ax25d.8
@@ -0,0 +1,46 @@
+.TH AX25D 8 "27 August 1996" Linux "Linux System Managers Manual"
+.SH NAME
+ax25d \- General purpose AX.25, NET/ROM and Rose daemon
+.SH SYNOPSIS
+.B ax25d [-v] [-c altconffile] [-l]
+.SH DESCRIPTION
+.LP
+.B Ax25d
+is a general purpose server daemon that listens on a number of AX.25, NET/ROM
+and Rose ports and offers different services depending upon port, callsign
+and other parameters.
+.B Ax25d
+is driven by a complex configuration file, a full description of which may
+be found in another manual page.
+.sp 1
+.B AX25d
+has the facility to log information about incoming connections to the
+system log file. By default no logging is done. When
+.B ax25d
+is running, and a change in the configuration file is made,
+.B ax25d
+can be forced to re-read its configuration file by sending it a SIGHUP.
+.SH OPTIONS
+.TP 15
+.BI "\-c altconffile"
+Specifies an alternate configuration file name.
+.TP 15
+.BI \-l
+Specifies that messages should be logged into the system log file. By default
+no messages are logged.
+.TP 15
+.BI \-v
+Display the version.
+.SH FILES
+.LP
+/etc/ax25/ax25d.conf
+.SH "SEE ALSO"
+.BR kill (1),
+.BR ax25 (4),
+.BR netrom (4),
+.BR rose (4),
+.BR ax25d.conf (5).
+.SH AUTHOR
+Darryl Miles G7LED <dlm@frink.demon.co.uk>
+.br
+Jonathan Naylor G4KLX <g4klx@g4klx.demon.co.uk>
diff --git a/ax25/ax25d.c b/ax25/ax25d.c
new file mode 100644
index 0000000..8d45713
--- /dev/null
+++ b/ax25/ax25d.c
@@ -0,0 +1,1195 @@
+/*
+ * This is my version of axl.c, written for the LBBS code to make it
+ * compatable with the kernel AX25 driver. It appears to work, with
+ * my setup, so it'll probably not work else where :-).
+ *
+ * This was inspired by the example code written by Alan Cox (GW4PTS)
+ * axl.c in AX25USER.TGZ from sunacm.swan.ac.uk.
+ *
+ *
+ * Copyright (C) 1995, 1996 by Darryl L. Miles, G7LED.
+ * Copyright (C) 1996 by Jonathan Naylor G4KLX
+ *
+ * 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.
+ *
+ *
+ *
+ * Just a quickie Feb 1995.
+ * It *was* just a quickie (at the time) but you'd know how these things
+ * just... Apr 1995.
+ *
+ * If your AX25/NETROM system is relying on this code for
+ * securetty/firewalling then please be aware this has been coded
+ * with the intent on striving on through system/(mis)configuration
+ * errors in the hope that at worst it will run with a degraded
+ * service. Rather than leave your system providing no service at
+ * all, if opinions require the old behavior back when let me know
+ * and I'll #ifdef it in.
+ *
+ *
+ * History:
+ *
+ * 1.0 Feb 1995 Basic AX25 listening daemon, Multi-port, Call
+ * matching, etc...
+ *
+ * 1.1 Feb 1995 Moved entry scanning before fork().
+ * Added setgroups() to plug security hole.
+ * Minor fixes + Improved handling.
+ *
+ * 1.2 Apr 1995 NETROM support added from developing AX25
+ * 028b/029.
+ * Added 'defaults' port setting.
+ * Added FLAG_NODIGIS.
+ *
+ * 1.3 Jul 1995 Make it a little more intelligent about what to
+ * do with errors.
+ * Added exec and argv[0] as two different fields,
+ * much like inetd uses.
+ *
+ * 1.4 Aug 1995 Confirmed support for AX25 030 (1.3.20 + hacks),
+ * it appears to work.
+ * It will now bootup even if initial config errors
+ * occur when setting up and binding (e.g. port(s)
+ * down), it will skip the port(s) with a problem
+ * and listen out on those which are left standing.
+ *
+ * 1.5 Aug 1995 Updated old (buggy) libax25.a function copies in axl.
+ * Causing all sorts of problems.
+ *
+ * 1.6 Aug 1995 Reset the 'defaults' entry's when we start parsing
+ * a new interface.
+ *
+ * 1.7 Dec 1995 Added BROKEN_NETROM_KERNEL define for setsockopt.
+ *
+ * 1.8 Jan 1996 Added support for AX25_BIND_ANY_DEVICE, specify just
+ * [CALL-X VIA *].
+ * Better param parsing, T1 and T2 now using the real
+ * time in seconds as params, and not kernel units.
+ * Connection loggin added, either via it's own logfile
+ * or syslog.
+ * Modified 'defaults' to 'parameters'.
+ *
+ * 1.9 Jun 1996 Reworked config file parsing to use port names instead
+ * of callsigns. Reformated source code.
+ *
+ * Under alpha:
+ * BPQ like clever mode called for.... also a mode that
+ * requires a packet to kick application open.
+ * A flag/mode which will cause a call to initgroups()
+ * based on uid.
+ * Callsign validation check.
+ * Logging of errors.
+ *
+ *
+ * TODO:
+ * The timing of the 'accept()' might be changed, defered to the
+ * child, then that child fork() itself, to stop race conditions
+ * around 'accept()'.
+ * Add a config file to allow/disallow connections/services at
+ * different times of the day to restrict access say.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <string.h>
+#include <ctype.h>
+#include <time.h>
+#include <pwd.h>
+#include <grp.h>
+#include <syslog.h>
+#include <errno.h>
+
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/fcntl.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+
+#include <netax25/ax25.h>
+#include <netrom/netrom.h>
+#include <netrose/rose.h>
+
+#include <netax25/axlib.h>
+#include <netax25/axconfig.h>
+#include <netax25/nrconfig.h>
+#include <netax25/rsconfig.h>
+#include <netax25/daemon.h>
+
+#include <config.h>
+
+#include "../pathnames.h"
+
+/* Maximum number of command line arguments for the application we run */
+#define MAX_ARGS 32
+
+#define FLAG_VALIDCALL 0x01 /* NOTUSED */
+#define FLAG_NOLOGGING 0x02 /* Don't log this connection */
+#define FLAG_CHKNRN 0x04 /* Check NetRom Neighbour - NOTUSED */
+#define FLAG_NODIGIS 0x08 /* Disallow digipeated uplinks */
+#define FLAG_LOCKOUT 0x10 /* Disallow connection */
+
+
+struct axlist { /* Have used same struct for quickness */
+ struct axlist *next; /* Port list */
+
+ char *port; /* Port call, only set across the port list */
+ int fd; /* The listening socket fd */
+
+ int af_type; /* AF_AX25, AF_NETROM or AF_ROSE port */
+
+ struct axlist *ents; /* Exec line entries */
+ char *call; /* Call in listing entries */
+ char *node; /* Node call in listing entries */
+ uid_t uid; /* UID to run program as */
+ gid_t gid; /* GID to run program as */
+ char *exec; /* Real exec */
+ char *shell; /* Command line. With possible escapes. */
+
+ unsigned int window; /* Set window to... */
+ unsigned long t1; /* Set T1 to... (Retrans timer) */
+ unsigned long t2; /* Set T2 to... (Ack delay) */
+ unsigned long t3; /* Set T3 to... (Idle Poll timer) */
+ unsigned long idle; /* Set T4 to... (Link Drop timer) */
+ unsigned long n2; /* Set N2 to... (Retries) */
+ unsigned long flags; /* FLAG_ values ORed... */
+};
+
+static struct axlist *AXL = NULL;
+static char *ConfigFile = CONF_AX25D_FILE;
+static char User[10]; /* Room for 'GB9ZZZ-15\0' */
+static char Node[11]; /* Room for 'GB9ZZZ-15\0' */
+static char *Port;
+static sig_atomic_t Update = TRUE; /* Cause update on bootup */
+static int Logging = FALSE;
+
+static void SignalHUP(int);
+static void SignalTERM(int);
+static void WorkoutArgs(int, char *, int *, char **);
+static void SetupOptions(int, struct axlist *);
+static int ReadConfig(void);
+static unsigned long ParseFlags(const char *, int);
+static struct axlist *ClearList(struct axlist *);
+static char *stripssid(const char *);
+
+
+int main(int argc, char *argv[])
+{
+ struct axlist *axltmp, *paxl, *raxl;
+ union {
+ struct full_sockaddr_ax25 ax25;
+ struct sockaddr_rose rose;
+ } sockaddr;
+ struct sigaction act, oact;
+ int maxfd = -1;
+ fd_set fdread;
+ int addrlen;
+ int cnt;
+
+ while ((cnt = getopt(argc, argv, "c:lv")) != EOF) {
+ switch (cnt) {
+ case 'c':
+ ConfigFile = optarg;
+ break;
+
+ case 'l':
+ Logging = TRUE;
+ break;
+
+ case 'v':
+ printf("ax25d: %s\n", VERSION);
+ return 1;
+
+ default:
+ fprintf(stderr, "Usage: ax25d [-v] [-c altfile] [-l]\n");
+ return 1;
+ }
+ }
+
+ if (ax25_config_load_ports() == 0) {
+ fprintf(stderr, "ax25d: no AX.25 port data configured\n");
+ return 1;
+ }
+
+ nr_config_load_ports();
+
+ rs_config_load_ports();
+
+ if (!daemon_start(TRUE)) {
+ fprintf(stderr, "ax25d: cannot become a daemon\n");
+ return 1;
+ }
+
+ if (Logging) {
+ openlog("ax25d", LOG_PID, LOG_DAEMON);
+ syslog(LOG_INFO, "starting");
+ }
+
+ act.sa_handler = SignalHUP;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = 0;
+ sigaction(SIGHUP, &act, &oact);
+
+ act.sa_handler = SignalTERM;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = 0;
+ sigaction(SIGTERM, &act, &oact);
+
+ for (;;) {
+ if (Update) {
+ if (ReadConfig() < 0) {
+ if (AXL == NULL) {
+ if (Logging)
+ syslog(LOG_ERR, "config file reload error, exiting");
+ return 1;
+ } else {
+ if (Logging)
+ syslog(LOG_INFO, "config file reload error, continuing with original");
+ }
+ } else {
+ if (Logging)
+ syslog(LOG_INFO, "new config file loaded successfuly");
+ }
+
+ Update = FALSE;
+ }
+
+ FD_ZERO(&fdread);
+
+ for (paxl = AXL; paxl != NULL && paxl->fd >= 0; paxl = paxl->next) {
+ FD_SET(paxl->fd, &fdread);
+
+ if (paxl->fd > maxfd)
+ maxfd = paxl->fd;
+ }
+
+ if (select(maxfd + 1, &fdread, NULL, NULL, NULL) <= 0)
+ continue;
+
+ for (paxl = AXL; paxl != NULL; paxl = paxl->next) {
+ if (FD_ISSET(paxl->fd, &fdread)) {
+ pid_t pid;
+ gid_t grps[2];
+ char *argv[MAX_ARGS];
+ int argc;
+ int new;
+ int i;
+
+ /*
+ * Setting up a non-blocking accept() so is does not hang up
+ * - I am not sure at this time why I didn't/don't assign
+ * the socket non-blocking to start with.
+ */
+ /*
+ * We really need to setup the netrom window option here so
+ * that it's negotiated correctly on accepting the connection.
+ */
+ /*
+ * It would be very useful if recvmsg/sendmsg were supported
+ * then we can move the call checking up here.
+ */
+ i = TRUE;
+ ioctl(paxl->fd, FIONBIO, &i);
+
+ addrlen = sizeof(struct full_sockaddr_ax25);
+ new = accept(paxl->fd, (struct sockaddr *)&sockaddr, &addrlen);
+
+ i = FALSE;
+ ioctl(paxl->fd, FIONBIO, &i);
+
+ if (new < 0) {
+ if (errno == EWOULDBLOCK)
+ continue; /* It's gone ??? */
+
+ if (Logging)
+ syslog(LOG_ERR, "accept error %m, closing socket on port %s", paxl->port);
+ close(paxl->fd);
+ paxl->fd = -1;
+ continue;
+ }
+
+ switch (paxl->af_type) {
+ case AF_AX25:
+ strcpy(User, ax25_ntoa(&sockaddr.ax25.fsa_ax25.sax25_call));
+ strcpy(Node, "");
+ break;
+ case AF_NETROM:
+ strcpy(User, ax25_ntoa(&sockaddr.ax25.fsa_ax25.sax25_call));
+ strcpy(Node, ax25_ntoa(&sockaddr.ax25.fsa_digipeater[0]));
+ break;
+ case AF_ROSE:
+ strcpy(User, ax25_ntoa(&sockaddr.rose.srose_call));
+ strcpy(Node, rose_ntoa(&sockaddr.rose.srose_addr));
+ break;
+ }
+
+ for (raxl = paxl->ents; raxl != NULL; raxl = raxl->ents) {
+ if (paxl->af_type == AF_NETROM && raxl->node != NULL && Node[0] != '\0') {
+ if (strchr(raxl->node, '-') == NULL) {
+ if (strcasecmp(raxl->node, stripssid(Node)) != 0)
+ continue; /* Found no match (for any SSID) */
+ } else {
+ if (strcasecmp(raxl->node, Node) != 0)
+ continue; /* Found no match */
+ }
+ }
+
+ if (raxl->call == NULL) /* default */
+ break;
+
+ if (strchr(raxl->call, '-') == NULL) {
+ if (strcasecmp(raxl->call, stripssid(User)) == 0)
+ break; /* Found a match (for any SSID) */
+ } else {
+ if (strcasecmp(raxl->call, User) == 0)
+ break; /* Found a match */
+ }
+ }
+
+ addrlen = sizeof(struct full_sockaddr_ax25);
+ getsockname(new, (struct sockaddr *)&sockaddr, &addrlen);
+
+ switch (paxl->af_type) {
+ case AF_AX25:
+ Port = ax25_config_get_port(&sockaddr.ax25.fsa_digipeater[0]);
+ break;
+ case AF_NETROM:
+ Port = nr_config_get_port(&sockaddr.ax25.fsa_ax25.sax25_call);
+ break;
+ case AF_ROSE:
+ Port = rs_config_get_port(&sockaddr.rose.srose_addr);
+ break;
+ default:
+ Port = "???";
+ break;
+ }
+
+ if (raxl == NULL) {
+ /* No default */
+ if (Logging && !(paxl->flags & FLAG_NOLOGGING)) {
+ switch (paxl->af_type) {
+ case AF_AX25:
+ syslog(LOG_INFO, "AX.25 %s (%s) rejected - no default", User, Port);
+ break;
+ case AF_NETROM:
+ syslog(LOG_INFO, "NET/ROM %s@%s (%s) rejected - no default", User, Node, Port);
+ break;
+ case AF_ROSE:
+ syslog(LOG_INFO, "Rose %s@%s (%s) rejected - no default", User, Node, Port);
+ break;
+ }
+ }
+ close(new);
+ continue;
+ }
+
+ if (raxl->flags & FLAG_LOCKOUT) {
+ /* Not allowed to connect */
+ if (Logging && !(paxl->flags & FLAG_NOLOGGING)) {
+ switch (raxl->af_type) {
+ case AF_AX25:
+ syslog(LOG_INFO, "AX.25 %s (%s) rejected - port locked", User, Port);
+ break;
+ case AF_NETROM:
+ syslog(LOG_INFO, "NET/ROM %s@%s (%s) rejected - port locked", User, Node, Port);
+ break;
+ case AF_ROSE:
+ syslog(LOG_INFO, "Rose %s@%s (%s) rejected - port locked", User, Node, Port);
+ break;
+ }
+ }
+ close(new);
+ continue;
+ }
+
+ if (raxl->af_type == AF_AX25 && (raxl->flags & FLAG_NODIGIS) && sockaddr.ax25.fsa_ax25.sax25_ndigis != 0) {
+ /* Not allowed to uplink via digi's */
+ if (Logging && !(paxl->flags & FLAG_NOLOGGING))
+ syslog(LOG_INFO, "AX.25 %s (%s) rejected - digipeaters", User, Port);
+ close(new);
+ continue;
+ }
+
+ pid = fork();
+
+ switch (pid) {
+ case -1:
+ if (Logging)
+ syslog(LOG_ERR, "fork error %m");
+ /*
+ * I don't think AX25 at the moment will hold the
+ * connection open, if the above does not make it
+ * through first time.
+ */
+ close(new);
+ break; /* Oh well... */
+
+ case 0:
+ SetupOptions(new, raxl);
+ WorkoutArgs(raxl->af_type, raxl->shell, &argc, argv);
+
+ if (Logging && !(paxl->flags & FLAG_NOLOGGING)) {
+ switch (paxl->af_type) {
+ case AF_AX25:
+ syslog(LOG_INFO, "AX.25 %s (%s) %s", User, Port, argv[0]);
+ break;
+ case AF_NETROM:
+ syslog(LOG_INFO, "NET/ROM %s@%s (%s) %s", User, Node, Port, argv[0]);
+ break;
+ case AF_ROSE:
+ syslog(LOG_INFO, "Rose %s@%s (%s) %s", User, Node, Port, argv[0]);
+ break;
+ }
+ }
+
+ dup2(new, STDIN_FILENO);
+ dup2(new, STDOUT_FILENO);
+ close(new);
+
+ /*
+ * Might be more efficient if we just went down AXL,
+ * we cleaned up our parents left overs on bootup.
+ */
+ for (axltmp = AXL; axltmp != NULL; axltmp = axltmp->next)
+ close(axltmp->fd);
+
+ if (Logging)
+ closelog();
+
+ /* Make root secure, before we exec() */
+ setgroups(0, grps); /* Strip any supplementary gid's */
+ setgid(raxl->gid);
+ setuid(raxl->uid);
+ execve(raxl->exec, argv, NULL);
+ return 1;
+
+ default:
+ close(new);
+ break;
+ }
+ }
+ }
+ }
+
+ /* NOT REACHED */
+ return 0;
+}
+
+static void SignalHUP(int code)
+{
+ Update = TRUE; /* Schedule an update */
+}
+
+static void SignalTERM(int code)
+{
+ if (Logging) {
+ syslog(LOG_INFO, "terminating on SIGTERM\n");
+ closelog();
+ }
+
+ exit(0);
+}
+
+static void WorkoutArgs(int af_type, char *shell, int *argc, char **argv)
+{
+ char buffer[1024]; /* Maximum arg size */
+ char *sp, *cp;
+ int cnt = 0;
+ int args = 0;
+
+ for (cp = shell; *cp != '\0'; cp++) {
+ if (isspace(*cp) && cnt != 0) {
+ buffer[cnt] = '\0';
+ argv[args++] = strdup(buffer);
+ cnt = 0;
+
+ if (args == MAX_ARGS - 1) {
+ argv[args] = NULL;
+ *argc = args;
+ return;
+ }
+
+ continue;
+ } else if (isspace(*cp)) /* && !cnt */
+ continue;
+
+ if (*cp == '%') {
+ cp++;
+
+ switch(*cp) {
+ case 'd': /* portname */
+ for (sp = Port; *sp != '\0' && *sp != '-'; sp++)
+ buffer[cnt++] = *sp;
+ break;
+
+ case 'U': /* username in UPPER */
+ for (sp = User; *sp != '\0' && *sp != '-'; sp++)
+ buffer[cnt++] = toupper(*sp);
+ break;
+
+ case 'u': /* USERNAME IN lower */
+ for (sp = User; *sp != '\0' && *sp != '-'; sp++)
+ buffer[cnt++] = tolower(*sp);
+ break;
+
+ case 'S': /* username in UPPER (with SSID) */
+ for (sp = User; *sp != '\0'; sp++)
+ buffer[cnt++] = toupper(*sp);
+ break;
+
+ case 's': /* USERNAME IN lower (with SSID) */
+ for (sp = User; *sp != '\0'; sp++)
+ buffer[cnt++] = tolower(*sp);
+ break;
+
+ case 'P': /* nodename in UPPER */
+ if (af_type == AF_NETROM) {
+ for (sp = Node; *sp != '\0' && *sp != '-'; sp++)
+ buffer[cnt++] = toupper(*sp);
+ } else {
+ buffer[cnt++] = '%';
+ }
+ break;
+
+ case 'p': /* NODENAME IN lower */
+ if (af_type == AF_NETROM) {
+ for(sp = Node; *sp != '\0' && *sp != '-'; sp++)
+ buffer[cnt++] = tolower(*sp);
+ } else {
+ buffer[cnt++] = '%';
+ }
+ break;
+
+ case 'R': /* nodename in UPPER (with SSID) */
+ if (af_type == AF_NETROM) {
+ for (sp = Node; *sp != '\0'; sp++)
+ buffer[cnt++] = toupper(*sp);
+ } else {
+ buffer[cnt++] = '%';
+ }
+ break;
+
+ case 'r': /* NODENAME IN lower (with SSID) */
+ if (af_type == AF_NETROM) {
+ for (sp = Node; *sp != '\0'; sp++)
+ buffer[cnt++] = tolower(*sp);
+ } else {
+ buffer[cnt++] = '%';
+ }
+ break;
+
+ case '\0':
+ case '%':
+ default:
+ buffer[cnt++] = '%';
+ break;
+ }
+ } else {
+ buffer[cnt++] = *cp;
+ }
+ }
+
+ if (cnt != 0) {
+ buffer[cnt] = '\0';
+ argv[args++] = strdup(buffer);
+ }
+
+ argv[args] = NULL;
+ *argc = args;
+}
+
+static void SetupOptions(int new, struct axlist *axl)
+{
+ switch (axl->af_type) {
+ case AF_AX25:
+ if (axl->window != 0)
+ setsockopt(new, SOL_AX25, AX25_WINDOW, &axl->window, sizeof(axl->window));
+ if (axl->t1 != 0)
+ setsockopt(new, SOL_AX25, AX25_T1, &axl->t1, sizeof(axl->t1));
+ if (axl->n2 != 0)
+ setsockopt(new, SOL_AX25, AX25_N2, &axl->n2, sizeof(axl->n2));
+ if (axl->t2 != 0)
+ setsockopt(new, SOL_AX25, AX25_T2, &axl->t2, sizeof(axl->t2));
+ if (axl->t3 != 0)
+ setsockopt(new, SOL_AX25, AX25_T3, &axl->t3, sizeof(axl->t3));
+ if (axl->idle != 0)
+ setsockopt(new, SOL_AX25, AX25_IDLE, &axl->idle, sizeof(axl->idle));
+ break;
+ case AF_NETROM:
+ if (axl->t1 != 0)
+ setsockopt(new, SOL_NETROM, NETROM_T1, &axl->t1, sizeof(axl->t1));
+ if (axl->n2 != 0)
+ setsockopt(new, SOL_NETROM, NETROM_N2, &axl->n2, sizeof(axl->n2));
+ if (axl->t2 != 0)
+ setsockopt(new, SOL_NETROM, NETROM_T2, &axl->t2, sizeof(axl->t2));
+ break;
+ case AF_ROSE:
+ if (axl->idle != 0)
+ setsockopt(new, SOL_ROSE, ROSE_IDLE, &axl->idle, sizeof(axl->idle));
+ break;
+ }
+}
+
+/**************************** CONFIGURATION STUFF ***************************/
+
+static int ReadConfig(void)
+{
+ struct axlist axl_defaults;
+ struct axlist *axl_build = NULL;
+ struct axlist *axl_port = NULL;
+ struct axlist *axl_ent, *axltmp;
+ union {
+ struct full_sockaddr_ax25 ax25;
+ struct sockaddr_rose rose;
+ } sockaddr;
+ struct passwd *pwd;
+ FILE *fp;
+ char buffer[2048];
+ char *s, *port, *call, *node, *addr = NULL;
+ unsigned long val;
+ int addrlen;
+ int af_type = 0; /* Keep GCC happy */
+ int line = 0;
+ int hunt = TRUE, error = FALSE;
+ int iamdigi = FALSE, yes;
+ int parameters = 0;
+
+ memset(&axl_defaults, 0, sizeof(axl_defaults));
+
+ if ((fp = fopen(ConfigFile, "r")) == NULL)
+ return -1;
+
+ while (fgets(buffer, sizeof(buffer), fp) != NULL) {
+ line++;
+
+ if ((s = strchr(buffer, '\n')) != NULL)
+ *s = '\0';
+ if ((s = strchr(buffer, '\r')) != NULL)
+ *s = '\0';
+
+ if (buffer[0] == '#')
+ continue;
+
+ switch (buffer[0]) {
+ case '[': /* AX25 port call */
+ af_type = AF_AX25;
+ hunt = TRUE;
+ error = FALSE;
+ iamdigi = FALSE;
+ break;
+
+ case '<': /* NETROM iface call */
+ af_type = AF_NETROM;
+ hunt = TRUE;
+ error = FALSE;
+ iamdigi = FALSE;
+ break;
+
+ case '{': /* ROSE iface call */
+ af_type = AF_ROSE;
+ hunt = TRUE;
+ error = FALSE;
+ iamdigi = FALSE;
+ break;
+
+ default:
+ if (hunt && !error)
+ goto BadLine;
+ break;
+ }
+
+ if (hunt) { /* We've found a Iface entry */
+ /* Reset 'defaults' entry on the interface */
+ memset(&axl_defaults, 0, sizeof(axl_defaults));
+
+ switch (af_type) {
+ case AF_AX25:
+ if ((s = strchr(buffer, ']')) == NULL)
+ goto BadLine;
+ *s = '\0';
+ if ((s = strtok(buffer + 1, " \t")) == NULL)
+ goto BadLine;
+ port = s;
+ call = NULL;
+ if ((s = strtok(NULL, " \t")) != NULL) {
+ if (strcasecmp(s, "VIA") == 0 || strcasecmp(s, "V") == 0) {
+ if ((s = strtok(NULL, " \t")) == NULL)
+ goto BadLine;
+ }
+
+ call = port;
+ port = s;
+
+ if ((s = strchr(call, '*')) != NULL) {
+ iamdigi = TRUE;
+ *s = '\0';
+ }
+ }
+ if (strcmp(port, "*") == 0 && call == NULL) {
+ fprintf(stderr, "ax25d: invalid port name\n");
+ continue;
+ }
+ if (strcmp(port, "*") != 0) {
+ if ((addr = ax25_config_get_addr(port)) == NULL) {
+ fprintf(stderr, "ax25d: invalid AX.25 port '%s'\n", port);
+ continue;
+ }
+ }
+ if (call == NULL) {
+ sockaddr.ax25.fsa_ax25.sax25_family = AF_AX25;
+ sockaddr.ax25.fsa_ax25.sax25_ndigis = 0;
+ ax25_aton_entry(addr, sockaddr.ax25.fsa_ax25.sax25_call.ax25_call);
+ } else {
+ sockaddr.ax25.fsa_ax25.sax25_family = AF_AX25;
+ sockaddr.ax25.fsa_ax25.sax25_ndigis = 1;
+ ax25_aton_entry(call, sockaddr.ax25.fsa_ax25.sax25_call.ax25_call);
+ if (strcmp(port, "*") != 0)
+ ax25_aton_entry(addr, sockaddr.ax25.fsa_digipeater[0].ax25_call);
+ else
+ sockaddr.ax25.fsa_digipeater[0] = null_ax25_address;
+ }
+ addrlen = sizeof(struct full_sockaddr_ax25);
+ break;
+
+ case AF_NETROM:
+ if ((s = strchr(buffer, '>')) == NULL)
+ goto BadLine;
+ *s = '\0';
+ port = buffer + 1;
+ if ((addr = nr_config_get_addr(port)) == NULL) {
+ fprintf(stderr, "ax25d: invalid NET/ROM port '%s'\n", port);
+ continue;
+ }
+ sockaddr.ax25.fsa_ax25.sax25_family = AF_NETROM;
+ sockaddr.ax25.fsa_ax25.sax25_ndigis = 0;
+ ax25_aton_entry(addr, sockaddr.ax25.fsa_ax25.sax25_call.ax25_call);
+ addrlen = sizeof(struct full_sockaddr_ax25);
+ break;
+
+ case AF_ROSE:
+ if ((s = strchr(buffer, '}')) == NULL)
+ goto BadLine;
+ *s = '\0';
+ if ((s = strtok(buffer + 1, " \t")) == NULL)
+ goto BadLine;
+ call = s;
+ if ((s = strtok(NULL, " \t")) == NULL)
+ goto BadLine;
+ if (strcasecmp(s, "VIA") == 0 || strcasecmp(s, "V") == 0) {
+ if ((s = strtok(NULL, " \t")) == NULL)
+ goto BadLine;
+ }
+ port = s;
+ if ((addr = rs_config_get_addr(port)) == NULL) {
+ fprintf(stderr, "ax25d: invalid Rose port '%s'\n", port);
+ continue;
+ }
+ if (strcmp(call, "*") == 0) {
+ sockaddr.rose.srose_family = AF_ROSE;
+ sockaddr.rose.srose_ndigis = 0;
+ rose_aton(addr, sockaddr.rose.srose_addr.rose_addr);
+ sockaddr.rose.srose_call = null_ax25_address;
+ } else {
+ sockaddr.rose.srose_family = AF_ROSE;
+ sockaddr.rose.srose_ndigis = 0;
+ rose_aton(addr, sockaddr.rose.srose_addr.rose_addr);
+ ax25_aton_entry(call, sockaddr.rose.srose_call.ax25_call);
+ }
+ addrlen = sizeof(struct sockaddr_rose);
+ break;
+
+ default:
+ fprintf(stderr, "ax25d: unknown af_type=%d\n", af_type);
+ exit(1);
+ }
+
+ if ((axl_port = calloc(1, sizeof(*axl_port))) == NULL) {
+ fprintf(stderr, "ax25d: out of memory\n");
+ goto Error;
+ }
+
+ axl_port->port = strdup(port);
+ axl_port->af_type = af_type;
+
+ if ((axl_port->fd = socket(axl_port->af_type, SOCK_SEQPACKET, 0)) < 0) {
+ fprintf(stderr, "ax25d: socket: %s\n", strerror(errno));
+ free(axl_port->port);
+ free(axl_port);
+ error = TRUE;
+ continue;
+ }
+ /* xlz - have to nuke this as this option is gone
+ * what should be here?
+ if (iamdigi) {
+ yes = 1;
+ setsockopt(axl_port->fd, SOL_AX25, AX25_IAMDIGI, &yes, sizeof(yes));
+ }
+ */
+
+ if (bind(axl_port->fd, (struct sockaddr *)&sockaddr, addrlen) < 0) {
+ fprintf(stderr, "ax25d: bind: %s on port %s\n", strerror(errno), axl_port->port);
+ close(axl_port->fd);
+ free(axl_port->port);
+ free(axl_port);
+ error = TRUE;
+ continue;
+ }
+
+ if (listen(axl_port->fd, SOMAXCONN) < 0) {
+ fprintf(stderr, "ax25d: listen: %s\n", strerror(errno));
+ close(axl_port->fd);
+ free(axl_port->port);
+ free(axl_port);
+ error = TRUE;
+ continue;
+ }
+
+ /* Add it to the head of the list we are building */
+ if (axl_build == NULL) {
+ axl_build = axl_port;
+ } else {
+ for (axltmp = axl_build; axltmp->next != NULL; axltmp = axltmp->next);
+ axltmp->next = axl_port;
+ }
+
+ hunt = FALSE; /* Next lines will be entries */
+ } else { /* This is an entry */
+ if ((axl_ent = calloc(1, sizeof(*axl_ent))) == NULL) {
+ fprintf(stderr, "ax25d: out of memory\n");
+ goto Error;
+ }
+
+ axl_ent->af_type = axl_port->af_type; /* Inherit this */
+
+ if ((call = strtok(buffer, " \t")) == NULL) {
+ free(axl_ent);
+ continue;
+ }
+
+ strupr(call);
+
+ if (axl_ent->af_type == AF_NETROM) {
+ if ((s = strchr(call, '@')) != NULL) {
+ node = s + 1;
+ *s = '\0';
+
+ if (*node == '\0') {
+ free(axl_ent);
+ continue;
+ }
+
+ axl_ent->node = strdup(node);
+
+ if (*call == '\0')
+ call = "default"; /* @NODE means default@NODE */
+ }
+ }
+
+ parameters = FALSE;
+
+ if (strcasecmp("parameters", call) == 0)
+ parameters = TRUE;
+ else if (strcasecmp("default", call) != 0)
+ axl_ent->call = strdup(call);
+
+ /* Window */
+ if ((s = strtok(NULL, " \t")) == NULL)
+ goto BadArgsFree;
+
+ if (!parameters) {
+ if (strcmp(s, "*") != 0)
+ axl_ent->window = atoi(s);
+ else
+ axl_ent->window = axl_defaults.window;
+ } else {
+ if (strcmp(s, "*") != 0)
+ axl_defaults.window = atoi(s);
+ }
+
+ /* T1 */
+ if ((s = strtok(NULL, " \t")) == NULL)
+ goto BadArgsFree;
+
+ if (!parameters) {
+ if (strcmp(s, "*") != 0) {
+ val = (unsigned long)(atof(s) / 0.1);
+
+ if (val == 0 || val > 65535)
+ axl_ent->t1 = axl_defaults.t1;
+ else
+ axl_ent->t1 = val;
+ } else {
+ axl_ent->t1 = axl_defaults.t1;
+ }
+ } else {
+ if (strcmp(s, "*") != 0) {
+ val = (unsigned long)(atof(s) / 0.1);
+
+ if (val > 0 && val < 65535)
+ axl_defaults.t1 = val;
+ }
+ }
+
+ /* T2 */
+ if ((s = strtok(NULL, " \t")) == NULL)
+ goto BadArgsFree;
+
+ if (!parameters) {
+ if (strcmp(s, "*") != 0) {
+ val = (unsigned long)(atof(s) / 0.1);
+
+ if (val == 0 || val > 65535)
+ axl_ent->t2 = axl_defaults.t2;
+ else
+ axl_ent->t2 = val;
+ } else {
+ axl_ent->t2 = axl_defaults.t2;
+ }
+ } else {
+ if (strcmp(s, "*") != 0) {
+ val = (unsigned long)(atof(s) / 0.1);
+
+ if (val > 0 && val < 65535)
+ axl_defaults.t2 = val;
+ }
+ }
+
+ /* T3 */
+ if ((s = strtok(NULL, " \t")) == NULL)
+ goto BadArgsFree;
+
+ if (!parameters) {
+ if (strcmp(s, "*") != 0)
+ axl_ent->t3 = atoi(s);
+ else
+ axl_ent->t3 = axl_defaults.t3;
+ } else {
+ if (strcmp(s, "*") != 0)
+ axl_defaults.t3 = atoi(s);
+ }
+
+ /* Idle */
+ if ((s = strtok(NULL, " \t")) == NULL)
+ goto BadArgsFree;
+
+ if (!parameters) {
+ if (strcmp(s, "*") != 0)
+ axl_ent->idle = atoi(s);
+ else
+ axl_ent->idle = axl_defaults.idle;
+ } else {
+ if (strcmp(s, "*") != 0)
+ axl_defaults.idle = atoi(s);
+ }
+
+ /* N2 */
+ if ((s = strtok(NULL, " \t")) == NULL)
+ goto BadArgsFree;
+
+ if (!parameters) {
+ if (strcmp(s, "*") != 0)
+ axl_ent->n2 = atoi(s);
+ else
+ axl_ent->n2 = axl_defaults.n2;
+ } else {
+ if (strcmp(s, "*") != 0)
+ axl_defaults.n2 = atoi(s);
+ }
+
+ if (!parameters) {
+ /* Flags */
+ if ((s = strtok(NULL, " \t")) == NULL)
+ goto BadArgsFree;
+
+ axl_ent->flags = ParseFlags(s, line);
+
+ if (!(axl_ent->flags & FLAG_LOCKOUT)) {
+ /* Get username */
+ if ((s = strtok(NULL, " \t")) == NULL)
+ goto BadArgsFree;
+
+ if ((pwd = getpwnam(s)) == NULL) {
+ fprintf(stderr, "ax25d: UID for user '%s' is unknown, ignoring entry\n", s);
+ goto BadUID;
+ }
+
+ axl_ent->uid = pwd->pw_uid;
+ axl_ent->gid = pwd->pw_gid;
+
+ /* Get exec file */
+ if ((s = strtok(NULL, " \t")) == NULL)
+ goto BadArgsFree;
+
+ axl_ent->exec = strdup(s);
+
+ /* Get command line */
+ if ((s = strtok(NULL, "")) == NULL)
+ goto BadArgsFree2;
+
+ axl_ent->shell = strdup(s);
+ }
+
+ axl_ent->next = NULL;
+
+ if (axl_port->ents == NULL) {
+ axl_port->ents = axl_ent;
+ } else {
+ for (axltmp = axl_port->ents; axltmp->ents != NULL; axltmp = axltmp->ents)
+ ;
+ axltmp->ents = axl_ent;
+ }
+ }
+ }
+
+ continue;
+
+BadLine:
+ fprintf(stderr, "ax25d: bad config entry on line %d\n", line);
+ continue;
+
+BadUID:
+ if (axl_ent->call != NULL)
+ free(axl_ent->call);
+ free(axl_ent);
+ continue;
+
+BadArgsFree2:
+ if (axl_ent->exec != NULL)
+ free(axl_ent->exec);
+BadArgsFree:
+ if (axl_ent->call != NULL)
+ free(axl_ent->call);
+ free(axl_ent);
+
+ /* BadArgs: */
+ fprintf(stderr, "ax25d: bad config entry on line %d, not enough fields.\n", line);
+ continue;
+ }
+
+ fclose(fp);
+
+ AXL = ClearList(AXL);
+ AXL = axl_build; /* Assign our built list to AXL */
+
+ return 0;
+
+Error:
+ axl_build = ClearList(axl_build);
+ return -1;
+}
+
+static unsigned long ParseFlags(const char *kp, int line)
+{
+ unsigned long flags = 0UL;
+
+ for (; *kp != '\0'; kp++) {
+ switch (*kp) {
+ case 'v':
+ case 'V':
+ flags |= FLAG_VALIDCALL;
+ break;
+
+ case 'q':
+ case 'Q':
+ flags |= FLAG_NOLOGGING;
+ break;
+
+ case 'n':
+ case 'N':
+ flags |= FLAG_CHKNRN;
+ break;
+
+ case 'd':
+ case 'D':
+ flags |= FLAG_NODIGIS;
+ break;
+
+ case 'l':
+ case 'L':
+ flags |= FLAG_LOCKOUT;
+ break;
+
+ case '0':
+ case '*':
+ case '-': /* Be compatible and allow markers */
+ break;
+
+ default:
+ fprintf(stderr, "ax25d: config file line %d bad flag option '%c'.\n", line, *kp);
+ break;
+ }
+ }
+
+ return flags;
+}
+
+static struct axlist *ClearList(struct axlist *list)
+{
+ struct axlist *tp1, *tp2, *tmp;
+
+ for (tp1 = list; tp1 != NULL; ) {
+ for (tp2 = tp1->ents; tp2 != NULL; ) {
+ if (tp2->port != NULL)
+ free(tp2->port);
+ if (tp2->call != NULL)
+ free(tp2->call);
+ if (tp2->node != NULL)
+ free(tp2->node);
+ if (tp2->exec != NULL)
+ free(tp2->exec);
+ if (tp2->shell != NULL)
+ free(tp2->shell);
+
+ tmp = tp2->ents;
+ free(tp2);
+ tp2 = tmp;
+ }
+
+ if (tp1->port != NULL)
+ free(tp1->port);
+ if (tp1->call != NULL)
+ free(tp1->call);
+ if (tp1->node != NULL)
+ free(tp1->node);
+ if (tp1->exec != NULL)
+ free(tp1->exec);
+ if (tp1->shell != NULL)
+ free(tp1->shell);
+
+ close(tp1->fd);
+
+ tmp = tp1->next;
+ free(tp1);
+ tp1 = tmp;
+ }
+
+ return NULL;
+}
+
+static char *stripssid(const char *call)
+{
+ static char newcall[10];
+ char *s;
+
+ strcpy(newcall, call);
+
+ if ((s = strchr(newcall, '-')) != NULL)
+ *s = '\0';
+
+ return newcall;
+}
diff --git a/ax25/ax25d.conf b/ax25/ax25d.conf
new file mode 100644
index 0000000..c55f7ba
--- /dev/null
+++ b/ax25/ax25d.conf
@@ -0,0 +1,45 @@
+# /etc/ax25/ax25d.conf
+#
+# ax25d Configuration File.
+#
+# AX.25 Ports begin with a '['.
+#
+[OH2BNS VIA 1]
+NOCALL * * * * * * L
+default * * * * * * - root /usr/local/sbin/ttylinkd ttylinkd
+#
+[OH2BNS-2 VIA 1]
+NOCALL * * * * * * L
+default * * * * * * - root /usr/sbin/node node
+#
+#
+[OH2BNS VIA 2]
+NOCALL * * * * * * L
+default * * * * * * - root /usr/local/sbin/ttylinkd ttylinkd
+#
+[OH2BNS-2 VIA 2]
+NOCALL * * * * * * L
+default * * * * * * - root /usr/sbin/node node
+#
+[OH2BNS-3 VIA 2]
+NOCALL * * * * * * L
+default * * * * * * - root /usr/local/sbin/axwrapper axwrapper /usr/bin/finger finger
+#
+#[OH2BNS-9]
+#NOCALL * * * * * * L
+#default * * * * * * - root /usr/sbin/node node
+#
+# NET/ROM Ports begin with a '<'.
+#
+#<netrom>
+#NOCALL * * * * * * L
+#default * * * * * * - root /usr/local/sbin/ttylinkd ttylinkd
+#
+<netrom>
+NOCALL * * * * * * L
+default * * * * * * - root /usr/sbin/node node
+#
+#<netrom>
+#NOCALL * * * * * * L
+#default * * * * * * - root /usr/sbin/node node
+#
diff --git a/ax25/ax25d.conf.5 b/ax25/ax25d.conf.5
new file mode 100644
index 0000000..446c0e3
--- /dev/null
+++ b/ax25/ax25d.conf.5
@@ -0,0 +1,269 @@
+.TH AX25D.CONF 5 "17 January 1997" Linux "Linux Programmer's Manual"
+.SH NAME
+ax25d.conf \- ax25d configuration file.
+.SH DESCRIPTION
+.LP
+.B Ax25d.conf
+controls the functioning of
+.B ax25d.
+Its purpose is to specify on which ports to listen on, which applications
+are available, and to whom they are available to. The configuration file is
+common to both AX.25, NET/ROM and Rose and their is similarity between the
+two parts of the file.
+.sp 1
+The general layout for an entry for a given port is as follows:
+.sp 1
+.RS
+interface control
+.br
+callsign entry 1
+.br
+ .
+.br
+ .
+.br
+callsign entry n
+.RE
+.sp 1
+The
+.B "interface control"
+line determines which port and callsigns apply to the following
+.B "callsign entry"
+lines, until the next
+.B "interface control"
+is read. There are four different variants of the
+.B "interface control"
+line:
+.sp 1
+.RS
+1. [AX.25 Port Name]
+.br
+2. [Callsign VIA AX.25 Port Name]
+.br
+3. <NET/ROM Port Name>
+.br
+4. {Callsign VIA Rose Port Name}
+.RE
+.sp 1
+Version 1 allows the following
+.B "callsign entry"
+lines to listen on the AX.25 port specified by the AX.25 port name using the
+default callsign of that AX.25 port.
+.sp 1
+Version 2 allows the following
+.B "callsign entry"
+lines to listen on the AX.25 port specified by the AX.25 port name using the
+callsign specified instead of the default callsign of that AX.25 port.
+Specifying a * for the AX.25 port name allows the following
+.B "callsign entries"
+to be valid for all the operating AX.25 ports using the callsign specified. VIA
+can be abbreviated to just V. If the callsign has an asterisk appended to it
+then the system will be listening on the port with the callsign, but as a
+pseudo-digipeater instead of being the normal destination callsign.
+.sp 1
+Version 3 allows the following
+.B "callsign entry"
+lines to listen on the NET/ROM port specified by the NET/ROM port name using
+the default callsign of that NET/ROM port.
+.sp 1
+Version 4 allows the following
+.B "callsign entry"
+lines to listen on the Rose port using the specified Rose port name using
+the callsign specified as the service access point (SAP). A * may be
+specified for a callsign to allow matching to any incoming Call Requests
+with any SAP.
+.sp 1
+The
+.B "callsign entry"
+lines have a similar layout for both AX.25, NET/ROM and Rose, the layout is:
+.sp 1
+.RS
+peer window t1 t2 t3 idle n2 mode uid exec args...
+.RE
+.sp 1
+All values must be entered for all entries even when they are not used (ie
+window for NET/ROM, just enter a * instead), The meanings of each of the
+fields is given below. All timings apart from the idle value are given in
+seconds, the idle values is given in minutes.
+.RS
+.TP 10
+.B peer
+This specifies the callsign of the remote end of the connection that should
+have the following parameters and executable set up for them. The syntax of
+the peer argument is explained below.
+.TP 10
+.B window
+This sets the the value of the window size, if a value of * is entered in this
+field then the default value for the port is taken from the \(lqparameters\(rq
+entry (see below) or lacking such an entry, the kernel default value is used.
+This entry is used by AX.25 but not by NET/ROM or Rose.
+.TP 10
+.B t1
+This sets the the value of the T1 timer, if a value of * is entered in this
+field then the default value for the port is taken from the \(lqparameters\(rq
+entry (see below) or lacking such an entry, the kernel default value is used.
+This entry is used by both AX.25 and NET/ROM but not by Rose.
+.TP 10
+.B t2
+This sets the the value of the T2 timer, if a value of * is entered in this
+field then the default value for the port is taken from the \(lqparameters\(rq
+entry (see below) or lacking such an entry, the kernel default value is used.
+This entry is used by both AX.25 and NET/ROM but not by Rose.
+.TP 10
+.B t3
+This sets the the value of the T3 timer, if a value of * is entered in this
+field then the default value for the port is taken from the \(lqparameters\(rq
+entry (see below) or lacking such an entry, the kernel default value is used.
+This entry is used by AX.25 but not by NET/ROM or Rose.
+.TP 10
+.B idle
+This sets the the value of the idle timer, if a value of * is entered in
+this field then the default value for the port is taken from the
+\(lqparameters\(rq entry (see below) or lacking such an entry, the kernel
+default value is used.
+.TP 10
+.B n2
+This sets the the value of the N2 counter, if a value of * is entered in this
+field then the default value for the port is taken from the \(lqparameters\(rq
+entry (see below) or lacking such an entry, the kernel default value is used.
+This entry is used by both AX.25 and NET/ROM but not by Rose.
+.TP 10
+.B mode
+This is a set of flags that control the various properties associated with
+the incoming connection. The flags are single letters, may be in either
+upper or lower case, and there may not be any spaces between them. If no
+flags are to be specified either a 0, - or a * must be entered instead. The
+valid mode flag letters are:
+.RS
+.TP 5
+.B D
+Do not allow connections that have passed via any digi-peaters. AX.25 only.
+.TP 5
+.B L
+Do not allow this station to connect, they are Locked out.
+.TP 5
+.B N
+Check that the NET/ROM neighbour is allowed, currently unused.
+.TP 5
+.B Q
+Do not make an entry into the log file for this connection.
+.TP 5
+.B V
+Validate the callsign of the incoming connection, currently unused.
+.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 when an incoming connection
+matches the criteria of both the
+.B "interface control"
+and the
+.B "callsign entry".
+.TP 10
+.B args...
+These are the optional arguments that are passed to the executable. All of
+the arguments are passed literally apart from the following:
+.RS
+.TP 5
+.B %d
+The name of the port that the connection is on.
+.TP 5
+.B %U
+The username (callsign) of the remote station in upper case without the SSID.
+.TP 5
+.B %u
+The username (callsign) of the remote station in lower case without the SSID.
+.TP 5
+.B %S
+The username (callsign) of the remote station in upper case with the SSID.
+.TP 5
+.B %s
+The username (callsign) of the remote station in lower case with the SSID.
+.TP 5
+.B %P
+The nodename of the remote station in upper case without the SSID.
+This is only valid under NET/ROM and Rose, under AX.25 a % is substituted instead.
+.TP 5
+.B %p
+The nodename of the remote station in lower case without the SSID.
+This is only valid under NET/ROM and Rose, under AX.25 a % is substituted instead.
+.TP 5
+.B %R
+The nodename of the remote station in upper case with the SSID.
+This is only valid under NET/ROM and Rose, under AX.25 a % is substituted instead.
+.TP 5
+.B %r
+The nodename of the remote station in lower case with the SSID.
+This is only valid under NET/ROM and Rose, under AX.25 a % is substituted instead.
+.TP 5
+.B %%
+A %.
+.RE
+.RE
+.sp 1
+The
+.B peer
+argument is dependant upon whether AX.25, NET/ROM or Rose is being used. There are
+five formats of this argument:
+.sp 1
+.RS
+1. default
+.br
+2. parameters
+.br
+3. callsign
+.br
+4. callsign@node
+.br
+5. @node
+.RE
+.sp 1
+The first version is used by AX.25, NET/ROM and Rose to specify that all callsigns
+on a given port are to be matched. The default line is usually the last of the
+.B "callsign entry"
+lines, so that more specific entries may have the chance to be matched
+first.
+.sp 1
+The second version is not a
+.B "callsign entry"
+that is used by any incoming connections. It is a means to specify default
+values for parameters such as Window, T1, T2, T3, Idle and N2. It is used for
+both AX.25, NET/ROM and Rose.
+.sp 1
+The third version is used by both AX.25, NET/ROM and Rose to specify the callsign of
+the remote station to match the
+.B "callsign entry"
+line. If no SSID is specified then the callsign will be matched with any
+that has the same callsign and any SSID. Specifying an SSID causes the
+callsign to be matched exactly. In the case of NET/ROM and Rose this entry does not
+specify which node the originating callsign comes from.
+.sp 1
+The fourth version is used by NET/ROM and Rose to specify the callsign of the remote
+station and the remote node to match the
+.B "callsign entry"
+line. If no SSID is specified in the callsign section then the callsign will
+be matched with any that has the same callsign and any SSID. Specifying an
+SSID causes the callsign to be matched exactly.
+.sp 1
+The fifth version is used by NET/ROM and Rose to specify only the address of the
+remote node to match the
+.B "callsign entry"
+line. This entry will mean that all remote users at the given node will
+match the entry.
+.sp 1
+Comments may be embedded in the configuration file by placing a # in the
+first column.
+.SH FILES
+.LP
+/etc/ax25/ax25d.conf
+.SH "SEE ALSO"
+.BR ax25 (4),
+.BR netrom (4),
+.BR rose (4),
+.BR axports (5),
+.BR nrports (5),
+.BR rsports (5),
+.BR ax25d (8).
diff --git a/ax25/axctl.8 b/ax25/axctl.8
new file mode 100644
index 0000000..3189aa8
--- /dev/null
+++ b/ax25/axctl.8
@@ -0,0 +1,67 @@
+.TH AXCTL 8 "2 August 1996" Linux "Linux System Managers Manual"
+.SH NAME
+axctl \- Configure/Kill running AX.25 connections.
+.SH SYNOPSIS
+.B axctl [-v] port dest src -window|-t1|-t2|-t3|-n2|-idle|-paclen|-kill [parm]
+.SH DESCRIPTION
+.LP
+The
+.B axctl
+command is designed to be a multi-function command that allows miscellaneous
+commands to be issued to the Linux AX.25 protocol layer for existing AX.25
+connections. The connection is uniquely identified via the combination of
+port, destination callsign and source callsign, with that information the
+kernel is able to change the parameters, or abort the connection.
+.LP
+Many of the options are similar to those found in
+.B axparms
+and perform the same function. Only one parameter may be changed on each
+invokation of
+.B axctl.
+.SH OPTIONS
+.TP 20
+.BI \-v
+Displays the version number.
+.TP 20
+.BI "\-window window"
+Sets the window size for the AX.25 connection.
+.TP 20
+.BI "\-t1 t1\-timeout"
+Sets the initial T1 timeout value for the AX.25 connection, the value is given in
+seconds.
+.TP 20
+.BI "\-t2 t2\-timeout"
+Sets the T2 timeout value for the AX.25 connection, the value is given in
+seconds.
+.TP 20
+.BI "\-t3 t3\-timeout"
+Sets the T3 timeout value for the AX.25 connected, the value is given in
+seconds.
+.TP 20
+.BI "\-n2 n2\-count"
+Sets the maximum number of tries for the AX.25 connection.
+.TP 20
+.BI "\-idle idle-timeout"
+Sets the value for the idle timer for the AX.25 connection, the value is in
+minutes.
+.TP 20
+.BI "\-paclen paclength"
+Sets the maximum packet length that may be transmitted on the AX.25
+connection.
+.TP 20
+.BI "\-kill"
+Will abort an existing AX.25 connection.
+.SH FILES
+.LP
+/etc/ax25/axports
+.SH "SEE ALSO"
+.BR call (1),
+.BR getsockopt (2),
+.BR setsockopt (2),
+.BR ax25 (4),
+.BR axparms (8),
+.BR axports (5).
+.SH AUTHORS
+.nf
+Joerg Reuter DL1BKE <jreuter@poboxes.com>
+.fi
diff --git a/ax25/axctl.c b/ax25/axctl.c
new file mode 100644
index 0000000..84422fd
--- /dev/null
+++ b/ax25/axctl.c
@@ -0,0 +1,92 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <pwd.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 <config.h>
+
+int main(int argc, char **argv)
+{
+ struct ax25_ctl_struct ax25_ctl;
+ char *addr;
+ int s;
+
+ if (argc == 2 && strncmp(argv[1], "-v", 2) == 0) {
+ printf("axctl: %s\n", VERSION);
+ return 0;
+ }
+
+ if (argc < 5) {
+ fprintf(stderr, "Usage: axctl [-v] port dest src -t1|-t2|-t3|-n2|-paclen|-idle|-window|-maxq|-kill parm\n");
+ return 1;
+ }
+
+ if (ax25_config_load_ports() == 0) {
+ fprintf(stderr, "axctl: no AX.25 port data configured\n");
+ return 1;
+ }
+
+ if ((addr = ax25_config_get_addr(argv[1])) == NULL) {
+ fprintf(stderr, "axctl: invalid port name - %s\n", argv[1]);
+ return 1;
+ }
+
+ if (ax25_aton_entry(addr, (char *)&ax25_ctl.port_addr) == -1)
+ return 1;
+ if (ax25_aton_entry(argv[2], (char *)&ax25_ctl.dest_addr) == -1)
+ return 1;
+ if (ax25_aton_entry(argv[3], (char *)&ax25_ctl.source_addr) == -1)
+ return 1;
+
+ if ((s = socket(AF_AX25, SOCK_SEQPACKET, 0)) < 0) {
+ perror("axctl: socket");
+ return 1;
+ }
+
+ if (strcmp(argv[4], "-kill") == 0) {
+ ax25_ctl.cmd = AX25_KILL;
+ ax25_ctl.arg = 0;
+ } else {
+ if (argc < 6) {
+ fprintf(stderr,"axctl: parameter missing\n");
+ return 1;
+ }
+ ax25_ctl.arg = atoi(argv[5]);
+
+ if (strcmp(argv[4], "-t1") == 0)
+ ax25_ctl.cmd = AX25_T1;
+ else if (strcmp(argv[4], "-t2") == 0)
+ ax25_ctl.cmd = AX25_T2;
+ else if (strcmp(argv[4], "-t3") == 0)
+ ax25_ctl.cmd = AX25_T3;
+ else if (strcmp(argv[4], "-idle") == 0)
+ ax25_ctl.cmd = AX25_IDLE;
+ else if (strcmp(argv[4], "-n2") == 0)
+ ax25_ctl.cmd = AX25_N2;
+ else if (strcmp(argv[4], "-window") == 0)
+ ax25_ctl.cmd = AX25_WINDOW;
+ else if (strcmp(argv[4], "-paclen") == 0)
+ ax25_ctl.cmd = AX25_PACLEN;
+ }
+
+ if (ioctl(s, SIOCAX25CTLCON, &ax25_ctl) != 0) {
+ perror("axctl: SIOAX25CTLCON");
+ return 1;
+ }
+
+ return 0;
+}
+
diff --git a/ax25/axparms.8 b/ax25/axparms.8
new file mode 100644
index 0000000..627adbf
--- /dev/null
+++ b/ax25/axparms.8
@@ -0,0 +1,119 @@
+.TH AXPARMS 8 "25 July 1997" Linux "Linux System Managers Manual"
+.SH NAME
+axparms \- Configure AX.25 interfaces.
+.SH SYNOPSIS
+.B axparms -assoc|-forward|-route|-setcall|-version ...
+.SH DESCRIPTION
+.LP
+The
+.B axparms
+command is designed to be a multi-function command that allows miscellaneous
+commands to be issued to the Linux AX.25 protocol layer. It includes the
+functionality of
+.B axassociate
+and
+.B axsetcall
+which this command superceedes. The different modes of the command are
+chosen by the first argument. Sunsequent arguments depend upon this argument
+and so no generalised command format can be given.
+.SH "-assoc Argument"
+.LP
+The format of this option is:
+.LP
+.nf
+.B axparms -assoc <callsign> <username>
+.br
+.B axparms -assoc <callsign> delete
+.br
+.B axparms -assoc policy [default|deny]
+.br
+.B axparms -assoc show
+.fi
+.LP
+This option mainpulates the kernel uid/callsign mapping table, allowing
+callsigns to be associated and dis-associated with a user. The
+.B policy
+option permits the superuser to have all other uid's either default to the
+actual port name, or to block traffic.
+.LP
+At power up the table is blank and the policy is 'default', which is thus
+backward compatible.
+.SH "-forward Argument"
+.LP
+Allows the use of many receivers with one transmitter, known as packet
+forwarding in many systems. The format of this command is:
+.LP
+.nf
+.B axparms -forward <portfrom> <portto>
+.br
+.B axparms -forward <portfrom> delete
+.fi
+.LP
+Any packets to be transmitted on port portfrom will be transmitted on port
+portto. This will stay in force until the second form of the command is
+issued which will remove the association.
+.SH "-route Argument"
+.LP
+This option allows the internal AX.25 routing table to be manipulated. This
+table is available for reading in /proc/net/ax25_route, and will be built up
+dynamically by stations heard. However it is possible to add, delete and list
+entries via this option.
+.LP
+The formats of this option are:
+.LP
+.nf
+.B axparms -route add <port> <callsign> [<digis>] [-ipmode V|D]
+.br
+.B axparms -route del <port> <callsign>
+.fi
+.B axparms -route list
+.fi
+.LP
+Routes added via this command will not be removed from the internal routing
+table when they are \(lqold\(rq as normal entries are. The
+.B -ipmode
+option sets mode vc or mode datagram for this destination.
+.LP
+If the <callsign> argument is set to \(lqdefault\(rq then this will set the
+default route for all outgoing AX.25 connections which will be used when there
+is no specific route to the required destination.
+.SH "-setcall Argument"
+.LP
+The format of this option is:
+.LP
+.B axparms -setcall <serial-device> <callsign>
+.LP
+This changes the callsign associated with the given serial device in KISS mode.
+The change is permanent until the link is downed or another \(lqaxparms
+-setcall\(rq is made.
+.LP
+The interface must already have been attached with
+.B kissattach
+to use this option.
+.SH "-version Argument"
+.LP
+This option displays the version of the AX.25 utilities that
+.B axparms
+belongs to.
+.SH FILES
+.LP
+/proc/net/ax25_bpqether
+.br
+/proc/net/ax25_calls
+.br
+/etc/ax25/axports
+.SH "SEE ALSO"
+.BR call (1),
+.BR getsockopt (2),
+.BR setsockopt (2),
+.BR ax25 (4),
+.BR axctl (8),
+.BR axports (5).
+.SH AUTHORS
+.nf
+Alan Cox GW4PTS <alan@cymru.net>
+.br
+Jonathan Naylor G4KLX <g4klx@g4klx.demon.co.uk>
+.br
+Joerg Reuter DL1BKE <jreuter@poboxes.com>
+.fi
diff --git a/ax25/axparms.c b/ax25/axparms.c
new file mode 100644
index 0000000..5683d46
--- /dev/null
+++ b/ax25/axparms.c
@@ -0,0 +1,442 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <pwd.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+
+#include <net/if.h>
+
+#include <netax25/ax25.h>
+#include <netrose/rose.h>
+
+#include <netax25/axlib.h>
+#include <netax25/axconfig.h>
+#include <config.h>
+
+#include "../pathnames.h"
+
+void usage(void)
+{
+ fprintf(stderr, "usage: axparms -assoc|-forward|-route|-setcall|-version ...\n");
+}
+
+void usageassoc(void)
+{
+ fprintf(stderr, "usage: axparms -assoc show\n");
+ fprintf(stderr, "usage: axparms -assoc policy default|deny\n");
+ fprintf(stderr, "usage: axparms -assoc [callsign] [username]\n");
+ fprintf(stderr, "usage: axparms -assoc [callsign] delete\n");
+}
+
+void usageforward(void)
+{
+ fprintf(stderr, "usage: axparms -forward <portfrom> <portto>\n");
+ fprintf(stderr, "usage: axparms -forward <portfrom> delete\n");
+}
+
+void usageroute(void)
+{
+ fprintf(stderr, "usage: axparms -route add port callsign [digi ...] [-ipmode mode]\n");
+ fprintf(stderr, "usage: axparms -route del port callsign\n");
+ fprintf(stderr, "usage: axparms -route list\n");
+}
+
+void usagesetcall(void)
+{
+ fprintf(stderr, "usage: axparms -setcall interface callsign\n");
+}
+
+int routes(int s, int argc, char *argv[], ax25_address *callsign)
+{
+ struct ax25_routes_struct ax25_route;
+ struct ax25_route_opt_struct ax25_opt;
+ int i, j;
+ int ip_mode = ' ';
+ FILE* fp;
+ char routebuf[80];
+
+ if (strcmp(argv[2], "add") == 0) {
+ ax25_route.port_addr = *callsign;
+ ax25_route.digi_count = 0;
+
+ if (strcmp(argv[4], "default") == 0) {
+ ax25_route.dest_addr = null_ax25_address;
+ } else {
+ if (ax25_aton_entry(argv[4], (char *)&ax25_route.dest_addr) == -1)
+ return 1;
+ }
+
+ for (i = 5, j = 0; i < argc && j < 6; i++) {
+ if (strncmp(argv[i], "-i", 2) == 0) {
+ if (++i == argc) {
+ fprintf(stderr, "axparms: -i must have a parameter\n");
+ return 1;
+ }
+ switch (*argv[i]) {
+ case 'd':
+ case 'D':
+ ip_mode = 'D';
+ break;
+ case 'v':
+ case 'V':
+ ip_mode = 'V';
+ break;
+ default:
+ ip_mode = ' ';
+ break;
+ }
+ } else {
+ if (ax25_aton_entry(argv[i], (char *)&ax25_route.digi_addr[j]) == -1)
+ return 1;
+ ax25_route.digi_count++;
+ j++;
+ }
+ }
+
+ if (ioctl(s, SIOCADDRT, &ax25_route) != 0) {
+ perror("axparms: SIOCADDRT");
+ return 1;
+ }
+
+ ax25_opt.port_addr = *callsign;
+ ax25_opt.dest_addr = ax25_route.dest_addr;
+ ax25_opt.cmd = AX25_SET_RT_IPMODE;
+ ax25_opt.arg = ip_mode;
+
+ if (ioctl(s, SIOCAX25OPTRT, &ax25_opt) != 0) {
+ perror("axparms: SIOCAX25OPTRT");
+ return 1;
+ }
+ }
+
+ if (strcmp(argv[2], "del") == 0) {
+ ax25_route.port_addr = *callsign;
+ ax25_route.digi_count = 0;
+
+ if (strcmp(argv[4], "default") == 0) {
+ ax25_route.dest_addr = null_ax25_address;
+ } else {
+ if (ax25_aton_entry(argv[4], (char *)&ax25_route.dest_addr) == -1)
+ return 1;
+ }
+
+ if (ioctl(s, SIOCDELRT, &ax25_route) != 0) {
+ perror("axparms: SIOCDELRT");
+ return 1;
+ }
+ }
+
+ if (strcmp(argv[2], "list") == 0) {
+ if ((fp=fopen(PROC_AX25_ROUTE_FILE,"r")) == NULL) {
+ fprintf(stderr, "axparms: route: cannot open %s\n",
+PROC_AX25_ROUTE_FILE);
+ return 1;
+ }
+ while (fgets(routebuf,80,fp))
+ printf(routebuf);
+ puts("");
+ }
+
+ return 0;
+}
+
+int setifcall(int s, char *ifn, char *name)
+{
+ char call[7];
+ struct ifreq ifr;
+
+ if (ax25_aton_entry(name, call) == -1)
+ return 1;
+
+ strcpy(ifr.ifr_name, ifn);
+ memcpy(ifr.ifr_hwaddr.sa_data, call, 7);
+ ifr.ifr_hwaddr.sa_family = AF_AX25;
+
+ if (ioctl(s, SIOCSIFHWADDR, &ifr) != 0) {
+ perror("axparms: SIOCSIFHWADDR");
+ return 1;
+ }
+
+ return 0;
+}
+
+int associate(int s, int argc, char *argv[])
+{
+ char buffer[80], *u, *c;
+ struct sockaddr_ax25 sax25;
+ struct passwd *pw;
+ int opt;
+ FILE *fp;
+
+
+ if (strcmp(argv[2], "show") == 0) {
+ if (argc < 3) {
+ usageassoc();
+ exit(1);
+ }
+
+ if ((fp = fopen(PROC_AX25_CALLS_FILE, "r")) == NULL) {
+ fprintf(stderr, "axparms: associate: cannot open %s\n", PROC_AX25_CALLS_FILE);
+ return 1;
+ }
+
+ fgets(buffer, 80, fp);
+
+ printf("Userid Callsign\n");
+
+ while (fgets(buffer, 80, fp) != NULL) {
+ u = strtok(buffer, " \t\n");
+ c = strtok(NULL, " \t\n");
+ if ((pw = getpwuid(atoi(u))) != NULL)
+ printf("%-10s %s\n", pw->pw_name, c);
+ }
+
+ fclose(fp);
+
+ return 0;
+ }
+
+ if (strcmp(argv[2], "policy") == 0) {
+ if (argc < 4) {
+ usageassoc();
+ exit(1);
+ }
+
+ if (strcmp(argv[3], "default") == 0) {
+ opt = AX25_NOUID_DEFAULT;
+
+ if (ioctl(s, SIOCAX25NOUID, &opt) == -1) {
+ perror("axparms: SIOCAX25NOUID");
+ return 1;
+ }
+
+ return 0;
+ }
+
+ if (strcmp(argv[3], "deny") == 0) {
+ opt = AX25_NOUID_BLOCK;
+
+ if (ioctl(s, SIOCAX25NOUID, &opt) == -1) {
+ perror("axparms: SIOCAX25NOUID");
+ return 1;
+ }
+
+ return 0;
+ }
+
+ fprintf(stderr, "axparms: associate: 'default' or 'deny' required\n");
+
+ return 1;
+ }
+
+ if (argc < 4) {
+ usageassoc();
+ exit(1);
+ }
+
+ if (ax25_aton_entry(argv[2], (char *)&sax25.sax25_call) == -1) {
+ fprintf(stderr, "axparms: associate: invalid callsign %s\n", argv[2]);
+ return 1;
+ }
+
+ if (strcmp(argv[3], "delete") == 0) {
+ if (ioctl(s, SIOCAX25DELUID, &sax25) == -1) {
+ perror("axparms: SIOCAX25DELUID");
+ return 1;
+ }
+
+ return 0;
+ }
+
+ if ((pw = getpwnam(argv[3])) == NULL) {
+ fprintf(stderr, "axparms: associate: unknown username %s\n", argv[3]);
+ return 1;
+ }
+
+ sax25.sax25_uid = pw->pw_uid;
+
+ if (ioctl(s, SIOCAX25ADDUID, &sax25) == -1) {
+ perror("axparms: SIOCAX25ADDUID");
+ return 1;
+ }
+
+ return 0;
+}
+
+int forward(int s, int argc, char *argv[])
+{
+#ifdef HAVE_AX25_FWD_STRUCT
+ struct ax25_fwd_struct ax25_fwd;
+ char *addr;
+
+ if (argc < 4) {
+ usageforward();
+ exit(1);
+ }
+
+ if (ax25_config_load_ports() == 0) {
+ fprintf(stderr, "axparms: no AX.25 port data configured\n");
+ return 1;
+ }
+
+ if ((addr = ax25_config_get_addr(argv[2])) == NULL) {
+ fprintf(stderr, "axparms: invalid port name - %s\n", argv[2]);
+ return 1;
+ }
+
+ if (ax25_aton_entry(addr, (char *)&ax25_fwd.port_from) == -1) {
+ fprintf(stderr, "axparms: invalid port name - %s\n", argv[2]);
+ return 1;
+ }
+
+ if (strcmp(argv[3], "delete") == 0) {
+ if (ioctl(s, SIOCAX25DELFWD, &ax25_fwd) == -1) {
+ perror("axparms: SIOCAX25DELFWD");
+ return 1;
+ }
+
+ return 0;
+ }
+
+ if ((addr = ax25_config_get_addr(argv[3])) == NULL) {
+ fprintf(stderr, "axparms: invalid port name - %s\n", argv[3]);
+ return 1;
+ }
+
+ if (ax25_aton_entry(addr, (char *)&ax25_fwd.port_to) == -1) {
+ fprintf(stderr, "axparms: invalid port name - %s\n", argv[3]);
+ return 1;
+ }
+
+ if (ioctl(s, SIOCAX25ADDFWD, &ax25_fwd) == -1) {
+ perror("axparms: SIOCAX25ADDFWD");
+ return 1;
+ }
+#else
+ fprintf(stderr, "axparms: Not compiled in with forwarding option.\n");
+#endif /* HAVE_AX25_FWD_STRUCT */
+
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ ax25_address callsign;
+ int s, n;
+ char *addr;
+
+ if (argc == 1) {
+ usage();
+ return 1;
+ }
+
+ if (strncmp(argv[1], "-v", 2) == 0) {
+ printf("axparms: %s\n", VERSION);
+ return 0;
+ }
+
+ if (strncmp(argv[1], "-a", 2) == 0) {
+
+ if (argc < 3) {
+ usageassoc();
+ return 1;
+ }
+
+ if ((s = socket(AF_AX25, SOCK_SEQPACKET, 0)) < 0) {
+ perror("axparms: socket");
+ return 1;
+ }
+
+ n = associate(s, argc, argv);
+
+ close(s);
+
+ return n;
+ }
+
+ if (strncmp(argv[1], "-f", 2) == 0) {
+ if (argc == 2) {
+ usageforward();
+ return 1;
+ }
+
+ if ((s = socket(AF_AX25, SOCK_SEQPACKET, 0)) < 0) {
+ perror("axparms: socket");
+ return 1;
+ }
+
+ n = forward(s, argc, argv);
+
+ close(s);
+
+ return n;
+ }
+
+ if (strncmp(argv[1], "-r", 2) == 0) {
+ if (argc < 3 ) {
+ usageroute();
+ return 1;
+ }
+
+ if (strcmp(argv[2], "add") != 0 && strcmp(argv[2], "del") != 0 && strcmp(argv[2], "list") != 0) {
+ usageroute();
+ return 1;
+ }
+
+ if (argc < 5 && strcmp(argv[2], "list") != 0) {
+ usageroute();
+ return 1;
+ }
+
+ if (ax25_config_load_ports() == 0) {
+ fprintf(stderr, "axparms: no AX.25 port data configured\n");
+ return 1;
+ }
+
+ if ((addr = ax25_config_get_addr(argv[3])) == NULL) {
+ fprintf(stderr, "axparms: invalid port name - %s\n", argv[3]);
+ return 1;
+ }
+
+ if (ax25_aton_entry(addr, callsign.ax25_call) == -1)
+ return 1;
+
+ if ((s = socket(AF_AX25, SOCK_SEQPACKET, 0)) < 0) {
+ perror("axparms: socket");
+ return 1;
+ }
+
+ n = routes(s, argc, argv, &callsign);
+
+ close(s);
+
+ return n;
+ }
+
+ if (strncmp(argv[1], "-s", 2) == 0) {
+ if (argc != 4) {
+ usagesetcall();
+ return 1;
+ }
+
+ if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ perror("axparms: socket");
+ return 1;
+ }
+
+ n = setifcall(s, argv[2], argv[3]);
+
+ close(s);
+
+ return n;
+ }
+
+ usage();
+
+ return 1;
+}
diff --git a/ax25/axports.5 b/ax25/axports.5
new file mode 100644
index 0000000..fc61a47
--- /dev/null
+++ b/ax25/axports.5
@@ -0,0 +1,62 @@
+.TH AXPORTS 5 "15 October 1996" Linux "Linux Programmer's Manual"
+.SH NAME
+axports \- AX.25 port configuration file.
+.SH DESCRIPTION
+.LP
+.B Axports
+is an ASCII file that contains information about each of the physical AX.25
+ports that are to be used. When dealing with an AX.25 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 axports,
+which has that name as its first argument. The information on each line
+contains enough information to bind the command to a particular physical AX.25
+interface, this binding is done by matching the callsign on the line in
+.B axports
+with the callsign of the port set by
+.B kissattach.
+.LP
+The lines within
+.B axports
+must either be a comment line, which starts with a # in the first column, or
+a port description in the following format, each field being delimited by
+white space:
+.sp
+.RS
+name callsign speed paclen window description
+.RE
+.sp
+The field descriptions are:
+.sp
+.RS
+.TP 14
+.B name
+is the unique identifier of the port. This is the name given as the port
+argument of many of the AX.25 support programs.
+.TP 14
+.B callsign
+the callsign of the physical interface to bind to.
+.TP 14
+.B speed
+this is the speed of interface, a value of zero means that no speed will be
+set by kissattach(8).
+.TP 14
+.B paclen
+is the default maximum packet size for this interface.
+.TP 14
+.B window
+the default window size for this interface.
+.TP 14
+.B description
+a free format description of this interface, this field extends to the end
+of the line. This field may contain spaces.
+.RE
+.SH FILES
+.LP
+/etc/ax25/axports
+.SH "SEE ALSO"
+.BR call (1),
+.BR ax25 (4),
+.BR axparms (8),
+.BR kissattach (8).
diff --git a/ax25/axspawn.8 b/ax25/axspawn.8
new file mode 100644
index 0000000..ccb6934
--- /dev/null
+++ b/ax25/axspawn.8
@@ -0,0 +1,52 @@
+.TH AXSPAWN 8 "25 August 1996" Linux "Linux System Managers Manual"
+.SH NAME
+axspawn \- Allow automatic login to a Linux system.
+.SH SYNOPSIS
+.B axspawn [--wait, -w]
+.SH DESCRIPTION
+.LP
+.B Axspawn
+will check if the peer is an AX.25 connect, the callsign a valid Amateur
+Radio callsign, strip the SSID, check if UID/GID are valid, allow a
+password-less login if the password-entry in /etc/passwd is \(lq+\(rq or
+empty; in every other case login will prompt for a password.
+.LP
+.B Axspawn
+can create user accounts automatically. You may specify the user shell,
+first and maximum user id, group ID in the config file and (unlike WAMPES)
+create a file \(lq/etc/ax25/ax25.profile\(rq which will be copied to
+~/.profile.
+.SH SECURITY
+.LP
+Auto accounting is a security problem by definition. Unlike WAMPES, which
+creates an empty password field, Axspawn adds an \(lqimpossible\(rq ('+')
+password to /etc/passwd. Login gets called with the \(lq-f\(rq option, thus
+new users have the chance to login without a password. (I guess this won't
+work with the shadow password system).
+.LP
+Of course
+.B axspawn
+does callsign checking: Only letters and numbers are allowed, the callsign
+must be longer than 4 characters and shorter than 6 characters (without
+SSID). There must be at least one digit, and max. two digits within the
+call. The SSID must be within the range of 0 and 15. Please drop me a note
+if you know a valid Amateur Radio callsign that does not fit this pattern
+_and_ can be represented correctly in AX.25.
+.SH OPTIONS
+.TP 5
+.B -w, --wait
+Disables the prompting for a password if the password entry in /etc/passwd
+is either a \(lq+\(rq or blank.
+.SH FILES
+.nf
+/etc/passwd
+.br
+/etc/ax25/ax25.profile
+.br
+/etc/ax25/axspawn.conf
+.fi
+.SH "SEE ALSO"
+.BR axspawn.conf (5),
+.BR ax25d (8).
+.SH AUTHOR
+Joerg Reuter DL1BKE <jreuter@poboxes.com>
diff --git a/ax25/axspawn.c b/ax25/axspawn.c
new file mode 100644
index 0000000..88381cf
--- /dev/null
+++ b/ax25/axspawn.c
@@ -0,0 +1,911 @@
+/*
+ *
+ * $Id: axspawn.c,v 1.6 1996/08/24 22:33:05 jreuter Exp jreuter $
+ *
+ * axspawn.c - run a program from ax25d.
+ *
+ * Copyright (c) 1996 Jörg Reuter DL1BKE (jreuter@poboxes.com)
+ *
+ * This program is a hack.
+ *
+ * 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.
+ *
+ * It might even kill your cat... ;-)
+ *
+ * Status: alpha (still...)
+ *
+ * usage: change the "default" lines in your /usr/local/etc/ax25d.conf:
+ *
+ * default * * * * * 1 root /usr/local/sbin/axspawn axspawn
+ *
+ * a line like this would wait for an incoming info frame first.
+ *
+ * default * * * * * 1 root /usr/local/sbin/axspawn axspawn --wait
+ *
+ * The program will check if the peer is an AX.25 socket, the
+ * callsign is a valid amateur radio callsign, strip the SSID,
+ * check if UID/GID are valid, allow a password-less login if the
+ * password-entry in /etc/passwd is "+" or empty; in every other case
+ * login will prompt for a password.
+ *
+ * Still on my TODO list: a TheNet compatible or MD5 based
+ * authentication scheme... Won't help you if you changed the "+"-entry
+ * in /etc/passwd to a valid passord and login with telnet, though.
+ * A better solution could be a small program called from .profile.
+ *
+ * Axspawn can create user accounts automatically. You may specify
+ * the user shell, first and maximum user id, group ID in the config
+ * file and (unlike WAMPES) create a file "/usr/local/etc/ax25.profile"
+ * which will be copied to ~/.profile.
+ *
+ * This is an example for the config file:
+ *
+ * # this is /usr/local/etc/axspawn.conf
+ * #
+ * # allow automatic creation of user accounts
+ * create yes
+ * #
+ * # guest user if above is 'no' or everything else fails. Disable with "no"
+ * guest ax25
+ * #
+ * # group id or name for autoaccount
+ * group ax25
+ * #
+ * # first user id to use
+ * first_uid 400
+ * #
+ * # maximum user id
+ * max_uid 2000
+ * #
+ * # where to add the home directory for the new user
+ * home /home/ax25
+ * #
+ * # user's shell
+ * shell /bin/bash
+ * #
+ * # bind user id to callsign for outgoing connects.
+ * associate yes
+ *
+ * SECURITY:
+ *
+ * Umm... auto accounting is a security problem by definition. Unlike
+ * WAMPES, which creates an empty password field, Axspawn adds an
+ * "impossible" ('+') password to /etc/passwd. Login gets called with
+ * the "-f" option, thus new users have the chance to login without
+ * a password. (I guess this won't work with the shadow password system).
+ *
+ * The "associate" option has to be used with great care. If a user
+ * logs on it removes any existing callsign from the translation table
+ * for this userid and replaces it with the callsign and SSID of the
+ * user. This will happen with multiple connects (same callsign,
+ * different SSIDs), too. Unless you want your users to be able
+ * to call out from your machine disable "associate".
+ *
+ * Of course Axspawn does callsign checking: Only letters and numbers
+ * are allowed, the callsign must be longer than 4 characters and
+ * shorter than 6 characters (without SSID). There must be at least
+ * one digit, and max. two digits within the call. The SSID must
+ * be within the range of 0 and 15. Please drop me a note if you
+ * know a valid Amateur Radio (sic!) callsign that does not fit this
+ * pattern _and_ can be represented correctly in AX.25.
+ *
+ * It uses the forkpty from libbsd.a (found after analyzing logind)
+ * which has no prototype in any of my .h files.
+ *
+ */
+
+/* removed -h <protocol> from login command as it was causing hostname lookups
+ with new login/libc - Terry, vk2ktj. */
+
+
+#define QUEUE_DELAY 400 /* 400 msec */
+#define USERPROFILE ".profile"
+#define PASSWDFILE "/etc/passwd"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <strings.h>
+#include <ctype.h>
+#include <termios.h>
+#include <unistd.h>
+#include <signal.h>
+#include <pwd.h>
+#include <grp.h>
+#include <utmp.h>
+#include <paths.h>
+#include <errno.h>
+#include <syslog.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/file.h>
+
+#include <sys/socket.h>
+
+#include <netax25/ax25.h>
+#include <netrose/rose.h>
+#include <netax25/axlib.h>
+
+#include "../pathnames.h"
+
+#define MAXLEN strlen("DB0PRA-15")
+#define MINLEN strlen("KA9Q")
+
+#define AX_PACLEN 256
+#define NETROM_PACLEN 236
+#define ROSE_PACLEN 128
+
+#define IS_DIGIT(x) ( (x >= '0') && (x <= '9') )
+#define IS_LETTER(x) ( (x >= 'A') && (x <= 'Z') )
+
+#define MSG_NOCALL "Sorry, you are not allowed to connect.\n"
+#define MSG_CANNOTFORK "Sorry, system is overloaded.\n"
+#define MSG_NOPTY "Sorry, all channels in use.\n"
+#define MSG_NOTINDBF "Sorry, you are not in my database\n"
+
+#define EXITDELAY 10
+
+char policy_add_user = 1;
+char policy_guest = 1;
+char policy_associate = 0;
+
+gid_t user_gid = 400;
+char *user_shell = "/bin/bash";
+char *start_home = "/home/funk";
+char *guest = "guest";
+int start_uid = 400;
+int end_uid = 65535;
+int paclen = ROSE_PACLEN; /* Its the shortest ie safest */
+
+struct write_queue {
+ struct write_queue *next;
+ char *data;
+ int len;
+};
+
+struct write_queue *wqueue_head = NULL;
+struct write_queue *wqueue_tail = NULL;
+long wqueue_length = 0;
+
+/* This one is in /usr/lib/libbsd.a, but not in bsd.h and fellows... weird. */
+/* (found in logind.c) */
+
+pid_t forkpty(int *, char *, void *, struct winsize *);
+
+int _write_ax25(const char *s, int len)
+{
+ int k, m;
+ char *p;
+
+ p = (char *) malloc(len+1);
+
+ if (p == NULL)
+ return 0;
+
+ m = 0;
+ for (k = 0; k < len; k++)
+ {
+ if ( (s[k] == '\r') && ((k+1) < len) && (s[k+1] == '\n') )
+ continue;
+ else if (s[k] == '\n')
+ p[m++] = '\r';
+ else
+ p[m++] = s[k];
+ }
+
+ if (m)
+ write(1, p, m);
+
+ free(p);
+ return len;
+}
+
+int read_ax25(char *s, int size)
+{
+ int len = read(0, s, size);
+ int k;
+
+ for (k = 0; k < len; k++)
+ if (s[k] == '\r') s[k] = '\n';
+
+ return len;
+}
+
+/*
+ * We need to buffer the data from the pipe since bash does
+ * a fflush() on every output line. We don't want it, it's
+ * PACKET radio, isn't it?
+ */
+
+void kick_wqueue(int dummy)
+{
+ char *s, *p;
+ struct write_queue *buf;
+
+
+ if (wqueue_length == 0)
+ return;
+
+ s = (char *) malloc(wqueue_length);
+
+ p = s;
+
+ while (wqueue_head)
+ {
+ buf = wqueue_head;
+ wqueue_head = buf->next;
+
+ memcpy(p, buf->data, buf->len);
+ p += buf->len;
+ free(buf->data);
+ free(buf);
+ }
+
+ _write_ax25(s, wqueue_length);
+ free(s);
+ wqueue_tail=NULL;
+ wqueue_length=0;
+}
+
+int write_ax25(const char *s, int len)
+{
+ struct itimerval itv, oitv;
+ struct write_queue * buf;
+
+ signal(SIGALRM, SIG_IGN);
+
+ buf = (struct write_queue *) malloc(sizeof(struct write_queue));
+ if (buf == NULL)
+ return 0;
+
+ buf->data = (char *) malloc(len);
+ if (buf->data == NULL)
+ return 0;
+
+ memcpy(buf->data, s, len);
+ buf->len = len;
+ buf->next = NULL;
+
+ if (wqueue_head == NULL)
+ {
+ wqueue_head = buf;
+ wqueue_tail = buf;
+ wqueue_length = len;
+ } else {
+ wqueue_tail->next = buf;
+ wqueue_tail = buf;
+ wqueue_length += len;
+ }
+
+ if (wqueue_length >= paclen)
+ {
+ kick_wqueue(0);
+ } else {
+ itv.it_interval.tv_sec = 0;
+ itv.it_interval.tv_usec = 0;
+ itv.it_value.tv_sec = 0;
+ itv.it_value.tv_usec = QUEUE_DELAY;
+
+ setitimer(ITIMER_REAL, &itv, &oitv);
+ signal(SIGALRM, kick_wqueue);
+ }
+ return len;
+}
+
+int get_assoc(struct sockaddr_ax25 *sax25)
+{
+ FILE *fp;
+ int uid;
+ char buf[81];
+
+ fp = fopen(PROC_AX25_CALLS_FILE, "r");
+ if (!fp) return -1;
+
+ fgets(buf, sizeof(buf)-1, fp);
+
+ while(!feof(fp))
+ {
+ if (fscanf(fp, "%d %s", &uid, buf) == 2)
+ if (sax25->sax25_uid == uid)
+ {
+ ax25_aton_entry(buf, (char *) &sax25->sax25_call);
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+
+void cleanup(char *tty)
+{
+ struct utmp ut, *ut_line;
+ FILE *fp;
+
+ setutent();
+ ut.ut_type = LOGIN_PROCESS;
+ strncpy(ut.ut_id, tty + 3, sizeof(ut.ut_line));
+ ut_line = getutid(&ut);
+
+ if (ut_line != NULL) {
+ ut_line->ut_type = DEAD_PROCESS;
+ ut_line->ut_host[0] = '\0';
+ ut_line->ut_user[0] = '\0';
+ time(&ut_line->ut_time);
+ pututline(ut_line);
+ if ((fp = fopen(_PATH_WTMP, "r+")) != NULL) {
+ fseek(fp, 0L, SEEK_END);
+ if (fwrite(ut_line, sizeof(ut), 1, fp) != 1)
+ syslog(LOG_ERR, "Ooops, I think I've just barbecued your wtmp file\n");
+ fclose(fp);
+ }
+ }
+
+ endutent();
+}
+
+
+/*
+ * add a new user to /etc/passwd and do some init
+ */
+
+void new_user(char *newuser)
+{
+ struct passwd pw, *pwp;
+ uid_t uid;
+ FILE *fp;
+ char username[80];
+ char homedir[256], userdir[256];
+ char buf[4096];
+ char subdir[4];
+ int cnt;
+ unsigned char *p, *q;
+ struct stat fst;
+ int fd_a, fd_b, fd_l;
+
+ /*
+ * build path for home directory
+ */
+
+ strncpy(subdir, newuser, 3);
+ subdir[3] = '\0';
+ sprintf(username, "%s", newuser);
+ sprintf(homedir, "%s/%s.../%s", start_home, subdir, newuser);
+ strcpy(userdir, homedir);
+
+ fd_l = open(LOCK_AXSPAWN_FILE, O_CREAT | O_APPEND, S_IRUSR | S_IWUSR);
+ flock(fd_l, LOCK_EX);
+
+retry:
+ /*
+ * find first free UID
+ */
+
+ for (uid = start_uid; uid < 65535; uid++)
+ {
+ pwp = getpwuid(uid);
+ if (pwp == NULL)
+ break;
+ }
+
+ if (uid >= 65535 || uid < start_uid)
+ return;
+
+ /*
+ * build directories for home
+ */
+
+ p = homedir;
+
+ while (*p == '/') p++;
+
+ chdir("/");
+
+ while(p)
+ {
+ q = strchr(p, '/');
+ if (q)
+ {
+ *q = '\0';
+ q++;
+ while (*q == '/') q++;
+ if (*q == 0) q = NULL;
+ }
+
+ if (stat(p, &fst) < 0)
+ {
+ if (errno == ENOENT)
+ {
+ mkdir(p, S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
+
+ if (q == NULL)
+ {
+ chown(p, uid, user_gid);
+ chmod(p, S_IRUSR|S_IWUSR|S_IXUSR);
+ }
+ }
+ else
+ return;
+ }
+
+ if (chdir(p) < 0)
+ return;
+ p = q;
+ }
+
+ /*
+ * add the user now
+ */
+
+ fp = fopen(PASSWDFILE, "a+");
+ if (fp == NULL)
+ return;
+
+ pw.pw_name = newuser;
+ pw.pw_passwd = "+";
+ pw.pw_uid = uid;
+ pw.pw_gid = user_gid;
+ pw.pw_gecos = username;
+ pw.pw_dir = userdir;
+ pw.pw_shell = user_shell;
+
+ if (getpwuid(uid) != NULL) goto retry; /* oops?! */
+
+ if (putpwent(&pw, fp) < 0)
+ return;
+
+ flock(fd_l, LOCK_UN);
+ fclose(fp);
+
+ /*
+ * copy ax25.profile
+ */
+
+ fd_a = open(CONF_AXSPAWN_PROF_FILE, O_RDONLY);
+
+ if (fd_a > 0)
+ {
+ fd_b = open(USERPROFILE, O_CREAT|O_WRONLY, S_IRUSR|S_IWUSR|S_IXUSR);
+
+ if (fd_b < 0)
+ return;
+
+ while ( (cnt = read(fd_a, &buf, sizeof(buf))) > 0 )
+ write(fd_b, &buf, cnt);
+ close(fd_b);
+ close(fd_a);
+ chown(USERPROFILE, uid, user_gid);
+ }
+}
+
+void read_config(void)
+{
+ FILE *fp = fopen(CONF_AXSPAWN_FILE, "r");
+ char buf[512];
+ char cmd[40], param[80];
+ char *p;
+
+ if (fp == NULL)
+ return;
+
+ while (!feof(fp))
+ {
+ fgets(buf, sizeof(buf), fp);
+ p = strchr(buf, '#');
+ if (p) *p='\0';
+
+ if (buf[0] != '\0')
+ {
+ sscanf(buf, "%s %s", cmd, param);
+
+ if (!strncmp(cmd, "create", 5))
+ {
+ policy_add_user = (param[0] == 'y');
+ } else
+ if (!strncmp(cmd, "guest", 5))
+ {
+ if (!strcmp(param, "no"))
+ {
+ policy_guest = 0;
+ } else {
+ policy_guest = 1;
+ guest = (char *) malloc(strlen(param)+1);
+ strcpy(guest, param);
+ }
+ } else
+ if (!strncmp(cmd, "group", 5))
+ {
+ user_gid = strtol(param, &p, 0);
+ if (*p != '\0')
+ {
+ struct group * gp = getgrnam(param);
+ if (gp != NULL)
+ user_gid = gp->gr_gid;
+ else
+ user_gid = 400;
+ endgrent();
+ }
+ } else
+ if (!strncmp(cmd, "first", 5))
+ {
+ start_uid = strtol(param, &p, 0);
+ if (*p != '\0')
+ start_uid = 400;
+ } else
+ if (!strncmp(cmd, "max", 3))
+ {
+ end_uid = strtol(param, &p, 0);
+ if (*p != '\0')
+ end_uid = 0;
+ } else
+ if (!strncmp(cmd, "home", 4))
+ {
+ start_home = (char *) malloc(strlen(param)+1);
+ strcpy(start_home, param);
+ } else
+ if (!strncmp(cmd, "assoc", 5))
+ {
+ if (!strcmp(param, "yes"))
+ policy_associate = 1;
+ else
+ policy_associate = 0;
+ } else
+ if (!strncmp(cmd, "shell", 5))
+ {
+ user_shell = (char *) malloc(strlen(param)+1);
+ strcpy(user_shell, param);
+ } else
+ {
+ printf("error in config: ->%s %s<-\n", cmd, param);
+ }
+ }
+ }
+
+ fclose(fp);
+}
+
+char ptyslave[20];
+int child_pid;
+
+void signal_handler(int dummy)
+{
+ kill(child_pid, SIGHUP);
+ cleanup(ptyslave+5);
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+ char call[20], user[20], real_user[20];
+ char buf[2048];
+ int k, cnt, digits, letters, invalid, ssid, ssidcnt, addrlen;
+ int fdmaster;
+ pid_t pid = -1;
+ char *p;
+ fd_set fds_read, fds_err;
+ struct passwd *pw;
+ int chargc;
+ char *chargv[20];
+ int envc;
+ char *envp[20];
+ char wait_for_tcp;
+ struct utmp ut_line;
+ struct winsize win = { 0, 0, 0, 0};
+ struct sockaddr_ax25 sax25;
+ union {
+ struct full_sockaddr_ax25 fsax25;
+ struct sockaddr_rose rose;
+ } sockaddr;
+ char *protocol;
+
+ digits = letters = invalid = ssid = ssidcnt = 0;
+
+ if (argc > 1 && (!strcmp(argv[1],"-w") || !strcmp(argv[1],"--wait")))
+ wait_for_tcp = 1;
+ else
+ wait_for_tcp = 0;
+
+ read_config();
+
+ openlog("axspawn", LOG_PID, LOG_DAEMON);
+
+ if (getuid() != 0) {
+ printf("permission denied\n");
+ syslog(LOG_NOTICE, "user %d tried to run axspawn\n", getuid());
+ return 1;
+ }
+
+ addrlen = sizeof(struct full_sockaddr_ax25);
+ k = getpeername(0, (struct sockaddr *) &sockaddr, &addrlen);
+
+ if (k < 0) {
+ syslog(LOG_NOTICE, "getpeername: %m\n");
+ return 1;
+ }
+
+ switch (sockaddr.fsax25.fsa_ax25.sax25_family) {
+ case AF_AX25:
+ strcpy(call, ax25_ntoa(&sockaddr.fsax25.fsa_ax25.sax25_call));
+ protocol = "AX.25";
+ paclen = AX_PACLEN;
+ break;
+
+ case AF_NETROM:
+ strcpy(call, ax25_ntoa(&sockaddr.fsax25.fsa_ax25.sax25_call));
+ protocol = "NET/ROM";
+ paclen = NETROM_PACLEN;
+ break;
+
+ case AF_ROSE:
+ strcpy(call, ax25_ntoa(&sockaddr.rose.srose_call));
+ protocol = "Rose";
+ paclen = ROSE_PACLEN;
+ break;
+
+ default:
+ syslog(LOG_NOTICE, "peer is not an AX.25, NET/ROM or Rose socket\n");
+ return 1;
+ }
+
+ for (k = 0; k < strlen(call); k++)
+ {
+ if (ssidcnt)
+ {
+ if (!IS_DIGIT(call[k]))
+ invalid++;
+ else
+ {
+ if (ssidcnt > 2)
+ invalid++;
+ else if (ssidcnt == 1)
+ ssid = (int) (call[k] - '0');
+ else
+ {
+ ssid *= 10;
+ ssid += (int) (call[k] - '0');
+
+ if (ssid > 15) invalid++;
+ }
+ ssidcnt++;
+ }
+ } else
+ if (IS_DIGIT(call[k]))
+ {
+ digits++;
+ if (k > 3) invalid++;
+ } else
+ if (IS_LETTER(call[k]))
+ letters++;
+ else
+ if (call[k] == '-')
+ {
+ if (k < MINLEN)
+ invalid++;
+ else
+ ssidcnt++;
+ }
+ else
+ invalid++;
+ }
+
+ if ( invalid || (k < MINLEN) || (digits > 2) || (digits < 1) )
+ {
+ write_ax25(MSG_NOCALL, sizeof(MSG_NOCALL));
+ syslog(LOG_NOTICE, "%s is not an Amateur Radio callsign\n", call);
+ sleep(EXITDELAY);
+ return 1;
+ }
+
+ strcpy(user, call);
+ strlwr(user);
+ p = strchr(user, '-');
+ if (p) *p = '\0';
+ strcpy(real_user, user);
+
+ if (wait_for_tcp)
+ read_ax25(buf, sizeof(buf)); /* incoming TCP/IP connection? */
+
+ pw = getpwnam(user);
+
+ if (pw == NULL)
+ {
+ if (policy_add_user)
+ {
+ new_user(user);
+ pw = getpwnam(user);
+ }
+
+ if (pw == NULL && policy_guest)
+ {
+ strcpy(real_user,guest);
+ pw = getpwnam(guest);
+
+ if (! (pw && pw->pw_uid && pw->pw_gid) )
+ {
+ write_ax25(MSG_NOTINDBF, sizeof(MSG_NOTINDBF));
+ syslog(LOG_NOTICE, "%s (callsign: %s) not found in /etc/passwd\n", user, call);
+ sleep(EXITDELAY);
+ return 1;
+ }
+ }
+ }
+
+ endpwent();
+
+ if (pw->pw_uid == 0 || pw->pw_gid == 0)
+ {
+ write_ax25(MSG_NOCALL, sizeof(MSG_NOCALL));
+ syslog(LOG_NOTICE, "root login of %s (callsign: %s) denied\n", user, call);
+ sleep(EXITDELAY);
+ return 1;
+ }
+
+ /*
+ * associate UID with callsign (or vice versa?)
+ */
+
+ if (policy_associate)
+ {
+ int fds = socket(AF_AX25, SOCK_SEQPACKET, 0);
+ if (fds != -1)
+ {
+ sax25.sax25_uid = pw->pw_uid;
+ if (get_assoc(&sax25) != -1)
+ ioctl(fds, SIOCAX25DELUID, &sax25);
+ switch (sockaddr.fsax25.fsa_ax25.sax25_family) {
+ case AF_AX25:
+ case AF_NETROM:
+ sax25.sax25_call = sockaddr.fsax25.fsa_ax25.sax25_call;
+ break;
+ case AF_ROSE:
+ sax25.sax25_call = sockaddr.rose.srose_call;
+ break;
+ }
+ ioctl(fds, SIOCAX25ADDUID, &sax25);
+ close(fds);
+ }
+ }
+
+ fcntl(1, F_SETFL, O_NONBLOCK);
+
+ pid = forkpty(&fdmaster, ptyslave, NULL, &win);
+
+ if (pid == 0)
+ {
+ struct termios termios;
+
+ memset((char *) &termios, 0, sizeof(termios));
+
+ ioctl(0, TIOCSCTTY, (char *) 0);
+
+ termios.c_iflag = ICRNL | IXOFF;
+ termios.c_oflag = OPOST | ONLCR;
+ termios.c_cflag = CS8 | CREAD | CLOCAL;
+ termios.c_lflag = ISIG | ICANON;
+ termios.c_cc[VINTR] = 127;
+ termios.c_cc[VQUIT] = 28;
+ termios.c_cc[VERASE] = 8;
+ termios.c_cc[VKILL] = 24;
+ termios.c_cc[VEOF] = 4;
+ cfsetispeed(&termios, B19200);
+ cfsetospeed(&termios, B19200);
+ tcsetattr(0, TCSANOW, &termios);
+
+ setutent();
+ ut_line.ut_type = LOGIN_PROCESS;
+ ut_line.ut_pid = getpid();
+ strncpy(ut_line.ut_line, ptyslave + 5, sizeof(ut_line.ut_line));
+ strncpy(ut_line.ut_id, ptyslave + 8, sizeof(ut_line.ut_id));
+ strncpy(ut_line.ut_user, "LOGIN", sizeof(ut_line.ut_user));
+ strncpy(ut_line.ut_host, protocol, sizeof(ut_line.ut_host));
+ time(&ut_line.ut_time);
+ ut_line.ut_addr = 0;
+ pututline(&ut_line);
+ endutent();
+
+ chargc = 0;
+ chargv[chargc++] = "/bin/login";
+ chargv[chargc++] = "-p";
+ if (!strcmp(pw->pw_passwd, "+"))
+ chargv[chargc++] = "-f";
+ chargv[chargc++] = real_user;
+ chargv[chargc] = NULL;
+
+ envc = 0;
+ envp[envc] = (char *) malloc(30);
+ sprintf(envp[envc++], "AXCALL=%s", call);
+ envp[envc] = (char *) malloc(30);
+ sprintf(envp[envc++], "CALL=%s", user);
+ envp[envc] = (char *) malloc(30);
+ sprintf(envp[envc++], "PROTOCOL=%s", protocol);
+ envp[envc] = NULL;
+
+ execve(chargv[0], chargv, envp);
+ }
+ else if (pid > 0)
+ {
+ child_pid = 0;
+ signal(SIGHUP, signal_handler);
+ signal(SIGTERM, signal_handler);
+ signal(SIGINT, signal_handler);
+ signal(SIGQUIT, signal_handler);
+
+ while(1)
+ {
+ FD_ZERO(&fds_read);
+ FD_ZERO(&fds_err);
+ FD_SET(0, &fds_read);
+ FD_SET(0, &fds_err);
+ FD_SET(fdmaster, &fds_read);
+ FD_SET(fdmaster, &fds_err);
+
+ k = select(fdmaster+1, &fds_read, NULL, &fds_err, NULL);
+
+ if (k > 0)
+ {
+ if (FD_ISSET(0, &fds_err))
+ {
+ kill(pid, SIGHUP);
+ cleanup(ptyslave+5);
+ return 1;
+ }
+
+ if (FD_ISSET(fdmaster, &fds_err))
+ {
+ cleanup(ptyslave+5);
+ return 1;
+ }
+
+ if (FD_ISSET(0, &fds_read))
+ {
+ cnt = read_ax25(buf, sizeof(buf));
+ if (cnt < 0) /* Connection died */
+ {
+ kill(pid, SIGHUP);
+ cleanup(ptyslave+5);
+ return 1;
+ } else
+ write(fdmaster, buf, cnt);
+ }
+
+ if (FD_ISSET(fdmaster, &fds_read))
+ {
+ cnt = read(fdmaster, buf, sizeof(buf));
+ if (cnt < 0)
+ {
+ cleanup(ptyslave+5);
+ return 1; /* Child died */
+ }
+ write_ax25(buf, cnt);
+ }
+ } else
+ if (k < 0 && errno != EINTR)
+ {
+ kill(pid, SIGHUP); /* just in case... */
+ cleanup(ptyslave+5);
+ return 0;
+ }
+ }
+ }
+ else
+ {
+ syslog(LOG_ERR, "cannot fork %m, closing connection to %s\n", call);
+ write_ax25(MSG_CANNOTFORK, sizeof(MSG_CANNOTFORK));
+ sleep(EXITDELAY);
+ return 1;
+ }
+
+ sleep(EXITDELAY);
+
+ return 0;
+}
diff --git a/ax25/axspawn.conf b/ax25/axspawn.conf
new file mode 100644
index 0000000..1f0bac4
--- /dev/null
+++ b/ax25/axspawn.conf
@@ -0,0 +1,25 @@
+# /etc/ax25/axspawn.conf
+#
+# allow automatic creation of user accounts
+create yes
+#
+# guest user if above is 'no' or everything else fails. Disable with "no"
+guest ax25
+#
+# group id or name for autoaccount
+group ax25
+#
+# first user id to use
+first_uid 400
+#
+# maximum user id
+max_uid 2000
+#
+# where to add the home directory for the new user
+home /home/ax25
+#
+# user shell
+shell /bin/bash
+#
+# bind user id to callsign for outgoing connects.
+associate no
diff --git a/ax25/axspawn.conf.5 b/ax25/axspawn.conf.5
new file mode 100644
index 0000000..416ccdf
--- /dev/null
+++ b/ax25/axspawn.conf.5
@@ -0,0 +1,75 @@
+.TH AXSPAWN.CONF 5 "2 August 1996" Linux "Linux Programmer's Manual"
+.SH NAME
+axspawn.conf \- Control the operation of axspawn.
+.SH DESCRIPTION
+.LP
+The
+.B axspawn.conf
+file controls the operation of the axspawn(8) program. The operation of the
+config file can best be seen in an example:
+.LP
+.RS
+# this is /etc/ax25/axspawn.conf
+.br
+#
+.br
+# allow automatic creation of user accounts
+.br
+create yes
+.br
+#
+.br
+# guest user if above is 'no' or everything else
+.br
+# fails. Disable with "no"
+.br
+guest ax25
+.br
+#
+.br
+# group id or name for autoaccount
+.br
+group ax25
+.br
+#
+.br
+# first user id to use
+.br
+first_uid 400
+.br
+#
+.br
+# maximum user id
+.br
+max_uid 2000
+.br
+#
+.br
+# where to add the home directory for the new user
+.br
+home /home/ax25
+.br
+#
+.br
+# user's shell
+.br
+shell /bin/bash
+.br
+#
+.br
+# bind user id to callsign for outgoing connects.
+.br
+associate yes
+.RE
+.LP
+The \(lqassociate\(rq option has to be used with great care. If a user logs
+on it removes any existing callsign from the translation table for this
+userid and replaces it with the callsign and SSID of the user. This will
+happen with multiple connects (same callsign, different SSIDs), too. Unless
+you want your users to be able to call out from your machine disable
+\(lqassociate\(rq.
+.SH FILES
+.LP
+/etc/ax25/axspawn.conf
+.SH "SEE ALSO"
+.BR axspawn (8).
diff --git a/ax25/beacon.8 b/ax25/beacon.8
new file mode 100644
index 0000000..9b38db7
--- /dev/null
+++ b/ax25/beacon.8
@@ -0,0 +1,51 @@
+.TH BEACON 8 "10 February 1997" Linux "Linux System Managers Manual"
+.SH NAME
+beacon \- transmit periodic messages on an AX.25 port.
+.SH SYNOPSIS
+.B beacon [-c <src_call>] [-d <dest_call>] [-l] [-m] [-s] [-t interval] [-v] port \(lqmessage\(rq
+.SH DESCRIPTION
+.LP
+.B Beacon
+transmits the message text on an AX.25 port every thirty minutes. The message
+is addressed to \(lqIDENT\(rq and is sent using the AX.25 callsign of the port
+specified on the command line. Typically the message text will contain
+spaces and/or other characters, therefore the message text should be
+enclosed in quotes to ensure they are passed to the
+.B beacon
+program untranslated.
+.SH OPTIONS
+.TP 16
+.BI \-c
+Configure the source callsign for beacons. The default is to use the
+interface callsign.
+.TP 16
+.BI \-d
+Configure the destination callsign for beacons. The default is \(lqIDENT\(rq.
+.TP 16
+.BI \-l
+Enables the logging of errors to the system log, the default is off.
+.TP 16
+.BI \-m
+Changes the destination address to \(lqMAIL\(rq and sends the message text
+once only. This option overrides any destination callsign given with the \-d option.
+.TP 16
+.BI \-s
+Sends the message text once only.
+.TP 16
+.BI "\-t interval"
+The time interval between messages, the interval is given in minutes and the
+default is thirty minutes.
+.TP 16
+.BI \-v
+Display the version.
+.SH "SEE ALSO"
+.BR ax25 (4),
+.BR axports (5).
+.SH AUTHORS
+.nf
+Alan Cox GW4PTS <alan@cymru.net>
+.br
+Jonathan Naylor G4KLX <g4klx@g4klx.demon.co.uk>
+.br
+David Brooke G6GZH <db@fusk.demon.co.uk>
+.fi
diff --git a/ax25/beacon.c b/ax25/beacon.c
new file mode 100644
index 0000000..c9b989e
--- /dev/null
+++ b/ax25/beacon.c
@@ -0,0 +1,163 @@
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <syslog.h>
+#include <signal.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/daemon.h>
+
+#include <config.h>
+
+static int logging = FALSE;
+static int mail = FALSE;
+static int single = FALSE;
+
+static void terminate(int sig)
+{
+ if (logging) {
+ syslog(LOG_INFO, "terminating on SIGTERM\n");
+ closelog();
+ }
+
+ exit(0);
+}
+
+int main(int argc, char *argv[])
+{
+ struct full_sockaddr_ax25 dest;
+ struct full_sockaddr_ax25 src;
+ int s, n, dlen, len, interval = 30;
+ char addr[20], *port, *message, *portcall;
+ char *srccall = NULL, *destcall = NULL;
+
+ while ((n = getopt(argc, argv, "c:d:lmst:v")) != -1) {
+ switch (n) {
+ case 'c':
+ srccall = optarg;
+ break;
+ case 'd':
+ destcall = optarg;
+ break;
+ case 'l':
+ logging = TRUE;
+ break;
+ case 'm':
+ mail = TRUE;
+ /* falls through */
+ case 's':
+ single = TRUE;
+ break;
+ case 't':
+ interval = atoi(optarg);
+ if (interval < 1) {
+ fprintf(stderr, "beacon: interval must be greater than on minute\n");
+ return 1;
+ }
+ break;
+ case 'v':
+ printf("beacon: %s\n", VERSION);
+ return 0;
+ case '?':
+ case ':':
+ fprintf(stderr, "usage: beacon [-c <src_call>] [-d <dest_call>] [-l] [-m] [-s] [-t interval] [-v] <port> <message>\n");
+ return 1;
+ }
+ }
+
+ signal(SIGTERM, terminate);
+
+ if (optind == argc || optind == argc - 1) {
+ fprintf(stderr, "usage: beacon [-c <src_call>] [-d <dest_call>] [-l] [-m] [-s] [-t interval] [-v] <port> <message>\n");
+ return 1;
+ }
+
+ port = argv[optind];
+ message = argv[optind + 1];
+
+ if (ax25_config_load_ports() == 0) {
+ fprintf(stderr, "beacon: no AX.25 ports defined\n");
+ return 1;
+ }
+
+ if ((portcall = ax25_config_get_addr(port)) == NULL) {
+ fprintf(stderr, "beacon: invalid AX.25 port setting - %s\n", port);
+ return 1;
+ }
+
+ if (mail)
+ strcpy(addr, "MAIL");
+ else if (destcall != NULL)
+ strcpy(addr, destcall);
+ else
+ strcpy(addr, "IDENT");
+
+ if ((dlen = ax25_aton(addr, &dest)) == -1) {
+ fprintf(stderr, "beacon: unable to convert callsign '%s'\n", addr);
+ return 1;
+ }
+
+ if (srccall != NULL && strcmp(srccall, portcall) != 0)
+ sprintf(addr, "%s %s", srccall, portcall);
+ else
+ strcpy(addr, portcall);
+
+ if ((len = ax25_aton(addr, &src)) == -1) {
+ fprintf(stderr, "beacon: unable to convert callsign '%s'\n", addr);
+ return 1;
+ }
+
+ if (!single) {
+ if (!daemon_start(FALSE)) {
+ fprintf(stderr, "beacon: cannot become a daemon\n");
+ return 1;
+ }
+ }
+
+ if (logging) {
+ openlog("beacon", LOG_PID, LOG_DAEMON);
+ syslog(LOG_INFO, "starting");
+ }
+
+ for (;;) {
+ if ((s = socket(AF_AX25, SOCK_DGRAM, 0)) == -1) {
+ if (logging) {
+ syslog(LOG_ERR, "socket: %m");
+ closelog();
+ }
+ return 1;
+ }
+
+ if (bind(s, (struct sockaddr *)&src, len) == -1) {
+ if (logging) {
+ syslog(LOG_ERR, "bind: %m");
+ closelog();
+ }
+ return 1;
+ }
+
+ if (sendto(s, message, strlen(message), 0, (struct sockaddr *)&dest, dlen) == -1) {
+ if (logging) {
+ syslog(LOG_ERR, "sendto: %m");
+ closelog();
+ }
+ return 1;
+ }
+
+ close(s);
+
+ if (!single)
+ sleep(interval * 60);
+ else
+ break;
+ }
+
+ return 0;
+}
diff --git a/ax25/bpqparms.8 b/ax25/bpqparms.8
new file mode 100644
index 0000000..7a8b450
--- /dev/null
+++ b/ax25/bpqparms.8
@@ -0,0 +1,37 @@
+.TH BPQPARMS 8 "4 September 1996" Linux "Linux System Managers Manual"
+.SH NAME
+bpqparms \- Configure BPQ ethernet devices.
+.SH SYNOPSIS
+.B bpqparms device [-a ethaddr] [-d ethaddr] [-vV]
+.SH DESCRIPTION
+.LP
+.B Bpqparms
+allows the setting of the BPQ Ethernet options for a particular device. Each
+BPQ Ethernet device appears as a device named bpq0...bpqN which overlays the
+original Ethernet device, usually eth0...ethN. This device is an AX.25
+device driver and allows AX.25 frames to be transmitted over an Ethernet to
+another machine using the same protocol. The default for the device is to
+send and receive BPQ Ethernet packets to the broadcast address. This
+program replaces the previous \(lqaxparms -dev\(rq option.
+.SH OPTIONS
+.TP 15
+.BI "\-a ethaddr"
+Allows the setting of which ethernet address will be accepted by the BPQ
+Ethernet device.
+.TP 15
+.BI "\-d ethaddr"
+If specified on its own, will set the destination ethernet address will be
+used for transmitting and for receiving of BPQ ethernet packets. An address
+of \(lqbroadcast\(rq sets it to the ethernet broadcast address.
+.TP 15
+.BI \-v
+Displays the version number.
+.TP 15
+.BI \-V
+The original version messages.
+.SH "SEE ALSO"
+.BR ax25 (4),
+.BR axports (5),
+.BR ifconfig (8).
+.SH AUTHOR
+Joerg Reuter DL1BKE <jreuter@poboxes.com>
diff --git a/ax25/bpqparms.c b/ax25/bpqparms.c
new file mode 100644
index 0000000..1a88fd6
--- /dev/null
+++ b/ax25/bpqparms.c
@@ -0,0 +1,146 @@
+/*
+ bpqparms.c
+
+ Copyright 1996, by Joerg Reuter jreuter@poboxes.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the (modified) GNU General Public License
+ delivered with the LinuX kernel source.
+
+ 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 find a copy of the GNU General Public License in
+ /usr/src/linux/COPYING;
+
+*/
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <termios.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/ioctl.h>
+#include <linux/timer.h>
+
+#include <sys/socket.h>
+#include <net/if.h>
+#include <net/ethernet.h>
+#include <linux/bpqether.h> /* xlz - dammit, we need this again */
+
+#include <config.h>
+
+#define RCS_ID "$Id:$"
+
+void usage(void)
+{
+ fprintf(stderr, "usage : bpqparms dev -d address [-a address]\n");
+ fprintf(stderr, "examples: bpqparms bpq0 -d 00:80:AD:1B:05:26\n");
+ fprintf(stderr, " bpqparms bpq0 -d broadcast -a 00:80:AD:1B:05:26\n");
+ exit(1);
+}
+
+char *Version = "$Revision:$";
+
+int get_hwaddr(unsigned char *k, char *s)
+{
+ unsigned char broadcast[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+ unsigned int eth[ETH_ALEN];
+ int n;
+
+ if (strcmp(s, "default") == 0 || strcmp(s, "broadcast") == 0) {
+ memcpy(k, broadcast, ETH_ALEN);
+ } else {
+ n = sscanf(s, "%x:%x:%x:%x:%x:%x",
+ &eth[0], &eth[1], &eth[2], &eth[3], &eth[4], &eth[5]);
+
+ if (n < 6)
+ return 1;
+
+ for (n = 0; n < ETH_ALEN; n++)
+ k[n] = eth[n];
+ }
+
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ int fd;
+ int cmd, flag;
+ struct ifreq ifr;
+ char dev[40];
+ struct bpq_ethaddr addr;
+
+ strcpy(dev, argv[1]);
+
+ flag = 0;
+
+ while ((cmd = getopt(argc, argv, "d:a:vVh")) != EOF) {
+ switch (cmd) {
+ case 'd':
+ flag |= 1;
+ if (get_hwaddr(addr.destination, optarg)) {
+ fprintf(stderr, "bpqparms: invalid 'destination' address %s\n", optarg);
+ return 1;
+ }
+ break;
+
+ case 'a':
+ flag |= 2;
+ if (get_hwaddr(addr.accept, optarg)) {
+ fprintf(stderr, "bpqparms: invalid 'accept' address %s\n", optarg);
+ return 1;
+ }
+ break;
+
+ case 'V':
+ printf("bpqparms version %s\n", Version);
+ printf("Copyright 1996, Jörg Reuter (jreuter@poboxes.com)\n");
+ printf("This program is free software; you can redistribute it and/or modify\n");
+ printf("it under the terms of the GNU General Public License as published by\n");
+ printf("the Free Software Foundation; either version 2 of the License, or\n");
+ printf(" (at your option) any later version.\n\n");
+ printf("This program is distributed in the hope that it will be useful,\n");
+ printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");
+ printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
+ return 0;
+
+ case 'v':
+ printf("bpqparms: %s\n", VERSION);
+ return(0);
+
+ case 'h':
+ case ':':
+ case '?':
+ usage();
+ }
+ }
+
+ if (!(flag & 0x01) || optind+1 > argc)
+ usage();
+
+ strcpy(dev, argv[optind]);
+
+ if ((flag & 0x02) == 0)
+ memcpy(addr.accept, addr.destination, ETH_ALEN);
+
+ fd = socket(AF_INET, SOCK_DGRAM, 0);
+
+ strcpy(ifr.ifr_name, dev);
+ ifr.ifr_data = (caddr_t) &addr;
+
+ if (ioctl(fd, SIOCSBPQETHADDR, &ifr) < 0) {
+ perror("bpqparms SIOCSBPQETHADDR");
+ close(fd);
+ return 1;
+ }
+
+ close(fd);
+
+ return 0;
+}
diff --git a/ax25/mheard.1 b/ax25/mheard.1
new file mode 100644
index 0000000..b300aaf
--- /dev/null
+++ b/ax25/mheard.1
@@ -0,0 +1,74 @@
+.TH MHEARD 1 "19 August 1996" Linux "Linux Programmer's Manual"
+.SH NAME
+mheard \- display AX.25 calls recently heard.
+.SH SYNOPSIS
+.B mheard [-d cmns] [-n] [-o cfpt] [-v] [port...]
+.SH DESCRIPTION
+.LP
+.B Mheard
+displays information about most recently heard AX.25 callsigns, the interface
+upon which they were heard, the total packets heard, the time
+at which the last one was heard and other information.
+.B Mheard
+displays different information, in different orders depending on the
+settings of the arguments. Information on specific ports can be displayed by
+giving the port names as arguments.
+.SH OPTIONS
+.TP 13
+.BI "\-d cmns"
+Sets the information that is displayed for each AX.25 callsign heard. The
+different arguments are:
+.RS
+.TP 5
+.BI c
+Display all the information with regard to callsigns, from-callsign,
+to-callsign, port name, and any digipeaters that may be in use.
+.TP 5
+.BI m
+Display miscellaneous information, the from-callsign, port name, no frames
+heard, the last type of frames heard, and which different PIDs have been
+heard from that station.
+.TP 5
+.BI n
+Display the default information. This is the from-callsign, port name, no frames
+heard and the date and time last heard.
+.TP 5
+.BI s
+Displays statistics about the station heard, the from-callsign, port name,
+no I frames, no S frames, no U frames, time first heard, and time last
+heard.
+.RE
+.TP 13
+.BI \-n
+Supress the displaying of titles.
+.TP 13
+.BI "\-o cfpt"
+Sets the ordering of the information displayed. The meanings of the
+different arguments are:
+.RS
+.TP 5
+.BI c
+Sort list by from-callsign.
+.TP 5
+.BI f
+Sort list by number of frames heard.
+.TP 5
+.BI p
+Sort list by port name.
+.TP 5
+.BI t
+Sort list by the time last heard, this is the default.
+.RE
+.TP 13
+.BI \-v
+Display the version.
+.SH FILES
+.LP
+/var/ax25/mheard/mheard.dat
+.br
+/etc/ax25/axports
+.SH "SEE ALSO"
+.BR ax25 (4),
+.BR mheardd (8).
+.SH AUTHOR
+Jonathan Naylor G4KLX <g4klx@g4klx.demon.co.uk>
diff --git a/ax25/mheard.c b/ax25/mheard.c
new file mode 100644
index 0000000..2ab582c
--- /dev/null
+++ b/ax25/mheard.c
@@ -0,0 +1,374 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netax25/ax25.h>
+#include <netrose/rose.h>
+#include <netax25/axlib.h>
+#include <netax25/mheard.h>
+
+#include <config.h>
+
+#include "../pathnames.h"
+
+struct PortRecord {
+ struct mheard_struct entry;
+ struct PortRecord *Next;
+};
+
+static char *types[] = {
+ "SABM",
+ "SABME",
+ "DISC",
+ "UA",
+ "DM",
+ "RR",
+ "RNR",
+ "REJ",
+ "FRMR",
+ "I",
+ "UI",
+ "????"};
+
+static struct PortRecord *PortList = NULL;
+
+static void PrintHeader(int data)
+{
+ switch (data) {
+ case 0:
+ printf("Callsign Port Packets Last Heard\n");
+ break;
+ case 1:
+ printf("Callsign Port\n");
+ break;
+ case 2:
+ printf("Callsign Port #I #S #U First Heard Last Heard\n");
+ break;
+ case 3:
+ printf("Callsign Port Packets Type PIDs\n");
+ break;
+ }
+}
+
+static void PrintPortEntry(struct PortRecord *pr, int data)
+{
+ char lh[30], fh[30], *call, *s;
+ char buffer[80];
+ int i;
+
+ switch (data) {
+ case 0:
+ strcpy(lh, ctime(&pr->entry.last_heard));
+ lh[19] = 0;
+ call = ax25_ntoa(&pr->entry.from_call);
+ if ((s = strstr(call, "-0")) != NULL)
+ *s = '\0';
+ printf("%-10s %-5s %5d %s\n",
+ call, pr->entry.portname, pr->entry.count, lh);
+ break;
+ case 1:
+ buffer[0] = '\0';
+ call = ax25_ntoa(&pr->entry.from_call);
+ if ((s = strstr(call, "-0")) != NULL)
+ *s = '\0';
+ strcat(buffer, call);
+ call = ax25_ntoa(&pr->entry.to_call);
+ if ((s = strstr(call, "-0")) != NULL)
+ *s = '\0';
+ strcat(buffer, ">");
+ strcat(buffer, call);
+ for (i = 0; i < pr->entry.ndigis && i < 4; i++) {
+ strcat(buffer, ",");
+ call = ax25_ntoa(&pr->entry.digis[i]);
+ if ((s = strstr(call, "-0")) != NULL)
+ *s = '\0';
+ strcat(buffer, call);
+ }
+ if (pr->entry.ndigis >= 4)
+ strcat(buffer, ",...");
+ printf("%-70s %-5s\n",
+ buffer, pr->entry.portname);
+ break;
+ case 2:
+ strcpy(lh, ctime(&pr->entry.last_heard));
+ lh[19] = 0;
+ strcpy(fh, ctime(&pr->entry.first_heard));
+ fh[19] = 0;
+ call = ax25_ntoa(&pr->entry.from_call);
+ if ((s = strstr(call, "-0")) != NULL)
+ *s = '\0';
+ printf("%-10s %-5s %5d %5d %5d %s %s\n",
+ call, pr->entry.portname, pr->entry.iframes, pr->entry.sframes, pr->entry.uframes, fh, lh);
+ break;
+ case 3:
+ call = ax25_ntoa(&pr->entry.from_call);
+ if ((s = strstr(call, "-0")) != NULL)
+ *s = '\0';
+ printf("%-10s %-5s %5d %5s ",
+ call, pr->entry.portname, pr->entry.count, types[pr->entry.type]);
+ if (pr->entry.mode & MHEARD_MODE_ARP)
+ printf(" ARP");
+ if (pr->entry.mode & MHEARD_MODE_FLEXNET)
+ printf(" FlexNet");
+ if (pr->entry.mode & MHEARD_MODE_IP_DG)
+ printf(" IP-DG");
+ if (pr->entry.mode & MHEARD_MODE_IP_VC)
+ printf(" IP-VC");
+ if (pr->entry.mode & MHEARD_MODE_NETROM)
+ printf(" NET/ROM");
+ if (pr->entry.mode & MHEARD_MODE_ROSE)
+ printf(" Rose");
+ if (pr->entry.mode & MHEARD_MODE_SEGMENT)
+ printf(" Segment");
+ if (pr->entry.mode & MHEARD_MODE_TEXNET)
+ printf(" TexNet");
+ if (pr->entry.mode & MHEARD_MODE_TEXT)
+ printf(" Text");
+ if (pr->entry.mode & MHEARD_MODE_PSATFT)
+ printf(" PacsatFT");
+ if (pr->entry.mode & MHEARD_MODE_PSATPB)
+ printf(" PacsatPB");
+ if (pr->entry.mode & MHEARD_MODE_UNKNOWN)
+ printf(" Unknown");
+ printf("\n");
+ break;
+ }
+}
+
+static void ListAllPorts(int data)
+{
+ struct PortRecord *pr;
+
+ for (pr = PortList; pr != NULL; pr = pr->Next)
+ PrintPortEntry(pr, data);
+}
+
+static void ListOnlyPort(char *name, int data)
+{
+ struct PortRecord *pr;
+
+ for (pr = PortList; pr != NULL; pr = pr->Next)
+ if (strcmp(pr->entry.portname, name) == 0)
+ PrintPortEntry(pr, data);
+}
+
+static void LoadPortData(void)
+{
+ FILE *fp;
+ struct PortRecord *pr;
+ struct mheard_struct mheard;
+
+ if ((fp = fopen(DATA_MHEARD_FILE, "r")) == NULL) {
+ fprintf(stderr, "mheard: cannot open mheard data file\n");
+ exit(1);
+ }
+
+ while (fread(&mheard, sizeof(struct mheard_struct), 1, fp) == 1) {
+ pr = malloc(sizeof(struct PortRecord));
+ pr->entry = mheard;
+ pr->Next = PortList;
+ PortList = pr;
+ }
+
+ fclose(fp);
+}
+
+static void SortByTime(void)
+{
+ struct PortRecord *p = PortList;
+ struct PortRecord *n;
+ PortList = NULL;
+
+ while (p != NULL) {
+ struct PortRecord *w = PortList;
+
+ n = p->Next;
+
+ if (w == NULL || p->entry.last_heard > w->entry.last_heard) {
+ p->Next = w;
+ PortList = p;
+ p = n;
+ continue;
+ }
+
+ while (w->Next != NULL && p->entry.last_heard <= w->Next->entry.last_heard)
+ w = w->Next;
+
+ p->Next = w->Next;
+ w->Next = p;
+ p = n;
+ }
+}
+
+
+static void SortByPort(void)
+{
+ struct PortRecord *p = PortList;
+ struct PortRecord *n;
+ PortList = NULL;
+
+ while (p != NULL) {
+ struct PortRecord *w = PortList;
+
+ n = p->Next;
+
+ if (w == NULL || strcmp(p->entry.portname, w->entry.portname) < 0) {
+ p->Next = w;
+ PortList = p;
+ p = n;
+ continue;
+ }
+
+ while (w->Next != NULL && strcmp(p->entry.portname, w->Next->entry.portname) >= 0)
+ w = w->Next;
+
+ p->Next = w->Next;
+ w->Next = p;
+ p = n;
+ }
+}
+
+static void SortByCall(void)
+{
+ struct PortRecord *p = PortList;
+ struct PortRecord *n;
+ PortList = NULL;
+
+ while (p != NULL) {
+ struct PortRecord *w = PortList;
+
+ n = p->Next;
+
+ if (w == NULL || memcmp(&p->entry.from_call, &w->entry.from_call, sizeof(ax25_address)) < 0) {
+ p->Next = w;
+ PortList = p;
+ p = n;
+ continue;
+ }
+
+ while (w->Next != NULL && memcmp(&p->entry.from_call, &w->Next->entry.from_call, sizeof(ax25_address)) >= 0)
+ w = w->Next;
+
+ p->Next = w->Next;
+ w->Next = p;
+ p = n;
+ }
+}
+
+static void SortByFrame(void)
+{
+ struct PortRecord *p = PortList;
+ struct PortRecord *n;
+ PortList = NULL;
+
+ while (p != NULL) {
+ struct PortRecord *w = PortList;
+
+ n = p->Next;
+
+ if (w == NULL || p->entry.count > w->entry.count) {
+ p->Next = w;
+ PortList = p;
+ p = n;
+ continue;
+ }
+
+ while (w->Next != NULL && p->entry.count <= w->Next->entry.count)
+ w = w->Next;
+
+ p->Next = w->Next;
+ w->Next = p;
+ p = n;
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ int headers = TRUE;
+ int mode = 0;
+ int data = 0;
+ int c;
+
+ while ((c = getopt(argc, argv, "d:no:v")) != -1) {
+ switch (c) {
+ case 'd':
+ switch (*optarg) {
+ case 'c':
+ data = 1;
+ break;
+ case 'm':
+ data = 3;
+ break;
+ case 'n':
+ data = 0;
+ break;
+ case 's':
+ data = 2;
+ break;
+ default:
+ fprintf(stderr, "mheard: invalid display type '%s'\n", optarg);
+ return 1;
+ }
+ break;
+ case 'n':
+ headers = FALSE;
+ break;
+ case 'o':
+ switch (*optarg) {
+ case 'c':
+ mode = 2;
+ break;
+ case 'f':
+ mode = 3;
+ break;
+ case 'p':
+ mode = 1;
+ break;
+ case 't':
+ mode = 0;
+ break;
+ default:
+ fprintf(stderr, "mheard: invalid ordering type '%s'\n", optarg);
+ return 1;
+ }
+ break;
+ case 'v':
+ printf("mheard: %s\n", VERSION);
+ return 0;
+ case '?':
+ case ':':
+ fprintf(stderr, "Usage: %s [-d cmns] [-n] [-o cfpt] [-v] [port ...]\n", argv[0]);
+ return 1;
+ }
+ }
+
+ LoadPortData();
+
+ switch (mode) {
+ case 0: SortByTime(); break;
+ case 1: SortByPort(); break;
+ case 2: SortByCall(); break;
+ case 3: SortByFrame(); break;
+ }
+
+ if (argc == optind) {
+ if (headers)
+ PrintHeader(data);
+ ListAllPorts(data);
+ } else {
+ while (argv[optind] != NULL) {
+ if (headers) {
+ printf("Port %s:\n", argv[optind]);
+ PrintHeader(data);
+ }
+ ListOnlyPort(argv[optind], data);
+ optind++;
+ }
+ }
+
+ return 0;
+}
diff --git a/ax25/mheard.dat b/ax25/mheard.dat
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/ax25/mheard.dat
diff --git a/ax25/mheardd.8 b/ax25/mheardd.8
new file mode 100644
index 0000000..63cda36
--- /dev/null
+++ b/ax25/mheardd.8
@@ -0,0 +1,42 @@
+.TH MHEARDD 8 "27 August 1996" Linux "Linux Programmer's Manual"
+.SH NAME
+mheardd \- collect information about packet activity
+.SH SYNOPSIS
+.B mheardd [-f] [-l] [-n number] [-v]
+.SH DESCRIPTION
+.LP
+.B Mheardd
+is a daemon that collects the statistics about the activity on all the AX.25
+channels that are configured. The list generated is available for viewing by
+the
+.BR mheard (1)
+program. The information collected is a superset of the information normally
+collected by similar mheard programs and this is reflected in the options
+available for the viewing program. Logging to the system log file may be
+enabled which will enable monitoring of pathalogical conditions, for example
+invalid frame types and invalid/unknown protocol IDs.
+.SH OPTIONS
+.TP 10
+.BI \-f
+Deletes the existing mheard logging file at program startup, this is not the
+default.
+.TP 10
+.BI \-l
+Enables logging to the system log file. The default is off.
+.TP 10
+.BI "\-n number"
+Sets the number of entries in the activity list file, the default is 40. The
+minimum value allowed is 10 and the maximum is 100.
+.TP 10
+.BI \-v
+Display the version.
+.SH FILES
+.LP
+/var/ax25/mheard/mheard.dat
+.br
+/etc/ax25/axports
+.SH "SEE ALSO"
+.BR mheard (1),
+.BR ax25 (4).
+.SH AUTHOR
+Jonathan Naylor G4KLX <g4klx@g4klx.demon.co.uk>
diff --git a/ax25/mheardd.c b/ax25/mheardd.c
new file mode 100644
index 0000000..2d98fad
--- /dev/null
+++ b/ax25/mheardd.c
@@ -0,0 +1,436 @@
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <string.h>
+#include <signal.h>
+#include <syslog.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <sys/socket.h>
+#include <net/ethernet.h>
+#include <netinet/in.h>
+
+#include <netax25/ax25.h>
+#include <netrose/rose.h>
+
+#include <netax25/axlib.h>
+#include <netax25/axconfig.h>
+#include <netax25/daemon.h>
+#include <netax25/mheard.h>
+
+#include <config.h>
+
+#include "../pathnames.h"
+
+#define KISS_MASK 0x0F
+#define KISS_DATA 0x00
+
+#define PID_SEGMENT 0x08
+#define PID_ARP 0xCD
+#define PID_NETROM 0xCF
+#define PID_IP 0xCC
+#define PID_ROSE 0x01
+#define PID_TEXNET 0xC3
+#define PID_FLEXNET 0xCE
+#define PID_TEXT 0xF0
+#define PID_PSATFT 0xBB
+#define PID_PSATPB 0xBD
+
+#define I 0x00
+#define S 0x01
+#define RR 0x01
+#define RNR 0x05
+#define REJ 0x09
+#define U 0x03
+#define SABM 0x2F
+#define SABME 0x6F
+#define DISC 0x43
+#define DM 0x0F
+#define UA 0x63
+#define FRMR 0x87
+#define UI 0x03
+
+#define PF 0x10
+#define EPF 0x01
+
+#define MMASK 7
+
+#define HDLCAEB 0x01
+#define SSID 0x1E
+#define SSSID_SPARE 0x40
+#define ESSID_SPARE 0x20
+
+#define ALEN 6
+#define AXLEN 7
+
+struct mheard_list_struct {
+ int in_use;
+ struct mheard_struct entry;
+ long position;
+};
+
+static struct mheard_list_struct *mheard_list;
+static int mheard_list_size = 40;
+static int logging = FALSE;
+
+static int ftype(unsigned char *, int *, int);
+static struct mheard_list_struct *findentry(ax25_address *, char *);
+
+static void terminate(int sig)
+{
+ if (logging) {
+ syslog(LOG_INFO, "terminating on SIGTERM\n");
+ closelog();
+ }
+
+ exit(0);
+}
+
+int main(int argc, char **argv)
+{
+ struct mheard_list_struct *mheard;
+ unsigned char buffer[1500], *data;
+ int size, s;
+ char *port = NULL;
+ struct sockaddr sa;
+ int asize;
+ long position;
+ int ctlen, type, end, extseq, flush = FALSE;
+ FILE *fp;
+
+ while ((s = getopt(argc, argv, "fln:v")) != -1) {
+ switch (s) {
+ case 'l':
+ logging = TRUE;
+ break;
+ case 'f':
+ flush = TRUE;
+ break;
+ case 'n':
+ mheard_list_size = atoi(optarg);
+ if (mheard_list_size < 10 || mheard_list_size > 100) {
+ fprintf(stderr, "mheardd: list size must be between 10 and 100\n");
+ return 1;
+ }
+ break;
+ case 'v':
+ printf("mheardd: %s\n", VERSION);
+ return 0;
+ case ':':
+ fprintf(stderr, "mheardd: option -n needs an argument\n");
+ return 1;
+ case '?':
+ fprintf(stderr, "Usage: mheardd [-f] [-l] [-n number] [-v]\n");
+ return 1;
+ }
+ }
+
+ signal(SIGTERM, terminate);
+
+ if (ax25_config_load_ports() == 0) {
+ fprintf(stderr, "mheardd: no AX.25 port data configured\n");
+ return 1;
+ }
+
+ if ((mheard_list = calloc(mheard_list_size, sizeof(struct mheard_list_struct))) == NULL) {
+ fprintf(stderr, "mheardd: cannot allocate memory\n");
+ return 1;
+ }
+
+ if (flush)
+ unlink(DATA_MHEARD_FILE);
+
+ /* Load an existing heard list */
+ if ((fp = fopen(DATA_MHEARD_FILE, "r")) != NULL) {
+ s = 0;
+ position = ftell(fp);
+
+ while (fread(buffer, sizeof(struct mheard_struct), 1, fp) == 1 && s < mheard_list_size) {
+ memcpy(&mheard_list[s].entry, buffer, sizeof(struct mheard_struct));
+ mheard_list[s].in_use = TRUE;
+ mheard_list[s].position = position;
+ position = ftell(fp);
+ s++;
+ }
+
+ fclose(fp);
+ } else {
+ if ((fp = fopen(DATA_MHEARD_FILE, "w")) != NULL)
+ fclose(fp);
+ }
+
+ if ((s = socket(AF_INET, SOCK_PACKET, htons(ETH_P_AX25))) == -1) {
+ perror("mheardd: socket");
+ return 1;
+ }
+
+ if (!daemon_start(FALSE)) {
+ fprintf(stderr, "mheardd: cannot become a daemon\n");
+ return 1;
+ }
+
+ /* Use syslog for error messages rather than perror/fprintf */
+ if (logging) {
+ openlog("mheardd", LOG_PID, LOG_DAEMON);
+ syslog(LOG_INFO, "starting");
+ }
+
+ for (;;) {
+ asize = sizeof(sa);
+
+ if ((size = recvfrom(s, buffer, sizeof(buffer), 0, &sa, &asize)) == -1) {
+ if (logging) {
+ syslog(LOG_ERR, "recv: %m");
+ closelog();
+ }
+ return 1;
+ }
+
+ if ((port = ax25_config_get_name(sa.sa_data)) == NULL) {
+ if (logging)
+ syslog(LOG_WARNING, "unknown port '%s'\n", sa.sa_data);
+ continue;
+ }
+
+ data = buffer;
+
+ if ((*data & KISS_MASK) != KISS_DATA)
+ continue;
+
+ data++;
+ size--;
+
+ if (size < (AXLEN + AXLEN + 1)) {
+ if (logging)
+ syslog(LOG_WARNING, "packet too short\n");
+ continue;
+ }
+
+ mheard = findentry((ax25_address *)(data + AXLEN), port);
+
+ if (!ax25_validate(data + 0) || !ax25_validate(data + AXLEN)) {
+ if (logging)
+ syslog(LOG_WARNING, "invalid callsign on port %s\n", port);
+ continue;
+ }
+
+ memcpy(&mheard->entry.from_call, data + AXLEN, sizeof(ax25_address));
+ memcpy(&mheard->entry.to_call, data + 0, sizeof(ax25_address));
+ strcpy(mheard->entry.portname, port);
+ mheard->entry.ndigis = 0;
+
+ extseq = ((data[AXLEN + ALEN] & SSSID_SPARE) != SSSID_SPARE);
+ end = (data[AXLEN + ALEN] & HDLCAEB);
+
+ data += (AXLEN + AXLEN);
+ size -= (AXLEN + AXLEN);
+
+ while (!end) {
+ memcpy(&mheard->entry.digis[mheard->entry.ndigis], data, sizeof(ax25_address));
+ mheard->entry.ndigis++;
+
+ end = (data[ALEN] & HDLCAEB);
+
+ data += AXLEN;
+ size -= AXLEN;
+ }
+
+ if (size == 0) {
+ if (logging)
+ syslog(LOG_WARNING, "packet too short\n");
+ continue;
+ }
+
+ ctlen = ftype(data, &type, extseq);
+
+ mheard->entry.count++;
+
+ switch (type) {
+ case SABM:
+ mheard->entry.type = MHEARD_TYPE_SABM;
+ mheard->entry.uframes++;
+ break;
+ case SABME:
+ mheard->entry.type = MHEARD_TYPE_SABME;
+ mheard->entry.uframes++;
+ break;
+ case DISC:
+ mheard->entry.type = MHEARD_TYPE_DISC;
+ mheard->entry.uframes++;
+ break;
+ case UA:
+ mheard->entry.type = MHEARD_TYPE_UA;
+ mheard->entry.uframes++;
+ break;
+ case DM:
+ mheard->entry.type = MHEARD_TYPE_DM;
+ mheard->entry.uframes++;
+ break;
+ case RR:
+ mheard->entry.type = MHEARD_TYPE_RR;
+ mheard->entry.sframes++;
+ break;
+ case RNR:
+ mheard->entry.type = MHEARD_TYPE_RNR;
+ mheard->entry.sframes++;
+ break;
+ case REJ:
+ mheard->entry.type = MHEARD_TYPE_REJ;
+ mheard->entry.sframes++;
+ break;
+ case FRMR:
+ mheard->entry.type = MHEARD_TYPE_FRMR;
+ mheard->entry.uframes++;
+ break;
+ case I:
+ mheard->entry.type = MHEARD_TYPE_I;
+ mheard->entry.iframes++;
+ break;
+ case UI:
+ mheard->entry.type = MHEARD_TYPE_UI;
+ mheard->entry.uframes++;
+ break;
+ default:
+ if (logging)
+ syslog(LOG_WARNING, "unknown packet type %02X\n", *data);
+ mheard->entry.type = MHEARD_TYPE_UNKNOWN;
+ break;
+ }
+
+ data += ctlen;
+ size -= ctlen;
+
+ if (type == I || type == UI) {
+ switch (*data) {
+ case PID_TEXT:
+ mheard->entry.mode |= MHEARD_MODE_TEXT;
+ break;
+ case PID_SEGMENT:
+ mheard->entry.mode |= MHEARD_MODE_SEGMENT;
+ break;
+ case PID_ARP:
+ mheard->entry.mode |= MHEARD_MODE_ARP;
+ break;
+ case PID_NETROM:
+ mheard->entry.mode |= MHEARD_MODE_NETROM;
+ break;
+ case PID_IP:
+ mheard->entry.mode |= (type == I) ? MHEARD_MODE_IP_VC : MHEARD_MODE_IP_DG;
+ break;
+ case PID_ROSE:
+ mheard->entry.mode |= MHEARD_MODE_ROSE;
+ break;
+ case PID_TEXNET:
+ mheard->entry.mode |= MHEARD_MODE_TEXNET;
+ break;
+ case PID_FLEXNET:
+ mheard->entry.mode |= MHEARD_MODE_FLEXNET;
+ break;
+ case PID_PSATPB:
+ mheard->entry.mode |= MHEARD_MODE_PSATPB;
+ break;
+ case PID_PSATFT:
+ mheard->entry.mode |= MHEARD_MODE_PSATFT;
+ break;
+ default:
+ if (logging)
+ syslog(LOG_WARNING, "unknown PID %02X\n", *data);
+ mheard->entry.mode |= MHEARD_MODE_UNKNOWN;
+ break;
+ }
+ }
+
+ if (mheard->entry.first_heard == 0)
+ time(&mheard->entry.first_heard);
+
+ time(&mheard->entry.last_heard);
+
+ if ((fp = fopen(DATA_MHEARD_FILE, "r+")) == NULL) {
+ if (logging)
+ syslog(LOG_ERR, "cannot open mheard data file\n");
+ continue;
+ }
+
+ if (mheard->position == 0xFFFFFF) {
+ fseek(fp, 0L, SEEK_END);
+ mheard->position = ftell(fp);
+ }
+
+ fseek(fp, mheard->position, SEEK_SET);
+
+ fwrite(&mheard->entry, sizeof(struct mheard_struct), 1, fp);
+
+ fclose(fp);
+ }
+}
+
+static int ftype(unsigned char *data, int *type, int extseq)
+{
+ if (extseq) {
+ if ((*data & 0x01) == 0) { /* An I frame is an I-frame ... */
+ *type = I;
+ return 2;
+ }
+ if (*data & 0x02) {
+ *type = *data & ~PF;
+ return 1;
+ } else {
+ *type = *data;
+ return 2;
+ }
+ } else {
+ if ((*data & 0x01) == 0) { /* An I frame is an I-frame ... */
+ *type = I;
+ return 1;
+ }
+ if (*data & 0x02) { /* U-frames use all except P/F bit for type */
+ *type = *data & ~PF;
+ return 1;
+ } else { /* S-frames use low order 4 bits for type */
+ *type = *data & 0x0F;
+ return 1;
+ }
+ }
+}
+
+static struct mheard_list_struct *findentry(ax25_address *callsign, char *port)
+{
+ struct mheard_list_struct *oldest = NULL;
+ int i;
+
+ for (i = 0; i < mheard_list_size; i++)
+ if (mheard_list[i].in_use &&
+ ax25_cmp(&mheard_list[i].entry.from_call, callsign) == 0 &&
+ strcmp(mheard_list[i].entry.portname, port) == 0)
+ return mheard_list + i;
+
+ for (i = 0; i < mheard_list_size; i++) {
+ if (!mheard_list[i].in_use) {
+ mheard_list[i].in_use = TRUE;
+ mheard_list[i].position = 0xFFFFFF;
+ return mheard_list + i;
+ }
+ }
+
+ for (i = 0; i < mheard_list_size; i++) {
+ if (mheard_list[i].in_use) {
+ if (oldest == NULL) {
+ oldest = mheard_list + i;
+ } else {
+ if (mheard_list[i].entry.last_heard < oldest->entry.last_heard)
+ oldest = mheard_list + i;
+ }
+ }
+ }
+
+ memset(&oldest->entry, 0x00, sizeof(struct mheard_struct));
+
+ return oldest;
+}
diff --git a/ax25/rxecho.8 b/ax25/rxecho.8
new file mode 100644
index 0000000..7a9ed80
--- /dev/null
+++ b/ax25/rxecho.8
@@ -0,0 +1,38 @@
+.TH RXECHO 8 "15 October 1996" Linux "Linux System Managers Manual"
+.SH NAME
+rxecho \- Route AX.25 packets between ports transparently.
+.SH SYNOPSIS
+.B rxecho [-l] [-v]
+.SH DESCRIPTION
+.LP
+.B Rxecho
+copies AX.25 frames between interfaces without altering their contents. The
+purpose of this utility is to allow other AX.25 aware programs/computers to
+share the same AX.25 ports as the Linux kernel AX.25 code. It could be used
+to route packets out onto another serial port to allow another machine
+running DOS based programs to share the same radio ports as the Linux
+machine, or it could route packets out onto a pseudo-tty to another
+application on the same machine. The copying could even be to another
+radio port.
+.LP
+The copying of the packets is controlled by a configuration file
+rxecho.conf(5), which can be set up to selectively copy packets.
+.SH OPTIONS
+.TP 10
+.BI \-l
+Enables logging of errors to the system log, the default is off.
+.TP 10
+.BI \-v
+Display the version.
+.SH FILES
+.nf
+/etc/ax25/axports
+.br
+/etc/ax25/rxecho.conf
+.fi
+.SH "SEE ALSO"
+.BR axports (5),
+.BR rxecho.conf (5),
+.BR kissattach (8).
+.SH AUTHOR
+Tomi Manninen OH2BNS <tpmannin@cc.hut.fi>
diff --git a/ax25/rxecho.c b/ax25/rxecho.c
new file mode 100644
index 0000000..31334aa
--- /dev/null
+++ b/ax25/rxecho.c
@@ -0,0 +1,376 @@
+/*
+ * rxecho.c - Copies AX.25 packets from an interface to another interface.
+ * Reads CONFIGFILE (see below) and uses that information to
+ * decide what packets should be copied and where.
+ *
+ * CONFIGFILE format is:
+ *
+ * # this is a comment
+ * 144 kiss0 oh2bns-1,oh2bns-2
+ * kiss0 144 *
+ *
+ * This means that packets received on port 144 are copied to port
+ * kiss0 if they are destined to oh2bns-1 or oh2bns-2. Packets
+ * from port kiss0 are all copied to port 144.
+ *
+ * There may be empty lines and an arbirary amount of white
+ * space around the tokens but the callsign field must not
+ * have any spaces in it. There can be up to MAXCALLS call-
+ * signs in the callsign field (see below).
+ *
+ * Copyright (C) 1996 by Tomi Manninen, OH2BNS, <tomi.manninen@hut.fi>.
+ *
+ * *** Modified 9/9/96 by Heikki Hannikainen, OH7LZB, <hessu@pspt.fi>:
+ *
+ * One port can actually be echoed to multiple ports (with a
+ * different recipient callsign, of course). The old behaviour was
+ * to give up on the first matching port, even if the recipient
+ * callsign didn't match (and the frame wasn't echoed anywhere).
+ *
+ * ***
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <signal.h>
+#include <sys/types.h>
+
+#include <sys/socket.h>
+#include <net/ethernet.h>
+#include <netinet/in.h>
+#include <netax25/ax25.h>
+#include <netrose/rose.h>
+
+#include <netax25/axlib.h>
+#include <netax25/axconfig.h>
+#include <netax25/daemon.h>
+
+#include <config.h>
+
+#include "../pathnames.h"
+
+#define MAXCALLS 8
+
+struct config {
+ char from[14]; /* sockaddr.sa_data is 14 bytes */
+ char to[14];
+ ax25_address calls[MAXCALLS];/* list of calls to echo */
+ int ncalls; /* number of calls to echo */
+
+ struct config *next;
+};
+
+static int logging = FALSE;
+
+static void terminate(int sig)
+{
+ if (logging) {
+ syslog(LOG_INFO, "terminating on SIGTERM\n");
+ closelog();
+ }
+
+ exit(0);
+}
+
+/*
+ * Read string "call1,call2,call3,..." into p.
+ */
+static int read_calls(struct config *p, char *s)
+{
+ char *cp, *cp1;
+
+ if (p == NULL || s == NULL)
+ return -1;
+
+ p->ncalls = 0;
+
+ if (strcmp(s, "*") == 0)
+ return 0;
+
+ cp = s;
+
+ while ((cp1 = strchr(cp, ',')) != NULL && p->ncalls < MAXCALLS) {
+ *cp1 = 0;
+
+ if (ax25_aton_entry(cp, p->calls[p->ncalls].ax25_call) == -1)
+ return -1;
+
+ p->ncalls++;
+ cp = ++cp1;
+ }
+
+ if (p->ncalls < MAXCALLS) {
+ if (ax25_aton_entry(cp, p->calls[p->ncalls].ax25_call) == -1)
+ return -1;
+
+ p->ncalls++;
+ }
+
+ return p->ncalls;
+}
+
+static struct config *readconfig(void)
+{
+ FILE *fp;
+ char line[80], *cp, *dev;
+ struct config *p, *list = NULL;
+
+ if ((fp = fopen(CONF_RXECHO_FILE, "r")) == NULL) {
+ fprintf(stderr, "rxecho: cannot open config file\n");
+ return NULL;
+ }
+
+ while (fgets(line, 80, fp) != NULL) {
+ cp = strtok(line, " \t\r\n");
+
+ if (cp == NULL || cp[0] == '#')
+ continue;
+
+ if ((p = calloc(1, sizeof(struct config))) == NULL) {
+ perror("rxecho: malloc");
+ return NULL;
+ }
+
+ if ((dev = ax25_config_get_dev(cp)) == NULL) {
+ fprintf(stderr, "rxecho: invalid port name - %s\n", cp);
+ return NULL;
+ }
+
+ strcpy(p->from, dev);
+
+ if ((cp = strtok(NULL, " \t\r\n")) == NULL) {
+ fprintf(stderr, "rxecho: config file error.\n");
+ return NULL;
+ }
+
+ if ((dev = ax25_config_get_dev(cp)) == NULL) {
+ fprintf(stderr, "rxecho: invalid port name - %s\n", cp);
+ return NULL;
+ }
+
+ strcpy(p->to, dev);
+
+ if (read_calls(p, strtok(NULL, " \t\r\n")) == -1) {
+ fprintf(stderr, "rxecho: config file error.\n");
+ return NULL;
+ }
+
+ p->next = list;
+ list = p;
+ }
+
+ fclose(fp);
+
+ if (list == NULL)
+ fprintf(stderr, "rxecho: Empty config file!\n");
+
+ return list;
+}
+
+/*
+ * Slightly modified from linux/include/net/ax25.h and
+ * linux/net/ax25/ax25_subr.c:
+ */
+
+#if 0
+#define C_COMMAND 1
+#define C_RESPONSE 2
+#define LAPB_C 0x80
+#endif
+#define LAPB_E 0x01
+#define AX25_ADDR_LEN 7
+#define AX25_REPEATED 0x80
+
+typedef struct {
+ ax25_address calls[AX25_MAX_DIGIS];
+ unsigned char repeated[AX25_MAX_DIGIS];
+ char ndigi;
+ char lastrepeat;
+} ax25_digi;
+
+/*
+ * Given an AX.25 address pull of to, from, digi list, and the start of data.
+ */
+static unsigned char *ax25_parse_addr(unsigned char *buf, int len, ax25_address *src, ax25_address *dest, ax25_digi *digi)
+{
+ int d = 0;
+
+ if (len < 14) return NULL;
+
+#if 0
+ if (flags != NULL) {
+ *flags = 0;
+
+ if (buf[6] & LAPB_C) {
+ *flags = C_COMMAND;
+ }
+
+ if (buf[13] & LAPB_C) {
+ *flags = C_RESPONSE;
+ }
+ }
+
+ if (dama != NULL)
+ *dama = ~buf[13] & DAMA_FLAG;
+#endif
+
+ /* Copy to, from */
+ if (dest != NULL)
+ memcpy(dest, buf + 0, AX25_ADDR_LEN);
+
+ if (src != NULL)
+ memcpy(src, buf + 7, AX25_ADDR_LEN);
+
+ buf += 2 * AX25_ADDR_LEN;
+ len -= 2 * AX25_ADDR_LEN;
+
+ digi->lastrepeat = -1;
+ digi->ndigi = 0;
+
+ while (!(buf[-1] & LAPB_E)) {
+ if (d >= AX25_MAX_DIGIS) return NULL; /* Max of 6 digis */
+ if (len < 7) return NULL; /* Short packet */
+
+ if (digi != NULL) {
+ memcpy(&digi->calls[d], buf, AX25_ADDR_LEN);
+ digi->ndigi = d + 1;
+
+ if (buf[6] & AX25_REPEATED) {
+ digi->repeated[d] = 1;
+ digi->lastrepeat = d;
+ } else {
+ digi->repeated[d] = 0;
+ }
+ }
+
+ buf += AX25_ADDR_LEN;
+ len -= AX25_ADDR_LEN;
+ d++;
+ }
+
+ return buf;
+}
+
+/*
+ * Check if frame should be echoed. Return 0 if it should and -1 if not.
+ */
+static int check_calls(struct config *cfg, unsigned char *buf, int len)
+{
+ ax25_address dest;
+ ax25_digi digi;
+ ax25_address *axp;
+ int i;
+
+ if ((buf[0] & 0x0F) != 0)
+ return -1; /* don't echo non-data */
+
+ if (cfg->ncalls == 0)
+ return 0; /* copy everything */
+
+ if (ax25_parse_addr(++buf, --len, NULL, &dest, &digi) == NULL)
+ return -1; /* invalid ax.25 header */
+
+ /*
+ * If there are no digis or all digis are already repeated
+ * use destination address. Else use first non-repeated digi.
+ */
+ if (digi.ndigi == 0 || digi.ndigi == digi.lastrepeat + 1)
+ axp = &dest;
+ else
+ axp = &digi.calls[digi.lastrepeat + 1];
+
+ for (i = 0; i < cfg->ncalls; i++)
+ if (ax25_cmp(&cfg->calls[i], axp) == 0)
+ return 0;
+
+ return -1;
+}
+
+int main(int argc, char **argv)
+{
+ struct sockaddr sa;
+ int s, size, alen;
+ unsigned char buf[1500];
+ struct config *p, *list;
+
+ while ((s = getopt(argc, argv, "lv")) != -1) {
+ switch (s) {
+ case 'l':
+ logging = TRUE;
+ break;
+ case 'v':
+ printf("rxecho: %s\n", VERSION);
+ return 0;
+ default:
+ fprintf(stderr, "usage: rxecho [-l] [-v]\n");
+ return 1;
+ }
+ }
+
+ signal(SIGTERM, terminate);
+
+ if (ax25_config_load_ports() == 0) {
+ fprintf(stderr, "rxecho: no AX.25 port data configured\n");
+ return 1;
+ }
+
+ if ((list = readconfig()) == NULL)
+ return 1;
+
+ if ((s = socket(AF_INET, SOCK_PACKET, htons(ETH_P_AX25))) == -1) {
+ perror("rxecho: socket:");
+ return 1;
+ }
+
+ if (!daemon_start(FALSE)) {
+ fprintf(stderr, "rxecho: cannot become a daemon\n");
+ close(s);
+ return 1;
+ }
+
+ if (logging) {
+ openlog("rxecho", LOG_PID, LOG_DAEMON);
+ syslog(LOG_INFO, "starting");
+ }
+
+ for (;;) {
+ alen = sizeof(sa);
+
+ if ((size = recvfrom(s, buf, 1500, 0, &sa, &alen)) == -1) {
+ if (logging) {
+ syslog(LOG_ERR, "recvfrom: %m");
+ closelog();
+ }
+ return 1;
+ }
+
+ for (p = list; p != NULL; p = p->next)
+ if ((strcmp(p->from, sa.sa_data) == 0) && (check_calls(p, buf, size) == 0)) {
+ strcpy(sa.sa_data, p->to);
+ if (sendto(s, buf, size, 0, &sa, alen) == -1) {
+ if (logging) {
+ syslog(LOG_ERR, "sendto: %m");
+ closelog();
+ }
+ }
+ }
+ }
+}
diff --git a/ax25/rxecho.conf b/ax25/rxecho.conf
new file mode 100644
index 0000000..0bb498c
--- /dev/null
+++ b/ax25/rxecho.conf
@@ -0,0 +1,12 @@
+# /etc/ax25/rxecho.conf
+#
+# This means that packets received on port '1' are copied to port '2' if they
+# are destined to oh2bns-1 or oh2bns-2. All packets from port '2' are copied
+# to port '1'.
+#
+# There may be empty lines and an arbirary amount of white space around the
+# tokens but the callsign field must not have any spaces in it. There can be
+# up to MAXCALLS callsigns in the callsign field.
+#
+1 2 oh2bns-1,oh2bns-2
+2 1 *
diff --git a/ax25/rxecho.conf.5 b/ax25/rxecho.conf.5
new file mode 100644
index 0000000..105c45b
--- /dev/null
+++ b/ax25/rxecho.conf.5
@@ -0,0 +1,22 @@
+.TH RXECHO.CONF 5 "2 August 1996" Linux "Linux Programmer's Manual"
+.SH NAME
+rxecho.conf \- control rxecho AX.25 packet routing.
+.SH DESCRIPTION
+.LP
+.B Rxecho.conf
+controls the copying of packets between AX.25 ports performed by the program
+rxecho. The format of the configuration file is:
+
+portin portout * | callsign...
+
+Each entry in the file represents a one-way packet flow between ports. Any
+packet received on portin is copied to portout, if its destination callsign
+or the next callsign to digipeat the frame is in the list of callsigns. If
+the callsign list is replaced by a \(lq*\(rq then all packets are copied.
+The configuration file may contain comments that begin with a #.
+.SH FILES
+.LP
+/etc/ax25/rxecho.conf
+.SH "SEE ALSO"
+.BR axports (8),
+.BR rxecho (8).
diff --git a/config.h.in b/config.h.in
new file mode 100644
index 0000000..29a1390
--- /dev/null
+++ b/config.h.in
@@ -0,0 +1,124 @@
+/* config.h.in. Generated automatically from configure.in by autoheader. */
+
+/* Define to empty if the keyword does not work. */
+#undef const
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef gid_t
+
+/* Define if you have the strftime function. */
+#undef HAVE_STRFTIME
+
+/* Define if you have <sys/wait.h> that is POSIX.1 compatible. */
+#undef HAVE_SYS_WAIT_H
+
+/* Define if you have the wait3 system call. */
+#undef HAVE_WAIT3
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef pid_t
+
+/* Define as the return type of signal handlers (int or void). */
+#undef RETSIGTYPE
+
+/* Define if the `setpgrp' function takes no argument. */
+#undef SETPGRP_VOID
+
+/* Define if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define if you can safely include both <sys/time.h> and <time.h>. */
+#undef TIME_WITH_SYS_TIME
+
+/* Define if your <sys/time.h> declares struct tm. */
+#undef TM_IN_SYS_TIME
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef uid_t
+
+/* Define if the X Window System is missing or not being used. */
+#undef X_DISPLAY_MISSING
+
+#undef HAVE_AX25_FWD_STRUCT
+
+#undef HAVE_AX25_IAMDIGI
+#undef HAVE_AX25_PIDINCL
+
+/* Define if you have the gethostname function. */
+#undef HAVE_GETHOSTNAME
+
+/* Define if you have the gettimeofday function. */
+#undef HAVE_GETTIMEOFDAY
+
+/* Define if you have the mkdir function. */
+#undef HAVE_MKDIR
+
+/* Define if you have the select function. */
+#undef HAVE_SELECT
+
+/* Define if you have the socket function. */
+#undef HAVE_SOCKET
+
+/* Define if you have the strdup function. */
+#undef HAVE_STRDUP
+
+/* Define if you have the strerror function. */
+#undef HAVE_STRERROR
+
+/* Define if you have the strspn function. */
+#undef HAVE_STRSPN
+
+/* Define if you have the strstr function. */
+#undef HAVE_STRSTR
+
+/* Define if you have the strtol function. */
+#undef HAVE_STRTOL
+
+/* Define if you have the strtoul function. */
+#undef HAVE_STRTOUL
+
+/* Define if you have the uname function. */
+#undef HAVE_UNAME
+
+/* Define if you have the <fcntl.h> header file. */
+#undef HAVE_FCNTL_H
+
+/* Define if you have the <limits.h> header file. */
+#undef HAVE_LIMITS_H
+
+/* Define if you have the <paths.h> header file. */
+#undef HAVE_PATHS_H
+
+/* Define if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define if you have the <sys/file.h> header file. */
+#undef HAVE_SYS_FILE_H
+
+/* Define if you have the <sys/ioctl.h> header file. */
+#undef HAVE_SYS_IOCTL_H
+
+/* Define if you have the <sys/time.h> header file. */
+#undef HAVE_SYS_TIME_H
+
+/* Define if you have the <syslog.h> header file. */
+#undef HAVE_SYSLOG_H
+
+/* Define if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define if you have the ax25 library (-lax25). */
+#undef HAVE_LIBAX25
+
+/* Define if you have the util library (-lutil). */
+#undef HAVE_LIBUTIL
+
+/* Define if you have the z library (-lz). */
+#undef HAVE_LIBZ
+
+/* Name of package */
+#undef PACKAGE
+
+/* Version number of package */
+#undef VERSION
+
diff --git a/configure b/configure
new file mode 100755
index 0000000..1e9bf5a
--- /dev/null
+++ b/configure
@@ -0,0 +1,3654 @@
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.13
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+ac_help="$ac_help
+ --with-x use the X Window System"
+ac_help="$ac_help
+ --with-x use the X Window System"
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
+
+ac_prev=
+for ac_option
+do
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval "$ac_prev=\$ac_option"
+ ac_prev=
+ continue
+ fi
+
+ case "$ac_option" in
+ -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) ac_optarg= ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case "$ac_option" in
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir="$ac_optarg" ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build="$ac_optarg" ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file="$ac_optarg" ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir="$ac_optarg" ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ eval "enable_${ac_feature}=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "enable_${ac_feature}='$ac_optarg'" ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix="$ac_optarg" ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he)
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+ --cache-file=FILE cache test results in FILE
+ --help print this message
+ --no-create do not create output files
+ --quiet, --silent do not print \`checking...' messages
+ --version print the version of autoconf that created configure
+Directory and file names:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [same as prefix]
+ --bindir=DIR user executables in DIR [EPREFIX/bin]
+ --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
+ --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data in DIR
+ [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data in DIR
+ [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
+ --libdir=DIR object code libraries in DIR [EPREFIX/lib]
+ --includedir=DIR C header files in DIR [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
+ --infodir=DIR info documentation in DIR [PREFIX/info]
+ --mandir=DIR man documentation in DIR [PREFIX/man]
+ --srcdir=DIR find the sources in DIR [configure dir or ..]
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM
+ run sed PROGRAM on installed program names
+EOF
+ cat << EOF
+Host type:
+ --build=BUILD configure for building on BUILD [BUILD=HOST]
+ --host=HOST configure for HOST [guessed]
+ --target=TARGET configure for TARGET [TARGET=HOST]
+Features and packages:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --x-includes=DIR X include files are in DIR
+ --x-libraries=DIR X library files are in DIR
+EOF
+ if test -n "$ac_help"; then
+ echo "--enable and --with options recognized:$ac_help"
+ fi
+ exit 0 ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host="$ac_optarg" ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir="$ac_optarg" ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir="$ac_optarg" ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir="$ac_optarg" ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir="$ac_optarg" ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+ | --locals | --local | --loca | --loc | --lo)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ localstatedir="$ac_optarg" ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir="$ac_optarg" ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir="$ac_optarg" ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix="$ac_optarg" ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix="$ac_optarg" ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix="$ac_optarg" ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name="$ac_optarg" ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir="$ac_optarg" ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir="$ac_optarg" ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site="$ac_optarg" ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir="$ac_optarg" ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir="$ac_optarg" ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target="$ac_optarg" ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers)
+ echo "configure generated by autoconf version 2.13"
+ exit 0 ;;
+
+ -with-* | --with-*)
+ ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_${ac_package}='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ eval "with_${ac_package}=no" ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes="$ac_optarg" ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries="$ac_optarg" ;;
+
+ -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+ ;;
+
+ *)
+ if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+ echo "configure: warning: $ac_option: invalid host type" 1>&2
+ fi
+ if test "x$nonopt" != xNONE; then
+ { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+ fi
+ nonopt="$ac_option"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+ exec 6>/dev/null
+else
+ exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+ case "$ac_arg" in
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c) ;;
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+ ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+ esac
+done
+
+# NLS nuisances.
+# Only set these to C if already set. These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
+if test "${LANG+set}" = set; then LANG=C; export LANG; fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=ax25/ax25d.c
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then its parent.
+ ac_prog=$0
+ ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+ test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+ srcdir=$ac_confdir
+ if test ! -r $srcdir/$ac_unique_file; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+ else
+ { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+ fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+ echo "loading site script $ac_site_file"
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ echo "loading cache $cache_file"
+ . $cache_file
+else
+ echo "creating cache $cache_file"
+ > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+ac_exeext=
+ac_objext=o
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+ # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+ if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+ ac_n= ac_c='
+' ac_t=' '
+ else
+ ac_n=-n ac_c= ac_t=
+ fi
+else
+ ac_n= ac_c='\c' ac_t=
+fi
+
+
+
+VERSION=0.0.1
+PACKAGE=ax25-tools
+ac_aux_dir=
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+ if test -f $ac_dir/install-sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f $ac_dir/install.sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+echo "configure:563: checking for a BSD compatible install" >&5
+if test -z "$INSTALL"; then
+if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":"
+ for ac_dir in $PATH; do
+ # Account for people who put trailing slashes in PATH elements.
+ case "$ac_dir/" in
+ /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ if test -f $ac_dir/$ac_prog; then
+ if test $ac_prog = install &&
+ grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ else
+ ac_cv_path_install="$ac_dir/$ac_prog -c"
+ break 2
+ fi
+ fi
+ done
+ ;;
+ esac
+ done
+ IFS="$ac_save_IFS"
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL="$ac_cv_path_install"
+ else
+ # As a last resort, use the slow shell script. We don't cache a
+ # path for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the path is relative.
+ INSTALL="$ac_install_sh"
+ fi
+fi
+echo "$ac_t""$INSTALL" 1>&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6
+echo "configure:616: checking whether build environment is sane" >&5
+# Just in case
+sleep 1
+echo timestamp > conftestfile
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments. Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+ set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null`
+ if test "$*" = "X"; then
+ # -L didn't work.
+ set X `ls -t $srcdir/configure conftestfile`
+ fi
+ if test "$*" != "X $srcdir/configure conftestfile" \
+ && test "$*" != "X conftestfile $srcdir/configure"; then
+
+ # If neither matched, then we have a broken ls. This can happen
+ # if, for instance, CONFIG_SHELL is bash and it inherits a
+ # broken ls alias from the environment. This has actually
+ # happened. Such a system could not be considered "sane".
+ { echo "configure: error: ls -t appears to fail. Make sure there is not a broken
+alias in your environment" 1>&2; exit 1; }
+ fi
+
+ test "$2" = conftestfile
+ )
+then
+ # Ok.
+ :
+else
+ { echo "configure: error: newly created file is older than distributed files!
+Check your system clock" 1>&2; exit 1; }
+fi
+rm -f conftest*
+echo "$ac_t""yes" 1>&6
+if test "$program_transform_name" = s,x,x,; then
+ program_transform_name=
+else
+ # Double any \ or $. echo might interpret backslashes.
+ cat <<\EOF_SED > conftestsed
+s,\\,\\\\,g; s,\$,$$,g
+EOF_SED
+ program_transform_name="`echo $program_transform_name|sed -f conftestsed`"
+ rm -f conftestsed
+fi
+test "$program_prefix" != NONE &&
+ program_transform_name="s,^,${program_prefix},; $program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+ program_transform_name="s,\$\$,${program_suffix},; $program_transform_name"
+
+# sed with no file args requires a program.
+test "$program_transform_name" = "" && program_transform_name="s,x,x,"
+
+echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
+echo "configure:673: checking whether ${MAKE-make} sets \${MAKE}" >&5
+set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftestmake <<\EOF
+all:
+ @echo 'ac_maketemp="${MAKE}"'
+EOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=`
+if test -n "$ac_maketemp"; then
+ eval ac_cv_prog_make_${ac_make}_set=yes
+else
+ eval ac_cv_prog_make_${ac_make}_set=no
+fi
+rm -f conftestmake
+fi
+if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ SET_MAKE=
+else
+ echo "$ac_t""no" 1>&6
+ SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+
+PACKAGE=$PACKAGE
+
+VERSION=$VERSION
+
+if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then
+ { echo "configure: error: source directory already configured; run "make distclean" there first" 1>&2; exit 1; }
+fi
+cat >> confdefs.h <<EOF
+#define PACKAGE "$PACKAGE"
+EOF
+
+cat >> confdefs.h <<EOF
+#define VERSION "$VERSION"
+EOF
+
+
+
+missing_dir=`cd $ac_aux_dir && pwd`
+echo $ac_n "checking for working aclocal""... $ac_c" 1>&6
+echo "configure:719: checking for working aclocal" >&5
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf. Sigh.
+if (aclocal --version) < /dev/null > /dev/null 2>&1; then
+ ACLOCAL=aclocal
+ echo "$ac_t""found" 1>&6
+else
+ ACLOCAL="$missing_dir/missing aclocal"
+ echo "$ac_t""missing" 1>&6
+fi
+
+echo $ac_n "checking for working autoconf""... $ac_c" 1>&6
+echo "configure:732: checking for working autoconf" >&5
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf. Sigh.
+if (autoconf --version) < /dev/null > /dev/null 2>&1; then
+ AUTOCONF=autoconf
+ echo "$ac_t""found" 1>&6
+else
+ AUTOCONF="$missing_dir/missing autoconf"
+ echo "$ac_t""missing" 1>&6
+fi
+
+echo $ac_n "checking for working automake""... $ac_c" 1>&6
+echo "configure:745: checking for working automake" >&5
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf. Sigh.
+if (automake --version) < /dev/null > /dev/null 2>&1; then
+ AUTOMAKE=automake
+ echo "$ac_t""found" 1>&6
+else
+ AUTOMAKE="$missing_dir/missing automake"
+ echo "$ac_t""missing" 1>&6
+fi
+
+echo $ac_n "checking for working autoheader""... $ac_c" 1>&6
+echo "configure:758: checking for working autoheader" >&5
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf. Sigh.
+if (autoheader --version) < /dev/null > /dev/null 2>&1; then
+ AUTOHEADER=autoheader
+ echo "$ac_t""found" 1>&6
+else
+ AUTOHEADER="$missing_dir/missing autoheader"
+ echo "$ac_t""missing" 1>&6
+fi
+
+echo $ac_n "checking for working makeinfo""... $ac_c" 1>&6
+echo "configure:771: checking for working makeinfo" >&5
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf. Sigh.
+if (makeinfo --version) < /dev/null > /dev/null 2>&1; then
+ MAKEINFO=makeinfo
+ echo "$ac_t""found" 1>&6
+else
+ MAKEINFO="$missing_dir/missing makeinfo"
+ echo "$ac_t""missing" 1>&6
+fi
+
+
+
+
+
+
+
+
+
+for ac_prog in mawk gawk nawk awk
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:796: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_AWK'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$AWK"; then
+ ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_AWK="$ac_prog"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+AWK="$ac_cv_prog_AWK"
+if test -n "$AWK"; then
+ echo "$ac_t""$AWK" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+test -n "$AWK" && break
+done
+
+# Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:828: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="gcc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:858: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_prog_rejected=no
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# -gt 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ set dummy "$ac_dir/$ac_word" "$@"
+ shift
+ ac_cv_prog_CC="$@"
+ fi
+fi
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test -z "$CC"; then
+ case "`uname -s`" in
+ *win32* | *WIN32*)
+ # Extract the first word of "cl", so it can be a program name with args.
+set dummy cl; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:909: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="cl"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+ ;;
+ esac
+ fi
+ test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:941: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+cat > conftest.$ac_ext << EOF
+
+#line 952 "configure"
+#include "confdefs.h"
+
+main(){return(0);}
+EOF
+if { (eval echo configure:957: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ ac_cv_prog_cc_works=yes
+ # If we can't run a trivial program, we are probably using a cross compiler.
+ if (./conftest; exit) 2>/dev/null; then
+ ac_cv_prog_cc_cross=no
+ else
+ ac_cv_prog_cc_cross=yes
+ fi
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ ac_cv_prog_cc_works=no
+fi
+rm -fr conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
+if test $ac_cv_prog_cc_works = no; then
+ { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:983: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+echo "configure:988: checking whether we are using GNU C" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.c <<EOF
+#ifdef __GNUC__
+ yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:997: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+ ac_cv_prog_gcc=yes
+else
+ ac_cv_prog_gcc=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+
+if test $ac_cv_prog_gcc = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+
+ac_test_CFLAGS="${CFLAGS+set}"
+ac_save_CFLAGS="$CFLAGS"
+CFLAGS=
+echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+echo "configure:1016: checking whether ${CC-cc} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ echo 'void f(){}' > conftest.c
+if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
+ ac_cv_prog_cc_g=yes
+else
+ ac_cv_prog_cc_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS="$ac_save_CFLAGS"
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+echo "configure:1059: checking for a BSD compatible install" >&5
+if test -z "$INSTALL"; then
+if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":"
+ for ac_dir in $PATH; do
+ # Account for people who put trailing slashes in PATH elements.
+ case "$ac_dir/" in
+ /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ if test -f $ac_dir/$ac_prog; then
+ if test $ac_prog = install &&
+ grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ else
+ ac_cv_path_install="$ac_dir/$ac_prog -c"
+ break 2
+ fi
+ fi
+ done
+ ;;
+ esac
+ done
+ IFS="$ac_save_IFS"
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL="$ac_cv_path_install"
+ else
+ # As a last resort, use the slow shell script. We don't cache a
+ # path for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the path is relative.
+ INSTALL="$ac_install_sh"
+ fi
+fi
+echo "$ac_t""$INSTALL" 1>&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+
+echo $ac_n "checking for zlibVersion in -lz""... $ac_c" 1>&6
+echo "configure:1113: checking for zlibVersion in -lz" >&5
+ac_lib_var=`echo z'_'zlibVersion | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lz $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1121 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char zlibVersion();
+
+int main() {
+zlibVersion()
+; return 0; }
+EOF
+if { (eval echo configure:1132: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo z | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-lz $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+echo $ac_n "checking for ax25_config_load_ports in -lax25""... $ac_c" 1>&6
+echo "configure:1160: checking for ax25_config_load_ports in -lax25" >&5
+ac_lib_var=`echo ax25'_'ax25_config_load_ports | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lax25 -lz $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1168 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char ax25_config_load_ports();
+
+int main() {
+ax25_config_load_ports()
+; return 0; }
+EOF
+if { (eval echo configure:1179: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo ax25 | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-lax25 $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+echo $ac_n "checking for initscr in -lncurses""... $ac_c" 1>&6
+echo "configure:1208: checking for initscr in -lncurses" >&5
+ac_lib_var=`echo ncurses'_'initscr | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lncurses $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1216 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char initscr();
+
+int main() {
+initscr()
+; return 0; }
+EOF
+if { (eval echo configure:1227: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ NCURSES_LIB="-lncurses"
+else
+ echo "$ac_t""no" 1>&6
+NCURSES_LIB=
+fi
+
+
+echo $ac_n "checking for openpty in -lutil""... $ac_c" 1>&6
+echo "configure:1250: checking for openpty in -lutil" >&5
+ac_lib_var=`echo util'_'openpty | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lutil $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1258 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char openpty();
+
+int main() {
+openpty()
+; return 0; }
+EOF
+if { (eval echo configure:1269: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo util | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-lutil $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+echo "configure:1297: checking how to run the C preprocessor" >&5
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ # This must be in double quotes, not single quotes, because CPP may get
+ # substituted into the Makefile and "${CC-cc}" will confuse make.
+ CPP="${CC-cc} -E"
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp.
+ cat > conftest.$ac_ext <<EOF
+#line 1312 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1318: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -E -traditional-cpp"
+ cat > conftest.$ac_ext <<EOF
+#line 1329 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1335: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -nologo -E"
+ cat > conftest.$ac_ext <<EOF
+#line 1346 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1352: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP=/lib/cpp
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+ ac_cv_prog_CPP="$CPP"
+fi
+ CPP="$ac_cv_prog_CPP"
+else
+ ac_cv_prog_CPP="$CPP"
+fi
+echo "$ac_t""$CPP" 1>&6
+
+# If we find X, set shell vars x_includes and x_libraries to the
+# paths, otherwise set no_x=yes.
+# Uses ac_ vars as temps to allow command line to override cache and checks.
+# --without-x overrides everything else, but does not touch the cache.
+echo $ac_n "checking for X""... $ac_c" 1>&6
+echo "configure:1381: checking for X" >&5
+
+# Check whether --with-x or --without-x was given.
+if test "${with_x+set}" = set; then
+ withval="$with_x"
+ :
+fi
+
+# $have_x is `yes', `no', `disabled', or empty when we do not yet know.
+if test "x$with_x" = xno; then
+ # The user explicitly disabled X.
+ have_x=disabled
+else
+ if test "x$x_includes" != xNONE && test "x$x_libraries" != xNONE; then
+ # Both variables are already set.
+ have_x=yes
+ else
+if eval "test \"`echo '$''{'ac_cv_have_x'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ # One or both of the vars are not set, and there is no cached value.
+ac_x_includes=NO ac_x_libraries=NO
+rm -fr conftestdir
+if mkdir conftestdir; then
+ cd conftestdir
+ # Make sure to not put "make" in the Imakefile rules, since we grep it out.
+ cat > Imakefile <<'EOF'
+acfindx:
+ @echo 'ac_im_incroot="${INCROOT}"; ac_im_usrlibdir="${USRLIBDIR}"; ac_im_libdir="${LIBDIR}"'
+EOF
+ if (xmkmf) >/dev/null 2>/dev/null && test -f Makefile; then
+ # GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+ eval `${MAKE-make} acfindx 2>/dev/null | grep -v make`
+ # Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR.
+ for ac_extension in a so sl; do
+ if test ! -f $ac_im_usrlibdir/libX11.$ac_extension &&
+ test -f $ac_im_libdir/libX11.$ac_extension; then
+ ac_im_usrlibdir=$ac_im_libdir; break
+ fi
+ done
+ # Screen out bogus values from the imake configuration. They are
+ # bogus both because they are the default anyway, and because
+ # using them would break gcc on systems where it needs fixed includes.
+ case "$ac_im_incroot" in
+ /usr/include) ;;
+ *) test -f "$ac_im_incroot/X11/Xos.h" && ac_x_includes="$ac_im_incroot" ;;
+ esac
+ case "$ac_im_usrlibdir" in
+ /usr/lib | /lib) ;;
+ *) test -d "$ac_im_usrlibdir" && ac_x_libraries="$ac_im_usrlibdir" ;;
+ esac
+ fi
+ cd ..
+ rm -fr conftestdir
+fi
+
+if test "$ac_x_includes" = NO; then
+ # Guess where to find include files, by looking for this one X11 .h file.
+ test -z "$x_direct_test_include" && x_direct_test_include=X11/Intrinsic.h
+
+ # First, try using that file with no special directory specified.
+cat > conftest.$ac_ext <<EOF
+#line 1443 "configure"
+#include "confdefs.h"
+#include <$x_direct_test_include>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1448: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ # We can compile using X headers with no special include directory.
+ac_x_includes=
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ # Look for the header file in a standard set of common directories.
+# Check X11 before X11Rn because it is often a symlink to the current release.
+ for ac_dir in \
+ /usr/X11/include \
+ /usr/X11R6/include \
+ /usr/X11R5/include \
+ /usr/X11R4/include \
+ \
+ /usr/include/X11 \
+ /usr/include/X11R6 \
+ /usr/include/X11R5 \
+ /usr/include/X11R4 \
+ \
+ /usr/local/X11/include \
+ /usr/local/X11R6/include \
+ /usr/local/X11R5/include \
+ /usr/local/X11R4/include \
+ \
+ /usr/local/include/X11 \
+ /usr/local/include/X11R6 \
+ /usr/local/include/X11R5 \
+ /usr/local/include/X11R4 \
+ \
+ /usr/X386/include \
+ /usr/x386/include \
+ /usr/XFree86/include/X11 \
+ \
+ /usr/include \
+ /usr/local/include \
+ /usr/unsupported/include \
+ /usr/athena/include \
+ /usr/local/x11r5/include \
+ /usr/lpp/Xamples/include \
+ \
+ /usr/openwin/include \
+ /usr/openwin/share/include \
+ ; \
+ do
+ if test -r "$ac_dir/$x_direct_test_include"; then
+ ac_x_includes=$ac_dir
+ break
+ fi
+ done
+fi
+rm -f conftest*
+fi # $ac_x_includes = NO
+
+if test "$ac_x_libraries" = NO; then
+ # Check for the libraries.
+
+ test -z "$x_direct_test_library" && x_direct_test_library=Xt
+ test -z "$x_direct_test_function" && x_direct_test_function=XtMalloc
+
+ # See if we find them without any special options.
+ # Don't add to $LIBS permanently.
+ ac_save_LIBS="$LIBS"
+ LIBS="-l$x_direct_test_library $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1517 "configure"
+#include "confdefs.h"
+
+int main() {
+${x_direct_test_function}()
+; return 0; }
+EOF
+if { (eval echo configure:1524: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ LIBS="$ac_save_LIBS"
+# We can link X programs with no special library path.
+ac_x_libraries=
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ LIBS="$ac_save_LIBS"
+# First see if replacing the include by lib works.
+# Check X11 before X11Rn because it is often a symlink to the current release.
+for ac_dir in `echo "$ac_x_includes" | sed s/include/lib/` \
+ /usr/X11/lib \
+ /usr/X11R6/lib \
+ /usr/X11R5/lib \
+ /usr/X11R4/lib \
+ \
+ /usr/lib/X11 \
+ /usr/lib/X11R6 \
+ /usr/lib/X11R5 \
+ /usr/lib/X11R4 \
+ \
+ /usr/local/X11/lib \
+ /usr/local/X11R6/lib \
+ /usr/local/X11R5/lib \
+ /usr/local/X11R4/lib \
+ \
+ /usr/local/lib/X11 \
+ /usr/local/lib/X11R6 \
+ /usr/local/lib/X11R5 \
+ /usr/local/lib/X11R4 \
+ \
+ /usr/X386/lib \
+ /usr/x386/lib \
+ /usr/XFree86/lib/X11 \
+ \
+ /usr/lib \
+ /usr/local/lib \
+ /usr/unsupported/lib \
+ /usr/athena/lib \
+ /usr/local/x11r5/lib \
+ /usr/lpp/Xamples/lib \
+ /lib/usr/lib/X11 \
+ \
+ /usr/openwin/lib \
+ /usr/openwin/share/lib \
+ ; \
+do
+ for ac_extension in a so sl; do
+ if test -r $ac_dir/lib${x_direct_test_library}.$ac_extension; then
+ ac_x_libraries=$ac_dir
+ break 2
+ fi
+ done
+done
+fi
+rm -f conftest*
+fi # $ac_x_libraries = NO
+
+if test "$ac_x_includes" = NO || test "$ac_x_libraries" = NO; then
+ # Didn't find X anywhere. Cache the known absence of X.
+ ac_cv_have_x="have_x=no"
+else
+ # Record where we found X for the cache.
+ ac_cv_have_x="have_x=yes \
+ ac_x_includes=$ac_x_includes ac_x_libraries=$ac_x_libraries"
+fi
+fi
+ fi
+ eval "$ac_cv_have_x"
+fi # $with_x != no
+
+if test "$have_x" != yes; then
+ echo "$ac_t""$have_x" 1>&6
+ no_x=yes
+else
+ # If each of the values was on the command line, it overrides each guess.
+ test "x$x_includes" = xNONE && x_includes=$ac_x_includes
+ test "x$x_libraries" = xNONE && x_libraries=$ac_x_libraries
+ # Update the cache value to reflect the command line values.
+ ac_cv_have_x="have_x=yes \
+ ac_x_includes=$x_includes ac_x_libraries=$x_libraries"
+ echo "$ac_t""libraries $x_libraries, headers $x_includes" 1>&6
+fi
+
+if test "$no_x" = yes; then
+ # Not all programs may use this symbol, but it does not hurt to define it.
+ cat >> confdefs.h <<\EOF
+#define X_DISPLAY_MISSING 1
+EOF
+
+ X_CFLAGS= X_PRE_LIBS= X_LIBS= X_EXTRA_LIBS=
+else
+ if test -n "$x_includes"; then
+ X_CFLAGS="$X_CFLAGS -I$x_includes"
+ fi
+
+ # It would also be nice to do this for all -L options, not just this one.
+ if test -n "$x_libraries"; then
+ X_LIBS="$X_LIBS -L$x_libraries"
+ # For Solaris; some versions of Sun CC require a space after -R and
+ # others require no space. Words are not sufficient . . . .
+ case "`(uname -sr) 2>/dev/null`" in
+ "SunOS 5"*)
+ echo $ac_n "checking whether -R must be followed by a space""... $ac_c" 1>&6
+echo "configure:1630: checking whether -R must be followed by a space" >&5
+ ac_xsave_LIBS="$LIBS"; LIBS="$LIBS -R$x_libraries"
+ cat > conftest.$ac_ext <<EOF
+#line 1633 "configure"
+#include "confdefs.h"
+
+int main() {
+
+; return 0; }
+EOF
+if { (eval echo configure:1640: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ ac_R_nospace=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_R_nospace=no
+fi
+rm -f conftest*
+ if test $ac_R_nospace = yes; then
+ echo "$ac_t""no" 1>&6
+ X_LIBS="$X_LIBS -R$x_libraries"
+ else
+ LIBS="$ac_xsave_LIBS -R $x_libraries"
+ cat > conftest.$ac_ext <<EOF
+#line 1656 "configure"
+#include "confdefs.h"
+
+int main() {
+
+; return 0; }
+EOF
+if { (eval echo configure:1663: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ ac_R_space=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_R_space=no
+fi
+rm -f conftest*
+ if test $ac_R_space = yes; then
+ echo "$ac_t""yes" 1>&6
+ X_LIBS="$X_LIBS -R $x_libraries"
+ else
+ echo "$ac_t""neither works" 1>&6
+ fi
+ fi
+ LIBS="$ac_xsave_LIBS"
+ esac
+ fi
+
+ # Check for system-dependent libraries X programs must link with.
+ # Do this before checking for the system-independent R6 libraries
+ # (-lICE), since we may need -lsocket or whatever for X linking.
+
+ if test "$ISC" = yes; then
+ X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl_s -linet"
+ else
+ # Martyn.Johnson@cl.cam.ac.uk says this is needed for Ultrix, if the X
+ # libraries were built with DECnet support. And karl@cs.umb.edu says
+ # the Alpha needs dnet_stub (dnet does not exist).
+ echo $ac_n "checking for dnet_ntoa in -ldnet""... $ac_c" 1>&6
+echo "configure:1695: checking for dnet_ntoa in -ldnet" >&5
+ac_lib_var=`echo dnet'_'dnet_ntoa | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-ldnet $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1703 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char dnet_ntoa();
+
+int main() {
+dnet_ntoa()
+; return 0; }
+EOF
+if { (eval echo configure:1714: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test $ac_cv_lib_dnet_dnet_ntoa = no; then
+ echo $ac_n "checking for dnet_ntoa in -ldnet_stub""... $ac_c" 1>&6
+echo "configure:1736: checking for dnet_ntoa in -ldnet_stub" >&5
+ac_lib_var=`echo dnet_stub'_'dnet_ntoa | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-ldnet_stub $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1744 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char dnet_ntoa();
+
+int main() {
+dnet_ntoa()
+; return 0; }
+EOF
+if { (eval echo configure:1755: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet_stub"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ fi
+
+ # msh@cis.ufl.edu says -lnsl (and -lsocket) are needed for his 386/AT,
+ # to get the SysV transport functions.
+ # chad@anasazi.com says the Pyramis MIS-ES running DC/OSx (SVR4)
+ # needs -lnsl.
+ # The nsl library prevents programs from opening the X display
+ # on Irix 5.2, according to dickey@clark.net.
+ echo $ac_n "checking for gethostbyname""... $ac_c" 1>&6
+echo "configure:1784: checking for gethostbyname" >&5
+if eval "test \"`echo '$''{'ac_cv_func_gethostbyname'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1789 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char gethostbyname(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char gethostbyname();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_gethostbyname) || defined (__stub___gethostbyname)
+choke me
+#else
+gethostbyname();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1812: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_gethostbyname=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_gethostbyname=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'gethostbyname`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ :
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test $ac_cv_func_gethostbyname = no; then
+ echo $ac_n "checking for gethostbyname in -lnsl""... $ac_c" 1>&6
+echo "configure:1833: checking for gethostbyname in -lnsl" >&5
+ac_lib_var=`echo nsl'_'gethostbyname | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lnsl $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1841 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char gethostbyname();
+
+int main() {
+gethostbyname()
+; return 0; }
+EOF
+if { (eval echo configure:1852: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ fi
+
+ # lieder@skyler.mavd.honeywell.com says without -lsocket,
+ # socket/setsockopt and other routines are undefined under SCO ODT
+ # 2.0. But -lsocket is broken on IRIX 5.2 (and is not necessary
+ # on later versions), says simon@lia.di.epfl.ch: it contains
+ # gethostby* variants that don't use the nameserver (or something).
+ # -lsocket must be given before -lnsl if both are needed.
+ # We assume that if connect needs -lnsl, so does gethostbyname.
+ echo $ac_n "checking for connect""... $ac_c" 1>&6
+echo "configure:1882: checking for connect" >&5
+if eval "test \"`echo '$''{'ac_cv_func_connect'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1887 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char connect(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char connect();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_connect) || defined (__stub___connect)
+choke me
+#else
+connect();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1910: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_connect=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_connect=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'connect`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ :
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test $ac_cv_func_connect = no; then
+ echo $ac_n "checking for connect in -lsocket""... $ac_c" 1>&6
+echo "configure:1931: checking for connect in -lsocket" >&5
+ac_lib_var=`echo socket'_'connect | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lsocket $X_EXTRA_LIBS $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1939 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char connect();
+
+int main() {
+connect()
+; return 0; }
+EOF
+if { (eval echo configure:1950: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ X_EXTRA_LIBS="-lsocket $X_EXTRA_LIBS"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ fi
+
+ # gomez@mi.uni-erlangen.de says -lposix is necessary on A/UX.
+ echo $ac_n "checking for remove""... $ac_c" 1>&6
+echo "configure:1974: checking for remove" >&5
+if eval "test \"`echo '$''{'ac_cv_func_remove'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1979 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char remove(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char remove();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_remove) || defined (__stub___remove)
+choke me
+#else
+remove();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2002: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_remove=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_remove=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'remove`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ :
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test $ac_cv_func_remove = no; then
+ echo $ac_n "checking for remove in -lposix""... $ac_c" 1>&6
+echo "configure:2023: checking for remove in -lposix" >&5
+ac_lib_var=`echo posix'_'remove | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lposix $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2031 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char remove();
+
+int main() {
+remove()
+; return 0; }
+EOF
+if { (eval echo configure:2042: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ X_EXTRA_LIBS="$X_EXTRA_LIBS -lposix"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ fi
+
+ # BSDI BSD/OS 2.1 needs -lipc for XOpenDisplay.
+ echo $ac_n "checking for shmat""... $ac_c" 1>&6
+echo "configure:2066: checking for shmat" >&5
+if eval "test \"`echo '$''{'ac_cv_func_shmat'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2071 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char shmat(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char shmat();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_shmat) || defined (__stub___shmat)
+choke me
+#else
+shmat();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2094: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_shmat=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_shmat=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'shmat`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ :
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test $ac_cv_func_shmat = no; then
+ echo $ac_n "checking for shmat in -lipc""... $ac_c" 1>&6
+echo "configure:2115: checking for shmat in -lipc" >&5
+ac_lib_var=`echo ipc'_'shmat | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lipc $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2123 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char shmat();
+
+int main() {
+shmat()
+; return 0; }
+EOF
+if { (eval echo configure:2134: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ X_EXTRA_LIBS="$X_EXTRA_LIBS -lipc"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ fi
+ fi
+
+ # Check for libraries that X11R6 Xt/Xaw programs need.
+ ac_save_LDFLAGS="$LDFLAGS"
+ test -n "$x_libraries" && LDFLAGS="$LDFLAGS -L$x_libraries"
+ # SM needs ICE to (dynamically) link under SunOS 4.x (so we have to
+ # check for ICE first), but we must link in the order -lSM -lICE or
+ # we get undefined symbols. So assume we have SM if we have ICE.
+ # These have to be linked with before -lX11, unlike the other
+ # libraries we check for below, so use a different variable.
+ # --interran@uluru.Stanford.EDU, kb@cs.umb.edu.
+ echo $ac_n "checking for IceConnectionNumber in -lICE""... $ac_c" 1>&6
+echo "configure:2167: checking for IceConnectionNumber in -lICE" >&5
+ac_lib_var=`echo ICE'_'IceConnectionNumber | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lICE $X_EXTRA_LIBS $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2175 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char IceConnectionNumber();
+
+int main() {
+IceConnectionNumber()
+; return 0; }
+EOF
+if { (eval echo configure:2186: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ X_PRE_LIBS="$X_PRE_LIBS -lSM -lICE"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ LDFLAGS="$ac_save_LDFLAGS"
+
+fi
+
+
+# If we find X, set shell vars x_includes and x_libraries to the
+# paths, otherwise set no_x=yes.
+# Uses ac_ vars as temps to allow command line to override cache and checks.
+# --without-x overrides everything else, but does not touch the cache.
+echo $ac_n "checking for X""... $ac_c" 1>&6
+echo "configure:2216: checking for X" >&5
+
+# Check whether --with-x or --without-x was given.
+if test "${with_x+set}" = set; then
+ withval="$with_x"
+ :
+fi
+
+# $have_x is `yes', `no', `disabled', or empty when we do not yet know.
+if test "x$with_x" = xno; then
+ # The user explicitly disabled X.
+ have_x=disabled
+else
+ if test "x$x_includes" != xNONE && test "x$x_libraries" != xNONE; then
+ # Both variables are already set.
+ have_x=yes
+ else
+if eval "test \"`echo '$''{'ac_cv_have_x'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ # One or both of the vars are not set, and there is no cached value.
+ac_x_includes=NO ac_x_libraries=NO
+rm -fr conftestdir
+if mkdir conftestdir; then
+ cd conftestdir
+ # Make sure to not put "make" in the Imakefile rules, since we grep it out.
+ cat > Imakefile <<'EOF'
+acfindx:
+ @echo 'ac_im_incroot="${INCROOT}"; ac_im_usrlibdir="${USRLIBDIR}"; ac_im_libdir="${LIBDIR}"'
+EOF
+ if (xmkmf) >/dev/null 2>/dev/null && test -f Makefile; then
+ # GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+ eval `${MAKE-make} acfindx 2>/dev/null | grep -v make`
+ # Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR.
+ for ac_extension in a so sl; do
+ if test ! -f $ac_im_usrlibdir/libX11.$ac_extension &&
+ test -f $ac_im_libdir/libX11.$ac_extension; then
+ ac_im_usrlibdir=$ac_im_libdir; break
+ fi
+ done
+ # Screen out bogus values from the imake configuration. They are
+ # bogus both because they are the default anyway, and because
+ # using them would break gcc on systems where it needs fixed includes.
+ case "$ac_im_incroot" in
+ /usr/include) ;;
+ *) test -f "$ac_im_incroot/X11/Xos.h" && ac_x_includes="$ac_im_incroot" ;;
+ esac
+ case "$ac_im_usrlibdir" in
+ /usr/lib | /lib) ;;
+ *) test -d "$ac_im_usrlibdir" && ac_x_libraries="$ac_im_usrlibdir" ;;
+ esac
+ fi
+ cd ..
+ rm -fr conftestdir
+fi
+
+if test "$ac_x_includes" = NO; then
+ # Guess where to find include files, by looking for this one X11 .h file.
+ test -z "$x_direct_test_include" && x_direct_test_include=X11/Intrinsic.h
+
+ # First, try using that file with no special directory specified.
+cat > conftest.$ac_ext <<EOF
+#line 2278 "configure"
+#include "confdefs.h"
+#include <$x_direct_test_include>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2283: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ # We can compile using X headers with no special include directory.
+ac_x_includes=
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ # Look for the header file in a standard set of common directories.
+# Check X11 before X11Rn because it is often a symlink to the current release.
+ for ac_dir in \
+ /usr/X11/include \
+ /usr/X11R6/include \
+ /usr/X11R5/include \
+ /usr/X11R4/include \
+ \
+ /usr/include/X11 \
+ /usr/include/X11R6 \
+ /usr/include/X11R5 \
+ /usr/include/X11R4 \
+ \
+ /usr/local/X11/include \
+ /usr/local/X11R6/include \
+ /usr/local/X11R5/include \
+ /usr/local/X11R4/include \
+ \
+ /usr/local/include/X11 \
+ /usr/local/include/X11R6 \
+ /usr/local/include/X11R5 \
+ /usr/local/include/X11R4 \
+ \
+ /usr/X386/include \
+ /usr/x386/include \
+ /usr/XFree86/include/X11 \
+ \
+ /usr/include \
+ /usr/local/include \
+ /usr/unsupported/include \
+ /usr/athena/include \
+ /usr/local/x11r5/include \
+ /usr/lpp/Xamples/include \
+ \
+ /usr/openwin/include \
+ /usr/openwin/share/include \
+ ; \
+ do
+ if test -r "$ac_dir/$x_direct_test_include"; then
+ ac_x_includes=$ac_dir
+ break
+ fi
+ done
+fi
+rm -f conftest*
+fi # $ac_x_includes = NO
+
+if test "$ac_x_libraries" = NO; then
+ # Check for the libraries.
+
+ test -z "$x_direct_test_library" && x_direct_test_library=Xt
+ test -z "$x_direct_test_function" && x_direct_test_function=XtMalloc
+
+ # See if we find them without any special options.
+ # Don't add to $LIBS permanently.
+ ac_save_LIBS="$LIBS"
+ LIBS="-l$x_direct_test_library $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2352 "configure"
+#include "confdefs.h"
+
+int main() {
+${x_direct_test_function}()
+; return 0; }
+EOF
+if { (eval echo configure:2359: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ LIBS="$ac_save_LIBS"
+# We can link X programs with no special library path.
+ac_x_libraries=
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ LIBS="$ac_save_LIBS"
+# First see if replacing the include by lib works.
+# Check X11 before X11Rn because it is often a symlink to the current release.
+for ac_dir in `echo "$ac_x_includes" | sed s/include/lib/` \
+ /usr/X11/lib \
+ /usr/X11R6/lib \
+ /usr/X11R5/lib \
+ /usr/X11R4/lib \
+ \
+ /usr/lib/X11 \
+ /usr/lib/X11R6 \
+ /usr/lib/X11R5 \
+ /usr/lib/X11R4 \
+ \
+ /usr/local/X11/lib \
+ /usr/local/X11R6/lib \
+ /usr/local/X11R5/lib \
+ /usr/local/X11R4/lib \
+ \
+ /usr/local/lib/X11 \
+ /usr/local/lib/X11R6 \
+ /usr/local/lib/X11R5 \
+ /usr/local/lib/X11R4 \
+ \
+ /usr/X386/lib \
+ /usr/x386/lib \
+ /usr/XFree86/lib/X11 \
+ \
+ /usr/lib \
+ /usr/local/lib \
+ /usr/unsupported/lib \
+ /usr/athena/lib \
+ /usr/local/x11r5/lib \
+ /usr/lpp/Xamples/lib \
+ /lib/usr/lib/X11 \
+ \
+ /usr/openwin/lib \
+ /usr/openwin/share/lib \
+ ; \
+do
+ for ac_extension in a so sl; do
+ if test -r $ac_dir/lib${x_direct_test_library}.$ac_extension; then
+ ac_x_libraries=$ac_dir
+ break 2
+ fi
+ done
+done
+fi
+rm -f conftest*
+fi # $ac_x_libraries = NO
+
+if test "$ac_x_includes" = NO || test "$ac_x_libraries" = NO; then
+ # Didn't find X anywhere. Cache the known absence of X.
+ ac_cv_have_x="have_x=no"
+else
+ # Record where we found X for the cache.
+ ac_cv_have_x="have_x=yes \
+ ac_x_includes=$ac_x_includes ac_x_libraries=$ac_x_libraries"
+fi
+fi
+ fi
+ eval "$ac_cv_have_x"
+fi # $with_x != no
+
+if test "$have_x" != yes; then
+ echo "$ac_t""$have_x" 1>&6
+ no_x=yes
+else
+ # If each of the values was on the command line, it overrides each guess.
+ test "x$x_includes" = xNONE && x_includes=$ac_x_includes
+ test "x$x_libraries" = xNONE && x_libraries=$ac_x_libraries
+ # Update the cache value to reflect the command line values.
+ ac_cv_have_x="have_x=yes \
+ ac_x_includes=$x_includes ac_x_libraries=$x_libraries"
+ echo "$ac_t""libraries $x_libraries, headers $x_includes" 1>&6
+fi
+
+echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
+echo "configure:2446: checking for ANSI C header files" >&5
+if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2451 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2459: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ ac_cv_header_stdc=yes
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 2476 "configure"
+#include "confdefs.h"
+#include <string.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "memchr" >/dev/null 2>&1; then
+ :
+else
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 2494 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "free" >/dev/null 2>&1; then
+ :
+else
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+if test "$cross_compiling" = yes; then
+ :
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2515 "configure"
+#include "confdefs.h"
+#include <ctype.h>
+#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int main () { int i; for (i = 0; i < 256; i++)
+if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
+exit (0); }
+
+EOF
+if { (eval echo configure:2526: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ :
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_header_stdc=no
+fi
+rm -fr conftest*
+fi
+
+fi
+fi
+
+echo "$ac_t""$ac_cv_header_stdc" 1>&6
+if test $ac_cv_header_stdc = yes; then
+ cat >> confdefs.h <<\EOF
+#define STDC_HEADERS 1
+EOF
+
+fi
+
+echo $ac_n "checking for sys/wait.h that is POSIX.1 compatible""... $ac_c" 1>&6
+echo "configure:2550: checking for sys/wait.h that is POSIX.1 compatible" >&5
+if eval "test \"`echo '$''{'ac_cv_header_sys_wait_h'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2555 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/wait.h>
+#ifndef WEXITSTATUS
+#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
+#endif
+#ifndef WIFEXITED
+#define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
+#endif
+int main() {
+int s;
+wait (&s);
+s = WIFEXITED (s) ? WEXITSTATUS (s) : 1;
+; return 0; }
+EOF
+if { (eval echo configure:2571: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_header_sys_wait_h=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_header_sys_wait_h=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_header_sys_wait_h" 1>&6
+if test $ac_cv_header_sys_wait_h = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_SYS_WAIT_H 1
+EOF
+
+fi
+
+for ac_hdr in fcntl.h limits.h paths.h strings.h sys/file.h sys/ioctl.h sys/time.h syslog.h unistd.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:2595: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2600 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2605: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+
+cat > conftest.$ac_ext <<EOF
+#line 2633 "configure"
+#include "confdefs.h"
+#include <netax25/ax25.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "ax25_fwd_struct" >/dev/null 2>&1; then
+ rm -rf conftest*
+ cat >> confdefs.h <<\EOF
+#define HAVE_AX25_FWD_STRUCT 1
+EOF
+
+fi
+rm -f conftest*
+
+cat > conftest.$ac_ext <<EOF
+#line 2648 "configure"
+#include "confdefs.h"
+#include <netax25/ax25.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "AX25_IAMDIGI" >/dev/null 2>&1; then
+ rm -rf conftest*
+ cat >> confdefs.h <<\EOF
+#define HAVE_AX25_IAMDIGI 1
+EOF
+
+fi
+rm -f conftest*
+
+cat > conftest.$ac_ext <<EOF
+#line 2663 "configure"
+#include "confdefs.h"
+#include <netax25/ax25.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "AX25_PIDINCL" >/dev/null 2>&1; then
+ rm -rf conftest*
+ cat >> confdefs.h <<\EOF
+#define HAVE_AX25_PIDINCL 1
+EOF
+
+fi
+rm -f conftest*
+
+
+
+
+echo $ac_n "checking for working const""... $ac_c" 1>&6
+echo "configure:2681: checking for working const" >&5
+if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2686 "configure"
+#include "confdefs.h"
+
+int main() {
+
+/* Ultrix mips cc rejects this. */
+typedef int charset[2]; const charset x;
+/* SunOS 4.1.1 cc rejects this. */
+char const *const *ccp;
+char **p;
+/* NEC SVR4.0.2 mips cc rejects this. */
+struct point {int x, y;};
+static struct point const zero = {0,0};
+/* AIX XL C 1.02.0.0 rejects this.
+ It does not let you subtract one const X* pointer from another in an arm
+ of an if-expression whose if-part is not a constant expression */
+const char *g = "string";
+ccp = &g + (g ? g-g : 0);
+/* HPUX 7.0 cc rejects these. */
+++ccp;
+p = (char**) ccp;
+ccp = (char const *const *) p;
+{ /* SCO 3.2v4 cc rejects this. */
+ char *t;
+ char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+ *t++ = 0;
+}
+{ /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */
+ int x[] = {25, 17};
+ const int *foo = &x[0];
+ ++foo;
+}
+{ /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+ typedef const int *iptr;
+ iptr p = 0;
+ ++p;
+}
+{ /* AIX XL C 1.02.0.0 rejects this saying
+ "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+ struct s { int j; const int *ap[3]; };
+ struct s *b; b->j = 5;
+}
+{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+ const int foo = 10;
+}
+
+; return 0; }
+EOF
+if { (eval echo configure:2735: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_c_const=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_c_const=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_c_const" 1>&6
+if test $ac_cv_c_const = no; then
+ cat >> confdefs.h <<\EOF
+#define const
+EOF
+
+fi
+
+echo $ac_n "checking for uid_t in sys/types.h""... $ac_c" 1>&6
+echo "configure:2756: checking for uid_t in sys/types.h" >&5
+if eval "test \"`echo '$''{'ac_cv_type_uid_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2761 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "uid_t" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_type_uid_t=yes
+else
+ rm -rf conftest*
+ ac_cv_type_uid_t=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_type_uid_t" 1>&6
+if test $ac_cv_type_uid_t = no; then
+ cat >> confdefs.h <<\EOF
+#define uid_t int
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define gid_t int
+EOF
+
+fi
+
+echo $ac_n "checking for pid_t""... $ac_c" 1>&6
+echo "configure:2790: checking for pid_t" >&5
+if eval "test \"`echo '$''{'ac_cv_type_pid_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2795 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "(^|[^a-zA-Z_0-9])pid_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_type_pid_t=yes
+else
+ rm -rf conftest*
+ ac_cv_type_pid_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_pid_t" 1>&6
+if test $ac_cv_type_pid_t = no; then
+ cat >> confdefs.h <<\EOF
+#define pid_t int
+EOF
+
+fi
+
+echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6
+echo "configure:2823: checking whether time.h and sys/time.h may both be included" >&5
+if eval "test \"`echo '$''{'ac_cv_header_time'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2828 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/time.h>
+#include <time.h>
+int main() {
+struct tm *tp;
+; return 0; }
+EOF
+if { (eval echo configure:2837: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_header_time=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_header_time=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_header_time" 1>&6
+if test $ac_cv_header_time = yes; then
+ cat >> confdefs.h <<\EOF
+#define TIME_WITH_SYS_TIME 1
+EOF
+
+fi
+
+echo $ac_n "checking whether struct tm is in sys/time.h or time.h""... $ac_c" 1>&6
+echo "configure:2858: checking whether struct tm is in sys/time.h or time.h" >&5
+if eval "test \"`echo '$''{'ac_cv_struct_tm'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2863 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <time.h>
+int main() {
+struct tm *tp; tp->tm_sec;
+; return 0; }
+EOF
+if { (eval echo configure:2871: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_struct_tm=time.h
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_struct_tm=sys/time.h
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_struct_tm" 1>&6
+if test $ac_cv_struct_tm = sys/time.h; then
+ cat >> confdefs.h <<\EOF
+#define TM_IN_SYS_TIME 1
+EOF
+
+fi
+
+
+if test $ac_cv_prog_gcc = yes; then
+ echo $ac_n "checking whether ${CC-cc} needs -traditional""... $ac_c" 1>&6
+echo "configure:2894: checking whether ${CC-cc} needs -traditional" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gcc_traditional'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_pattern="Autoconf.*'x'"
+ cat > conftest.$ac_ext <<EOF
+#line 2900 "configure"
+#include "confdefs.h"
+#include <sgtty.h>
+Autoconf TIOCGETP
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "$ac_pattern" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_prog_gcc_traditional=yes
+else
+ rm -rf conftest*
+ ac_cv_prog_gcc_traditional=no
+fi
+rm -f conftest*
+
+
+ if test $ac_cv_prog_gcc_traditional = no; then
+ cat > conftest.$ac_ext <<EOF
+#line 2918 "configure"
+#include "confdefs.h"
+#include <termio.h>
+Autoconf TCGETA
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "$ac_pattern" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_prog_gcc_traditional=yes
+fi
+rm -f conftest*
+
+ fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc_traditional" 1>&6
+ if test $ac_cv_prog_gcc_traditional = yes; then
+ CC="$CC -traditional"
+ fi
+fi
+
+echo $ac_n "checking for 8-bit clean memcmp""... $ac_c" 1>&6
+echo "configure:2940: checking for 8-bit clean memcmp" >&5
+if eval "test \"`echo '$''{'ac_cv_func_memcmp_clean'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_func_memcmp_clean=no
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2948 "configure"
+#include "confdefs.h"
+
+main()
+{
+ char c0 = 0x40, c1 = 0x80, c2 = 0x81;
+ exit(memcmp(&c0, &c2, 1) < 0 && memcmp(&c1, &c2, 1) < 0 ? 0 : 1);
+}
+
+EOF
+if { (eval echo configure:2958: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_func_memcmp_clean=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_func_memcmp_clean=no
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo "$ac_t""$ac_cv_func_memcmp_clean" 1>&6
+test $ac_cv_func_memcmp_clean = no && LIBOBJS="$LIBOBJS memcmp.${ac_objext}"
+
+echo $ac_n "checking whether setpgrp takes no argument""... $ac_c" 1>&6
+echo "configure:2976: checking whether setpgrp takes no argument" >&5
+if eval "test \"`echo '$''{'ac_cv_func_setpgrp_void'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ { echo "configure: error: cannot check setpgrp if cross compiling" 1>&2; exit 1; }
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2984 "configure"
+#include "confdefs.h"
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+/*
+ * If this system has a BSD-style setpgrp, which takes arguments, exit
+ * successfully.
+ */
+main()
+{
+ if (setpgrp(1,1) == -1)
+ exit(0);
+ else
+ exit(1);
+}
+
+EOF
+if { (eval echo configure:3004: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_func_setpgrp_void=no
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_func_setpgrp_void=yes
+fi
+rm -fr conftest*
+fi
+
+
+fi
+
+echo "$ac_t""$ac_cv_func_setpgrp_void" 1>&6
+if test $ac_cv_func_setpgrp_void = yes; then
+ cat >> confdefs.h <<\EOF
+#define SETPGRP_VOID 1
+EOF
+
+fi
+
+echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6
+echo "configure:3028: checking return type of signal handlers" >&5
+if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3033 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <signal.h>
+#ifdef signal
+#undef signal
+#endif
+#ifdef __cplusplus
+extern "C" void (*signal (int, void (*)(int)))(int);
+#else
+void (*signal ()) ();
+#endif
+
+int main() {
+int i;
+; return 0; }
+EOF
+if { (eval echo configure:3050: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_type_signal=void
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_type_signal=int
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_type_signal" 1>&6
+cat >> confdefs.h <<EOF
+#define RETSIGTYPE $ac_cv_type_signal
+EOF
+
+
+echo $ac_n "checking for strftime""... $ac_c" 1>&6
+echo "configure:3069: checking for strftime" >&5
+if eval "test \"`echo '$''{'ac_cv_func_strftime'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3074 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char strftime(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char strftime();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_strftime) || defined (__stub___strftime)
+choke me
+#else
+strftime();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:3097: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_strftime=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_strftime=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'strftime`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<\EOF
+#define HAVE_STRFTIME 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+# strftime is in -lintl on SCO UNIX.
+echo $ac_n "checking for strftime in -lintl""... $ac_c" 1>&6
+echo "configure:3119: checking for strftime in -lintl" >&5
+ac_lib_var=`echo intl'_'strftime | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lintl $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 3127 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char strftime();
+
+int main() {
+strftime()
+; return 0; }
+EOF
+if { (eval echo configure:3138: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<\EOF
+#define HAVE_STRFTIME 1
+EOF
+
+LIBS="-lintl $LIBS"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+fi
+
+echo $ac_n "checking for wait3 that fills in rusage""... $ac_c" 1>&6
+echo "configure:3165: checking for wait3 that fills in rusage" >&5
+if eval "test \"`echo '$''{'ac_cv_func_wait3_rusage'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_func_wait3_rusage=no
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3173 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <stdio.h>
+/* HP-UX has wait3 but does not fill in rusage at all. */
+main() {
+ struct rusage r;
+ int i;
+ /* Use a field that we can force nonzero --
+ voluntary context switches.
+ For systems like NeXT and OSF/1 that don't set it,
+ also use the system CPU time. And page faults (I/O) for Linux. */
+ r.ru_nvcsw = 0;
+ r.ru_stime.tv_sec = 0;
+ r.ru_stime.tv_usec = 0;
+ r.ru_majflt = r.ru_minflt = 0;
+ switch (fork()) {
+ case 0: /* Child. */
+ sleep(1); /* Give up the CPU. */
+ _exit(0);
+ case -1: _exit(0); /* What can we do? */
+ default: /* Parent. */
+ wait3(&i, 0, &r);
+ sleep(2); /* Avoid "text file busy" from rm on fast HP-UX machines. */
+ exit(r.ru_nvcsw == 0 && r.ru_majflt == 0 && r.ru_minflt == 0
+ && r.ru_stime.tv_sec == 0 && r.ru_stime.tv_usec == 0);
+ }
+}
+EOF
+if { (eval echo configure:3204: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_func_wait3_rusage=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_func_wait3_rusage=no
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo "$ac_t""$ac_cv_func_wait3_rusage" 1>&6
+if test $ac_cv_func_wait3_rusage = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_WAIT3 1
+EOF
+
+fi
+
+for ac_func in gethostname gettimeofday mkdir select socket strdup strerror strspn strstr strtol strtoul uname
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:3229: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3234 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:3257: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+ case `(ac_space=' '; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote substitution
+ # turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ -e "s/'/'\\\\''/g" \
+ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+ ;;
+ esac >> confcache
+if cmp -s $cache_file confcache; then
+ :
+else
+ if test -w $cache_file; then
+ echo "updating cache $cache_file"
+ cat confcache > $cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+DEFS=-DHAVE_CONFIG_H
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+ case "\$ac_option" in
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+ exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+ -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+ echo "$CONFIG_STATUS generated by autoconf version 2.13"
+ exit 0 ;;
+ -help | --help | --hel | --he | --h)
+ echo "\$ac_cs_usage"; exit 0 ;;
+ *) echo "\$ac_cs_usage"; exit 1 ;;
+ esac
+done
+
+ac_given_srcdir=$srcdir
+ac_given_INSTALL="$INSTALL"
+
+trap 'rm -fr `echo "netrom/Makefile tcpip/Makefile ax25/Makefile Makefile rose/Makefile user_call/Makefile kiss/Makefile hdlcutil/Makefile config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@SHELL@%$SHELL%g
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@FFLAGS@%$FFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
+s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g
+s%@INSTALL_DATA@%$INSTALL_DATA%g
+s%@PACKAGE@%$PACKAGE%g
+s%@VERSION@%$VERSION%g
+s%@ACLOCAL@%$ACLOCAL%g
+s%@AUTOCONF@%$AUTOCONF%g
+s%@AUTOMAKE@%$AUTOMAKE%g
+s%@AUTOHEADER@%$AUTOHEADER%g
+s%@MAKEINFO@%$MAKEINFO%g
+s%@SET_MAKE@%$SET_MAKE%g
+s%@AWK@%$AWK%g
+s%@CC@%$CC%g
+s%@NCURSES_LIB@%$NCURSES_LIB%g
+s%@CPP@%$CPP%g
+s%@X_CFLAGS@%$X_CFLAGS%g
+s%@X_PRE_LIBS@%$X_PRE_LIBS%g
+s%@X_LIBS@%$X_LIBS%g
+s%@X_EXTRA_LIBS@%$X_EXTRA_LIBS%g
+s%@LIBOBJS@%$LIBOBJS%g
+
+CEOF
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+ else
+ sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+ fi
+ if test ! -s conftest.s$ac_file; then
+ ac_more_lines=false
+ rm -f conftest.s$ac_file
+ else
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f conftest.s$ac_file"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+ fi
+ ac_file=`expr $ac_file + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_cmds`
+ fi
+done
+if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+fi
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"netrom/Makefile tcpip/Makefile ax25/Makefile Makefile rose/Makefile user_call/Makefile kiss/Makefile hdlcutil/Makefile"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dir_suffix= ac_dots=
+ fi
+
+ case "$ac_given_srcdir" in
+ .) srcdir=.
+ if test -z "$ac_dots"; then top_srcdir=.
+ else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+ /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+ *) # Relative path.
+ srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+ top_srcdir="$ac_dots$ac_given_srcdir" ;;
+ esac
+
+ case "$ac_given_INSTALL" in
+ [/$]*) INSTALL="$ac_given_INSTALL" ;;
+ *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
+ esac
+
+ echo creating "$ac_file"
+ rm -f "$ac_file"
+ configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+ case "$ac_file" in
+ *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+ *) ac_comsub= ;;
+ esac
+
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+s%@INSTALL@%$INSTALL%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
+# NAME is the cpp macro being defined and VALUE is the value it is being given.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)'
+ac_dB='\([ ][ ]*\)[^ ]*%\1#\2'
+ac_dC='\3'
+ac_dD='%g'
+# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE".
+ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
+ac_uB='\([ ]\)%\1#\2define\3'
+ac_uC=' '
+ac_uD='\4%g'
+# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
+ac_eB='$%\1#\2define\3'
+ac_eC=' '
+ac_eD='%g'
+
+if test "${CONFIG_HEADERS+set}" != set; then
+EOF
+cat >> $CONFIG_STATUS <<EOF
+ CONFIG_HEADERS="config.h"
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+fi
+for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ echo creating $ac_file
+
+ rm -f conftest.frag conftest.in conftest.out
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ cat $ac_file_inputs > conftest.in
+
+EOF
+
+# Transform confdefs.h into a sed script conftest.vals that substitutes
+# the proper values into config.h.in to produce config.h. And first:
+# Protect against being on the right side of a sed subst in config.status.
+# Protect against being in an unquoted here document in config.status.
+rm -f conftest.vals
+cat > conftest.hdr <<\EOF
+s/[\\&%]/\\&/g
+s%[\\$`]%\\&%g
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp
+s%ac_d%ac_u%gp
+s%ac_u%ac_e%gp
+EOF
+sed -n -f conftest.hdr confdefs.h > conftest.vals
+rm -f conftest.hdr
+
+# This sed command replaces #undef with comments. This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+cat >> conftest.vals <<\EOF
+s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */%
+EOF
+
+# Break up conftest.vals because some shells have a limit on
+# the size of here documents, and old seds have small limits too.
+
+rm -f conftest.tail
+while :
+do
+ ac_lines=`grep -c . conftest.vals`
+ # grep -c gives empty output for an empty file on some AIX systems.
+ if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi
+ # Write a limited-size here document to conftest.frag.
+ echo ' cat > conftest.frag <<CEOF' >> $CONFIG_STATUS
+ sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS
+ echo 'CEOF
+ sed -f conftest.frag conftest.in > conftest.out
+ rm -f conftest.in
+ mv conftest.out conftest.in
+' >> $CONFIG_STATUS
+ sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail
+ rm -f conftest.vals
+ mv conftest.tail conftest.vals
+done
+rm -f conftest.vals
+
+cat >> $CONFIG_STATUS <<\EOF
+ rm -f conftest.frag conftest.h
+ echo "/* $ac_file. Generated automatically by configure. */" > conftest.h
+ cat conftest.in >> conftest.h
+ rm -f conftest.in
+ if cmp -s $ac_file conftest.h 2>/dev/null; then
+ echo "$ac_file is unchanged"
+ rm -f conftest.h
+ else
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ fi
+ rm -f $ac_file
+ mv conftest.h $ac_file
+ fi
+fi; done
+
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+test -z "$CONFIG_HEADERS" || echo timestamp > stamp-h
+
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
diff --git a/configure.in b/configure.in
new file mode 100644
index 0000000..4efad35
--- /dev/null
+++ b/configure.in
@@ -0,0 +1,58 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_INIT(ax25/ax25d.c)
+
+dnl For automake
+VERSION=0.0.1
+PACKAGE=ax25-tools
+AM_INIT_AUTOMAKE($PACKAGE,$VERSION)
+
+AM_CONFIG_HEADER(config.h)
+
+
+
+dnl Checks for programs.
+AC_PROG_AWK
+AC_PROG_CC
+AC_PROG_INSTALL
+
+dnl Checks for libraries.
+AC_CHECK_LIB(z, zlibVersion)
+dnl AC_SUBST(AX25_LIB)
+dnl AC_CHECK_LIB(ax25, ax25_config_load_ports, AX25_LIB="-lax25", AX25_LIB=,-lz)
+AC_CHECK_LIB(ax25, ax25_config_load_ports,,,-lz)
+AC_SUBST(NCURSES_LIB)
+AC_CHECK_LIB(ncurses, initscr,NCURSES_LIB="-lncurses",NCURSES_LIB=)
+
+AC_CHECK_LIB(util, openpty)
+AC_PATH_XTRA
+
+dnl Checks for header files.
+AC_PATH_X
+AC_HEADER_STDC
+AC_HEADER_SYS_WAIT
+AC_CHECK_HEADERS(fcntl.h limits.h paths.h strings.h sys/file.h sys/ioctl.h sys/time.h syslog.h unistd.h)
+
+dnl Check for ceratin functions in header files
+AC_HEADER_EGREP(ax25_fwd_struct, netax25/ax25.h, AC_DEFINE(HAVE_AX25_FWD_STRUCT))
+AC_HEADER_EGREP(AX25_IAMDIGI, netax25/ax25.h, AC_DEFINE(HAVE_AX25_IAMDIGI))
+AC_HEADER_EGREP(AX25_PIDINCL, netax25/ax25.h, AC_DEFINE(HAVE_AX25_PIDINCL))
+
+
+
+dnl Checks for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+AC_TYPE_UID_T
+AC_TYPE_PID_T
+AC_HEADER_TIME
+AC_STRUCT_TM
+
+dnl Checks for library functions.
+AC_PROG_GCC_TRADITIONAL
+AC_FUNC_MEMCMP
+AC_FUNC_SETPGRP
+AC_TYPE_SIGNAL
+AC_FUNC_STRFTIME
+AC_FUNC_WAIT3
+AC_CHECK_FUNCS(gethostname gettimeofday mkdir select socket strdup strerror strspn strstr strtol strtoul uname)
+
+AC_OUTPUT(netrom/Makefile tcpip/Makefile ax25/Makefile Makefile rose/Makefile user_call/Makefile kiss/Makefile hdlcutil/Makefile)
diff --git a/hdlcutil/Makefile.am b/hdlcutil/Makefile.am
new file mode 100644
index 0000000..32059d1
--- /dev/null
+++ b/hdlcutil/Makefile.am
@@ -0,0 +1,31 @@
+
+installconf:
+
+sbin_PROGRAMS = setcrystal sethdlc smmixer smdiag
+
+man_MANS = sethdlc.8 smdiag.8 smmixer.8 baycom.9 hdlcdrv.9 soundmodem.9
+
+setcrystal_SOURCES = \
+ setcrystal.c
+
+sethdlc_SOURCES = \
+ sethdlc.c \
+ hdrvcomm.c \
+ hdrvcomm.h \
+ usersmdiag.h
+
+smmixer_SOURCES = \
+ smmixer.c \
+ hdrvcomm.c \
+ hdrvcomm.h \
+ usersmdiag.h
+
+smdiag_SOURCES = \
+ smdiag.c \
+ hdrvcomm.c \
+ hdrvcomm.h \
+ usersmdiag.h
+
+smdiag_LDADD = \
+ $(X_LIBS) \
+ -lX11
diff --git a/hdlcutil/Makefile.in b/hdlcutil/Makefile.in
new file mode 100644
index 0000000..edf7170
--- /dev/null
+++ b/hdlcutil/Makefile.in
@@ -0,0 +1,403 @@
+# 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@
+
+sbin_PROGRAMS = setcrystal sethdlc smmixer smdiag
+
+man_MANS = sethdlc.8 smdiag.8 smmixer.8 baycom.9 hdlcdrv.9 soundmodem.9
+
+setcrystal_SOURCES = setcrystal.c
+
+
+sethdlc_SOURCES = sethdlc.c hdrvcomm.c hdrvcomm.h usersmdiag.h
+
+
+smmixer_SOURCES = smmixer.c hdrvcomm.c hdrvcomm.h usersmdiag.h
+
+
+smdiag_SOURCES = smdiag.c hdrvcomm.c hdrvcomm.h usersmdiag.h
+
+
+smdiag_LDADD = $(X_LIBS) -lX11
+
+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@
+setcrystal_OBJECTS = setcrystal.o
+setcrystal_LDADD = $(LDADD)
+setcrystal_DEPENDENCIES =
+setcrystal_LDFLAGS =
+sethdlc_OBJECTS = sethdlc.o hdrvcomm.o
+sethdlc_LDADD = $(LDADD)
+sethdlc_DEPENDENCIES =
+sethdlc_LDFLAGS =
+smmixer_OBJECTS = smmixer.o hdrvcomm.o
+smmixer_LDADD = $(LDADD)
+smmixer_DEPENDENCIES =
+smmixer_LDFLAGS =
+smdiag_OBJECTS = smdiag.o hdrvcomm.o
+smdiag_DEPENDENCIES =
+smdiag_LDFLAGS =
+CFLAGS = @CFLAGS@
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+man8dir = $(mandir)/man8
+man9dir = $(mandir)/man9
+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 = $(setcrystal_SOURCES) $(sethdlc_SOURCES) $(smmixer_SOURCES) $(smdiag_SOURCES)
+OBJECTS = $(setcrystal_OBJECTS) $(sethdlc_OBJECTS) $(smmixer_OBJECTS) $(smdiag_OBJECTS)
+
+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 hdlcutil/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:
+
+setcrystal: $(setcrystal_OBJECTS) $(setcrystal_DEPENDENCIES)
+ @rm -f setcrystal
+ $(LINK) $(setcrystal_LDFLAGS) $(setcrystal_OBJECTS) $(setcrystal_LDADD) $(LIBS)
+
+sethdlc: $(sethdlc_OBJECTS) $(sethdlc_DEPENDENCIES)
+ @rm -f sethdlc
+ $(LINK) $(sethdlc_LDFLAGS) $(sethdlc_OBJECTS) $(sethdlc_LDADD) $(LIBS)
+
+smmixer: $(smmixer_OBJECTS) $(smmixer_DEPENDENCIES)
+ @rm -f smmixer
+ $(LINK) $(smmixer_LDFLAGS) $(smmixer_OBJECTS) $(smmixer_LDADD) $(LIBS)
+
+smdiag: $(smdiag_OBJECTS) $(smdiag_DEPENDENCIES)
+ @rm -f smdiag
+ $(LINK) $(smdiag_LDFLAGS) $(smdiag_OBJECTS) $(smdiag_LDADD) $(LIBS)
+
+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-man9:
+ $(mkinstalldirs) $(DESTDIR)$(man9dir)
+ @list='$(man9_MANS)'; \
+ l2='$(man_MANS)'; for i in $$l2; do \
+ case "$$i" in \
+ *.9*) 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)$(man9dir)/$$inst"; \
+ $(INSTALL_DATA) $$file $(DESTDIR)$(man9dir)/$$inst; \
+ done
+
+uninstall-man9:
+ @list='$(man9_MANS)'; \
+ l2='$(man_MANS)'; for i in $$l2; do \
+ case "$$i" in \
+ *.9*) 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)$(man9dir)/$$inst"; \
+ rm -f $(DESTDIR)$(man9dir)/$$inst; \
+ done
+install-man: $(MANS)
+ @$(NORMAL_INSTALL)
+ $(MAKE) $(AM_MAKEFLAGS) install-man8 install-man9
+uninstall-man:
+ @$(NORMAL_UNINSTALL)
+ $(MAKE) $(AM_MAKEFLAGS) uninstall-man8 uninstall-man9
+
+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 = hdlcutil
+
+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
+hdrvcomm.o: hdrvcomm.c hdrvcomm.h usersmdiag.h
+setcrystal.o: setcrystal.c
+sethdlc.o: sethdlc.c hdrvcomm.h
+smdiag.o: smdiag.c hdrvcomm.h
+smmixer.o: smmixer.c hdrvcomm.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-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-man
+uninstall: uninstall-am
+all-am: Makefile $(PROGRAMS) $(MANS)
+all-redirect: all-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+installdirs:
+ $(mkinstalldirs) $(DESTDIR)$(sbindir) $(DESTDIR)$(mandir)/man8 \
+ $(DESTDIR)$(mandir)/man9
+
+
+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 install-man8 uninstall-man8 \
+install-man9 uninstall-man9 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:
+
+# 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/hdlcutil/hdrvcomm.c b/hdlcutil/hdrvcomm.c
new file mode 100644
index 0000000..55f0f38
--- /dev/null
+++ b/hdlcutil/hdrvcomm.c
@@ -0,0 +1,663 @@
+/*****************************************************************************/
+
+/*
+ * hdrvcomm.c -- HDLC driver communications.
+ *
+ * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch)
+ *
+ * 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.
+ *
+ * Please note that the GPL allows you to use the driver, NOT the radio.
+ * In order to use the radio, you need a license from the communications
+ * authority of your country.
+ *
+ *
+ * History:
+ * 0.1 10.5.97 Started
+ */
+
+/*****************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ipc.h>
+#include <sys/msg.h>
+#include <asm/byteorder.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+/*#include <linux/if.h>*/
+#include <net/if.h>
+#include "hdrvcomm.h"
+#include "usersmdiag.h"
+
+#include <linux/hdlcdrv.h>
+/* ---------------------------------------------------------------------- */
+
+#ifdef HDRVC_KERNEL
+static int kernel_mode = 1;
+#endif /* HDRVC_KERNEL */
+static char *if_name = "bc0";
+static char *prg_name;
+static int fd = -1;
+static struct ifreq ifr_h;
+static int promisc = 0;
+static int msqid = -1;
+
+/* ---------------------------------------------------------------------- */
+
+static void terminate(void)
+{
+#ifdef HDRVC_KERNEL
+ if (kernel_mode) {
+ if (ioctl(fd, SIOCSIFFLAGS, &ifr_h) < 0) {
+ perror("ioctl (SIOCSIFFLAGS)");
+ exit(1);
+ }
+ }
+#endif /* HDRVC_KERNEL */
+ exit(0);
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void terminate_sig(int signal)
+{
+ printf("signal %i caught\n", signal);
+ terminate();
+}
+
+/* ---------------------------------------------------------------------- */
+
+int hdrvc_recvpacket(char *pkt, int maxlen)
+{
+ struct ifreq ifr_new;
+ struct sockaddr from;
+ int from_len = sizeof(from);
+
+#ifdef HDRVC_KERNEL
+ if (kernel_mode) {
+ if (!promisc) {
+ struct sockaddr sa;
+
+ strcpy(sa.sa_data, if_name);
+ sa.sa_family = AF_INET;
+ if (bind(fd, &sa, sizeof(struct sockaddr)) < 0) {
+ fprintf(stderr, "%s: Error %s (%i) bind failed\n",
+ prg_name, strerror(errno), errno);
+ exit(-2);
+ }
+ ifr_new = ifr_h;
+ ifr_new.ifr_flags |= IFF_PROMISC;
+ if (ioctl(fd, SIOCSIFFLAGS, &ifr_new) < 0) {
+ perror("ioctl (SIOCSIFFLAGS)");
+ exit(1);
+ }
+ signal(SIGTERM, terminate_sig);
+ signal(SIGQUIT, terminate_sig);
+ if (atexit((void (*)(void))terminate)) {
+ perror("atexit");
+ terminate();
+ }
+ promisc = 1;
+ fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
+ }
+ if (!pkt || maxlen < 2)
+ return 0;
+ return recvfrom(fd, pkt, maxlen, 0, &from, &from_len);
+ }
+#endif /* HDRVC_KERNEL */
+ return -1;
+}
+
+/* ---------------------------------------------------------------------- */
+
+int hdrvc_getfd(void)
+{
+ return fd;
+}
+
+/* ---------------------------------------------------------------------- */
+
+char *hdrvc_ifname(void)
+{
+ return if_name;
+}
+
+/* ---------------------------------------------------------------------- */
+
+void hdrvc_args(int *argc, char *argv[], char *def_if)
+{
+ int ac, i;
+
+ if (def_if)
+ if_name = def_if;
+ if (!argc || !argv || (ac = *argc) < 1)
+ return;
+ prg_name = argv[0];
+ for (i = 1; i < ac-1; i++) {
+#ifdef HDRVC_KERNEL
+ if (!strcmp(argv[i], "-i")) {
+ kernel_mode = 1;
+ if_name = argv[i+1];
+ ac -= 2;
+ if (i < ac)
+ memmove(argv+i, argv+i+2, (ac-i) * sizeof(void *));
+ i--;
+ } else
+#endif /* HDRVC_KERNEL */
+ if (!strcmp(argv[i], "-u")) {
+#ifdef HDRVC_KERNEL
+ kernel_mode = 0;
+#endif /* HDRVC_KERNEL */
+ if_name = argv[i+1];
+ ac -= 2;
+ if (i < ac)
+ memmove(argv+i, argv+i+2, (ac-i) * sizeof(void *));
+ i--;
+ }
+ }
+ *argc = ac;
+}
+
+/* ---------------------------------------------------------------------- */
+
+void hdrvc_init(void)
+{
+#ifdef HDRVC_KERNEL
+ if (kernel_mode) {
+ if ((fd = socket(PF_INET, SOCK_PACKET, htons(ETH_P_AX25))) < 0) {
+ fprintf(stderr, "%s: Error %s (%i), cannot open %s\n", prg_name,
+ strerror(errno), errno, if_name);
+ exit(-1);
+ }
+ strcpy(ifr_h.ifr_name, if_name);
+ if (ioctl(fd, SIOCGIFFLAGS, &ifr_h) < 0) {
+ fprintf(stderr, "%s: Error %s (%i), cannot ioctl %s\n", prg_name,
+ strerror(errno), errno, if_name);
+ exit(-1);
+ }
+ } else
+#endif /* HDRVC_KERNEL */
+ {
+ key_t k = ftok(if_name, USERSM_KEY_PROJ);
+
+ if (k == (key_t)-1) {
+ fprintf(stderr, "%s: Error %s (%i), cannot ftok on %s\n", prg_name,
+ strerror(errno), errno, if_name);
+ exit(-1);
+ }
+ if ((msqid = msgget(k, 0700)) < 0) {
+ fprintf(stderr, "%s: Error %s (%i), cannot msgget %d\n", prg_name,
+ strerror(errno), errno, k);
+ exit(-1);
+ }
+ }
+}
+
+/* ---------------------------------------------------------------------- */
+
+extern __inline__ void hdrvc_sendmsg(struct usersmmsg *msg, int len)
+{
+ if (msgsnd(msqid, (struct msgbuf *)msg, len+sizeof(msg->hdr)-sizeof(long), 0) < 0) {
+ perror("msgsnd");
+ exit(1);
+ }
+}
+
+extern __inline__ int hdrvc_recvmsg(struct usersmmsg *msg, int maxlen, long type)
+{
+ int len;
+
+ if ((len = msgrcv(msqid, (struct msgbuf *)msg, maxlen-sizeof(long), type, MSG_NOERROR)) < 0) {
+ perror("msgrcv");
+ exit(1);
+ }
+#if 0
+ for (;;) {
+ if ((len = msgrcv(msqid, (struct msgbuf *)msg, maxlen-sizeof(long), type, IPC_NOWAIT|MSG_NOERROR)) >= 0)
+ return len+sizeof(long);
+ if (errno != ENOMSG) {
+ perror("msgrcv");
+ exit(1);
+ }
+ usleep(250000);
+ }
+#endif
+ return len+sizeof(long);
+}
+
+/* ---------------------------------------------------------------------- */
+
+#ifdef HDRVC_KERNEL
+
+int hdrvc_hdlcdrv_ioctl(int cmd, struct hdlcdrv_ioctl *par)
+{
+ struct ifreq ifr = ifr_h;
+
+ if (!kernel_mode) {
+ errno = EINVAL;
+ return -1;
+ }
+ ifr.ifr_data = (caddr_t)par;
+ par->cmd = cmd;
+ return ioctl(fd, SIOCDEVPRIVATE, &ifr);
+}
+
+/* ---------------------------------------------------------------------- */
+
+int hdrvc_sm_ioctl(int cmd, struct sm_ioctl *par)
+{
+ struct ifreq ifr = ifr_h;
+
+ if (!kernel_mode) {
+ errno = EINVAL;
+ return -1;
+ }
+ ifr.ifr_data = (caddr_t)par;
+ par->cmd = cmd;
+ return ioctl(fd, SIOCDEVPRIVATE, &ifr);
+}
+
+/* ---------------------------------------------------------------------- */
+
+int hdrvc_baycom_ioctl(int cmd, struct baycom_ioctl *par)
+{
+ struct ifreq ifr = ifr_h;
+
+ if (!kernel_mode) {
+ errno = EINVAL;
+ return -1;
+ }
+ ifr.ifr_data = (caddr_t)par;
+ par->cmd = cmd;
+ return ioctl(fd, SIOCDEVPRIVATE, &ifr);
+}
+
+/* ---------------------------------------------------------------------- */
+
+unsigned int hdrvc_get_ifflags(void)
+{
+ struct ifreq ifr;
+
+ if (kernel_mode) {
+ memcpy(&ifr, &ifr_h, sizeof(ifr));
+ if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
+ perror("ioctl: SIOCGIFFLAGS");
+ exit(-1);
+ }
+ return ifr.ifr_flags;
+ }
+ return IFF_UP | IFF_RUNNING;
+}
+
+/* ---------------------------------------------------------------------- */
+
+int hdrvc_diag(struct sm_diag_data *diag)
+{
+ struct sm_ioctl smi;
+ int ret;
+ struct usersmmsg msg;
+
+ if (!diag) {
+ errno = EINVAL;
+ return -1;
+ }
+ if (kernel_mode) {
+ memcpy(&smi.data.diag, diag, sizeof(smi.data.diag));
+ ret = hdrvc_sm_ioctl(SMCTL_DIAGNOSE, &smi);
+ memcpy(diag, &smi.data.diag, sizeof(smi.data.diag));
+ return ret;
+ }
+ msg.hdr.type = USERSM_CMD_REQ_DIAG;
+ msg.hdr.channel = 0;
+ msg.data.diag.mode = diag->mode;
+ msg.data.diag.flags = diag->flags;
+ msg.data.diag.samplesperbit = diag->samplesperbit;
+ msg.data.diag.datalen = diag->datalen;
+ hdrvc_sendmsg(&msg, sizeof(msg.data.diag));
+ ret = hdrvc_recvmsg(&msg, sizeof(msg), USERSM_CMD_ACK_DIAG);
+ if (ret < 0)
+ return ret;
+ if (ret < sizeof(msg.data.diag) || ret < sizeof(msg.data.diag)+msg.data.diag.datalen*sizeof(short)) {
+ errno = EIO;
+ return -1;
+ }
+ diag->mode = msg.data.diag.mode;
+ diag->flags = msg.data.diag.flags;
+ diag->samplesperbit = msg.data.diag.samplesperbit;
+ diag->datalen = msg.data.diag.datalen;
+ memcpy(diag->data, msg.data.diag_out.samples, msg.data.diag.datalen*sizeof(short));
+ return 0;
+}
+
+#endif /* HDRVC_KERNEL */
+
+/* ---------------------------------------------------------------------- */
+
+int hdrvc_get_samples(void)
+{
+ int ret;
+ struct hdlcdrv_ioctl bi;
+
+#ifdef HDRVC_KERNEL
+ if (kernel_mode) {
+ ret = hdrvc_hdlcdrv_ioctl(HDLCDRVCTL_GETSAMPLES, &bi);
+ if (ret < 0)
+ return ret;
+ return bi.data.bits & 0xff;
+ }
+#endif /* HDRVC_KERNEL */
+ errno = EAGAIN;
+ return -1;
+}
+
+/* ---------------------------------------------------------------------- */
+
+int hdrvc_get_bits(void)
+{
+ int ret;
+ struct hdlcdrv_ioctl bi;
+
+#ifdef HDRVC_KERNEL
+ if (kernel_mode) {
+ ret = hdrvc_hdlcdrv_ioctl(HDLCDRVCTL_GETBITS, &bi);
+ if (ret < 0)
+ return ret;
+ return bi.data.bits & 0xff;
+ }
+#endif /* HDRVC_KERNEL */
+ errno = EAGAIN;
+ return -1;
+}
+
+/* ---------------------------------------------------------------------- */
+
+int hdrvc_get_channel_access_param(struct hdrvc_channel_params *par)
+{
+ struct hdlcdrv_ioctl hi;
+ int ret;
+ struct usersmmsg msg;
+
+#ifdef HDRVC_KERNEL
+ if (kernel_mode) {
+ if ((ret = hdrvc_hdlcdrv_ioctl(HDLCDRVCTL_GETCHANNELPAR, &hi)) < 0)
+ return ret;
+ if (!par) {
+ errno = EINVAL;
+ return -1;
+ }
+ par->tx_delay = hi.data.cp.tx_delay;
+ par->tx_tail = hi.data.cp.tx_tail;
+ par->slottime = hi.data.cp.slottime;
+ par->ppersist = hi.data.cp.ppersist;
+ par->fulldup = hi.data.cp.fulldup;
+ return 0;
+ }
+#endif /* HDRVC_KERNEL */
+ msg.hdr.type = USERSM_CMD_REQ_CHACCESS_PAR;
+ msg.hdr.channel = 0;
+ hdrvc_sendmsg(&msg, 0);
+ ret = hdrvc_recvmsg(&msg, sizeof(msg), USERSM_CMD_ACK_CHACCESS_PAR);
+ if (ret < 0)
+ return ret;
+ if (ret < sizeof(msg.data.cp)) {
+ errno = EIO;
+ return -1;
+ }
+ par->tx_delay = msg.data.cp.tx_delay;
+ par->tx_tail = msg.data.cp.tx_tail;
+ par->slottime = msg.data.cp.slottime;
+ par->ppersist = msg.data.cp.ppersist;
+ par->fulldup = msg.data.cp.fulldup;
+ return 0;
+}
+
+/* ---------------------------------------------------------------------- */
+
+int hdrvc_set_channel_access_param(struct hdrvc_channel_params par)
+{
+ int ret;
+ struct usersmmsg msg;
+
+#ifdef HDRVC_KERNEL
+ if (kernel_mode) {
+ struct hdlcdrv_ioctl hi;
+
+ hi.data.cp.tx_delay = par.tx_delay;
+ hi.data.cp.tx_tail = par.tx_tail;
+ hi.data.cp.slottime = par.slottime;
+ hi.data.cp.ppersist = par.ppersist;
+ hi.data.cp.fulldup = par.fulldup;
+ if ((ret = hdrvc_hdlcdrv_ioctl(HDLCDRVCTL_SETCHANNELPAR, &hi)) < 0)
+ return ret;
+ return 0;
+ }
+#endif /* HDRVC_KERNEL */
+ msg.hdr.type = USERSM_CMD_SET_CHACCESS_PAR;
+ msg.hdr.channel = 0;
+ msg.data.cp.tx_delay = par.tx_delay;
+ msg.data.cp.tx_tail = par.tx_tail;
+ msg.data.cp.slottime = par.slottime;
+ msg.data.cp.ppersist = par.ppersist;
+ msg.data.cp.fulldup = par.fulldup;
+ hdrvc_sendmsg(&msg, sizeof(msg.data.cp));
+ return 0;
+}
+
+/* ---------------------------------------------------------------------- */
+
+int hdrvc_calibrate(int calib)
+{
+ struct hdlcdrv_ioctl bhi;
+ struct usersmmsg msg;
+
+#ifdef HDRVC_KERNEL
+ if (kernel_mode) {
+ bhi.data.calibrate = calib;
+ return hdrvc_hdlcdrv_ioctl(HDLCDRVCTL_CALIBRATE, &bhi);
+ }
+#endif /* HDRVC_KERNEL */
+ msg.hdr.type = USERSM_CMD_CALIBRATE;
+ msg.hdr.channel = 0;
+ msg.data.calib = calib;
+ hdrvc_sendmsg(&msg, sizeof(msg.data.calib));
+ return 0;
+}
+
+/* ---------------------------------------------------------------------- */
+
+int hdrvc_get_channel_state(struct hdrvc_channel_state *st)
+{
+ struct hdlcdrv_ioctl bhi;
+ int ret;
+ struct usersmmsg msg;
+
+ if (!st) {
+ errno = EINVAL;
+ return -1;
+ }
+#ifdef HDRVC_KERNEL
+ if (kernel_mode) {
+ ret = hdrvc_hdlcdrv_ioctl(HDLCDRVCTL_GETSTAT, &bhi);
+ if (ret >= 0) {
+ st->ptt = bhi.data.cs.ptt;
+ st->dcd = bhi.data.cs.dcd;
+ st->ptt_keyed = bhi.data.cs.ptt_keyed;
+ st->tx_packets = bhi.data.cs.tx_packets;
+ st->tx_errors = bhi.data.cs.tx_errors;
+ st->rx_packets = bhi.data.cs.rx_packets;
+ st->rx_errors = bhi.data.cs.rx_errors;
+ }
+ return ret;
+ }
+#endif /* HDRVC_KERNEL */
+ msg.hdr.type = USERSM_CMD_REQ_CHANNELSTATE;
+ msg.hdr.channel = 0;
+ hdrvc_sendmsg(&msg, 0);
+ ret = hdrvc_recvmsg(&msg, sizeof(msg), USERSM_CMD_ACK_CHANNELSTATE);
+ if (ret < 0)
+ return ret;
+ if (ret < sizeof(msg.data.cs)) {
+ errno = EIO;
+ return -1;
+ }
+ st->ptt = msg.data.cs.ptt;
+ st->dcd = msg.data.cs.dcd;
+ st->ptt_keyed = msg.data.cs.ptt_keyed;
+ st->tx_packets = msg.data.cs.tx_packets;
+ st->tx_errors = msg.data.cs.tx_errors;
+ st->rx_packets = msg.data.cs.rx_packets;
+ st->rx_errors = msg.data.cs.rx_errors;
+ return 0;
+}
+
+/* ---------------------------------------------------------------------- */
+
+int hdrvc_diag2(unsigned int mode, unsigned int flags, short *data,
+ unsigned int maxdatalen, unsigned int *samplesperbit)
+{
+ int ret;
+ struct usersmmsg msg;
+ static unsigned int modeconvusersm[4] = {
+ USERSM_DIAGMODE_OFF, USERSM_DIAGMODE_INPUT, USERSM_DIAGMODE_DEMOD,
+ USERSM_DIAGMODE_CONSTELLATION
+ };
+
+ if (mode > HDRVC_DIAGMODE_CONSTELLATION) {
+ errno = EINVAL;
+ return -1;
+ }
+#ifdef HDRVC_KERNEL
+ if (kernel_mode) {
+ struct sm_ioctl smi;
+ static unsigned int modeconvsm[4] = {
+ SM_DIAGMODE_OFF, SM_DIAGMODE_INPUT, SM_DIAGMODE_DEMOD, SM_DIAGMODE_CONSTELLATION
+ };
+
+ smi.data.diag.mode = modeconvsm[mode];
+ smi.data.diag.flags = (flags & HDRVC_DIAGFLAG_DCDGATE) ? SM_DIAGFLAG_DCDGATE : 0;
+ smi.data.diag.samplesperbit = 0;
+ smi.data.diag.datalen = maxdatalen;
+ smi.data.diag.data = data;
+ if ((ret = hdrvc_sm_ioctl(SMCTL_DIAGNOSE, &smi)) < 0)
+ return ret;
+ if (samplesperbit)
+ *samplesperbit = smi.data.diag.samplesperbit;
+ if (smi.data.diag.mode != modeconvsm[mode] || !(smi.data.diag.flags & SM_DIAGFLAG_VALID))
+ return 0;
+ return smi.data.diag.datalen;
+ }
+#endif /* HDRVC_KERNEL */
+ msg.hdr.type = USERSM_CMD_REQ_DIAG;
+ msg.hdr.channel = 0;
+ msg.data.diag.mode = modeconvusersm[mode];
+ msg.data.diag.flags = (flags & HDRVC_DIAGFLAG_DCDGATE) ? USERSM_DIAGFLAG_DCDGATE : 0;
+ msg.data.diag.samplesperbit = 0;
+ msg.data.diag.datalen = maxdatalen;
+ hdrvc_sendmsg(&msg, sizeof(msg.data.diag));
+ ret = hdrvc_recvmsg(&msg, sizeof(msg), USERSM_CMD_ACK_DIAG);
+ if (ret < 0)
+ return ret;
+ if (ret < sizeof(msg.data.diag) || ret < sizeof(msg.data.diag)+msg.data.diag.datalen*sizeof(short)) {
+ errno = EIO;
+ return -1;
+ }
+ if (samplesperbit)
+ *samplesperbit = msg.data.diag.samplesperbit;
+ if (msg.data.diag.mode != modeconvusersm[mode] || !(msg.data.diag.flags & USERSM_DIAGFLAG_VALID))
+ return 0;
+ if (!data || msg.data.diag.datalen <= 0)
+ return 0;
+ memcpy(data, msg.data.diag_out.samples, msg.data.diag.datalen*sizeof(short));
+ return msg.data.diag.datalen;
+}
+
+/* ---------------------------------------------------------------------- */
+
+int hdrvc_get_driver_name(char *buf, int bufsz)
+{
+ int ret;
+ struct usersmmsg msg;
+
+#ifdef HDRVC_KERNEL
+ if (kernel_mode) {
+ struct hdlcdrv_ioctl bhi;
+
+ ret = hdrvc_hdlcdrv_ioctl(HDLCDRVCTL_DRIVERNAME, &bhi);
+ if (ret < 0)
+ return ret;
+ strncpy(buf, bhi.data.modename, bufsz);
+ return 0;
+ }
+#endif /* HDRVC_KERNEL */
+ msg.hdr.type = USERSM_CMD_REQ_DRVNAME;
+ msg.hdr.channel = 0;
+ hdrvc_sendmsg(&msg, 0);
+ ret = hdrvc_recvmsg(&msg, sizeof(msg), USERSM_CMD_ACK_DRVNAME);
+ if (ret < 0)
+ return ret;
+ if (ret < 1) {
+ errno = EIO;
+ return -1;
+ }
+ if (bufsz < ret)
+ ret = bufsz;
+ strncpy(buf, msg.data.by, ret);
+ buf[ret-1] = 0;
+ return 0;
+}
+
+/* ---------------------------------------------------------------------- */
+
+int hdrvc_get_mode_name(char *buf, int bufsz)
+{
+ int ret;
+ struct usersmmsg msg;
+
+#ifdef HDRVC_KERNEL
+ if (kernel_mode) {
+ struct hdlcdrv_ioctl bhi;
+
+ ret = hdrvc_hdlcdrv_ioctl(HDLCDRVCTL_GETMODE, &bhi);
+ if (ret < 0)
+ return ret;
+ strncpy(buf, bhi.data.modename, bufsz);
+ return 0;
+ }
+#endif /* HDRVC_KERNEL */
+ msg.hdr.type = USERSM_CMD_REQ_DRVMODE;
+ msg.hdr.channel = 0;
+ hdrvc_sendmsg(&msg, 0);
+ ret = hdrvc_recvmsg(&msg, sizeof(msg), USERSM_CMD_ACK_DRVMODE);
+ if (ret < 0)
+ return ret;
+ if (ret < 1) {
+ errno = EIO;
+ return -1;
+ }
+ if (bufsz < ret)
+ ret = bufsz;
+ strncpy(buf, msg.data.by, ret);
+ buf[ret-1] = 0;
+ return 0;
+}
+
+/* ---------------------------------------------------------------------- */
diff --git a/hdlcutil/hdrvcomm.h b/hdlcutil/hdrvcomm.h
new file mode 100644
index 0000000..ec4be73
--- /dev/null
+++ b/hdlcutil/hdrvcomm.h
@@ -0,0 +1,109 @@
+/*****************************************************************************/
+
+/*
+ * hdrvcomm.h -- HDLC driver communications.
+ *
+ * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch)
+ *
+ * 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.
+ *
+ * Please note that the GPL allows you to use the driver, NOT the radio.
+ * In order to use the radio, you need a license from the communications
+ * authority of your country.
+ *
+ */
+
+/*****************************************************************************/
+
+#ifndef _HDRVCOMM_H
+#define _HDRVCOMM_H
+
+/* ---------------------------------------------------------------------- */
+
+#undef HDRVC_KERNEL 1
+
+/* ---------------------------------------------------------------------- */
+
+#ifdef HDRVC_KERNEL
+#include <linux/hdlcdrv.h>
+#include <linux/soundmodem.h>
+#include <linux/baycom.h>
+#endif /* HDRVC_KERNEL */
+
+/* ---------------------------------------------------------------------- */
+
+struct hdrvc_channel_params {
+ int tx_delay; /* the transmitter keyup delay in 10ms units */
+ int tx_tail; /* the transmitter keyoff delay in 10ms units */
+ int slottime; /* the slottime in 10ms; usually 10 = 100ms */
+ int ppersist; /* the p-persistence 0..255 */
+ int fulldup; /* some driver do not support full duplex, setting */
+ /* this just makes them send even if DCD is on */
+};
+
+struct hdrvc_channel_state {
+ int ptt;
+ int dcd;
+ int ptt_keyed;
+ unsigned long tx_packets;
+ unsigned long tx_errors;
+ unsigned long rx_packets;
+ unsigned long rx_errors;
+};
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * diagnose modes
+ */
+#define HDRVC_DIAGMODE_OFF 0
+#define HDRVC_DIAGMODE_INPUT 1
+#define HDRVC_DIAGMODE_DEMOD 2
+#define HDRVC_DIAGMODE_CONSTELLATION 3
+
+/*
+ * diagnose flags
+ */
+#define HDRVC_DIAGFLAG_DCDGATE (1<<0)
+
+
+/* ---------------------------------------------------------------------- */
+
+extern int hdrvc_recvpacket(char *pkt, int maxlen);
+extern int hdrvc_getfd(void);
+extern char *hdrvc_ifname(void);
+extern void hdrvc_args(int *argc, char *argv[], char *def_if);
+extern void hdrvc_init(void);
+extern int hdrvc_get_samples(void);
+extern int hdrvc_get_bits(void);
+extern int hdrvc_get_channel_access_param(struct hdrvc_channel_params *par);
+extern int hdrvc_set_channel_access_param(struct hdrvc_channel_params par);
+extern int hdrvc_calibrate(int calib);
+extern int hdrvc_get_channel_state(struct hdrvc_channel_state *st);
+extern unsigned int hdrvc_get_ifflags(void);
+extern int hdrvc_diag2(unsigned int mode, unsigned int flags, short *data, unsigned int maxdatalen,
+ unsigned int *samplesperbit);
+extern int hdrvc_get_driver_name(char *buf, int bufsz);
+extern int hdrvc_get_mode_name(char *buf, int bufsz);
+
+#ifdef HDRVC_KERNEL
+extern int hdrvc_hdlcdrv_ioctl(int cmd, struct hdlcdrv_ioctl *par);
+extern int hdrvc_sm_ioctl(int cmd, struct sm_ioctl *par);
+extern int hdrvc_baycom_ioctl(int cmd, struct baycom_ioctl *par);
+extern int hdrvc_diag(struct sm_diag_data *diag);
+#endif /* HDRVC_KERNEL */
+
+/* ---------------------------------------------------------------------- */
+#endif /* _HDRVCOMM_H */
diff --git a/hdlcutil/setcrystal.c b/hdlcutil/setcrystal.c
new file mode 100644
index 0000000..f5181f3
--- /dev/null
+++ b/hdlcutil/setcrystal.c
@@ -0,0 +1,136 @@
+/*****************************************************************************/
+
+/*
+ * setcrystal.c -- crystal soundcard configuration utility
+ *
+ * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch)
+ *
+ * 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.
+ *
+ * Please note that the GPL allows you to use the driver, NOT the radio.
+ * In order to use the radio, you need a license from the communications
+ * authority of your country.
+ *
+ */
+
+/* --------------------------------------------------------------------- */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <asm/io.h>
+
+/* --------------------------------------------------------------------- */
+
+static const unsigned char crystal_key[32] = {
+ 0x96, 0x35, 0x9a, 0xcd, 0xe6, 0xf3, 0x79, 0xbc,
+ 0x5e, 0xaf, 0x57, 0x2b, 0x15, 0x8a, 0xc5, 0xe2,
+ 0xf1, 0xf8, 0x7c, 0x3e, 0x9f, 0x4f, 0x27, 0x13,
+ 0x09, 0x84, 0x42, 0xa1, 0xd0, 0x68, 0x34, 0x1a
+};
+
+#define KEY_PORT 0x279
+#define CSN 1 /* card select number */
+
+/* --------------------------------------------------------------------- */
+
+int main(int argc, char *argv[])
+{
+ int wssbase = 0x534;
+ int synbase = 0x388;
+ int sbbase = 0x220;
+ int irq = 5;
+ int dma = 1;
+ int dma2 = 3;
+
+ int i;
+
+ printf("Crystal PnP Soundcard enabler\n"
+ "(C) 1996 by Thomas Sailer, HB9JNX/AE4WA\n"
+ "WARNING: This utility is incompatible with OS PnP support!\n"
+ " Remove it as soon as Linux supports PnP!\n");
+ while ((i = getopt(argc, argv, "i:d:c:s:w:f:h")) != EOF) {
+ switch (i) {
+ case 'i':
+ irq = strtoul(optarg, NULL, 0);
+ break;
+ case 'd':
+ dma = strtoul(optarg, NULL, 0);
+ break;
+ case 'c':
+ dma2 = strtoul(optarg, NULL, 0);
+ break;
+ case 's':
+ sbbase = strtoul(optarg, NULL, 0);
+ break;
+ case 'w':
+ wssbase = strtoul(optarg, NULL, 0);
+ break;
+ case 'f':
+ synbase = strtoul(optarg, NULL, 0);
+ break;
+
+ default:
+ case ':':
+ case '?':
+ case 'h':
+ fprintf(stderr, "usage: [-w wssio] [-s sbio] "
+ "[-f synthio] [-i irq] [-d dma] [-c dma2]\n");
+ exit(1);
+ }
+ }
+
+ if ((i = ioperm(KEY_PORT, 1, 1))) {
+ perror("ioperm");
+ exit(1);
+ }
+ /*
+ * send crystal key
+ */
+ for (i = 0; i < 32; i++)
+ outb(crystal_key[i], KEY_PORT);
+ /*
+ * send config data
+ */
+ outb(0x6, KEY_PORT);
+ outb(CSN, KEY_PORT);
+ outb(0x15, KEY_PORT);
+ outb(0x0, KEY_PORT); /* logical device 0 */
+ outb(0x47, KEY_PORT);
+ outb(wssbase >> 8, KEY_PORT);
+ outb(wssbase & 0xff, KEY_PORT);
+ outb(0x48, KEY_PORT);
+ outb(synbase >> 8, KEY_PORT);
+ outb(synbase & 0xff, KEY_PORT);
+ outb(0x42, KEY_PORT);
+ outb(sbbase >> 8, KEY_PORT);
+ outb(sbbase & 0xff, KEY_PORT);
+ outb(0x22, KEY_PORT);
+ outb(irq, KEY_PORT);
+ outb(0x2a, KEY_PORT);
+ outb(dma, KEY_PORT);
+ outb(0x25, KEY_PORT);
+ outb(dma2, KEY_PORT);
+ outb(0x33, KEY_PORT);
+ outb(0x1, KEY_PORT); /* activate logical device */
+ outb(0x79, KEY_PORT); /* activate part */
+
+ printf("Crystal CS423[26] set to: WSS iobase 0x%x, Synth iobase 0x%x,"
+ " SB iobase 0x%x,\n IRQ %u, DMA %u, DMA2 %u\n", wssbase,
+ synbase, sbbase, irq, dma, dma2);
+ exit(0);
+}
+
+/* --------------------------------------------------------------------- */
diff --git a/hdlcutil/sethdlc.c b/hdlcutil/sethdlc.c
new file mode 100644
index 0000000..b07c0de
--- /dev/null
+++ b/hdlcutil/sethdlc.c
@@ -0,0 +1,598 @@
+/*****************************************************************************/
+
+/*
+ * sethdlc.c -- kernel HDLC radio modem driver setup utility.
+ *
+ * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch)
+ *
+ * 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.
+ *
+ * Please note that the GPL allows you to use the driver, NOT the radio.
+ * In order to use the radio, you need a license from the communications
+ * authority of your country.
+ *
+ *
+ * History:
+ * 0.1 16.10.96 Adapted from setbaycom.c and setsm.c
+ * 0.2 20.11.96 New mode set/query code
+ * 0.5 11.05.97 introduced hdrvcomm.h
+ */
+
+/*****************************************************************************/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+/*#include <linux/if.h>*/
+#include <net/if.h>
+#include "hdrvcomm.h"
+
+#include <linux/soundmodem.h>
+#include <linux/baycom.h>
+
+/* ---------------------------------------------------------------------- */
+
+static unsigned char trace_stat = 0;
+static char *progname;
+
+/* ---------------------------------------------------------------------- */
+
+static void display_packet(unsigned char *bp, unsigned int len)
+{
+ unsigned char v1=1,cmd=0;
+ unsigned char i,j;
+
+ if (!bp || !len)
+ return;
+ if (len < 8)
+ return;
+ if (bp[1] & 1) {
+ /*
+ * FlexNet Header Compression
+ */
+ v1 = 0;
+ cmd = (bp[1] & 2) != 0;
+ printf("fm ? to ");
+ i = (bp[2] >> 2) & 0x3f;
+ if (i)
+ printf("%c",i+0x20);
+ i = ((bp[2] << 4) | ((bp[3] >> 4) & 0xf)) & 0x3f;
+ if (i)
+ printf("%c",i+0x20);
+ i = ((bp[3] << 2) | ((bp[4] >> 6) & 3)) & 0x3f;
+ if (i)
+ printf("%c",i+0x20);
+ i = bp[4] & 0x3f;
+ if (i)
+ printf("%c",i+0x20);
+ i = (bp[5] >> 2) & 0x3f;
+ if (i)
+ printf("%c",i+0x20);
+ i = ((bp[5] << 4) | ((bp[6] >> 4) & 0xf)) & 0x3f;
+ if (i)
+ printf("%c",i+0x20);
+ printf("-%u QSO Nr %u", bp[6] & 0xf, (bp[0] << 6) |
+ (bp[1] >> 2));
+ bp += 7;
+ len -= 7;
+ } else {
+ /*
+ * normal header
+ */
+ if (len < 15)
+ return;
+ if ((bp[6] & 0x80) != (bp[13] & 0x80)) {
+ v1 = 0;
+ cmd = (bp[6] & 0x80);
+ }
+ printf("fm ");
+ for(i = 7; i < 13; i++)
+ if ((bp[i] &0xfe) != 0x40)
+ printf("%c",bp[i] >> 1);
+ printf("-%u to ",(bp[13] >> 1) & 0xf);
+ for(i = 0; i < 6; i++)
+ if ((bp[i] &0xfe) != 0x40)
+ printf("%c", bp[i] >> 1);
+ printf("-%u", (bp[6] >> 1) & 0xf);
+ bp += 14;
+ len -= 14;
+ if ((!(bp[-1] & 1)) && (len >= 7))
+ printf(" via ");
+ while ((!(bp[-1] & 1)) && (len >= 7)) {
+ for(i = 0; i < 6; i++)
+ if ((bp[i] &0xfe) != 0x40)
+ printf("%c",bp[i] >> 1);
+ printf("-%u",(bp[6] >> 1) & 0xf);
+ bp += 7;
+ len -= 7;
+ if ((!(bp[-1] & 1)) && (len >= 7))
+ printf(",");
+ }
+ }
+ if(!len)
+ return;
+ i = *bp++;
+ len--;
+ j = v1 ? ((i & 0x10) ? '!' : ' ') :
+ ((i & 0x10) ? (cmd ? '+' : '-') : (cmd ? '^' : 'v'));
+ if (!(i & 1)) {
+ /*
+ * Info frame
+ */
+ printf(" I%u%u%c",(i >> 5) & 7,(i >> 1) & 7,j);
+ } else if (i & 2) {
+ /*
+ * U frame
+ */
+ switch (i & (~0x10)) {
+ case 0x03:
+ printf(" UI%c",j);
+ break;
+ case 0x2f:
+ printf(" SABM%c",j);
+ break;
+ case 0x43:
+ printf(" DISC%c",j);
+ break;
+ case 0x0f:
+ printf(" DM%c",j);
+ break;
+ case 0x63:
+ printf(" UA%c",j);
+ break;
+ case 0x87:
+ printf(" FRMR%c",j);
+ break;
+ default:
+ printf(" unknown U (0x%x)%c",i & (~0x10),j);
+ break;
+ }
+ } else {
+ /*
+ * supervisory
+ */
+ switch (i & 0xf) {
+ case 0x1:
+ printf(" RR%u%c",(i >> 5) & 7,j);
+ break;
+ case 0x5:
+ printf(" RNR%u%c",(i >> 5) & 7,j);
+ break;
+ case 0x9:
+ printf(" REJ%u%c",(i >> 5) & 7,j);
+ break;
+ default:
+ printf(" unknown S (0x%x)%u%c", i & 0xf,
+ (i >> 5) & 7, j);
+ break;
+ }
+ }
+ if (!len) {
+ printf("\n");
+ return;
+ }
+ printf(" pid=%02X\n", *bp++);
+ len--;
+ j = 0;
+ while (len) {
+ i = *bp++;
+ if ((i >= 32) && (i < 128))
+ printf("%c",i);
+ else if (i == 13) {
+ if (j)
+ printf("\n");
+ j = 0;
+ } else
+ printf(".");
+ if (i >= 32)
+ j = 1;
+ len--;
+ }
+ if (j)
+ printf("\n");
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void print_bits(int (*bitproc)(void))
+{
+ int ret;
+ int i;
+ char str[9];
+ char *cp;
+
+ for(;;) {
+ ret = bitproc();
+ if (ret < 0) {
+ if (errno == EAGAIN)
+ return;
+ fprintf(stderr, "%s: Error %s (%i), cannot ioctl\n",
+ progname, strerror(errno), errno);
+ return;
+ }
+ strcpy(cp = str, "00000000");
+ for(i = 0; i < 8; i++, cp++, ret >>= 1)
+ *cp += (ret & 1);
+ printf("%s", str);
+ }
+}
+
+/* ---------------------------------------------------------------------- */
+
+#ifdef HDRVC_KERNEL
+
+static void do_set_params(int argc, char **argv)
+{
+ struct hdlcdrv_ioctl drvname, curm, newm, mlist, curp, newp, mpmask;
+ char set = 0;
+ int ret;
+ int mask;
+
+ ret = hdrvc_hdlcdrv_ioctl(HDLCDRVCTL_DRIVERNAME, &drvname);
+ if (ret < 0) {
+ perror("ioctl (HDLCDRVCTL_DRIVERNAME)");
+ exit(1);
+ }
+ printf("driver name: %s\n", drvname.data.drivername);
+
+ mask = hdrvc_hdlcdrv_ioctl(HDLCDRVCTL_MODEMPARMASK, &mpmask);
+ if (mask < 0)
+ mask = ~0;
+
+ ret = hdrvc_hdlcdrv_ioctl(HDLCDRVCTL_GETMODEMPAR, &curp);
+ if (ret < 0) {
+ perror("ioctl (HDLCDRVCTL_GETMODEMPAR)");
+ exit(1);
+ }
+ ret = hdrvc_hdlcdrv_ioctl(HDLCDRVCTL_GETMODE, &curm);
+ if (ret < 0) {
+ perror("ioctl (HDLCDRVCTL_GETMODE)");
+ exit(1);
+ }
+ newm = curm;
+ newp = curp;
+ while (argc >= 2) {
+ if (!strcasecmp(argv[0], "mode")) {
+ strncpy(newm.data.modename, argv[1],
+ sizeof(newm.data.modename));
+ set |= 1;
+ } else if (!strcasecmp(argv[0], "io") && mask & HDLCDRV_PARMASK_IOBASE) {
+ newp.data.mp.iobase = strtoul(argv[1], NULL, 0);
+ set |= 2;
+ } else if (!strcasecmp(argv[0], "irq") && mask & HDLCDRV_PARMASK_IRQ) {
+ newp.data.mp.irq = strtoul(argv[1], NULL, 0);
+ set |= 2;
+ } else if (!strcasecmp(argv[0], "dma") && mask & HDLCDRV_PARMASK_DMA) {
+ newp.data.mp.dma = strtoul(argv[1], NULL, 0);
+ set |= 2;
+ } else if (!strcasecmp(argv[0], "dma2") && mask & HDLCDRV_PARMASK_DMA2) {
+ newp.data.mp.dma2 = strtoul(argv[1], NULL, 0);
+ set |= 2;
+ } else if (!strcasecmp(argv[0], "serio") && mask & HDLCDRV_PARMASK_SERIOBASE) {
+ newp.data.mp.seriobase = strtol(argv[1], NULL, 0);
+ set |= 2;
+ } else if (!strcasecmp(argv[0], "pario") && mask & HDLCDRV_PARMASK_PARIOBASE) {
+ newp.data.mp.pariobase = strtol(argv[1], NULL, 0);
+ set |= 2;
+ } else if (!strcasecmp(argv[0], "midiio") && mask & HDLCDRV_PARMASK_MIDIIOBASE) {
+ newp.data.mp.midiiobase = strtol(argv[1], NULL, 0);
+ set |= 2;
+ } else {
+ fprintf(stderr, "%s: invalid parameter type '%s', "
+ "valid: mode%s%s%s%s%s%s%s\n",
+ progname, argv[0],
+ (mask & HDLCDRV_PARMASK_IOBASE) ? " io" : "",
+ (mask & HDLCDRV_PARMASK_IRQ) ? " irq" : "",
+ (mask & HDLCDRV_PARMASK_DMA) ? " dma" : "",
+ (mask & HDLCDRV_PARMASK_DMA2) ? " dma2" : "",
+ (mask & HDLCDRV_PARMASK_SERIOBASE) ? " serio" : "",
+ (mask & HDLCDRV_PARMASK_PARIOBASE) ? " pario" : "",
+ (mask & HDLCDRV_PARMASK_MIDIIOBASE) ? " midiio" : "");
+ }
+ argv += 2;
+ argc -= 2;
+ }
+ if (argc >= 1)
+ fprintf(stderr, "%s: orphaned parameter type '%s', no data\n",
+ progname, argv[0]);
+ printf("current parameters: mode %s", curm.data.modename);
+ if (mask & HDLCDRV_PARMASK_IOBASE)
+ printf(" io 0x%x", curp.data.mp.iobase);
+ if (mask & HDLCDRV_PARMASK_IRQ)
+ printf(" irq %u", curp.data.mp.irq);
+ if (mask & HDLCDRV_PARMASK_DMA)
+ printf(" dma %u", curp.data.mp.dma);
+ if (mask & HDLCDRV_PARMASK_DMA2)
+ printf(" dma2 %u", curp.data.mp.dma2);
+ if (mask & HDLCDRV_PARMASK_SERIOBASE)
+ printf(" serio 0x%x", curp.data.mp.seriobase);
+ if (mask & HDLCDRV_PARMASK_PARIOBASE)
+ printf(" pario 0x%x", curp.data.mp.pariobase);
+ if (mask & HDLCDRV_PARMASK_MIDIIOBASE)
+ printf(" midiio 0x%x", curp.data.mp.midiiobase);
+ printf("\n");
+
+ if (set & 1)
+ ret = hdrvc_hdlcdrv_ioctl(HDLCDRVCTL_SETMODE, &newm);
+ if (ret < 0) {
+ perror("ioctl (HDLCDRVCTL_SETMODE)");
+ ret = hdrvc_hdlcdrv_ioctl(HDLCDRVCTL_MODELIST, &mlist);
+ if (ret < 0) {
+ perror("ioctl (HDLCDRVCTL_MODELIST)");
+ exit(1);
+ }
+ printf("driver supported modes: %s\n",
+ mlist.data.modename);
+ exit(1);
+ }
+ if (set & 2) {
+ ret = hdrvc_hdlcdrv_ioctl(HDLCDRVCTL_SETMODEMPAR, &newp);
+ if (ret < 0) {
+ perror("ioctl (HDLCDRVCTL_SETMODEMPAR)");
+ fprintf(stderr, "%s: trying to restore old "
+ "parameters\n", progname);
+ ret = hdrvc_hdlcdrv_ioctl(HDLCDRVCTL_SETMODEMPAR, &curp);
+ if (ret < 0)
+ perror("ioctl (HDLCDRVCTL_SETMODEMPAR)");
+ exit(1);
+ }
+ }
+ if (set & 3) {
+ printf("new parameters: mode %s", newm.data.modename);
+ if (mask & HDLCDRV_PARMASK_IOBASE)
+ printf(" io 0x%x", newp.data.mp.iobase);
+ if (mask & HDLCDRV_PARMASK_IRQ)
+ printf(" irq %u", newp.data.mp.irq);
+ if (mask & HDLCDRV_PARMASK_DMA)
+ printf(" dma %u", newp.data.mp.dma);
+ if (mask & HDLCDRV_PARMASK_DMA2)
+ printf(" dma2 %u", newp.data.mp.dma2);
+ if (mask & HDLCDRV_PARMASK_SERIOBASE)
+ printf(" serio 0x%x", newp.data.mp.seriobase);
+ if (mask & HDLCDRV_PARMASK_PARIOBASE)
+ printf(" pario 0x%x", newp.data.mp.pariobase);
+ if (mask & HDLCDRV_PARMASK_MIDIIOBASE)
+ printf(" midiio 0x%x", newp.data.mp.midiiobase);
+ printf("\n");
+ }
+ exit(0);
+}
+
+#endif /* HDRVC_KERNEL */
+
+/* ---------------------------------------------------------------------- */
+
+static void display_channel_params(const struct hdrvc_channel_params *par)
+{
+ printf("TX delay %ums, TX tail %ums, slottime %ums, p-persistence "
+ " %u/256, %s duplex\n", 10*par->tx_delay, 10*par->tx_tail,
+ 10*par->slottime, par->ppersist,
+ par->fulldup ? "Full" : "Half");
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void do_set_channel_params(int argc, char **argv)
+{
+ struct hdrvc_channel_params par1, par2;
+ char set = 0;
+ int ret;
+
+ ret = hdrvc_get_channel_access_param(&par1);
+ if (ret < 0) {
+ perror("hdrvc_get_channel_access_param");
+ exit(1);
+ }
+ par2 = par1;
+ while (argc > 0) {
+ if (argc >= 2 && !strcasecmp(argv[0], "txd")) {
+ par2.tx_delay = strtoul(argv[1], NULL, 0) / 10;
+ set = 1;
+ argv += 2;
+ argc -= 2;
+ } else if (argc >= 2 && !strcasecmp(argv[0], "txtail")) {
+ par2.tx_tail = strtoul(argv[1], NULL, 0) / 10;
+ set = 1;
+ argv += 2;
+ argc -= 2;
+ } else if (argc >= 2 && !strcasecmp(argv[0], "slot")) {
+ par2.slottime = strtoul(argv[1], NULL, 0) / 10;
+ set = 1;
+ argv += 2;
+ argc -= 2;
+ } else if (argc >= 2 && !strcasecmp(argv[0], "ppersist")) {
+ par2.ppersist = strtoul(argv[1], NULL, 0);
+ set = 1;
+ argv += 2;
+ argc -= 2;
+ } else if (!strcasecmp(argv[0], "half")) {
+ par2.fulldup = 0;
+ set = 1;
+ argv += 1;
+ argc -= 1;
+ } else if (!strcasecmp(argv[0], "full")) {
+ par2.fulldup = 1;
+ set = 1;
+ argv += 1;
+ argc -= 1;
+ } else {
+
+ argv += 1;
+ argc -= 1;
+ }
+ }
+ printf("current parameters: ");
+ display_channel_params(&par1);
+ if (set) {
+ ret = hdrvc_set_channel_access_param(par2);
+ if (ret < 0) {
+ perror("hdrvc_set_channel_access_param");
+ exit(1);
+ }
+ printf("new parameters: ");
+ display_channel_params(&par2);
+ }
+ exit(0);
+}
+
+/* ---------------------------------------------------------------------- */
+
+static const char *usage_str =
+"[-b] [-i] [-d] [-i <baycomif>] [-h] [-c <cal>]\n"
+"[-p] [hw <hw>] [type <type>] [io <iobase>] [irq <irq>] [dma <dma>]\n"
+" [options <opt>] [serio <serio>] [pario <pario>] [midiio <midiio>]\n"
+"[-a] [txd <txdelay>] [txtail <txtail>] [slot <slottime>]\n"
+" [ppersist <ppersistence>] [full] [half]\n"
+" -a: set or display channel access parameters\n"
+" -b: trace demodulated bits\n"
+" -s: trace sampled input from tcm3105 (ser12 only)\n"
+" -d: trace dcd and ptt status on stdout\n"
+" -i: specify the name of the baycom kernel driver interface\n"
+" -c: calibrate (i.e. send calibration pattern) for cal seconds\n"
+#ifdef HDRVC_KERNEL
+" -p: set or display interface parameters\n"
+#endif /* HDRVC_KERNEL */
+" -h: this help\n\n";
+
+int main(int argc, char *argv[])
+{
+ int ret;
+ fd_set fds_read;
+ fd_set fds_write;
+ struct timeval tm;
+ char getsetparams = 0;
+ char cal = 0;
+ int cal_val = 0;
+ struct sm_ioctl bsi;
+ struct baycom_ioctl bbi;
+ struct hdrvc_channel_state chst;
+ unsigned char pktbuf[2048];
+
+ progname = *argv;
+ printf("%s: Version 0.5; (C) 1996-1997 by Thomas Sailer HB9JNX/AE4WA\n", *argv);
+ hdrvc_args(&argc, argv, "bc0");
+ while ((ret = getopt(argc, argv, "bsdhpc:a")) != -1) {
+ switch (ret) {
+ case 'b':
+ trace_stat = 2;
+ break;
+ case 's':
+ trace_stat = 3;
+ break;
+ case 'd':
+ trace_stat = 1;
+ break;
+#ifdef HDRVC_KERNEL
+ case 'p':
+ getsetparams = 1;
+ break;
+#endif /* HDRVC_KERNEL */
+ case 'a':
+ getsetparams = 2;
+ break;
+ case 'c':
+ cal = 1;
+ cal_val = strtoul(optarg, NULL, 0);
+ break;
+ default:
+ printf("usage: %s %s", *argv, usage_str);
+ exit(-1);
+ }
+ }
+ hdrvc_init();
+ if (getsetparams == 1) {
+#ifdef HDRVC_KERNEL
+ do_set_params(argc - optind, argv+optind);
+#endif /* HDRVC_KERNEL */
+ exit(0);
+ }
+ if (getsetparams == 2) {
+ do_set_channel_params(argc - optind, argv+optind);
+ exit(0);
+ }
+ if (cal) {
+ ret = hdrvc_calibrate(cal_val);
+ if (ret < 0) {
+ perror("hdrvc_calibrate");
+ exit(1);
+ }
+ fprintf(stdout, "%s: calibrating for %i seconds\n", *argv,
+ cal_val);
+ exit(0);
+ }
+ for (;;) {
+ while ((ret = hdrvc_recvpacket(pktbuf, sizeof(pktbuf))) > 1)
+ display_packet(pktbuf+1, ret-1);
+ switch (trace_stat) {
+ case 1:
+ ret = hdrvc_get_channel_state(&chst);
+ if (ret < 0)
+ perror("hdrvc_get_channel_state");
+ printf("%c%c rx: %lu tx: %lu rxerr: %lu txerr: %lu",
+ chst.dcd ? 'D' : '-', chst.ptt ? 'P' : '-',
+ chst.rx_packets, chst.tx_packets, chst.rx_errors,
+ chst.tx_errors);
+#ifdef HDRVC_KERNEL
+ if (hdrvc_sm_ioctl(SMCTL_GETDEBUG, &bsi) >= 0) {
+ printf(" intrate: %u modcyc: %u "
+ "demodcyc: %u dmares: %u",
+ bsi.data.dbg.int_rate,
+ bsi.data.dbg.mod_cycles,
+ bsi.data.dbg.demod_cycles,
+ bsi.data.dbg.dma_residue);
+ }
+ if (hdrvc_baycom_ioctl(BAYCOMCTL_GETDEBUG, &bbi) >= 0) {
+ printf(" dbg1: %lu dbg2: %lu dbg3: %li",
+ bbi.data.dbg.debug1, bbi.data.dbg.debug2,
+ bbi.data.dbg.debug3);
+ }
+#endif /* HDRVC_KERNEL */
+ printf("\n");
+ break;
+ case 2:
+ print_bits(hdrvc_get_bits);
+ printf("\n");
+ break;
+ case 3:
+ print_bits(hdrvc_get_samples);
+ printf("\n");
+ break;
+ default:
+ break;
+ }
+ tm.tv_usec = 500000L;
+ tm.tv_sec = 0L;
+ if (hdrvc_getfd() >= 0) {
+ FD_ZERO(&fds_read);
+ FD_ZERO(&fds_write);
+ FD_SET(hdrvc_getfd(), &fds_read);
+ ret = select(hdrvc_getfd()+1, &fds_read, &fds_write, NULL, &tm);
+ } else
+ ret = select(0, NULL, NULL, NULL, &tm);
+ if (ret < 0) {
+ fprintf(stderr, "%s: Error %s (%i) in select\n", *argv,
+ strerror(errno), errno);
+ exit(-2);
+ }
+ }
+}
+
+/* ---------------------------------------------------------------------- */
diff --git a/hdlcutil/smdiag.c b/hdlcutil/smdiag.c
new file mode 100644
index 0000000..d8a20f8
--- /dev/null
+++ b/hdlcutil/smdiag.c
@@ -0,0 +1,434 @@
+/*****************************************************************************/
+
+/*
+ * smdiag.c -- kernel soundcard radio modem driver diagnostics utility.
+ *
+ * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch)
+ *
+ * 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.
+ *
+ * Please note that the GPL allows you to use the driver, NOT the radio.
+ * In order to use the radio, you need a license from the communications
+ * authority of your country.
+ *
+ *
+ * History:
+ * 0.1 26.06.96 Started
+ * 0.2 11.05.97 introduced hdrvcomm.h
+ */
+
+/*****************************************************************************/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <limits.h>
+#include <net/if.h>
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include "hdrvcomm.h"
+
+#include <linux/soundmodem.h>
+
+/* ---------------------------------------------------------------------- */
+
+static char *progname;
+static Display *display = NULL;
+static Window window;
+static Pixmap pixmap;
+static unsigned long col_zeroline;
+static unsigned long col_background;
+static unsigned long col_trace;
+static GC gr_context;
+static int xmul;
+
+/* ---------------------------------------------------------------------- */
+
+static int x_error_handler(Display *disp, XErrorEvent *evt)
+{
+ char err_buf[256], mesg[256], number[256];
+ char *mtype = "XlibMessage";
+
+ XGetErrorText(disp, evt->error_code, err_buf, sizeof(err_buf));
+ fprintf(stderr, "X Error: %s\n", err_buf);
+ XGetErrorDatabaseText(disp, mtype, "MajorCode", "Request Major code %d",
+ mesg, sizeof(mesg));
+ fprintf(stderr, mesg, evt->request_code);
+ sprintf(number, "%d", evt->request_code);
+ XGetErrorDatabaseText(disp, "XRequest", number, "", err_buf,
+ sizeof(err_buf));
+ fprintf(stderr, " (%s)\n", err_buf);
+ abort();
+}
+
+/* ---------------------------------------------------------------------- */
+
+#define WIDTH 512
+#define HEIGHT (constell ? 512 : 256)
+
+static int openwindow(char *disp, int constell, int samplesperbit)
+{
+ XSetWindowAttributes attr;
+ XGCValues gr_values;
+ XColor color, dummy;
+ XSizeHints sizehints;
+
+ if (!(display = XOpenDisplay(NULL)))
+ return -1;
+ XSetErrorHandler(x_error_handler);
+ XAllocNamedColor(display, DefaultColormap(display, 0), "red",
+ &color, &dummy);
+ col_zeroline = color.pixel;
+ col_background = WhitePixel(display, 0);
+ col_trace = BlackPixel(display, 0);
+ attr.background_pixel = col_background;
+ if (!(window = XCreateWindow(display, XRootWindow(display, 0),
+ 200, 200, WIDTH, HEIGHT, 5,
+ DefaultDepth(display, 0),
+ InputOutput, DefaultVisual(display, 0),
+ CWBackPixel, &attr))) {
+ fprintf(stderr, "smdiag: unable to open X window\n");
+ exit(1);
+ }
+ if (!(pixmap = XCreatePixmap(display, window, WIDTH, HEIGHT,
+ DefaultDepth(display, 0)))) {
+ fprintf(stderr, "smdiag: unable to open offscreen pixmap\n");
+ exit(1);
+ }
+ xmul = WIDTH / (2*(samplesperbit > 0 ? samplesperbit : 1));
+ XSelectInput(display, window, KeyPressMask | StructureNotifyMask
+ | ExposureMask) ;
+ XAllocNamedColor(display, DefaultColormap(display, 0), "red",
+ &color, &dummy);
+ gr_values.foreground = col_trace;
+ gr_values.line_width = 1;
+ gr_values.line_style = LineSolid;
+ gr_context = XCreateGC(display, window, GCForeground | GCLineWidth |
+ GCLineStyle, &gr_values);
+ XStoreName(display, window, "diagnostics");
+ /*
+ * Do not allow the window to be resized
+ */
+ memset(&sizehints, 0, sizeof(sizehints));
+ sizehints.min_width = sizehints.max_width = WIDTH;
+ sizehints.min_height = sizehints.max_height = HEIGHT;
+ sizehints.flags = PMinSize | PMaxSize;
+ XSetWMNormalHints(display, window, &sizehints);
+ XMapWindow(display, window);
+ XSynchronize(display, 1);
+ return 0;
+}
+
+#undef WIDTH
+#undef HEIGHT
+
+/* ---------------------------------------------------------------------- */
+
+static void closewindow(void)
+{
+ if (!display)
+ return;
+ XDestroyWindow(display, window);
+ XCloseDisplay(display);
+ display = NULL;
+}
+
+/* ---------------------------------------------------------------------- */
+
+#define XCOORD(x) ((x) * xm)
+#define YCOORD(y) ((SHRT_MAX - (int)(y)) * winattrs.height / USHRT_MAX)
+
+static void drawdata(short *data, int len, int replace, int xm)
+{
+ int cnt;
+ GC gc;
+ XGCValues gcv;
+ XWindowAttributes winattrs;
+
+ if (!display || !pixmap)
+ return;
+ XGetWindowAttributes(display, window, &winattrs);
+ gcv.line_width = 1;
+ gcv.line_style = LineSolid;
+ gc = XCreateGC(display, pixmap, GCLineWidth | GCLineStyle, &gcv);
+ XSetState(display, gc, col_background, col_background, GXcopy,
+ AllPlanes);
+ if (replace)
+ XFillRectangle(display, pixmap, gc, 0, 0,
+ winattrs.width, winattrs.height);
+ else
+ XCopyArea(display, window, pixmap, gr_context, 0, 0,
+ winattrs.width, winattrs.height, 0, 0);
+ XSetForeground(display, gc, col_trace);
+ for (cnt = 0; cnt < len-1; cnt++)
+ XDrawLine(display, pixmap, gc, XCOORD(cnt), YCOORD(data[cnt]),
+ XCOORD(cnt+1), YCOORD(data[cnt+1]));
+ XSetForeground(display, gc, col_zeroline);
+ XDrawLine(display, pixmap, gc, 0, YCOORD(0), winattrs.width,
+ YCOORD(0));
+ XCopyArea(display, pixmap, window, gr_context, 0, 0, winattrs.width,
+ winattrs.height, 0, 0);
+ XFreeGC(display, gc);
+ XSync(display, 0);
+}
+
+#undef XCOORD
+#undef YCOORD
+
+/* ---------------------------------------------------------------------- */
+
+#define XCOORD(x) ((SHRT_MAX - (int)(x)) * winattrs.width / USHRT_MAX)
+#define YCOORD(y) ((SHRT_MAX - (int)(y)) * winattrs.height / USHRT_MAX)
+
+static void drawconstell(short *data, int len)
+{
+ int cnt;
+ GC gc;
+ XGCValues gcv;
+ XWindowAttributes winattrs;
+
+ if (!display || !pixmap)
+ return;
+ XGetWindowAttributes(display, window, &winattrs);
+ gcv.line_width = 1;
+ gcv.line_style = LineSolid;
+ gc = XCreateGC(display, pixmap, GCLineWidth | GCLineStyle, &gcv);
+ XSetState(display, gc, col_background, col_background, GXcopy,
+ AllPlanes);
+ XCopyArea(display, window, pixmap, gr_context, 0, 0,
+ winattrs.width, winattrs.height, 0, 0);
+ XSetForeground(display, gc, col_trace);
+ for (cnt = 0; cnt < len-1; cnt += 2)
+ XDrawPoint(display, pixmap, gc,
+ XCOORD(data[cnt]), YCOORD(data[cnt+1]));
+ XSetForeground(display, gc, col_zeroline);
+ XDrawLine(display, pixmap, gc, 0, YCOORD(0), winattrs.width, YCOORD(0));
+ XDrawLine(display, pixmap, gc, XCOORD(0), 0, XCOORD(0), winattrs.height);
+ XCopyArea(display, pixmap, window, gr_context, 0, 0, winattrs.width,
+ winattrs.height, 0, 0);
+ XFreeGC(display, gc);
+ XSync(display, 0);
+}
+
+#undef XCOORD
+#undef YCOORD
+
+/* ---------------------------------------------------------------------- */
+
+static void clearwindow(void)
+{
+ XWindowAttributes winattrs;
+ GC gc;
+ XGCValues gcv;
+
+ if (!display || !pixmap)
+ return;
+ XGetWindowAttributes(display, window, &winattrs);
+ gcv.line_width = 1;
+ gcv.line_style = LineSolid;
+ gc = XCreateGC(display, pixmap, GCLineWidth | GCLineStyle, &gcv);
+ XSetState(display, gc, col_background, col_background, GXcopy,
+ AllPlanes);
+ XFillRectangle(display, pixmap, gc, 0, 0,
+ winattrs.width, winattrs.height);
+ XSetForeground(display, gc, col_zeroline);
+ XClearArea(display, window, 0, 0, 0, 0, False);
+ XCopyArea(display, pixmap, window, gr_context, 0, 0, winattrs.width,
+ winattrs.height, 0, 0);
+ XFreeGC(display, gc);
+}
+
+/* ---------------------------------------------------------------------- */
+
+static Bool predicate(Display *display, XEvent *event, char *arg)
+{
+ return True;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static char *getkey(void)
+{
+ XWindowAttributes winattrs;
+ XEvent evt;
+ static char kbuf[32];
+ int i;
+
+ if (!display)
+ return NULL;
+ XSync(display, 0);
+ while (XCheckIfEvent(display, &evt, predicate, NULL)) {
+ switch (evt.type) {
+ case KeyPress:
+ i = XLookupString((XKeyEvent *)&evt, kbuf, sizeof(kbuf)-1,
+ NULL, NULL);
+ if (!i)
+ return NULL;
+ kbuf[i] = 0;
+ return kbuf;
+ case DestroyNotify:
+ XCloseDisplay(display);
+ display = NULL;
+ return NULL;
+ case Expose:
+ XGetWindowAttributes(display, window, &winattrs);
+ XCopyArea(display, pixmap, window, gr_context, 0, 0,
+ winattrs.width, winattrs.height, 0, 0);
+ break;
+ default:
+ break;
+ }
+ }
+ return NULL;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void printmode(unsigned int mode, unsigned int trigger)
+{
+ printf("Source: %s%s\n", (mode == SM_DIAGMODE_DEMOD) ?
+ "demodulator (eye diagram)" : "input (oscilloscope)",
+ (trigger & SM_DIAGFLAG_DCDGATE) ? " gated with DCD" : "");
+}
+
+/* ---------------------------------------------------------------------- */
+
+static const char *usage_str =
+"[-d display] [-i smif] [-c] [-e]\n"
+" -d: display host\n"
+" -i: specify the name of the baycom kernel driver interface\n"
+" -c: toggle carrier trigger\n"
+" -e: eye diagram mode\n\n"
+" -p: constellation plot\n\n";
+
+int main(int argc, char *argv[])
+{
+ char *disp = NULL;
+ unsigned int mode = HDRVC_DIAGMODE_INPUT;
+ unsigned int trigger = 0;
+ unsigned int ifflags;
+ short data[256];
+ char *cp;
+ int ret;
+ unsigned int samplesperbit;
+
+ progname = *argv;
+ printf("%s: Version 0.2; (C) 1996-1997 by Thomas Sailer HB9JNX/AE4WA\n", *argv);
+ hdrvc_args(&argc, argv, "sm0");
+ while ((ret = getopt(argc, argv, "d:ecp")) != -1) {
+ switch (ret) {
+ case 'd':
+ disp = optarg;
+ break;
+ case 'e':
+ mode = HDRVC_DIAGMODE_DEMOD;
+ trigger = HDRVC_DIAGFLAG_DCDGATE;
+ break;
+ case 'c':
+ trigger ^= HDRVC_DIAGFLAG_DCDGATE;
+ break;
+ case 'p':
+ mode = HDRVC_DIAGMODE_CONSTELLATION;
+ break;
+ default:
+ printf("usage: %s %s", *argv, usage_str);
+ exit(-1);
+ }
+ }
+ hdrvc_init();
+#ifdef HDRVC_KERNEL
+ ifflags = hdrvc_get_ifflags();
+ if (!(ifflags & IFF_UP)) {
+ fprintf(stderr, "interface %s down\n", hdrvc_ifname());
+ exit(1);
+ }
+ if (!(ifflags & IFF_RUNNING)) {
+ fprintf(stderr, "interface %s not running\n", hdrvc_ifname());
+ exit(1);
+ }
+#endif /* HDRVC_KERNEL */
+ printmode(mode, trigger);
+ for (;;) {
+ if ((ret = hdrvc_diag2(mode, trigger, data, sizeof(data) / sizeof(short),
+ &samplesperbit)) < 0) {
+ perror("hdrvc_diag2");
+ exit(1);
+ }
+ if (ret > 0) {
+ if (!display) {
+ openwindow(disp, mode == HDRVC_DIAGMODE_CONSTELLATION,
+ samplesperbit);
+ clearwindow();
+ }
+ if (mode == SM_DIAGMODE_CONSTELLATION)
+ drawconstell(data, ret);
+ else
+ drawdata(data, ret, mode == HDRVC_DIAGMODE_INPUT,
+ mode == HDRVC_DIAGMODE_INPUT ? 5:xmul);
+ } else
+ usleep(100000L);
+ if (display) {
+ if ((cp = getkey())) {
+ for (; *cp; cp++) {
+ printf("char pressed: '%c'\n", *cp);
+ switch (*cp) {
+ case 'c':
+ case 'C':
+ clearwindow();
+ printmode(mode, trigger);
+ break;
+ case 'q':
+ case 'Q':
+ closewindow();
+ break;
+ case 'i':
+ case 'I':
+ if (mode == HDRVC_DIAGMODE_CONSTELLATION)
+ break;
+ mode = HDRVC_DIAGMODE_INPUT;
+ clearwindow();
+ printmode(mode, trigger);
+ break;
+ case 'e':
+ case 'E':
+ if (mode == HDRVC_DIAGMODE_CONSTELLATION)
+ break;
+ mode = HDRVC_DIAGMODE_DEMOD;
+ clearwindow();
+ printmode(mode, trigger);
+ break;
+ case 'd':
+ case 'D':
+ trigger ^= HDRVC_DIAGFLAG_DCDGATE;
+ clearwindow();
+ printmode(mode, trigger);
+ break;
+ }
+ }
+ }
+ if (!display)
+ exit(0);
+ }
+ }
+}
+
+/* ---------------------------------------------------------------------- */
diff --git a/hdlcutil/smmixer.c b/hdlcutil/smmixer.c
new file mode 100644
index 0000000..3cfc7e7
--- /dev/null
+++ b/hdlcutil/smmixer.c
@@ -0,0 +1,781 @@
+/*****************************************************************************/
+
+/*
+ * smmixer.c -- kernel soundcard radio modem driver mixer utility.
+ *
+ * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch)
+ *
+ * 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.
+ *
+ * Please note that the GPL allows you to use the driver, NOT the radio.
+ * In order to use the radio, you need a license from the communications
+ * authority of your country.
+ *
+ *
+ * History:
+ * 0.1 26.06.96 Started
+ * 0.2 11.05.97 introduced hdrvcomm.h
+ */
+
+/*****************************************************************************/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
+#include <net/if.h>
+#include "hdrvcomm.h"
+
+#include <linux/soundmodem.h>
+/* ---------------------------------------------------------------------- */
+
+static char *progname;
+static unsigned int mixdevice;
+
+/* ---------------------------------------------------------------------- */
+
+static int do_mix_ioctl(int cmd, struct sm_mixer_data *mixdat)
+{
+ struct sm_ioctl par;
+ int i;
+
+ par.cmd = cmd;
+ par.data.mix = *mixdat;
+#ifdef HDRVC_KERNEL
+ i = hdrvc_sm_ioctl(cmd, &par);
+#endif
+ *mixdat = par.data.mix;
+ return i;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static unsigned char get_mixer_reg(unsigned char addr)
+{
+ int i;
+ struct sm_mixer_data mixdat;
+
+ mixdat.reg = addr;
+ if ((i = do_mix_ioctl(SMCTL_GETMIXER, &mixdat)) < 0) {
+ perror("do_mix_ioctl: SMCTL_GETMIXER");
+ exit(1);
+ }
+ if (!i)
+ fprintf(stderr, "warning: mixer device %u register %u not "
+ "accessible for reading!\n", mixdat.mixer_type,
+ addr);
+ if (mixdat.mixer_type != mixdevice) {
+ fprintf(stderr, "error: mixer type changed !?\n");
+ exit(2);
+ }
+ return mixdat.data;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void set_mixer_reg(unsigned char addr, unsigned char data)
+{
+ struct sm_mixer_data mixdat;
+
+ mixdat.reg = addr;
+ mixdat.data = data;
+ mixdat.mixer_type = mixdevice;
+ if (do_mix_ioctl(SMCTL_SETMIXER, &mixdat) < 0) {
+ perror("do_mix_ioctl: SMCTL_SETMIXER");
+ exit(1);
+ }
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void display_mixer_ad1848(void)
+{
+ static const char *src[4] = { "Line", "Aux1", "Mic", "Dac" };
+ unsigned char data;
+
+ data = get_mixer_reg(0);
+ printf("Left input: Source: %-4s Gain: %3ddB\n", src[(data>>6)&3],
+ (((data & 0xe0) == 0xa0) ? 20 : 0) + (data & 0xf) * 3 / 2);
+ data = get_mixer_reg(1);
+ printf("Right input: Source: %-4s Gain: %3ddB\n", src[(data>>6)&3],
+ (((data & 0xe0) == 0xa0) ? 20 : 0) + (data & 0xf) * 3 / 2);
+ data = get_mixer_reg(2);
+ if (!(data & 0x80))
+ printf("Left Aux1 mixing: Gain: %3ddB\n",
+ (8 - (int)(data & 0x1f)) * 3 / 2);
+ data = get_mixer_reg(3);
+ if (!(data & 0x80))
+ printf("Right Aux1 mixing: Gain: %3ddB\n",
+ (8 - (int)(data & 0x1f)) * 3 / 2);
+ data = get_mixer_reg(4);
+ if (!(data & 0x80))
+ printf("Left Aux2 mixing: Gain: %3ddB\n",
+ (8 - (int)(data & 0x1f)) * 3 / 2);
+ data = get_mixer_reg(5);
+ if (!(data & 0x80))
+ printf("Right Aux2 mixing: Gain: %3ddB\n",
+ (8 - (int)(data & 0x1f)) * 3 / 2);
+ data = get_mixer_reg(6);
+ if (data & 0x80)
+ printf("Left output: muted\n");
+ else
+ printf("Left output: Gain: %3ddB\n",
+ ((int)(data & 0x3f)) * (-3) / 2);
+ data = get_mixer_reg(7);
+ if (data & 0x80)
+ printf("Right output: muted\n");
+ else
+ printf("Right output: Gain: %3ddB\n",
+ ((int)(data & 0x3f)) * (-3) / 2);
+ data = get_mixer_reg(13);
+ if (data & 1)
+ printf("Digital mix: Gain: %3ddB\n",
+ ((int)((data >> 2) & 0x3f)) * (-3) / 2);
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void display_mixer_cs423x(void)
+{
+ unsigned char data;
+
+ display_mixer_ad1848();
+ data = get_mixer_reg(26);
+ printf("Mono: %s%s%s Gain: %3ddB\n",
+ (data & 0x80) ? "input muted, " : "",
+ (data & 0x40) ? "output muted, " : "",
+ (data & 0x20) ? "bypass, " : "",
+ (int)(data & 0xf) * (-3));
+ data = get_mixer_reg(27);
+ if (data & 0x80)
+ printf("Left output: muted\n");
+ else
+ printf("Left output: Gain: %3ddB\n",
+ ((int)(data & 0xf)) * (-2));
+ data = get_mixer_reg(29);
+ if (data & 0x80)
+ printf("Right output: muted\n");
+ else
+ printf("Right output: Gain: %3ddB\n",
+ ((int)(data & 0xf)) * (-2));
+
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void display_mixer_ct1335(void)
+{
+ unsigned char data;
+
+ data = get_mixer_reg(0x2);
+ printf("Master volume: %3ddB\n",
+ (((int)((data >> 1) & 7)) - 7) * 46 / 7);
+ data = get_mixer_reg(0xa);
+ printf("Voice volume: %3ddB\n",
+ (((int)((data >> 1) & 3)) - 3) * 46 / 3);
+ data = get_mixer_reg(0x6);
+ printf("MIDI volume: %3ddB\n",
+ (((int)((data >> 1) & 7)) - 7) * 46 / 7);
+ data = get_mixer_reg(0x8);
+ printf("CD volume: %3ddB\n",
+ (((int)((data >> 1) & 7)) - 7) * 46 / 7);
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void display_mixer_ct1345(void)
+{
+ static const char *src[4] = { "Mic", "CD", "Mic", "Line" };
+ unsigned char data, data2;
+
+ data = get_mixer_reg(0xc);
+ data2 = get_mixer_reg(0xe);
+ printf("Input source: %s\n", src[(data >> 1) & 3]);
+ if (!(data & data2 & 0x20)) {
+ printf("Filter: Low pass %s kHz: ", (data & 0x8) ?
+ "8.8" : "3.2");
+ if (data & 0x20)
+ printf("output\n");
+ else
+ printf("input%s\n", (data2 & 0x20) ? "" : ", output");
+ }
+ if (data2 & 2)
+ printf("stereo\n");
+
+ data = get_mixer_reg(0x22);
+ printf("Master volume: Left: %3ddB Right: %3ddB\n",
+ (((int)((data >> 5) & 7)) - 7) * 46 / 7,
+ (((int)((data >> 1) & 7)) - 7) * 46 / 7);
+ data = get_mixer_reg(0x4);
+ printf("Voice volume: Left: %3ddB Right: %3ddB\n",
+ (((int)((data >> 5) & 7)) - 7) * 46 / 7,
+ (((int)((data >> 1) & 7)) - 7) * 46 / 7);
+ data = get_mixer_reg(0x26);
+ printf("MIDI volume: Left: %3ddB Right: %3ddB\n",
+ (((int)((data >> 5) & 7)) - 7) * 46 / 7,
+ (((int)((data >> 1) & 7)) - 7) * 46 / 7);
+ data = get_mixer_reg(0x28);
+ printf("CD volume: Left: %3ddB Right: %3ddB\n",
+ (((int)((data >> 5) & 7)) - 7) * 46 / 7,
+ (((int)((data >> 1) & 7)) - 7) * 46 / 7);
+ data = get_mixer_reg(0x2e);
+ printf("Line volume: Left: %3ddB Right: %3ddB\n",
+ (((int)((data >> 5) & 7)) - 7) * 46 / 7,
+ (((int)((data >> 1) & 7)) - 7) * 46 / 7);
+ data = get_mixer_reg(0x0a);
+ printf("Mic mixing volume: %3ddB\n",
+ (((int)((data >> 1) & 3)) - 3) * 46 / 3);
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void display_mixer_ct1745(void)
+{
+ unsigned char data, data2;
+
+ printf("Master volume: Left: %3ddB Right: %3ddB\n",
+ ((int)((get_mixer_reg(0x30) >> 3) & 0x1f) - 31) * 2,
+ ((int)((get_mixer_reg(0x31) >> 3) & 0x1f) - 31) * 2);
+ printf("Voice volume: Left: %3ddB Right: %3ddB\n",
+ ((int)((get_mixer_reg(0x32) >> 3) & 0x1f) - 31) * 2,
+ ((int)((get_mixer_reg(0x33) >> 3) & 0x1f) - 31) * 2);
+ printf("MIDI volume: Left: %3ddB Right: %3ddB\n",
+ ((int)((get_mixer_reg(0x34) >> 3) & 0x1f) - 31) * 2,
+ ((int)((get_mixer_reg(0x35) >> 3) & 0x1f) - 31) * 2);
+ printf("CD volume: Left: %3ddB Right: %3ddB\n",
+ ((int)((get_mixer_reg(0x36) >> 3) & 0x1f) - 31) * 2,
+ ((int)((get_mixer_reg(0x37) >> 3) & 0x1f) - 31) * 2);
+ printf("Line volume: Left: %3ddB Right: %3ddB\n",
+ ((int)((get_mixer_reg(0x38) >> 3) & 0x1f) - 31) * 2,
+ ((int)((get_mixer_reg(0x39) >> 3) & 0x1f) - 31) * 2);
+ printf("Mic volume: %3ddB\n",
+ ((int)((get_mixer_reg(0x3a) >> 3) & 0x1f) - 31) * 2);
+ printf("PC speaker volume: %3ddB\n",
+ ((int)((get_mixer_reg(0x3b) >> 6) & 0x3) - 3) * 6);
+ printf("Mic gain: %s\n",
+ (get_mixer_reg(0x43) & 1) ? "fixed 20dB" : "AGC");
+ printf("Output gain: Left: %3ddB Right: %3ddB\n",
+ ((int)((get_mixer_reg(0x41) >> 6) & 3)) * 6,
+ ((int)((get_mixer_reg(0x42) >> 6) & 3)) * 6);
+ printf("Input gain: Left: %3ddB Right: %3ddB\n",
+ ((int)((get_mixer_reg(0x3f) >> 6) & 3)) * 6,
+ ((int)((get_mixer_reg(0x40) >> 6) & 3)) * 6);
+ data = (get_mixer_reg(0x44) >> 4) & 0xf;
+ if (data > 7)
+ data--;
+ data2 = (get_mixer_reg(0x45) >> 4) & 0xf;
+ if (data2 > 7)
+ data2--;
+ printf("Treble: Left: %3ddB Right: %3ddB\n",
+ ((int)data - 7) * 2, ((int)data2 - 7) * 2);
+ data = (get_mixer_reg(0x46) >> 4) & 0xf;
+ if (data > 7)
+ data--;
+ data2 = (get_mixer_reg(0x47) >> 4) & 0xf;
+ if (data2 > 7)
+ data2--;
+ printf("Bass: Left: %3ddB Right: %3ddB\n",
+ ((int)data - 7) * 2, ((int)data2 - 7) * 2);
+ data = get_mixer_reg(0x3c);
+ printf("Output sources left: PCSpeaker Voice.L%s%s%s\n",
+ (data & 1) ? " Mic" : "", (data & 4) ? " CD.L" : "",
+ (data & 0x10) ? " Line.L" : "");
+ printf("Output sources right: PCSpeaker Voice.R%s%s%s\n",
+ (data & 1) ? " Mic" : "", (data & 2) ? " CD.R" : "",
+ (data & 8) ? " Line.R" : "");
+ data = get_mixer_reg(0x3d);
+ printf("Input sources left: %s%s%s%s%s%s%s\n",
+ (data & 1) ? " Mic" : "", (data & 2) ? " CD.R" : "",
+ (data & 4) ? " CD.L" : "", (data & 8) ? " Line.R" : "",
+ (data & 0x10) ? " Line.L" : "", (data & 0x20) ? " Midi.R" : "",
+ (data & 0x40) ? " Midi.L" : "");
+ data = get_mixer_reg(0x3e);
+ printf("Input sources right: %s%s%s%s%s%s%s\n",
+ (data & 1) ? " Mic" : "", (data & 2) ? " CD.R" : "",
+ (data & 4) ? " CD.L" : "", (data & 8) ? " Line.R" : "",
+ (data & 0x10) ? " Line.L" : "", (data & 0x20) ? " Midi.R" : "",
+ (data & 0x40) ? " Midi.L" : "");
+}
+
+/* ---------------------------------------------------------------------- */
+
+static int parse_ad_src(const char *cp)
+{
+ if (!strcasecmp(cp, "line"))
+ return 0;
+ if (!strcasecmp(cp, "aux1"))
+ return 1;
+ if (!strcasecmp(cp, "mic"))
+ return 2;
+ if (!strcasecmp(cp, "dac"))
+ return 3;
+ return -1;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static int set_mixer_ad1848(int argc, char *argv[])
+{
+ unsigned int mask = 0;
+ int olvll = 0, olvlr = 0;
+ int isrcl = 0, isrcr = 0;
+ int ilvll = 0, ilvlr = 0;
+ unsigned int data;
+
+ for (; argc >= 1; argc--, argv++) {
+ if (!strncasecmp(argv[0], "ol=", 3)) {
+ olvll = strtol(argv[0]+3, NULL, 0);
+ mask |= 1;
+ if (olvll < -46 || olvll > 0) {
+ fprintf(stderr, "output level out of range "
+ "-100..0dB\n");
+ return -1;
+ }
+ } else if (!strncasecmp(argv[0], "or=", 3)) {
+ olvlr = strtol(argv[0]+3, NULL, 0);
+ mask |= 2;
+ if (olvlr < -46 || olvlr > 0) {
+ fprintf(stderr, "output level out of range "
+ "-100..0dB\n");
+ return -1;
+ }
+ } else if (!strncasecmp(argv[0], "o=", 2)) {
+ olvll = olvlr = strtol(argv[0]+2, NULL, 0);
+ mask |= 3;
+ if (olvll < -46 || olvll > 0) {
+ fprintf(stderr, "output level out of range "
+ "-100..0dB\n");
+ return -1;
+ }
+ } else if (!strncasecmp(argv[0], "il=", 3)) {
+ ilvll = strtol(argv[0]+3, NULL, 0);
+ mask |= 4;
+ if (ilvll < 0 || ilvll > 43) {
+ fprintf(stderr, "input gain out of range "
+ "0..43dB\n");
+ return -1;
+ }
+ } else if (!strncasecmp(argv[0], "ir=", 3)) {
+ ilvlr = strtol(argv[0]+3, NULL, 0);
+ mask |= 8;
+ if (ilvll < 0 || ilvll > 43) {
+ fprintf(stderr, "input gain out of range "
+ "0..43dB\n");
+ return -1;
+ }
+ } else if (!strncasecmp(argv[0], "i=", 2)) {
+ ilvll = ilvlr = strtol(argv[0]+2, NULL, 0);
+ mask |= 12;
+ if (ilvll < 0 || ilvll > 43) {
+ fprintf(stderr, "input gain out of range "
+ "0..43dB\n");
+ return -1;
+ }
+ } else if (!strncasecmp(argv[0], "sl=", 3)) {
+ mask |= 16;
+ if ((isrcl = parse_ad_src(argv[0]+3)) < 0) {
+ fprintf(stderr, "invalid input source, must "
+ "be either line, aux1, mic or dac\n");
+ return -1;
+ }
+ } else if (!strncasecmp(argv[0], "sr=", 3)) {
+ mask |= 32;
+ if ((isrcr = parse_ad_src(argv[0]+3)) < 0) {
+ fprintf(stderr, "invalid input source, must "
+ "be either line, aux1, mic or dac\n");
+ return -1;
+ }
+ } else if (!strncasecmp(argv[0], "s=", 2)) {
+ mask |= 48;
+ if ((isrcl = isrcr = parse_ad_src(argv[0]+2)) < 0) {
+ fprintf(stderr, "invalid input source, must "
+ "be either line, aux1, mic or dac\n");
+ return -1;
+ }
+ } else {
+ fprintf(stderr, "invalid parameter \"%s\"\n", argv[0]);
+ return -1;
+ }
+ }
+ data = get_mixer_reg(0x00);
+ if (mask & 4) {
+ data &= 0xc0;
+ if (ilvll > 23) {
+ data |= 0x20;
+ ilvll -= 20;
+ }
+ data |= ilvll * 2 / 3;
+ }
+ if (mask & 16)
+ data = (data & 0x3f) | (isrcl << 6);
+ if ((data & 0xc0) != 0x80)
+ data &= ~0x20;
+ set_mixer_reg(0x00, data);
+ data = get_mixer_reg(0x01);
+ if (mask & 8) {
+ data &= 0xc0;
+ if (ilvlr > 23) {
+ data |= 0x20;
+ ilvlr -= 20;
+ }
+ data |= ilvlr * 2 / 3;
+ }
+ if (mask & 32)
+ data = (data & 0x3f) | (isrcr << 6);
+ if ((data & 0xc0) != 0x80)
+ data &= ~0x20;
+ set_mixer_reg(0x01, data);
+ set_mixer_reg(0x02, 0x80);
+ set_mixer_reg(0x03, 0x80);
+ set_mixer_reg(0x04, 0x80);
+ set_mixer_reg(0x05, 0x80);
+ if (mask & 1) {
+ if (olvll < -95)
+ set_mixer_reg(0x06, 0x80);
+ else
+ set_mixer_reg(0x06, (olvll * (-2) / 3));
+ }
+ if (mask & 2) {
+ if (olvlr < -95)
+ set_mixer_reg(0x07, 0x80);
+ else
+ set_mixer_reg(0x07, (olvlr * (-2) / 3));
+ }
+ set_mixer_reg(0x0d, 0x00);
+ return 0;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static int set_mixer_ct1335(int argc, char *argv[])
+{
+ unsigned int mask = 0;
+ int olvl = 0;
+
+ for (; argc >= 1; argc--, argv++) {
+ if (!strncasecmp(argv[0], "o=", 2)) {
+ olvl = strtol(argv[0]+2, NULL, 0);
+ mask |= 1;
+ if (olvl < -46 || olvl > 0) {
+ fprintf(stderr, "output level out of range "
+ "-46..0dB\n");
+ return -1;
+ }
+ } else {
+ fprintf(stderr, "invalid parameter \"%s\"\n", argv[0]);
+ return -1;
+ }
+ }
+ if (mask & 1)
+ set_mixer_reg(0x02, (((olvl * 7 / 46) + 7) << 1));
+ set_mixer_reg(0x06, 0x00);
+ set_mixer_reg(0x08, 0x00);
+ set_mixer_reg(0x0a, 0x06);
+ return 0;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static int set_mixer_ct1345(int argc, char *argv[])
+{
+ unsigned int mask = 0;
+ int olvll = 0, olvlr = 0;
+ int isrc = 0;
+ unsigned int data;
+
+ for (; argc >= 1; argc--, argv++) {
+ if (!strncasecmp(argv[0], "ol=", 3)) {
+ olvll = strtol(argv[0]+3, NULL, 0);
+ mask |= 1;
+ if (olvll < -46 || olvll > 0) {
+ fprintf(stderr, "output level out of range "
+ "-46..0dB\n");
+ return -1;
+ }
+ } else if (!strncasecmp(argv[0], "or=", 3)) {
+ olvlr = strtol(argv[0]+3, NULL, 0);
+ mask |= 2;
+ if (olvlr < -46 || olvlr > 0) {
+ fprintf(stderr, "output level out of range "
+ "-46..0dB\n");
+ return -1;
+ }
+ } else if (!strncasecmp(argv[0], "o=", 2)) {
+ olvll = olvlr = strtol(argv[0]+2, NULL, 0);
+ mask |= 3;
+ if (olvll < -46 || olvll > 0) {
+ fprintf(stderr, "output level out of range "
+ "-46..0dB\n");
+ return -1;
+ }
+ } else if (!strncasecmp(argv[0], "s=", 2)) {
+ mask |= 4;
+ if (!strcasecmp(argv[0]+2, "mic"))
+ isrc = 0;
+ else if (!strcasecmp(argv[0]+2, "cd"))
+ isrc = 1;
+ else if (!strcasecmp(argv[0]+2, "line"))
+ isrc = 3;
+ else {
+ fprintf(stderr, "invalid input source, must "
+ "be either mic, cd or line\n");
+ return -1;
+ }
+ } else {
+ fprintf(stderr, "invalid parameter \"%s\"\n", argv[0]);
+ return -1;
+ }
+ }
+ set_mixer_reg(0x04, 0xee);
+ set_mixer_reg(0x0a, 0x00);
+ if (mask & 4)
+ data = (isrc & 3) << 1;
+ else
+ data = get_mixer_reg(0x0c) & 0x06;
+ set_mixer_reg(0x0c, data | 0x20);
+ set_mixer_reg(0x0e, 0x20);
+ data = get_mixer_reg(0x22);
+ if (mask & 1)
+ data = (data & 0x0f) | (((olvll * 7 / 46) + 7) << 5);
+ if (mask & 2)
+ data = (data & 0xf0) | (((olvlr * 7 / 46) + 7) << 1);
+ set_mixer_reg(0x22, data);
+ set_mixer_reg(0x26, 0x00);
+ set_mixer_reg(0x28, 0x00);
+ set_mixer_reg(0x2e, 0x00);
+ return 0;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static int set_mixer_ct1745(int argc, char *argv[])
+{
+ unsigned int mask = 0;
+ int olvll = 0, olvlr = 0;
+ int ilvll = 0, ilvlr = 0;
+ unsigned int insrc = 0;
+ unsigned int data;
+
+ for (; argc >= 1; argc--, argv++) {
+ if (!strncasecmp(argv[0], "ol=", 3)) {
+ olvll = strtol(argv[0]+3, NULL, 0);
+ mask |= 1;
+ if (olvll < -62 || olvll > 18) {
+ fprintf(stderr, "output level out of range "
+ "-62..18dB\n");
+ return -1;
+ }
+ } else if (!strncasecmp(argv[0], "or=", 3)) {
+ olvlr = strtol(argv[0]+3, NULL, 0);
+ mask |= 2;
+ if (olvlr < -62 || olvlr > 18) {
+ fprintf(stderr, "output level out of range "
+ "-62..18dB\n");
+ return -1;
+ }
+ } else if (!strncasecmp(argv[0], "o=", 2)) {
+ olvll = olvlr = strtol(argv[0]+2, NULL, 0);
+ mask |= 3;
+ if (olvll < -62 || olvll > 18) {
+ fprintf(stderr, "output level out of range "
+ "-62..18dB\n");
+ return -1;
+ }
+ } else if (!strncasecmp(argv[0], "il=", 3)) {
+ ilvll = strtol(argv[0]+3, NULL, 0);
+ mask |= 4;
+ if (ilvll < -62 || ilvll > 18) {
+ fprintf(stderr, "input gain out of range "
+ "-62..18dB\n");
+ return -1;
+ }
+ } else if (!strncasecmp(argv[0], "ir=", 3)) {
+ ilvlr = strtol(argv[0]+3, NULL, 0);
+ mask |= 8;
+ if (ilvll < -62 || ilvll > 18) {
+ fprintf(stderr, "input gain out of range "
+ "-62..18dB\n");
+ return -1;
+ }
+ } else if (!strncasecmp(argv[0], "i=", 2)) {
+ ilvll = ilvlr = strtol(argv[0]+2, NULL, 0);
+ mask |= 12;
+ if (ilvll < -62 || ilvll > 18) {
+ fprintf(stderr, "input gain out of range "
+ "-62..18dB\n");
+ return -1;
+ }
+ } else if (!strncasecmp(argv[0], "s=", 2)) {
+ mask |= 16;
+ if (!strcasecmp(argv[0]+2, "mic"))
+ insrc |= 1;
+ else if (!strcasecmp(argv[0]+2, "cd.r"))
+ insrc |= 2;
+ else if (!strcasecmp(argv[0]+2, "cd.l"))
+ insrc |= 4;
+ else if (!strcasecmp(argv[0]+2, "cd"))
+ insrc |= 6;
+ else if (!strcasecmp(argv[0]+2, "line.r"))
+ insrc |= 0x08;
+ else if (!strcasecmp(argv[0]+2, "line.l"))
+ insrc |= 0x10;
+ else if (!strcasecmp(argv[0]+2, "line"))
+ insrc |= 0x18;
+ else if (!strcasecmp(argv[0]+2, "midi.r"))
+ insrc |= 0x20;
+ else if (!strcasecmp(argv[0]+2, "midi.l"))
+ insrc |= 0x40;
+ else if (!strcasecmp(argv[0]+2, "midi"))
+ insrc |= 0x60;
+ else {
+ fprintf(stderr, "invalid input source, must "
+ "be either line, cd, mic or midi\n");
+ return -1;
+ }
+ } else {
+ fprintf(stderr, "invalid parameter \"%s\"\n", argv[0]);
+ return -1;
+ }
+ }
+ if (mask & 3) {
+ set_mixer_reg(0x3c, 0); /* output src: only voice and pcspk */
+ set_mixer_reg(0x44, 4<<4); /* treble.l: -6dB */
+ set_mixer_reg(0x45, 4<<4); /* treble.r: -6dB */
+ set_mixer_reg(0x46, 6<<4); /* bass.l: -2dB */
+ set_mixer_reg(0x47, 6<<4); /* bass.r: -2dB */
+ set_mixer_reg(0x3b, 0); /* PC speaker vol -18dB */
+ }
+ if (mask & 12)
+ set_mixer_reg(0x43, 1); /* mic: agc off, fixed 20dB gain */
+ if (mask & 1) {
+ data = 0;
+ while (olvll > 0) {
+ olvll -= 6;
+ data += 0x40;
+ }
+ set_mixer_reg(0x41, data); /* output gain */
+ set_mixer_reg(0x30, 0xf8); /* master vol */
+ set_mixer_reg(0x32, (olvll / 2 + 31) << 3); /* voice vol */
+ }
+ if (mask & 2) {
+ data = 0;
+ while (olvlr > 0) {
+ olvlr -= 6;
+ data += 0x40;
+ }
+ set_mixer_reg(0x42, data); /* output gain */
+ set_mixer_reg(0x31, 0xf8); /* master vol */
+ set_mixer_reg(0x33, (olvlr / 2 + 31) << 3); /* voice vol */
+ }
+ if (mask & 4) {
+ data = 0;
+ while (ilvll > 0) {
+ ilvll -= 6;
+ data += 0x40;
+ }
+ set_mixer_reg(0x3f, data); /* input gain */
+ data = (ilvll / 2 + 31) << 3;
+ set_mixer_reg(0x34, data); /* midi vol */
+ set_mixer_reg(0x36, data); /* cd vol */
+ set_mixer_reg(0x38, data); /* line vol */
+ set_mixer_reg(0x3a, data); /* mic vol */
+ }
+ if (mask & 8) {
+ data = 0;
+ while (ilvlr > 0) {
+ ilvlr -= 6;
+ data += 0x40;
+ }
+ set_mixer_reg(0x40, data); /* input gain */
+ data = (ilvlr / 2 + 31) << 3;
+ set_mixer_reg(0x35, data); /* midi vol */
+ set_mixer_reg(0x37, data); /* cd vol */
+ set_mixer_reg(0x39, data); /* line vol */
+ set_mixer_reg(0x3a, data); /* mic vol */
+ }
+ if (mask & 16) {
+ set_mixer_reg(0x3d, insrc); /* input sources */
+ set_mixer_reg(0x3e, insrc); /* input sources */
+ }
+ return 0;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static const char *usage_str =
+"[-i smif]\n\n";
+
+int main(int argc, char *argv[])
+{
+ int c;
+ struct sm_mixer_data mixdat;
+
+ progname = *argv;
+ printf("%s: Version 0.2; (C) 1996-1997 by Thomas Sailer HB9JNX/AE4WA\n", *argv);
+ hdrvc_args(&argc, argv, "sm0");
+ while ((c = getopt(argc, argv, "")) != -1) {
+ switch (c) {
+ default:
+ printf("usage: %s %s", *argv, usage_str);
+ exit(-1);
+ }
+ }
+ hdrvc_init();
+ mixdat.reg = 0;
+ if (do_mix_ioctl(SMCTL_GETMIXER, &mixdat) < 0) {
+ perror("do_mix_ioctl: SMCTL_GETMIXER");
+ exit(1);
+ }
+ mixdevice = mixdat.mixer_type;
+ switch (mixdevice) {
+ case SM_MIXER_INVALID:
+ printf("invalid mixer device\n");
+ exit(1);
+ case SM_MIXER_AD1848:
+ if (optind < argc)
+ set_mixer_ad1848(argc - optind, argv + optind);
+ display_mixer_ad1848();
+ break;
+ case SM_MIXER_CRYSTAL:
+ if (optind < argc)
+ set_mixer_ad1848(argc - optind, argv + optind);
+ display_mixer_cs423x();
+ break;
+ case SM_MIXER_CT1335:
+ if (optind < argc)
+ set_mixer_ct1335(argc - optind, argv + optind);
+ display_mixer_ct1335();
+ break;
+ case SM_MIXER_CT1345:
+ if (optind < argc)
+ set_mixer_ct1345(argc - optind, argv + optind);
+ display_mixer_ct1345();
+ break;
+ case SM_MIXER_CT1745:
+ if (optind < argc)
+ set_mixer_ct1745(argc - optind, argv + optind);
+ display_mixer_ct1745();
+ break;
+ default:
+ printf("unknown mixer device %d\n", mixdevice);
+ exit(1);
+ }
+ exit(0);
+}
+
+/* ---------------------------------------------------------------------- */
diff --git a/hdlcutil/usersmdiag.h b/hdlcutil/usersmdiag.h
new file mode 100644
index 0000000..5335002
--- /dev/null
+++ b/hdlcutil/usersmdiag.h
@@ -0,0 +1,118 @@
+/*****************************************************************************/
+
+/*
+ * usersmdiag.h -- Diagnostics interface.
+ *
+ * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch)
+ * Swiss Federal Institute of Technology (ETH), Electronics Lab
+ *
+ * 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.
+ *
+ *
+ * This is the Linux realtime sound output driver
+ */
+
+/*****************************************************************************/
+
+#ifndef _USERSMDIAG_H
+#define _USERSMDIAG_H
+
+/* --------------------------------------------------------------------- */
+
+#define USERSM_KEY_PROJ '0'
+
+/* --------------------------------------------------------------------- */
+
+#define USERSM_CMD_REQ_CHACCESS_PAR 0x00020
+#define USERSM_CMD_ACK_CHACCESS_PAR 0x10021
+#define USERSM_CMD_SET_CHACCESS_PAR 0x00022
+
+#define USERSM_CMD_CALIBRATE 0x00030
+#define USERSM_CMD_REQ_CHANNELSTATE 0x00031
+#define USERSM_CMD_ACK_CHANNELSTATE 0x10032
+
+#define USERSM_CMD_REQ_DIAG 0x00040
+#define USERSM_CMD_ACK_DIAG 0x10041
+
+#define USERSM_CMD_REQ_DRVNAME 0x00050
+#define USERSM_CMD_ACK_DRVNAME 0x10051
+#define USERSM_CMD_REQ_DRVMODE 0x00052
+#define USERSM_CMD_ACK_DRVMODE 0x10053
+
+/*
+ * diagnose modes; same as in <linux/soundmodem.h>
+ */
+#define USERSM_DIAGMODE_OFF 0
+#define USERSM_DIAGMODE_INPUT 1
+#define USERSM_DIAGMODE_DEMOD 2
+#define USERSM_DIAGMODE_CONSTELLATION 3
+
+/*
+ * diagnose flags; same as in <linux/soundmodem.h>
+ */
+#define USERSM_DIAGFLAG_DCDGATE (1<<0)
+#define USERSM_DIAGFLAG_VALID (1<<1)
+
+/* --------------------------------------------------------------------- */
+
+#define DIAGDATALEN 64
+
+/* --------------------------------------------------------------------- */
+
+struct usersmmsg {
+ struct usersm_hdr {
+ long type;
+ unsigned int channel;
+ } hdr;
+ union {
+ struct usersm_chaccess_par {
+ int tx_delay; /* the transmitter keyup delay in 10ms units */
+ int tx_tail; /* the transmitter keyoff delay in 10ms units */
+ int slottime; /* the slottime in 10ms; usually 10 = 100ms */
+ int ppersist; /* the p-persistence 0..255 */
+ int fulldup; /* some driver do not support full duplex, setting */
+ /* this just makes them send even if DCD is on */
+ } cp;
+
+ int calib;
+
+ struct usersm_channel_state {
+ int ptt;
+ int dcd;
+ int ptt_keyed;
+ unsigned long tx_packets;
+ unsigned long tx_errors;
+ unsigned long rx_packets;
+ unsigned long rx_errors;
+ } cs;
+
+ struct usersm_diag {
+ unsigned int mode;
+ unsigned int flags;
+ unsigned int samplesperbit;
+ unsigned int datalen;
+ } diag;
+
+ struct usersm_diag_out {
+ struct usersm_diag diag;
+ short samples[DIAGDATALEN];
+ } diag_out;
+
+ unsigned char by[0];
+ } data;
+};
+
+/* --------------------------------------------------------------------- */
+#endif /* _USERSMDIAG_H */
diff --git a/install-sh b/install-sh
new file mode 100755
index 0000000..e9de238
--- /dev/null
+++ b/install-sh
@@ -0,0 +1,251 @@
+#!/bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5 (mit/util/scripts/install.sh).
+#
+# Copyright 1991 by the Massachusetts Institute of Technology
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation, and that the name of M.I.T. not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission. M.I.T. makes no representations about the
+# suitability of this software for any purpose. It is provided "as is"
+# without express or implied warranty.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch. It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+ case $1 in
+ -c) instcmd="$cpprog"
+ shift
+ continue;;
+
+ -d) dir_arg=true
+ shift
+ continue;;
+
+ -m) chmodcmd="$chmodprog $2"
+ shift
+ shift
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd="$stripprog"
+ shift
+ continue;;
+
+ -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+ shift
+ continue;;
+
+ -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+ shift
+ continue;;
+
+ *) if [ x"$src" = x ]
+ then
+ src=$1
+ else
+ # this colon is to work around a 386BSD /bin/sh bug
+ :
+ dst=$1
+ fi
+ shift
+ continue;;
+ esac
+done
+
+if [ x"$src" = x ]
+then
+ echo "install: no input file specified"
+ exit 1
+else
+ true
+fi
+
+if [ x"$dir_arg" != x ]; then
+ dst=$src
+ src=""
+
+ if [ -d $dst ]; then
+ instcmd=:
+ chmodcmd=""
+ else
+ instcmd=mkdir
+ fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad
+# if $src (and thus $dsttmp) contains '*'.
+
+ if [ -f $src -o -d $src ]
+ then
+ true
+ else
+ echo "install: $src does not exist"
+ exit 1
+ fi
+
+ if [ x"$dst" = x ]
+ then
+ echo "install: no destination specified"
+ exit 1
+ else
+ true
+ fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+ if [ -d $dst ]
+ then
+ dst="$dst"/`basename $src`
+ else
+ true
+ fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+# this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+ pathcomp="${pathcomp}${1}"
+ shift
+
+ if [ ! -d "${pathcomp}" ] ;
+ then
+ $mkdirprog "${pathcomp}"
+ else
+ true
+ fi
+
+ pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+ $doit $instcmd $dst &&
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+ if [ x"$transformarg" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ dstfile=`basename $dst $transformbasename |
+ sed $transformarg`$transformbasename
+ fi
+
+# don't allow the sed command to completely eliminate the filename
+
+ if [ x"$dstfile" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ true
+ fi
+
+# Make a temp file name in the proper directory.
+
+ dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+ $doit $instcmd $src $dsttmp &&
+
+ trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing. If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+ $doit $rmcmd -f $dstdir/$dstfile &&
+ $doit $mvcmd $dsttmp $dstdir/$dstfile
+
+fi &&
+
+
+exit 0
diff --git a/kiss/Makefile.am b/kiss/Makefile.am
new file mode 100644
index 0000000..7a130da
--- /dev/null
+++ b/kiss/Makefile.am
@@ -0,0 +1,8 @@
+
+installconf:
+
+sbin_PROGRAMS = kissattach kissnetd kissparms mkiss net2kiss
+
+man_MANS = kissattach.8 kissnetd.8 kissparms.8 mkiss.8 net2kiss.8
+
+
diff --git a/kiss/Makefile.in b/kiss/Makefile.in
new file mode 100644
index 0000000..883ef04
--- /dev/null
+++ b/kiss/Makefile.in
@@ -0,0 +1,367 @@
+# 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@
+
+sbin_PROGRAMS = kissattach kissnetd kissparms mkiss net2kiss
+
+man_MANS = kissattach.8 kissnetd.8 kissparms.8 mkiss.8 net2kiss.8
+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@
+kissattach_SOURCES = kissattach.c
+kissattach_OBJECTS = kissattach.o
+kissattach_LDADD = $(LDADD)
+kissattach_DEPENDENCIES =
+kissattach_LDFLAGS =
+kissnetd_SOURCES = kissnetd.c
+kissnetd_OBJECTS = kissnetd.o
+kissnetd_LDADD = $(LDADD)
+kissnetd_DEPENDENCIES =
+kissnetd_LDFLAGS =
+kissparms_SOURCES = kissparms.c
+kissparms_OBJECTS = kissparms.o
+kissparms_LDADD = $(LDADD)
+kissparms_DEPENDENCIES =
+kissparms_LDFLAGS =
+mkiss_SOURCES = mkiss.c
+mkiss_OBJECTS = mkiss.o
+mkiss_LDADD = $(LDADD)
+mkiss_DEPENDENCIES =
+mkiss_LDFLAGS =
+net2kiss_SOURCES = net2kiss.c
+net2kiss_OBJECTS = net2kiss.o
+net2kiss_LDADD = $(LDADD)
+net2kiss_DEPENDENCIES =
+net2kiss_LDFLAGS =
+CFLAGS = @CFLAGS@
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+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 = kissattach.c kissnetd.c kissparms.c mkiss.c net2kiss.c
+OBJECTS = kissattach.o kissnetd.o kissparms.o mkiss.o net2kiss.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 kiss/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:
+
+kissattach: $(kissattach_OBJECTS) $(kissattach_DEPENDENCIES)
+ @rm -f kissattach
+ $(LINK) $(kissattach_LDFLAGS) $(kissattach_OBJECTS) $(kissattach_LDADD) $(LIBS)
+
+kissnetd: $(kissnetd_OBJECTS) $(kissnetd_DEPENDENCIES)
+ @rm -f kissnetd
+ $(LINK) $(kissnetd_LDFLAGS) $(kissnetd_OBJECTS) $(kissnetd_LDADD) $(LIBS)
+
+kissparms: $(kissparms_OBJECTS) $(kissparms_DEPENDENCIES)
+ @rm -f kissparms
+ $(LINK) $(kissparms_LDFLAGS) $(kissparms_OBJECTS) $(kissparms_LDADD) $(LIBS)
+
+mkiss: $(mkiss_OBJECTS) $(mkiss_DEPENDENCIES)
+ @rm -f mkiss
+ $(LINK) $(mkiss_LDFLAGS) $(mkiss_OBJECTS) $(mkiss_LDADD) $(LIBS)
+
+net2kiss: $(net2kiss_OBJECTS) $(net2kiss_DEPENDENCIES)
+ @rm -f net2kiss
+ $(LINK) $(net2kiss_LDFLAGS) $(net2kiss_OBJECTS) $(net2kiss_LDADD) $(LIBS)
+
+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-man8
+uninstall-man:
+ @$(NORMAL_UNINSTALL)
+ $(MAKE) $(AM_MAKEFLAGS) 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 = kiss
+
+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
+kissattach.o: kissattach.c ../config.h ../pathnames.h
+kissnetd.o: kissnetd.c
+kissparms.o: kissparms.c ../config.h
+mkiss.o: mkiss.c ../config.h
+net2kiss.o: net2kiss.c
+
+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-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-man
+uninstall: uninstall-am
+all-am: Makefile $(PROGRAMS) $(MANS)
+all-redirect: all-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+installdirs:
+ $(mkinstalldirs) $(DESTDIR)$(sbindir) $(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 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:
+
+# 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/kiss/kissattach.c b/kiss/kissattach.c
new file mode 100644
index 0000000..149c2bd
--- /dev/null
+++ b/kiss/kissattach.c
@@ -0,0 +1,289 @@
+
+#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 <syslog.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+
+#include <net/if.h>
+#include <netax25/ax25.h>
+#include <netrose/rose.h>
+
+#include <netax25/daemon.h>
+#include <netax25/axlib.h>
+#include <netax25/ttyutils.h>
+
+#include <config.h>
+
+#include "../pathnames.h"
+
+static char *callsign;
+static int speed = 0;
+static int mtu = 0;
+static int logging = FALSE;
+
+static void terminate(int sig)
+{
+ if (logging) {
+ syslog(LOG_INFO, "terminating on SIGTERM\n");
+ closelog();
+ }
+
+ exit(0);
+}
+
+static int readconfig(char *port)
+{
+ FILE *fp;
+ char buffer[90], *s;
+ int n = 0;
+
+ if ((fp = fopen(CONF_AXPORTS_FILE, "r")) == NULL) {
+ fprintf(stderr, "kissattach: cannot open axports 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, "kissattach: unable to parse line %d of the axports file\n", n);
+ return FALSE;
+ }
+
+ if (strcmp(s, port) != 0)
+ continue;
+
+ if ((s = strtok(NULL, " \t\r\n")) == NULL) {
+ fprintf(stderr, "kissattach: unable to parse line %d of the axports file\n", n);
+ return FALSE;
+ }
+
+ callsign = strdup(s);
+
+ if ((s = strtok(NULL, " \t\r\n")) == NULL) {
+ fprintf(stderr, "kissattach: unable to parse line %d of the axports file\n", n);
+ return FALSE;
+ }
+
+ speed = atoi(s);
+
+ if ((s = strtok(NULL, " \t\r\n")) == NULL) {
+ fprintf(stderr, "kissattach: unable to parse line %d of the axports file\n", n);
+ return FALSE;
+ }
+
+ if (mtu == 0) {
+ if ((mtu = atoi(s)) <= 0) {
+ fprintf(stderr, "kissattach: invalid paclen setting\n");
+ return FALSE;
+ }
+ }
+
+ fclose(fp);
+
+ return TRUE;
+ }
+
+ fclose(fp);
+
+ fprintf(stderr, "kissattach: cannot find port %s in axports\n", port);
+
+ return FALSE;
+}
+
+
+static int setifcall(int fd, char *name)
+{
+ char call[7];
+
+ if (ax25_aton_entry(name, call) == -1)
+ return FALSE;
+
+ if (ioctl(fd, SIOCSIFHWADDR, call) != 0) {
+ close(fd);
+ perror("kissattach: SIOCSIFHWADDR");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+static int startiface(char *dev, struct hostent *hp)
+{
+ struct ifreq ifr;
+ int fd;
+
+ if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ perror("kissattach: 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("kissattach: SIOCSIFADDR");
+ return FALSE;
+ }
+ }
+
+ ifr.ifr_mtu = mtu;
+
+ if (ioctl(fd, SIOCSIFMTU, &ifr) < 0) {
+ perror("kissattach: SIOCSIFMTU");
+ return FALSE;
+ }
+
+ if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
+ perror("kissattach: 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("kissattach: SIOCSIFFLAGS");
+ return FALSE;
+ }
+
+ close(fd);
+
+ return TRUE;
+}
+
+
+int main(int argc, char *argv[])
+{
+ int fd;
+ int disc = N_AX25;
+ char dev[64];
+ int v = 4;
+ struct hostent *hp = NULL;
+
+ while ((fd = getopt(argc, argv, "i:lm:v")) != -1) {
+ switch (fd) {
+ case 'i':
+ if ((hp = gethostbyname(optarg)) == NULL) {
+ fprintf(stderr, "kissattach: invalid internet name/address - %s\n", optarg);
+ return 1;
+ }
+ break;
+ case 'l':
+ logging = TRUE;
+ break;
+ case 'm':
+ if ((mtu = atoi(optarg)) <= 0) {
+ fprintf(stderr, "kissattach: invalid mtu size - %s\n", optarg);
+ return 1;
+ }
+ break;
+ case 'v':
+ printf("kissattach: %s\n", VERSION);
+ return 0;
+ case ':':
+ case '?':
+ fprintf(stderr, "usage: kissattach [-i inetaddr] [-l] [-m mtu] [-v] ttyinterface port\n");
+ return 1;
+ }
+ }
+
+ if ((argc - optind) != 2) {
+ fprintf(stderr, "usage: kissattach [-i inetaddr] [-l] [-m mtu] [-v] ttyinterface port\n");
+ return 1;
+ }
+
+ if (tty_is_locked(argv[optind])) {
+ fprintf(stderr, "kissattach: device %s already in use\n", argv[optind]);
+ return 1;
+ }
+
+ if (!readconfig(argv[optind + 1]))
+ return 1;
+
+ if ((fd = open(argv[optind], O_RDONLY | O_NONBLOCK)) == -1) {
+ perror("kissattach: open");
+ return 1;
+ }
+
+ if (speed != 0 && !tty_speed(fd, speed))
+ return 1;
+
+ if (ioctl(fd, TIOCSETD, &disc) == -1) {
+ perror("kissattach: TIOCSETD");
+ return 1;
+ }
+
+ if (ioctl(fd, SIOCGIFNAME, dev) == -1) {
+ perror("kissattach: SIOCGIFNAME");
+ return 1;
+ }
+
+ if (!setifcall(fd, callsign))
+ return 1;
+
+ /* Now set the encapsulation */
+ if (ioctl(fd, SIOCSIFENCAP, &v) == -1) {
+ perror("kissattach: SIOCSIFENCAP");
+ return 1;
+ }
+
+ if (!startiface(dev, hp))
+ return 1;
+
+ printf("AX.25 port %s bound to device %s\n", argv[optind + 1], dev);
+
+ if (logging) {
+ openlog("kissattach", LOG_PID, LOG_DAEMON);
+ syslog(LOG_INFO, "AX.25 port %s bound to device %s\n", argv[optind + 1], dev);
+ }
+
+ signal(SIGHUP, SIG_IGN);
+ signal(SIGTERM, terminate);
+
+ /*
+ * Become a daemon if we can.
+ */
+ if (!daemon_start(FALSE)) {
+ fprintf(stderr, "kissattach: cannot become a daemon\n");
+ return 1;
+ }
+
+ if (!tty_lock(argv[optind]))
+ return 1;
+
+ while (1)
+ sleep(10000);
+
+ /* NOT REACHED */
+ return 0;
+}
diff --git a/kiss/kissnetd.c b/kiss/kissnetd.c
new file mode 100644
index 0000000..ff38779
--- /dev/null
+++ b/kiss/kissnetd.c
@@ -0,0 +1,257 @@
+/*
+ * kissnetd.c : Simple kiss broadcast daemon between several
+ * pseudo-tty devices.
+ * Each kiss frame received on one pty is broadcasted
+ * to each other one.
+ *
+ * ATEPRA FPAC/Linux Project
+ *
+ * F1OAT 960804 - Frederic RIBLE
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <strings.h>
+#include <errno.h>
+#include <syslog.h>
+#include <time.h>
+
+static char *Version = "1.5";
+static int VerboseMode = 0;
+static int MaxFrameSize = 512;
+
+#define REOPEN_TIMEOUT 30 /* try tio reopen every 10 s */
+
+struct PortDescriptor {
+ char Name[80];
+ int Fd;
+ unsigned char *FrameBuffer;
+ int BufferIndex;
+ time_t TimeLastOpen;
+};
+
+static struct PortDescriptor *PortList[FD_SETSIZE];
+static int NbPort = 0;
+
+static void Usage(void)
+{
+ fprintf(stderr, "\nUsage : kissnetd [-v] [-f size] /dev/pty?? [/dev/pty??]*\n");
+ fprintf(stderr, " -v : Verbose mode, trace on stdout\n");
+ fprintf(stderr, " -f size : Set max frame size to size bytes (default 512)\n");
+ exit(1);
+}
+
+static void Banner(int Small)
+{
+ if (Small) {
+ printf("kissnetd V %s by Frederic RIBLE F1OAT - ATEPRA FPAC/Linux Project\n", Version);
+ }
+ else {
+ printf("****************************************\n");
+ printf("* Network broadcast between kiss ports *\n");
+ printf("* ATEPRA FPAC/Linux Project *\n");
+ printf("****************************************\n");
+ printf("* kissnetd Version %-4s *\n", Version);
+ printf("* by Frederic RIBLE F1OAT *\n");
+ printf("****************************************\n");
+ }
+}
+
+static void NewPort(char *Name)
+{
+ struct PortDescriptor *MyPort;
+
+ if (VerboseMode) {
+ printf("Opening port %s\n", Name);
+ }
+
+ if (NbPort == FD_SETSIZE) {
+ fprintf(stderr, "Cannot handle %s : too many ports\n", Name);
+ exit(1);
+ }
+
+ MyPort = calloc(sizeof(struct PortDescriptor), 1);
+ if (MyPort) MyPort->FrameBuffer = calloc(sizeof (unsigned char), MaxFrameSize);
+ if (!MyPort || !MyPort->FrameBuffer) {
+ perror("cannot allocate port descriptor");
+ exit(1);
+ }
+
+ strncpy(MyPort->Name, Name, sizeof(MyPort->Name));
+ MyPort->Fd = -1;
+ MyPort->FrameBuffer[0] = 0xC0;
+ MyPort->BufferIndex = 1;
+ PortList[NbPort++] = MyPort;
+}
+
+static void ReopenPort(int PortNumber)
+{
+ char MyString[80];
+
+ PortList[PortNumber]->TimeLastOpen = time(NULL);
+
+ if (VerboseMode) {
+ printf("Reopening port %d\n", PortNumber);
+ }
+
+ syslog(LOG_WARNING, "kissnetd : Opening port %s\n", PortList[PortNumber]->Name);
+
+ PortList[PortNumber]->Fd = open(PortList[PortNumber]->Name, O_RDWR | O_NONBLOCK);
+ if (PortList[PortNumber]->Fd < 0) {
+ syslog(LOG_WARNING, "kissnetd : Error opening port %s : %s\n",
+ PortList[PortNumber]->Name, sys_errlist[errno]);
+ if (VerboseMode) {
+ sprintf(MyString, "cannot reopen %s", PortList[PortNumber]->Name);
+ perror(MyString);
+ }
+ }
+}
+
+static void TickReopen(void)
+{
+ int i;
+ time_t CurrentTime = time(NULL);
+
+ for (i=0; i<NbPort; i++) {
+ if (PortList[i]->Fd >= 0) continue;
+ if ( (CurrentTime - PortList[i]->TimeLastOpen) > REOPEN_TIMEOUT ) ReopenPort(i);
+ }
+}
+
+static void Broadcast(int InputPort)
+{
+ int i;
+ int rc;
+
+ /* Broadcast only info frames */
+
+ if (PortList[InputPort]->FrameBuffer[1] != 0x00) return;
+
+ for (i=0; i<NbPort; i++) {
+ if (i == InputPort) continue;
+ if (PortList[i]->Fd < 0) continue;
+ rc = write(PortList[i]->Fd,
+ PortList[InputPort]->FrameBuffer,
+ PortList[InputPort]->BufferIndex);
+ if (VerboseMode) {
+ printf("Sending %d bytes on port %d : rc=%d\n",
+ PortList[InputPort]->BufferIndex,
+ i, rc);
+ }
+ }
+}
+
+static void ProcessInput(int PortNumber)
+{
+ static unsigned char MyBuffer[2048];
+ int Length;
+ int i;
+ struct PortDescriptor *MyPort = PortList[PortNumber];
+
+ Length = read(MyPort->Fd, MyBuffer, sizeof(MyBuffer));
+ if (VerboseMode) {
+ printf("Read port %d : rc=%d\n", PortNumber, Length);
+ }
+ if (!Length) return;
+ if (Length < 0) {
+ syslog(LOG_WARNING, "kissnetd : Error reading port %s : %s\n",
+ PortList[PortNumber]->Name, sys_errlist[errno]);
+ if (VerboseMode) perror("read");
+ close(MyPort->Fd);
+ MyPort->Fd = -1;
+ return;
+ }
+ for (i=0; i<Length; i++) {
+ if (MyPort->BufferIndex == MaxFrameSize) {
+ if (MyBuffer[i] == 0xC0) {
+ if (VerboseMode) printf("Drop frame too long\n");
+ MyPort->BufferIndex = 1;
+ }
+ }
+ else {
+ MyPort->FrameBuffer[MyPort->BufferIndex++] = MyBuffer[i];
+ if (MyBuffer[i] == 0xC0) {
+ Broadcast(PortNumber);
+ MyPort->BufferIndex = 1;
+ }
+ }
+ }
+}
+
+static void ProcessPortList(void)
+{
+ static fd_set MyFdSet;
+ int i, rc;
+ struct timeval Timeout;
+
+ Timeout.tv_sec = 1;
+ Timeout.tv_usec = 0;
+
+ FD_ZERO(&MyFdSet);
+ for (i=0; i<NbPort; i++) {
+ if (PortList[i]->Fd >= 0) FD_SET(PortList[i]->Fd, &MyFdSet);
+ }
+ rc = select(FD_SETSIZE, &MyFdSet, NULL, NULL, &Timeout);
+
+ if (VerboseMode) printf("select : rc=%d\n", rc);
+ if (!rc ) TickReopen();
+
+ if (rc > 0) {
+ for (i=0; i<NbPort && rc; i++) {
+ if (PortList[i]->Fd < 0) continue;
+ if (FD_ISSET(PortList[i]->Fd, &MyFdSet)) {
+ ProcessInput(i);
+ rc--;
+ }
+ }
+ }
+}
+
+static void ProcessArgv(char *argv[])
+{
+ char *Opt;
+ int ArgvIndex = 0;
+
+ while (argv[ArgvIndex]) {
+ if (argv[ArgvIndex][0] != '-') {
+ NewPort(argv[ArgvIndex++]);
+ continue;
+ }
+ for (Opt = &argv[ArgvIndex++][1]; *Opt; Opt++) {
+ switch (*Opt) {
+ case 'v':
+ VerboseMode = 1;
+ break;
+ case 'f':
+ MaxFrameSize = atoi(argv[ArgvIndex++]);
+ break;
+ default:
+ fprintf(stderr, "Invalid option %c\n", *Opt);
+ Usage();
+ break;
+ }
+ }
+
+ }
+}
+
+
+int main(int argc, char *argv[])
+{
+ if (argc < 2) {
+ Banner(0);
+ Usage();
+ }
+ else {
+ Banner(1);
+ }
+
+ ProcessArgv(argv+1);
+ while (1) ProcessPortList();
+ return 0;
+}
diff --git a/kiss/kissparms.c b/kiss/kissparms.c
new file mode 100644
index 0000000..0a1a101
--- /dev/null
+++ b/kiss/kissparms.c
@@ -0,0 +1,221 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <net/ethernet.h>
+
+#include <netax25/ax25.h>
+#include <netax25/axconfig.h>
+
+#include <config.h>
+
+#define PARAM_TXDELAY 1
+#define PARAM_PERSIST 2
+#define PARAM_SLOTTIME 3
+#define PARAM_TXTAIL 4
+#define PARAM_FULLDUP 5
+#define PARAM_HARDWARE 6
+#define PARAM_FECLEVEL 8
+#define PARAM_RETURN 255
+
+#define USAGE "usage: kissparms -p <port> [-f y|n] [-h hw] [-l txtail] \
+ [-r pers ] [-s slot] [-t txd] [-e feclevel] [-v] [-x]\n"
+
+int main(int argc, char *argv[])
+{
+ unsigned char buffer[2];
+ struct sockaddr sa;
+ int proto = ETH_P_AX25;
+ int txdelay = -1;
+ int txtail = -1;
+ int persist = -1;
+ int slottime = -1;
+ int fulldup = -1;
+ int hardware = -1;
+ int feclevel = -1;
+ int kissoff = 0;
+ int buflen, s;
+ char *port = NULL;
+
+ if (ax25_config_load_ports() == 0) {
+ fprintf(stderr, "kissparms: no AX.25 ports configured\n");
+ return 1;
+ }
+
+ while ((s = getopt(argc, argv, "e:f:h:l:p:r:s:t:vx")) != -1) {
+ switch (s) {
+ case 'e':
+ feclevel = atoi(optarg);
+ if (feclevel < 0 || feclevel > 3) {
+ fprintf(stderr, "kissparms: invalid FEC level value\n");
+ return 1;
+ }
+ break;
+
+ case 'f':
+ if (*optarg != 'y' && *optarg != 'n') {
+ fprintf(stderr, "kissparms: invalid full duplex setting\n");
+ return 1;
+ }
+ fulldup = *optarg == 'y';
+ break;
+
+ case 'l':
+ txtail = atoi(optarg) / 10;
+ if (txtail < 0 || txtail > 255) {
+ fprintf(stderr, "kissparms: invalid txtail value\n");
+ return 1;
+ }
+ break;
+
+
+ case 'h':
+ hardware = atoi(optarg);
+ if (hardware < 0 || hardware > 255) {
+ fprintf(stderr, "kissparms: invalid hardware value\n");
+ return 1;
+ }
+ break;
+
+ case 'p':
+ port = optarg;
+ if (ax25_config_get_addr(port) == NULL) {
+ fprintf(stderr, "kissparms: invalid port name - %s\n", port);
+ return 1;
+ }
+ break;
+
+ case 'r':
+ persist = atoi(optarg);
+ if (persist < 0 || persist > 255) {
+ fprintf(stderr, "kissparms: invalid persist value\n");
+ return 1;
+ }
+ break;
+
+ case 's':
+ slottime = atoi(optarg) / 10;
+ if (slottime < 0 || slottime > 255) {
+ fprintf(stderr, "kissparms: invalid slottime value\n");
+ return 1;
+ }
+ break;
+
+ case 't':
+ txdelay = atoi(optarg) / 10;
+ if (txdelay < 0 || txdelay > 255) {
+ fprintf(stderr, "kissparms: invalid txdelay value\n");
+ return 1;
+ }
+ break;
+
+ case 'v':
+ printf("kissparms: %s\n", VERSION);
+ return 0;
+
+ case 'x':
+ kissoff = 1;
+ break;
+
+ case ':':
+ case '?':
+ fprintf(stderr, USAGE);
+ return 1;
+ }
+ }
+
+ if (port == NULL) {
+ fprintf(stderr, USAGE);
+ return 1;
+ }
+
+ if ((s = socket(AF_INET, SOCK_PACKET, htons(proto))) < 0) {
+ perror("kissparms: socket");
+ return 1;
+ }
+
+ strcpy(sa.sa_data, ax25_config_get_dev(port));
+
+ if (kissoff) {
+ buffer[0] = PARAM_RETURN;
+ buflen = 1;
+ if (sendto(s, buffer, buflen, 0, &sa, sizeof(struct sockaddr)) == -1) {
+ perror("kissparms: sendto");
+ return 1;
+ }
+ } else {
+ if (txdelay != -1) {
+ buffer[0] = PARAM_TXDELAY;
+ buffer[1] = txdelay;
+ buflen = 2;
+ if (sendto(s, buffer, buflen, 0, &sa, sizeof(struct sockaddr)) == -1) {
+ perror("kissparms: sendto");
+ return 1;
+ }
+ }
+ if (txtail != -1) {
+ buffer[0] = PARAM_TXTAIL;
+ buffer[1] = txtail;
+ buflen = 2;
+ if (sendto(s, buffer, buflen, 0, &sa, sizeof(struct sockaddr)) == -1) {
+ perror("kissparms: sendto");
+ return 1;
+ }
+ }
+ if (persist != -1) {
+ buffer[0] = PARAM_PERSIST;
+ buffer[1] = persist;
+ buflen = 2;
+ if (sendto(s, buffer, buflen, 0, &sa, sizeof(struct sockaddr)) == -1) {
+ perror("kissparms: sendto");
+ return 1;
+ }
+ }
+ if (slottime != -1) {
+ buffer[0] = PARAM_SLOTTIME;
+ buffer[1] = slottime;
+ buflen = 2;
+ if (sendto(s, buffer, buflen, 0, &sa, sizeof(struct sockaddr)) == -1) {
+ perror("kissparms: sendto");
+ return 1;
+ }
+ }
+ if (fulldup != -1) {
+ buffer[0] = PARAM_FULLDUP;
+ buffer[1] = fulldup;
+ buflen = 2;
+ if (sendto(s, buffer, buflen, 0, &sa, sizeof(struct sockaddr)) == -1) {
+ perror("kissparms: sendto");
+ return 1;
+ }
+ }
+ if (hardware != -1) {
+ buffer[0] = PARAM_HARDWARE;
+ buffer[1] = hardware;
+ buflen = 2;
+ if (sendto(s, buffer, buflen, 0, &sa, sizeof(struct sockaddr)) == -1) {
+ perror("kissparms: sendto");
+ return 1;
+ }
+ }
+
+ if (feclevel != -1) {
+ buffer[0] = PARAM_FECLEVEL;
+ buffer[1] = feclevel;
+
+ buflen = 2;
+ if (sendto(s, buffer, buflen, 0, &sa, sizeof(struct sockaddr)) == -1) {
+ perror("kissparms: sendto");
+ return 1;
+ }
+ }
+ }
+
+ close(s);
+
+ return 0;
+}
diff --git a/kiss/mkiss.c b/kiss/mkiss.c
new file mode 100644
index 0000000..8621ce4
--- /dev/null
+++ b/kiss/mkiss.c
@@ -0,0 +1,512 @@
+/*
+ * mkiss.c
+ * Fake out AX.25 code into supporting dual port TNCS by routing serial
+ * port data to/from two pseudo ttys.
+ *
+ * Version 1.03
+ *
+ * N0BEL
+ * Kevin Uhlir
+ * kevinu@flochart.com
+ *
+ * 1.01 12/30/95 Ron Curry - Fixed FD_STATE bug where FD_STATE was being used for
+ * three state machines causing spurious writes to wrong TNC port. FD_STATE is
+ * now used for real serial port, FD0_STATE for first psuedo tty, and FD1_STATE
+ * for second psuedo tty. This was an easy fix but a MAJOR bug.
+ *
+ * 1.02 3/1/96 Jonathan Naylor - Make hardware handshaking default to off.
+ * Allowed for true multiplexing of the data from the two pseudo ttys.
+ * Numerous formatting changes.
+ *
+ * 1.03 4/20/96 Tomi Manninen - Rewrote KISS en/decapsulation (much of the
+ * code taken from linux/drivers/net/slip.c). Added support for all the 16
+ * possible kiss ports and G8BPQ-style checksumming on ttyinterface. Now
+ * mkiss also sends a statistic report to stderr if a SIGUSR1 is sent to it.
+ *
+ * 1.04 25/5/96 Jonathan Naylor - Added check for UUCP style tty lock files.
+ * As they are now supported by kissattach as well.
+ *
+ * 1.05 20/8/96 Jonathan Naylor - Convert to becoming a daemon and added
+ * system logging.
+ *
+ * 1.06 23/11/96 Tomi Manninen - Added simple support for polled kiss.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <termios.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <ctype.h>
+#include <syslog.h>
+
+#include <netax25/ttyutils.h>
+#include <netax25/daemon.h>
+
+#include <config.h>
+
+#define SIZE 4096
+
+#define FEND 0300 /* Frame End (0xC0) */
+#define FESC 0333 /* Frame Escape (0xDB) */
+#define TFEND 0334 /* Transposed Frame End (0xDC) */
+#define TFESC 0335 /* Transposed Frame Escape (0xDD) */
+
+#define POLL 0x0E
+
+/*
+ * Keep these off the stack.
+ */
+static unsigned char ibuf[SIZE]; /* buffer for input operations */
+static unsigned char obuf[SIZE]; /* buffer for kiss_tx() */
+
+static int crc_errors = 0;
+static int invalid_ports = 0;
+static int return_polls = 0;
+
+static char *usage_string = "usage: mkiss [-p] [-c] [-h] [-l] [-s speed] [-v] ttyinterface pty ...\n";
+
+static int dump_report = FALSE;
+
+static int logging = FALSE;
+static int crcflag = FALSE;
+static int hwflag = FALSE;
+static int pollflag = FALSE;
+
+struct iface
+{
+ char *name; /* Interface name (/dev/???) */
+ int fd; /* File descriptor */
+ int escaped; /* FESC received? */
+ unsigned char crc; /* Incoming frame crc */
+ unsigned char obuf[SIZE]; /* TX buffer */
+ unsigned char *optr; /* Next byte to transmit */
+ unsigned int errors; /* KISS protocol error count */
+ unsigned int nondata; /* Non-data frames rx count */
+ unsigned int rxpackets; /* RX frames count */
+ unsigned int txpackets; /* TX frames count */
+ unsigned long rxbytes; /* RX bytes count */
+ unsigned long txbytes; /* TX bytes count */
+};
+
+static int poll(int fd, int ports)
+{
+ char buffer[3];
+ static int port = 0;
+
+ buffer[0] = FEND;
+ buffer[1] = POLL | (port << 4);
+ buffer[2] = FEND;
+ if (write(fd, buffer, 3) == -1) {
+ perror("mkiss: poll: write");
+ return 1;
+ }
+ if (++port >= ports)
+ port = 0;
+ return 0;
+}
+
+static int kiss_tx(int fd, int port, unsigned char *s, int len, int usecrc)
+{
+ unsigned char *ptr = obuf;
+ unsigned char c;
+ unsigned char crc = 0;
+ int first = TRUE;
+
+ /* Non-data frames don't get a checksum byte */
+ if ((s[0] & 0x0F) != 0)
+ usecrc = FALSE;
+
+ /* Allow for checksum byte */
+ if (usecrc)
+ len++;
+
+ /*
+ * Send an initial FEND character to flush out any
+ * data that may have accumulated in the receiver
+ * due to line noise.
+ */
+
+ *ptr++ = FEND;
+
+ /*
+ * For each byte in the packet, send the appropriate
+ * character sequence, according to the SLIP protocol.
+ */
+
+ while (len-- > 0) {
+ c = *s++;
+ if (first) { /* Control byte */
+ c = (c & 0x0F) | (port << 4);
+ first = FALSE;
+ }
+ if (usecrc) {
+ if (len == 0) /* Now past user data... */
+ c = crc; /* ...time to encode cksum */
+ else
+ crc ^= c; /* Adjust checksum */
+ }
+ switch (c) {
+ case FEND:
+ *ptr++ = FESC;
+ *ptr++ = TFEND;
+ break;
+ case FESC:
+ *ptr++ = FESC;
+ *ptr++ = TFESC;
+ break;
+ default:
+ *ptr++ = c;
+ break;
+ }
+ }
+ *ptr++ = FEND;
+ return write(fd, obuf, ptr - obuf);
+}
+
+static int kiss_rx(struct iface *ifp, unsigned char c, int usecrc)
+{
+ int len;
+
+ switch (c) {
+ case FEND:
+ len = ifp->optr - ifp->obuf;
+ if (len != 0 && ifp->escaped) { /* protocol error... */
+ len = 0; /* ...drop frame */
+ ifp->errors++;
+ }
+ if (len != 0 && (ifp->obuf[0] & 0x0F) != 0) {
+ /*
+ * Non-data frames don't have checksum.
+ */
+ usecrc = 0;
+ if ((ifp->obuf[0] & 0x0F) == POLL) {
+ len = 0; /* drop returned polls */
+ return_polls++;
+ } else
+ ifp->nondata++;
+ }
+ if (len != 0 && usecrc) {
+ if (ifp->crc != 0) { /* checksum failed... */
+ len = 0; /* ...drop frame */
+ crc_errors++;
+ } else
+ len--; /* delete checksum byte */
+ }
+ if (len != 0) {
+ ifp->rxpackets++;
+ ifp->rxbytes += len;
+ }
+ /*
+ * Clean up.
+ */
+ ifp->optr = ifp->obuf;
+ ifp->crc = 0;
+ ifp->escaped = FALSE;
+ return len;
+ case FESC:
+ ifp->escaped = TRUE;
+ return 0;
+ case TFESC:
+ if (ifp->escaped) {
+ ifp->escaped = FALSE;
+ c = FESC;
+ }
+ break;
+ case TFEND:
+ if (ifp->escaped) {
+ ifp->escaped = FALSE;
+ c = FEND;
+ }
+ break;
+ default:
+ if (ifp->escaped) { /* protocol error... */
+ ifp->escaped = FALSE;
+ ifp->errors++;
+ }
+ break;
+ }
+ *ifp->optr++ = c;
+ if (usecrc)
+ ifp->crc ^= c;
+ return 0;
+}
+
+static void sigterm_handler(int sig)
+{
+ if (logging) {
+ syslog(LOG_INFO, "terminating on SIGTERM\n");
+ closelog();
+ }
+
+ exit(0);
+}
+
+static void sigusr1_handler(int sig)
+{
+ signal(SIGUSR1, sigusr1_handler);
+ dump_report = TRUE;
+}
+
+static void report(struct iface *tty, struct iface **pty, int numptys)
+{
+ int i;
+ long t;
+
+ time(&t);
+ syslog(LOG_INFO, "version %s.", VERSION);
+ syslog(LOG_INFO, "Status report at %s", ctime(&t));
+ syslog(LOG_INFO, "Hardware handshaking %sabled.",
+ hwflag ? "en" : "dis");
+ syslog(LOG_INFO, "G8BPQ checksumming %sabled.",
+ crcflag ? "en" : "dis");
+ syslog(LOG_INFO, "polling %sabled.",
+ pollflag ? "en" : "dis");
+ syslog(LOG_INFO, "ttyinterface is %s (fd=%d)", tty->name, tty->fd);
+ for (i = 0; i < numptys; i++)
+ syslog(LOG_INFO, "pty%d is %s (fd=%d)", i, pty[i]->name,
+ pty[i]->fd);
+ syslog(LOG_INFO, "Checksum errors: %d", crc_errors);
+ syslog(LOG_INFO, "Invalid ports: %d", invalid_ports);
+ syslog(LOG_INFO, "Returned polls: %d", return_polls);
+ syslog(LOG_INFO, "Interface TX frames TX bytes RX frames RX bytes Errors");
+ syslog(LOG_INFO, "%-11s %-9u %-9lu %-9u %-9lu %u",
+ tty->name,
+ tty->txpackets, tty->txbytes,
+ tty->rxpackets, tty->rxbytes,
+ tty->errors);
+ for (i = 0; i < numptys; i++) {
+ syslog(LOG_INFO, "%-11s %-9u %-9lu %-9u %-9lu %u",
+ pty[i]->name,
+ pty[i]->txpackets, pty[i]->txbytes,
+ pty[i]->rxpackets, pty[i]->rxbytes,
+ pty[i]->errors);
+ }
+ return;
+}
+
+int main(int argc, char *argv[])
+{
+ struct iface *pty[16];
+ struct iface *tty;
+ unsigned char *icp;
+ int topfd;
+ fd_set readfd;
+ struct timeval timeout;
+ int retval, numptys, i, size, len;
+ int speed = -1;
+
+ while ((size = getopt(argc, argv, "chlps:v")) != -1) {
+ switch (size) {
+ case 'c':
+ crcflag = TRUE;
+ break;
+ case 'h':
+ hwflag = TRUE;
+ break;
+ case 'l':
+ logging = TRUE;
+ break;
+ case 'p':
+ pollflag = TRUE;
+ break;
+ case 's':
+ speed = atoi(optarg);
+ break;
+ case 'v':
+ printf("mkiss: %s\n", VERSION);
+ return 1;
+ case ':':
+ case '?':
+ fprintf(stderr, usage_string);
+ return 1;
+ }
+ }
+
+ if ((argc - optind) < 2) {
+ fprintf(stderr, usage_string);
+ return 1;
+ }
+ if ((numptys = argc - optind - 1) > 16) {
+ fprintf(stderr, "mkiss: max 16 pty interfaces allowed.\n");
+ return 1;
+ }
+
+ /*
+ * Check for lock files before opening any TTYs
+ */
+ if (tty_is_locked(argv[optind])) {
+ fprintf(stderr, "mkiss: tty %s is locked by another process\n", argv[optind]);
+ return 1;
+ }
+ for (i = 0; i < numptys; i++) {
+ if (tty_is_locked(argv[optind + i + 1])) {
+ fprintf(stderr, "mkiss: tty %s is locked by another process\n", argv[optind + i + 1]);
+ return 1;
+ }
+ }
+
+ /*
+ * Open and configure the tty interface. Open() is
+ * non-blocking so it won't block regardless of the modem
+ * status lines.
+ */
+ if ((tty = calloc(1, sizeof(struct iface))) == NULL) {
+ perror("mkiss: malloc");
+ return 1;
+ }
+
+ if ((tty->fd = open(argv[optind], O_RDWR | O_NDELAY)) == -1) {
+ perror("mkiss: open");
+ return 1;
+ }
+
+ tty->name = argv[optind];
+ tty_raw(tty->fd, hwflag);
+ if (speed != -1) tty_speed(tty->fd, speed);
+ tty->optr = tty->obuf;
+ topfd = tty->fd;
+ /*
+ * Make it block again...
+ */
+ fcntl(tty->fd, F_SETFL, 0);
+
+ /*
+ * Open and configure the pty interfaces
+ */
+ for (i = 0; i < numptys; i++) {
+ if ((pty[i] = calloc(1, sizeof(struct iface))) == NULL) {
+ perror("mkiss: malloc");
+ return 1;
+ }
+ if ((pty[i]->fd = open(argv[optind + i + 1], O_RDWR)) == -1) {
+ perror("mkiss: open");
+ return 1;
+ }
+ pty[i]->name = argv[optind + i + 1];
+ tty_raw(pty[i]->fd, FALSE);
+ pty[i]->optr = pty[i]->obuf;
+ topfd = (pty[i]->fd > topfd) ? pty[i]->fd : topfd;
+ }
+
+ /*
+ * Now all the ports are open, lock them.
+ */
+ tty_lock(argv[optind]);
+ for (i = 0; i < numptys; i++)
+ tty_lock(argv[optind + i + 1]);
+
+ signal(SIGHUP, SIG_IGN);
+ signal(SIGUSR1, sigusr1_handler);
+ signal(SIGTERM, sigterm_handler);
+
+ if (!daemon_start(FALSE)) {
+ fprintf(stderr, "mkiss: cannot become a daemon\n");
+ return 1;
+ }
+
+ if (logging) {
+ openlog("mkiss", LOG_PID, LOG_DAEMON);
+ syslog(LOG_INFO, "starting");
+ }
+
+ /*
+ * Loop until an error occurs on a read.
+ */
+ while (TRUE) {
+ FD_ZERO(&readfd);
+ FD_SET(tty->fd, &readfd);
+ for (i = 0; i < numptys; i++)
+ FD_SET(pty[i]->fd, &readfd);
+
+ if (pollflag) {
+ timeout.tv_sec = 1;
+ timeout.tv_usec = 0;
+ }
+
+ errno = 0;
+ retval = select(topfd + 1, &readfd, NULL, NULL, pollflag ? &timeout : NULL);
+
+ if (retval == -1) {
+ if (dump_report) {
+ if (logging)
+ report(tty, pty, numptys);
+ dump_report = FALSE;
+ continue;
+ } else {
+ perror("mkiss: select");
+ continue;
+ }
+ }
+
+ /*
+ * Timer expired.
+ */
+ if (retval == 0 && pollflag) {
+ poll(tty->fd, numptys);
+ continue;
+ }
+
+ /*
+ * A character has arrived on the ttyinterface.
+ */
+ if (FD_ISSET(tty->fd, &readfd)) {
+ if ((size = read(tty->fd, ibuf, SIZE)) < 0 && errno != EINTR) {
+ if (logging)
+ syslog(LOG_ERR, "tty->fd: %m");
+ break;
+ }
+ for (icp = ibuf; size > 0; size--, icp++) {
+ if ((len = kiss_rx(tty, *icp, crcflag)) != 0) {
+ if ((i = (*tty->obuf & 0xF0) >> 4) < numptys) {
+ kiss_tx(pty[i]->fd, 0, tty->obuf, len, FALSE);
+ pty[i]->txpackets++;
+ pty[i]->txbytes += len;
+ } else
+ invalid_ports++;
+ if (pollflag)
+ poll(tty->fd, numptys);
+ }
+ }
+ }
+
+ for (i = 0; i < numptys; i++) {
+ /*
+ * A character has arrived on pty[i].
+ */
+ if (FD_ISSET(pty[i]->fd, &readfd)) {
+ if ((size = read(pty[i]->fd, ibuf, SIZE)) < 0 && errno != EINTR) {
+ if (logging)
+ syslog(LOG_ERR, "pty[%d]->fd: %m\n", i);
+ goto end;
+ }
+ for (icp = ibuf; size > 0; size--, icp++) {
+ if ((len = kiss_rx(pty[i], *icp, FALSE)) != 0) {
+ kiss_tx(tty->fd, i, pty[i]->obuf, len, crcflag);
+ tty->txpackets++;
+ tty->txbytes += len;
+ }
+ }
+ }
+ }
+ }
+
+ end:
+ if (logging)
+ closelog();
+
+ close(tty->fd);
+ free(tty);
+
+ for (i = 0; i < numptys; i++) {
+ close(pty[i]->fd);
+ free(pty[i]);
+ }
+
+ return 1;
+}
diff --git a/kiss/net2kiss.c b/kiss/net2kiss.c
new file mode 100644
index 0000000..19a7385
--- /dev/null
+++ b/kiss/net2kiss.c
@@ -0,0 +1,643 @@
+/*****************************************************************************/
+
+/*
+ * net2kiss.c - convert a network interface to KISS data stream
+ *
+ * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch)
+ *
+ * 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.
+ *
+ * Please note that the GPL allows you to use the driver, NOT the radio.
+ * In order to use the radio, you need a license from the communications
+ * authority of your country.
+ *
+ *
+ * History:
+ * 0.1 18.09.96 Started
+ */
+
+/*****************************************************************************/
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <asm/byteorder.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <grp.h>
+#include <string.h>
+#include <termios.h>
+
+#include <sys/socket.h>
+#include <net/if.h>
+#include <net/ethernet.h>
+
+/* --------------------------------------------------------------------- */
+
+static int fdif, fdpty;
+static struct ifreq ifr;
+static char *progname;
+static int verbose = 0;
+
+/* --------------------------------------------------------------------- */
+
+static void die(char *func)
+{
+ fprintf(stderr, "%s: %s (%i)%s%s\n", progname, strerror(errno),
+ errno, func ? " in " : "", func ? func : "");
+ exit(-1);
+}
+
+/* --------------------------------------------------------------------- */
+
+static void display_packet(unsigned char *bp, unsigned int len)
+{
+ unsigned char v1=1,cmd=0;
+ unsigned char i,j;
+
+ if (!bp || !len)
+ return;
+ if (len < 8)
+ return;
+ if (bp[1] & 1) {
+ /*
+ * FlexNet Header Compression
+ */
+ v1 = 0;
+ cmd = (bp[1] & 2) != 0;
+ printf("fm ? to ");
+ i = (bp[2] >> 2) & 0x3f;
+ if (i)
+ printf("%c",i+0x20);
+ i = ((bp[2] << 4) | ((bp[3] >> 4) & 0xf)) & 0x3f;
+ if (i)
+ printf("%c",i+0x20);
+ i = ((bp[3] << 2) | ((bp[4] >> 6) & 3)) & 0x3f;
+ if (i)
+ printf("%c",i+0x20);
+ i = bp[4] & 0x3f;
+ if (i)
+ printf("%c",i+0x20);
+ i = (bp[5] >> 2) & 0x3f;
+ if (i)
+ printf("%c",i+0x20);
+ i = ((bp[5] << 4) | ((bp[6] >> 4) & 0xf)) & 0x3f;
+ if (i)
+ printf("%c",i+0x20);
+ printf("-%u QSO Nr %u", bp[6] & 0xf, (bp[0] << 6) |
+ (bp[1] >> 2));
+ bp += 7;
+ len -= 7;
+ } else {
+ /*
+ * normal header
+ */
+ if (len < 15)
+ return;
+ if ((bp[6] & 0x80) != (bp[13] & 0x80)) {
+ v1 = 0;
+ cmd = (bp[6] & 0x80);
+ }
+ printf("fm ");
+ for(i = 7; i < 13; i++)
+ if ((bp[i] &0xfe) != 0x40)
+ printf("%c",bp[i] >> 1);
+ printf("-%u to ",(bp[13] >> 1) & 0xf);
+ for(i = 0; i < 6; i++)
+ if ((bp[i] &0xfe) != 0x40)
+ printf("%c",bp[i] >> 1);
+ printf("-%u",(bp[6] >> 1) & 0xf);
+ bp += 14;
+ len -= 14;
+ if ((!(bp[-1] & 1)) && (len >= 7)) printf(" via ");
+ while ((!(bp[-1] & 1)) && (len >= 7)) {
+ for(i = 0; i < 6; i++)
+ if ((bp[i] &0xfe) != 0x40)
+ printf("%c",bp[i] >> 1);
+ printf("-%u",(bp[6] >> 1) & 0xf);
+ bp += 7;
+ len -= 7;
+ if ((!(bp[-1] & 1)) && (len >= 7))
+ printf(",");
+ }
+ }
+ if(!len)
+ return;
+ i = *bp++;
+ len--;
+ j = v1 ? ((i & 0x10) ? '!' : ' ') :
+ ((i & 0x10) ? (cmd ? '+' : '-') : (cmd ? '^' : 'v'));
+ if (!(i & 1)) {
+ /*
+ * Info frame
+ */
+ printf(" I%u%u%c",(i >> 5) & 7,(i >> 1) & 7,j);
+ } else if (i & 2) {
+ /*
+ * U frame
+ */
+ switch (i & (~0x10)) {
+ case 0x03:
+ printf(" UI%c",j);
+ break;
+ case 0x2f:
+ printf(" SABM%c",j);
+ break;
+ case 0x43:
+ printf(" DISC%c",j);
+ break;
+ case 0x0f:
+ printf(" DM%c",j);
+ break;
+ case 0x63:
+ printf(" UA%c",j);
+ break;
+ case 0x87:
+ printf(" FRMR%c",j);
+ break;
+ default:
+ printf(" unknown U (0x%x)%c",i & (~0x10),j);
+ break;
+ }
+ } else {
+ /*
+ * supervisory
+ */
+ switch (i & 0xf) {
+ case 0x1:
+ printf(" RR%u%c",(i >> 5) & 7,j);
+ break;
+ case 0x5:
+ printf(" RNR%u%c",(i >> 5) & 7,j);
+ break;
+ case 0x9:
+ printf(" REJ%u%c",(i >> 5) & 7,j);
+ break;
+ default:
+ printf(" unknown S (0x%x)%u%c", i & 0xf,
+ (i >> 5) & 7, j);
+ break;
+ }
+ }
+ if (!len) {
+ printf("\n");
+ return;
+ }
+ printf(" pid=%02X\n", *bp++);
+ len--;
+ j = 0;
+ while (len) {
+ i = *bp++;
+ if ((i >= 32) && (i < 128))
+ printf("%c",i);
+ else if (i == 13) {
+ if (j)
+ printf("\n");
+ j = 0;
+ } else
+ printf(".");
+ if (i >= 32)
+ j = 1;
+ len--;
+ }
+ if (j)
+ printf("\n");
+}
+
+/* ---------------------------------------------------------------------- */
+
+static int openpty(int *amaster, int *aslave, char *name,
+ struct termios *termp, struct winsize *winp)
+{
+ char line[] = "/dev/ptyXX";
+ const char *cp1, *cp2;
+ int master, slave;
+ struct group *gr = getgrnam("tty");
+
+ for (cp1 = "pqrstuvwxyzPQRST"; *cp1; cp1++) {
+ line[8] = *cp1;
+ for (cp2 = "0123456789abcdef"; *cp2; cp2++) {
+ line[9] = *cp2;
+ if ((master = open(line, O_RDWR, 0)) == -1) {
+ if (errno == ENOENT)
+ return (-1); /* out of ptys */
+ } else {
+ line[5] = 't';
+ (void) chown(line, getuid(),
+ gr ? gr->gr_gid : -1);
+ (void) chmod(line, S_IRUSR|S_IWUSR|S_IWGRP);
+#if 0
+ (void) revoke(line);
+#endif
+ if ((slave = open(line, O_RDWR, 0)) != -1) {
+ *amaster = master;
+ *aslave = slave;
+ if (name)
+ strcpy(name, line);
+ if (termp)
+ (void) tcsetattr(slave,
+ TCSAFLUSH,
+ termp);
+ if (winp)
+ (void) ioctl(slave,
+ TIOCSWINSZ,
+ (char *)winp);
+ return 0;
+ }
+ (void) close(master);
+ line[5] = 'p';
+ }
+ }
+ }
+ errno = ENOENT; /* out of ptys */
+ return (-1);
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void restore_ifflags(int signum)
+{
+ if (ioctl(fdif, SIOCSIFFLAGS, &ifr) < 0)
+ die("ioctl SIOCSIFFLAGS");
+ close(fdif);
+ close(fdpty);
+ exit(0);
+}
+
+/* --------------------------------------------------------------------- */
+
+#define KISS_FEND ((unsigned char)0300)
+#define KISS_FESC ((unsigned char)0333)
+#define KISS_TFEND ((unsigned char)0334)
+#define KISS_TFESC ((unsigned char)0335)
+
+#define KISS_CMD_DATA 0
+#define KISS_CMD_TXDELAY 1
+#define KISS_CMD_PPERSIST 2
+#define KISS_CMD_SLOTTIME 3
+#define KISS_CMD_TXTAIL 4
+#define KISS_CMD_FULLDUP 5
+
+#define KISS_HUNT 0
+#define KISS_RX 1
+#define KISS_ESCAPED 2
+
+/* --------------------------------------------------------------------- */
+
+static void kiss_overflow(void)
+{
+ if (verbose)
+ printf("KISS: packet overflow\n");
+}
+
+static void kiss_bad_escape(void)
+{
+ if (verbose)
+ printf("KISS: bad escape sequence\n");
+}
+
+static void display_kiss_packet(char *pfx, unsigned char *pkt,
+ unsigned int pktlen)
+{
+ if (!verbose)
+ return;
+ switch (*pkt) {
+ case KISS_CMD_DATA:
+ printf("%s: ", pfx);
+ display_packet(pkt+1, pktlen-1);
+ break;
+
+ case KISS_CMD_TXDELAY:
+ printf("%s: txdelay = %dms\n", pfx, (int)pkt[1] * 10);
+ break;
+
+ case KISS_CMD_PPERSIST:
+ printf("%s: p persistence = %d\n", pfx, pkt[1]);
+ break;
+
+ case KISS_CMD_SLOTTIME:
+ printf("%s: slottime = %dms\n", pfx, (int)pkt[1] * 10);
+ break;
+
+ case KISS_CMD_TXTAIL:
+ printf("%s: txtail = %dms\n", pfx, (int)pkt[1] * 10);
+ break;
+
+ case KISS_CMD_FULLDUP:
+ printf("%s: %sduplex\n", pfx, pkt[1] ? "full" : "half");
+ break;
+
+ default:
+ printf("%s: unknown frame type 0x%02x, length %d\n", pfx,
+ *pkt, pktlen);
+ }
+}
+
+static void kiss_packet(int fdif, char *addr,
+ unsigned char *pkt, unsigned int pktlen)
+{
+ struct sockaddr to;
+ int i;
+
+ if (pktlen < 2)
+ return;
+ display_kiss_packet("KISS", pkt, pktlen);
+ strncpy(to.sa_data, addr, sizeof(to.sa_data));
+ i = sendto(fdif, pkt, pktlen, 0, &to, sizeof(to));
+ if (i >= 0)
+ return;
+ if (errno == EMSGSIZE) {
+ if (verbose)
+ printf("sendto: %s: packet (size %d) too "
+ "long\n", addr, pktlen-1);
+ return;
+ }
+ if (errno == EWOULDBLOCK) {
+ if (verbose)
+ printf("sendto: %s: busy\n", addr);
+ return;
+ }
+ die("sendto");
+ return;
+}
+
+/* --------------------------------------------------------------------- */
+
+static int doio(int fdif, int fdpty, char *ifaddr)
+{
+ unsigned char ibuf[2048];
+ unsigned char *bp;
+ unsigned char pktbuf[2048];
+ unsigned char *pktptr = pktbuf;
+ unsigned char pktstate = KISS_HUNT;
+ unsigned char obuf[16384];
+ unsigned int ob_wp = 0, ob_rp = 0, ob_wpx;
+ int i;
+ fd_set rmask, wmask;
+ struct sockaddr from;
+ int from_len;
+
+#define ADD_CHAR(c) \
+ obuf[ob_wpx] = c; \
+ ob_wpx = (ob_wpx + 1) % sizeof(obuf); \
+ if (ob_wpx == ob_rp) goto kissencerr;
+
+#define ADD_KISSCHAR(c) \
+ if (((c) & 0xff) == KISS_FEND) \
+ { ADD_CHAR(KISS_FESC); ADD_CHAR(KISS_TFEND); } \
+ else if (((c) & 0xff) == KISS_FESC) \
+ { ADD_CHAR(KISS_FESC); ADD_CHAR(KISS_TFESC); } \
+ else { ADD_CHAR(c); }
+
+ for (;;) {
+ FD_ZERO(&rmask);
+ FD_ZERO(&wmask);
+ FD_SET(fdif, &rmask);
+ FD_SET(fdpty, &rmask);
+ if (ob_rp != ob_wp)
+ FD_SET(fdpty, &wmask);
+ i = select((fdif > fdpty) ? fdif+1 : fdpty+1, &rmask, &wmask,
+ NULL, NULL);
+ if (i < 0)
+ die("select");
+ if (FD_ISSET(fdpty, &wmask)) {
+ if (ob_rp > ob_wp)
+ i = write(fdpty, obuf+ob_rp,
+ sizeof(obuf)-ob_rp);
+ else
+ i = write(fdpty, obuf+ob_rp, ob_wp - ob_rp);
+ if (i < 0)
+ die("write");
+ ob_rp = (ob_rp + i) % sizeof(obuf);
+ }
+ if (FD_ISSET(fdpty, &rmask)) {
+ i = read(fdpty, bp = ibuf, sizeof(ibuf));
+ if (i < 0) {
+ if (errno != EIO)
+ die("read");
+ return 0;
+ }
+ for (; i > 0; i--, bp++) {
+ switch (pktstate) {
+ default:
+ case KISS_HUNT:
+ if (*bp != KISS_FEND)
+ break;
+ pktptr = pktbuf;
+ pktstate = KISS_RX;
+ break;
+
+ case KISS_RX:
+ if (*bp == KISS_FESC) {
+ pktstate = KISS_ESCAPED;
+ break;
+ }
+ if (*bp == KISS_FEND) {
+ kiss_packet(fdif, ifaddr,
+ pktbuf,
+ pktptr - pktbuf);
+ pktptr = pktbuf;
+ break;
+ }
+ if (pktptr >= pktbuf+sizeof(pktbuf)) {
+ kiss_overflow();
+ pktstate = KISS_HUNT;
+ break;
+ }
+ *pktptr++ = *bp;
+ break;
+
+ case KISS_ESCAPED:
+ if (pktptr >= pktbuf+sizeof(pktbuf)) {
+ kiss_overflow();
+ pktstate = KISS_HUNT;
+ break;
+ }
+ if (*bp == KISS_TFESC)
+ *pktptr++ = KISS_FESC;
+ else if (*bp == KISS_TFEND)
+ *pktptr++ = KISS_FEND;
+ else {
+ kiss_bad_escape();
+ pktstate = KISS_HUNT;
+ break;
+ }
+ pktstate = KISS_RX;
+ break;
+ }
+ }
+ }
+ if (FD_ISSET(fdif, &rmask)) {
+ from_len = sizeof(from);
+ i = recvfrom(fdif, bp = ibuf, sizeof(ibuf), 0, &from,
+ &from_len);
+ if (i < 0) {
+ if (errno == EWOULDBLOCK)
+ continue;
+ die("recvfrom");
+ }
+ if (verbose)
+ display_kiss_packet(from.sa_data, ibuf, i);
+ ob_wpx = ob_wp;
+ ADD_CHAR(KISS_FEND);
+ for (; i > 0; i--, bp++) {
+ ADD_KISSCHAR(*bp);
+ }
+ ADD_CHAR(KISS_FEND);
+ ob_wp = ob_wpx;
+ }
+ continue;
+ kissencerr:
+ if (verbose)
+ printf("KISS: Encoder out of memory\n");
+ }
+#undef ADD_CHAR
+#undef ADD_KISSCHAR
+}
+
+/* --------------------------------------------------------------------- */
+
+int main(int argc, char *argv[])
+{
+ struct ifreq ifr_new;
+ struct sockaddr sa;
+ char *name_iface = "bc0";
+ char *name_pname = NULL;
+ char slavename[32];
+ char *master_name;
+ struct termios termios;
+ int c;
+ int errflg = 0;
+ int symlnk = 0;
+ int symlnkforce = 0;
+ short if_newflags = 0;
+ int proto = htons(ETH_P_AX25);
+
+ progname = argv[0];
+ while ((c = getopt(argc, argv, "sfzvai:")) != EOF) {
+ switch (c) {
+ case 's':
+ symlnk = 1;
+ break;
+ case 'f':
+ symlnkforce = 1;
+ break;
+ case 'i':
+ name_iface = optarg;
+ break;
+ case 'z':
+ if_newflags |= IFF_PROMISC;
+ break;
+ case 'v':
+ verbose++;
+ break;
+ case 'a':
+ proto = htons(ETH_P_ALL);
+ break;
+ default:
+ errflg++;
+ break;
+ }
+ }
+ if (argc > optind)
+ name_pname = argv[optind];
+ else
+ errflg++;
+ if (errflg) {
+ fprintf(stderr, "usage: %s [-s] [-f] [-i iface] "
+ "[-z] [-v] ptyname\n", progname);
+ exit(1);
+ }
+ if (symlnk) {
+ int fdtty;
+
+ if (openpty(&fdpty, &fdtty, slavename, NULL, NULL)) {
+ fprintf(stderr, "%s: out of pseudoterminals\n",
+ progname);
+ exit(1);
+ }
+ close(fdtty);
+ fcntl(fdpty, F_SETFL, fcntl(fdpty, F_GETFL, 0) | O_NONBLOCK);
+ if (symlnkforce)
+ unlink(name_pname);
+ if (symlink(slavename, name_pname))
+ perror("symlink");
+ slavename[5] = 'p';
+ master_name = slavename;
+ } else {
+ if ((fdpty = open(name_pname,
+ O_RDWR | O_NOCTTY | O_NONBLOCK)) < 0) {
+ fprintf(stderr, "%s: cannot open \"%s\"\n", progname,
+ name_pname);
+ exit(1);
+ }
+ master_name = name_pname;
+ }
+ if ((fdif = socket(PF_INET, SOCK_PACKET, proto)) < 0)
+ die("socket");
+ strcpy(sa.sa_data, name_iface);
+ sa.sa_family = AF_INET;
+ if (bind(fdif, &sa, sizeof(struct sockaddr)) < 0)
+ die("bind");
+ strcpy(ifr.ifr_name, name_iface);
+ if (ioctl(fdif, SIOCGIFFLAGS, &ifr) < 0)
+ die("ioctl SIOCGIFFLAGS");
+ ifr_new = ifr;
+ ifr_new.ifr_flags |= if_newflags;
+ if (ioctl(fdif, SIOCSIFFLAGS, &ifr_new) < 0)
+ die("ioctl SIOCSIFFLAGS");
+ signal(SIGHUP, restore_ifflags);
+ signal(SIGINT, restore_ifflags);
+ signal(SIGTERM, restore_ifflags);
+ signal(SIGQUIT, restore_ifflags);
+ signal(SIGUSR1, restore_ifflags);
+ signal(SIGUSR2, restore_ifflags);
+
+ for (;;) {
+ if (tcgetattr(fdpty, &termios))
+ die("tcgetattr");
+ termios.c_iflag = IGNBRK;
+ termios.c_oflag = 0;
+ termios.c_lflag = 0;
+ termios.c_cflag &= ~(CSIZE|CSTOPB|PARENB|HUPCL|CRTSCTS);
+ termios.c_cflag |= CS8|CREAD|CLOCAL;
+ if (tcsetattr(fdpty, TCSANOW, &termios))
+ die("tsgetattr");
+ if (doio(fdif, fdpty, name_iface))
+ break;
+ /*
+ * try to reopen master
+ */
+ if (verbose)
+ printf("reopening master tty: %s\n", master_name);
+ close(fdpty);
+ if ((fdpty = open(master_name,
+ O_RDWR | O_NOCTTY | O_NONBLOCK)) < 0) {
+ fprintf(stderr, "%s: cannot reopen \"%s\"\n", progname,
+ master_name);
+ exit(1);
+ }
+ }
+
+ restore_ifflags(0);
+ exit(0);
+}
+
+/* --------------------------------------------------------------------- */
diff --git a/missing b/missing
new file mode 100755
index 0000000..7789652
--- /dev/null
+++ b/missing
@@ -0,0 +1,190 @@
+#! /bin/sh
+# Common stub for a few missing GNU programs while installing.
+# Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+# Franc,ois Pinard <pinard@iro.umontreal.ca>, 1996.
+
+# 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, 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., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+if test $# -eq 0; then
+ echo 1>&2 "Try \`$0 --help' for more information"
+ exit 1
+fi
+
+case "$1" in
+
+ -h|--h|--he|--hel|--help)
+ echo "\
+$0 [OPTION]... PROGRAM [ARGUMENT]...
+
+Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
+error status if there is no known handling for PROGRAM.
+
+Options:
+ -h, --help display this help and exit
+ -v, --version output version information and exit
+
+Supported PROGRAM values:
+ aclocal touch file \`aclocal.m4'
+ autoconf touch file \`configure'
+ autoheader touch file \`config.h.in'
+ automake touch all \`Makefile.in' files
+ bison create \`y.tab.[ch]', if possible, from existing .[ch]
+ flex create \`lex.yy.c', if possible, from existing .c
+ lex create \`lex.yy.c', if possible, from existing .c
+ makeinfo touch the output file
+ yacc create \`y.tab.[ch]', if possible, from existing .[ch]"
+ ;;
+
+ -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
+ echo "missing - GNU libit 0.0"
+ ;;
+
+ -*)
+ echo 1>&2 "$0: Unknown \`$1' option"
+ echo 1>&2 "Try \`$0 --help' for more information"
+ exit 1
+ ;;
+
+ aclocal)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified \`acinclude.m4' or \`configure.in'. You might want
+ to install the \`Automake' and \`Perl' packages. Grab them from
+ any GNU archive site."
+ touch aclocal.m4
+ ;;
+
+ autoconf)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified \`configure.in'. You might want to install the
+ \`Autoconf' and \`GNU m4' packages. Grab them from any GNU
+ archive site."
+ touch configure
+ ;;
+
+ autoheader)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified \`acconfig.h' or \`configure.in'. You might want
+ to install the \`Autoconf' and \`GNU m4' packages. Grab them
+ from any GNU archive site."
+ files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' configure.in`
+ test -z "$files" && files="config.h"
+ touch_files=
+ for f in $files; do
+ case "$f" in
+ *:*) touch_files="$touch_files "`echo "$f" |
+ sed -e 's/^[^:]*://' -e 's/:.*//'`;;
+ *) touch_files="$touch_files $f.in";;
+ esac
+ done
+ touch $touch_files
+ ;;
+
+ automake)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified \`Makefile.am', \`acinclude.m4' or \`configure.in'.
+ You might want to install the \`Automake' and \`Perl' packages.
+ Grab them from any GNU archive site."
+ find . -type f -name Makefile.am -print |
+ sed 's/\.am$/.in/' |
+ while read f; do touch "$f"; done
+ ;;
+
+ bison|yacc)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified a \`.y' file. You may need the \`Bison' package
+ in order for those modifications to take effect. You can get
+ \`Bison' from any GNU archive site."
+ rm -f y.tab.c y.tab.h
+ if [ $# -ne 1 ]; then
+ eval LASTARG="\${$#}"
+ case "$LASTARG" in
+ *.y)
+ SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
+ if [ -f "$SRCFILE" ]; then
+ cp "$SRCFILE" y.tab.c
+ fi
+ SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
+ if [ -f "$SRCFILE" ]; then
+ cp "$SRCFILE" y.tab.h
+ fi
+ ;;
+ esac
+ fi
+ if [ ! -f y.tab.h ]; then
+ echo >y.tab.h
+ fi
+ if [ ! -f y.tab.c ]; then
+ echo 'main() { return 0; }' >y.tab.c
+ fi
+ ;;
+
+ lex|flex)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified a \`.l' file. You may need the \`Flex' package
+ in order for those modifications to take effect. You can get
+ \`Flex' from any GNU archive site."
+ rm -f lex.yy.c
+ if [ $# -ne 1 ]; then
+ eval LASTARG="\${$#}"
+ case "$LASTARG" in
+ *.l)
+ SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
+ if [ -f "$SRCFILE" ]; then
+ cp "$SRCFILE" lex.yy.c
+ fi
+ ;;
+ esac
+ fi
+ if [ ! -f lex.yy.c ]; then
+ echo 'main() { return 0; }' >lex.yy.c
+ fi
+ ;;
+
+ makeinfo)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified a \`.texi' or \`.texinfo' file, or any other file
+ indirectly affecting the aspect of the manual. The spurious
+ call might also be the consequence of using a buggy \`make' (AIX,
+ DU, IRIX). You might want to install the \`Texinfo' package or
+ the \`GNU make' package. Grab either from any GNU archive site."
+ file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
+ if test -z "$file"; then
+ file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
+ file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file`
+ fi
+ touch $file
+ ;;
+
+ *)
+ echo 1>&2 "\
+WARNING: \`$1' is needed, and you do not seem to have it handy on your
+ system. You might have modified some files without having the
+ proper tools for further handling them. Check the \`README' file,
+ it often tells you about the needed prerequirements for installing
+ this package. You may also peek at any GNU archive site, in case
+ some other package would contain this missing \`$1' program."
+ exit 1
+ ;;
+esac
+
+exit 0
diff --git a/mkinstalldirs b/mkinstalldirs
new file mode 100755
index 0000000..4f58503
--- /dev/null
+++ b/mkinstalldirs
@@ -0,0 +1,40 @@
+#! /bin/sh
+# mkinstalldirs --- make directory hierarchy
+# Author: Noah Friedman <friedman@prep.ai.mit.edu>
+# Created: 1993-05-16
+# Public domain
+
+# $Id: mkinstalldirs,v 1.13 1999/01/05 03:18:55 bje Exp $
+
+errstatus=0
+
+for file
+do
+ set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
+ shift
+
+ pathcomp=
+ for d
+ do
+ pathcomp="$pathcomp$d"
+ case "$pathcomp" in
+ -* ) pathcomp=./$pathcomp ;;
+ esac
+
+ if test ! -d "$pathcomp"; then
+ echo "mkdir $pathcomp"
+
+ mkdir "$pathcomp" || lasterr=$?
+
+ if test ! -d "$pathcomp"; then
+ errstatus=$lasterr
+ fi
+ fi
+
+ pathcomp="$pathcomp/"
+ done
+done
+
+exit $errstatus
+
+# mkinstalldirs ends here
diff --git a/netrom/Makefile.am b/netrom/Makefile.am
new file mode 100644
index 0000000..03f0c0d
--- /dev/null
+++ b/netrom/Makefile.am
@@ -0,0 +1,26 @@
+
+etcfiles = nrbroadcast nrports
+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 = netromd nodesave nrattach nrparms nrsdrv
+
+man_MANS = netrom.4 nrports.5 nrbroadcast.5 netromd.8 nodesave.8 \
+ nrattach.8 nrparms.8 nrsdrv.8
+
+EXTRA_DIST = $(man_MANS) $(etcfiles)
+
+netromd_SOURCES = \
+ netromd.c \
+ netromd.h \
+ netromr.c \
+ netromt.c
+
+
diff --git a/netrom/Makefile.in b/netrom/Makefile.in
new file mode 100644
index 0000000..80c3c9c
--- /dev/null
+++ b/netrom/Makefile.in
@@ -0,0 +1,452 @@
+# 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 = nrbroadcast nrports
+etcdir = $(sysconfdir)/ax25
+
+sbin_PROGRAMS = netromd nodesave nrattach nrparms nrsdrv
+
+man_MANS = netrom.4 nrports.5 nrbroadcast.5 netromd.8 nodesave.8 nrattach.8 nrparms.8 nrsdrv.8
+
+
+EXTRA_DIST = $(man_MANS) $(etcfiles)
+
+netromd_SOURCES = netromd.c netromd.h netromr.c netromt.c
+
+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@
+netromd_OBJECTS = netromd.o netromr.o netromt.o
+netromd_LDADD = $(LDADD)
+netromd_DEPENDENCIES =
+netromd_LDFLAGS =
+nodesave_SOURCES = nodesave.c
+nodesave_OBJECTS = nodesave.o
+nodesave_LDADD = $(LDADD)
+nodesave_DEPENDENCIES =
+nodesave_LDFLAGS =
+nrattach_SOURCES = nrattach.c
+nrattach_OBJECTS = nrattach.o
+nrattach_LDADD = $(LDADD)
+nrattach_DEPENDENCIES =
+nrattach_LDFLAGS =
+nrparms_SOURCES = nrparms.c
+nrparms_OBJECTS = nrparms.o
+nrparms_LDADD = $(LDADD)
+nrparms_DEPENDENCIES =
+nrparms_LDFLAGS =
+nrsdrv_SOURCES = nrsdrv.c
+nrsdrv_OBJECTS = nrsdrv.o
+nrsdrv_LDADD = $(LDADD)
+nrsdrv_DEPENDENCIES =
+nrsdrv_LDFLAGS =
+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 = $(netromd_SOURCES) nodesave.c nrattach.c nrparms.c nrsdrv.c
+OBJECTS = $(netromd_OBJECTS) nodesave.o nrattach.o nrparms.o nrsdrv.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 netrom/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:
+
+netromd: $(netromd_OBJECTS) $(netromd_DEPENDENCIES)
+ @rm -f netromd
+ $(LINK) $(netromd_LDFLAGS) $(netromd_OBJECTS) $(netromd_LDADD) $(LIBS)
+
+nodesave: $(nodesave_OBJECTS) $(nodesave_DEPENDENCIES)
+ @rm -f nodesave
+ $(LINK) $(nodesave_LDFLAGS) $(nodesave_OBJECTS) $(nodesave_LDADD) $(LIBS)
+
+nrattach: $(nrattach_OBJECTS) $(nrattach_DEPENDENCIES)
+ @rm -f nrattach
+ $(LINK) $(nrattach_LDFLAGS) $(nrattach_OBJECTS) $(nrattach_LDADD) $(LIBS)
+
+nrparms: $(nrparms_OBJECTS) $(nrparms_DEPENDENCIES)
+ @rm -f nrparms
+ $(LINK) $(nrparms_LDFLAGS) $(nrparms_OBJECTS) $(nrparms_LDADD) $(LIBS)
+
+nrsdrv: $(nrsdrv_OBJECTS) $(nrsdrv_DEPENDENCIES)
+ @rm -f nrsdrv
+ $(LINK) $(nrsdrv_LDFLAGS) $(nrsdrv_OBJECTS) $(nrsdrv_LDADD) $(LIBS)
+
+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 = netrom
+
+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
+netromd.o: netromd.c ../config.h ../pathnames.h netromd.h
+netromr.o: netromr.c ../pathnames.h netromd.h
+netromt.o: netromt.c ../pathnames.h netromd.h
+nodesave.o: nodesave.c
+nrattach.o: nrattach.c ../config.h ../pathnames.h
+nrparms.o: nrparms.c ../config.h
+nrsdrv.o: nrsdrv.c ../config.h ../pathnames.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-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-man
+uninstall: uninstall-am
+all-am: Makefile $(PROGRAMS) $(MANS)
+all-redirect: all-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+installdirs:
+ $(mkinstalldirs) $(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 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/netrom/netrom.4 b/netrom/netrom.4
new file mode 100644
index 0000000..67b159a
--- /dev/null
+++ b/netrom/netrom.4
@@ -0,0 +1,51 @@
+.TH NETROM 4 "25 July 1996" Linux "Linux Programmer's Manual"
+.SH NAME
+AF_NETROM \- NET/ROM amateur packet radio protocol family
+.SH DESCRIPTION
+.LP
+.B NET/ROM
+is a protocol used extensively by radio amateurs. The Linux
+NET/ROM protocol family permits access to these protocols via
+the standard networking
+.B socket
+metaphor.
+.LP
+The NET/ROM protocol layer only supports connected mode. IP traffic may be
+stacked on top of NET/ROM frames using a non-standard extension to the
+NET/ROM protocol.
+.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 NET/ROM).
+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
+NET/ROM addresses consist of 6 ascii characters and a number called the
+SSID. These are encoded into a sockaddr_ax25 structure which is provided to
+the relevant system calls.
+.LP
+NET/ROM 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
+NET/ROM supports the following socket options for SOL_NETROM. NETROM_T1 is
+the T1 timer in 1/10ths of a second, NETROM_T2 is the T2 timer in 1/10ths of
+a second. NETROM_N2, the retry counter is also configurable. There is no 'infinite
+retry' option supported however. It is possible for an application
+to request that the NET/ROM layer return the NET/ROM header as well as the
+application data, this is done via the NETROM_HDRINCL socket option.
+.SH "SEE ALSO"
+.BR call (1),
+.BR socket (2),
+.BR setsockopt(2),
+.BR getsockopt(2),
+.BR nrbroadcast (5),
+.BR nrports (5),
+.BR netromd (8),
+.BR noderest (8),
+.BR nodesave (8),
+.BR nrctl (8),
+.BR nrparms (8).
+.LP
+.SH AUTHOR
+Jonathan Naylor G4KLX <g4klx@g4klx.demon.co.uk>
diff --git a/netrom/netromd.8 b/netrom/netromd.8
new file mode 100644
index 0000000..ef1860e
--- /dev/null
+++ b/netrom/netromd.8
@@ -0,0 +1,97 @@
+.TH NETROMD 8 "20 August 1996" Linux "Linux System Managers Manual"
+.SH NAME
+netromd \- Send and receive NET/ROM routing messages
+.SH SYNOPSIS
+.B netromd [-c] [-d] [-i] [-l] [-p pause] [-q quality] [-t interval] [-v]
+.SH DESCRIPTION
+.LP
+For a NET/ROM based network to operate correctly, a periodic broadcast of
+routing information needs to occur. Typically this occurs once every hour on
+every port which is expected to carry NET/ROM traffic. The purpose of
+.B netromd
+is to send and receive NET/ROM routing broadcasts. To operate correctly a
+set of parameters that corresponds to each AX.25 port needs to be passed to
+the program. This information is encoded in a configuration file, by default
+which is /etc/ax25/nrbroadcast with each line representing one
+port, see the manual page for
+.BR nrbroadcast (5).
+.LP
+To cut down the length of these routing broadcasts, only the information
+about the highest quality neighbour for a particular node is transmitted.
+The transmission is also limited to those node that have a certain minimum
+value in their obsolesence count, this value is decremented every time a
+routing broadcast is transmitted, and is refreshed by receiving a routing
+broadcast which contains that particular node.
+.LP
+The value of the default quality is traditionally assigned a value that
+represents the quality of the radio links on that port. A higher number
+representing better radio links with 255 (the maximum) reserved for wire
+connections. The practise in the UK is to set the default quality to a low
+value, typically 10, and manually set up the trusted neighbouring nodes in
+the neighbour list manually. The worst quality for auto-updates value is a
+way to filter out low quality (ie distant) nodes.
+.LP
+The verbose flag may be either 0 or 1, representing no and yes. By
+specifying no, the program will only generate a routing message containing
+information about the node on which it is running, by specifying the yes
+option, all the information in the nodes routing tables will be transmitted.
+The quality advertised for the other node callsigns on this machine may be
+set using the \-q option.
+.LP
+Between each transmission
+.B netromd
+pauses for five seconds (default) in order to avoid flooding the channels
+that it must broadcast on. The value of this delay is settable with the \-p
+option.
+.SH OPTIONS
+.TP 16
+.BI \-c
+Forces strict compliance to Software 2000 specifications. At present this
+only determines how node mnemonics with lower case characters will be handled.
+With compliance enabled mixed case node mnemonics will be ignored. The default
+is to accept node mnemonics of mixed case.
+.TP 16
+.BI \-d
+Switches on debugging messages, the default is off. Logging must be enabled
+for them to be output.
+.TP 16
+.BI \-i
+Transmit a routing broadcast immediately, the default is to wait for the
+time interval to elapse before transmitting the first routing broadcast.
+.TP 16
+.BI \-l
+Enables logging of errors and debug messages to the system log. The default
+is off.
+.TP 16
+.BI "\-p pause"
+Sets the delay between transmissions of individual routing broadcast
+packets. The default is five seconds.
+.TP 16
+.BI "\-q quality"
+Sets the quality of the subsidiary nodes relative to the main node. The
+default is 255.
+.TP 16
+.BI "\-t interval"
+The time interval between routing broadcasts, in minutes. The default is 60
+minutes.
+.TP 16
+.BI \-v
+Display the version.
+.SH FILES
+.nf
+/proc/net/nr_neigh
+.br
+/proc/net/nr_nodes
+.br
+/etc/ax25/axports
+.br
+/etc/ax25/nrbroadcast
+.fi
+.SH "SEE ALSO"
+.BR ax25 (4),
+.BR axports (5),
+.BR nrbroadcast (5),
+.BR netrom (4),
+.BR nrparms (8).
+.SH AUTHOR
+Jonathan Naylor G4KLX <g4klx@g4klx.demon.co.uk>
diff --git a/netrom/netromd.c b/netrom/netromd.c
new file mode 100644
index 0000000..fa80c9b
--- /dev/null
+++ b/netrom/netromd.c
@@ -0,0 +1,254 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <signal.h>
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include <net/if.h>
+#include <net/ethernet.h>
+#include <netax25/ax25.h>
+#include <netrom/netrom.h>
+#include <netrose/rose.h>
+
+#include <netax25/axlib.h>
+#include <netax25/axconfig.h>
+#include <netax25/daemon.h>
+#include <netax25/nrconfig.h>
+
+#include <config.h>
+
+#include "../pathnames.h"
+#include "netromd.h"
+
+struct port_struct port_list[20];
+
+int port_count = FALSE;
+int compliant = FALSE;
+int debug = FALSE;
+int logging = FALSE;
+
+ax25_address my_call;
+ax25_address node_call;
+
+static void terminate(int sig)
+{
+ if (logging) {
+ syslog(LOG_INFO, "terminating on SIGTERM\n");
+ closelog();
+ }
+
+ exit(0);
+}
+
+static int bcast_config_load_ports(void)
+{
+ char buffer[255], port[32], *s;
+ FILE *fp;
+
+ if ((fp = fopen(CONF_NETROMD_FILE, "r")) == NULL) {
+ fprintf(stderr, "netromd: cannot open config file\n");
+ return -1;
+ }
+
+ while (fgets(buffer, 255, fp) != NULL) {
+ if ((s = strchr(buffer, '\n')) != NULL)
+ *s = '\0';
+
+ if (strlen(buffer) == 0 || buffer[0] == '#')
+ continue;
+
+ if (sscanf(buffer, "%s %d %d %d %d",
+ port,
+ &port_list[port_count].minimum_obs,
+ &port_list[port_count].default_qual,
+ &port_list[port_count].worst_qual,
+ &port_list[port_count].verbose) == -1) {
+ fprintf(stderr, "netromd: unable to parse: %s", buffer);
+ return -1;
+ }
+
+ if (ax25_config_get_addr(port) == NULL) {
+ fprintf(stderr, "netromd: invalid port name - %s\n", port);
+ return -1;
+ }
+
+ port_list[port_count].port = strdup(port);
+ port_list[port_count].device = strdup(ax25_config_get_dev(port_list[port_count].port));
+
+ if (port_list[port_count].minimum_obs < 0 || port_list[port_count].minimum_obs > 6) {
+ fprintf(stderr, "netromd: invalid minimum obsolescence\n");
+ return -1;
+ }
+
+ if (port_list[port_count].default_qual < 0 || port_list[port_count].default_qual > 255) {
+ fprintf(stderr, "netromd: invalid default quality\n");
+ return -1;
+ }
+
+ if (port_list[port_count].worst_qual < 0 || port_list[port_count].worst_qual > 255) {
+ fprintf(stderr, "netromd: invalid worst quality\n");
+ return -1;
+ }
+
+ if (port_list[port_count].verbose != 0 && port_list[port_count].verbose != 1) {
+ fprintf(stderr, "netromd: invalid verbose setting\n");
+ return -1;
+ }
+
+ port_count++;
+ }
+
+ fclose(fp);
+
+ if (port_count == 0)
+ return -1;
+
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ unsigned char buffer[512];
+ int size, s, i;
+ struct sockaddr sa;
+ int asize;
+ struct timeval timeout;
+ time_t timenow, timelast;
+ int interval = 3600;
+ int localval = 255;
+ int pause = 5;
+ fd_set fdset;
+
+ time(&timelast);
+
+ while ((i = getopt(argc, argv, "cdilp:q:t:v")) != -1) {
+ switch (i) {
+ case 'c':
+ compliant = TRUE;
+ break;
+ case 'd':
+ debug = TRUE;
+ break;
+ case 'i':
+ timelast = 0;
+ break;
+ case 'l':
+ logging = TRUE;
+ break;
+ case 'p':
+ pause = atoi(optarg);
+ if (pause < 1 || pause > 120) {
+ fprintf(stderr, "netromd: invalid pause value\n");
+ return 1;
+ }
+ break;
+ case 'q':
+ localval = atoi(optarg);
+ if (localval < 10 || localval > 255) {
+ fprintf(stderr, "netromd: invalid local quality\n");
+ return 1;
+ }
+ break;
+ case 't':
+ interval = atoi(optarg) * 60;
+ if (interval < 60 || interval > 7200) {
+ fprintf(stderr, "netromd: invalid time interval\n");
+ return 1;
+ }
+ break;
+ case 'v':
+ printf("netromd: %s\n", VERSION);
+ return 0;
+ case '?':
+ case ':':
+ fprintf(stderr, "usage: netromd [-d] [-i] [-l] [-q quality] [-t interval] [-v]\n");
+ return 1;
+ }
+ }
+
+ signal(SIGTERM, terminate);
+
+ if (ax25_config_load_ports() == 0) {
+ fprintf(stderr, "netromd: no AX.25 ports defined\n");
+ return 1;
+ }
+
+ if (nr_config_load_ports() == 0) {
+ fprintf(stderr, "netromd: no NET/ROM ports defined\n");
+ return 1;
+ }
+
+ if (bcast_config_load_ports() == -1) {
+ fprintf(stderr, "netromd: no NET/ROM broadcast ports defined\n");
+ return 1;
+ }
+
+ ax25_aton_entry(nr_config_get_addr(NULL), (char *)&my_call);
+ ax25_aton_entry("NODES", (char *)&node_call);
+
+ if ((s = socket(AF_INET, SOCK_PACKET, htons(ETH_P_AX25))) == -1) {
+ perror("netromd: socket");
+ return 1;
+ }
+
+ if (!daemon_start(TRUE)) {
+ fprintf(stderr, "netromd: cannot become a daemon\n");
+ return 1;
+ }
+
+ if (logging) {
+ openlog("netromd", LOG_PID, LOG_DAEMON);
+ syslog(LOG_INFO, "starting");
+ }
+
+ for (;;) {
+ FD_ZERO(&fdset);
+ FD_SET(s, &fdset);
+
+ timeout.tv_sec = 30;
+ timeout.tv_usec = 0;
+
+ if (select(s + 1, &fdset, NULL, NULL, &timeout) == -1)
+ continue; /* Signal received ? */
+
+ if (FD_ISSET(s, &fdset)) {
+ asize = sizeof(sa);
+
+ if ((size = recvfrom(s, buffer, sizeof(buffer), 0, &sa, &asize)) == -1) {
+ if (logging) {
+ syslog(LOG_ERR, "recvfrom: %m");
+ closelog();
+ }
+ return 1;
+ }
+
+ if (ax25_cmp((ax25_address *)(buffer + 1), &node_call) == 0 &&
+ ax25_cmp((ax25_address *)(buffer + 8), &my_call) != 0 &&
+ buffer[16] == NETROM_PID && buffer[17] == NODES_SIG) {
+ for (i = 0; i < port_count; i++) {
+ if (strcmp(port_list[i].device, sa.sa_data) == 0) {
+ if (debug && logging)
+ syslog(LOG_DEBUG, "receiving NODES broadcast on port %s from %s\n", port_list[i].port, ax25_ntoa((ax25_address *)(buffer + 8)));
+ receive_nodes(buffer + 18, size - 18, (ax25_address *)(buffer + 8), i);
+ break;
+ }
+ }
+ }
+ }
+
+ time(&timenow);
+
+ if ((timenow - timelast) > interval) {
+ timelast = timenow;
+ transmit_nodes(localval, pause);
+ }
+ }
+}
diff --git a/netrom/netromd.h b/netrom/netromd.h
new file mode 100644
index 0000000..3007b02
--- /dev/null
+++ b/netrom/netromd.h
@@ -0,0 +1,41 @@
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#define NETROM_PID 0xCF
+
+#define NODES_SIG 0xFF
+
+#define CALLSIGN_LEN 7
+#define MNEMONIC_LEN 6
+#define QUALITY_LEN 1
+
+#define NODES_PACLEN 256
+#define ROUTE_LEN (CALLSIGN_LEN+MNEMONIC_LEN+CALLSIGN_LEN+QUALITY_LEN)
+
+struct port_struct {
+ char *device;
+ char *port;
+ int minimum_obs;
+ int default_qual;
+ int worst_qual;
+ int verbose;
+};
+
+extern struct port_struct port_list[];
+
+extern int port_count;
+extern int debug;
+extern int logging;
+
+extern ax25_address my_call;
+extern ax25_address node_call;
+
+/* In netromt.c */
+extern void transmit_nodes(int, int);
+
+/* In netromr.c */
+extern void receive_nodes(unsigned char *, int, ax25_address *, int);
diff --git a/netrom/netromr.c b/netrom/netromr.c
new file mode 100644
index 0000000..eafd225
--- /dev/null
+++ b/netrom/netromr.c
@@ -0,0 +1,164 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <syslog.h>
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <net/ethernet.h>
+
+#include <netax25/ax25.h>
+#include <netrom/netrom.h>
+#include <netrose/rose.h>
+#include <netax25/axlib.h>
+#include "../pathnames.h"
+
+#include "netromd.h"
+
+extern int compliant;
+
+static int validmnemonic(char *mnemonic)
+{
+ if (compliant) {
+ if (strspn(mnemonic, "#_&-/ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") == strlen(mnemonic))
+ return TRUE;
+ } else {
+ if (strspn(mnemonic, "#_&-/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") == strlen(mnemonic))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+void receive_nodes(unsigned char *buffer, int length, ax25_address *neighbour, int index)
+{
+ struct nr_route_struct nr_node;
+ char neigh_buffer[90], *portcall, *p;
+ FILE *fp;
+ int s;
+ int quality, obs_count, qual, lock;
+ char *addr, *callsign, *device;
+
+ nr_node.type = NETROM_NODE;
+ /*nr_node.ndigis = 0;*/
+
+ sprintf(neigh_buffer, "%s/obsolescence_count_initialiser", PROC_NR_SYSCTL_DIR);
+
+ if ((fp = fopen(neigh_buffer, "r")) == NULL) {
+ if (logging)
+ syslog(LOG_ERR, "netromr: cannot open %s\n", neigh_buffer);
+ return;
+ }
+
+ fgets(neigh_buffer, 90, fp);
+
+ obs_count = atoi(neigh_buffer);
+
+ fclose(fp);
+
+ if ((s = socket(AF_NETROM, SOCK_SEQPACKET, 0)) < 0) {
+ if (logging)
+ syslog(LOG_ERR, "netromr: socket: %m");
+ return;
+ }
+
+ if ((fp = fopen(PROC_NR_NEIGH_FILE, "r")) == NULL) {
+ if (logging)
+ syslog(LOG_ERR, "netromr: cannot open %s\n", PROC_NR_NEIGH_FILE);
+ close(s);
+ return;
+ }
+
+ fgets(neigh_buffer, 90, fp);
+
+ portcall = ax25_ntoa(neighbour);
+
+ quality = port_list[index].default_qual;
+
+ while (fgets(neigh_buffer, 90, fp) != NULL) {
+ addr = strtok(neigh_buffer, " ");
+ callsign = strtok(NULL, " ");
+ device = strtok(NULL, " ");
+ qual = atoi(strtok(NULL, " "));
+ lock = atoi(strtok(NULL, " "));
+
+ if (strcmp(callsign, portcall) == 0 &&
+ strcmp(device, port_list[index].device) == 0 &&
+ lock == 1) {
+ quality = qual;
+ break;
+ }
+ }
+
+ fclose(fp);
+
+ nr_node.callsign = *neighbour;
+ memcpy(nr_node.mnemonic, buffer, MNEMONIC_LEN);
+ nr_node.mnemonic[MNEMONIC_LEN] = '\0';
+
+ if ((p = strchr(nr_node.mnemonic, ' ')) != NULL)
+ *p = '\0';
+
+ if (!validmnemonic(nr_node.mnemonic)) {
+ if (debug && logging)
+ syslog(LOG_DEBUG, "rejecting route, invalid mnemonic - %s\n", nr_node.mnemonic);
+ } else {
+ nr_node.neighbour = *neighbour;
+ strcpy(nr_node.device, port_list[index].device);
+ nr_node.quality = quality;
+ nr_node.obs_count = obs_count;
+
+ if (ioctl(s, SIOCADDRT, &nr_node) == -1) {
+ if (logging)
+ syslog(LOG_ERR, "netromr: SIOCADDRT: %m");
+ close(s);
+ return;
+ }
+ }
+
+ buffer += MNEMONIC_LEN;
+ length -= MNEMONIC_LEN;
+
+ while (length >= ROUTE_LEN) {
+ /*
+ * Ensure that a) the route is not via me, and
+ * b) it is better than my minimum acceptable quality
+ */
+ if (ax25_cmp(&my_call, (ax25_address *)(buffer + 13)) != 0 &&
+ buffer[20] > port_list[index].worst_qual) {
+ memcpy(&nr_node.callsign, buffer + 0, CALLSIGN_LEN);
+ memcpy(nr_node.mnemonic, buffer + 7, MNEMONIC_LEN);
+ nr_node.mnemonic[MNEMONIC_LEN] = '\0';
+
+ if ((p = strchr(nr_node.mnemonic, ' ')) != NULL)
+ *p = '\0';
+
+ if (!validmnemonic(nr_node.mnemonic)) {
+ if (debug && logging)
+ syslog(LOG_DEBUG, "rejecting route, invalid mnemonic - %s\n", nr_node.mnemonic);
+ } else {
+ nr_node.neighbour = *neighbour;
+ strcpy(nr_node.device, port_list[index].device);
+ nr_node.quality = ((quality * buffer[20]) + 128) / 256;
+ nr_node.obs_count = obs_count;
+
+ if (ioctl(s, SIOCADDRT, &nr_node) == -1) {
+ if (logging)
+ syslog(LOG_ERR, "netromr: SIOCADDRT: %m");
+ close(s);
+ return;
+ }
+ }
+ }
+
+ buffer += ROUTE_LEN;
+ length -= ROUTE_LEN;
+ }
+
+ close(s);
+}
diff --git a/netrom/netromt.c b/netrom/netromt.c
new file mode 100644
index 0000000..d22caf1
--- /dev/null
+++ b/netrom/netromt.c
@@ -0,0 +1,268 @@
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <syslog.h>
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+
+#include <sys/socket.h>
+#include <netax25/ax25.h>
+#include <netrom/netrom.h>
+#include <netrose/rose.h>
+
+#include <netax25/axlib.h>
+#include <netax25/axconfig.h>
+#include <netax25/nrconfig.h>
+
+#include "../pathnames.h"
+#include "netromd.h"
+
+static int build_header(unsigned char *message)
+{
+ message[0] = NODES_SIG;
+
+ strcpy(message + 1, nr_config_get_alias(NULL));
+ strncat(message + 1, " ", MNEMONIC_LEN - strlen(message + 1));
+
+ return 7;
+}
+
+static void build_mine(int s, struct full_sockaddr_ax25 *dest, int dlen, int localval, int pause)
+{
+ unsigned char message[100];
+ char buffer[255], *port, *p;
+ FILE *fp;
+ int len;
+
+ len = build_header(message);
+
+ if ((fp = fopen(CONF_NRPORTS_FILE, "r")) == NULL) {
+ if (logging)
+ syslog(LOG_ERR, "netromt: cannot open nrports file\n");
+ return;
+ }
+
+ while (fgets(buffer, 255, fp) != NULL) {
+ if ((p = strchr(buffer, '\n')) != NULL)
+ *p = '\0';
+
+ if (strlen(buffer) == 0 || buffer[0] == '#')
+ continue;
+
+ port = strtok(buffer, " \t");
+
+ if (nr_config_get_addr(port) == NULL)
+ continue;
+
+ if (strcmp(nr_config_get_addr(port), nr_config_get_addr(NULL)) == 0)
+ continue;
+
+ if (ax25_aton_entry(nr_config_get_addr(port), message + len) == -1) {
+ if (logging)
+ syslog(LOG_ERR, "netromt: invalid callsign in nrports\n");
+ fclose(fp);
+ return;
+ }
+ len += CALLSIGN_LEN;
+
+ strcpy(message + len, nr_config_get_alias(port));
+ strncat(message + len, " ", MNEMONIC_LEN - strlen(message + len));
+ len += MNEMONIC_LEN;
+
+ ax25_aton_entry(nr_config_get_addr(NULL), message + len);
+ len += CALLSIGN_LEN;
+
+ message[len] = localval;
+ len += QUALITY_LEN;
+ }
+
+ fclose(fp);
+
+ if (sendto(s, message, len, 0, (struct sockaddr *)dest, dlen) == -1) {
+ if (logging)
+ syslog(LOG_ERR, "netromt: sendto: %m");
+ }
+
+ sleep(pause);
+}
+
+static void build_others(int s, int min_obs, struct full_sockaddr_ax25 *dest, int dlen, int port, int pause)
+{
+ unsigned char message[300];
+ FILE *fpnodes, *fpneigh;
+ char nodes_buffer[90];
+ char neigh_buffer[90];
+ char *callsign, *mnemonic, *neighbour;
+ int which, number, quality, neigh_no, obs_count;
+ int olen, len;
+
+ if ((fpnodes = fopen(PROC_NR_NODES_FILE, "r")) == NULL) {
+ if (logging)
+ syslog(LOG_ERR, "netromt: cannot open %s\n", PROC_NR_NODES_FILE);
+ return;
+ }
+
+ if ((fpneigh = fopen(PROC_NR_NEIGH_FILE, "r")) == NULL) {
+ if (logging)
+ syslog(LOG_ERR, "netromt: cannot open %s\n", PROC_NR_NEIGH_FILE);
+ fclose(fpnodes);
+ return;
+ }
+
+ fgets(nodes_buffer, 90, fpnodes);
+
+ do {
+ len = olen = build_header(message);
+
+ while (fgets(nodes_buffer, 90, fpnodes) != NULL) {
+ callsign = strtok(nodes_buffer, " ");
+ mnemonic = strtok(NULL, " ");
+ which = atoi(strtok(NULL, " "));
+ number = atoi(strtok(NULL, " "));
+ quality = atoi(strtok(NULL, " "));
+ obs_count = atoi(strtok(NULL, " "));
+ neigh_no = atoi(strtok(NULL, " "));
+ neighbour = NULL;
+
+ if (obs_count < min_obs || quality == 0) continue;
+
+ /* "Blank" mnemonic */
+ if (strcmp(mnemonic, "*") == 0)
+ mnemonic = "";
+
+ fseek(fpneigh, 0L, SEEK_SET);
+
+ fgets(neigh_buffer, 90, fpneigh);
+
+ while (fgets(neigh_buffer, 90, fpneigh) != NULL) {
+ if (atoi(strtok(neigh_buffer, " ")) == neigh_no) {
+ neighbour = strtok(NULL, " ");
+ break;
+ }
+ }
+
+ if (neighbour == NULL) {
+ if (logging)
+ syslog(LOG_ERR, "netromt: corruption in nodes/neighbour matching\n");
+ continue;
+ }
+
+ if (ax25_aton_entry(callsign, message + len) == -1) {
+ if (logging)
+ syslog(LOG_ERR, "netromt: invalid callsign '%s' in /proc/net/nr_nodes\n", callsign);
+ continue;
+ }
+ len += CALLSIGN_LEN;
+
+ strcpy(message + len, mnemonic);
+ strncat(message + len, " ", MNEMONIC_LEN - strlen(message + len));
+ len += MNEMONIC_LEN;
+
+ if (ax25_aton_entry(neighbour, message + len) == -1) {
+ if (logging)
+ syslog(LOG_ERR, "netromt: invalid callsign '%s' in /proc/net/nr_neigh\n", neighbour);
+ len -= (CALLSIGN_LEN + MNEMONIC_LEN);
+ continue;
+ }
+ len += CALLSIGN_LEN;
+
+ message[len] = quality;
+ len += QUALITY_LEN;
+
+ /* No room for another entry? */
+ if (len + ROUTE_LEN > NODES_PACLEN)
+ break;
+ }
+
+ /* Only send it if there is more that just the header */
+ if (len > olen) {
+ if (sendto(s, message, len, 0, (struct sockaddr *)dest, dlen) == -1) {
+ if (logging)
+ syslog(LOG_ERR, "netromt: sendto: %m");
+ }
+
+ sleep(pause);
+ }
+
+ /* If the packet was not full then we are done */
+ } while (len + ROUTE_LEN > NODES_PACLEN);
+
+ fclose(fpnodes);
+ fclose(fpneigh);
+}
+
+void transmit_nodes(int localval, int pause)
+{
+ struct full_sockaddr_ax25 dest;
+ struct full_sockaddr_ax25 src;
+ int s, dlen, slen;
+ char path[25], *addr;
+ int i;
+
+ switch (fork()) {
+ case 0:
+ break;
+ case -1:
+ if (logging)
+ syslog(LOG_ERR, "netromt: fork: %m\n");
+ return;
+ default:
+ return;
+ }
+
+ dlen = ax25_aton("NODES", &dest);
+
+ for (i = 0; i < port_count; i++) {
+
+ addr = ax25_config_get_addr(port_list[i].port);
+
+ if (addr == NULL) continue;
+
+ if (debug && logging)
+ syslog(LOG_DEBUG, "transmitting NODES broadcast on port %s\n", port_list[i].port);
+
+ sprintf(path, "%s %s", nr_config_get_addr(NULL), addr);
+
+ ax25_aton(path, &src);
+ slen = sizeof(struct full_sockaddr_ax25);
+
+ if ((s = socket(AF_AX25, SOCK_DGRAM, NETROM_PID)) < 0) {
+ if (logging)
+ syslog(LOG_ERR, "netromt: socket: %m");
+ continue;
+ }
+
+ if (bind(s, (struct sockaddr *)&src, slen) == -1) {
+ if (logging)
+ syslog(LOG_ERR, "netromt: bind: %m");
+ close(s);
+ continue;
+ }
+
+ build_mine(s, &dest, dlen, localval, pause);
+
+ if (port_list[i].verbose)
+ build_others(s, port_list[i].minimum_obs, &dest, dlen, i, pause);
+
+ close(s);
+ }
+
+ if ((s = socket(AF_NETROM, SOCK_SEQPACKET, 0)) < 0) {
+ if (logging)
+ syslog(LOG_ERR, "netromt: socket: %m");
+ exit(1);
+ }
+
+ if (ioctl(s, SIOCNRDECOBS, &i) == -1) {
+ if (logging)
+ syslog(LOG_ERR, "netromt: SIOCNRDECOBS: %m");
+ exit(1);
+ }
+
+ close(s);
+
+ exit(0);
+}
diff --git a/netrom/nodesave.8 b/netrom/nodesave.8
new file mode 100644
index 0000000..626778b
--- /dev/null
+++ b/netrom/nodesave.8
@@ -0,0 +1,31 @@
+.TH NODESAVE 8 "21 May 1996" Linux "Linux System Managers Manual"
+.SH NAME
+nodesave \- Saves NET/ROM routing information
+.SH SYNOPSIS
+.B nodesave [filename]
+.SH DESCRIPTION
+.LP
+.B Nodesave
+saves the contents of the /proc filesystem entries for the NET/ROM routing
+tables. The output of the program is in the form of a Bourne shell script
+that calls nrparms(8) to recreate the NET/ROM routing information. If no
+filename is given on the command line, the program writes the script to
+stdout.
+.LP
+Typically
+.B nodesave
+would be used when taking a system off-air so that the NET/ROM routing may
+be quickly restored when the system is brought back on-line.
+.SH FILES
+.nf
+/proc/net/nr_neigh
+.br
+/proc/net/nr_nodes
+.fi
+.SH "SEE ALSO"
+.BR netrom (4),
+.BR netromd (8),
+.BR nrparms (8).
+.LP
+.SH AUTHOR
+Tomi Manninen OH2BNS <tpmannin@cc.hut.fi>
diff --git a/netrom/nodesave.c b/netrom/nodesave.c
new file mode 100644
index 0000000..3eab61b
--- /dev/null
+++ b/netrom/nodesave.c
@@ -0,0 +1,101 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+
+#include <netax25/ax25.h>
+
+#include <netax25/axconfig.h>
+
+#include <netax25/procutils.h>
+
+int main(int argc, char **argv)
+{
+ FILE *fp = stdout;
+ struct proc_nr_nodes *nodes, *nop;
+ struct proc_nr_neigh *neighs, *nep;
+
+ if (ax25_config_load_ports() == 0) {
+ fprintf(stderr, "nodesave: no AX.25 port data configured\n");
+ return 1;
+ }
+
+ if (argc > 1) {
+ if ((fp = fopen(argv[1], "w")) == NULL) {
+ fprintf(stderr, "nodesave: cannot open file %s\n", argv[1]);
+ return 1;
+ }
+ }
+
+ if ((neighs = read_proc_nr_neigh()) == NULL && errno != 0) {
+ perror("nodesave: read_proc_nr_neigh");
+ fclose(fp);
+ return 1;
+ }
+
+ if ((nodes = read_proc_nr_nodes()) == NULL && errno != 0) {
+ perror("nodesave: read_proc_nr_nodes");
+ free_proc_nr_neigh(neighs);
+ fclose(fp);
+ return 1;
+ }
+
+ fprintf(fp, "#! /bin/sh\n#\n# Locked routes:\n#\n");
+
+ for (nep = neighs; nep != NULL; nep = nep->next) {
+ if (nep->lock) {
+ fprintf(fp, "nrparms -routes \"%s\" %s + %d\n",
+ ax25_config_get_name(nep->dev),
+ nep->call,
+ nep->qual);
+ }
+ }
+
+ fprintf(fp, "#\n# Nodes:\n#\n");
+
+ for (nop = nodes; nop != NULL; nop = nop->next) {
+ if ((nep = find_neigh(nop->addr1, neighs)) != NULL) {
+ fprintf(fp, "nrparms -nodes %s + \"%s\" %d %d \"%s\" %s\n",
+ nop->call,
+ nop->alias,
+ nop->qual1,
+ nop->obs1,
+ ax25_config_get_name(nep->dev),
+ nep->call);
+ }
+
+ if (nop->n > 1 && (nep = find_neigh(nop->addr2, neighs)) != NULL) {
+ fprintf(fp, "nrparms -nodes %s + \"%s\" %d %d \"%s\" %s\n",
+ nop->call,
+ nop->alias,
+ nop->qual2,
+ nop->obs2,
+ ax25_config_get_name(nep->dev),
+ nep->call);
+ }
+
+ if (nop->n > 2 && (nep = find_neigh(nop->addr3, neighs)) != NULL) {
+ fprintf(fp, "nrparms -nodes %s + \"%s\" %d %d \"%s\" %s\n",
+ nop->call,
+ nop->alias,
+ nop->qual3,
+ nop->obs3,
+ ax25_config_get_name(nep->dev),
+ nep->call);
+ }
+ }
+
+ free_proc_nr_neigh(neighs);
+ free_proc_nr_nodes(nodes);
+
+ fclose(fp);
+
+ if (argc > 1) {
+ chmod(argv[1], S_IEXEC);
+ }
+
+ return 0;
+}
diff --git a/netrom/nrattach.8 b/netrom/nrattach.8
new file mode 100644
index 0000000..692e3f2
--- /dev/null
+++ b/netrom/nrattach.8
@@ -0,0 +1,39 @@
+.TH NRATTACH 8 "21 May 1996" Linux "Linux System Managers Manual"
+.SH NAME
+nrattach \- Start a NET/ROM interface
+.SH SYNOPSIS
+.B nrattach [-i inetaddr] [-m mtu] [-v] port
+.SH DESCRIPTION
+.LP
+.B Nrattach
+takes many of the parameters for the port from the nrports(5) file. The
+paclen parameter is used for the device mtu unless overridden by a value on
+the command line. The port argument is the name of a port as given in the
+nrports(5) file.
+.LP
+.B Nrattach
+tries to find the first free NET/ROM device in the system. The devices
+checked are nr0, nr1, nr2 and nr3 in that order. If no free NET/ROM 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 "\-m mtu"
+Sets the mtu of the interface. If this value is not given then the value is
+taken from the paclen parameter in nrports.
+.TP 16
+.BI \-v
+Display the version.
+.SH "SEE ALSO"
+.BR netrom (4),
+.BR nrparms (4),
+.BR nrports (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/netrom/nrattach.c b/netrom/nrattach.c
new file mode 100644
index 0000000..aee0936
--- /dev/null
+++ b/netrom/nrattach.c
@@ -0,0 +1,240 @@
+#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 <net/if.h>
+#include <net/if_arp.h>
+
+#include <netax25/ax25.h>
+#include <netrose/rose.h>
+#include <netax25/axlib.h>
+
+#include <config.h>
+
+#include "../pathnames.h"
+
+char *callsign;
+int mtu = 0;
+
+int readconfig(char *port)
+{
+ FILE *fp;
+ char buffer[90], *s;
+ int n = 0;
+
+ if ((fp = fopen(CONF_NRPORTS_FILE, "r")) == NULL) {
+ fprintf(stderr, "nrattach: cannot open nrports 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, "nrattach: unable to parse line %d of the nrports file\n", n);
+ return FALSE;
+ }
+
+ if (strcmp(s, port) != 0)
+ continue;
+
+ if ((s = strtok(NULL, " \t\r\n")) == NULL) {
+ fprintf(stderr, "nrattach: unable to parse line %d of the nrports file\n", n);
+ return FALSE;
+ }
+
+ callsign = strdup(s);
+
+ if ((s = strtok(NULL, " \t\r\n")) == NULL) {
+ fprintf(stderr, "nrattach: unable to parse line %d of the nrports file\n", n);
+ return FALSE;
+ }
+
+ if ((s = strtok(NULL, " \t\r\n")) == NULL) {
+ fprintf(stderr, "nrattach: unable to parse line %d of the nrports file\n", n);
+ return FALSE;
+ }
+
+ if (mtu == 0) {
+ if ((mtu = atoi(s)) <= 0) {
+ fprintf(stderr, "nrattach: invalid paclen setting\n");
+ return FALSE;
+ }
+ }
+
+ fclose(fp);
+
+ return TRUE;
+ }
+
+ fclose(fp);
+
+ fprintf(stderr, "nrattach: cannot find port %s in nrports\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("nrattach: socket");
+ return FALSE;
+ }
+
+ for (i = 0; i < 4; i++) {
+ sprintf(dev, "nr%d", i);
+ strcpy(ifr.ifr_name, dev);
+
+ if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
+ perror("nrattach: 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 call[7];
+ int fd;
+
+ if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ perror("nrattach: 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("nrattach: SIOCSIFADDR");
+ return FALSE;
+ }
+ }
+
+ if (ax25_aton_entry(callsign, call) == -1)
+ return FALSE;
+
+ ifr.ifr_hwaddr.sa_family = ARPHRD_NETROM;
+ memcpy(ifr.ifr_hwaddr.sa_data, call, 7);
+
+ if (ioctl(fd, SIOCSIFHWADDR, &ifr) != 0) {
+ perror("nrattach: SIOCSIFHWADDR");
+ return FALSE;
+ }
+
+ ifr.ifr_mtu = mtu;
+
+ if (ioctl(fd, SIOCSIFMTU, &ifr) < 0) {
+ perror("nrattach: SIOCSIFMTU");
+ return FALSE;
+ }
+
+ if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
+ perror("nrattach: 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("nrattach: 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, "nrattach: invalid internet name/address - %s\n", optarg);
+ return 1;
+ }
+ break;
+ case 'm':
+ if ((mtu = atoi(optarg)) <= 0) {
+ fprintf(stderr, "nrattach: invalid mtu size - %s\n", optarg);
+ return 1;
+ }
+ break;
+ case 'v':
+ printf("nrattach: %s\n", VERSION);
+ return 0;
+ case ':':
+ case '?':
+ fprintf(stderr, "usage: nrattach [-i inetaddr] [-m mtu] [-v] port\n");
+ return 1;
+ }
+ }
+
+ if ((argc - optind) != 1) {
+ fprintf(stderr, "usage: nrattach [-i inetaddr] [-m mtu] [-v] port\n");
+ return 1;
+ }
+
+ if (!readconfig(argv[optind]))
+ return 1;
+
+ if (!getfreedev(dev)) {
+ fprintf(stderr, "nrattach: cannot find free NET/ROM device\n");
+ return 1;
+ }
+
+ if (!startiface(dev, hp))
+ return 1;
+
+ printf("NET/ROM port %s bound to device %s\n", argv[optind], dev);
+
+ return 0;
+}
diff --git a/netrom/nrbroadcast b/netrom/nrbroadcast
new file mode 100644
index 0000000..8584b22
--- /dev/null
+++ b/netrom/nrbroadcast
@@ -0,0 +1,8 @@
+# /etc/ax25/nrbroadcast
+#
+# The format of this file is:
+#
+# ax25_name min_obs def_qual worst_qual verbose
+#
+1 5 192 100 0
+2 5 255 100 1
diff --git a/netrom/nrbroadcast.5 b/netrom/nrbroadcast.5
new file mode 100644
index 0000000..7258bc7
--- /dev/null
+++ b/netrom/nrbroadcast.5
@@ -0,0 +1,49 @@
+.TH NRBROADCAST 5 "2 August 1996" Linux "Linux Programmer's Manual"
+.SH NAME
+nrbroadcast \- NET/ROM routing broadcast configuration file.
+.SH DESCRIPTION
+.LP
+.B Nrbroadcast
+is an ASCII file that contains information about each of the physical AX.25
+ports that are to have NET/ROM routing broadcasts transmitted from them.
+.LP
+Each line has the following format, each field being delimited by white space:
+.sp
+.RS
+port minobs defqual worstqual verbose
+.RE
+.sp
+The field descriptions are:
+.sp
+.RS
+.TP 14
+.B port
+the port name of the AX.25 port to broadcast on.
+.TP
+.B minobs
+this is the minimum obsolescence count of a routing table entry to be
+broadcast on this port.
+.TP
+.B defqual
+this is the default quality of an incoming routing broadcast from an unknown
+neighbour.
+.TP
+.B worstqual
+this is the worst quality node received from a routing broadcast that will
+be added to our routing table.
+.TP
+.B verbose
+whether the routes to all of my nodes in my routing table, or just the nodes
+resident on my machine are to be broadcast.
+.RE
+.SH FILES
+.LP
+/etc/ax25/nrbroadcast
+.br
+/etc/ax25/axports
+.SH "SEE ALSO"
+.BR call (1),
+.BR netrom (4),
+.BR axports (5),
+.BR netromd (8),
+.BR nrparms (8).
diff --git a/netrom/nrparms.8 b/netrom/nrparms.8
new file mode 100644
index 0000000..38d3dd8
--- /dev/null
+++ b/netrom/nrparms.8
@@ -0,0 +1,76 @@
+.TH NRPARMS 8 "25 January 1997" Linux "Linux System Managers Manual"
+.SH NAME
+nrparms \- Configure the NET/ROM interface.
+.SH SYNOPSIS
+.B nrparms -nodes node +|- ident quality count port neighbour [digicall...]
+.LP
+.B nrparms -routes port nodecall [digicall...] +|- quality
+.LP
+.B nrparms -version
+.SH DESCRIPTION
+.LP
+This program is used to manipulate the routing tables of the NET/ROM network
+layer, or to get and set many of the network and transport layer parameters
+for the NET/ROM protocol. The program has three basic modes of operation,
+node setting, neighbour setting and general parameter setting. The syntax
+for the node and neighbour setting is taken from the original NET/ROM manual
+and is therefore not very UNIXy but should be familiar to those familiar
+with NET/ROMs or TheNet.
+.LP
+To set up a new route to a NET/ROM 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 nrparms -nodes GB7BPQ + NMCLUS 120 6 vhf G8ROU-3
+.LP
+This creates a new route to a distant node with the callsign GB7BPQ and the
+alias NMCLUS, it has a quality of 120 (out of 255) and has an obsolescence
+count of six and packets for that node should be sent on the AX.25 port named
+vhf to my immediate neighbour G8ROU-3. The callsigns of the node and the
+neighbour may be the same. For example to set up the node G8ROU-3 which is
+also my immediate neighbour, I would use:
+.LP
+.B nrparms -nodes G8ROU-3 + MATLCK 200 6 vhf G8ROU-3
+.LP
+If the ident of the remote node is not known, it is possible to add a
+node with a blank ident. To do this an ident of '*' must be entered on
+the command line. Because of the command line expansion that shells do, the *
+must be escaped by enclosing it in quotes.
+.LP
+It is also possible to remove a route to a distant node with the same
+command except that the + is replaced by a -. The other parameters must also
+be present. If the node has not 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, and it is not a locked neighbour entry.
+.LP
+When setting up a new node, a new neighbour entry may also be created. This
+will have a default value. For that neighbour to be meaningful in the
+automatic routing process, it must have a more reasonable entry in the
+neighbours list. To do this the routes option of the command must be used.
+An example:
+.LP
+.B nrparms -routes ax0 G8ROU-3 + 120
+.LP
+This will create (or update) the neighbour entry for G8ROU-3 with a quality
+of 120 and it will be locked, it will not create a node entry for the
+neighbour. This quality will be used by the
+.BR netromd (8)
+program when calculating route qualities via this neighbour. Normally once a
+neighbour has zero node routes going via it, it will be deleted. Locking a
+neighbour prevents the deletion from occurring. To unlock a neighbour entry,
+the same command is used but with the + replaced by a -.
+.SH FILES
+.LP
+/etc/ax25/axports
+.br
+/etc/ax25/nrports
+.SH "SEE ALSO"
+.BR call (1),
+.BR netrom (4),
+.BR nrports (5),
+.BR axparms (8),
+.BR netromd (8),
+.BR nrctl (8),
+.BR nrparms (8).
+.SH AUTHOR
+Jonathan Naylor G4KLX <g4klx@g4klx.demon.co.uk>
diff --git a/netrom/nrparms.c b/netrom/nrparms.c
new file mode 100644
index 0000000..7e89ff9
--- /dev/null
+++ b/netrom/nrparms.c
@@ -0,0 +1,239 @@
+#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 <netrom/netrom.h>
+#include <netrose/rose.h>
+
+#include <netax25/axlib.h>
+#include <netax25/axconfig.h>
+#include <netax25/nrconfig.h>
+
+#include <config.h>
+
+char nodes_usage[] = "usage: nrparms -nodes nodecall +|- ident quality count port neighbour [digicall...]\n";
+char routes_usage[] = "usage: nrparms -routes port nodecall [digicall...] +|- pathquality\n";
+
+void nodes(int s, char *nodecall, char *op, char *ident, int quality, int count, char *port, char *neighbour, char *digis[])
+{
+ struct nr_route_struct nr_node;
+ char *p, *q, *dev;
+ int i;
+
+ if (ax25_config_load_ports() == 0) {
+ fprintf(stderr, "nrparms: nodes: no AX.25 ports configured\n");
+ exit(1);
+ }
+
+ nr_node.type = NETROM_NODE;
+ /*nr_node.ndigis = 0;*/
+
+ if (op[0] != '+' && op[0] != '-') {
+ fprintf(stderr, "nrparms: nodes: invalid operation %s\n", op);
+ close(s);
+ exit(1);
+ }
+
+ if (quality < 1 || quality > 255) {
+ fprintf(stderr, "nrparms: nodes: invalid quality %d\n", quality);
+ close(s);
+ exit(1);
+ }
+
+ if (count < 1 || count > 6) {
+ fprintf(stderr, "nrparms: nodes: invalid obs count %d\n", count);
+ close(s);
+ exit(1);
+ }
+
+ if (ax25_aton_entry(nodecall, nr_node.callsign.ax25_call) != 0) {
+ fprintf(stderr, "nrparms: nodes: invalid callsign %s\n", nodecall);
+ close(s);
+ exit(1);
+ }
+
+ if (strlen(ident) > 7) {
+ fprintf(stderr, "nrparms: nodes: invalid length of mnemonic %s\n", ident);
+ close(s);
+ exit(1);
+ }
+
+ if (strcmp(ident, "*") != 0) {
+ for (p = ident, q = nr_node.mnemonic; *p != '\0'; p++, q++)
+ *q = toupper(*p);
+ *q = '\0';
+
+ if (strspn(nr_node.mnemonic, "&#-_/ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") != strlen(nr_node.mnemonic)) {
+ fprintf(stderr, "nrparms: nodes: invalid ident %s\n", ident);
+ close(s);
+ exit(1);
+ }
+ } else {
+ strcpy(nr_node.mnemonic, "");
+ }
+
+ if (ax25_aton_entry(neighbour, nr_node.neighbour.ax25_call) != 0) {
+ fprintf(stderr, "nrparms: nodes: invalid callsign %s\n", neighbour);
+ close(s);
+ exit(1);
+ }
+ /*
+ for (i = 0; i < AX25_MAX_DIGIS && digis[i] != NULL; i++) {
+ if (ax25_aton_entry(digis[i], nr_node.digipeaters[i].ax25_call) != 0) {
+ fprintf(stderr, "nrparms: invalid callsign %s\n", digis[i]);
+ close(s);
+ exit(1);
+ }
+ nr_node.ndigis++;
+ } */
+
+ if ((dev = ax25_config_get_dev(port)) == NULL) {
+ fprintf(stderr, "nrparms: nodes: invalid port name - %s\n", port);
+ close(s);
+ exit(1);
+ }
+
+ strcpy(nr_node.device, dev);
+
+ nr_node.quality = quality;
+ nr_node.obs_count = count;
+
+ if (op[0] == '+') {
+ if (ioctl(s, SIOCADDRT, &nr_node) == -1) {
+ perror("nrparms: SIOCADDRT");
+ close(s);
+ exit(1);
+ }
+ } else {
+ if (ioctl(s, SIOCDELRT, &nr_node) == -1) {
+ perror("nrparms: SIOCDELRT");
+ close(s);
+ exit(1);
+ }
+ }
+}
+
+void routes(int s, char *port, char *nodecall, char *rest[])
+{
+ struct nr_route_struct nr_neigh;
+ char *dev, *op;
+ int i, quality;
+
+ if (ax25_config_load_ports() == 0) {
+ fprintf(stderr, "nrparms: routes: no AX.25 ports configured\n");
+ exit(1);
+ }
+
+ nr_neigh.type = NETROM_NEIGH;
+ /*nr_neigh.ndigis = 0;
+
+ for (i = 0; i < AX25_MAX_DIGIS && rest[i][0] != '-' && rest[i][0] != '+'; i++) {
+ if (ax25_aton_entry(rest[i], nr_neigh.digipeaters[i].ax25_call) != 0) {
+ fprintf(stderr, "nrparms: routes: invalid callsign %s\n", rest[i]);
+ close(s);
+ exit(1);
+ }
+ nr_neigh.ndigis++;
+ }
+ */
+
+ op = rest[i + 0];
+ quality = atoi(rest[i + 1]);
+
+ if (op[0] != '+' && op[0] != '-') {
+ fprintf(stderr, "nrparms: routes: invalid operation %s\n", op);
+ close(s);
+ exit(1);
+ }
+
+ if (quality < 1 || quality > 255) {
+ fprintf(stderr, "nrparms: routes: invalid quality %d\n", quality);
+ close(s);
+ exit(1);
+ }
+
+ if ((dev = ax25_config_get_dev(port)) == NULL) {
+ fprintf(stderr, "nrparms: routes: invalid port name - %s\n", port);
+ close(s);
+ exit(1);
+ }
+
+ strcpy(nr_neigh.device, dev);
+
+ if (ax25_aton_entry(nodecall, nr_neigh.callsign.ax25_call) != 0) {
+ fprintf(stderr, "nrparms: routes: invalid callsign %s\n", nodecall);
+ close(s);
+ exit(1);
+ }
+
+ nr_neigh.quality = quality;
+
+ if (op[0] == '+') {
+ if (ioctl(s, SIOCADDRT, &nr_neigh) == -1) {
+ perror("nrparms: SIOCADDRT");
+ close(s);
+ exit(1);
+ }
+ } else {
+ if (ioctl(s, SIOCDELRT, &nr_neigh) == -1) {
+ perror("nrparms: SIOCDELRT");
+ close(s);
+ exit(1);
+ }
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ int s;
+
+ if (argc == 1) {
+ fprintf(stderr, "usage: nrparms -nodes|-routes|-version ...\n");
+ return 1;
+ }
+
+ if (strncmp(argv[1], "-v", 2) == 0) {
+ printf("nrparms: %s\n", VERSION);
+ return 0;
+ }
+
+ if ((s = socket(AF_NETROM, SOCK_SEQPACKET, 0)) < 0) {
+ perror("nrparms: socket");
+ return 1;
+ }
+
+ if (strncmp(argv[1], "-n", 2) == 0) {
+ if (argc < 9) {
+ fprintf(stderr, nodes_usage);
+ close(s);
+ return 1;
+ }
+ nodes(s, argv[2], argv[3], argv[4], atoi(argv[5]), atoi(argv[6]), argv[7], argv[8], argv + 9);
+ close(s);
+ return 0;
+ }
+
+ if (strncmp(argv[1], "-r", 2) == 0) {
+ if (argc < 6) {
+ fprintf(stderr, routes_usage);
+ close(s);
+ return 1;
+ }
+ routes(s, argv[2], argv[3], argv + 4);
+ close(s);
+ return 0;
+ }
+
+ fprintf(stderr, "usage: nrparms -nodes|-routes|-version ...\n");
+
+ close(s);
+
+ return 1;
+}
diff --git a/netrom/nrports b/netrom/nrports
new file mode 100644
index 0000000..4faa359
--- /dev/null
+++ b/netrom/nrports
@@ -0,0 +1,7 @@
+# /etc/ax25/nrports
+#
+# The format of this file is:
+#
+# name callsign alias paclen description
+#
+netrom OH2BNS-10 #LNODE 235 Switch Port
diff --git a/netrom/nrports.5 b/netrom/nrports.5
new file mode 100644
index 0000000..3449113
--- /dev/null
+++ b/netrom/nrports.5
@@ -0,0 +1,56 @@
+.TH NRPORTS 5 "2 August 1996" Linux "Linux Programmer's Manual"
+.SH NAME
+nrports \- NET/ROM port configuration file.
+.SH DESCRIPTION
+.LP
+.B Nrports
+is an ASCII file that contains information about each of the NET/ROM
+ports that are to be used. When dealing with an NET/ROM 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 nrports,
+which has the same name. The information on each line contains
+enough information to bind the command to a particular NET/ROM
+interface, this binding is done by matching the callsign on the line in
+.B nrports
+with the callsign of the port set by
+.B ifconfig.
+.LP
+The
+.B nrports
+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 callsign alias paclen description
+.RE
+.sp
+The field descriptions are:
+.sp
+.RS
+.TP 14
+.B name
+this is the unique NET/ROM port identifier.
+.TP 14
+.B callsign
+the callsign of the NET/ROM interface to bind to.
+.TP 14
+.B alias
+this is the alias of the NET/ROM port.
+.TP 14
+.B paclen
+is the default packet size for this interface.
+.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/nrports
+.SH "SEE ALSO"
+.BR call (1),
+.BR netrom (4),
+.BR ifconfig (8),
+.BR nrparms (8).
diff --git a/netrom/nrsdrv.8 b/netrom/nrsdrv.8
new file mode 100644
index 0000000..fb27562
--- /dev/null
+++ b/netrom/nrsdrv.8
@@ -0,0 +1,44 @@
+.TH NRSDRV 8 "22 December 1996" Linux "Linux System Managers Manual"
+.SH NAME
+nrsdrv \- KISS to NET/ROM serial converter
+.SH SYNOPSIS
+.B nrsdrv [-f] [-l] [-s speed] [-v] kissdev nrsdev
+.SH DESCRIPTION
+.LP
+.B Nrsdrv
+is a program designed to convert from the KISS protocol to the NET/ROM
+serial protocol used by real NET/ROM's and TheNet's. The protocols are
+fairly similar, although the NET/ROM serial protocol does include a one byte
+checksum which KISS does not.
+.sp 1
+Typically
+.B nrsdrv
+will be attached to one end of a pseudo-tty of which the other end has been
+attached to a KISS capable program. The NET/ROM device will probably be a
+real serial port attached to a TNC or a Hexipus. The full specification of
+the NET/ROM serial protocol can be found in the original Software 2000
+documentation that accompanied NET/ROMs.
+.SH OPTIONS
+.TP 10
+.BI \-f
+Flow control enabled for use with a Hexipus, the default is disabled.
+See the file hexipus.txt in the source distribution for wiring details.
+
+.TP 10
+.BI \-l
+Log messages to the system log, the default is not to.
+.TP 10
+.BI "\-s speed"
+Sets the speed of both interfaces. If no value is specified then no speed
+will be set.
+.TP 10
+.BI \-v
+Display the version.
+.SH BUGS
+None known.
+.SH "SEE ALSO"
+.BR kill (1),
+.BR stty (1),
+.BR ax25 (4).
+.SH AUTHOR
+Jonathan Naylor G4KLX <g4klx@g4klx.demon.co.uk>
diff --git a/netrom/nrsdrv.c b/netrom/nrsdrv.c
new file mode 100644
index 0000000..92b3d6a
--- /dev/null
+++ b/netrom/nrsdrv.c
@@ -0,0 +1,457 @@
+#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 <syslog.h>
+
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+
+#include <sys/socket.h>
+#include <netax25/daemon.h>
+#include <netax25/ttyutils.h>
+
+#include <config.h>
+
+#include "../pathnames.h"
+
+static int kissfd, nrsfd;
+static int logging = FALSE;
+static int debugging = FALSE;
+static int flowcontrol = FALSE;
+static char *kissdev, *nrsdev;
+
+#define NUL 000
+#define STX 002
+#define ETX 003
+#define DLE 020
+
+#define NRS_WAIT 0
+#define NRS_DATA 1
+#define NRS_ESCAPE 2
+#define NRS_CKSUM 3
+static int nrs_state = NRS_WAIT;
+
+static unsigned char nrs_cksum = 0;
+
+static unsigned char nrs_rxbuffer[512];
+static int nrs_rxcount = 0;
+
+#define FEND 0300
+#define FESC 0333
+#define FESCEND 0334
+#define FESCESC 0335
+
+#define KISS_WAIT 0
+#define KISS_CTRL 1
+#define KISS_DATA 2
+#define KISS_ESCAPE 3
+static int kiss_state = KISS_WAIT;
+
+static unsigned char kiss_rxbuffer[512];
+static int kiss_rxcount = 0;
+
+static void terminate(int sig)
+{
+ if (logging) {
+ syslog(LOG_INFO, "terminating on SIGTERM\n");
+ closelog();
+ }
+
+ tty_unlock(kissdev);
+ tty_unlock(nrsdev);
+
+ exit(0);
+}
+
+static void key_rts(int fd)
+{
+ int status;
+
+ if (!flowcontrol)
+ return;
+
+ /* Wait for CTS to be low */
+ while (1) {
+ /* Get CTS status */
+ if (ioctl(fd, TIOCMGET, &status) < 0) {
+ syslog(LOG_INFO|LOG_ERR, "TIOCMGET failed: flowcontrol disabled (%m)\n");
+ flowcontrol = 0;
+ return;
+ }
+ if (status & TIOCM_CTS) {
+ if (debugging) {
+ fprintf(stderr,"CTS high: waiting\n");
+ }
+ ioctl(fd, TIOCMIWAIT, &status);
+ } else {
+ break;
+ }
+ }
+
+ if (debugging) {
+ fprintf(stderr,"CTS low: keying RTS\n");
+ }
+ status |= TIOCM_RTS | TIOCM_DTR;
+ if (ioctl(fd, TIOCMSET, &status) < 0) {
+ syslog(LOG_INFO|LOG_ERR, "TIOCMGET failed: flowcontrol disabled (%m)\n");
+ flowcontrol = 0;
+ }
+}
+
+static void unkey_rts(int fd)
+{
+ int status;
+
+ if (!flowcontrol)
+ return;
+
+ if (debugging) {
+ fprintf(stderr,"Transmission finished: unkeying RTS\n");
+ }
+ ioctl(fd, TIOCMGET, &status);
+ status &= ~TIOCM_RTS;
+ status |= TIOCM_DTR;
+ if (ioctl(fd, TIOCMSET, &status) < 0) {
+ syslog(LOG_INFO|LOG_ERR, "TIOCMGET failed: flowcontrol disabled (%m)\n");
+ flowcontrol = 0;
+ }
+}
+
+static void nrs_esc(unsigned char *s, int len)
+{
+ static unsigned char buffer[512];
+ unsigned char *ptr = buffer;
+ unsigned char csum = 0;
+ unsigned char c;
+
+ *ptr++ = STX;
+
+ while (len-- > 0) {
+ switch (c = *s++) {
+ case STX:
+ case ETX:
+ case DLE:
+ *ptr++ = DLE;
+ /* Fall through */
+ default:
+ *ptr++ = c;
+ break;
+ }
+
+ csum += c;
+ }
+
+ *ptr++ = ETX;
+ *ptr++ = csum;
+ *ptr++ = NUL;
+ *ptr++ = NUL;
+
+ key_rts(nrsfd);
+ write(nrsfd, buffer, ptr - buffer);
+ unkey_rts(nrsfd);
+}
+
+static void kiss_esc(unsigned char *s, int len)
+{
+ static unsigned char buffer[512];
+ unsigned char *ptr = buffer;
+ unsigned char c;
+
+ *ptr++ = FEND;
+ *ptr++ = 0x00; /* KISS DATA */
+
+ while (len-- > 0) {
+ switch (c = *s++) {
+ case FESC:
+ *ptr++ = FESC;
+ *ptr++ = FESCESC;
+ break;
+ case FEND:
+ *ptr++ = FESC;
+ *ptr++ = FESCEND;
+ break;
+ default:
+ *ptr++ = c;
+ break;
+ }
+ }
+
+ *ptr++ = FEND;
+
+ write(kissfd, buffer, ptr - buffer);
+}
+
+static void nrs_unesc(unsigned char *buffer, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++) {
+ switch (nrs_state) {
+ case NRS_WAIT:
+ if (buffer[i] == STX) {
+ nrs_state = NRS_DATA;
+ nrs_rxcount = 0;
+ nrs_cksum = 0;
+ }
+ break;
+
+ case NRS_DATA:
+ switch (buffer[i]) {
+ case STX: /* !! */
+ nrs_rxcount = 0;
+ nrs_cksum = 0;
+ break;
+ case DLE:
+ nrs_state = NRS_ESCAPE;
+ break;
+ case ETX:
+ nrs_state = NRS_CKSUM;
+ break;
+ default:
+ if (nrs_rxcount < 512) {
+ nrs_cksum += buffer[i];
+ nrs_rxbuffer[nrs_rxcount++] = buffer[i];
+ }
+ break;
+ }
+ break;
+
+ case NRS_ESCAPE:
+ nrs_state = NRS_DATA;
+ if (nrs_rxcount < 512) {
+ nrs_cksum += buffer[i];
+ nrs_rxbuffer[nrs_rxcount++] = buffer[i];
+ }
+ break;
+
+ case NRS_CKSUM:
+ if (buffer[i] == nrs_cksum)
+ kiss_esc(nrs_rxbuffer, nrs_rxcount);
+ nrs_state = NRS_WAIT;
+ nrs_cksum = 0;
+ nrs_rxcount = 0;
+ break;
+ }
+ }
+}
+
+static void kiss_unesc(unsigned char *buffer, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++) {
+ switch (kiss_state) {
+ case KISS_WAIT:
+ if (buffer[i] == FEND) {
+ kiss_state = KISS_CTRL;
+ kiss_rxcount = 0;
+ }
+ break;
+
+ case KISS_CTRL:
+ if ((buffer[i] & 0x0F) == 0x00) {
+ kiss_state = KISS_DATA;
+ kiss_rxcount = 0;
+ } else {
+ kiss_state = KISS_WAIT;
+ kiss_rxcount = 0;
+ }
+ break;
+
+ case KISS_DATA:
+ switch (buffer[i]) {
+ case FEND:
+ if (kiss_rxcount > 2)
+ nrs_esc(kiss_rxbuffer, kiss_rxcount);
+ kiss_state = KISS_WAIT;
+ kiss_rxcount = 0;
+ break;
+ case FESC:
+ kiss_state = KISS_ESCAPE;
+ break;
+ default:
+ if (kiss_rxcount < 512)
+ kiss_rxbuffer[kiss_rxcount++] = buffer[i];
+ break;
+ }
+ break;
+
+ case KISS_ESCAPE:
+ kiss_state = KISS_DATA;
+ switch (buffer[i]) {
+ case FESCESC:
+ if (kiss_rxcount < 512)
+ kiss_rxbuffer[kiss_rxcount++] = FESC;
+ break;
+ case FESCEND:
+ if (kiss_rxcount < 512)
+ kiss_rxbuffer[kiss_rxcount++] = FEND;
+ break;
+ }
+ break;
+ }
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ static char buffer[512];
+ unsigned int speed = 0;
+ fd_set read_fd;
+ int c, n;
+
+ while ((c = getopt(argc, argv, "dfls:v")) != -1) {
+ switch (c) {
+ case 'd':
+ debugging = TRUE;
+ break;
+ case 'f':
+ flowcontrol = TRUE;
+ break;
+ case 'l':
+ logging = TRUE;
+ break;
+ case 's':
+ if ((speed = atoi(optarg)) <= 0) {
+ fprintf(stderr, "nrsdrv: invalid speed %s\n", optarg);
+ return 1;
+ }
+ break;
+ case 'v':
+ printf("kissattach: %s\n", VERSION);
+ return 0;
+ case ':':
+ case '?':
+ fprintf(stderr, "usage: nrsdrv [-f] [-l] [-s speed] [-v] kisstty nrstty\n");
+ return 1;
+ }
+ }
+
+ if (debugging) {
+ fprintf(stderr,"Flow control %s\n",
+ flowcontrol ? "enabled" : "disabled");
+ }
+
+ if ((argc - optind) != 2) {
+ fprintf(stderr, "usage: nrsdrv [-f] [-l] [-s speed] [-v] kisstty nrstty\n");
+ return 1;
+ }
+
+ kissdev = argv[optind + 0];
+ nrsdev = argv[optind + 1];
+
+ if (tty_is_locked(kissdev)) {
+ fprintf(stderr, "nrsdrv: device %s already in use\n", argv[optind]);
+ return 1;
+ }
+
+ if (tty_is_locked(nrsdev)) {
+ fprintf(stderr, "nrsdrv: device %s already in use\n", argv[optind + 1]);
+ return 1;
+ }
+
+ if ((kissfd = open(kissdev, O_RDWR)) == -1) {
+ perror("nrsdrv: open kiss device");
+ return 1;
+ }
+
+ if ((nrsfd = open(nrsdev, O_RDWR)) == -1) {
+ perror("nrsdrv: open nrs device");
+ return 1;
+ }
+
+ tty_lock(kissdev);
+ tty_lock(nrsdev);
+
+ if (!tty_raw(kissfd, FALSE)) {
+ tty_unlock(kissdev);
+ tty_unlock(nrsdev);
+ return 1;
+ }
+
+ if (!tty_raw(nrsfd, FALSE)) {
+ tty_unlock(kissdev);
+ tty_unlock(nrsdev);
+ return 1;
+ }
+
+ if (speed != 0 && !tty_speed(kissfd, speed)) {
+ tty_unlock(kissdev);
+ tty_unlock(nrsdev);
+ return 1;
+ }
+
+ if (speed != 0 && !tty_speed(nrsfd, speed)) {
+ tty_unlock(kissdev);
+ tty_unlock(nrsdev);
+ return 1;
+ }
+
+ if (logging) {
+ openlog("nrsdrv", LOG_PID, LOG_DAEMON);
+ syslog(LOG_INFO, "KISS device %s connected to NRS device %s\n", argv[optind + 0], argv[optind + 1]);
+ }
+
+ signal(SIGHUP, SIG_IGN);
+ signal(SIGTERM, terminate);
+
+ /*
+ * Become a daemon if we can.
+ */
+ if (!daemon_start(FALSE)) {
+ fprintf(stderr, "nrsdrv: cannot become a daemon\n");
+ tty_unlock(kissdev);
+ tty_unlock(nrsdev);
+ return 1;
+ }
+
+ if (flowcontrol) {
+ unkey_rts(nrsfd);
+ }
+
+ c = ((kissfd > nrsfd) ? kissfd : nrsfd) + 1;
+
+ for (;;) {
+ FD_ZERO(&read_fd);
+
+ FD_SET(kissfd, &read_fd);
+ FD_SET(nrsfd, &read_fd);
+
+ n = select(c, &read_fd, NULL, NULL, NULL);
+
+ if (FD_ISSET(kissfd, &read_fd)) {
+ if ((n = read(kissfd, buffer, 512)) <= 0) {
+ if (logging) {
+ syslog(LOG_INFO, "terminating on KISS device closure\n");
+ closelog();
+ }
+ break;
+ }
+ kiss_unesc(buffer, n);
+ }
+
+ if (FD_ISSET(nrsfd, &read_fd)) {
+ if ((n = read(nrsfd, buffer, 512)) <= 0) {
+ if (logging) {
+ syslog(LOG_INFO, "terminating on NRS device closure\n");
+ closelog();
+ }
+ break;
+ }
+ nrs_unesc(buffer, n);
+ }
+ }
+
+ tty_unlock(kissdev);
+ tty_unlock(nrsdev);
+
+ return 0;
+}
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;
+}
diff --git a/stamp-h.in b/stamp-h.in
new file mode 100644
index 0000000..9788f70
--- /dev/null
+++ b/stamp-h.in
@@ -0,0 +1 @@
+timestamp
diff --git a/tcpip/Makefile.am b/tcpip/Makefile.am
new file mode 100644
index 0000000..d047ac5
--- /dev/null
+++ b/tcpip/Makefile.am
@@ -0,0 +1,23 @@
+
+etcfiles = rip98.conf ttylinkd.conf
+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 = rip98d ttylinkd
+
+man_MANS = rip98.conf.5 rip98d.8 ttylinkd.conf.5 ttylinkd.8
+
+EXTRA_DIST = $(man_MANS) $(etcfiles)
+
+rip98d_SOURCES = \
+ rip98d.c \
+ rip98r.c \
+ rip98t.c \
+ rip98d.h
+
diff --git a/tcpip/Makefile.in b/tcpip/Makefile.in
new file mode 100644
index 0000000..90da959
--- /dev/null
+++ b/tcpip/Makefile.in
@@ -0,0 +1,386 @@
+# 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 = rip98.conf ttylinkd.conf
+etcdir = $(sysconfdir)/ax25
+
+sbin_PROGRAMS = rip98d ttylinkd
+
+man_MANS = rip98.conf.5 rip98d.8 ttylinkd.conf.5 ttylinkd.8
+
+EXTRA_DIST = $(man_MANS) $(etcfiles)
+
+rip98d_SOURCES = rip98d.c rip98r.c rip98t.c rip98d.h
+
+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@
+rip98d_OBJECTS = rip98d.o rip98r.o rip98t.o
+rip98d_LDADD = $(LDADD)
+rip98d_DEPENDENCIES =
+rip98d_LDFLAGS =
+ttylinkd_SOURCES = ttylinkd.c
+ttylinkd_OBJECTS = ttylinkd.o
+ttylinkd_LDADD = $(LDADD)
+ttylinkd_DEPENDENCIES =
+ttylinkd_LDFLAGS =
+CFLAGS = @CFLAGS@
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+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 = $(rip98d_SOURCES) ttylinkd.c
+OBJECTS = $(rip98d_OBJECTS) ttylinkd.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 tcpip/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:
+
+rip98d: $(rip98d_OBJECTS) $(rip98d_DEPENDENCIES)
+ @rm -f rip98d
+ $(LINK) $(rip98d_LDFLAGS) $(rip98d_OBJECTS) $(rip98d_LDADD) $(LIBS)
+
+ttylinkd: $(ttylinkd_OBJECTS) $(ttylinkd_DEPENDENCIES)
+ @rm -f ttylinkd
+ $(LINK) $(ttylinkd_LDFLAGS) $(ttylinkd_OBJECTS) $(ttylinkd_LDADD) $(LIBS)
+
+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-man5 install-man8
+uninstall-man:
+ @$(NORMAL_UNINSTALL)
+ $(MAKE) $(AM_MAKEFLAGS) 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 = tcpip
+
+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
+rip98d.o: rip98d.c ../config.h ../pathnames.h rip98d.h
+rip98r.o: rip98r.c rip98d.h
+rip98t.o: rip98t.c rip98d.h
+ttylinkd.o: ttylinkd.c ../pathnames.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-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-man
+uninstall: uninstall-am
+all-am: Makefile $(PROGRAMS) $(MANS)
+all-redirect: all-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+installdirs:
+ $(mkinstalldirs) $(DESTDIR)$(sbindir) $(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 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/tcpip/rip98.conf b/tcpip/rip98.conf
new file mode 100644
index 0000000..3574d56
--- /dev/null
+++ b/tcpip/rip98.conf
@@ -0,0 +1 @@
+44.131.4.7
diff --git a/tcpip/rip98.conf.5 b/tcpip/rip98.conf.5
new file mode 100644
index 0000000..7e2d3a4
--- /dev/null
+++ b/tcpip/rip98.conf.5
@@ -0,0 +1,19 @@
+.TH RIP98.CONF 5 "2 August 1996" Linux "Linux Programmer's Manual"
+.SH NAME
+rip98.conf \- control RIP98 routing messages.
+.SH DESCRIPTION
+.LP
+.B Rip98.conf
+controls the transmission of RIP98 routing messages. RIP98 is not a
+broadcast protocol but instead is transmitted individually to each other
+known RIP98 capable system. The list of these systems is kept in the RIP98
+configuration file as a list of host names or IP numbers that are to be
+transmitted to, and messages received from.
+.SH FILES
+.LP
+/etc/ax25/rip98.conf
+.SH "SEE ALSO"
+.BR arp (8),
+.BR ifconfig (8),
+.BR rip98d (8),
+.BR route (8).
diff --git a/tcpip/rip98d.8 b/tcpip/rip98d.8
new file mode 100644
index 0000000..0ee12dc
--- /dev/null
+++ b/tcpip/rip98d.8
@@ -0,0 +1,59 @@
+.TH RIP98D 8 "20 August 1996" Linux "Linux System Managers Manual"
+.SH NAME
+rip98d \- Send and receive RIP98 routing messages
+.SH SYNOPSIS
+.B rip98d [-d] [-l] [-r] [-t interval] [-v]
+.SH DESCRIPTION
+.LP
+The RIP98 routing protocol was devised by John Wiseman G8BPQ as an
+alternative to both traditional RIP and RSPF for use in an RF environment.
+Its main advantage is that each routing element only takes six bytes and is
+therefore much more efficient in terms of bandwidth than other routing
+protocols.
+.LP
+In operation
+.B rip98d
+that each neighbour that also uses RIP98 must be listed. RIP98 is not a
+broadcast protocol and each neighbour is individually contacted. Any
+incoming RIP98 message is also validated against this list. The list of
+neighbours is held in /etc/ax25/rip98.conf, and each line is
+either the name or the dotted decimal IP address of the neighbour.
+.LP
+The time interval between RIP98 transmissions is set to one hour by default
+but other intervals can be set with the \-t option. The routes advertised
+and received can be restricted by the \-r option which only allows
+processing of ampr.org addresses. At present
+.B rip98d
+is under development and any feedback on its operation would be welcome.
+.SH OPTIONS
+.TP 16
+.BI \-d
+Set debugging on. Information is only output if the logging option is also
+enabled.
+.TP 16
+.BI \-l
+Enable logging to the system log, the default is off.
+.TP 16
+.BI \-r
+Restricts the transmitting and receiving of routes to ampr.org (44.x.x.x)
+addresses only.
+.TP 16
+.BI "\-t interval"
+The time interval between routing broadcasts, in minutes. The default is 60
+minutes.
+.TP 16
+.BI \-v
+Display the version.
+.SH FILES
+.nf
+/proc/net/route
+.br
+/etc/ax25/rip98.conf
+.fi
+.SH "SEE ALSO"
+.BR rip98.conf (5),
+.BR arp (8),
+.BR ifconfig (8),
+.BR route (8).
+.SH AUTHOR
+Jonathan Naylor G4KLX <g4klx@g4klx.demon.co.uk>
diff --git a/tcpip/rip98d.c b/tcpip/rip98d.c
new file mode 100644
index 0000000..78851cd
--- /dev/null
+++ b/tcpip/rip98d.c
@@ -0,0 +1,360 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <syslog.h>
+#include <signal.h>
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <net/route.h>
+
+#include <netax25/daemon.h>
+
+#include <config.h>
+
+#include "../pathnames.h"
+#include "rip98d.h"
+
+struct dest_struct dest_list[50];
+
+int dest_count = 0;
+
+int debug = FALSE;
+int restrict = FALSE;
+int logging = FALSE;
+
+struct route_struct *first_route = NULL;
+
+static struct mask_struct {
+ unsigned long int mask;
+ unsigned int bits;
+} mask_table[] = {
+ {0xFFFFFFFF, 32},
+ {0xFFFFFFFE, 31},
+ {0xFFFFFFFC, 30},
+ {0xFFFFFFF8, 29},
+ {0xFFFFFFF0, 28},
+ {0xFFFFFFE0, 27},
+ {0xFFFFFFC0, 26},
+ {0xFFFFFF80, 25},
+ {0xFFFFFF00, 24},
+ {0xFFFFFE00, 23},
+ {0xFFFFFC00, 22},
+ {0xFFFFF800, 21},
+ {0xFFFFF000, 20},
+ {0xFFFFE000, 19},
+ {0xFFFFC000, 18},
+ {0xFFFF8000, 17},
+ {0xFFFF0000, 16},
+ {0xFFFE0000, 15},
+ {0xFFFC0000, 14},
+ {0xFFF80000, 13},
+ {0xFFF00000, 12},
+ {0xFFE00000, 11},
+ {0xFFC00000, 10},
+ {0xFF800000, 9},
+ {0xFF000000, 8},
+ {0xFE000000, 7},
+ {0xFC000000, 6},
+ {0xF8000000, 5},
+ {0xF0000000, 4},
+ {0xE0000000, 3},
+ {0xC0000000, 2},
+ {0x80000000, 1},
+ {0x00000000, 0},
+};
+
+static void terminate(int sig)
+{
+ if (logging) {
+ syslog(LOG_INFO, "terminating on SIGTERM\n");
+ closelog();
+ }
+
+ exit(0);
+}
+
+unsigned int mask2bits(unsigned long int mask)
+{
+ struct mask_struct *t;
+
+ for (t = mask_table; t->mask != 0; t++)
+ if (mask == t->mask)
+ return t->bits;
+
+ return 0;
+}
+
+unsigned long int bits2mask(unsigned int bits)
+{
+ struct mask_struct *t;
+
+ for (t = mask_table; t->mask != 0; t++)
+ if (bits == t->bits)
+ return htonl(t->mask);
+
+ return 0;
+}
+
+static unsigned long int hex2intrev(char *buffer)
+{
+ unsigned long int result = 0L;
+
+ if (buffer[0] >= 'A')
+ result += (buffer[0] - 'A' + 10) * 16;
+ else
+ result += (buffer[0] - '0') * 16;
+
+ if (buffer[1] >= 'A')
+ result += buffer[1] - 'A' + 10;
+ else
+ result += buffer[1] - '0';
+
+ if (buffer[2] >= 'A')
+ result += (buffer[2] - 'A' + 10) * 16 * 16 * 16;
+ else
+ result += (buffer[2] - '0') * 16 * 16 * 16;
+
+ if (buffer[3] >= 'A')
+ result += (buffer[3] - 'A' + 10) * 16 * 16;
+ else
+ result += (buffer[3] - '0') * 16 * 16;
+
+ if (buffer[4] >= 'A')
+ result += (buffer[4] - 'A' + 10) * 16 * 16 * 16 * 16 * 16;
+ else
+ result += (buffer[4] - '0') * 16 * 16 * 16 * 16 * 16;
+
+ if (buffer[5] >= 'A')
+ result += (buffer[5] - 'A' + 10) * 16 * 16 * 16 * 16;
+ else
+ result += (buffer[5] - '0') * 16 * 16 * 16 * 16;
+
+ if (buffer[6] >= 'A')
+ result += (buffer[6] - 'A' + 10) * 16 * 16 * 16 * 16 * 16 * 16 * 16;
+ else
+ result += (buffer[6] - '0') * 16 * 16 * 16 * 16 * 16 * 16 * 16;
+
+ if (buffer[7] >= 'A')
+ result += (buffer[7] - 'A' + 10) * 16 * 16 * 16 * 16 * 16 * 16;
+ else
+ result += (buffer[7] - '0') * 16 * 16 * 16 * 16 * 16 * 16;
+
+ return result;
+}
+
+static int read_routes(void)
+{
+ struct route_struct *route, *temp;
+ char buffer[1023], iface[16], net_addr[64], gate_addr[64], mask_addr[64];
+ int n, iflags, refcnt, use, metric, mss, window;
+ struct in_addr address;
+ unsigned long int netmask;
+ unsigned long int network;
+ FILE *fp;
+
+ if (first_route != NULL) {
+ route = first_route;
+
+ while (route != NULL) {
+ temp = route->next;
+ free(route);
+ route = temp;
+ }
+
+ first_route = NULL;
+ }
+
+ if ((fp = fopen(PROC_IP_ROUTE_FILE, "r")) == NULL) {
+ if (logging)
+ syslog(LOG_ERR, "error cannot open %s\n", PROC_IP_ROUTE_FILE);
+ return FALSE;
+ }
+
+ while (fgets(buffer, 1023, fp) != NULL) {
+ n = sscanf(buffer, "%s %s %s %X %d %d %d %s %d %d\n",
+ iface, net_addr, gate_addr, &iflags, &refcnt, &use,
+ &metric, mask_addr, &mss, &window);
+
+ if (n != 10)
+ continue;
+
+ address.s_addr = htonl(hex2intrev(net_addr));
+ netmask = mask2bits(hex2intrev(mask_addr));
+
+ network = inet_netof(address);
+
+ if (network == 0 || network == 127) {
+ if (debug && logging)
+ syslog(LOG_DEBUG, "rejecting route to %s/%ld - should not be propogated\n", inet_ntoa(address), netmask);
+ continue;
+ }
+
+ if (restrict) {
+ if (inet_netof(address) != 44) {
+ if (debug && logging)
+ syslog(LOG_DEBUG, "rejecting route to %s/%ld - not ampr.org\n", inet_ntoa(address), netmask);
+ continue;
+ }
+ }
+
+ if ((route = malloc(sizeof(struct route_struct))) == NULL) {
+ if (logging)
+ syslog(LOG_ERR, "out of memory !\n");
+ return FALSE;
+ }
+
+ route->addr = address;
+ route->bits = netmask;
+ route->metric = metric;
+ route->action = (iflags & RTF_DYNAMIC) ? ORIG_ROUTE : FIXED_ROUTE;
+
+ route->next = first_route;
+ first_route = route;
+ }
+
+ fclose(fp);
+
+ return TRUE;
+}
+
+static int load_dests(void)
+{
+ struct hostent *host;
+ char buffer[255], *s;
+ FILE *fp;
+
+ if ((fp = fopen(CONF_RIP98D_FILE, "r")) == NULL) {
+ fprintf(stderr, "rip98d: cannot open config file\n");
+ return FALSE;
+ }
+
+ while (fgets(buffer, 255, fp) != NULL) {
+ if ((s = strchr(buffer, '\n')) != NULL) *s = '\0';
+
+ if ((host = gethostbyname(buffer)) == NULL) {
+ fprintf(stderr, "rip98d: cannot resolve name %s\n", buffer);
+ fclose(fp);
+ return FALSE;
+ }
+
+ bcopy(host->h_addr, (char *)&dest_list[dest_count].dest_addr, host->h_length);
+ dest_count++;
+ }
+
+ fclose(fp);
+
+ if (dest_count == 0)
+ return FALSE;
+
+ return TRUE;
+}
+
+int main(int argc, char **argv)
+{
+ int s, i;
+ struct sockaddr_in loc_addr;
+ struct timeval timeout;
+ time_t timenow, timelast = 0;
+ int interval = 3600;
+ fd_set fdset;
+
+ if (!load_dests()) {
+ fprintf(stderr, "rip98d: no destination routers defined\n");
+ return 1;
+ }
+
+ while ((i = getopt(argc, argv, "dlrt:v")) != -1) {
+ switch (i) {
+ case 'd':
+ debug = TRUE;
+ break;
+ case 'l':
+ logging = TRUE;
+ break;
+ case 'r':
+ restrict = TRUE;
+ break;
+ case 't':
+ interval = atoi(optarg) * 60;
+ if (interval < 60 || interval > 7200) {
+ fprintf(stderr, "rip98d: invalid time interval\n");
+ return 1;
+ }
+ break;
+ case 'v':
+ printf("rip98d: %s\n", VERSION);
+ return 0;
+ case ':':
+ fprintf(stderr, "rip98d: invalid time interval\n");
+ return 1;
+ case '?':
+ fprintf(stderr, "usage: rip98d [-d] [-l] [-r] [-t interval] [-v]\n");
+ return 1;
+ }
+ }
+
+ signal(SIGTERM, terminate);
+
+ if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ perror("rip98d: socket");
+ return 1;
+ }
+
+ bzero((char *)&loc_addr, sizeof(loc_addr));
+ loc_addr.sin_family = AF_INET;
+ loc_addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ loc_addr.sin_port = htons(RIP_PORT);
+
+ if (bind(s, (struct sockaddr *)&loc_addr, sizeof(loc_addr)) < 0) {
+ perror("rip98d: bind");
+ close(s);
+ return 1;
+ }
+
+ if (!daemon_start(FALSE)) {
+ fprintf(stderr, "rip98d: cannot become a daemon\n");
+ close(s);
+ return 1;
+ }
+
+ if (logging) {
+ openlog("rip98d", LOG_PID, LOG_DAEMON);
+ syslog(LOG_INFO, "starting");
+ }
+
+ for (;;) {
+ FD_ZERO(&fdset);
+ FD_SET(s, &fdset);
+
+ timeout.tv_sec = 60;
+ timeout.tv_usec = 0;
+
+ select(s + 1, &fdset, NULL, NULL, &timeout);
+
+ if (!read_routes()) {
+ if (logging)
+ closelog();
+ return 1;
+ }
+
+ if (FD_ISSET(s, &fdset))
+ receive_routes(s);
+
+ time(&timenow);
+
+ if ((timenow - timelast) > interval) {
+ timelast = timenow;
+ if (first_route != NULL)
+ transmit_routes(s);
+ }
+ }
+}
diff --git a/tcpip/rip98d.h b/tcpip/rip98d.h
new file mode 100644
index 0000000..fb00a7d
--- /dev/null
+++ b/tcpip/rip98d.h
@@ -0,0 +1,58 @@
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#define RIP_PORT 520
+
+#define RIPCMD_REQUEST 1
+#define RIPCMD_RESPONSE 2
+
+#define RIP98_INFINITY 16
+
+#define RIP_VERSION_98 98
+
+#define RIP_AF_INET 2
+
+#define RIP98_HEADER 4
+#define RIP98_ENTRY 6
+
+#define RIP98_MAX_FRAME 30
+
+struct route_struct {
+ struct route_struct *next;
+ struct in_addr addr;
+ int bits;
+ int metric;
+#define ORIG_ROUTE 0
+#define FIXED_ROUTE 1
+#define NEW_ROUTE 2
+#define DEL_ROUTE 3
+ int action;
+};
+
+extern struct route_struct *first_route;
+
+struct dest_struct {
+ struct in_addr dest_addr;
+};
+
+extern struct dest_struct dest_list[];
+
+extern int dest_count;
+
+extern int debug;
+extern int restrict;
+extern int logging;
+
+/* In rip98d.c */
+extern unsigned int mask2bits(unsigned long int);
+extern unsigned long int bits2mask(unsigned int);
+
+/* In rip98t.c */
+extern void transmit_routes(int);
+
+/* In rip98r.c */
+extern void receive_routes(int);
diff --git a/tcpip/rip98r.c b/tcpip/rip98r.c
new file mode 100644
index 0000000..765e786
--- /dev/null
+++ b/tcpip/rip98r.c
@@ -0,0 +1,255 @@
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <net/route.h>
+
+
+#include "rip98d.h"
+
+#define UNMATCH_ROUTE 0
+#define NO_ROUTE 1
+#define REPLACE_ROUTE 2
+#define ADDITIONAL_ROUTE 3
+
+static int cmp_route(struct route_struct *route, struct in_addr addr, int bits, int metric)
+{
+ unsigned long int old_mask, new_mask;
+ unsigned long int old_addr, new_addr;
+
+ old_mask = ntohl(bits2mask(route->bits));
+ new_mask = ntohl(bits2mask(bits));
+
+ old_addr = route->addr.s_addr;
+ new_addr = addr.s_addr;
+
+ if (bits < route->bits) {
+ new_addr = ntohl(new_addr) & new_mask;
+ old_addr = ntohl(old_addr) & new_mask;
+ } else {
+ new_addr = ntohl(new_addr) & old_mask;
+ old_addr = ntohl(old_addr) & old_mask;
+ }
+
+ if (route->action == DEL_ROUTE || route->action == NEW_ROUTE)
+ return UNMATCH_ROUTE;
+
+ if (old_addr != new_addr)
+ return UNMATCH_ROUTE;
+
+ if (route->metric <= metric)
+ return NO_ROUTE;
+
+ if (debug && logging) {
+ syslog(LOG_DEBUG, "comparing old: %s/%d to\n", inet_ntoa(route->addr), route->bits);
+ syslog(LOG_DEBUG, " new: %s/%d\n", inet_ntoa(addr), bits);
+ }
+
+ if (route->bits <= bits) {
+ if (route->action == ORIG_ROUTE) {
+ if (debug && logging)
+ syslog(LOG_DEBUG, " better route, replacing existing route\n");
+ return REPLACE_ROUTE;
+ } else {
+ if (debug && logging)
+ syslog(LOG_DEBUG, " better route, adding additional route\n");
+ return ADDITIONAL_ROUTE;
+ }
+ } else {
+ if (debug && logging)
+ syslog(LOG_DEBUG, " better route, adding additional route\n");
+ return ADDITIONAL_ROUTE;
+ }
+}
+
+void receive_routes(int s)
+{
+ unsigned char message[500], *p;
+ struct sockaddr_in rem_addr;
+ struct in_addr addr;
+ struct route_struct *route, *new;
+ struct sockaddr_in trg;
+ struct rtentry rt;
+ unsigned long int netmask;
+ unsigned long int network;
+ int bits, metric;
+ int size, found, matched;
+ int mess_len;
+ int i;
+
+ size = sizeof(struct sockaddr_in);
+
+ mess_len = recvfrom(s, message, 500, 0, (struct sockaddr *)&rem_addr, &size);
+
+ if (message[0] != RIPCMD_RESPONSE || message[1] != RIP_VERSION_98) {
+ if (debug && logging) {
+ syslog(LOG_DEBUG, "invalid RIP98 header received\n");
+ syslog(LOG_DEBUG, " cmd: %d vers: %d\n", message[0], message[1]);
+ }
+ return;
+ }
+
+ for (found = FALSE, i = 0; i < dest_count; i++) {
+ if (rem_addr.sin_addr.s_addr == dest_list[i].dest_addr.s_addr) {
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (!found) {
+ if (debug && logging)
+ syslog(LOG_DEBUG, "RIP98 message from unknown address %s\n", inet_ntoa(rem_addr.sin_addr));
+ return;
+ }
+
+ if (debug && logging)
+ syslog(LOG_DEBUG, "RIP98 message received from %s\n", inet_ntoa(rem_addr.sin_addr));
+
+ for (p = message + RIP98_HEADER; p < message + mess_len; p += RIP98_ENTRY) {
+ bcopy((char *)p, (char *)&addr, sizeof(addr));
+ bits = p[4];
+ metric = p[5];
+
+ network = inet_netof(addr);
+
+ if (network == 0 || network == 127) {
+ if (debug && logging)
+ syslog(LOG_DEBUG, " route to %s/%d metric %d - rejected\n", inet_ntoa(addr), bits, metric);
+ continue;
+ }
+
+ if (restrict) {
+ if (network != 44) {
+ if (debug && logging)
+ syslog(LOG_DEBUG, " route to %s/%d metric %d - rejected\n", inet_ntoa(addr), bits, metric);
+ continue;
+ }
+ }
+
+ if (debug && logging)
+ syslog(LOG_DEBUG, " route to %s/%d metric %d\n", inet_ntoa(addr), bits, metric);
+
+ metric++;
+
+ if (metric > RIP98_INFINITY)
+ metric = RIP98_INFINITY;
+
+ found = FALSE;
+ matched = FALSE;
+
+ for (route = first_route; route != NULL; route = route->next) {
+
+ switch (cmp_route(route, addr, bits, metric)) {
+
+ case NO_ROUTE:
+ matched = TRUE;
+ break;
+
+ case REPLACE_ROUTE:
+ route->action = DEL_ROUTE;
+
+ case ADDITIONAL_ROUTE:
+ if (!found) {
+ if ((new = malloc(sizeof(struct route_struct))) == NULL) {
+ if (logging)
+ syslog(LOG_ERR, "out of memory\n");
+ return;
+ }
+
+ new->addr = addr;
+ new->bits = bits;
+ new->metric = metric;
+ new->action = NEW_ROUTE;
+
+ new->next = first_route;
+ first_route = new;
+
+ found = TRUE;
+ }
+
+ matched = TRUE;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (!matched) {
+ if ((new = malloc(sizeof(struct route_struct))) == NULL) {
+ if (logging)
+ syslog(LOG_ERR, "out of memory\n");
+ return;
+ }
+
+ new->addr = addr;
+ new->bits = bits;
+ new->metric = metric;
+ new->action = NEW_ROUTE;
+
+ new->next = first_route;
+ first_route = new;
+ }
+ }
+
+ for (route = first_route; route != NULL; route = route->next) {
+ if (route->action == DEL_ROUTE) {
+ bzero((char *)&rt, sizeof(rt));
+
+ trg.sin_family = AF_INET;
+ trg.sin_addr = route->addr;
+ trg.sin_port = 0;
+ bcopy((char *)&trg, (char *)&rt.rt_dst, sizeof(struct sockaddr));
+
+ if (ioctl(s, SIOCDELRT, &rt) < 0) {
+ if (logging)
+ syslog(LOG_ERR, "SIOCDELRT: %m");
+ }
+ }
+ }
+
+ for (route = first_route; route != NULL; route = route->next) {
+ if (route->action == NEW_ROUTE) {
+ bzero((char *)&rt, sizeof(rt));
+
+ trg.sin_family = AF_INET;
+ trg.sin_addr = route->addr;
+ trg.sin_port = 0;
+ bcopy((char *)&trg, (char *)&rt.rt_dst, sizeof(struct sockaddr));
+
+ rt.rt_flags = RTF_UP | RTF_GATEWAY | RTF_DYNAMIC;
+
+ if (route->bits == 32) {
+ rt.rt_flags |= RTF_HOST;
+ } else {
+ netmask = bits2mask(route->bits);
+
+ trg.sin_family = AF_INET;
+ bcopy((char *)&netmask, (char *)&trg.sin_addr, sizeof(struct in_addr));
+ trg.sin_port = 0;
+ bcopy((char *)&trg, (char *)&rt.rt_genmask, sizeof(struct sockaddr));
+ }
+
+ rt.rt_metric = route->metric;
+
+ trg.sin_family = AF_INET;
+ trg.sin_addr = rem_addr.sin_addr;
+ trg.sin_port = 0;
+ bcopy((char *)&trg, (char *)&rt.rt_gateway, sizeof(struct sockaddr));
+
+ if (ioctl(s, SIOCADDRT, &rt) < 0) {
+ if (logging)
+ syslog(LOG_ERR, "SIOCADDRT: %m");
+ }
+ }
+ }
+}
diff --git a/tcpip/rip98t.c b/tcpip/rip98t.c
new file mode 100644
index 0000000..c227fc4
--- /dev/null
+++ b/tcpip/rip98t.c
@@ -0,0 +1,76 @@
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+
+#include <netinet/in.h>
+
+#include <arpa/inet.h>
+
+#include "rip98d.h"
+
+static int build_header(unsigned char *message)
+{
+ message[0] = RIPCMD_RESPONSE;
+ message[1] = RIP_VERSION_98;
+
+ message[2] = 0;
+ message[3] = 0;
+
+ return RIP98_HEADER;
+}
+
+
+void transmit_routes(int s)
+{
+ unsigned char message[500];
+ struct route_struct *route;
+ struct sockaddr_in rem_addr;
+ int mess_len;
+ int size;
+ int i;
+
+ size = sizeof(struct sockaddr_in);
+
+ for (i = 0; i < dest_count; i++) {
+
+ if (debug && logging)
+ syslog(LOG_DEBUG, "transmit_routes: sending routing message to %s\n", inet_ntoa(dest_list[i].dest_addr));
+
+ bzero((char *)&rem_addr, sizeof(rem_addr));
+ rem_addr.sin_family = AF_INET;
+ rem_addr.sin_addr = dest_list[i].dest_addr;
+ rem_addr.sin_port = htons(RIP_PORT);
+
+ route = first_route;
+
+ while (route != NULL) {
+
+ mess_len = build_header(message);
+
+ while (mess_len < 184 && route != NULL) {
+ if (route->action != DEL_ROUTE) {
+ bcopy((char *)&route->addr, message + mess_len + 0, sizeof(struct in_addr));
+ message[mess_len + 4] = route->bits;
+ message[mess_len + 5] = route->metric;
+
+ mess_len += RIP98_ENTRY;
+ }
+
+ route = route->next;
+ }
+
+ if (mess_len > RIP98_HEADER) {
+ if (sendto(s, message, mess_len, 0, (struct sockaddr *)&rem_addr, size) < 0) {
+ if (logging)
+ syslog(LOG_ERR, "sendto: %m");
+ }
+ }
+ }
+ }
+}
diff --git a/tcpip/ttylinkd.8 b/tcpip/ttylinkd.8
new file mode 100644
index 0000000..7b2379f
--- /dev/null
+++ b/tcpip/ttylinkd.8
@@ -0,0 +1,53 @@
+.TH TTYLINKD 8 "5 March 1997" Linux "Linux System Managers Manual"
+.SH NAME
+ttylinkd \- TTYlink daemon for AX.25, NET/ROM, ROSE and IP.
+.SH SYNOPSIS
+.B ttylinkd [-hv] [-c callsign] [-f file]
+.SH DESCRIPTION
+.LP
+.B ttylinkd
+is a simple daemon that allows incoming ttylink calls to be routed through
+to Linux's normal talkd(8)
+system and provides a pipe between the two.
+.LP
+.B ttylinkd
+is usually setup to be spawned from ax25d(8) or inetd(8)
+but can, since version 0.03, be used on the command line, although
+talk(1) is a much better idea for interactive users.
+.LP
+Use splitscreen(1)
+for outgoing ttylink sessions.
+.SH OPTIONS
+.TP 10
+.BI \-v
+Display the version.
+.TP 10
+.BI \-h
+Display some help and information on it.
+.TP 10
+.BI "\-c callsign"
+Disable callsign checking and use the given callsign for a name for this
+end of the link.
+.TP 10
+.BI "\-f file"
+Use <file> for the configuration file, instead of the default
+/etc/ax25/ttylinkd.conf
+.SH FILES
+.LP
+/etc/ax25/ttylinkd.conf the configuration file for ttylinkd
+.SH "SEE ALSO"
+.BR talk (1),
+.BR splitscreen (1),
+.BR ttylinkd.conf (5),
+.BR ax25d (8),
+.BR inetd (8),
+.BR talkd (8).
+.SH BUGS
+.LP
+There is still some need for some checking of who is still logged on.
+.LP
+The daemon may hang if you disconnect from it strangely.
+.LP
+There is no real way of working out what is going on with talkd.
+.SH AUTHOR
+Craig Small VK2XLZ <csmall@gonzo.triode.net.au>
diff --git a/tcpip/ttylinkd.c b/tcpip/ttylinkd.c
new file mode 100644
index 0000000..e185c7e
--- /dev/null
+++ b/tcpip/ttylinkd.c
@@ -0,0 +1,719 @@
+/*
+ * ttylinkd: A ttylink daemon using the ntalkd protocol.
+ * Copyright (C) 1996,1197 Craig Small (csmall@gonzo.triode.net.au)
+ *
+ * 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 recieved 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.
+ */
+ /*
+ * Versions:
+ * 13/01/96 cs Original Version
+ * 29/01/96 cs Added AX.25 proper support, thanks Tomi OH2BNS!!
+ * 27/01/97 cs Added support for stdin/stdout.
+ * 04/03/97 cs Added config file, no more defines.
+ * 09/03/97 tjd Enhanced to allow specifying user@hostname.wherever.
+ * rather than be confined to localhost.
+ */
+#include <ctype.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#define osockaddr sockaddr
+#include <protocols/talkd.h>
+
+#include <syslog.h>
+#include <sys/types.h>
+#include <sys/errno.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+
+#include <sys/socket.h>
+#include <netax25/ax25.h>
+#include <netrose/rose.h>
+
+#include "../pathnames.h"
+
+
+static char version[] = "ttylink daemon (Version 0.05, 9 March 1997) ready.\n";
+
+#define SYSOP_USER "root"
+
+/* TTY control characters from the sysop's talk screen */
+char erasec;
+char killc;
+char werasec;
+
+/* Users address family */
+int userfamily;
+
+#define ADDR_SIZE 256
+char sysop_addr[ADDR_SIZE];
+char *sysop_user=NULL, *sysop_host=NULL;
+char config_file[128];
+
+int send_control(int skt, struct in_addr addr, CTL_MSG msg, CTL_RESPONSE *resp);
+void alarm_handle(int i);
+void do_talk(int skt);
+void read_config_file(int dummy);
+
+/*static char *Commands[] = {
+ "leaving invitation",
+ "look-up",
+ "delete",
+ "announce" };
+*/
+static char *Responses[] = {
+ "success",
+ "sysop not logged on",
+ "failed for unknown reason",
+ "sysop's machine unknown",
+ "permission denied",
+ "unknown request",
+ "bad version",
+ "bad address",
+ "bad control address" };
+
+
+int main(int argc, char *argv[])
+{
+ struct sockaddr_in sin, ctl_sin;
+ struct in_addr my_addr, rem_addr;
+ int ctl_skt, skt, new_skt;
+ int length;
+ CTL_RESPONSE resp;
+ CTL_MSG msg;
+ struct protoent *ppe;
+ struct hostent *phe, *rhe=NULL;
+ char hostname[256];
+ int local_id, remote_id;
+ char buf[256];
+ char user[NAME_SIZE];
+ struct sockaddr sa;
+ int sa_len, i;
+ struct sockaddr_in *peer_sin=NULL;
+ struct sockaddr_ax25 *peer_sax;
+ struct sockaddr_rose *peer_srose;
+
+ /* Open up the system logger */
+ openlog(argv[0], LOG_PID, LOG_DAEMON);
+
+ write(STDOUT_FILENO, version, strlen(version));
+
+ /* Work out who is calling us */
+ userfamily = AF_UNSPEC;
+ bzero(user, NAME_SIZE);
+ strcpy(sysop_addr, SYSOP_USER);
+ strcpy(config_file, CONF_TTYLINKD_FILE);
+ for(i=1 ; i < argc ; i++)
+ {
+ if (argv[i][0] == '-')
+ {
+ switch (argv[i][1])
+ {
+ case 'v':
+ return 0;
+ break;
+ case 'h':
+ printf("ttylinkd comes with ABSOLUTELY NO WARRANY, see the file COPYING\n");
+ printf("This is free software, and you are welcome to redistribute it\n");
+ printf("under the terms of the GNU General Public License.\n\n");
+ printf("Usage: %s [-hv] [-c <callsign>] [-f <config_file>]\n", argv[0]);
+ return 0;
+ break;
+ case 'f':
+ if (i+2 > argc)
+ {
+ printf("The -f flag needs a parameter.\n");
+ return 0;
+ break;
+ }
+ strncpy(config_file, argv[++i], 127);
+ break;
+ case 'c':
+ if ( i+2 > argc)
+ {
+ printf("The -c flag need a parameter.\n");
+ return 0;
+ break;
+ }
+ strncpy(user, argv[++i], NAME_SIZE);
+ break;
+ default:
+ fprintf(stderr, "%s: Unknown flag, type %s -h for help\n", argv[0], argv[0]);
+ return -1;
+ break;
+ } /*switch */
+ } /* - */
+ } /* for */
+ if (user[0] == '\0')
+ {
+ sa_len = sizeof(sa);
+ if (getpeername(STDOUT_FILENO, &sa, &sa_len) < 0)
+ {
+ fprintf(stderr, "%s: getpeername() failed, you must specify a callsign in stdin mode.\n", argv[0]);
+ syslog(LOG_CRIT | LOG_DAEMON, "main(): getpeername() failed.");
+ return 0;
+ } else {
+ userfamily = sa.sa_family;
+ switch(sa.sa_family) {
+ case AF_INET:
+ peer_sin = (struct sockaddr_in*)&sa;
+ write(STDOUT_FILENO, buf, strlen(buf));
+ sprintf(buf, "Please enter your callsign: ");
+ write(STDOUT_FILENO, buf, strlen(buf));
+ fflush(stdout);
+ if (fgets(user, NAME_SIZE-1, stdin) == NULL)
+ return 0;
+ for (i = 0; user[i] != '\0' && user[i] != '\n' && user[i] != '\r'; i++)
+ ;
+ user[i] = '\0';
+ if (strlen(user) < 1)
+ return 0;
+ userfamily = AF_INET;
+ break;
+ case AF_AX25:
+ case AF_NETROM:
+ peer_sax = (struct sockaddr_ax25*)&sa;
+ for(i=0 ; i < 6 ; i++)
+ {
+ user[i] = tolower(((peer_sax->sax25_call.ax25_call[i]) >>1)&0x7f);
+ if (user[i] == ' ')
+ break;
+ }
+ user[i] = '\0';
+ break;
+ case AF_ROSE:
+ peer_srose = (struct sockaddr_rose*)&sa;
+ for(i=0 ; i < 6 ; i++)
+ {
+ user[i] = tolower(((peer_srose->srose_call.ax25_call[i]) >>1)&0x7f);
+ if (user[i] == ' ')
+ break;
+ }
+ user[i] = '\0';
+ break;
+ default:
+ syslog(LOG_DAEMON | LOG_CRIT, "Unsupported address family.");
+ exit(1);
+ }
+
+ }
+ } /* argc */
+
+ /* Read the configuration file to find the System Operator. */
+ read_config_file(0);
+ /* ... and parse it into user@host */
+ sysop_user=strtok(sysop_addr,"@");
+ sysop_host=strtok(NULL,"@");
+
+ if ((ppe = getprotobyname("udp")) == 0)
+ {
+ syslog(LOG_DAEMON | LOG_CRIT, "Cannot find udp protocol entry.");
+ exit(1);
+ }
+
+ /* Obtain our local hostname */
+ gethostname(hostname,256);
+
+ /* Get the remote address, or use ours if remote isn't specified */
+ if (sysop_host)
+ {
+ if ((rhe = gethostbyname(sysop_host)) == NULL)
+ {
+ syslog(LOG_DAEMON | LOG_CRIT, "main(): gethostbyname failed.");
+ exit(1);
+ }
+ }
+ else
+ {
+ if ((rhe = gethostbyname(hostname)) == NULL)
+ {
+ syslog(LOG_DAEMON | LOG_CRIT, "main(): gethostbyname failed.");
+ exit(1);
+ }
+ }
+ bcopy(rhe->h_addr, (char*)&rem_addr, rhe->h_length);
+
+ /* Get our local address */
+ if ((phe = gethostbyname(hostname)) == NULL)
+ {
+ syslog(LOG_DAEMON | LOG_CRIT, "main(): gethostbyname failed.");
+ exit(1);
+ }
+ bcopy(phe->h_addr, (char*)&my_addr, phe->h_length);
+
+ /* Create local data socket */
+ bzero((char*)&sin, sizeof(sin));
+
+ sin.sin_family = AF_INET;
+ sin.sin_port = htons(0);
+ bcopy(phe->h_addr, (char*)&sin.sin_addr, phe->h_length);
+
+ if ((skt = socket(PF_INET, SOCK_STREAM, 0)) < 0)
+ {
+ syslog(LOG_DAEMON | LOG_CRIT, "main(): socket() failed.");
+ exit(1);
+ }
+
+ if (bind( skt, (struct sockaddr*)&sin, sizeof(sin)) != 0)
+ {
+ syslog(LOG_DAEMON | LOG_CRIT, "main(): bind() failed.");
+ exit(1);
+ }
+
+ length = sizeof(sin);
+ if (getsockname(skt, (struct sockaddr*)&sin, &length) < 0)
+ {
+ syslog(LOG_DAEMON | LOG_CRIT, "main(): getsockname() failed.");
+ exit(1);
+ }
+
+ /* Create local control socket */
+ bzero((char*)&ctl_sin, sizeof(ctl_sin));
+
+ ctl_sin.sin_family = AF_INET;
+ bcopy(phe->h_addr, (char*)&ctl_sin.sin_addr, phe->h_length);
+ ctl_sin.sin_port = htons(0);
+
+ if ((ctl_skt = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
+ {
+ syslog(LOG_DAEMON | LOG_CRIT, "main(): socket() while attempting to create control socket.");
+ close(skt);
+ exit(1);
+ }
+
+ if (bind(ctl_skt, (struct sockaddr*)&ctl_sin, sizeof(ctl_sin)) != 0)
+ {
+ syslog(LOG_DAEMON | LOG_CRIT, "main(): Error when trying to bind() control socket.");
+ close(skt);
+ exit(1);
+ }
+
+ length = sizeof(ctl_sin);
+ if (getsockname(ctl_skt, (struct sockaddr*)&ctl_sin, &length) < 0)
+ {
+ syslog(LOG_DAEMON | LOG_CRIT,"main(): Error when trying to getsockname() for control socket.");
+ close(skt);
+ close(ctl_skt);
+ exit(1);
+ }
+
+ /* Start talking to the talk daemon */
+ bzero((char*)&msg, sizeof(msg));
+ msg.vers = TALK_VERSION;
+ msg.id_num = htonl(0);
+ msg.addr.sa_family = ntohs(AF_INET);
+ msg.ctl_addr = *(struct sockaddr*)&ctl_sin;
+ msg.ctl_addr = *(struct sockaddr*)&ctl_sin;
+ msg.ctl_addr.sa_family = ntohs(AF_INET);
+ msg.pid = htonl(getpid());
+ strncpy(msg.l_name, user, NAME_SIZE-1);
+ strncpy(msg.r_name, sysop_user, NAME_SIZE-1);
+
+
+ /* Now look for an invite */
+ msg.type = LOOK_UP;
+ (void) send_control(ctl_skt, rem_addr, msg, &resp);
+
+ /* The person not there? Send an announce and wake him up */
+ msg.type = ANNOUNCE;
+ msg.addr = *(struct sockaddr*)&sin;
+ msg.addr.sa_family = htons(AF_INET);
+ msg.id_num = -1;
+ i = send_control(ctl_skt, rem_addr, msg, &resp);
+ if ( i != SUCCESS)
+ {
+ if (i > BADCTLADDR)
+ printf("Cannot talk to sysop errno=%d.\n",i);
+ else
+ printf("Cannot talk to sysop, reason: %s.\n",Responses[i]);
+
+ close(skt);
+ close(ctl_skt);
+ return 0;
+ }
+ /* Update the ID number so that we both know what we're talking about. */
+ remote_id = resp.id_num;
+
+ /* Get the TCP port ready for a connection */
+ if (listen(skt, 5) != 0)
+ {
+ syslog(LOG_DAEMON | LOG_CRIT, "main(): Error when trying to listen() on socket.");
+ exit(1);
+ }
+
+ /* Now we have to make an invitation for the other user */
+ msg.type = LEAVE_INVITE;
+ if (send_control(ctl_skt, my_addr, msg, &resp) != SUCCESS)
+ {
+ printf("Problem with leaving an invitation\n");
+ syslog(LOG_DAEMON | LOG_CRIT, "main(): Cannot leave invititation.");
+ close(skt);
+ close(ctl_skt);
+ return 0;
+ }
+ local_id = resp.id_num;
+
+ sprintf(buf, "Paging sysop.\n");
+ write(STDOUT_FILENO, buf, strlen(buf));
+
+ /* Wait for the sysop to connect to us */
+ signal(SIGALRM, alarm_handle);
+ alarm(30);
+
+ if ((new_skt = accept(skt, 0, 0)) < 0)
+ {
+ if (errno == EINTR)
+ {
+ /* Delete invitations from both daemons */
+ msg.type = DELETE;
+ msg.id_num = htonl(local_id);
+ send_control(ctl_skt, my_addr, msg, &resp);
+ msg.id_num = htonl(remote_id);
+ send_control(ctl_skt, rem_addr, msg, &resp);
+
+ close(skt);
+ close(ctl_skt);
+ return 0;
+ }
+ syslog(LOG_DAEMON | LOG_WARNING, "main(): accept() failed. (%m)");
+ }
+ alarm(0);
+ signal(SIGALRM, SIG_DFL);
+
+ close(skt);
+ skt = new_skt;
+
+ /* Delete invitations from both daemons */
+ msg.type = DELETE;
+ msg.id_num = htonl(local_id);
+ send_control(ctl_skt, my_addr, msg, &resp);
+ msg.id_num = htonl(remote_id);
+ send_control(ctl_skt, rem_addr, msg, &resp);
+
+ sprintf(buf, "Sysop has responded.\n");
+ write(STDOUT_FILENO, buf, strlen(buf));
+
+ /*
+ * A little thing that they don't mention anywhere is the fact that the
+ * first three characters on a connection are used to work out to erase,
+ * kill and word erase characters. Nice to know eh?
+ */
+ /* We send ours first, but then again we get data in cooked form, so
+ * we don't use this. */
+ buf[0] = '\0';
+ buf[1] = '\0';
+ buf[2] = '\0';
+ if (write(skt, buf, 3) != 3)
+ {
+ printf("Connnection lost\n");
+ close(skt);
+ close(ctl_skt);
+ return 0;
+ }
+ /* Get their character stuff */
+ if (read(skt, buf, 3) != 3)
+ {
+ printf("Connection lost\n");
+ close(skt);
+ close(ctl_skt);
+ return 0;
+ }
+ erasec = buf[0];
+ killc = buf[1];
+ werasec = buf[2];
+
+ /* Tell the sysop who this person is */
+ if (sa.sa_family == AF_AX25)
+ {
+ sprintf(buf, "Incoming ttylink from %s.\n", user);
+ write(skt, buf, strlen(buf));
+ }
+ if (sa.sa_family == AF_INET)
+ {
+ sprintf(buf, "Incoming ttylink from %s@%s.\n", user, inet_ntoa(peer_sin->sin_addr));
+ write(skt, buf, strlen(buf));
+ }
+
+
+ do_talk(skt);
+
+ close(skt);
+ close(ctl_skt);
+ return 0;
+}
+
+/*
+ * Used to send control messages to our friendly local talk daemon
+ */
+int send_control(int skt, struct in_addr addr, CTL_MSG msg, CTL_RESPONSE *resp)
+{
+ fd_set fdvar;
+ struct timeval timeout;
+ struct sockaddr_in sin;
+ static int talk_port = 0;
+ struct servent *pse;
+
+ /* Look up talk port once only */
+ if (talk_port == 0)
+ {
+ if ((pse = getservbyname("ntalk", "udp")) == NULL)
+ {
+ perror("getservbyname, assuming 518");
+ talk_port = 518;
+ } else {
+ talk_port = pse->s_port;
+ }
+ }
+
+ /* Create the socket address */
+ bzero((char*)&sin, sizeof(sin));
+ sin.sin_addr = addr;
+ sin.sin_family = AF_INET;
+ sin.sin_port = talk_port;
+
+ if (sendto(skt, (char*)&msg, sizeof(msg), 0, (struct sockaddr*)&sin, sizeof(sin)) != sizeof(msg))
+ {
+ syslog(LOG_DAEMON | LOG_ERR, "send_control(): sendto failed (%m).");
+ return -1;
+ }
+
+ /* Wait for reply */
+ FD_ZERO(&fdvar);
+ FD_SET(skt, &fdvar);
+ timeout.tv_sec = RING_WAIT;
+ timeout.tv_usec = 0;
+
+ if (select(32, &fdvar, NULL, NULL, &timeout) < 0)
+ syslog(LOG_DAEMON | LOG_ERR, "send_control(): select failed. (%m)");
+
+ /*
+ * The server is ignoring us, see ya later
+ */
+ if (!(FD_ISSET(skt, &fdvar)))
+ {
+ printf("Talk server not responding after %d seconds, aborting.\n", RING_WAIT);
+ return -1;
+ }
+
+ /* Get the message */
+ if(recv(skt, resp, sizeof(resp),0) ==0)
+ syslog(LOG_DAEMON | LOG_ERR, "send_control(): recv failed. (%m)");
+
+ return resp->answer;
+}
+
+/* Used to process the data from the sysop */
+int send_sysop_data(char *buf, int len)
+{
+ static char outbuf[82];
+ static char *bptr = outbuf;
+ int i;
+
+ for(i = 0; i < len; i++)
+ {
+ /* Check for erase character */
+ if (buf[i] == erasec)
+ {
+ if (bptr > outbuf)
+ bptr--;
+ continue;
+ }
+
+ /* Check for kill character */
+ if (buf[i] == killc)
+ {
+ bptr = outbuf;
+ continue;
+ }
+
+ /* Check for word-erase character */
+ if (buf[i] == werasec)
+ {
+ while( (bptr > outbuf) && (*bptr != ' ') )
+ bptr--;
+ continue;
+ }
+
+ /* Check for newline character */
+ if (buf[i] == '\n')
+ {
+ if ( (userfamily == AF_AX25) || (userfamily == AF_NETROM) || (userfamily == AF_ROSE) )
+ {
+ *bptr = '\r';
+ bptr++;
+ } else {
+ *bptr = '\r';
+ bptr++;
+ *bptr = '\n';
+ bptr++;
+ }
+ } else {
+ *bptr = buf[i];
+ bptr++;
+ }
+
+ /* Check for carriage return, which means send it */
+ /* We also send if we have more than 80 characters */
+ if (buf[i] == '\n' || (bptr - outbuf) > 80 )
+ {
+ if (write(STDOUT_FILENO, outbuf, (bptr - outbuf) ) != (bptr - outbuf) )
+ {
+ return -1;
+ }
+ bptr = outbuf;
+ }
+ } /* for */
+ return 0;
+}
+
+/* Used to process the data from the user - len must not exceed 256 */
+int send_user_data(int skt, char *buf, int len)
+{
+ char outbuf[256];
+ char *bptr = outbuf;
+ int i;
+
+ for(i = 0; i < len; i++)
+ {
+ if (buf[i] == '\r')
+ {
+ if (userfamily == AF_INET)
+ {
+ *bptr = '\n';
+ bptr++;
+ /*
+ * check if this is a <CR><LF> or a <CR><NUL>
+ * and skip the <LF> or <NUL>.
+ */
+ if (buf[i + 1] == '\n' || buf[i + 1] == '\0')
+ {
+ i++;
+ }
+ } else
+ {
+ *bptr = '\n';
+ bptr++;
+ }
+ continue;
+ }
+ *bptr = buf[i];
+ bptr++;
+ } /* for */
+
+ if (write(skt, outbuf, bptr - outbuf) != bptr - outbuf)
+ {
+ return -1;
+ }
+ return 0;
+}
+
+
+/* The main talking loop */
+void do_talk(int skt)
+{
+ fd_set fdvar;
+ char inbuf[256], outbuf[256];
+ struct timeval timeout;
+ int i;
+
+
+ while(1)
+ {
+ FD_ZERO(&fdvar);
+ FD_SET(skt, &fdvar);
+ FD_SET(STDIN_FILENO, &fdvar);
+
+ timeout.tv_sec = 30;
+ timeout.tv_usec = 0;
+ if (select(32, &fdvar, NULL, NULL, &timeout) == 0)
+ {
+ if (ioctl(STDIN_FILENO, FIONREAD, (struct sgttyb *)&i) < 0)
+ return;
+ if (ioctl(skt, FIONREAD, (struct sgttyb*)&i) < 0)
+ return;
+ }
+
+ if (FD_ISSET(skt, &fdvar))
+ {
+ if ((i = read(skt, inbuf, 256)) <= 0)
+ {
+ strcpy(inbuf,"Sysop closed connection.\n");
+ write(STDOUT_FILENO, inbuf, strlen(inbuf));
+ return;
+ }
+ if (send_sysop_data(inbuf, i) < 0)
+ {
+ strcpy(outbuf, "User closed connection.\n");
+ (void) write(skt, outbuf, strlen(outbuf));
+ return;
+ }
+ }
+ if (FD_ISSET(STDIN_FILENO, &fdvar))
+ {
+ if ((i = read(STDIN_FILENO, outbuf, 256)) <= 0)
+ {
+ strcpy(outbuf, "User closed connection.\n");
+ (void) write(skt, outbuf, strlen(outbuf));
+ return;
+ }
+ if (send_user_data(skt, outbuf, i) < 0)
+ {
+ strcpy(inbuf,"Sysop closed connection.\n");
+ write(STDOUT_FILENO, inbuf, strlen(inbuf));
+ return;
+ }
+ }
+ }
+}
+
+void alarm_handle(int i)
+{
+ char buf[256];
+
+ strcpy(buf, "Sysop not responding.\n");
+ write(STDOUT_FILENO, buf, strlen(buf));
+}
+
+void read_config_file(int dummy)
+{
+ char buf[128];
+ char param[20], value[108];
+ FILE *fp;
+
+ if ( (fp = fopen(config_file, "r")) == NULL) {
+ syslog(LOG_DAEMON | LOG_ERR, "Cannot find configuration file: %s (%m)\n",config_file);
+ return;
+ }
+ /* Reset any variables here */
+
+ while ( fgets(buf, 128, fp) != NULL) {
+ if ( buf[0] == '#')
+ continue;
+ if (sscanf(buf, "%[^=]%*c%[^\n]", param, value) == 2) {
+ /* A big wierdo switch */
+ if (strcasecmp(param, "sysop") == 0) {
+ strncpy(sysop_addr, value, ADDR_SIZE);
+ }
+ }
+ } /* while */
+ fclose(fp);
+ signal(SIGHUP, read_config_file);
+}
diff --git a/tcpip/ttylinkd.conf b/tcpip/ttylinkd.conf
new file mode 100644
index 0000000..ae65749
--- /dev/null
+++ b/tcpip/ttylinkd.conf
@@ -0,0 +1,10 @@
+# /etc/ax25/ttylinkd.conf : config file for ttylinkd(8)
+#
+# We just have one line, who gets the incoming ttylink calls.
+#
+# sysop=user@hostname.domain.name
+# or:
+# sysop=user
+#
+sysop=root
+
diff --git a/tcpip/ttylinkd.conf.5 b/tcpip/ttylinkd.conf.5
new file mode 100644
index 0000000..ecba3a1
--- /dev/null
+++ b/tcpip/ttylinkd.conf.5
@@ -0,0 +1,22 @@
+.TH TTYLINKD.CONF 5 "9 March 1997" Linux "Linux Programmer's Manual"
+.SH NAME
+ttylinkd.conf \- ttylinkd configuration file.
+.SH DESCRIPTION
+.LP
+.B ttylinkd.conf
+allows the super user to determine certain parameters with ttylinkd(8).
+Current there is only one field, with the view of not extending this further
+(ttylinkd is about a resourceful as it is going to get).
+.SH PARAMETERS
+.TP 10
+.B #
+Any line beginning with the hash (#) symbol is a comment and wille be ignored.
+.TP 10
+.B "sysop=<user>[@hostname.domain.name]"
+The login <user> will be attempted to be contacted with ttylinkd(8) is
+launched. If you do not supply a hostname then the local host will be assumed.
+.SH SEE ALSO
+.BR ttylinkd (8).
+.SH AUTHOR
+Craig Small VK2XLZ <csmall@gonzo.triode.net.au>
+
diff --git a/user_call/Makefile.am b/user_call/Makefile.am
new file mode 100644
index 0000000..5aedbd3
--- /dev/null
+++ b/user_call/Makefile.am
@@ -0,0 +1,10 @@
+
+installconf:
+
+
+sbin_PROGRAMS = ax25_call netrom_call rose_call
+
+man_MANS = ax25_call.8 netrom_call.8 rose_call.8
+
+DATA_EXTRA = $(man_MANS)
+
diff --git a/user_call/Makefile.in b/user_call/Makefile.in
new file mode 100644
index 0000000..232f104
--- /dev/null
+++ b/user_call/Makefile.in
@@ -0,0 +1,349 @@
+# 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@
+
+sbin_PROGRAMS = ax25_call netrom_call rose_call
+
+man_MANS = ax25_call.8 netrom_call.8 rose_call.8
+
+DATA_EXTRA = $(man_MANS)
+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@
+ax25_call_SOURCES = ax25_call.c
+ax25_call_OBJECTS = ax25_call.o
+ax25_call_LDADD = $(LDADD)
+ax25_call_DEPENDENCIES =
+ax25_call_LDFLAGS =
+netrom_call_SOURCES = netrom_call.c
+netrom_call_OBJECTS = netrom_call.o
+netrom_call_LDADD = $(LDADD)
+netrom_call_DEPENDENCIES =
+netrom_call_LDFLAGS =
+rose_call_SOURCES = rose_call.c
+rose_call_OBJECTS = rose_call.o
+rose_call_LDADD = $(LDADD)
+rose_call_DEPENDENCIES =
+rose_call_LDFLAGS =
+CFLAGS = @CFLAGS@
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+man8dir = $(mandir)/man8
+MANS = $(man_MANS)
+
+NROFF = nroff
+DIST_COMMON = README Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = tar
+GZIP_ENV = --best
+SOURCES = ax25_call.c netrom_call.c rose_call.c
+OBJECTS = ax25_call.o netrom_call.o rose_call.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 user_call/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:
+
+ax25_call: $(ax25_call_OBJECTS) $(ax25_call_DEPENDENCIES)
+ @rm -f ax25_call
+ $(LINK) $(ax25_call_LDFLAGS) $(ax25_call_OBJECTS) $(ax25_call_LDADD) $(LIBS)
+
+netrom_call: $(netrom_call_OBJECTS) $(netrom_call_DEPENDENCIES)
+ @rm -f netrom_call
+ $(LINK) $(netrom_call_LDFLAGS) $(netrom_call_OBJECTS) $(netrom_call_LDADD) $(LIBS)
+
+rose_call: $(rose_call_OBJECTS) $(rose_call_DEPENDENCIES)
+ @rm -f rose_call
+ $(LINK) $(rose_call_LDFLAGS) $(rose_call_OBJECTS) $(rose_call_LDADD) $(LIBS)
+
+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-man8
+uninstall-man:
+ @$(NORMAL_UNINSTALL)
+ $(MAKE) $(AM_MAKEFLAGS) 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 = user_call
+
+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
+ax25_call.o: ax25_call.c
+netrom_call.o: netrom_call.c
+rose_call.o: rose_call.c
+
+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-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-man
+uninstall: uninstall-am
+all-am: Makefile $(PROGRAMS) $(MANS)
+all-redirect: all-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+installdirs:
+ $(mkinstalldirs) $(DESTDIR)$(sbindir) $(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 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:
+
+# 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/user_call/README b/user_call/README
new file mode 100644
index 0000000..beee347
--- /dev/null
+++ b/user_call/README
@@ -0,0 +1,59 @@
+This is the first version of the user_call utilities. They are little
+program,s to allow users of ax25d and the node to initiate outgoing AX.25,
+NET/ROM and Rose connections. They are very powerful program because it can
+pretend to be someone else, so be careful !
+
+My testing has been within the confined of the node, but the comments here
+apply equally well to use via ax25d.
+
+Ax25_call takes at least three parameters:
+
+ax25_call <port> <my callsign> <remote callsign> [<digipeaters> ...]
+
+Netrom_call takes three parameters:
+
+netrom_call <port> <my callsign> <remote address>
+
+Rose_call takes four parameters:
+
+rose_call <port> <my callsign> <remote callsign> <remote Rose address>
+
+The <port> is the name of a local AX.25, NET/ROM or Rose port as defined in
+the axports, nrports or rsports files respectively. <my callsign> is the
+callsign that this connection appears to have come from, ie the local
+*user*. It has nothing to do with your AX.25 port callsign.
+
+Ax25_call must have at least the callsign of the remote user and a set of
+optional digipeaters.
+
+The <remote address> for netrom_call may be of two forms, either the remote
+node callsign, or a combination of the remote node alias and remote node
+callsign seperated by a ':'. Netrom_call only connects to the remote
+callisgn, the full address is sent to the local user for information.
+
+The <remote callsign> for rose_call is the "service" at the remote Rose
+node, ie USERS or any other valid AX.25 callsign, <remote Rose address> is
+the ten-digit Rose address of the remote node.
+
+To start any of these from within the node, you will need to add a line like
+the following to the /etc/ax25/node.conf file, this example uses rose_call:
+
+ExtCmd BBS 0 root /usr/sbin/rose_call rose_call rose %S k4dpz 3100352392
+
+This assumes that rose_call is installed in /usr/sbin which is the default.
+This will create a new command "BBS" for the node, which when typed will
+connect the user to the callsign K4DPZ at remote Rose node 3100352392. The
+callsign of the local user is where the %S appears in the line, it is
+substituted by node for the users callsign. See node.conf(5) for more
+details of the syntax.
+
+Setting up these programs via ax25d is also quite simple and is similar
+conceptually to the example above.
+
+All of these programs generates errors that are received by the local user,
+so if there are any problems then the local user will be able to quote the
+message to you.
+
+Give them a whirl and let me know how you go.
+
+Jonathan
diff --git a/user_call/ax25_call.c b/user_call/ax25_call.c
new file mode 100644
index 0000000..aaa47ce
--- /dev/null
+++ b/user_call/ax25_call.c
@@ -0,0 +1,156 @@
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.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>
+
+void alarm_handler(int sig)
+{
+}
+
+void err(char *message)
+{
+ write(STDOUT_FILENO, message, strlen(message));
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+ char buffer[512], *addr;
+ fd_set read_fd;
+ int n, s, addrlen = sizeof(struct full_sockaddr_ax25);
+ struct full_sockaddr_ax25 axbind, axconnect;
+
+ /*
+ * Arguments should be "ax25_call port mycall remcall [digis ...]"
+ */
+ if (argc < 4) {
+ strcpy(buffer, "ERROR: invalid number of parameters\r");
+ err(buffer);
+ }
+
+ if (ax25_config_load_ports() == 0) {
+ strcpy(buffer, "ERROR: problem with axports file\r");
+ err(buffer);
+ }
+
+ /*
+ * Parse the passed values for correctness.
+ */
+ axconnect.fsa_ax25.sax25_family = axbind.fsa_ax25.sax25_family = AF_AX25;
+ axbind.fsa_ax25.sax25_ndigis = 1;
+
+ if ((addr = ax25_config_get_addr(argv[1])) == NULL) {
+ sprintf(buffer, "ERROR: invalid AX.25 port name - %s\r", argv[1]);
+ err(buffer);
+ }
+
+ if (ax25_aton_entry(addr, axbind.fsa_digipeater[0].ax25_call) == -1) {
+ sprintf(buffer, "ERROR: invalid AX.25 port callsign - %s\r", argv[1]);
+ err(buffer);
+ }
+
+ if (ax25_aton_entry(argv[2], axbind.fsa_ax25.sax25_call.ax25_call) == -1) {
+ sprintf(buffer, "ERROR: invalid callsign - %s\r", argv[2]);
+ err(buffer);
+ }
+
+ if (ax25_aton_arglist(argv + 3, &axconnect) == -1) {
+ sprintf(buffer, "ERROR: invalid destination callsign or digipeater\r");
+ err(buffer);
+ }
+
+ /*
+ * Open the socket into the kernel.
+ */
+ if ((s = socket(AF_AX25, SOCK_SEQPACKET, 0)) < 0) {
+ sprintf(buffer, "ERROR: cannot open AX.25 socket, %s\r", strerror(errno));
+ err(buffer);
+ }
+
+ /*
+ * Set our AX.25 callsign and AX.25 port callsign accordingly.
+ */
+ if (bind(s, (struct sockaddr *)&axbind, addrlen) != 0) {
+ sprintf(buffer, "ERROR: cannot bind AX.25 socket, %s\r", strerror(errno));
+ err(buffer);
+ }
+
+ sprintf(buffer, "Connecting to %s ...\r", argv[3]);
+ write(STDOUT_FILENO, buffer, strlen(buffer));
+
+ /*
+ * If no response in 30 seconds, go away.
+ */
+ alarm(30);
+
+ 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 - aborting\r");
+ break;
+ case ENETUNREACH:
+ strcpy(buffer, "*** No known route - aborting\r");
+ break;
+ case EINTR:
+ strcpy(buffer, "*** Connection timed out - aborting\r");
+ break;
+ default:
+ sprintf(buffer, "ERROR: cannot connect to AX.25 callsign, %s\r", strerror(errno));
+ break;
+ }
+
+ err(buffer);
+ }
+
+ /*
+ * 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, 512)) == -1) {
+ strcpy(buffer, "\r*** Disconnected\r");
+ err(buffer);
+ }
+ write(STDOUT_FILENO, buffer, n);
+ }
+
+ if (FD_ISSET(STDIN_FILENO, &read_fd)) {
+ if ((n = read(STDIN_FILENO, buffer, 512)) == -1) {
+ close(s);
+ break;
+ }
+ write(s, buffer, n);
+ }
+ }
+
+ return 0;
+}
diff --git a/user_call/netrom_call.c b/user_call/netrom_call.c
new file mode 100644
index 0000000..004b109
--- /dev/null
+++ b/user_call/netrom_call.c
@@ -0,0 +1,165 @@
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+
+#include <sys/time.h>
+#include <sys/types.h>
+
+#include <sys/socket.h>
+#include <netax25/ax25.h>
+#include <netrom/netrom.h>
+#include <netrose/rose.h>
+
+#include <netax25/axlib.h>
+#include <netax25/axconfig.h>
+#include <netax25/nrconfig.h>
+
+void alarm_handler(int sig)
+{
+}
+
+void err(char *message)
+{
+ write(STDOUT_FILENO, message, strlen(message));
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+ char buffer[512], *addr;
+ fd_set read_fd;
+ int n, s, addrlen = sizeof(struct full_sockaddr_ax25);
+ struct full_sockaddr_ax25 nrbind, nrconnect;
+
+ /*
+ * Arguments should be "netrom_call port mycall remaddr"
+ */
+ if (argc != 4) {
+ strcpy(buffer, "ERROR: invalid number of parameters\r");
+ err(buffer);
+ }
+
+ if (nr_config_load_ports() == 0) {
+ strcpy(buffer, "ERROR: problem with nrports file\r");
+ err(buffer);
+ }
+
+ /*
+ * Parse the passed values for correctness.
+ */
+ nrconnect.fsa_ax25.sax25_family = nrbind.fsa_ax25.sax25_family = AF_NETROM;
+ nrbind.fsa_ax25.sax25_ndigis = 1;
+ nrconnect.fsa_ax25.sax25_ndigis = 0;
+
+ if ((addr = nr_config_get_addr(argv[1])) == NULL) {
+ sprintf(buffer, "ERROR: invalid NET/ROM port name - %s\r", argv[1]);
+ err(buffer);
+ }
+
+ if (ax25_aton_entry(addr, nrbind.fsa_ax25.sax25_call.ax25_call) == -1) {
+ sprintf(buffer, "ERROR: invalid NET/ROM port callsign - %s\r", argv[1]);
+ err(buffer);
+ }
+
+ if (ax25_aton_entry(argv[2], nrbind.fsa_digipeater[0].ax25_call) == -1) {
+ sprintf(buffer, "ERROR: invalid callsign - %s\r", argv[2]);
+ err(buffer);
+ }
+
+ if ((addr = strchr(argv[3], ':')) == NULL)
+ addr = argv[3];
+ else
+ addr++;
+
+ if (ax25_aton_entry(addr, nrconnect.fsa_ax25.sax25_call.ax25_call) == -1) {
+ sprintf(buffer, "ERROR: invalid callsign - %s\r", argv[3]);
+ err(buffer);
+ }
+
+ /*
+ * Open the socket into the kernel.
+ */
+ if ((s = socket(AF_NETROM, SOCK_SEQPACKET, 0)) < 0) {
+ sprintf(buffer, "ERROR: cannot open NET/ROM socket, %s\r", strerror(errno));
+ err(buffer);
+ }
+
+ /*
+ * Set our AX.25 callsign and NET/ROM callsign accordingly.
+ */
+ if (bind(s, (struct sockaddr *)&nrbind, addrlen) != 0) {
+ sprintf(buffer, "ERROR: cannot bind NET/ROM socket, %s\r", strerror(errno));
+ err(buffer);
+ }
+
+ sprintf(buffer, "Connecting to %s ...\r", argv[3]);
+ write(STDOUT_FILENO, buffer, strlen(buffer));
+
+ /*
+ * If no response in 30 seconds, go away.
+ */
+ alarm(30);
+
+ signal(SIGALRM, alarm_handler);
+
+ /*
+ * Lets try and connect to the far end.
+ */
+ if (connect(s, (struct sockaddr *)&nrconnect, addrlen) != 0) {
+ switch (errno) {
+ case ECONNREFUSED:
+ strcpy(buffer, "*** Connection refused - aborting\r");
+ break;
+ case ENETUNREACH:
+ strcpy(buffer, "*** No known route - aborting\r");
+ break;
+ case EINTR:
+ strcpy(buffer, "*** Connection timed out - aborting\r");
+ break;
+ default:
+ sprintf(buffer, "ERROR: cannot connect to NET/ROM node, %s\r", strerror(errno));
+ break;
+ }
+
+ err(buffer);
+ }
+
+ /*
+ * 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, 512)) == -1) {
+ strcpy(buffer, "\r*** Disconnected\r");
+ err(buffer);
+ }
+ write(STDOUT_FILENO, buffer, n);
+ }
+
+ if (FD_ISSET(STDIN_FILENO, &read_fd)) {
+ if ((n = read(STDIN_FILENO, buffer, 512)) == -1) {
+ close(s);
+ break;
+ }
+ write(s, buffer, n);
+ }
+ }
+
+ return 0;
+}
diff --git a/user_call/rose_call.c b/user_call/rose_call.c
new file mode 100644
index 0000000..606284d
--- /dev/null
+++ b/user_call/rose_call.c
@@ -0,0 +1,162 @@
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.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>
+
+void alarm_handler(int sig)
+{
+}
+
+void err(char *message)
+{
+ write(STDOUT_FILENO, message, strlen(message));
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+ char buffer[512], *addr;
+ fd_set read_fd;
+ int n, s, addrlen = sizeof(struct sockaddr_rose);
+ struct sockaddr_rose rosebind, roseconnect;
+
+ /*
+ * Arguments should be "rose_call port mycall remcall remaddr"
+ */
+ if (argc != 5) {
+ strcpy(buffer, "ERROR: invalid number of parameters\r");
+ err(buffer);
+ }
+
+ if (rs_config_load_ports() == 0) {
+ strcpy(buffer, "ERROR: problem with rsports file\r");
+ err(buffer);
+ }
+
+ /*
+ * Parse the passed values for correctness.
+ */
+ roseconnect.srose_family = rosebind.srose_family = AF_ROSE;
+ roseconnect.srose_ndigis = rosebind.srose_ndigis = 0;
+
+ if ((addr = rs_config_get_addr(argv[1])) == NULL) {
+ sprintf(buffer, "ERROR: invalid Rose port name - %s\r", argv[1]);
+ err(buffer);
+ }
+
+ if (rose_aton(addr, rosebind.srose_addr.rose_addr) == -1) {
+ sprintf(buffer, "ERROR: invalid Rose port address - %s\r", argv[1]);
+ err(buffer);
+ }
+
+ if (ax25_aton_entry(argv[2], rosebind.srose_call.ax25_call) == -1) {
+ sprintf(buffer, "ERROR: invalid callsign - %s\r", argv[2]);
+ err(buffer);
+ }
+
+ if (ax25_aton_entry(argv[3], roseconnect.srose_call.ax25_call) == -1) {
+ sprintf(buffer, "ERROR: invalid callsign - %s\r", argv[3]);
+ err(buffer);
+ }
+
+ if (rose_aton(argv[4], roseconnect.srose_addr.rose_addr) == -1) {
+ sprintf(buffer, "ERROR: invalid Rose address - %s\r", argv[4]);
+ err(buffer);
+ }
+
+ /*
+ * Open the socket into the kernel.
+ */
+ if ((s = socket(AF_ROSE, SOCK_SEQPACKET, 0)) < 0) {
+ sprintf(buffer, "ERROR: cannot open Rose socket, %s\r", strerror(errno));
+ err(buffer);
+ }
+
+ /*
+ * Set our AX.25 callsign and Rose address accordingly.
+ */
+ if (bind(s, (struct sockaddr *)&rosebind, addrlen) != 0) {
+ sprintf(buffer, "ERROR: cannot bind Rose socket, %s\r", strerror(errno));
+ err(buffer);
+ }
+
+ sprintf(buffer, "Connecting to %s @ %s ...\r", argv[3], argv[4]);
+ write(STDOUT_FILENO, buffer, strlen(buffer));
+
+ /*
+ * If no response in 30 seconds, go away.
+ */
+ alarm(30);
+
+ 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, "*** Connection refused - aborting\r");
+ break;
+ case ENETUNREACH:
+ strcpy(buffer, "*** No known route - aborting\r");
+ break;
+ case EINTR:
+ strcpy(buffer, "*** Connection timed out - aborting\r");
+ break;
+ default:
+ sprintf(buffer, "ERROR: cannot connect to Rose address, %s\r", strerror(errno));
+ break;
+ }
+
+ err(buffer);
+ }
+
+ /*
+ * 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, 512)) == -1) {
+ strcpy(buffer, "\r*** Disconnected\r");
+ err(buffer);
+ }
+ write(STDOUT_FILENO, buffer, n);
+ }
+
+ if (FD_ISSET(STDIN_FILENO, &read_fd)) {
+ if ((n = read(STDIN_FILENO, buffer, 512)) == -1) {
+ close(s);
+ break;
+ }
+ write(s, buffer, n);
+ }
+ }
+
+ return 0;
+}