From 17287576555a5c46fa23549e2e5f073660dccb70 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 21 Apr 1999 09:51:03 +0200 Subject: Import ax25-tools 0.0.1 from tarball --- AUTHORS | 23 + COPYING | 340 +++++ ChangeLog | 4 + INSTALL | 18 + Makefile.am | 11 + Makefile.in | 358 +++++ NEWS | 3 + README | 17 + acconfig.h | 10 + aclocal.m4 | 127 ++ ax25/Makefile.am | 38 + ax25/Makefile.in | 563 ++++++++ ax25/ax25.4 | 77 + ax25/ax25.profile | 2 + ax25/ax25d.8 | 46 + ax25/ax25d.c | 1195 ++++++++++++++++ ax25/ax25d.conf | 45 + ax25/ax25d.conf.5 | 269 ++++ ax25/axctl.8 | 67 + ax25/axctl.c | 92 ++ ax25/axparms.8 | 119 ++ ax25/axparms.c | 442 ++++++ ax25/axports.5 | 62 + ax25/axspawn.8 | 52 + ax25/axspawn.c | 911 ++++++++++++ ax25/axspawn.conf | 25 + ax25/axspawn.conf.5 | 75 + ax25/beacon.8 | 51 + ax25/beacon.c | 163 +++ ax25/bpqparms.8 | 37 + ax25/bpqparms.c | 146 ++ ax25/mheard.1 | 74 + ax25/mheard.c | 374 +++++ ax25/mheard.dat | 0 ax25/mheardd.8 | 42 + ax25/mheardd.c | 436 ++++++ ax25/rxecho.8 | 38 + ax25/rxecho.c | 376 +++++ ax25/rxecho.conf | 12 + ax25/rxecho.conf.5 | 22 + config.h.in | 124 ++ configure | 3654 +++++++++++++++++++++++++++++++++++++++++++++++ configure.in | 58 + hdlcutil/Makefile.am | 31 + hdlcutil/Makefile.in | 403 ++++++ hdlcutil/hdrvcomm.c | 663 +++++++++ hdlcutil/hdrvcomm.h | 109 ++ hdlcutil/setcrystal.c | 136 ++ hdlcutil/sethdlc.c | 598 ++++++++ hdlcutil/smdiag.c | 434 ++++++ hdlcutil/smmixer.c | 781 ++++++++++ hdlcutil/usersmdiag.h | 118 ++ install-sh | 251 ++++ kiss/Makefile.am | 8 + kiss/Makefile.in | 367 +++++ kiss/kissattach.c | 289 ++++ kiss/kissnetd.c | 257 ++++ kiss/kissparms.c | 221 +++ kiss/mkiss.c | 512 +++++++ kiss/net2kiss.c | 643 +++++++++ missing | 190 +++ mkinstalldirs | 40 + netrom/Makefile.am | 26 + netrom/Makefile.in | 452 ++++++ netrom/netrom.4 | 51 + netrom/netromd.8 | 97 ++ netrom/netromd.c | 254 ++++ netrom/netromd.h | 41 + netrom/netromr.c | 164 +++ netrom/netromt.c | 268 ++++ netrom/nodesave.8 | 31 + netrom/nodesave.c | 101 ++ netrom/nrattach.8 | 39 + netrom/nrattach.c | 240 ++++ netrom/nrbroadcast | 8 + netrom/nrbroadcast.5 | 49 + netrom/nrparms.8 | 76 + netrom/nrparms.c | 239 ++++ netrom/nrports | 7 + netrom/nrports.5 | 56 + netrom/nrsdrv.8 | 44 + netrom/nrsdrv.c | 457 ++++++ rose/Makefile.am | 19 + rose/Makefile.in | 471 ++++++ rose/rose.4 | 44 + rose/rsattach.8 | 33 + rose/rsattach.c | 219 +++ rose/rsdwnlnk.8 | 58 + rose/rsdwnlnk.c | 272 ++++ rose/rsmemsiz.c | 204 +++ rose/rsparms.8 | 64 + rose/rsparms.c | 256 ++++ rose/rsports | 7 + rose/rsports.5 | 52 + rose/rsuplnk.8 | 63 + rose/rsuplnk.c | 288 ++++ stamp-h.in | 1 + tcpip/Makefile.am | 23 + tcpip/Makefile.in | 386 +++++ tcpip/rip98.conf | 1 + tcpip/rip98.conf.5 | 19 + tcpip/rip98d.8 | 59 + tcpip/rip98d.c | 360 +++++ tcpip/rip98d.h | 58 + tcpip/rip98r.c | 255 ++++ tcpip/rip98t.c | 76 + tcpip/ttylinkd.8 | 53 + tcpip/ttylinkd.c | 719 ++++++++++ tcpip/ttylinkd.conf | 10 + tcpip/ttylinkd.conf.5 | 22 + user_call/Makefile.am | 10 + user_call/Makefile.in | 349 +++++ user_call/README | 59 + user_call/ax25_call.c | 156 ++ user_call/netrom_call.c | 165 +++ user_call/rose_call.c | 162 +++ 116 files changed, 24342 insertions(+) create mode 100644 AUTHORS create mode 100644 COPYING create mode 100644 ChangeLog create mode 100644 INSTALL create mode 100644 Makefile.am create mode 100644 Makefile.in create mode 100644 NEWS create mode 100644 README create mode 100644 acconfig.h create mode 100644 aclocal.m4 create mode 100644 ax25/Makefile.am create mode 100644 ax25/Makefile.in create mode 100644 ax25/ax25.4 create mode 100644 ax25/ax25.profile create mode 100644 ax25/ax25d.8 create mode 100644 ax25/ax25d.c create mode 100644 ax25/ax25d.conf create mode 100644 ax25/ax25d.conf.5 create mode 100644 ax25/axctl.8 create mode 100644 ax25/axctl.c create mode 100644 ax25/axparms.8 create mode 100644 ax25/axparms.c create mode 100644 ax25/axports.5 create mode 100644 ax25/axspawn.8 create mode 100644 ax25/axspawn.c create mode 100644 ax25/axspawn.conf create mode 100644 ax25/axspawn.conf.5 create mode 100644 ax25/beacon.8 create mode 100644 ax25/beacon.c create mode 100644 ax25/bpqparms.8 create mode 100644 ax25/bpqparms.c create mode 100644 ax25/mheard.1 create mode 100644 ax25/mheard.c create mode 100644 ax25/mheard.dat create mode 100644 ax25/mheardd.8 create mode 100644 ax25/mheardd.c create mode 100644 ax25/rxecho.8 create mode 100644 ax25/rxecho.c create mode 100644 ax25/rxecho.conf create mode 100644 ax25/rxecho.conf.5 create mode 100644 config.h.in create mode 100755 configure create mode 100644 configure.in create mode 100644 hdlcutil/Makefile.am create mode 100644 hdlcutil/Makefile.in create mode 100644 hdlcutil/hdrvcomm.c create mode 100644 hdlcutil/hdrvcomm.h create mode 100644 hdlcutil/setcrystal.c create mode 100644 hdlcutil/sethdlc.c create mode 100644 hdlcutil/smdiag.c create mode 100644 hdlcutil/smmixer.c create mode 100644 hdlcutil/usersmdiag.h create mode 100755 install-sh create mode 100644 kiss/Makefile.am create mode 100644 kiss/Makefile.in create mode 100644 kiss/kissattach.c create mode 100644 kiss/kissnetd.c create mode 100644 kiss/kissparms.c create mode 100644 kiss/mkiss.c create mode 100644 kiss/net2kiss.c create mode 100755 missing create mode 100755 mkinstalldirs create mode 100644 netrom/Makefile.am create mode 100644 netrom/Makefile.in create mode 100644 netrom/netrom.4 create mode 100644 netrom/netromd.8 create mode 100644 netrom/netromd.c create mode 100644 netrom/netromd.h create mode 100644 netrom/netromr.c create mode 100644 netrom/netromt.c create mode 100644 netrom/nodesave.8 create mode 100644 netrom/nodesave.c create mode 100644 netrom/nrattach.8 create mode 100644 netrom/nrattach.c create mode 100644 netrom/nrbroadcast create mode 100644 netrom/nrbroadcast.5 create mode 100644 netrom/nrparms.8 create mode 100644 netrom/nrparms.c create mode 100644 netrom/nrports create mode 100644 netrom/nrports.5 create mode 100644 netrom/nrsdrv.8 create mode 100644 netrom/nrsdrv.c create mode 100644 rose/Makefile.am create mode 100644 rose/Makefile.in create mode 100644 rose/rose.4 create mode 100644 rose/rsattach.8 create mode 100644 rose/rsattach.c create mode 100644 rose/rsdwnlnk.8 create mode 100644 rose/rsdwnlnk.c create mode 100644 rose/rsmemsiz.c create mode 100644 rose/rsparms.8 create mode 100644 rose/rsparms.c create mode 100644 rose/rsports create mode 100644 rose/rsports.5 create mode 100644 rose/rsuplnk.8 create mode 100644 rose/rsuplnk.c create mode 100644 stamp-h.in create mode 100644 tcpip/Makefile.am create mode 100644 tcpip/Makefile.in create mode 100644 tcpip/rip98.conf create mode 100644 tcpip/rip98.conf.5 create mode 100644 tcpip/rip98d.8 create mode 100644 tcpip/rip98d.c create mode 100644 tcpip/rip98d.h create mode 100644 tcpip/rip98r.c create mode 100644 tcpip/rip98t.c create mode 100644 tcpip/ttylinkd.8 create mode 100644 tcpip/ttylinkd.c create mode 100644 tcpip/ttylinkd.conf create mode 100644 tcpip/ttylinkd.conf.5 create mode 100644 user_call/Makefile.am create mode 100644 user_call/Makefile.in create mode 100644 user_call/README create mode 100644 user_call/ax25_call.c create mode 100644 user_call/netrom_call.c create mode 100644 user_call/rose_call.c 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 +ax25ipd Rob Mayfield VK5XXX +ax25rtd Klaus Kudielka +bpqparms Joerg Reuter DL1BKE +call Alexander Tietzel DG6XA +mkiss Tomi Manninen OH2BNS +kissnetd Frederic Rible F1OAT +listen Heikki Hannikainen OH7LZB +net2kiss Thomas Sailer HB9JNX +node Tomi Manninen OH2BNS +nodesave Tomi Manninen OH2BNS +nrsdrv Dave Brown N2RJT +piconfig John Paul Morrison VE7JPM +pms David Brown N2RJT +rxecho Tomi Manninen OH2BNS +setcrystal Thomas Sailer HB9JNX +sethdlc Thomas Sailer HB9JNX +smdiag Thomas Sailer HB9JNX +smmixer Thomas Sailer HB9JNX +ttylinkd Craig Small VK2XLZ + +All others Jonathon Naylor G4KLX + 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. + + + Copyright (C) + + 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. + + , 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 + + * 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 + + 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>>, <<[^ ]>>, <<>>), <<>>, +<>CONFIG_HEADERS" || echo timestamp > patsubst(<<$1>>, <<^\([^:]*/\)?.*>>, <<\1>>)stamp-h<<>>dnl>>, +<>; 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 +.br +Jonathan Naylor G4KLX +.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 +.br +Jonathan Naylor G4KLX 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#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 '<'. +# +# +#NOCALL * * * * * * L +#default * * * * * * - root /usr/local/sbin/ttylinkd ttylinkd +# + +NOCALL * * * * * * L +default * * * * * * - root /usr/sbin/node node +# +# +#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. +.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 +.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 +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include + +#include +#include + +#include + +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 +.br +.B axparms -assoc 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 +.br +.B axparms -forward 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 [] [-ipmode V|D] +.br +.B axparms -route del +.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 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 +.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 +.br +Jonathan Naylor G4KLX +.br +Joerg Reuter DL1BKE +.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 +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include + +#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 \n"); + fprintf(stderr, "usage: axparms -forward 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 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 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#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 ] [-d ] [-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 +.br +Jonathan Naylor G4KLX +.br +David Brooke G6GZH +.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 +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include + +#include + +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 ] [-d ] [-l] [-m] [-s] [-t interval] [-v] \n"); + return 1; + } + } + + signal(SIGTERM, terminate); + + if (optind == argc || optind == argc - 1) { + fprintf(stderr, "usage: beacon [-c ] [-d ] [-l] [-m] [-s] [-t interval] [-v] \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 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include /* xlz - dammit, we need this again */ + +#include + +#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", + ð[0], ð[1], ð[2], ð[3], ð[4], ð[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 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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#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 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 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include + +#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 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, . + * + * *** Modified 9/9/96 by Heikki Hannikainen, OH7LZB, : + * + * 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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#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 doesn't define. */ +#undef gid_t + +/* Define if you have the strftime function. */ +#undef HAVE_STRFTIME + +/* Define if you have 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 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 and . */ +#undef TIME_WITH_SYS_TIME + +/* Define if your declares struct tm. */ +#undef TM_IN_SYS_TIME + +/* Define to `int' if 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 header file. */ +#undef HAVE_FCNTL_H + +/* Define if you have the header file. */ +#undef HAVE_LIMITS_H + +/* Define if you have the header file. */ +#undef HAVE_PATHS_H + +/* Define if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_FILE_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_IOCTL_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_TIME_H + +/* Define if you have the header file. */ +#undef HAVE_SYSLOG_H + +/* Define if you have the 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 <> confdefs.h <&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 <&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 <&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 <&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 <&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 <&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 <&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 <&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 <&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 < +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 < +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 < +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 +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 <&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 <&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 <&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 <&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 <&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 < +/* 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 <&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 < +/* 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 <&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 < +/* 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 <&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 < +/* 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 <&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 <&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 +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 <&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 < +#include +#include +#include +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 +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 +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 < +#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 < +#include +#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 +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 <&6 +fi +done + + +cat > conftest.$ac_ext < +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 +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 +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 <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 +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 < +#if STDC_HEADERS +#include +#include +#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 < +#include +#include +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 < +#include +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 < +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 < +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 <&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 < +#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 < +#include +#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 <&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 < +/* 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 <&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 < +#include +#include +#include +/* 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 < +/* 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 <&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 </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 < 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 <> $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 <> $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 <> $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 <> $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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/*#include */ +#include +#include "hdrvcomm.h" +#include "usersmdiag.h" + +#include +/* ---------------------------------------------------------------------- */ + +#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 +#include +#include +#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 +#include +#include +#include + +/* --------------------------------------------------------------------- */ + +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 +#include +#include +#include +#include +#include +#include +#include +#include +/*#include */ +#include +#include "hdrvcomm.h" + +#include +#include + +/* ---------------------------------------------------------------------- */ + +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 ] [-h] [-c ]\n" +"[-p] [hw ] [type ] [io ] [irq ] [dma ]\n" +" [options ] [serio ] [pario ] [midiio ]\n" +"[-a] [txd ] [txtail ] [slot ]\n" +" [ppersist ] [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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "hdrvcomm.h" + +#include + +/* ---------------------------------------------------------------------- */ + +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 +#include +#include +#include +#include +#include +#include +#include +#include "hdrvcomm.h" + +#include +/* ---------------------------------------------------------------------- */ + +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 + */ +#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 + */ +#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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include + +#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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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; iFd >= 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; iFd < 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; iBufferIndex == 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; iFd >= 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; iFd < 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 +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include + +#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 [-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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* --------------------------------------------------------------------- */ + +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 , 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 +# 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 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 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 +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#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 +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#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 +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#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 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 +#include +#include + +#include +#include +#include + +#include + +#include + +#include + +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 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include + +#include + +#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 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 +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include + +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 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include + +#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 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 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +/* #include */ +#include +#include +/* #include */ + +#include +#include +#include + +#include + +#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 +.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 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 +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include + +#include + +#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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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: + [