[hamradio-commits] [uronode] 01/03: Imported Upstream version 2.3.1
Dave Hibberd
hibby-guest at moszumanska.debian.org
Thu Sep 3 19:47:32 UTC 2015
This is an automated email from the git hooks/post-receive script.
hibby-guest pushed a commit to branch master
in repository uronode.
commit 4013fe89dba7bcbd25ffded96d12bba6c9c78476
Author: Dave Hibberd <d at vehibberd.com>
Date: Thu Sep 3 20:01:45 2015 +0100
Imported Upstream version 2.3.1
---
BBS.txt | 6 +
CHANGES.1 | 929 +++++++++++++++++++++++++++++++++++++++
CHANGES.2 | 637 +++++++++++++++++++++++++++
COLORS | 25 ++
COPYING | 339 +++++++++++++++
FAQ | 35 ++
INSTALL | 79 ++++
Makefile.in | 100 +++++
Makefile.include.in | 13 +
README | 95 ++++
URONode.his | 49 +++
axcalluser.c | 77 ++++
axcalluser.h | 16 +
axdigi.c | 255 +++++++++++
cmdparse.c | 300 +++++++++++++
command.c | 1058 ++++++++++++++++++++++++++++++++++++++++++++
config.c | 485 +++++++++++++++++++++
config.h.in | 36 ++
configure | 303 +++++++++++++
etc/axdigi.conf | 20 +
etc/flexd.conf | 14 +
etc/gateways | 0
etc/help/bye.hlp | 6 +
etc/help/color.hlp | 18 +
etc/help/connect.hlp | 25 ++
etc/help/desti.hlp | 14 +
etc/help/escape.hlp | 16 +
etc/help/finger.hlp | 13 +
etc/help/help.hlp | 10 +
etc/help/host.hlp | 11 +
etc/help/info.hlp | 8 +
etc/help/links.hlp | 16 +
etc/help/mail.hlp | 12 +
etc/help/message.hlp | 14 +
etc/help/mheard.hlp | 8 +
etc/help/msg.hlp | 15 +
etc/help/netstat.hlp | 7 +
etc/help/nodes.hlp | 15 +
etc/help/ping.hlp | 15 +
etc/help/ports.hlp | 12 +
etc/help/quit.hlp | 6 +
etc/help/rose.hlp | 2 +
etc/help/routes.hlp | 16 +
etc/help/sessions.hlp | 10 +
etc/help/status.hlp | 14 +
etc/help/telnet.hlp | 26 ++
etc/help/users.hlp | 8 +
etc/help/version.hlp | 6 +
etc/help/who.hlp | 8 +
etc/help/zconnect.hlp | 23 +
etc/help/ztelnet.hlp | 25 ++
etc/lastlog | 0
etc/loggedin | 0
etc/uronode.conf | 89 ++++
etc/uronode.info | 3 +
etc/uronode.motd | 4 +
etc/uronode.perms | 26 ++
etc/uronode.routes | 21 +
etc/uronode.users | 6 +
extcmd.c | 203 +++++++++
flexd.c | 431 ++++++++++++++++++
gateway.c | 1131 ++++++++++++++++++++++++++++++++++++++++++++++++
ipc.c | 193 +++++++++
man/axdigi.8.gz | Bin 0 -> 1006 bytes
man/flexd.conf.5.gz | Bin 0 -> 988 bytes
man/nodeusers.1.gz | Bin 0 -> 596 bytes
man/uronode.8.gz | Bin 0 -> 3287 bytes
man/uronode.conf.5.gz | Bin 0 -> 3333 bytes
man/uronode.perms.5.gz | Bin 0 -> 1267 bytes
mheard.c | 151 +++++++
node.c | 419 ++++++++++++++++++
node.h | 172 ++++++++
nodeusers.c | 82 ++++
procinfo.c | 358 +++++++++++++++
procinfo.h | 99 +++++
router.c | 261 +++++++++++
sysinfo.c | 243 +++++++++++
sysinfo.h | 26 ++
system.c | 632 +++++++++++++++++++++++++++
user.c | 289 +++++++++++++
util.c | 115 +++++
81 files changed, 10204 insertions(+)
diff --git a/BBS.txt b/BBS.txt
new file mode 100644
index 0000000..22e94cf
--- /dev/null
+++ b/BBS.txt
@@ -0,0 +1,6 @@
+Note in regards to PBBS forwarding:
+If you do compressed forwarding with other PBBS systems, insure you flag
+your connection so that you do NOT have ANSI turned on for that interface
+AND that you disable the escape character. See: man uronode.perms
+for the proper flags. This insures that compression will stay enabled
+and that a compressed ctrl+t is not sent via compressed ascii codes.
diff --git a/CHANGES.1 b/CHANGES.1
new file mode 100644
index 0000000..aa59b32
--- /dev/null
+++ b/CHANGES.1
@@ -0,0 +1,929 @@
+URONode bug fix and change notes:
+
+30/4/1998 v0.3a:
+Users with no permissions on AX25, NETROM, ROSE, TELNET outgoing connections,
+can use alias commands that connect a remote node by AX25, NETROM, ROSE and
+TELNET outgoing connections.
+
+30/4/1998 v0.3b:
+"!" command crashed on systems with no swap: CORRECTED!
+Reconnected on Telnet sended two prompt-line: CORRECTED!
+
+ 8/1/2000 v0.4-pre1:
+Now compile and run under kernel 2.2.x, glibc6 and new ax25 and ax25io libs!
+Added Gateway special tranfer mode.
+
+18/2/2000 v0.4-pre2:
+"Ports" command crashed on systems without listening sockets: CORRECTED!
+Bad Pre-compiler directive order for systems without ROSE support: CORRECTED!
+Now AWZNode have a better I/O flushing.
+Other little code bugs resolved.
+
+*Rewrites by Brian N1URO
+**Note: this is being done on a debian linux server running kernel 2.4.20.
+ your milage may vary depending on the flavor of linux you're using. It
+ may be possible that with the exception of screen pushes, the AWZNode
+ could infact be working 100% fine, this I don't know.
+
+5/4/2003 v0.5.2:
+Renamed the project to AWZ-URONode.
+Stripped out the recursing prompt to the end users.
+Redesigned the output of the node to be similar to that of TheNet X1J type
+nodes.
+Added NodeId variable header of several command output lines, this is
+totally configurable in /etc/ax25/node.conf under the "NodeId" option. I
+suggest in keeping with the design of TheNet X1J to use a format similar
+to: UROHUB:N1URO-2} (that's my personal preference hi!)
+In flexd.c (line 310), changed i++ from (2) to (16) to ignore additional ctext.
+If by chance you only get one packet burst worth of ctext or login.fpr
+information, you may reduce (16) below to 8, or if yo uget 3 packets worth
+of information you may go higher. In my case, I receive two packets of connect
+texts from my FlexNet gateway node so I use 16 for myself. You will have to
+experiment with this. You have been notified. Failure to adjust the parsing
+code properly -will- result in any connect text strings as being falsely
+parsed as bogus flexnet destinations and will maintain a sloppy list.
+
+5/4/2003 v0.5.3:
+With the amount of rewrites, I decided to rename the node to URONode.
+Did more cosmetic cleanups and changed the node to look more like TheNet
+type node. This also included some code cleanup and rewrites of some
+minor routines.
+Readded a node prompt as an option, however unlike the previous way
+the prompt was programmed, if there was no prompt defined, a generic
+AWZNode -> prompt displayed. If in /etc/ax25/node.conf the prompt
+was left blank (aka: "") then a null line feed occurred. Now in
+regards to the prompt, if no Prompt is defined in /etc/ax25/node.conf
+a flexnet type prompt "=>" will display, or if you set the prompt in
+/etc/ax25/node.conf to Prompt "", then the prompt will be defeated
+and no additional lines of text (null or not) will be displayed.
+*I found it VERY frustrating that when a sysop or a user with
+shell permissions accessed the shell, upon return, there was
+no notification that you were back into the node! Added a routine
+that welcomed the user back to the node upon shell logout.
+Repeated the above for the PMS gateway. I guess AWZ hardcoded in
+a prompt for such notifications so I assume I am the one who
+broke this hi!
+
+6/4/2003 v0.5.4
+Cleaned out some coded carriage returns which to me only adds junk to the
+code (unless the intent was for this to ensure a local echo wasn't working
+or something of that nature... ) at any rate, commented it out for now.
+Tightned some more of the displays which also cleans up some code as well.
+By now you may be wondering the madness behind my logic:
+As I stated when I first started this project, my goal was to use the
+existing AWZNode code and make it behave (oh austin powers behave!) as
+much like a TheNet X1J node as I could, with enhancing upon the existing
+tcp/ip and flexnet features this node has. Of course, code cleanup is part
+of the process. One thing I noticed on both AWZ and Tomi's node programs
+were the added strings both push such as the "Trying" messages when a
+user requests a connect to another node, etc. Personally, and especially
+on busy 1k2 baud links, i find it a bit irritating (as I'm sure end users
+do also) that additional lag due to a null line-feed or the node telling
+me what I asked it to is in process. In essance, this *should* make the
+node appear to connect faster for the end user... I hope *grin*
+Cleaned up the Sessions display... the net/rom sessions screen had an
+allocation for Rtt when it's not in use. This also caused the Sendq
+colum to appear grunged/misplaced.
+There's still some line-feeds here n there I'm cleaning as I go to which
+the subversion will increase hi!
+
+6/4/2003 v0.5.5
+Changed mailbox.c and system.c from looking at the users's environment
+mail variable to point to /usr/bin/mail and /var/spool/mail/ respectively.
+I noticed (on debian anyway) that the hardcoded paths failed mail to no
+end. Doing more work on mail as I go along. Note: this only affects internet
+based email! A seperate PBBS such as F6FBB is recommended for AX.25 mail.
+Changed MSession command back to Sessions. I have no idea why this was done.
+Deleted the Send command. It refuses to send no matter what I do anyway, so
+to me it's useless. Also changed ! (STats) to STats to match Tomi's node.
+Personally, I found this confusing between the two nodes. Added a Quit
+hardcoded command to match both TheNet X1J and FlexNet style nodes.
+Tweeked the way the Stats displayed. Memory shows not just 'memory' but
+the definitions between swap and physical ram are displayed. Also AX.25
+daemon socket stats are also a bit more defined.
+Mail checking sometimes worked, other times didn't. Fixed the mailpoll
+routines so that polling would keep displaying to the user that he/she
+has new mail. This may irritate the user, but considering it's your
+hard disk space that's storing their internet email, for them to be
+on the node and simply choose *not* to read and/or delete mail from
+your resources is just as rude to you (my train of thought anyway).
+**NOTE: I can't stress enough on how dangerous (in regards to spam)
+the mail feature can be! I **highly** suggest that you *only* give
+access to those you know are hams! Needless to say, I would *not*
+turn access for this feature on for global access!!! Not only would
+you upset many people who are against receiving junk emails, but you
+could risk losing any and all internet connectivity from your ISP as
+some are *very* picky about spam mail that's relayed! Working for ISPs
+in the past, I can verify this :-)
+
+8/4/2003 v0.5.6
+Still cleaning up some displays...this will be a task as I go along.
+One thing I'm not positive about is whether or not on multiple port
+usage how some diplays will read since I only have a single ax0 port
+I'm using.
+Fixed some routines in the do_finger command and added user usage
+messages. In some cases, routines were forced so that if certain
+strings (even null) weren't set after the finger command, it
+was programmed to force the user to finger the localhost whether
+or not that was their intentions. Personally, I found it better
+to push a usage message of one line to the user than to go ahead
+and process an errant finger request to the localhost. I did
+force finger to require an @ within the command... since you're
+fingering something"@"somewhere. This is displayed in the usage
+message to the end user whether or not the input string after
+the command is null.
+Mail checking still seems buggy, and the bug seems somehow (so far)
+to be linked with the mailbox.c routines. This is also where the
+do_sendmessage command is. Fixed some routines in the send command
+where if the To: or Subject fields comtained an UPPERCASE
+character, it could cause the node to segfault out and leave
+the ipcs open. This is bad! More on this in the Known Bugs section.
+
+10/4/2003 v0.5.7
+Whew! After much hassle...FIXED the former (and I mean former hi!)
+SEnd command. While I was at it I also renamed it from Send to
+MEssage. I thought Mail and MEssage were similar in function so
+I decided to keep them together on the prompt as well.
+
+11/4/2003 v0.5.8
+Found a bug in the MEssage command *sigh* more on this below.
+Moved the location of the help files from /usr/lib/ax25/node/help/
+to /var/ax25/node/help/ so that all created node files are together.
+Changed/fixed some of the help files to reflect changed commands, etc.
+Cleaned up more diplay text. (since I'm more a code hacker than a true
+coder, this is what I do best hi!.. but I learn as I go.)
+Edited the man pages and changed them from a text to a compressed format.
+Changed the configure script to grab the server's hostname. If your
+server's hostname is already an *.ampr.org host, then you should be
+fine with everything. If your server's hostname is a commercial domain
+based name, then you will have to edit config.h and insert the proper
+your.ampr.org hostname inside, or if you wish replied mail to be auto
+redirected to a NOS based node, enter in your NOS' ampr.org hostname.
+Added a warning message in the ./configure script to alert the sysop
+to check their config.h file for proper paths, etc. I was going to force
+a load of vi, but now-a-day most people don't use vi from my discussions
+but another editor such as ae, joe, pico, etc. Since the sysop will be
+editing their config files anyway, I feel the sysop can take a minute to
+verify paths and variables. Please pay close attention to any and all
+comments within this file!
+Added Makefile.in which is a 'generic' Makefile. Makefile is now created
+when you run the configure script. Also added some other environment
+grabber functions to the configure script which adds to the proper files
+that requires them for you.
+Added removal of Makefile in the command 'make distclean'.
+Removed local echo of "To:" field when using the MEssage command. That was
+for debugging purposes anyway.
+
+12/4/2003 v0.5.9
+Fixed the bug that drove me nuts with the mail command. Now the mail
+command will reject/refuse a parameter. One more down off of the
+hitlist of bugs :-) It was suggested by N1UAN to make a configure
+script toggle for the MEssage command too. I may do that in the future.
+Fixed a bug in the POrts output. Since I only have one port, this was
+hard for me to test. N1UAN has multiple ports and using his node I was
+able to see and fix this bug before it made it to the buglist.
+
+12/4/2003 v0.5.10
+Woops, fixed a bug in the Info command where there wasn't a line
+feed after the compile date. Reported by N1UAN. I also found a bug
+in the display of: Node Call|Alias where lines were grunging. I
+*think* I fixed this. Unfortunately this is the result of me only
+having one port to work with hi! I happened to find this myself
+using the copy N1UAN is running. Hopefully I fixed this bug.
+More of a maintenance release than anything else. Fixed a few tweeks
+here and there, nothing worthwhile to mention. The key thing in this
+version was to make it more customizable for the hard-set commands.
+This was suggested by N1UAN to which I kind of agree. It is possible that
+one could have a linux box on an amateur radio packet network but not wish
+to have it connected to the ampr.org or any other TCP/IP network. Coding in
+these commands would then become a bit of a tease to the end user who may
+wish to use URONode as a 'NOS' substitute for outbound telnet links, etc.
+Now hardcoded commands will be toggled on/off depending on how you answer
+the configure script. Answering NO to ALL questions will enable ONLY the
+following hardcoded commands:
+?, Bye, Escape, Help, Info, Quit, Status.
+Answering YES to AX.25 enables:
+Connect, Desti, Ports, Links, SEssions, Users.
+Answering YES to Email enables:
+MEssage.
+Answering NO to FlexNet:
+Disables the Desti command and will NOT compile or install the flexd
+daemon...however if you have a destinations file that is valid that
+will allow users to connect to digipeated paths without having to
+manually type a 'via' statement in.
+Answering YES to FlexNet enables:
+Desti.
+Answering YES to MHEARD enables:
+MHeard.
+Answering YES to NETROM enables:
+Nodes, Routes.
+Answering YES to ROSE enables:
+Rose based protocol strings within ax.25
+Answering YES to TCP/IP enables:
+Finger, HOst, Ping, Telnet
+Answering YES to TALK enables:
+TAlk.
+I may move the users to the default hardcoded commands..but for now my
+thinking at 5:00am on a saturday morning is, if you're not going to run
+ax.25, then you probably aren't as concerned who's in the node :-) Also
+the use of the linux netstat command will show you who's on. The commands
+I'm considering moving to the default are the ax.25 related commands...
+since after all, if you're on RF, you'll -need- ax.25 right?
+The Mail and SYsop commands are flagged on|off by the node.user file.
+
+14/4/2003 v.0.5.11
+Another change to the configure script. This time it checks your local
+hostname and requests that you verify it. If you see it's correct,
+just hit enter. If not, change it. Now... and this is tricky...
+*if* you do NOT wish to have users RECEIVE mail on the node but have another
+smtp based server such as a NOS node in which you wish your users to receive
+smtp mail, then what I suggest you do is set hostname to the hostname of
+THAT server. What this will do is send mail from the user with a 'return'
+path of your NOS server. For example;
+On my system I have an MFNOS node which users may send and receive SMTP
+based mail. It has a hostname of "n1uro.ampr.org". While users may have
+permission to SEND mail from URONode "dx.n1uro.ampr.org", I wish them to
+only receive their mail at n1uro.ampr.org, so in this case I would tell
+the configure script my hostname is: n1uro.ampr.org. It's sort of a way
+you can allow mail with some sort of anti-third-party protection. Its not
+perfect, but it helps. The configure script *will* prompt you for this
+whether or not you enable the Email feature.
+I added two neat commands. One is the new Version command. This is set
+as part of the default hardcoded commands. All it does is shows the
+version information of the node. This same data is also shown in the
+Users command to keep the node in line with the display parameters of
+TheNet/X1J style nodes (as I like). The other is what I call a Whowas
+command. I got the idea from being on IRC, and borrowed code from
+PE1RJA's node. With the W command, this will show you when a callsign
+was last on the node, and how that user connected... ie: which port,
+ip address, etc. If the user connected multiple times within the scope
+of the log rotation then a columnized listing of that user's information
+will be displayed. My happy news is that the SSID stripper from the
+user's connection in sending email is fixed. One bug down!
+
+15/4/2003 v0.5-R1
+WooHOO! MHeard table read/write of digipeated MHeard routing is FIXED!
+What I had to do was get argv to parse up to two digipeaters and then
+print to the device each in reverse order. Now since my RF digipeater
+gateway is a direct flexnet neighbor on axip, this was all I had to
+test with, your milage may vary. If the digipeated path is not yet in
+the mheard table, then it will fail. Another bug off of the list!
+*whew* I knew I was close <G>. Also found some more screen writes
+to tighten up. As far as I know, I'm going to (for now) close this
+chapter of my life's efforts and make a release. I"m happy with how
+URONode is performing and my alpha tester N1UAN appears to be just
+as pleased :)
+Found a bug in the output of the Who command when *
+was entered. While this didn't seem to affect me on a debian system,
+it did seem to act funky on a SuSe system. Flexd needs NOT be edited
+now. Cleaned up some time variables in the MHeard routine and added
+a column for the port heard, and the frame (pid) type. Since the
+users can now see the pid types, they'll have a hint as to how their
+connect request will be handled.
+Found two bugs in the finger routine, both which appear to be in ALL
+flavors of "*node". The first one I fixed, and that was quite simple.
+When fingering information, the [address] or [hostname] was omitted.
+I don't know if this was intentional, but I fixed it anyway to match
+that of standard 'finger' displays. The second appears to be that
+on a long RF hop, or a socket that's become broke due to routing
+being cut, etc... there's *no* escape. For now, I've omitted the
+Escape: CTRL-* display in all routines. It will still work for
+telnet, netrom, and other types of connects. Since the Escape
+command is a seperate command at the moment, I think it's fine
+for users to check|set their Escape sequence. Hopefully I'll be
+able to figure out a routine to escape from a 'stuck finger' :-)
+Also tweeked the output of the HOst command.
+*Welp, further research shows that there is no "escape" in the
+native linux finger command... as there is none with the ftp command.
+Needless to say, the better 'fix' was to simply disable all 'trying' state
+messages. Personally I find them to be excess traffic that's not needed as
+either the node will tell you that it's connected or it will tell you that
+it failed. I know flexnet will tell you that it's trying a link setup and
+xnet will take that a step further and show you which port the link is being
+setup on. I may add the set escape sequence in the login screen as default
+prior to users attempting connections so that it'll be easier on them to
+know that there is a way to break a connect if needed.
+
+16/4/2003 v0.5-R2
+Ok, well I did decide to add the CTRL-* message as part of the
+initial user login screen. Also made some minor tweeks to the
+telnet login where now it shows more of a 'linux' style login.
+Did some more screens cleanups and stripped out a lot of the debugs
+I had commented out of the code. Ok..enough for now...I'm considering
+this version 'done' unless bugs are reported. :)
+
+22/08/2003 - Bug/security report
+Morgan sm6tky publically posed a security report with some PoC listed but
+not all. While I was able to duplicate what he did submit for PoC, I
+wasn't able to find others. I'm very greatful to Morgan for bringing such
+information to my attention, I'm surprised that his first step was to post
+it in a public email list and list that I didn't reply when I wasn't even
+given the chance to... however with that being said, I still took his
+notations to heart and put the project a bit on the back-burner until I
+had time to do the fixes. I also offered Morgan a chance to submit code
+fixes to which he failed to do such. I don't claim to be a coder but just
+a hobbiest in regards to C and always welcome patches as I have with htppu
+with patches submitted by Thomas dl9sau who's also released his own flavor
+entitled SAUPP. Version 0.6.x will be in process as I have the time to do
+such.
+
+v0.6.0 - never happened. Just made the directory structure and took an
+initial peek at Morgan's reports.
+
+12/7/2005 v0.6.1
+Security issues fixed/removed. Rather than fix the talk command I decided
+to just eliminate it in favor of an external conversd command. I figure
+there's plenty of channels and lord knows there's actually more convers
+servers now than users to use them... why not just use that?
+
+Another security issue was mail. Instead of having mail routines built
+into the node itself, I figure a node sysop can grab my updated axmail
+node plugin and use that. I've done some basic security tests and it
+seems to be a better way to go.
+
+12/7/2005 v0.6.2
+Just a beta version, never released while working on more security
+fixes... I think I'm getting close now!
+
+Changed some code in the do_help routine in command.c where Morgan
+reported the possibility of a buffer overflow.
+
+Changed some code in the syslog routine in util.c hopefully fixing the
+formatstring vulnerability in that routine.
+
+Changed some code in gateway.c in hopes of fixing the reported buffer
+overflow.
+
+Found what I thought to be an open hole in ipc.c, should be fixed and
+with any luck the ipcs build-up issues will vanish with it. Only time
+and your debug reports will tell.
+
+Fixed a bug in Makefile where the man pages weren't installed due to the
+fact I gzipped them and didn't change this in Makefile.
+
+Changed the ftp url path, listed below.
+
+v0.6.3 - some cosmetic tweeks I can't recall what they were.
+
+04/07/2006 v0.6.4
+
+Found a bug where if a user's permissions were flagged for "no escape"
+such as a xNOS, F6FBB BBS, etc, that the node tried to display an Esc-?
+as part of the prompt/screens. Removed the Esc-? from displaying. That
+simply annoyed me and I'm surprised it wasn't reported... after all if
+there's no escape why show "?" as one since "?" can be used as an escape
+character with CTRL.
+
+Added an Email flag in node.conf. Simply add:
+Email <your at node.ampr.org>
+on a blank line within node.conf for it to get pulled into the node. If you
+don't "(null)" will display. It won't prevent the node from functioning but
+will show users how lazy you are hi! This allows a sysop to deny all users
+connection access _unless_ they have a password, while at the same time
+allowing the node sysop a means of displaying a point of contact so that
+users wishing to use their node and it requires a password can send a
+communication to gain access. I strongly suggest for any account that has
+sysop privs on the node that you force a password on _all_ connects and
+that you only grant access via internet/amprnet to those who request a
+password for security reasons if anything at all. Because I feel this is
+security related, I'm making this a release.
+
+Fixed a bug in the install routine for the man pages. The default
+install for man pages was /usr/man, now it's /usr/share/man. I also
+updated the manpage for node.conf.5 and re-gzipped it.
+
+24/10/2006 v0.6.5
+After a nudge from Stefano in Italy, I reintroduced a method in which one
+user on the node can send a brief "msg" to another. The command once was
+"talk" and still is on node (or if you prefer linuxnode that Tomi has
+set the standard for!). For the sender, they get a full status report
+as to what happened to their "msg" once the "enter" key is hit. For
+the receiver, if they're truely idle on the node, the message will pop up
+on them and the prompt will not return until they acknowledge receipt
+of the msg by hitting the "enter" key. Also note that a system bell
+will return on both sides, or just the sender's side *if* the msg
+wasn't delivered. Since this acts sort of similar to today's Instant
+Messaging world... I figure "what the hay they play noises too". I still
+stand on the theory that if one wishes to engage in keyboard chat, they
+should make direct TNC<>TNC connects or use convers but Stefano
+made me rethink this and I can see how it could be used for one user
+to "ping" another user with a msg saying "hey meet me on conv channel
+32767 and see if we can wake the sleeping sysops!" :-) Originally this
+was part of Morgan's security report filed back in 2003 (what? me
+procrastinate? LOL) so with convers so easily available to URONode as
+a plugin I felt it just as simple and quicker a fix just to remove
+"talk". I renamed the command to "msg" since you're really just sending
+a message and not really "talking" to the remote end.
+
+Fixed the help files a bit to move talk.hlp to msg.hlp, and edited the
+content of such to fit the re-introduced command.
+
+26/10/2006 v1.0.0
+First off, many thanks to Stefano and Alessio for their interest and
+contributions to URONode. They've inspired me to help improve this
+spinoff of AWZNode (which is a spinoff of FlexNode which is a
+spinoff of node which is a spinoff of.... :-} ) Stefano asked me a while
+back about putting in compression for Telnet and Connect commands.
+Considering so many have broadband now on their wired links, I somewhat felt
+this to be unnecessary, and here in the U.S. ax25 based transmissions are
+supposed to be in plain text... so between those two major reasons I had
+thought it best to just eliminate this feature a while back... not to
+mention security issues with zlib that were going on. Since those have
+been cleared and in respect to the motivation Stefano and Alessio have
+given me with their interest in this project I thought it only nice that
+I try and fullfill their desires as best as I can. Recieving compressed
+requests into URONode was always there but not an outgoing client... so
+I spent a few moments and coded one back into the front end. Needless
+to say, ZTelnet and ZConnect (as with node) are in URONode now as
+client gateway commands.
+You need to set up another inetd/xinetd instance on an unused port
+that calls "node -c" to enable receiving compressed connections via
+telnet. Make a new alias/ssid for ax25/netrom if you wish to support
+ZConnect client requests. Failure to do such will result in the remote
+end getting an error message.
+
+27/12/2007 v1.0.1
+After a heated discussion with w0rli (as if that has never happened
+on packet before, and him accusing me of knowing nothing about packet
+or it's protocols) I decided to keep him happy while working on a system
+that's linked to one of his. Hank feels that by having a login screen this
+makes a node an application. While I can understand how he determines this
+in his one-sided point of view, I still disagree with it but can appreciate
+his concerns. Apparently he has never logged into a backbone router at an
+ISP and seen a cisco MOTD file... or is a backbone core or border router
+not a node on a network? :) In any event, I decided that I'd make the whole
+login sequence of displaying the node version and /etc/ax25/node.motd file
+an option to the node sysop upon running the ./configure script. Along
+with not displaying a MOTD file, the default FlexNet style prompt of
+"=>" will also not display. This will make URONode act more like
+Hank's snos and like TheNet X1J-4 (with the "welcome" message flagged
+off upon connect). Thanks are given to w0rli for this idea.
+
+I also added a flag for the "NODE} Goodbye." string so that if you
+do not have a MOTD displayed, it will also halt the display of the
+node front-end saying bye to the user.
+
+01/01/2008 v1.0.1a
+I decided that I'd go through the code and search for more cases that
+if MOTD is *not* defined, to ignore any and all reconnect flags, whether or not
+they're defined for external plugins (ie: axMail) or alias commands in the
+/etc/ax25/node.conf file. If during configure you decided to add MOTD during
+the option questions, then the node will infact act more like a user
+application including allowing reconnects etc.
+
+I had thought I fixed the man pages install, appearantly I never saved it.
+This should now be fixed. My apologies.
+
+* Author's Note: If you're linking the node to systems such as SNOS, or
+you're on a very busy network, or if you forward with other BBS systems
+who for whatever reason feel the need to connect to your node first
+before connecting to the BBS (which I feel is unneccessary but happens), I
+strongly suggest that you do NOT enable the MOTD which is the default option
+now in the configure script.
+
+*** Important: I just don't have the time to clean up all the gcc-3.x
+compiler warnings however URONode compiles just fine under gcc-2.95
+so I made a decision to force gcc-2.95 for compiling URONode under.
+Configure was rewritten to check for this, and if it doesn't it will
+instruct you on where you can get a copy. This will not interfere with
+your installed copy of gcc-3.x if you so have it. I have verified that
+URONode compiles quite cleanly under gcc-2.95 and I do have both
+versions on my box:
+root at schlitz:/usr/bin# ls -al gcc
+lrwxrwxrwx 1 root root 7 Jun 25 00:00 gcc -> gcc-3.3
+root at schlitz:/usr/bin# ls -al gcc-*
+-rwxr-x--- 1 root root 69960 Mar 10 2004 gcc-2.95
+-rwxr-x--- 1 root root 85196 May 24 2005 gcc-3.3
+As you see above, gcc by itself is just a symlink to the latest
+version of gcc-*. Ensure that gcc-2.95 is in your executable
+path.
+
+23-24/01/2008 v1.0.2
+Huge news! I finally got off my duff and cleaned up compile warnings.
+URONode will now compile fine on gcc-4.1 and under! This was just something
+that was under my craw for a very long time, but not that critical enough
+so you can really ignore the above notes in regards to GCC.
+
+I ended up also making some modifications to the configure script, Makefile
+and config.h. Part of cleaning up some of the compile errors was a dupe
+conflict between library "log" routines and the internal node "log" routine.
+URONode now has it's own node_log() routine as to keep it seperate from
+library log routines. There's no change in it writing to syslog for you,
+just the function was renamed to avoid compiler warnings. Many files were
+updated due to this.
+
+**Man file for uronode is now called "uronode", not "node". The binary made now
+is also "uronode".** This is *very* important because when you run
+"make install" or "make installbin", your inetd.conf/xinetd files will need
+to be changed to spawn the new binary, and your config within
+/etc/ax25/ax25d.conf will also need to be changed from calling "node" to
+call "uronode" now!! If you do NOT do this, you will be stuck running either
+an older compile or it won't launch at all. Please see the examples in the
+INSTALL file for help on how to configure this properly. In the future
+I may change the config files from node.* to uronode.* too. The advantage
+of doing this would be tri fold:
+1) it'd allow sysops to compare and test URONode side by side with another
+ package such as Tomi's LinuxNode
+2) sysops could offer both flavors of a "node" to users if they so desired
+ to do such.
+3) a sysop might prefer to have 2 compiles of URONode... one with full
+ MOTD compiled in, one without.
+Those who know me, know I believe in allowing a sysop to have the freedom
+to pick and choose just how they run their nodes... and this just adds
+to their options. I do however discourage doing this unless it's for
+testing reasons but c'est la vie.
+
+**** Actually, I figured why wait to change files around, so I changed
+all the config files from "node.*" to "uronode.*". Now if you're doing
+an UPGRADE, you'll need to rename your config files in /etc/ax25/node.*
+to /etc/ax25/uronode.* or else you'll have issues with some routines.
+I also deleted the *.ex files and changed installconf so that the proper
+files get copied into /etc/ax25 for new installs. I also changed all the
+man page files that were node.* to uronode.*
+
+As much as it sorta kinda but not really pained me to do this, I decided
+that it may be cool to have *something* to let the user know that their
+outbound ax25-type connect is via flexnet, so I added a routine in
+gateway.c which checks the connect type and if the request is via FlexNet,
+the user will see the standard "link setup..." message like they would on
+a flexnet node, followed by "*** connected to <desti>". This MAY have an
+adverse affect on FBB forwarding since FBB looks for "Connected..." instead
+of "*** connected...", but there's ways around that in your FBB forward
+file.
+
+25/01/2008 v1.0.3
+
+*Big News*
+For Debian and (K)ubuntu users, I've decided to make a release of
+uronode as a .deb package. This is my first time doing this and I'm really
+not that comfortable with rolling it out officially since it's my first
+pre-packaged binary so here's what I suggest you do if you decide to use it:
+cd /etc and tar cvf ax25/* ax25files.tar
+dpkg -i /path/to/uronode*.deb
+tar xvf ax25files.tar
+For now this will preserve your current config as the .deb package *will*
+overwrite your current files in full including configs!
+YOU HAVE BEEN WARNED!
+
+Found a bug in the WHO command when MOTD was disabled. Currently if you
+don't define that, then the WHO command is deactivated and not compiled
+in. MH works fine and should be enough to be used to track recent connects
+to your node.
+
+Discovered a bug in the newly introduced FlexNet style cosmetics where
+after "link setup..." if the connect request times out, error isn't printed
+on a new line. I wrote a new string to push to the user so that if their
+request does time out, it matches that of FlexNet's timeout string while
+leaving vanilla ax25 and netrom timeout errors the same. Again, these
+strings will inform end users the type of outgoing request was made
+whether it was FlexNet or vanilla ax25.
+
+While I was add it, I decided it would be helpful to end users who are
+making FlexNet links to show which ax25 interface is being used for
+connects similar to that of how Xnet shows connect requests. The interface
+will be displayed in parentheses () such as: Link setup (ax0)...
+so if the link fails, the user can see which interface to try a direct ax25
+connect request out from.
+
+I think I fixed a slight bug in flexd.c where if the LO.FPR and C.FPR
+weren't formatted just right, it'd exit prematurely and issue a false
+error. Apparantly the buffer was set a bit too high and captured too much
+to parse, so I lowered "buffer" from 1024 to 512 and it now appears to be
+fine.
+
+A "bug" was reported about the config of the backend of URONode when infact
+the bug was with ax25d.conf and nrports. Remember, when you configure your
+node, ALL your SSIDs for ax25, netrom ports, and axports *MUST BE UNIQUE* if
+you have RF links to native netrom nodes. Failure to do such will result in
+some flooding issues because if an ssid in axports, ax25d.conf and nrports
+is shared, an X1J node connecting into URONode will result in the ax25 link
+layer being seen as a user and not a network socket. You'll ping-pong
+the node with X1J in almost an endless loop. *You have been warned!*
+
+22/02/2008 v1.0.4
+
+I decided to make the node text more "technically correct" in it's display
+of things... mainly in regards to "ports". We don't have "ports" per say
+but we do have "interfaces". Needless to say, any reference to "port(s)"
+has been changed to "interface(s)" including the former Ports command. This
+has been replaced with the new INTerfaces command.
+
+Users now will show the "interface" a user may be coming in on if it's ax25
+or if inbound from FlexNet.
+
+The PIng command has been shortened to Ping now with the refactor of the
+"Ports" command. Ping now only requires "P" to ping another node.
+
+*Note: this will be the last release for a while as I'm moving and won't
+have a server or test bed to test with.
+
+10/05/2008 v1.0.5r1
+
+The move has completed and of course in my own sick and twisted mind, I have
+decided to do a release that I call version 1.0.5 release candidate 1. This
+is a minor release but it's something I despirately wanted to do for a while
+and was just sitting like an itch under my skin to do, and sometimes you have
+to just take a break from it <all> to clear the noggin and get the code the
+way you want it. What was bothering me was the fact that not one flavor of
+a linux-node complies with that of the Software 2000, inc specifications of
+Net/Rom... and I desired to be the first to do such... yay me?
+
+In any event I went through the code and made changes to the following files:
+command.c, config.c, extcmd.c, gateway.c, node.c, node.h, and system.c.
+What this does for you is makes your URONode behave more to the specifications
+of Net/Rom regardless of how you define the MOTD flag. If you define the MOTD
+flag, the node will continue to behave as it has <all> along, however it forces
+it in "off" mode when the incoming connection is Net/Rom based. This is
+extremely useful if a robot script (such as FBB forwarding) is used to
+go through your node.
+
+The decision of making this a release candidate was because I'm sure I may
+have missed testing some of it's behavior and will have to do some cosmetic
+and/or bug fixes.. so if you find any, please report them to me and I'll do
+what I can to fix it.
+
+Source, .deb, and .rpm packages are available at the typical location of
+ftp://ftp.uroweb.net/pub/ax25/ ...enjoy for now!
+
+12/05/2008 v1.0.5r2
+
+I had this really irritating bug that appearantly I just never noticed
+all this time when HAVEMOTD was undefined. Thanks to some assistance from
+K2MF, I was able to identify and fix this bug. Inside the main loop statement
+for the node, when a user disconnected, it was adding an extra frame to
+the stream that contained only a line feed. Looking back at this, I did this
+due to the fact that X1J handles it's output to the terminal differently than
+does any other node that I'm aware of.
+
+In any event, taking out this line feed somewhat caused other outputs of
+text to lack a line feed when it needed it... so this meant changes in
+command.c, extcmd.c, gateway.c, ipc.c, node.c, system.c, user.c and maybe
+more that I can't quite recall as of this writing.
+
+The good news is that I did fix 2 minor bugs that were under my skin!
+One minor bug was that when a nodes or destis list ended with a row of
+4, an extra line-feed was displayed. While this bug still exists under
+certain conditions, it's no longer present during netrom connects.
+
+Also during a netrom disconnect, an extra line-feed no longer sends to
+the remote node thus making it more Software 2000, inc. compliant. I'll fix
+the previous mentioned bug for release 1.0.6 sometime.
+
+21/05/08 v1.0.5r3
+
+Fixed some screen cosmetics that I introduced while making the node more
+Software2000 compliant... I'm sure I missed a few more.
+
+***Big News***
+I've finally tracked down and fixed the remote escape bug (I think)!
+What I saw was happening was that the SIGPIPE handler wasn't being
+executed properly and it appeared to be waiting for more data which
+it never received. I added a quit_handler routine in the main loop
+which now will execute a node_logout(), flush out the IPCs,
+log the event to syslog, and close out the application properly.
+Due to this bug lingering in all flavors of *node for linux, and not
+having the resources to fully stress-test this, I'm going to leave this
+as release candidate 3 for now until (hopefully not!) someone reports
+that this routine is causing ill-behavior.
+
+26/05/08 v1.0.5r4
+
+There was a LOT of cosmetic changes in this one which caused me to add
+a LOT of conditional calls into the code, many of which I'm unsure whether
+or not it'll fly properly under every condition so your milage will definately
+vary depending on your specific setup! Since URONode has become very popular
+within the EastNet packet system I decided to make the node appear for both
+the ax25/FlexNet side or its NetRom side, dependant on how the user logs into
+the node. Because of the massive changes in structures, rather than listing
+them <all>, the above description should do.
+**Note: you MUST add a new line in uronode.conf that defines
+FlexId XX#XX-##
+Either take yourcall-ssid from ax25d.conf OR if you're linked to a
+node that does flexnet, use yourcall-ssid as it is on the remote flexnet
+system. If you don't, and a user connects in via telnet or ax25/flex you'll
+display (null) to them. Also: if you added a } after your NodeId
+callsign-ssid, remove it. It's been hardcoded into URONode now.
+
+I decided to mute the banner section of the login sequence however
+it will still display your MOTD if it's defined during ./configure.
+If there's a demand for it, I may add it as a configurable option.
+
+Even though I put r4 out for download, I did find a couple minor bugs
+which have since been fixed.
+
+29/05/08 v1.0.5r5
+
+In a nutshell, if the user connects to your URONode via NetRom, then
+they will get standard NetRom prompts with "ALIAS:CALL-#} " as a result
+header to all of your commands with the exception of FlexNet gateway
+connects.
+
+Now in uronode.conf, a *new* line _must_ be added for FlexId. The parameter
+is:
+FlexId <call-flexssid>
+An example since my URONode is on FlexNet as ssid 3:
+FlexId N1URO-3
+
+Also note that the need to have a closed bracket "}" after your NodeId
+now is not required and should be deleted. I finally got off my butt and
+hard-coded it into the software.
+
+The Version routine was also changed depending on how the user is connected
+in. If the incoming connect is made using NetRom, then the standard prompt
+is displayed. If the incoming connect is via any other type of link, then
+a columnized display is made showing Software version, NodeId, and FlexId
+in hopes of eliminating confusion to the end user.
+
+While in the midst of all the above, I did find some cosmetics to fix.
+
+Before I make this release candidate an official, I'm curious as to
+whether or not anyone would object to me eliminating some of the
+standards of the login banner of the node (non-NetRom displayed).
+Please let me know and I'll make the necessary changes if need be.
+-- actually I already decided to do this.
+
+I added a new routine in util.c which now will give the end user
+the type of prompt based upon the type of connection. The default
+for ax25/FlexNet is: "=> " (note the space after > unlike Flex)
+for NetRom is: "ALIAS:CALL-ID} "
+for tcp/ip is: "usercall at hostname:/uronode$ "
+
+With the new routine, I changed the main loop in node.c from defaulting to
+Prompt simply to using node_prompt().
+
+01/06/08 v 1.0.5
+URONode version 1.0.5 is now considered to be "final". With the new month
+is a new final release, and in this release it has more face-lifts than
+Joan Rivers hihi!
+
+I added a new routine in the configure script which will prompt you for
+telnet colored routines... yes we have ANSI! Now, a couple things about
+pushing ANSI code:
+1 - consider network bandwidth if you have IP users via RF
+2 - many windows apps such as WinPack do NOT support ansi. This is NOT
+ a fault of URONode, but that of the Windows application. If you
+ find you have trouble decoding ansi, try PuTTY or use HyperTerminal
+ in telnet mode. Ansi is hard disabled for ax25/Flex and NetRom connects.
+I also added ansi codes for "Nodes" and for "Desti" lists commands if the
+inbound connect is made via IP.
+
+Added an "EXit" command for users in IP mode since you now feel like you're
+in a bash shell... just a 'force of habit' thing. Bye still works.
+
+Fixed a bug introduced with the new node_prompt changes to node.c. If
+the user was required to enter a password outside of being on the localhost
+or amprnet, the prompt displayed twice... this is now fixed. I also found
+and fixed soem more cosmetics that I considered to be wrong. This bug was
+driving me insane as to why it was doing this, but I finally tracked it
+down.
+
+Found and fixed another bug where if the user's permissions were set
+to a perm "escape off", prompts didn't properly function.
+
+Made a change to nodeusers where now if no one is on the node, it'll
+say such instead of simply being blank.
+
+A note about ansi:
+linux shells will decode ansi pretty good as will old DOS based terminal
+programs such as Qmodem, Telix, etc. If you use a raw terminal such as
+xNOS, you'll need to insure you load ANSI.SYS in your C:\CONFIG.SYS file
+and reboot so the terminal will decode ansi.
+Windows telnet *will* decode ansi as well however since XP, local echoing
+by default is set to OFF. You can CTRL-] and type: set localecho, then hit
+enter twice and you can get echoing back on.
+If you use something such as WinPack which doesn't decode ANSI, please do
+NOT contact me! Contact the authors of WinPack and report the lack of
+ansi as a bug.
+
+I also am including a copy of axdigi from the original FlexNode package.
+This is compiled as a static binary and a copy of axdigi.conf IS
+also included in the source package, but I won't package it with the .deb
+or .rpm packages... however I do reserve the right to change my mind :)
+
+Static binary packages are compiled with the following options OFF:
+Rose support
+All other options are compiled in.
+
+04/07/2008 v1.0.6
+Found and fixed a bug in the Who routine where a netrom prompt was merging
+with the last entry of a list even if the connect was not netrom. This change
+was made in system.c.
+
+Added some more ansi routines if #defined COLOR. Here's the schema:
+Connects display in green as in "gateway go"
+Reconnects display in red as in "gateway stop"
+Commands display in bright white
+Netrom Nodes (full list) in bold cyan
+FlexNet destis (full list) in yellow
+Current users in magenta
+Aborts and timeouts blink bright red
+Logouts in low cyan
+I'm making the color schema a bit more consistant through out the application.
+While doing such, I'm cleaning things up so that just the headers are in
+color, not the actual results so that if one is NOT decoding in ansi (and
+again if not that's a fault of the client NOT of the node) the node won't
+appear as offensive.
+
+Found a bug in the auto router where it wasn't parsing the digi path
+from the mheard table, HUGE credit goes to Barry K2MF (of MFNOS fame) for
+supplying the code that properly handles this. Fixed.
+
+Did a lot of clean-up for how the node/shell responds dependant on how the
+user connects in. Many changes done in gateway.c, extcmd.c and node.c.
+
+Now made ANSI a flag in uronode.perm... I may change this later however
+because of such, it forced me to have to make a new nuser_list routine
+in command.c as well as move node_prompt from util.c elsewhere so
+command.c seemed like the best choice. Setting the user bit +512 will
+now grant them telnet ANSI color. Not giving them this will turn
+it off. I'd like to make it an end-user toggle so that depending on
+which client the user is coming in with they can choose online to get
+color or not. The user perm flag replaces defining Color during the
+configure script.
+
+Defining MOTD now serves multiple functions:
+1) Display of the MOTD screen/file
+2) Display of prompts for all interfaces
+3) Reconnect back to the node upon a gateway link out
+I suggest compiling with MOTD on, which configured by default in the
+.deb and .rpm packages.
+
+Changed some of the technical correctness of the node in regards to IP
+functions. Ping now returns ICMP Echo request/reply messages and IP based
+connects out now show the service/port that the connection request is being
+opened to.
+
+Added color schemas to the NetRom and ax25/Flex interfaces if the user
+requests it to be on. The same color schema is used on all 3 interfaces.
+
+Fixed a very irritating bug that some folks have reported on which
+when do_ports() was called, and the axport description was over 42
+characters in length, do_ports() was *not* properly truncating the
+additional characters, and making things looks a bit sloppy. A similar
+bug exists in LinuxNode =< 0.3.2. Note: In your axports file, you *MUST*
+have a tab after the window digit before writing your interface
+description or else the parser will consider the spaces as just that...
+empty spaces! You have been WARNED!
+
+Updated uronode.conf and uronode.perms files to show examples of recently
+added features.
+
+Long overdue: Updated the MAN pages!! I'm so sorry for letting these slide!
+It really is hard enough trying to keep track of things in this file, never
+mind actually documenting it in a manual page or two hihi!
+
+Found and fixed a bug in the logout routine where a false error was being
+reported that the shared memory segment (IPC) couldn't close. Somehow this
+was introduced by me duping the lines in the routines so that it was actually
+trying to close the shared memory segment twice! I guess in reality, the
+log error was indeed correct since there was no second segment to close hi!
+
+Added a "make update" option to the Makefile. This option *must* be used
+in version release sequential order or else it may fail!
+
+Fixed a cosmetic bug in the way NetRom nodes introduced by me when I created
+multiple interfaces. The word "NetRom" appeared twice in the header when
+a user would request a Nodes list.
+
+15/11/2008 v1.0.7
+
+Made some cosmetic changes to text and ansi color displays, still a few
+more to do but not critical so it gives me an excuse to do a maintenance
+release one of these days hihi!
+
+With the assistance of the great and mighty <all>, the <all> of c coding
+knowledge, I was able to incorporate a loop detection system when making
+FlexNet or ax25 connects... now if there's a loop in the outbound connect
+request, the user will be informed of such which includes a system bell
+(beep). I thought about adding a loop connect block such as with FlexNet
+however in the case of axip/axudp links many links may share the same
+interface which really would be unfair to the user trying to gateway out
+that's also coming in from the same axip interface.
+
+Now for the big news of this release: By request of Bob Anderson K2BJG,
+I wrote a kluge for flexd.c which now requires 2 additional fields in
+/etc/ax25/flexd.conf - MyGate and MyRange. Inside flexd.conf, MyGate
+is your neighbor FlexNet gateway without ssid, and MyRange would be
+the full ssid range of the FlexNet gateway you poll. This will add your
+FlexNet gateway into your local desti table complete with SSID range and
+give it a ttl of 0 since there's no true ttl polling going on... but there
+is a catch to this: you MUST add each ssid of the remote FlexNet system
+into uronode.routes as a direct link or else connect requests will fail
+because the connect will try to digi off of the remote FlexNet system
+to itself. I don't know if I agree with this yet or not as a local
+FlexNet system never shows itself in it's desti table, and that's what
+K2BJG has asked me to do with URONode. As I said, for now this is all
+a kluge but it does appear to work if instructions are followed
+verbatim.
+
+Examples:
+MyGate N1URO
+MyRange 1-11
+
+Made a change in the Makefile so that the axdigi module does NOT copy over
+by default. Now you MUST do this manually and add it to your scripts. Not
+everyone would wish to use this so why force more junk in a directory? :)
+
+--------------------------------------------------------------------------
+
+See CHANGES.2 for more notes in regards to changes.
diff --git a/CHANGES.2 b/CHANGES.2
new file mode 100644
index 0000000..1e742f3
--- /dev/null
+++ b/CHANGES.2
@@ -0,0 +1,637 @@
+
+28/11/2008 v1.0.8
+*notes lost, sorry.
+
+27/05/2009 v1.0.9
+**production copy stolen. See LICENSE for who did this and my response.
+
+11/05/2013 v2.0
+Clean up of some code... I had a copy of 1.0.8 from 2008 I recovered. I
+did
+have a version 1.0.9 in production but can't seem to locate it for some
+reason so starting from memory using 1.0.8. Thanks to Brett WA7V for
+supplying me with some teaser code :-)
+
+Updated version! We're on 2.0... finally! (yea, big news right? Maybe
+not!)
+
+Moved the "Who" commmand to the list of basic internal node commands.
+I can't recall why on earth I had it defined with MOTD. Perhaps it may
+come to me later but for now I can't recall. I may have to move it
+somewhere else, but I believe it has to do something with logging
+features or something along those lines. For now, you need to define
+MOTD as a compile selective to have the <Who (call)> defined.
+
+Fixed the sysop shell warning, this needed to be a tad more specific
+in my point of view... then again who am I? Also cleaned up the return
+prompt as it could be confusing if the incoming connection was done via
+NetRom. I removed the default FlexNet Identifier out. Now it just says:
+"Welcome back.".
+
+In regards to the "Who" command; I see what was going on here and where
+I left off with it! Logging and the "Who" command pretty much go hand in
+hand - so they're combined. The initial design of FlexNode was to have a
+MOTD based off of the logging of when the user last was on, otherwise if
+they did not exist, push the "new user" screen to them. The down and
+dirty quick fix is to simply remove it from netrom connections into the
+system! Who cares if you get a MOTD on a flex/ax25 or a telnet connect
+into the system!
+
+With the above said, I changed the sequence of "configure" to ask if the
+sysop/admin wishes to log user connects into the system. In the future I
+will either move this to be included with protocols or I may simply hard
+code it in as a defaulted option, and move the "Who" command as being
+defined into TCP/IP functions. For now, it's hard coded in as a selected
+option but will NOT display for NetRom connects.
+
+While I was at it, I changed some of the routines in the configure script.
+Nothing major but did improve upon a few things. While doing this, and
+running "make upgrade" I noticed that flexd.conf was being overwritten!
+OUCH! I'm surprised this went on for as long as it did. I *think* I did
+this to force people to add the new lines in flexd.conf that K2BJG/SK had
+asked me to do.
+
+Created a man page for flexd.conf(5)! I'm surprised no one asked me why this
+was missing! It explains further how to create the file. Keep in mind, this
+also works on Xnet as well as Flexnet. If this doesn't help you figure out
+how to create this file or edit the sample one... I don't honestly know what
+to tell you. In doing such, it also forced me to change the generated
+Makefile so that "install upgrade" and "install man" installs it.
+
+Changed the licensing! This is (I'll admit) very personal and _must_
+remain as is! I could fill a TB hard disk with reasons and debates
+as to why it's no longer GPL code. Please insure you are in an area
+where you can use this code. Thank you.
+
+Fixed an ANSI bug I had in the "Users" command which was driving me nuts!
+On NetRom, it would change the prompt to magenta which it shouldn't. What
+I did as a fix was to force a removal of ANSI on the prompt for NetRom
+based connects... simple enough. There may be other ANSIs for me to fix
+and I'll cross those bridges when I get to them. Found another in gateway.c
+and fixed the netrom ANSI to properly reflect that once a connection was
+made, it was "systems GO" (green) without changing the Node's ID string.
+
+Created a COLORS file which somewhat explains the hows/whys of not only
+how I came up with a schema, but when it should and should NOT be used.
+It may also be used as a quick reference guide for the local sysop. It's
+a nice little cheat sheet one may print and keep near their keyboard if
+they want.
+
+Added text to both the colors.hlp and help.hlp file for a users better
+understanding of the color schema and how to gain colors to their terminal
+if they so choose to have it. See my wishlist below for more information on
+where I wish to go with this.
+
+Added an item to the Wish List located further below in this file. With so
+many spend-thrifty hams, do I really need to go through the code and match
+it with the most up-to-date version(s) of GCC for compiling? I originally
+developed the code using GCC version 2.95, now I'm compiling it on version
+4.2.4 and it's not showing any errors during compile. If you have a specific
+version of GCC you're using, please submit that and proper hardware for me
+to run it on and I'll be more than happy to march forward :-)
+
+Changed the inactivity timeout message so that it does NOT show
+the FlexNet node call and gives a more specific message as to why the user
+was disconnected. This was a call I originally edited and have now cleaned
+up in node.c. There may be more of such messages. I can only test so much
+and for so long :)
+
+Made some more ANSI cleanups - in regards to Status and Users commands. I
+had them as magenta and they should only be bright white as they don't
+fit into any real category except for local system informations. For these
+I had to make routine changes as well as ANSI changes in user.c and in
+command.c. Also fixed the ANSI for version in NetRom. It currently had none.
+This was done in command.c. Also cleaned up Links and Routes ANSI in command.c
+and other places where needed. Originally I had the Routes as yellow which
+even though it points the ax25-interface that NetRom is encapsulated under,
+it's really more for NetRom "route"-ing... so changed it to cyan to keep with
+the schema.
+
+Found a disaster in ANSI routines for the Links command and the variant
+switches along with it! The ANSI ran to the table which I did not want
+to have happen and I believe I was very diligent in cleaning this up
+in ver 1.0.8 or 1.0.9. In any event, I recall doing this and now I have
+repeated my work... thus taken time away from more important tasks
+*sigh*.
+
+These were worked in router.c. I also cleaned up other places where ANSI
+ran over other strings that it shouldn't, and where it may have engaged
+prior to where it should. Such instances are when it would highlight over
+the Node-ID string (ex: MYNODE:mycall-5}). This really made my skin crawl
+and I *know* I fixed this before... who knows perhaps I made a cleaner
+routine than I had.
+
+I recall doing a LOT of code clean-up, and it appears I need to revisit this
+again. When I'm done, hopefully I can get rid of a few hundred lines of code
+that's simply commented out for testing purposes only. The sizes of your
+binaries should not be affected by this and I believe I've been diligent
+to clean up the configure script to somewhat automate this process for you.
+This task will be excessively time consuming! If anything it'd be an excuse
+for a maintenance release!
+
+Fixed a minor routine in ipc.c in regards to the Msg command. I deliberately
+did NOT add ANSI to this because in a way the Msg command I feel is a tad
+intrusive such as with an instant message, however I did clean up how an
+incoming message was handled to the recipient. It now (in my opinion)
+shows a cleaner screen.
+
+I found Craig Small's old axdigi code and made an elf compile. In layman's
+terms, it's a static binary and should run as-is for you. This binary
+claims to be fully automagic in regards to crossport digipeating unless you
+make changes to your interfaces in which you should restart it. This binary
+also should NOT require /etc/ax25/axdigi.conf anymore. I have the other
+binary so if you think you need it, let me know.
+
+Added an install for axdigi in Makefile.in under "install bin". Previously
+this file was not included, now it is. I may write a shell script to launch
+the daemons for you... keep an eye on this file for further info!
+
+26/05/2013 v2.1
+
+Fixed a bug in gateway.c where the finger "stop" ansi was white instead
+of red (for stop). This was one I missed not having proper routing yet
+to fully test. Thanks Brett WA7V for the link!!
+
+Made another change in gateway.c in regards to the handling of the
+flexnet destinations listing when using Flex/AX25 ONLY. There is a
+reason for this (believe it or not) and that's in the shell and netrom
+interfaces they both begin the destinations list with the string
+"Flexnet Destinations:". This may cause neighbor URONode/AWZNode/etc
+systems using flexd to improperly parse flexnet destinations from each
+other. At the moment, I don't have the facilities to properly test this
+but am hoping to work something out.
+
+Thanks to Bob K2JJT, I added an include for socket.h in ipc.c. While I
+never saw any errors here, I don't believe I've ever tested or compiled
+on a Slackware system... Bob uses Slack. K2JJT reported adding this to
+ipc.c helped him fix issues with his compile as it was griping about
+AF_NETROM. Adding it here made no difference so since it helps Slackware
+I'm all for being multi-distro compatable as much as humanly possible.
+
+In reviewing 2.0 changes, it had me look more into the shell function
+for sysops. I made a change that more defines which shell you may be
+in when you do a 'w' or a 'who' in a linux shell via the node. This
+was changed in system.c
+
+Made a patch to node.c where if called from a shell, it would coredump.
+Now, if it's called from a shell it simply exits back to the shell
+prompt. I believe the same is in other "node" variants to which
+the documentation directs the local sysop not to call the node from
+a prompt, however KI6ZHD felt this was an issue. Being harmless in
+nature to the function of my design I felt it wasn't harmful to add
+it in. This patch was provided by David Ranch KI6ZHD. Thanks to him
+for providing this, and eliminating any accidental core files on your
+hard drives, and to Steven, K6SPI for coding the patch.
+
+Thanks to David KI6ZHD for motivating me to do something I wanted to do
+but put it way on the back burner, and to Barry K2MF for his elite C
+skills. MHeard now will only print up to the 20 most recent heards. With
+the initial routine, it would just dump either the global list heard
+or if the user selected a specific interface the entire list for that
+interface. At first, it worked fine for telnet and/or ax25/flex
+connections but in NetRom it was double spacing. This was fixed by me. I
+chose 20 to leave room for system headers and prompt returns. In a
+standard 80x25 terminal screen, with a full listing, this should fill
+the entire screen without a need for the end user to scroll up and
+should help keep some traffic down on a busy network.
+
+Made a change in gateway.c to eliminate the "trying state" message only
+in NetRom when trying to connect to a remote NetRom node. This should
+keep the node more in compliance with Software2000 specifications.
+
+There was chatter within the BPQ32 user group on Yahoo that URONode was
+not releasing any keep-alive timers. Please, this is NOT the duty of
+a node Front End to control what the native protocol stack is designed
+to do. This is totally sysop configurable. To flag this I strongly
+suggest the following be added to your scripts:
+echo "600000" > /proc/sys/net/ax25/ax0/idle_timeout
+echo "600000" > /proc/sys/net/ax25/ax1/idle_timeout
+echo "600000" > /proc/sys/net/ax25/ax2/idle_timeout
+and so on... one line for each ax25 interface. This will break the
+keep-alive virtual circuit Netrom AND IP will use for transport, and
+thus break your IP as well. If you're running IP through an ax25
+interface I suggest you leave this defaulted to 0 (disabled).
+
+Rewrote the auto-find routine in gateway.c in do_connect so that first
+order of preference for connects searches the destis table from flexd
+BEFORE checking the netrom nodes and mheard tables, THEN it will search
+for the destination in the netrom nodes if not found in the destis
+table and prior to searching the mheard list. If you don't use flexnet,
+then this shouldn't be an issue for you. As of this time, I'm unsure
+if this would create any bugs if you don't define FlexNet during
+the configure procedure. If it does, please file a report on the
+online forum at https://www.n1uro.net/forum for me!
+
+Made some changes in util.c and gateway.c in regards to duplicate ax25
+route connection attempts. If you attempt to connect twice through the
+same path, same call, etc, to clarify the error handling. This was
+something I worked with K2MF on in regards to MFNOS. This does not mean
+you can't make a connect on the same interface you came in on, you will
+get a loop warning but the connect will attempt. If you connect from
+the node, and try to connect to <callsign>, loop back into the node,
+and try to connect to the same <callsign> again, you will NOT be allowed
+to connect. URONode will tell you that a duplicate connection is not
+allowed.
+
+Cleaned up the do_routes routine in command.c. Shortened "Quality" to
+"Qual" and renamed "Destinations" to "Nodes". After all, netrom doesn't
+really use "Destinations", that's more a flexnet thing. Still more
+cleanup to do in there *sigh*.
+
+While I was at the do_routes, I noticed missing ansi in do_routes and
+do_nodes. This has been fixed (and was previously in 1.0.10). I also
+cleaned up the ansi routine in do_destinations in router.c to match
+that of the netrom counterpart routines in command.c. Again, this was
+done in 1.0.10 *double sigh*.
+
+Rather than include an i686 elf of Craig Small's axdigi cross-port
+digipeater which probably would NOT work on a Raspberry PI, I added
+it into the Makefile by default. I also added an additional routine
+in the configure script to check to insure that this file is made.
+
+I also had to update axdigi.c so that it wouldn't error on the newer
+(as if I run newer ha!) gcc. This was done for strcpy so that it
+wouldn't produce errors as it does. I suspect in the "OLD" days of
+linux/gcc it may have been OK as I consider Craig to be one of the
+"village elders" of the packet system on linux.
+
+Added a man page for axdigi. READ THIS VERY CAREFULLY!! To digi through
+linux you *must* know some specific information and you might have to
+educate your users on how exactly to cross-port digi through you if
+they intend to do such. It's not something normally visible to them!
+I may add a node-help file on digi...but for now please study the man
+page on how. It works and works very slick as I've been testing it for
+a couple of months. Mheard also will learn digi paths and use them to
+connect to digipeated nodes if need be.
+
+Cleaned up do_nodes in command.c. Shortened Quality to Qual, and the
+equivilant of Obs. This will use less chars per line when doing a
+node <node> or node * . I've been wanting to do this but saved
+it for one of those rainy day things. Guess today was that rainy day?
+
+Cleaned up more code and hope to have it finished before 2.1's final
+release. So far I'm doing flexd.c at this point. FYI; code cleanup will
+be a 2-fold process. First; I'll be formatting each file so it's at a
+level of consistency. Second, things I have commented out for testing
+that aren't needed may be permanently removed. I may leave a few things
+in in case someone desires to say add a 'Welcome." message to netrom
+(which is NOT Software2000 compliant!).
+
+Speaking of which, I see I introduced a bug when ANSI is defined for
+a specific user which violates Software2000 specs. I believe I did this
+as a fail-safe in the prompt routine however now I see it's not needed
+with all the other ANSI cleanups I've done. This change (deletion)
+was done in node.c where I forced a shutoff of ANSI upon NetRom connects
+only, as NetRom does not display the MOTD.
+
+I rewrote a bit of the reconnect string. The "reconnect" in uronode.conf
+should be set to OFF. All connections with the exception of NetRom WILL
+reconnect. NetRom defaults to off, however with the {S|D} flags you may
+manually request you stay connected. Eventually I will remove this flag
+in the file so it will become moot. Please change it now to OFF! This
+was done in gateway.c. Previously, these flags were moot in NetRom
+connects. With the default to OFF, this keeps the NetRom in URONode
+Software2000 compliant. A NetRom disconnect should *never* send any
+text back whether it's a user or robot/script. Now a user can request
+staying connected to URONode from a incoming NetRom connection. For
+clarity sake, this only affects the user IF they connect INTO URONode
+via NetRom. The "S" flag works for ax25/Flex/NetRom outbound connects.
+A user connecting INTO URONode via ax25/Flex/IP will still automatically
+be reconnected after an outbound connect.
+
+N1UAN reports make install fails to install the config files. He's
+correct. Changed Makefile.in so that "make install" also includes
+make installconf which run by itself will install just the config
+files for /etc/ax25.
+
+I'm also working on changing the configure script to have some
+"eye candy". This will be a continuing work in progress. You'll see it
+as it comes. You will need the package "whiptail" in order to see this
+new configuration routine. I don't know if this is standard amongst
+ALL distributions, however I do know it comes default in debian and
+debian based systems. If this *is* too much of an issue, I'll revert
+back to the old method.
+
+Almost forgot about an ANSI bug in extcmd.c where if you created an
+external command in the node and the user was in via NetRom, when the
+node issued "Welcome back." the ansi did NOT clear the color. I found
+this in ver 2.0 and thought I fixed it, apparently not (age catching
+up to me?) In any event, this is now fixed and working properly again.
+Since most people don't use the +512 Color flags I'm sure it was missed.
+
+Found a non-critical bug in cmdparse.s in regards to running external
+commands - where it would automatically input a line feed before it
+executed the command. This was the only routine which did this. A
+routine like this really got under my skin and I was determined to find
+and fix this finally... this was a routine I never changed, and that
+was halted today (28 July 2013). Instead of totally removing this line
+of code, I changed it to now display "Executing command... " and where
+ANSI is defined, it is, naturally, green.
+
+Found a non-critical bug in the Info command where it would show as
+the first string to the user: "Help command for help" then it would push
+the uronode.info file. This is very wrong. While the Info command does
+use the routine of do_help in command.c, Info is an independent internal
+command and this should not have occurred. This is now fixed with ANSI
+if permissions display ANSI.
+
+Updated the outdated INSTALL text document. It had some now misleading
+pieces of information in it as some paths and make options have been
+changed. Since no one has said anything to this, I'll assume no one
+RTFM? (not surprised! email me and say in the subject line: surprise!
+if you do!)
+
+Went through the example config files and heavily commented them so for
+new installs, it explains each line more specifically in hopes less
+misconfigured systems will be created. I also found some typos as to
+man page references - fixed. Also updated some of the help files in
+regards to the new changes in relation to the "stay" sub command when
+connecting out from URONode.
+
+Note: in node.c I modified the pre-provided segfault patch to now
+push text to the local console instructing the local sysop or user
+what/how to properly execute the node. This will (I hope) force
+some RTFM to occur. Syslog logging was also added in the event this
+occurs. Actually, after thinking about this, I figured I'd dummy it up
+a bit and have it launch a login anyway. This depends that the local
+administrator/sysop -properly configures their box- and does the
+following:
+1 - add a line in /etc/services to point tcp/3694 to uronode
+2 - add uronode as a service in inetd or xinetd
+3 - insure you have a local telnet client on the box
+4 - enjoy!
+You will be reminded about this during the login, and syslog will
+reflect a local console login as well.I strongly urge you not to open
+2 shells and tail your syslog in one while you try to run URONode from
+the console. Wink
+
+Cleaned up a minor routine in do_nodes which lays in command.c where
+under an incoming NetRom connect, a user who did "Nodes" received
+an extra line feed if the columns were all equal at 4 per row. This
+was a bit under my skin... fixed/changed. While I was at it, I changed
+the output string when doing "Nodes *" from 'Nodes:' to "Detailed
+nodes listing:' which actually makes more sense since it is a detailed
+list.
+
+Fixed a minor bug in the way the prompts were handled under certain
+telnet clients. This was reported also by Marius Petrescu yo2loj. Under
+telnet, I added a carriage return (/r) along with the line feed (/n).
+Thank you Marius for the report.
+
+Slightly rewrote the way meminfo() was being handled. While I may have
+created a bug in 2.4 and lower kernels, this now should work in 2.6 and
+higher kernels. I guess the phrase "if it's not broke don't fix it"
+doesn't apply anymore?
+
+FINALLY - split the CHANGES file into a new page!! This makes it easier
+for me to input the change notes instead of having to scroll down for 30
+seconds Smile Call me lazy but don't call me late for supper! <G>
+
+04/09/2013 v2.2
+
+Made multiple .c file edits to reflect the new libax25-devel .h files.
+Currently these were pointing to the older kernel_*.h files and on newer
+linux systems was preventing compile. Now URONode should work fine.
+
+Added Marius Petrescu to the URONode team! With his c version of ripv2d,
+Marius will (and already has) make a huge impact on the future of
+URONode! Welcome Marius to the team! Made a reflection of this in the
+configure script.
+
+Marius brought to my attention the issue in the log timer routine where
+it was forcing 32-bit. He supplied code to fix this in both system.c and
+flexd.c.
+
+While in discussions, Marius brought it to my attention that Ubuntu (and
+this includes Mint and any other Ubuntu backed distributions) where they
+run as he calls it a "fortified libc6" which segfaults on every (what it
+thinks is suspicious) buffer accesseD to prevent overflows however this
+libc6 itself causes buffer overflowing. Why on earth did the Ubuntu team
+ever do this?? Anyway, we're investigating how we're going to handle
+this issue. I personally have verified URONode to compile and work on
+the new kernel 3.x series on Debian and Fedora.
+
+In "fixing" the prompt bug earlier reported by Marius, I made an error in
+the non-ANSI telnet prompt where the (/r) was also chopping off the first
+letter of a callsign! OOPS! This was reported by Ted K1YON. Fixed.
+
+** Key news of this release: ROSE is a LOT more user friendly, AND it also
+has the ability to display color screens to the end user. This now means
+that URONode is an 8-prompt system! 4 main prompts, and 4 color prompts.
+The prompt system is designed to show the end user what protocol/method
+they used to connect into URONode with. Also proper SSIDs are displayed
+to match that of how the end user connected. I did this because seeing
+other nodes, they don't and when (as a user) connect into, for example,
+a NetRom node who's ssid is -12 and the node displays something
+-=totally=- different, I often wonder if I connected to the proper node.
+
+The new prompt schema is:
+telnet : user@<sysop>.ampr.org:/uronode$
+netrom : <none> - this keeps in spec with Software2000
+flex/ax25: =>
+rose : -=>
+
+Each matches with its own colors as well if you run the ansi flag. The
+goodbye message for rose is also different than it is for flex/ax25 and
+telnet links. The new RoseID flag is used as a personalized message to
+the remote user to say a nice goodbye, and to remind them of your Rose
+information. The (V)ersion command also has a rose column added to show
+the remote user your rose information. An example of this is included
+in the uronode.conf.5 man page.
+
+With such, a new uronode.conf file string called RoseID has been created.
+Details are in the file. You must keep the single quotes ' ' around the
+string for it to display properly. You have been warned. Also, I've added
+a default ExtCmd called ROSe so those who connect remotely can get rose
+addresses for now. I'm sure I'll be changing this in the future.
+
+Also, I decided to eliminate the permissions flag for use of hidden interfaces.
+Reason being is if a sysop flags an interface to be hidden, they did so for a
+specific reason. With that, I moved the ANSI flag from 512 in it's place to
+64. This was also changed in the man page uronode.perms.5.
+
+In regards to PBBS forwarding, I -=URGE=- you to read BBS.txt. Since
+there's no need for me to rewrite it, please heed my warning here. This
+is not something critical, just informational to help you improve your
+link with URONode systems.
+
+Fixed a cosmetic bug in regards to windows->linux emulation where when
+logging in, sentences were not getting properly wrapped. This was done
+in node.c. Other emulations such as PuTTY do not give you in windows
+full linux-type emulation. Higher profile programs such as SecureCRT
+will. For a free/shareware program I suggest MobiXterm. This also
+gives you a raw Xserver emulated screen. Of course, there are no issues
+if you use a standard linux console.
+
+Added a .pid file to flexd, code supplied by Jaroslav, OK2JRQ and other
+patches such as installer edits, etc. The only patches he supplied that I
+have yet to add is the install location patch, and one he feels is good
+for non-interactive. Source installs need to be interactive, if not you
+would not be compliling - just my honest opinion. I can see in the case
+of a possible distro package this may not be desired. The distros for now
+can hash that out on their own.
+
+Many more cosmetic bugs fixed/changed. Moreso in ROSE but I did find a
+few others in there which needed my attention. I have noticed windows terminal
+based programs such as PuTTY have an issue determining \n based line feeds
+vs \r carriage returns in C code. This mainly seems to affect the various
+8 prompts. It seems if I put both in the code, Windows is happy but *nx
+may issue an added line-feed. I had thought I cleaned these all up but
+I introduced a couple old ones and some new ones with the ROSE work.
+
+01/10/2014 -2.2 released!
+
+02/10/2014 - 2.2.1
+
+Improperly packaged an old flexd.c! This one should compile. This is NOT
+the one I want, I've been fighting with flexd for a while now.
+
+uronode.conf may not update. If it does, you will need to redo yours from
+scratch. Look at the one in the etc/ directory in the source and add the
+line for RoseId. This is required. Thanks for the above reports from
+VE1JOT and SP2LOB.
+
+Removed the need to have quotes around the RoseId string in URONode.conf. I
+found it unneccessary to have to do this. Keep the string togther ex:
+callsign-ssid at 1000,200000 now is fine. I also find this cleaner.
+
+12/10/2014 - v5.1
+URONode release ver 51 is out!.. um.. I mean its main developer *sigh*
+
+21/12/2014 - v2.3
+
+Added Bob Tenty ve3tok to the development team and created a subversion
+server. Please welcome Bob to the team!
+
+Bob Tenty ve3tok reports when NOT using the official ax25 packages and
+on Ubuntu, the node when compiled natively may buffer overflow. He made
+changes to buffers in gateway.c, router.c, and flexd.c which prevent this.
+I have incorporated these changes and there's no ill effect on non Ubuntu
+distros.
+
+Fixed a bug I introduced into the ROSE ansi prompt where it wasn't
+executing a proper \n because I inadvertantly removed it. Restored.
+
+Fixed a warning in the axdigi code. Now that I'm on a more modern system
+I can fix these things as now I can see them better. This was also brought
+to my attention by Tomasz SP2L... thanks Tomasz!
+
+Figured out a way to compile and have it NOT segfault under Ubuntu. While
+I'll admit for the time being it's somewhat of a hack, but it *does* work
+for Ubuntu. There are warnings on Ubuntu compiles that don't exist on other
+platforms - interesting to say the least - but I think I see a relation
+between the warnings and the pervious Makefile. The prior statement is being
+left in as a comment deliberately as I hope to try and revert back to
+the previous method.
+
+**IMPORTANT: Per distro downstreams, I've been asked to change the paths
+of the URONode installs. Now your uronode and binaries will be placed in
+/usr/local/sbin instead of /usr/sbin. Config files will be in
+/usr/local/etc/ax25 instead of /usr/ax25/. Node files will now be in
+/usr/local/var/ax25/node or flexd instead of /var/ax25/node or flexd.
+If you're a thrifty ham such as myself, you'll already have symlinks created
+for easier management, so that /etc/ax25 is symlinked into /usr/local/etc/ax25
+and so forth. Local files I can think of that would need editing if you use
+my standard config:
+/usr/local/bin/ax25
+/etc/xinetd.d/uronode
+/etc/xinetd.d/telnet (?)
+/etc/ax25/ax25d.conf
+
+Added a compile flag to keep Ubuntu happy. This and other routines were at the
+suggestions of YO2LOJ and VE3TOK.
+
+SYSop command does NOT spawn a shell anymore. This is due to the changes
+with the UNIX98 file system. I'm debating on whether or not I wish to
+continue to keep this or possibly eliminate this (for possible security
+reasons). I see both PROs and CONs with it. Note: this ONLY affects those
+systems which force the use of /dev/ptmx in which one needs to use SOCAT
+to create static /dev/tty*# and /dev/pty*# pipes. This only affects the
+Kernel 3-series in which the older /dev/pty# system is no longer used and
+a master ptyx is used.
+
+I did notice UBUNTU made changes to their libraries last year (2013) in
+which URONode compiled but failed to execute any direct disk read/write
+routines. In any event, they fixed this bug late fall 2014 (at least in
+12.0.4LTS). One of the nice things about Ubuntu doing this is that you
+can add a line in your grub configuration to have the kernel create a
+number of satic pseudo terminals upon boot. Debian, however, breaks this
+ruleset. I contacted my downstream and he hasn't responded. This would
+help a sysop gain a shell... however also creates a possible backdoor.
+
+Edited gateway.c so that the callsign-ssid is force altered on outbound
+ax25 connect requests regardless of how the inbound connect was initiated.
+VE1JOT reports that when a user telnets in, and gateway ax25 connects out,
+the callsign-0 is kept. This should be altered to a -15. This was always
+true when inbound connects were ax25 and also outbound connects the same.
+VE1JOT reports this is troublesome, and in some cases causing DM frames
+to occur. While I tested this and found this not to be true on my own
+system, I did make a code adjustment to handle this.
+
+Fixed a bug in config.h which may cause flexd not to find the proper
+config lines. When I changed file paths I missed a couple. Now the system as
+a whole should be consistant in regards to config files.
+
+Removed the need for MyGate and MyRange in flexd.conf! This was added by
+the request of K2BJG/SK so that the flexgate itself would be listed. Actually
+it is in the LINKS file. Unfortunately when trying to connect to a listed
+flexgate, it would try to digi via itself! Not good. While I was at it, I
+also increased the buffer from 512 to 1024. This may help with those gates
+that insist on making L A R G E MOTDs.
+
+
+14/02/2015 - v2.3.1
+Happy Valentine's day to the one we all love: Our Compilers!
+This is a critical security patch! I URGE you *all* to recompile.
+If anything, hopefully you've all patched your systems against GHOST.
+For those who wish to test their system I have a tool on my ftp site
+which can do this for you.
+
+Through Paul G4APL, Andy G0HXT reported a condition on Ubuntu-based
+systems in which a user may enter a malformed NetRom connect string
+into URONode and the node will buffer overflow. I fixed this in
+gateway.c limiting the string for searching connects on the first parameter.
+Also changed the error output to the user so that they may know the error
+may be their own.
+
+Made edits to all the man pages and the INSTALL file as suggested by Tomasz
+SP2L. I also grepped for certain strings in other files and made a change
+to the README file as well.
+
+Changed the version in node.h to reflect this security patch.
+
+
+
+Known NON-Critical Bugs:
+Status memory/swap reporting fix
+
+Wish-list:
+Who file sorter
+pactor - requested by sv1uy
+-----------
+
+Original Development Information (aka Disclaimer):
+URONode was developed on an IBM eSeries 330 eServer with dual 1.2GHz CPUs
+The OS is Debian Linux 4 using kernel 2.4.27, libax25 v0.0.11,
+ax25-tools v0.0.8 and ax25-apps v0.0.6. This software comes with
+absolutely NO guarantees so crash n burn at your own risk. We all may
+be surprised and find out that it actually DOES something useful!
+URONode may not run 100% depending on environmental conditions specific
+to your system.
+
+URONode is GLPv2 code, and tested by it's main author on the following
+platforms: Raspberry Pi ver. B, Debian 7.7 on a Core-i3, Ubuntu 12.0.4LTS
+on a Core-i3, Fedora ver. 19
+
+------------
+
+Comments/suggestions? email: n1uro at n1uro.ampr.org
+Gripes??? cat gripes > /dev/null Smile just kidding!
+
+This version will get you going for now. I'll post any changes to:
+ftp://ftp.n1uro.net/packet
+
+Join our support mail list graciously donated by TAPR!
+http://www.tapr.org/mailman/listinfo/uronode
+
+73 de Brian N1URO
diff --git a/COLORS b/COLORS
new file mode 100644
index 0000000..ba14b9b
--- /dev/null
+++ b/COLORS
@@ -0,0 +1,25 @@
+Incase you're wondering about the method behind the madness in my color
+schema it's very simple. Picture yourself with 3 vehicles to drive on
+different roads with; a scooter, a compact car, and an SUV. Each vehicle
+(or protocol) has it's own color. Each vehicle follows the same rules
+of the road (green for go, red for stop, blinking red for alarms). When
+you command URONode to go somewhere, you get green. When you return and
+the process has completed it's red. Ax25/Flex is Yellow, NetRom is Cyan,
+and IP/System messages are Magenta.
+
+It's VERY IMPORTANT that you program any automated scripts that connect
+to URONode that they do NOT use colors! Simply remove 512 from their
+permissions. If you do NOT do this, the robot script may attempt to
+decipher ANSI code and it may cause it to hang. YOU HAVE BEEN WARNED!
+
+
+Here's the schema:
+Connects display in green as in "gateway go"
+Reconnects display in red as in "gateway stop"
+IP based information is in magenta
+Netrom Nodes (full list) in bold cyan
+FlexNet destis (full list) in yellow
+System info in bright white
+Aborts and timeouts blink bright red
+Logouts in low cyan
+
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..a43ea21
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/FAQ b/FAQ
new file mode 100644
index 0000000..3376db7
--- /dev/null
+++ b/FAQ
@@ -0,0 +1,35 @@
+Welcome to the official FAQ file for URONode.
+
+The purpose of this file is to help explain better about URONode and what
+the various features were designed for. Since this file will be maintained
+via URONode Sysop reports, I'll consider this file a constant 'work in
+progress' type file.
+
+When using URONode or really any other linux node flavor, keep in mind
+that the actual node program itself is only a front-end for the users
+to do various functions your linux server may have to provide. Node really
+doesn't do any sort of control features whatsoever, it merely acts as a
+sort of proxy to your linux daemons. Those features are toggled on/off at
+compile time by the operator of the node. I've taken time to rework the
+configure script to give the node ops more flexibility in what they wish
+to service their end users with. Nothing about URONode was ever designed
+as a 'replacement' for any existing services such as email and convers.
+I'm not even going to suggest one chooses to run URONode as a replacement
+for LinuxNode by Tomi, AWZNode, or even FlexNode. The goals I set when
+starting this project were moreso to custom fit my unique setup and its
+something I can share with the amateur community at the same time.
+
+URONode is NOT:
+A replacement for *NOS
+A replacement for Email
+A replacement for PBBS
+A replacement for convers
+A FlexNet router
+
+URONode IS:
+A user front-end with some additional features to help compliment those
+existing features an end user may need but for whatever reason doesn't
+have access to at the moment, while allowing links to various entities
+such as AX.25 links, Net/Rom routing, FlexNet destinations, general and
+amprnet TCP/IP services.
+
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..3bf51a6
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,79 @@
+1. COMPILING and INSTALLING
+
+To compile and run URONode you will need to have libax25-0.0.4 or newer
+installed on your system. It should work on any platform where libax25 can
+be compiled and installed.
+Note however that it will NOT work with 2.0.x kernels.
+
+To install you should first run:
+
+ ./configure
+
+and answer to the questions it makes.
+
+** IF ** this is an ** UPGRADE **:
+and if you said no to configure running a "make", just type:
+make; make upgrade
+This will *not* overwrite your config files, and will freshen up
+your binaries only. If you told the configure script to make, then
+all you need to type to upgrade is: make upgrade.
+
+** IF ** this is a new install:
+
+If all files needed are present everything should work. Next:
+
+ make (if you said "no" to the configure script launching it for you)
+ make install
+ make installhelp
+
+Optionally you may want to run also:
+
+ make installconf
+
+to install the default configuration files.
+Note however this copy example files in /usr/local/etc/ax25 but with ".ex".
+You should rename it by removing ".ex" at the end of filenames.
+
+After that you need to edit the configuration files to suit your system.
+The manual pages for uronode.conf(5) and uronode.perms(5) should give
+an idea of what to put into these files. The AX25-HOWTO is a must read also.
+
+2. RUNNING
+
+URONode is intended to be called from ax25d or inetd. It doesn't need
+any command line arguments. See the uronode(8) manual page.
+
+To run URONode from ax25d, /usr/local/etc/ax25/ax25d.conf should have something
+like this in it:
+
+ # AX25 Port ax0
+ # Belows SSID can not be the same as your netrom node SSID!
+ [N1URO-2 VIA ax0]
+ default * * * * * * - root /usr/local/sbin/uronode uronode
+
+ # NETROM Port
+ <nr0>
+ default * * * * * * - root /usr/local/sbin/uronode uronode
+
+add uronode as a service in /etc/services:
+uronode 3694/tcp # Node/URONode packet
+
+if you use inetd -
+/etc/inetd.conf could have something like this in it:
+
+# Listen at telnet port -> URONode
+uronode stream tcp nowait nobody /usr/local/sbin/uronode uronode
+
+if you use xinetd -
+/etc/xinetd.d/uronode should look like this:
+
+service uronode
+{
+ disable = no
+ socket_type = stream
+ protocol = tcp
+ user = nobody
+ server = /usr/local/sbin/uronode
+ wait = no
+ instances = 20
+}
diff --git a/Makefile.in b/Makefile.in
new file mode 100644
index 0000000..750e546
--- /dev/null
+++ b/Makefile.in
@@ -0,0 +1,100 @@
+all: nodeusers uronode axdigi @FLEXNET@
+
+CC = gcc
+LD = gcc
+# CFLAGS = -O2 -g -s -Wstrict-prototypes
+CFLAGS = -O2 -g -Wno-unused-result -Wstrict-prototypes
+LDFLAGS =
+LIBS = -lax25 -lax25io
+
+include Makefile.include
+
+COMMON_SRC = user.c util.c
+NODE_SRC = node.c cmdparse.c config.c command.c mheard.c axcalluser.c \
+ gateway.c extcmd.c procinfo.c router.c system.c sysinfo.c ipc.c
+NODEUSERS_SRC = nodeusers.c
+FLEXD_SRC = flexd.c procinfo.c
+DIGI_SRC = axdigi.c
+
+COMMON_OBJS = $(COMMON_SRC:.c=.o)
+NODE_OBJS = $(NODE_SRC:.c=.o)
+NODEUSERS_OBJS = $(NODEUSERS_SRC:.c=.o)
+FLEXD_OBJS = $(FLEXD_SRC:.c=.o)
+DIGI_OBJS = $(DIGI_SRC:.c=.o)
+.c.o:
+ $(CC) $(CFLAGS) -c $<
+
+install: installbin installman installhelp installconf
+ install -m 755 -D -d $(VAR_DIR)
+ install -m 755 -D -d $(VAR_DIR)/node
+ install -m 644 -p etc/loggedin $(VAR_DIR)/node
+ install -m 644 -p etc/lastlog $(VAR_DIR)/node
+ install -m 755 -D -d $(VAR_DIR)/flex
+ install -m 644 -p etc/gateways $(VAR_DIR)/flex
+
+installbin: all
+ install -m 755 -s -p uronode $(SBIN_DIR)
+ install -m 755 -s -p nodeusers $(SBIN_DIR)
+ install -m 755 -s -p axdigi $(SBIN_DIR)
+ at IN@ install -m 755 -s -p flexd $(SBIN_DIR)
+
+installhelp:
+ install -m 755 -D -d $(VAR_DIR)
+ install -m 755 -D -d $(VAR_DIR)/node/help
+ install -m 644 -p etc/help/*.hlp $(VAR_DIR)/node/help
+
+installconf: installhelp
+ install -m 755 -D -d $(ETC_DIR)
+ install -m 600 -p etc/uronode.conf $(ETC_DIR)
+ install -m 600 -p etc/uronode.perms $(ETC_DIR)
+ install -m 600 -p etc/uronode.info $(ETC_DIR)
+ install -m 600 -p etc/uronode.motd $(ETC_DIR)
+ install -m 600 -p etc/uronode.users $(ETC_DIR)
+ install -m 600 -p etc/uronode.routes $(ETC_DIR)
+ install -m 600 -p etc/flexd.conf $(ETC_DIR)
+
+installman:
+ install -m 755 -D -d $(MAN_DIR)/man1 $(MAN_DIR)/man5 $(MAN_DIR)/man8
+ install -m 644 -p man/nodeusers.1.gz $(MAN_DIR)/man1
+ install -m 644 -p man/uronode.conf.5.gz $(MAN_DIR)/man5
+ install -m 644 -p man/uronode.perms.5.gz $(MAN_DIR)/man5
+ install -m 644 -p man/flexd.conf.5.gz $(MAN_DIR)/man5
+ install -m 644 -p man/uronode.8.gz $(MAN_DIR)/man8
+ install -m 644 -p man/axdigi.8.gz $(MAN_DIR)/man8
+
+upgrade: installman
+ install -m 755 -p uronode $(SBIN_DIR)
+ install -m 755 -p nodeusers $(SBIN_DIR)
+ install -m 755 -p flexd $(SBIN_DIR)
+ install -m 755 -p axdigi $(SBIN_DIR)
+ install -m 644 -p uronode.conf $(ETC_DIR)
+ install -m 644 -p uronode.perms $(ETC_DIR)
+
+clean:
+ rm -f *.o *~ *.bak *.orig make.debug nodeusers uronode flexd axdigi
+ rm -f etc/*~ etc/*.bak etc/*.orig
+ rm -f etc/help/*~ etc/help/*.bak etc/help/*.orig
+
+distclean: clean
+ rm -f .depend Makefile.include config.h
+ rm -f uronode nodeusers axdigi @FLEXNET@
+ rm -f Makefile make.debug
+
+depend:
+ $(CC) $(CFLAGS) -M $(COMMON_SRC) $(NODE_SRC) $(NODEUSERS_SRC) $(FLEXD_SRC) > .depend
+
+uronode: $(COMMON_OBJS) $(NODE_OBJS)
+ $(LD) $(LDFLAGS) -o uronode $(COMMON_OBJS) $(NODE_OBJS) $(LIBS) $(ZLIB)
+
+nodeusers: $(COMMON_OBJS) $(NODEUSERS_OBJS)
+ $(LD) $(LDFLAGS) -o nodeusers $(COMMON_OBJS) $(NODEUSERS_OBJS) $(LIBS) $(ZLIB)
+
+flexd: $(FLEXD_OBJS)
+ $(LD) $(LDFLAGS) -o flexd $(FLEXD_OBJS) $(LIBS) $(ZLIB)
+
+axdigi: $(DIGI_OBJS)
+ $(LD) $(LDFLAGS) -o axdigi $(DIGI_OBJS)
+
+ifeq (.depend,$(wildcard .depend))
+include .depend
+endif
diff --git a/Makefile.include.in b/Makefile.include.in
new file mode 100644
index 0000000..aca87b5
--- /dev/null
+++ b/Makefile.include.in
@@ -0,0 +1,13 @@
+# Processor architecture
+ARCH = @ARCH@
+
+# Paths
+ETC_DIR = @ETC_DIR@
+SBIN_DIR = @SBIN_DIR@
+BIN_DIR = @BIN_DIR@
+LIB_DIR = @LIB_DIR@
+MAN_DIR = @MAN_DIR@
+VAR_DIR = @VAR_DIR@
+
+# Is Zlib available?
+ZLIB = @ZLIB@
\ No newline at end of file
diff --git a/README b/README
new file mode 100644
index 0000000..974b485
--- /dev/null
+++ b/README
@@ -0,0 +1,95 @@
+Please check out the file INSTALL to compile and install URONode.
+Also please read the CHANGES.* file for all version history changes.URONode README file September 09, 2013
+
+Note: Please read the CHANGES file for detailed information
+about the changes from AWZNode to URONode and what I've
+done with it... along with current version info! - Brian N1URO
+
+Hi linuxers!
+
+First all, I thanks PE1RJA and OH2BNS for their very great job!
+
+*****************************************************************************
+The v0.5.x release is a temporary version of URONode running and compiling
+under linux 2.4.x, with glibc 6 and new ax25 and ax25io libraries. v0.0.11
+*****************************************************************************
+
+UROnode is based on AWZ|LinuxNode by Tomi Manninen OH2BNS and FlexNode
+by Roy PE1RJA. It was born initially for the aripisa.ampr.org system
+by Stefano Noferi IZ5AWZ of ARI Ham Radio Association of Pisa (ITALY).
+Users in URONode can connect all ham packet world: all AX25, NETROM, ROSE,
+FLEXNET, ITANET, TCP/IP nodes in the world are now near.
+
+Comment from Stefano:
+I have a "packet" dream: all the packet networks can interchange connections.
+My version of node software for Linux is an attempt to realize this idea
+and I hope it can help the ham radio digital world to come back one. ;)
+
+I thanks ARI association of Pisa and Alex Del Chicca IK5PWJ,
+for their trust and supports.
+
+This README file, the documentation etc. are very incomplete!
+Sorry, but my free time is very very very... very little.. :)
+
+If you decide to use URONode, send me a mail.
+
+Routing features include: (in order preferance)
+- netrom routing
+- fixed routes
+ Create and/or modify /usr/local/etc/ax25/uronode.routes, the format of
+ this file is in the example file uronode.route.ex.
+ Now fixed link nodes in this file have an alias and 3 connection
+ modes, can be queried using the Links command and can be
+ connected directly using: Connect <call>|<alias> (ie. without
+ specifying the downlink port)
+- flexnet destination lists
+ A separate daemon (flexd) queries a neighbouring flexnet node for its
+ reachable destinations, these destinations are stored on the local
+ disk and can be queried using the Dest command and can be connected
+ directly using: Connect <destination>
+ Config file: flexd.conf:
+ MyCall <call> # the callsign used during the connection
+ PollInterval <interval> # how often the destinations are downloaded
+ FlexGate <call> # the neighbouring flexnet node
+ The pollinterval is specified in seconds and the callsign after
+ flexgate must be defined in uronode.routes !!
+- mheard based routing
+ When users are using your node the mheard tables are filled with
+ callsigns, callsigns heard on ports can be connected directly with
+ the Connect <call> command, without specifying the downlink port.
+
+Other features:
+- local users of the linux machine can be granted access to the mailreader
+ and optionally to the shell. Config file: /etc/ax25/node.users
+ <call>:<password>:<username>:[mail][,shell]
+ call : the callsign of the user that is allowed to access special features
+ password : a string pasword
+ username : the (real)-username on the linux side
+ options : mail - the user has permission to access his or her mailbox
+ shell - the user has permission to access the shell
+ Users with the mail option enabled will receive messages like "New mail
+ has arrived", mostly when the stated condition is met ;-)
+- all users can send messages to a callsign associated in the kernel table
+ with a linux username ("send" command).
+- now the sysop can modified the node prompt and password prompt
+- "!" command show system statistics
+- old "SEssions" command is now "MSessions"
+- now "MHeard" command can be used without port specification
+- changed the output of several query programs (like ports/routes etc.) also
+ included more netrom specific output in these commands
+- included a lastlog, which shows the time, date and port of your previous
+ session, if this is your first connect, you are requested to read the
+ info text
+
+The official FTP Site of URONode is:
+https://sourceforge.net/projects/uronode/?source=directory
+ftp://ftp.n1uro.net/packet/
+
+The official Forums site is:
+http://www.tapr.org/mailman/listinfo/uronode
+
+URONode is also a part of Fedora 20 and higher.
+"yum install uronode" to install the .rpm package.
+
+Please check out the file INSTALL to compile and install URONode.
+Also please read the CHANGES.* file for all version history changes.
diff --git a/URONode.his b/URONode.his
new file mode 100644
index 0000000..48ca670
--- /dev/null
+++ b/URONode.his
@@ -0,0 +1,49 @@
+** Note: this file is depreciated, refer to CHANGES.*
+
+URONode was spawned off of the original linuxnode by Tomi Manninen OH2BNS
+Before URONode was FlexNode by Roy PE1RJA, and then by Stefano Noferi IZ5AWZ
+who called it AWZNode. I took over the code willingly and on my own mainly
+as a project I could do under C program coding in April 2003 after it
+appeared that AWZNode was no longer being developed.
+
+My first goal was to make it appear and act more like TheNet X1J and spent
+most of my time configuring the node to behave as such which I felt I did
+quite successfully. While doing that I thought I'd try to add in email
+features by using the old PMS system written by Alan Cox, who has a lot
+of code in the main linux kernel for it's IP stack (most of which is taken
+directly out of KA9Q nos). While I was successful in doing that, Morgan
+SM6TKY reported that the code was old and exploitable... unfortunately I had
+a period where I couldn't devote the time into getting it repaired quickly
+and URONode sat and suffered with a note explaining that certain features
+should not be used or enabled. As a quick fix, I simply commented out the
+found exploits and did some more cosmetics to the code and released a patch.
+
+Still with users wanting EMAIL as a feature to the software, this inspired me
+to pick up with the dropped axMail code and bring that more up to date. axMail
+was originally started by Heikki Hannikainen, and then mailbox routines were
+added by Marius Petrescu, however system configs were lacking. I took the
+code and added in the routines which are in there now so that new users
+are properly created within the basic linux filesystem schema, and passwords
+can be created (optional) so that a web front-end such as NeoMail can be
+used in conjunction with axMail giving users the choice of the web or RF
+packet to do their SMTP based EMAIL with. It was and always will be an optional
+add-on module for URONode, and other flavors of *node for linux.
+
+These two packages together, along with F6FBB make for one heck of a feature
+packed system a sysop can piece together on one server. Because of such,
+URONode has become very popular in the NorthEast USA and in Central East
+Florida within the EastNet FlexNet network and with the Florida MARS
+networks. With this, I've taken the look and feel of URONode to try and
+match that of a FlexNet interface.
+
+The latest version of URONode under-went many face lifts! The node not only
+auto-senses the incoming connection but delivers an interface which clones
+that of the type of system they're connecting in from. A user connecting
+in via IP will actually get a prompt that looks and acts similar to a
+Unix bash prompt with custom aliased commands!.. and to top that all off
+I've added an ansi schema to the IP interface!!
+
+URONode is used world-wide in Europe, Africa, Asia, and in North America.
+A web bbs is available at https://www.n1uro.net/forum where release notes
+for URONode are posted. If the functionality of URONode isn't enough to
+get interest in packet growing, the stability of URONode should!
diff --git a/axcalluser.c b/axcalluser.c
new file mode 100644
index 0000000..107a285
--- /dev/null
+++ b/axcalluser.c
@@ -0,0 +1,77 @@
+/* axcalluser.c - determine username corresponding to callsign */
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <errno.h>
+#include "config.h"
+#include "axcalluser.h"
+
+int axcalluserid(char *call)
+{
+ char callsign[10];
+ char username[80];
+ int id;
+ int userid = -1;
+ FILE *f = fopen(PROC_AX25_CALLS_FILE,"r");
+ if (f) { /* VE3TOK, 18Nov2014, return value usage */
+ if (fgets(username,79,f) == NULL) {
+ syslog(LOG_DEBUG, "Can't get username: %s", strerror(errno));
+ return 1;
+ }
+ while (fscanf(f," %d %9s",&id,callsign) != EOF) {
+ char *a,*b;
+ for (a=call,b=callsign;
+ *a && *b && toupper(*a)==toupper(*b) && *b!='-';
+ a++,b++) ;
+ if (!isalnum(*a) && !isalnum(*b)) {
+ userid = id;
+ }
+ }
+
+ }
+ fclose(f);
+ return userid;
+}
+char *getusername(int userid)
+{
+ int colons;
+ int c,i;
+ char token[80];
+ static char name[80];
+ char *retval = NULL;
+ FILE *f;
+ f = fopen("/etc/passwd","r");
+ if (f) {
+ i = 0;
+ colons = 0;
+ while ((c = getc(f)) != EOF) {
+ switch (c) {
+ case ':':
+ token[i] = '\0';
+ colons++;
+ if (colons == 3) {
+ if (userid == atoi(token)) {
+ retval = name;
+ goto endloop;
+ }
+ } else if (colons == 1) {
+ strcpy(name,token);
+ }
+ i = 0;
+ break;
+ case '\n':
+ colons = 0;
+ i = 0;
+ break;
+ default:
+ token[i++] = c;
+ break;
+ }
+ }
+ endloop:
+ fclose(f);
+ }
+ return retval;
+}
diff --git a/axcalluser.h b/axcalluser.h
new file mode 100644
index 0000000..f802c30
--- /dev/null
+++ b/axcalluser.h
@@ -0,0 +1,16 @@
+#ifndef AXCALLUSER_H
+#define AXCALLUSER_H
+
+/* Simple functions to return userid of a callsign, and */
+/* username of a userid, by reading appropriate files. */
+/* Surely there's a better way to do 'getusername', but */
+/* this works. */
+/* Dave Brown N2RJT 5/5/96 */
+
+/* return userid of given callsign, or -1 if not found */
+int axcalluserid(char *callsign);
+
+/* return username of given userid, or NULL if not found */
+char *getusername(int userid);
+
+#endif
diff --git a/axdigi.c b/axdigi.c
new file mode 100644
index 0000000..252d7e5
--- /dev/null
+++ b/axdigi.c
@@ -0,0 +1,255 @@
+/*
+ * axdigi: Cross and straight port digipeater program
+ * Copyright (C) 1995 Craig Small VK2XLZ
+ *
+ * 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.
+ *
+ * JSN - Small tweaks to ensure compilation and execution under Linux 2.1.x.
+ * 12th June 1997.
+ */
+
+#include </usr/include/net/if.h>
+#include <linux/if_ether.h>
+#include <netinet/in.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+/* below added by N1URO */
+#include <string.h>
+#include <unistd.h>
+#include <linux/ax25.h>
+
+int recv_packet(unsigned char *buf, int size, unsigned char *port);
+void print_call(unsigned char *buf);
+unsigned char *find_call(char *port);
+void add_port(char *call, char *port);
+void get_interfaces(int skt);
+
+/*
+ * The defines we use
+ */
+#define AXALEN 7
+#define E_BIT 0x01 /* Address extension bit */
+#define REPEATED 0x80 /* Has-been-repeated bit */
+#define MAX_PORTS 16
+#define VERSION "0.2"
+
+int port_count = 0;
+unsigned char portname[MAX_PORTS][20];
+unsigned char portcall[MAX_PORTS][8];
+
+
+
+int main(int argc, char *argv[])
+{
+ int skt;
+ int size, rt;
+ unsigned char buf[4096];
+ struct sockaddr sa;
+ int asize;
+
+ /* Check our huge range of flags */
+ if (argc > 1)
+ {
+ if (strcmp(argv[1], "-v") == 0 || strcmp(argv[1], "-h") ==0)
+ {
+ printf("axdigi version %s. Copyright (C) 1995 Craig Small VK2XLZ\n\n", VERSION);
+ printf("axdigi comes with ABSOLUTELY NO WARRANTY.\n");
+ printf("This is free software, and you are welcome to redistribute it\n");
+ printf("under the terms of GNU General Public Licence as published\n");
+ printf("by Free Software Foundation; either version 2 of the License, or\n");
+ printf("(at your option) any later version.\n");
+ return 0;
+ }
+ }
+/* Change to keep code more modern - N1URO */
+ if ((skt = socket(PF_PACKET, SOCK_PACKET, htons(ETH_P_AX25))) == -1)
+ {
+ perror("socket");
+ return(1);
+ }
+ get_interfaces(skt);
+
+ while(1)
+ {
+ asize = sizeof(sa);
+
+ if ((size = recvfrom(skt, buf, sizeof(buf), 0, &sa, &asize)) == -1)
+ {
+ perror("recv");
+ exit(1);
+ }
+ if ((rt = recv_packet(buf, size, sa.sa_data)) >= 0)
+ {
+ if (rt < port_count)
+ {
+ asize = sizeof(sa);
+ strcpy(sa.sa_data, portname[rt]);
+ if (sendto(skt, buf, size, 0, &sa, asize) == -1)
+ perror("sendto");
+ continue;
+ }
+ /* printf("Unknown port %s\n", sa.sa_data);*/
+ } /* recv_packet true */
+ } /* while(1) */
+ close(skt);
+}
+
+int recv_packet(unsigned char *buf, int size, unsigned char *port)
+{
+ unsigned char *bptr;
+ int count, i;
+ unsigned char *call;
+
+ /* printf("Got packet size %d\n", size);*/
+
+ /*
+ * Decode the AX.25 Packet
+ */
+ /* Find packet, skip over flag */
+ bptr = buf+1;
+ /* Now at destination address */
+ /* print_call(bptr);
+ printf("<-");*/
+ bptr += AXALEN;
+
+ /* Now at source address */
+ /* print_call(bptr);*/
+ if (bptr[6] & E_BIT)
+ {
+ /* printf("\n");*/
+ return -1; /* No digis, we're not interested */
+ }
+ /* printf(" ");*/
+ bptr += AXALEN;
+ /* Now at digipeaters */
+
+ count = 0;
+ while( count < AX25_MAX_DIGIS && ( (bptr - buf) < size))
+ {
+ /* print_call(bptr);
+ printf(", ");*/
+ if (bptr[6] & REPEATED)
+ {
+ /* This one has been repeated, move to next one */
+ bptr += AXALEN;
+ count++;
+ continue;
+ }
+ /* Check to see if callsign is one of ours */
+ for (i = 0; i < port_count; i++)
+ {
+ /* printf("compare ");
+ print_call(bptr);
+ printf(" ");
+ print_call(portcall[i]);
+ printf("\n");*/
+ if ( (bcmp(bptr, portcall[i], AXALEN-1) == 0) && ((bptr[6] & 0x1e) == portcall[i][6]))
+ {
+ /* Copy new address over and turn on repeated bit*/
+ call = find_call(port);
+ if (call == NULL)
+ return -1;
+ bcopy(call, bptr, AXALEN-1);
+ bptr[6] = (bptr[6] & ~0x1e) | call[6];
+ bptr[6] |= REPEATED;
+ return i;
+ }
+ } /* for */
+ return -1;
+ }
+ return -1;
+}
+
+void print_call(unsigned char *bptr)
+{
+ printf("%c%c%c%c%c%c-%d", bptr[0] >> 1, bptr[1] >> 1,
+ bptr[2] >> 1, bptr[3] >> 1, bptr[4] >> 1, bptr[5] >> 1,
+ (bptr[6] >> 1) & 0xf);
+}
+
+void add_port(char *call, char *port)
+{
+ unsigned char *s;
+ int n;
+
+ if (port_count == MAX_PORTS)
+ return;
+
+ s = portcall[port_count];
+
+ while( (*call != '-') && ( (int)(s - portcall[port_count])< 6))
+ *s++ = (*call++) << 1;
+ call++; /* skip over dash */
+ n = atoi(call);
+ *s = n << 1;
+
+ strcpy(portname[port_count], port);
+ port_count++;
+}
+
+
+unsigned char *find_call(char *port)
+{
+ static unsigned char callsign[8];
+ int i;
+
+ for(i = 0; i < port_count; i++)
+ {
+ if (strcmp(port, portname[i]) == 0)
+ {
+ bcopy(portcall[i], callsign, 7);
+ return callsign;
+ }
+ }
+ return (char*)NULL;
+}
+
+void get_interfaces(int skt)
+{
+ char buf[1024];
+ struct ifconf ifc;
+ struct ifreq *ifr;
+ int i;
+
+ ifc.ifc_len = sizeof(buf);
+ ifc.ifc_buf = buf;
+ if (ioctl(skt, SIOCGIFCONF, &ifc) < 0)
+ {
+ perror("ioctl");
+ exit(1);
+ }
+
+ ifr = ifc.ifc_req;
+ for (i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++)
+ {
+ if (ioctl(skt, SIOCGIFHWADDR, ifr) < 0)
+ continue;
+ if (ifr->ifr_hwaddr.sa_family == AF_AX25)
+ {
+ /* AX25 port, add to list */
+ if (port_count < MAX_PORTS)
+ {
+ bcopy(ifr->ifr_hwaddr.sa_data, portcall[port_count], 7);
+ strcpy(portname[port_count], ifr->ifr_name);
+ port_count++;
+ }
+ }
+ } /* for */
+}
+
diff --git a/cmdparse.c b/cmdparse.c
new file mode 100644
index 0000000..298b1cf
--- /dev/null
+++ b/cmdparse.c
@@ -0,0 +1,300 @@
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+
+
+#include <sys/socket.h>
+#include <netax25/ax25.h>
+#include <netrose/rose.h>
+#include <netax25/axlib.h>
+
+#include "node.h"
+
+static void expand_string(char *dest, char *src, int argc, char **argv)
+{
+ char tmpbuf[64], def[64];
+ char *p1, *p2, *cp;
+ int n, skip, nocopy;
+
+ if (strchr(src, '%') == NULL) {
+ strcpy(dest, src);
+ return;
+ }
+ p1 = src;
+ p2 = dest;
+ while (*p1) {
+ if (*p1 == '%') {
+ nocopy=1;
+ p1++;
+ skip = 1;
+ def[0] = 0;
+ if (*p1 == '{') {
+ p1++;
+ if ((cp = strchr(p1, '}')) != NULL) {
+ skip = cp - p1 + 1;
+ cp = p1;
+ if (*++cp == ':') {
+ cp++;
+ n = min(skip - 3, 63);
+ strncpy(def, cp, n);
+ def[n] = 0;
+ }
+ }
+ }
+ switch (*p1) {
+ case 'u':
+ case 'U':
+ strcpy(tmpbuf, User.call);
+ if ((cp = strrchr(tmpbuf, '-'))) *cp = 0;
+ break;
+ case 's':
+ case 'S':
+ strcpy(tmpbuf, User.call);
+ break;
+ case 'p':
+ case 'P':
+ strcpy(tmpbuf, User.ul_name);
+ if ((cp = strrchr(tmpbuf, '-'))) *cp = 0;
+ break;
+ case 'r':
+ case 'R':
+ strcpy(tmpbuf, User.ul_name);
+ break;
+ case 't':
+ case 'T':
+ switch (User.ul_type) {
+ case AF_FLEXNET:
+ strcpy(tmpbuf, "flexnet");
+ break;
+ case AF_AX25:
+ strcpy(tmpbuf, "ax25");
+ break;
+ case AF_NETROM:
+ strcpy(tmpbuf, "netrom");
+ break;
+#ifdef HAVE_ROSE
+ case AF_ROSE:
+ strcpy(tmpbuf, "rose");
+ break;
+#endif
+ case AF_INET:
+ strcpy(tmpbuf, "inet");
+ break;
+ case AF_UNSPEC:
+ strcpy(tmpbuf, "host");
+ break;
+ }
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ n = *p1 - '0';
+ if (n < argc) strcpy(tmpbuf, argv[n]);
+ else strcpy(tmpbuf, def);
+ break;
+ case '*':
+ nocopy=0;
+ for(n=2;n<argc;n++) {
+ if (argv[n]==NULL) break;
+ strcpy(tmpbuf, argv[n]);
+ if (isalpha(*p1)) {
+ if (isupper(*p1)) strupr(tmpbuf);
+ else strlwr(tmpbuf);
+ }
+ strcpy(p2, tmpbuf);
+ p2 += strlen(tmpbuf);
+ }
+ break;
+ default:
+ strcpy(tmpbuf, "%");
+ break;
+ }
+ if (nocopy==1) {
+ if (isalpha(*p1)) {
+ if (isupper(*p1)) strupr(tmpbuf);
+ else strlwr(tmpbuf);
+ }
+ strcpy(p2, tmpbuf);
+ p2 += strlen(tmpbuf);
+ }
+ p1 += skip;
+ } else
+ *p2++ = *p1++;
+ }
+ *p2 = 0;
+ return;
+}
+
+/* This function is straight from *NOS */
+
+static char *parse_string(char *str)
+{
+ char *cp = str;
+ unsigned long num;
+
+ while (*str != '\0' && *str != '\"') {
+ if (*str == '\\') {
+ str++;
+ switch (*str++) {
+ case 'n': *cp++ = '\n'; break;
+ case 't': *cp++ = '\t'; break;
+ case 'v': *cp++ = '\v'; break;
+ case 'b': *cp++ = '\b'; break;
+ case 'r': *cp++ = '\r'; break;
+ case 'f': *cp++ = '\f'; break;
+ case 'a': *cp++ = '\007'; break;
+ case '\\': *cp++ = '\\'; break;
+ case '\"': *cp++ = '\"'; break;
+ case 'x':
+ num = strtoul(--str, &str, 16);
+ *cp++ = (char) num;
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ num = strtoul(--str, &str, 8);
+ *cp++ = (char) num;
+ break;
+ case '\0':
+ return NULL;
+ default:
+ *cp++ = *(str - 1);
+ break;
+ };
+ } else {
+ *cp++ = *str++;
+ }
+ }
+ if (*str == '\"') str++; /* skip final quote */
+ *cp = '\0'; /* terminate string */
+ return str;
+}
+
+int parse_args(char **argv, char *cmd)
+{
+ int ct = 0;
+ int quoted;
+
+ while (ct < 31) {
+ quoted = 0;
+ while (*cmd && isspace(*cmd)) cmd++;
+ if (*cmd == 0) break;
+ if (*cmd == '"') {
+ quoted++;
+ cmd++;
+ }
+ argv[ct++] = cmd;
+ if (quoted) {
+ if ((cmd = parse_string(cmd)) == NULL)
+ return 0;
+ } else {
+ while (*cmd && !isspace(*cmd)) cmd++;
+ }
+ if (*cmd) *cmd++ = 0;
+ }
+ argv[ct] = NULL;
+ return ct;
+}
+
+int cmdparse(struct cmd *list, char *cmdline)
+{
+ struct cmd *cmdp;
+ int argc;
+ char *argv[32];
+ static char cmdbuf[1024];
+
+ /* convert cmdline to argc,argv[] if '#' or empty: return */
+ if ((argc = parse_args(argv, cmdline)) == 0 || *argv[0] == '#') return 2;
+ /* check if the command in argv[0] is in the list */
+ for (cmdp = list; cmdp != NULL; cmdp = cmdp->next) {
+ if (strlen(argv[0]) < cmdp->len || strlen(argv[0]) > strlen(cmdp->name)) continue;
+ if (strncasecmp(cmdp->name, argv[0], strlen(argv[0])) == 0) break;
+ }
+ if (cmdp == NULL) return -1;
+ strlwr(argv[0]);
+ switch (cmdp->type) {
+ case CMD_INTERNAL: /* execute internal command */
+ return (*cmdp->function)(argc, argv);
+ case CMD_ALIAS:
+ /* evaluate arguments */
+ expand_string(cmdbuf, cmdp->command, argc, argv);
+ aliascmd=1;
+ /* re-execute the command */
+ return cmdparse(list, cmdbuf);
+ case CMD_EXTERNAL:
+ /* evaluate arguments */
+ expand_string(cmdbuf, cmdp->command, argc, argv);
+ /* convert the cmdline to argc,argv[] */
+ argc = parse_args(argv, cmdbuf);
+ /* execute an external command */
+ if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo, "%s} ", NodeId);
+ }
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo,"\e[01;32mExecuting command...\e[0m\n");
+ } else {
+ axio_puts("Executing command... \n", NodeIo);
+ }
+ return extcmd(cmdp, argv);
+ }
+ return -1;
+}
+
+void insert_cmd(struct cmd **list, struct cmd *new)
+{
+ struct cmd *tmp, *p;
+
+ if (*list == NULL || strcasecmp(new->name, (*list)->name) < 0) {
+ tmp = *list;
+ *list = new;
+ new->next = tmp;
+ } else {
+ for (p = *list; p->next != NULL; p = p->next)
+ if (strcasecmp(new->name, p->next->name) < 0) break;
+ tmp = p->next;
+ p->next = new;
+ new->next = tmp;
+ }
+}
+
+int add_internal_cmd(struct cmd **list, char *name, int len, int (*function) (int argc, char **argv))
+{
+ struct cmd *new;
+
+ if ((new = calloc(1, sizeof(struct cmd))) == NULL) {
+ node_perror("add_internal_cmd: calloc", errno);
+ return -1;
+ }
+ new->name = strdup(name);
+ new->len = len;
+ new->type = CMD_INTERNAL;
+ new->function = function;
+ insert_cmd(list, new);
+ return 0;
+}
+
+void free_cmdlist(struct cmd *list)
+{
+ struct cmd *tmp;
+
+ while (list != NULL) {
+ free(list->name);
+ free(list->command);
+ free(list->path);
+ tmp = list;
+ list = list->next;
+ free(tmp);
+ }
+}
diff --git a/command.c b/command.c
new file mode 100644
index 0000000..53fbcbb
--- /dev/null
+++ b/command.c
@@ -0,0 +1,1058 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <time.h>
+#include <fcntl.h>
+#include <sys/utsname.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <netax25/ax25.h>
+#include <netrose/rose.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <netax25/axlib.h>
+#include <netax25/axconfig.h>
+#include <netax25/nrconfig.h>
+#include <netax25/rsconfig.h>
+#include <netax25/procutils.h>
+#include <netax25/mheard.h>
+
+#include "node.h"
+#include "procinfo.h"
+#include "sysinfo.h"
+
+struct cmd *Nodecmds = NULL;
+
+void init_nodecmds(void)
+{
+ add_internal_cmd(&Nodecmds, "?", 1, do_help);
+ add_internal_cmd(&Nodecmds, "Bye", 1, do_bye);
+ add_internal_cmd(&Nodecmds, "Escape", 1, do_escape);
+ if (User.ul_type == AF_INET) {
+ add_internal_cmd(&Nodecmds, "EXit", 1, do_bye);
+ }
+ add_internal_cmd(&Nodecmds, "Help", 1, do_help);
+ add_internal_cmd(&Nodecmds, "Info", 1, do_help);
+ add_internal_cmd(&Nodecmds, "Quit", 1, do_bye);
+ add_internal_cmd(&Nodecmds, "Status", 1, do_status);
+ add_internal_cmd(&Nodecmds, "Version", 1, do_version);
+#ifdef HAVEMOTD
+ add_internal_cmd(&Nodecmds, "Who", 1, do_last);
+#endif
+ add_internal_cmd(&Nodecmds, "MSg", 2, do_msg);
+#ifdef HAVE_AX25
+ add_internal_cmd(&Nodecmds, "Connect", 1, do_connect);
+ add_internal_cmd(&Nodecmds, "Links", 1, do_links);
+ add_internal_cmd(&Nodecmds, "INTerfaces", 3, do_ports);
+ add_internal_cmd(&Nodecmds, "SEssions", 2, do_sessions);
+ add_internal_cmd(&Nodecmds, "Users", 1, nuser_list);
+#ifdef HAVE_FLEX
+ add_internal_cmd(&Nodecmds, "Desti", 1, do_dest);
+#endif
+#ifdef HAVE_MHEARD
+ add_internal_cmd(&Nodecmds, "MHeard", 2, do_mheard);
+#endif
+#ifdef HAVE_NETROM
+ add_internal_cmd(&Nodecmds, "Nodes", 1, do_nodes);
+ add_internal_cmd(&Nodecmds, "Routes", 1, do_routes);
+#endif
+#endif
+#ifdef HAVE_TCPIP
+ add_internal_cmd(&Nodecmds, "Finger", 1, do_finger);
+ add_internal_cmd(&Nodecmds, "HOst", 2, do_host);
+ add_internal_cmd(&Nodecmds, "Ping", 1, do_ping);
+ add_internal_cmd(&Nodecmds, "Telnet", 1, do_connect);
+#endif
+#ifdef HAVE_ZLIB_H
+ add_internal_cmd(&Nodecmds, "ZConnect", 1, do_connect);
+ add_internal_cmd(&Nodecmds, "ZTelnet", 1, do_connect);
+#endif
+};
+
+void node_prompt(const char *fmt, ...)
+{
+ if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo,"%s} ", NodeId);
+ }
+ if ((User.ul_type == AF_INET) && (check_perms(PERM_ANSI, 0L) != -1)) {
+ axio_printf(NodeIo,"\r\n\e[01;31m%s\e[0m@\e[01;34m%s\e[0m:/uronode$ ",User.call, HostName);
+ }
+ if ((User.ul_type == AF_INET) && (check_perms(PERM_ANSI, 0L) == -1)) {
+ axio_printf(NodeIo,"\r\n%s@%s:/uronode$ ", User.call, HostName);
+ }
+ if ((User.ul_type == AF_AX25) && (check_perms(PERM_ANSI, 0L) != -1)) {
+ axio_printf(NodeIo,"\b\e[01;33m");
+ }
+ if (User.ul_type == AF_AX25) {
+ axio_printf(NodeIo,"%s",Prompt);
+ }
+ if ((User.ul_type == AF_ROSE) && (check_perms(PERM_ANSI, 0L) == -1)) {
+ axio_printf(NodeIo,"\r-=> ");
+ }
+ if ((User.ul_type == AF_ROSE) && (check_perms(PERM_ANSI, 0L) != -1)) {
+ axio_printf(NodeIo,"\r\e[01;35m-=>\e[0m \b");
+ }
+ axio_flush(NodeIo);
+}
+
+void node_logout(char *reason)
+{
+#ifdef HAVEMOTD
+ if (User.ul_type == AF_INET) {
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[03;36m");
+ }
+ axio_printf(NodeIo, "Thank you %s, for connecting to the \n%s URONode packet shell.\n", User.call, HostName);
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[0;m");
+ }
+ }
+ if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo,"");
+ }
+ if (User.ul_type == AF_ROSE) {
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[03;36m");
+ }
+ axio_printf(NodeIo, "%s, thank you for connecting to the %s\nURONode ROSE network node. Come back again soon, 73!\r ", User.call, RoseId);
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[0;m\b");
+ }
+ } else
+ if ((User.ul_type == AF_FLEXNET) || (User.ul_type == AF_AX25)) {
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[03;36m");
+ }
+ axio_printf(NodeIo, "%s de %s\n73! ", User.call, FlexId);
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[0;m\b");
+ }
+ }
+#endif
+ axio_flush(NodeIo);
+ axio_end_all();
+ logout_user();
+ ipc_close();
+ node_log(LOGLVL_LOGIN, "%s @ %s logged out", User.call, User.ul_name);
+ node_log(LOGLVL_LOGIN, "%s %s", NodeId, reason);
+ free_cmdlist(Nodecmds);
+ Nodecmds = NULL;
+ exit(0);
+}
+
+int do_bye(int argc, char **argv)
+{
+ node_logout("User hit bye or quit");
+ return 0; /* Keep gcc happy */
+}
+
+int do_escape(int argc, char **argv)
+{
+ int now = 0;
+
+ if (argc > 1) {
+ EscChar = get_escape(argv[1]);
+ now = 1;
+ }
+ if (EscChar < -1 || EscChar > 255) {
+ if (User.ul_type == AF_NETROM) {
+ node_msg("%s} ", NodeId);
+ }
+ node_msg("Invalid escape character: %s", argv[1]);
+ return 0;
+ }
+
+ if (EscChar == -1) {
+ if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo, "%s} ", NodeId);
+ }
+ axio_printf(NodeIo,"The escape mechanism is %sdisabled", now ? "now " : "");
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ return 0;
+ }
+ if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo, "%s} ", NodeId);
+ }
+ axio_printf(NodeIo,"The escape character is %s%s%c",
+ now ? "now " : "",
+ EscChar < 32 ? "CTRL-" : "",
+ EscChar < 32 ? (EscChar + 'A' - 1) : EscChar);
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ return 0;
+}
+
+int do_help(int argc, char **argv)
+{
+ FILE *fp;
+ char fname[256], line[256];
+ struct cmd *cmdp;
+ int i = 0;
+
+ if (*argv[0] == '?') { /* "?" */
+ if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo, "%s} ", NodeId);
+ }
+ if (User.ul_type == AF_INET) {
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[01;37m");
+ }
+ axio_printf(NodeIo, "Shell ");
+ }
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[01;37m");
+ }
+ axio_printf(NodeIo,"Commands:");
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[0;m");
+ }
+ for (cmdp = Nodecmds; cmdp != NULL; cmdp = cmdp->next) {
+ axio_printf(NodeIo,"%s%s", i ? ", " : "\n", cmdp->name);
+ if (++i == 10) {
+ axio_printf(NodeIo,"");
+ i = 0;
+ }
+ }
+ if (i) axio_printf(NodeIo,"");
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ return 0;
+ }
+ if (argv[1] && strchr(argv[1], '/')) {
+ if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo,"%s} ", NodeId);
+ }
+ node_msg("Invalid command %s", argv[1]);
+ return 0;
+ }
+ if (*argv[0] == 'i') { /* "info" */
+ strcpy(fname, CONF_NODE_INFO_FILE);
+ if (User.ul_type == AF_NETROM) {
+
+ axio_printf(NodeIo,"%s} ", NodeId);
+ }
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[01;37m");
+ }
+ axio_printf(NodeIo,"System Information:\n");
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[0;m");
+ }
+ axio_printf(NodeIo,"%s - %s \n", VERSION, COMPILING);
+ } else if (!argv[1]) { /* "help" */
+ strcpy(fname, DATA_NODE_HELP_DIR "help.hlp");
+ } else { /* "help <cmd>" */
+ strlwr(argv[1]);
+ snprintf(fname, sizeof(fname), DATA_NODE_HELP_DIR "%s.hlp", argv[1]);
+ fname[sizeof(fname) - 1] = 0;
+ }
+ if ((fp = fopen(fname, "r")) == NULL) {
+ if (*argv[0] != 'i')
+ if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo,"%s} ", NodeId);
+ }
+ axio_printf(NodeIo,"No help for command %s", argv[1] ? argv[1] : "help");
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ return 0;
+ }
+ if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo,"%s} ", NodeId);
+ }
+ if (*argv[0] != 'i')
+ node_msg("Help for command %s", argv[1] ? argv[1] : "help");
+ while (fgets(line, 256, fp) != NULL)
+ axio_puts(line,NodeIo);
+ fclose(fp);
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ return 0;
+}
+
+int do_host(int argc, char **argv)
+{
+ struct hostent *h;
+ struct in_addr addr;
+ char **p, *cp;
+
+ if (argc < 2) {
+ if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo,"%s} ", NodeId);
+ }
+ node_msg("Usage: host <hostname>|<ip address>");
+ return 0;
+ }
+ if (inet_aton(argv[1], &addr) != 0)
+ h = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET);
+ else
+ h = gethostbyname(argv[1]);
+ if (h == NULL) {
+ switch (h_errno) {
+ case HOST_NOT_FOUND:
+ cp = "Unknown host";
+ break;
+ case TRY_AGAIN:
+ cp = "Temporary name server error";
+ break;
+ case NO_RECOVERY:
+ cp = "Non-recoverable name server error";
+ break;
+ case NO_ADDRESS:
+ cp = "No address";
+ break;
+ default:
+ cp = "Unknown error";
+ break;
+ }
+ node_msg("%s", cp);
+ return 0;
+ }
+ if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo,"%s} ", NodeId);
+ }
+ node_msg("Host name information for %s:", argv[1]);
+ axio_printf(NodeIo,"Hostname: %s", h->h_name);
+ axio_puts("\nAliases: ",NodeIo);
+ p = h->h_aliases;
+ while (*p != NULL) {
+ axio_printf(NodeIo," %s", *p);
+ p++;
+ }
+ axio_puts("\nAddress(es):",NodeIo);
+ p = h->h_addr_list;
+ while (*p != NULL) {
+ addr.s_addr = ((struct in_addr *)(*p))->s_addr;
+ axio_printf(NodeIo," %s", inet_ntoa(addr));
+ p++;
+ }
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ return 0;
+}
+
+int do_ports(int argc, char **argv)
+{
+ struct proc_ax25 *ax, *ax_list;
+ struct proc_dev *dev, *dev_list;
+ char *cp = NULL;
+ int n, tx, rx;
+
+ ax_list=read_proc_ax25();
+ dev_list=read_proc_dev();
+ if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo,"%s} ", NodeId);
+ }
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[01;35m");
+ }
+ node_msg("Interfaces:");
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[0;m");
+ }
+ axio_printf(NodeIo,"Name Description QSO RX packets TX packets\n");
+ axio_printf(NodeIo,"------- ------------------------------------------ ---- ----------- -----------");
+ while ((cp = ax25_config_get_next(cp)) != NULL) {
+ n=0;
+ if (ax_list) for (ax=ax_list;ax!=NULL;ax=ax->next) {
+ // if (strcmp(ax25_config_get_name(ax->dev), cp)==0 && strcmp(ax->dest_addr, "*")!=0) n++;
+ if (strcmp(ax->dest_addr, "*")!=0 && strcmp(ax25_config_get_name(ax->dev), cp)==0) n++;
+ }
+ tx=0; rx=0;
+ if (dev_list) for (dev=dev_list;dev!=NULL;dev=dev->next) {
+ if (strcmp(dev->interface, ax25_config_get_dev(cp))==0) {
+ tx=dev->tx_packets;
+ rx=dev->rx_packets;
+ }
+ }
+ if (is_hidden(cp) && check_perms(PERM_HIDDEN, 0L) == -1)
+ continue;
+ axio_printf(NodeIo,"\n%-7.7s %-42.42s %4d %11d %11d", cp, ax25_config_get_desc(cp), n, rx, tx);
+ }
+
+ free_proc_ax25(ax_list);
+ free_proc_dev(dev_list);
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ return 0;
+}
+
+int do_sessions(int argc, char **argv)
+{
+ struct proc_ax25 *ax_p, *ax_list;
+#ifdef HAVE_NETROM
+ struct proc_nr *nr_p, *nr_list;
+#endif
+ char *cp;
+
+ if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo,"%s} %s\n", NodeId, VERSION);
+ }
+ if ((ax_list = read_proc_ax25()) == NULL) {
+ if (errno) node_perror("sessions: read_proc_ax25:", errno);
+ else axio_printf (NodeIo,"No such AX25 sessions actives.");
+
+ } else {
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[01;33m");
+ }
+ node_msg("AX.25 Sessions:");
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo,"\e[0;m");
+ }
+ axio_printf(NodeIo,"Int. Dest addr Src addr State Unack T1 Retr Rtt Snd-Q Rcv-Q\n");
+ axio_printf(NodeIo,"------- --------- --------- ------------ ----- ------- ------ --- ----- -----\n");
+ for (ax_p = ax_list; ax_p != NULL; ax_p = ax_p->next) {
+ if (argc > 1 && strcasecmp(argv[1], "*") && strcasecmp(ax_p->dest_addr, argv[1]) &&
+ strcasecmp(ax_p->src_addr, argv[1])) continue;
+ if ((argc < 2) && !strcmp(ax_p->dest_addr, "*"))
+ continue;
+ cp = ax25_config_get_name(ax_p->dev);
+ axio_printf(NodeIo,"%-7s %-9s %-9s ", cp, ax_p->dest_addr, ax_p->src_addr);
+ if (!strcmp(ax_p->dest_addr, "*")) {
+ axio_printf(NodeIo,"Listening\n");
+ continue;
+ }
+ switch (ax_p->st) {
+ case 0:
+ cp = "Disconnected";
+ break;
+ case 1:
+ cp = "Conn pending";
+ break;
+ case 2:
+ cp = "Disc pending";
+ break;
+ case 3:
+ cp = "Connected ";
+ break;
+ case 4:
+ cp = "Recovery ";
+ break;
+ default:
+ cp = "Unknown ";
+ break;
+ }
+ axio_printf(NodeIo,"%s %02d/%02d %03d/%03d %02d/%03d %3d %5ld %5ld\n",
+ cp,
+ ax_p->vs < ax_p->va ? ax_p->vs - ax_p->va + 8 : ax_p->vs - ax_p->va,
+ ax_p->window,
+ ax_p->t1timer, ax_p->t1,
+ ax_p->n2count, ax_p->n2,
+ ax_p->rtt,
+ ax_p->sndq, ax_p->rcvq);
+ }
+ free_proc_ax25(ax_list);
+ axio_puts("",NodeIo);
+ }
+
+#ifdef HAVE_NETROM
+ if ((nr_list = read_proc_nr()) == NULL) {
+ if (errno) node_perror("sessions: read_proc_nr", errno);
+ else axio_printf (NodeIo,"No such NET/ROM sessions actives.\n");
+ } else {
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[01;36m");
+ }
+ node_msg("\nNET/ROM Sessions:");
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[0;m");
+ }
+ axio_printf(NodeIo,"User addr Dest node Src node State Unack T1 Retr Snd-Q Rcv-Q\n");
+ axio_printf(NodeIo,"--------- --------- --------- ------------ ----- ------- ------ ----- -----");
+ for (nr_p = nr_list; nr_p != NULL; nr_p = nr_p->next) {
+ if (argc > 1 && strcasecmp(argv[1], "*") && strcasecmp(nr_p->user_addr, argv[1]) &&
+ strcasecmp(nr_p->dest_node, argv[1]) && strcasecmp(nr_p->src_node, argv[1])) continue;
+ if ((argc < 2) && !strcmp(nr_p->user_addr, "*")) continue;
+ cp = nr_config_get_name(nr_p->dev);
+ axio_printf(NodeIo,"\n%-9s %-9s %-9s ", nr_p->user_addr, nr_p->dest_node, nr_p->src_node);
+ if (!strcmp(nr_p->user_addr, "*")) {
+ axio_printf(NodeIo,"Listening\n");
+ continue;
+ }
+ switch (nr_p->st) {
+ case 0:
+ cp = "Disconnected";
+ break;
+ case 1:
+ cp = "Conn pending";
+ break;
+ case 2:
+ cp = "Disc pending";
+ break;
+ case 3:
+ cp = "Connected ";
+ break;
+ case 4:
+ cp = "Recovery ";
+ break;
+ default:
+ cp = "Unknown ";
+ break;
+ }
+ axio_printf(NodeIo,"%s %02d/%02d %03d/%03d %02d/%03d %5ld %5ld",
+ cp,
+ nr_p->vs < nr_p->va ? nr_p->vs - nr_p->va + 8 : nr_p->vs - nr_p->va,
+ nr_p->window,
+ nr_p->t1timer, nr_p->t1,
+ nr_p->n2count, nr_p->n2,
+ nr_p->sndq, nr_p->rcvq);
+ }
+ free_proc_nr(nr_list);
+ }
+
+#endif
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ return 0;
+}
+
+int do_routes(int argc, char **argv)
+{
+ struct proc_nr *nr, *nr_list;
+ struct proc_nr_neigh *nrh, *nrh_list;
+ struct proc_nr_nodes *nrn, *nrn_list;
+ struct proc_ax25 *ap;
+ char *cp, portcall[10];
+ int link, n;
+
+ nr_list=read_proc_nr();
+ nrn_list=read_proc_nr_nodes();
+ if ((nrh_list = read_proc_nr_neigh()) == NULL) {
+ if (errno) node_perror("do_routes: read_proc_nr_neigh", errno);
+ else
+ if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo,"%s} ", NodeId);
+ }
+ axio_printf (NodeIo,"No such routes");
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ free_proc_nr_neigh(nrh_list);
+ free_proc_nr_nodes(nrn_list);
+ free_proc_nr(nr_list);
+
+ return 0;
+ }
+ /* if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[01;33m");
+ } */
+ if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo,"%s} ", NodeId);
+ }
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[01;36m");
+ }
+ node_msg("Routes:");
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[0;m");
+ }
+ axio_printf(NodeIo,"Link Intface Callsign Qual Nodes Lock QSO\n");
+ axio_printf(NodeIo,"---- ------- --------- ---- ----- ---- ---");
+ strcpy(portcall,nr_config_get_addr(nr_config_get_next(NULL)));
+ if (strchr(portcall, '-')==NULL) strcat(portcall, "-0");
+ for (nrh = nrh_list; nrh != NULL; nrh = nrh->next) {
+ link=0; n=0;
+ if ((ap = find_link(portcall, nrh->call, nrh->dev)) != NULL && ap->st >= 3) link = 1;
+ if ((ap = find_link(nrh->call, portcall, nrh->dev)) != NULL && ap->st >= 3) link = 2;
+ cp = ax25_config_get_name(nrh->dev);
+
+ if (nr_list) for (nr=nr_list;nr!=NULL;nr=nr->next) {
+ if (strcmp(nr->dest_node, nrh->call)==0) {
+ n++;
+ } else {
+ if (nrn_list) for(nrn=nrn_list;nrn!=NULL;nrn=nrn->next) {
+ if (strcmp(nrn->call, nr->dest_node)==0) {
+ switch(nrn->w) {
+ case 1: if (nrn->addr1==nrh->addr) n++; break;
+ case 2: if (nrn->addr2==nrh->addr) n++; break;
+ case 3: if (nrn->addr3==nrh->addr) n++; break;
+ }
+ }
+ }
+ }
+ }
+
+ axio_printf(NodeIo,"\n%c %-7s %-9s %4d %5d %c %4d",
+ link == 0 ? ' ' : '>',
+ cp,
+ nrh->call,
+ nrh->qual,
+ nrh->cnt,
+ nrh->lock == 1 ? '!' : ' ',
+ n);
+ }
+
+ free_proc_nr_neigh(nrh_list);
+ free_proc_nr_nodes(nrn_list);
+ free_proc_nr(nr_list);
+ free_proc_ax25(ap);
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ return 0;
+}
+
+int do_nodes(int argc, char **argv)
+{
+ struct proc_nr_nodes *p, *list;
+ struct proc_nr_neigh *np, *nlist;
+ int i = 0;
+ if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo,"%s} ", NodeId);
+ }
+ if ((list = read_proc_nr_nodes()) == NULL) {
+ if (errno)
+ node_perror("do_nodes: read_proc_nr_nodes", errno);
+ else
+ axio_printf(NodeIo,"No known nodes");
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ return 0;
+ }
+ /* "nodes" */
+ if (argc == 1) {
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[01;36m");
+ } else if (check_perms(PERM_ANSI, 0L) == -1) {
+ axio_printf(NodeIo, "");
+ }
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[01;36m");
+ }
+ node_msg("Nodes:");
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[0;m");
+ }
+ for (p = list; p != NULL; p = p->next) {
+ axio_printf(NodeIo,"%-16.16s %c",print_node(p->alias, p->call),(++i % 4) ? ' ' : '\n');
+ }
+ if ((User.ul_type == AF_NETROM) && (i % 4) != 0) {
+ node_msg("");
+ }
+ free_proc_nr_nodes(list);
+ return 0;
+ }
+ if ((nlist = read_proc_nr_neigh()) == NULL) {
+ node_perror("do_nodes: read_proc_nr_neigh", errno);
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ return 0;
+ }
+ /* "nodes *" */
+ if (*argv[1] == '*') {
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[01;36m");
+ }
+
+ node_msg("Detailed nodes listing:");
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[0;m");
+ }
+ axio_printf(NodeIo,"Node Qual Obs Intface Neighbour\n");
+ axio_printf(NodeIo,"----------------- ---- --- ------- ---------");
+ for (p = list; p != NULL; p = p->next) {
+ axio_printf(NodeIo,"\n%-16.16s ", print_node(p->alias, p->call));
+ if ((np = find_neigh(p->addr1, nlist)) != NULL) {
+ axio_printf(NodeIo,"%4d %3d %-7s %s",p->qual1,p->obs1,ax25_config_get_name(np->dev),np->call);
+ }
+ else if (p->n > 1 && (np = find_neigh(p->addr2, nlist)) != NULL) {
+ axio_printf(NodeIo," ");
+ axio_printf(NodeIo,"%7d %12d %-7s %s",p->qual2, p->obs2,ax25_config_get_name(np->dev),np->call);
+ }
+ else if (p->n > 2 && (np = find_neigh(p->addr3, nlist)) != NULL) {
+ axio_printf(NodeIo," ");
+ axio_printf(NodeIo,"%7d %12d %-7s %s",p->qual3, p->obs3,ax25_config_get_name(np->dev),np->call);
+ }
+ else if (p->n == 0) axio_puts("",NodeIo);
+ }
+ free_proc_nr_nodes(list);
+ free_proc_nr_neigh(nlist);
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ return 0;
+ }
+ /* "nodes <node>" */
+ p = find_node(argv[1], list);
+ if (p != NULL) {
+ if (p->n == 0) axio_printf(NodeIo,"Local node without routes: %s", print_node(p->alias, p->call));
+ else {
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[01;36m");
+ }
+ node_msg("Routes to: %s", print_node(p->alias, p->call));
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[0;m");
+ }
+ axio_printf(NodeIo,"Which Qual Obs Intface Neighbour\n");
+ axio_printf(NodeIo,"----- ---- --- ------- ---------");
+
+ if ((np = find_neigh(p->addr1, nlist)) != NULL) {
+ axio_printf(NodeIo,"\n%c %4d %3d %-7s %s",p->w == 1 ? '>' : ' ',p->qual1,p->obs1,
+ ax25_config_get_name(np->dev),np->call);
+ }
+ if (p->n > 1 && (np = find_neigh(p->addr2, nlist)) != NULL) {
+ axio_printf(NodeIo,"\n%c %4d %3d %-7s %s",p->w == 2 ? '>' : ' ',p->qual2, p->obs2,
+ ax25_config_get_name(np->dev),np->call);
+ }
+ if (p->n > 1 && (np = find_neigh(p->addr3, nlist)) != NULL) {
+ axio_printf(NodeIo,"\n%c %4d %3d %-7s %s",p->w == 3 ? '>' : ' ',p->qual3, p->obs3,
+ ax25_config_get_name(np->dev),np->call);
+ }
+ }
+ } else {
+ axio_printf(NodeIo,"No such node");
+ }
+ free_proc_nr_nodes(list);
+ free_proc_nr_neigh(nlist);
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ return 0;
+}
+
+/*
+ * by Heikki Hannikainen <hessu at pspt.fi>
+ * The following was mostly learnt from the procps package and the
+ * gnu sh-utils (mainly uname).
+ */
+int do_status(int argc, char **argv)
+{
+ int upminutes, uphours, updays;
+ double uptime_secs, idle_secs;
+ double av[3];
+ unsigned **mem;
+ struct utsname name;
+ time_t t;
+#ifdef HAVE_AX25
+ struct flex_dst *fd, *fd_list;
+ struct ax_routes *ar, *ar_list;
+ struct proc_ax25 *ax, *ax_list;
+#ifdef HAVE_NETROM
+ struct proc_nr *nr, *nr_list;
+ struct proc_nr_nodes *nop, *nolist;
+ struct proc_nr_neigh *nep, *nelist;
+ int n, r, nn;
+#endif
+ int na, nl, nd;
+#endif
+ int ma, mu, mf, sa, su, sf;
+ if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo,"%s} ", NodeId);
+ }
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[01;37m");
+ }
+ node_msg("Status:");
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[0;m");
+ }
+ time(&t);
+ axio_printf(NodeIo,"System time: %s", ctime(&t));
+ if (uname(&name) == -1) axio_printf(NodeIo,"Cannot get system name\n");
+ else {
+ axio_printf(NodeIo,"Hostname: %s\n", HostName);
+ axio_printf(NodeIo,"Operating system: %s %s (%s)\n", name.sysname, name.release, name.machine);
+ }
+ /* read and calculate the amount of uptime and format it nicely */
+ uptime(&uptime_secs, &idle_secs);
+ updays = (int) uptime_secs / (60*60*24);
+ upminutes = (int) uptime_secs / 60;
+ uphours = upminutes / 60;
+ uphours = uphours % 24;
+ upminutes = upminutes % 60;
+ axio_printf(NodeIo,"Uptime: ");
+ if (updays) axio_printf(NodeIo,"%d day%s, ", updays, (updays != 1) ? "s" : "");
+ if(uphours) axio_printf(NodeIo,"%d hour%s ", uphours, (uphours != 1) ? "s" : "");
+ axio_printf(NodeIo,"%d minute%s\n", upminutes, (upminutes != 1) ? "s" : "");
+ loadavg(&av[0], &av[1], &av[2]);
+ axio_printf(NodeIo,"Load average: %.2f, %.2f, %.2f\n", av[0], av[1], av[2]);
+ axio_printf(NodeIo,"Users: %d node, %d system\n", user_count(), system_user_count());
+
+ if (!(mem = meminfo()) || mem[meminfo_main][meminfo_total] == 0) {
+ /* cannot normalize mem usage */
+ axio_printf(NodeIo,"Cannot get memory information!\n");
+ } else {
+ ma = mem[meminfo_main][meminfo_total];
+ mu = (mem[meminfo_main][meminfo_total] - mem[meminfo_free][meminfo_total]);
+ mf = mem[meminfo_free][meminfo_total];
+ axio_printf(NodeIo,"Memory: Available Used Free perc. Used\n");
+ axio_printf(NodeIo,"------------------ ---------- ---------- ---------- ----------\n");
+ axio_printf(NodeIo,"Physical: %-7d kB %-7d kB %-7d kB %3d %%\n", ma, mu, mf, (mu*100)/ma);
+
+ if (!(mem = meminfo()) || mem[meminfo_stotal][meminfo_total] != 0)
+{
+ sa = mem[meminfo_stotal][meminfo_total];
+ su = (mem[meminfo_stotal][meminfo_total] - mem[meminfo_sfree][meminfo_total]);
+ sf = mem[meminfo_sfree][meminfo_total];
+ axio_printf(NodeIo,"Swap: %-7d kB %-7d kB %-7d kB %3d %%\n",sa,su,sf,(su*100)/sa);
+ }
+ else
+/* axio_printf(NodeIo,"Cannot get swap information!\n"); */
+ axio_printf(NodeIo," ");
+
+ }
+
+#ifdef HAVE_AX25
+#ifdef HAVE_NETROM
+ if ((nolist = read_proc_nr_nodes()) == NULL && errno != 0)
+ node_perror("sessions: read_proc_nr_nodes", errno);
+ n = 0;
+ for (nop = nolist; nop != NULL; nop = nop->next)
+ n++;
+ free_proc_nr_nodes(nolist);
+ if ((nelist = read_proc_nr_neigh()) == NULL && errno != 0)
+ node_perror("sessions: read_proc_nr_neigh", errno);
+ r = 0;
+ for (nep = nelist; nep != NULL; nep = nep->next)
+ r++;
+ free_proc_nr_neigh(nelist);
+#endif
+ na=0;
+ ax_list=read_proc_ax25();
+ if (ax_list) for (ax=ax_list;ax!=NULL;ax=ax->next) {
+ if (strcmp(ax->dest_addr, "*")==0) continue;
+ na++;
+ }
+ free_proc_ax25(ax_list);
+#ifdef HAVE_NETROM
+ nn=0;
+ nr_list=read_proc_nr();
+ if (nr_list) for (nr=nr_list;nr!=NULL;nr=nr->next) {
+ if (strcmp(nr->dest_node, "*")==0) continue;
+ nn++;
+ }
+ free_proc_nr(nr_list);
+#endif
+ nl=0;
+ ar_list=read_ax_routes();
+ if (ar_list) for (ar=ar_list;ar!=NULL;ar=ar->next) {
+ nl++;
+ }
+ free_ax_routes(ar_list);
+ nd=0;
+ fd_list=read_flex_dst();
+ if (fd_list) for (fd=fd_list;fd!=NULL;fd=fd->next) {
+ nd++;
+ }
+ free_flex_dst(fd_list);
+
+ axio_printf(NodeIo,"Sockets: Sessions Dest/Nodes Links/Routes\n");
+ axio_printf(NodeIo,"------------------ ---------- ---------- ------------\n");
+ axio_printf(NodeIo,"AX25: %-10d %-10d %-10d\n",na,nd,nl);
+#ifdef HAVE_NETROM
+ axio_printf(NodeIo,"NET/ROM: %-10d %-10d %-10d",nn,n,r);
+#endif
+#endif
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ return 0;
+}
+
+int do_version(int argc, char **argv)
+{
+ if (User.ul_type != AF_NETROM) {
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo,"\e[01;37mShell : %s\n\e[01;35mHostname : %s\n\e[01;33max25/Flex: %s\n\e[01;36mNetRom : %s\n\e[01;35mRose : %s \e[0;m", VERSION, HostName, FlexId, NodeId, RoseId);
+ return 0;
+ }
+ if (check_perms(PERM_ANSI, 0L) == -1) {
+ axio_printf(NodeIo,"Shell : %s\nHostname : %s\nax25/Flex: %s\nNetRom : %s\nRose : %s", VERSION, HostName, FlexId, NodeId, RoseId);
+ return 0;
+ }
+ /*
+ if (User.ul_type != AF_NETROM) {
+ axio_printf(NodeIo, "Version : %s\nax25/Flex: %s\nNetRom : %s", VERSION, FlexId, NodeId);
+ return 0;
+ }
+ */
+ } else
+ axio_printf(NodeIo,"%s} ", NodeId);
+ if (check_perms(PERM_ANSI ,0L) != -1) {
+ axio_printf(NodeIo,"\e[01;37m");
+ }
+ axio_printf(NodeIo,"%s", VERSION);
+ node_msg("");
+ if (check_perms(PERM_ANSI ,0L) != -1) {
+ axio_printf(NodeIo,"\e[0;m");
+ }
+ return 0;
+}
+int nuser_list(int argc, char **argv)
+{
+ FILE *f;
+ struct user u;
+ struct tm *tp;
+ struct proc_nr_nodes *np;
+ char buf[80];
+ long l;
+ axio_puts("",NodeIo);
+ if ((f = fopen(DATA_NODE_LOGIN_FILE, "r")) == NULL) {
+ node_perror(DATA_NODE_LOGIN_FILE, errno);
+ return 0;
+ }
+ if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo, "%s} ", NodeId);
+ }
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[01;37m");
+ }
+ if (User.ul_type == AF_NETROM) {
+ /* axio_printf(NodeIo, "\e[0;m%s} %s", NodeId, VERSION); */
+ axio_printf(NodeIo, "%s", VERSION);
+ } else {
+ axio_printf(NodeIo, "Current users:");
+ }
+ if (user_count() == 0) {
+ axio_printf(NodeIo, " No users online.\n");
+ }
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo,"\e[0;m");
+ }
+ if (user_count() != 0) /* axio_printf(NodeIo,"") */ ;
+ while (fread(&u, sizeof(u), 1, f) == 1) {
+ if (u.pid == -1 || (kill(u.pid, 0) == -1 && errno == ESRCH))
+ continue;
+ switch (u.ul_type) {
+ case AF_FLEXNET:
+ sprintf(buf, "\nFlexNet (%.9s)",
+ u.call);
+ break;
+ case AF_AX25:
+ sprintf(buf, "\nUplink (%.9s on interface %.10s)",
+ u.call, u.ul_name);
+ break;
+ case AF_NETROM:
+ if ((np = find_node(u.ul_name, NULL)) != NULL) {
+ sprintf(buf, "\nCircuit (%.9s %.18s)",
+ u.call,
+ print_node(np->alias, np->call));
+ } else {
+ sprintf(buf, "\nCircuit (%.9s %.18s)",
+ u.call, u.ul_name);
+ }
+ break;
+#ifdef HAVE_ROSE
+ case AF_ROSE:
+ sprintf(buf, "\nROSE (%.9s %.18s)",
+ u.call, u.ul_name);
+ break;
+#endif
+ case AF_INET:
+ sprintf(buf, "\nTelnet (%.9s @ %.16s)",
+ u.call, u.ul_name);
+ break;
+ case AF_UNSPEC:
+ sprintf(buf, "\nHost (%.9s on local)",
+ u.call);
+ break;
+ default:
+ sprintf(buf, "\n?????? (%.9s %.18s)",
+ u.call, u.ul_name);
+ break;
+ }
+ axio_printf(NodeIo,"%-37.37s ", buf);
+ switch (u.state) {
+ case STATE_QUIT:
+ logout_user();
+ break;
+ case STATE_LOGIN:
+ axio_puts(" -> Logging in",NodeIo);
+ break;
+ case STATE_IDLE:
+ time(&l);
+ l -= u.cmdtime;
+ tp = gmtime(&l);
+ axio_printf(NodeIo," -> Idle (%d:%02d:%02d:%02d)",
+ tp->tm_yday, tp->tm_hour,
+ tp->tm_min, tp->tm_sec);
+ break;
+ case STATE_TRYING:
+ switch (u.dl_type) {
+ case AF_FLEXNET:
+ axio_printf(NodeIo," -> Trying (%s)",
+ u.dl_name);
+ break;
+ case AF_AX25:
+ axio_printf(NodeIo," -> Trying (%s on interface %s)",
+ u.dl_name, u.dl_port);
+ break;
+ case AF_NETROM:
+ axio_printf(NodeIo," -> Trying (%s)",
+ u.dl_name);
+ break;
+#ifdef HAVE_ROSE
+ case AF_ROSE:
+ axio_printf(NodeIo," -> Trying (%s)",
+ u.dl_name);
+ break;
+#endif
+ case AF_INET:
+ axio_printf(NodeIo," -> Trying (%s:%s)",
+ u.dl_name, u.dl_port);
+ break;
+ default:
+ axio_puts(" -> ???",NodeIo);
+ break;
+ }
+ break;
+ case STATE_CONNECTED:
+ switch (u.dl_type) {
+ case AF_FLEXNET:
+ axio_printf(NodeIo,"<--> FlexNet (%s)",
+ u.dl_name);
+ break;
+ case AF_AX25:
+ axio_printf(NodeIo,"<--> Downlink (%s on interface %s)",
+ u.dl_name, u.dl_port);
+ break;
+ case AF_NETROM:
+ axio_printf(NodeIo,"<--> Circuit (%s)",
+ u.dl_name);
+ break;
+#ifdef HAVE_ROSE
+ case AF_ROSE:
+ axio_printf(NodeIo,"<--> ROSE (%s)",
+ u.dl_name);
+ break;
+#endif
+ case AF_INET:
+ axio_printf(NodeIo,"<--> Telnet (%s:%s)",
+ u.dl_name, u.dl_port);
+ break;
+ default:
+ axio_printf(NodeIo,"<--> ???");
+ break;
+ }
+ break;
+ case STATE_PINGING:
+ axio_printf(NodeIo,"<--> Pinging (%s)", u.dl_name);
+ break;
+ case STATE_EXTCMD:
+ axio_printf(NodeIo,"<--> Extcmd (%s)", u.dl_name);
+ break;
+ }
+ axio_puts("",NodeIo);
+ }
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ fclose(f);
+ return 0;
+}
diff --git a/config.c b/config.c
new file mode 100644
index 0000000..f222db6
--- /dev/null
+++ b/config.c
@@ -0,0 +1,485 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <pwd.h>
+#include <netax25/ax25.h> /* axutils.h needs this... */
+#include <netrose/rose.h>
+#include <netax25/axlib.h>
+#include <netax25/axconfig.h>
+
+#include "node.h"
+
+long IdleTimeout = 360L; /* default to 6 mins */
+long ConnTimeout = 300L; /* default to 5 mins */
+int ReConnectTo = 0;
+int LogLevel = LOGLVL_ERROR;
+int EscChar = 20; /* CTRL-T */
+
+char *Email = NULL;
+char *HostName = NULL;
+char *NodeId = NULL;
+char *NrPort = NULL; /* first netrom port */
+char *FlexId = NULL;
+char *RoseId = NULL;
+
+#ifdef HAVEMOTD
+char *Prompt = "\n=> "; /* Prompt by IZ5AWZ */
+#else
+char *Prompt = "\n";
+#endif
+char *PassPrompt = "\nPassword >"; /* Prompt Password by IZ5AWZ */
+
+static unsigned long Permissions = 0L;
+static unsigned long LocalNet = 0L;
+static unsigned long LocalMask = ~0L;
+static char *HiddenPorts[32] = {0};
+
+/*
+ * Return non-zero if `port' is a hidden port.
+ */
+int is_hidden(const char *port)
+{
+ int i;
+
+ for (i = 0; HiddenPorts[i] != NULL && i < 31; i++)
+ if (!strcmp(port, HiddenPorts[i]))
+ return 1;
+ return 0;
+}
+
+/*
+ * Return non-zero if peer is on "local" or loopback network.
+ */
+static int is_local(unsigned long peer)
+{
+ return ((peer & LocalMask) == LocalNet) || ((peer & 0xff) == 127);
+}
+
+/*
+ * Return non-zero if peer is on amprnet.
+ */
+static int is_ampr(unsigned long peer)
+{
+ return ((peer & 0xff) == 44);
+}
+
+/*
+ * Convert NOS style width to a netmask in network byte order.
+ */
+static unsigned long bits_to_mask(int bits)
+{
+ return htonl(~0L << (32 - bits));
+}
+
+int check_perms(int what, unsigned long peer)
+{
+ if (what == PERM_TELNET) {
+ if (is_local(peer)) {
+ if (Permissions & PERM_TELNET_LOCAL)
+ return 0;
+ } else if (is_ampr(peer)) {
+ if (Permissions & PERM_TELNET_AMPR)
+ return 0;
+ } else {
+ if (Permissions & PERM_TELNET_INET)
+ return 0;
+ }
+ return -1;
+ }
+ if ((Permissions & what) == 0) {
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * Read permissions file and return a password if needed or "*" if not.
+ * If user access is denied return NULL.
+ */
+char *read_perms(struct user *up, unsigned long peer)
+{
+ FILE *fp;
+ char line[256], *argv[32], *cp;
+ int argc, n = 0;
+
+ if ((fp = fopen(CONF_NODE_PERMS_FILE, "r")) == NULL) {
+ node_perror(CONF_NODE_PERMS_FILE, errno);
+ return NULL;
+ }
+ if ((cp = strchr(up->call, '-')) != NULL)
+ *cp = 0;
+ while (fgets(line, 256, fp) != NULL) {
+ n++;
+ argc = parse_args(argv, line);
+ if (argc == 0 || *argv[0] == '#')
+ continue;
+ if (argc != 5) {
+ node_msg("Configuration error");
+ node_log(LOGLVL_ERROR, "Syntax error in permission file at line %d", n);
+ break;
+ }
+ if (strcmp(argv[0], "*") && strcasecmp(argv[0], up->call))
+ continue;
+ switch (up->ul_type) {
+ case AF_FLEXNET:
+ if (!strcmp(argv[1], "*"))
+ break;
+ if (!strcasecmp(argv[1], "flexnet"))
+ break;
+ continue;
+ case AF_AX25:
+ if (!strcmp(argv[1], "*"))
+ break;
+ if (!strcasecmp(argv[1], "ax25"))
+ break;
+ continue;
+ case AF_NETROM:
+ if (!strcmp(argv[1], "*"))
+ break;
+ if (!strcasecmp(argv[1], "netrom"))
+ break;
+ continue;
+#ifdef HAVE_ROSE
+ case AF_ROSE:
+ if (!strcmp(argv[1], "*"))
+ break;
+ if (!strcasecmp(argv[1], "rose"))
+ break;
+ continue;
+#endif
+ case AF_INET:
+ if (!strcmp(argv[1], "*"))
+ break;
+ if (!strcasecmp(argv[1], "local") && is_local(peer))
+ break;
+ if (!strcasecmp(argv[1], "ampr") && is_ampr(peer))
+ break;
+ if (!strcasecmp(argv[1], "inet") && !is_local(peer) && !is_ampr(peer))
+ break;
+ continue;
+ case AF_UNSPEC:
+ if (!strcmp(argv[1], "*"))
+ break;
+ if (!strcasecmp(argv[1], "host"))
+ break;
+ continue;
+ }
+ if (up->ul_type == AF_AX25) {
+ if (strcmp(argv[2], "*") && strcmp(argv[2], up->ul_name))
+ continue;
+ }
+ if (cp != NULL)
+ *cp = '-';
+ if ((Permissions = strtoul(argv[4], NULL, 10)) == 0)
+ return NULL;
+ else
+ return strdup(argv[3]);
+ }
+ return NULL;
+}
+
+static int do_alias(int argc, char **argv)
+{
+ struct cmd *new;
+ int len = 0;
+
+ if (argc < 3)
+ return -1;
+ if ((new = calloc(1, sizeof(struct cmd))) == NULL) {
+ node_perror("do_alias: malloc", errno);
+ return -2;
+ }
+ new->name = strdup(argv[1]);
+ while (isupper(new->name[len]))
+ len++;
+ /* Ok. So they can't read... */
+ if (len == 0) {
+ strupr(new->name);
+ len = strlen(new->name);
+ }
+ new->len = len;
+ new->command = strdup(argv[2]);
+ new->type = CMD_ALIAS;
+ insert_cmd(&Nodecmds, new);
+ return 0;
+}
+
+static int do_loglevel(int argc, char **argv)
+{
+ if (argc < 2)
+ return -1;
+ LogLevel = atoi(argv[1]);
+ return 0;
+}
+
+int get_escape(char *s)
+{
+ int escape;
+ char *endptr[1];
+
+ if (isdigit(*s)) {
+ escape = strtol(s, endptr, 0);
+ if (**endptr)
+ return -2;
+ else
+ return escape;
+ }
+
+ if (strlen(s) == 1)
+ return *s;
+
+ if (strlen(s) == 2 && *s == '^')
+ return (toupper(*++s) - 'A' + 1);
+
+ if (strcasecmp(s, "off") == 0 || strcmp(s, "-1") == 0)
+ return -1;
+
+ return -2;
+}
+
+
+static int do_escapechar(int argc, char **argv)
+{
+ if (argc < 2)
+ return -1;
+
+ EscChar = get_escape(argv[1]);
+
+ if (EscChar < -1 || EscChar > 255) {
+ node_msg("Configuration error");
+ node_log(LOGLVL_ERROR, "do_escapechar: Invalid escape character %s",
+ argv[1]);
+ return -2;
+ }
+
+ return 0;
+}
+
+static int do_idletimeout(int argc, char **argv)
+{
+ if (argc < 2)
+ return -1;
+ IdleTimeout = atol(argv[1]);
+ return 0;
+}
+
+static int do_conntimeout(int argc, char **argv)
+{
+ if (argc < 2)
+ return -1;
+ ConnTimeout = atol(argv[1]);
+ return 0;
+}
+
+static int do_hostname(int argc, char **argv)
+{
+ if (argc < 2)
+ return -1;
+ HostName = strdup(argv[1]);
+ return 0;
+}
+
+static int do_localnet(int argc, char **argv)
+{
+ char *cp;
+
+ if (argc < 2)
+ return -1;
+ if ((cp = strchr(argv[1], '/')) != NULL) {
+ *cp = 0;
+ LocalMask = bits_to_mask(atoi(++cp));
+ }
+ LocalNet = inet_addr(argv[1]);
+ LocalNet &= LocalMask;
+ return 0;
+}
+
+static int do_reconnect(int argc, char **argv)
+{
+#ifdef HAVEMOTD
+ if (argc < 2)
+ return -1;
+ if (!strcasecmp(argv[1], "on"))
+ ReConnectTo = 1;
+ else
+#endif
+ ReConnectTo = 0;
+ return 0;
+}
+
+static int do_hiddenports(int argc, char **argv)
+{
+ int i;
+
+ if (argc < 2)
+ return -1;
+ for (i = 1; i < argc && i < 31; i++) {
+ if (ax25_config_get_dev(argv[i]) == NULL) {
+ node_msg("Configuration error");
+ node_log(LOGLVL_ERROR, "do_hiddenports: invalid port %s", argv[i]);
+ return -2;
+ }
+ HiddenPorts[i - 1] = strdup(argv[i]);
+ }
+ HiddenPorts[i - 1] = NULL;
+ return 0;
+}
+
+static int do_extcmd(int argc, char **argv)
+{
+ struct cmd *new;
+ struct passwd *pw;
+ char buf[1024];
+ int i, len;
+
+ if (argc < 6)
+ return -1;
+ if ((new = calloc(1, sizeof(struct cmd))) == NULL) {
+ node_perror("do_extcmd: malloc", errno);
+ return -2;
+ }
+ new->name = strdup(argv[1]);
+ len = 0;
+ while (isupper(new->name[len]))
+ len++;
+ /* Ok. So they can't read... */
+ if (len == 0) {
+ strupr(new->name);
+ len = strlen(new->name);
+ }
+ new->len = len;
+ new->flags = atoi(argv[2]);
+ if ((pw = getpwnam(argv[3])) == NULL) {
+ node_msg("Configuration error");
+ node_log(LOGLVL_ERROR, "do_extcmd: Unknown user %s", argv[3]);
+ return -2;
+ }
+ new->uid = pw->pw_uid;
+ new->gid = pw->pw_gid;
+ new->path = strdup(argv[4]);
+ len = 0;
+ for (i = 0; argv[i + 5] != NULL; i++) {
+ sprintf(&buf[len], "\"%s\" ", argv[i + 5]);
+ len = strlen(buf);
+ }
+ new->command = strdup(buf);
+ new->type = CMD_EXTERNAL;
+ insert_cmd(&Nodecmds, new);
+ return 0;
+}
+
+static int do_nodeid(int argc, char **argv)
+{
+ if (User.ul_type == AF_NETROM) {
+ if (argc < 2)
+ return -1;
+ NodeId = strdup(argv[1]);
+ } else if (User.ul_type != AF_NETROM) {
+ NodeId = strdup(argv[1]);
+ }
+ return 0;
+}
+
+static int do_flexid(int argc, char **argv)
+{
+ if (argc < 2 )
+ return -1;
+ FlexId = ("%s ;" , strdup(argv[1]));
+ return 0;
+}
+
+static int do_roseid(int argc, char **argv)
+{
+ if (argc < 2 )
+ return -1;
+ RoseId = ("%s ;" , strdup(argv[1]));
+ return 0;
+}
+
+static int do_prompt(int argc, char **argv)
+{
+ if ((User.ul_type != AF_NETROM) || (User.ul_type != AF_INET)) {
+ if (argc < 2) {
+ return -1;
+ Prompt = strdup(argv[1]);
+ return 0;
+ }
+ }
+}
+
+static int do_passprompt(int argc, char **argv)
+{
+ if (User.ul_type != AF_NETROM) {
+ if (argc < 2)
+ return -1;
+ PassPrompt = strdup(argv[1]);
+ return 0;
+ }
+}
+
+static int do_nrport(int argc, char **argv)
+{
+ if (argc < 2)
+ return -1;
+ NrPort = strdup(argv[1]);
+ return 0;
+}
+
+static int do_email(int argc, char **argv)
+{
+ if (argc < 2)
+ return -1;
+ Email = strdup(argv[1]);
+ return 0;
+}
+
+int read_config(void)
+{
+ struct cmd *cfg_cmds = NULL;
+ FILE *fp;
+ char line[256];
+ int ret, n = 0;
+
+ add_internal_cmd(&cfg_cmds, "alias", 5, do_alias);
+ add_internal_cmd(&cfg_cmds, "conntimeout", 11, do_conntimeout);
+ add_internal_cmd(&cfg_cmds, "email", 5, do_email);
+ add_internal_cmd(&cfg_cmds, "escapechar", 10, do_escapechar);
+ add_internal_cmd(&cfg_cmds, "extcmd", 6, do_extcmd);
+ add_internal_cmd(&cfg_cmds, "hiddenports", 11, do_hiddenports);
+ add_internal_cmd(&cfg_cmds, "hostname", 8, do_hostname);
+ add_internal_cmd(&cfg_cmds, "idletimeout", 11, do_idletimeout);
+ add_internal_cmd(&cfg_cmds, "localnet", 8, do_localnet);
+ add_internal_cmd(&cfg_cmds, "loglevel", 8, do_loglevel);
+ add_internal_cmd(&cfg_cmds, "nodeid", 6, do_nodeid);
+ add_internal_cmd(&cfg_cmds, "flexid", 6, do_flexid);
+ add_internal_cmd(&cfg_cmds, "roseid", 6, do_roseid);
+ add_internal_cmd(&cfg_cmds, "prompt", 6, do_prompt);
+ add_internal_cmd(&cfg_cmds, "nrport", 6, do_nrport);
+ add_internal_cmd(&cfg_cmds, "reconnect", 8, do_reconnect);
+ add_internal_cmd(&cfg_cmds, "passprompt", 6, do_passprompt);
+
+ if ((fp = fopen(CONF_NODE_FILE, "r")) == NULL) {
+ node_perror(CONF_NODE_FILE, errno);
+ return -1;
+ }
+ while (fgets(line, 256, fp) != NULL) {
+ n++;
+ ret = cmdparse(cfg_cmds, line);
+ if (ret == -1) {
+ node_msg("Configuration error");
+ node_log(LOGLVL_ERROR, "Syntax error in config file at line %d: %s", n, line);
+ }
+ if (ret < 0) {
+ fclose(fp);
+ return -1;
+ }
+ }
+ fclose(fp);
+ free_cmdlist(cfg_cmds);
+ cfg_cmds = NULL;
+ return 0;
+}
diff --git a/config.h.in b/config.h.in
new file mode 100644
index 0000000..76a7e9e
--- /dev/null
+++ b/config.h.in
@@ -0,0 +1,36 @@
+#ifndef CONFIG_H
+#define CONFIG_H
+
+/*
+ * Some global #defines for programmers to use for conditional compilation
+ */
+ at HAVEAX25@
+ at HAVEFLEX@
+ at HAVEROSE@
+ at HAVENETROM@
+ at HAVEZLIB@
+ at HAVEMHEARD@
+ at HAVETCPIP@
+#define PROC_AX25_CALLS_FILE "/proc/net/ax25_calls"
+
+/*
+ * node specific
+ */
+#define CONF_NODE_FILE "@ETC_DIR@/uronode.conf"
+#define CONF_NODE_PERMS_FILE "@ETC_DIR@/uronode.perms"
+ at HAVEMOTD@ @MOTDPATH@
+#define CONF_NODE_INFO_FILE "@ETC_DIR@/uronode.info"
+#define AX_ROUTES_FILE "@ETC_DIR@/uronode.routes"
+#define CONF_USERS_FILE "@ETC_DIR@/uronode.users"
+#define FLEXD_CONF_FILE "@ETC_DIR@/flexd.conf"
+#define FLEXD_TEMP_PATH "@VAR_DIR@/flex/"
+#define FLEXD_PID_FILE "/var/run/flexd.pid"
+#define FLEX_GT_FILE "@VAR_DIR@/flex/gateways"
+#define FLEX_DST_FILE "@VAR_DIR@/flex/destinations"
+#define DATA_MHEARD_FILE "@VAR_DIR@/mheard/mheard.dat"
+#define DATA_NODE_LOGIN_FILE "@VAR_DIR@/node/loggedin"
+#define DATA_NODE_HELP_DIR "@VAR_DIR@/node/help/"
+#define DATA_NODE_LAST_FILE "@VAR_DIR@/node/lastlog"
+#define DATA_NODE_IP_FILE "@VAR_DIR@/node/iplog"
+
+#endif
diff --git a/configure b/configure
new file mode 100755
index 0000000..68fde56
--- /dev/null
+++ b/configure
@@ -0,0 +1,303 @@
+#!/bin/sh
+
+_sleep()
+{
+ [ "$NON_INTERACTIVE" = 1 ] || sleep "$@"
+}
+
+_whiptail()
+{
+ [ "$NON_INTERACTIVE" = 1 ] || whiptail "$@"
+}
+
+echo "Cleaning the directory for a fresh configuration..."
+_sleep 2
+make distclean > make.debug
+
+ETC_DIR=/usr/local/etc/ax25
+SBIN_DIR=/usr/local/sbin
+BIN_DIR=/usr/local/bin
+LIB_DIR=/usr/local/lib
+MAN_DIR=/usr/local/share/man
+VAR_DIR=/usr/local/var/ax25
+
+echo "Welcome to the configuration utility for URONode. This configure script"
+echo "will very simply and easily guide you into installling URONode with as"
+echo "very little trouble as possible. All you need to really do is simply"
+echo "answer the following questions below properly. If you make a mistake"
+echo "just break out of it (ctrl+c) and rerun ./configure. Let's get started!"
+_sleep 1
+echo " "
+_sleep 1
+echo -n "you need gcc to build URONode: "
+GCC=`which gcc`
+_sleep 2
+if [ -e "$GCC" ]
+ then
+ echo -n "saw $GCC... "
+ _sleep 1
+ echo "GCC found! Congratulations!!"
+else
+ echo "gcc not found!"
+ echo " "
+ echo "You need this compiler to build URONode."
+ echo "Please install gcc, and rerun this ./configure script."
+ echo "If you have a copy of gcc installed, please insure you have a"
+ echo "symlink by typing as root: ln -s /usr/bin/gcc-#.## /usr/bin/gcc"
+ echo "and rerun ./configure to continue."
+ exit 1
+fi
+echo -n "Your machine architecture is: "
+_sleep 1
+ARCH=`uname -m`
+echo $ARCH
+_sleep 1
+echo -n "Checking for the existence of the Zlib headers... "
+ZLIB=""
+HAVEZLIB="#undef HAVE_ZLIB"
+for zlibdir in /usr/include /usr/local/include
+do
+ if [ -f $zlibdir/zlib.h ]
+ then
+ echo $zlibdir/zlib.h
+ ZLIB="-lz"
+ HAVEZLIB="#define HAVE_ZLIB 1"
+ fi
+done
+if [ -z "$ZLIB" ]
+then
+ echo "not found."
+ echo " Without Zlib Node will lack compression support"
+ echo " See INSTALL for more information."
+ echo
+fi
+
+# Global protocol definition symbols for programmers that want to conditionally
+# compile
+ HAVEAX25="#undef HAVE_AX25"
+ HAVEFLEX="#undef HAVE_FLEX"
+ FLEXNET=" "
+ IN="#"
+ HAVENETROM="#undef HAVE_NETROM"
+ HAVEROSE="#undef HAVE_ROSE"
+ HAVEMHEARD="#undef HAVE_MHEARD"
+ HAVETCPIP="#undef HAVE_TCPIP"
+ HAVEMOTD="#undef HAVE_MOTD"
+ MOTDPATH=
+# echo -n "Include support for the AX.25 protocol ? [Y/n]: "; read answer
+# if [ "$answer" = "Y" -o "$answer" = "y" -o "$answer" = "" ]
+ if [ "$NON_INTERACTIVE" = 1 ]
+ then
+ echo "$@" | grep -vqe "--without-ax25"
+ else
+ whiptail --title "URONode Options:" --yesno "Support AX25?" 7 22
+ fi
+ if [ $? -ne 1 ]
+ then
+ HAVEAX25="#define HAVE_AX25 1"
+ fi
+ #
+# echo -n "Include support for the FlexNet protocol ? [Y/n]: "; read answer
+# if [ "$answer" = "Y" -o "$answer" = "y" -o "$answer" = "" ]
+
+ if [ "$NON_INTERACTIVE" = 1 ]
+ then
+ echo "$@" | grep -vqe "--without-flexnet"
+ else
+ whiptail --title "URONode Options:" --yesno "Support FlexNet?" 7 22
+ fi
+ if [ $? -ne 1 ]
+ then
+ HAVEAX25="#define HAVE_AX25 1"
+ HAVEFLEX="#define HAVE_FLEX 1"
+ FLEXNET="flexd"
+ IN=""
+ fi
+ #
+# echo -n "Include support for the NetRom protocol ? [Y/n]: "; read answer
+# if [ "$answer" = "Y" -o "$answer" = "y" -o "$answer" = "" ]
+ if [ "$NON_INTERACTIVE" = 1 ]
+ then
+ echo "$@" | grep -vqe "--without-netrom"
+ else
+ whiptail --title "URONode Options:" --yesno "Support NetRom?" 7 22
+ fi
+ if [ $? -ne 1 ]
+ then
+ HAVEAX25="#define HAVE_AX25 1"
+ HAVENETROM="#define HAVE_NETROM 1"
+ fi
+ #
+# echo -n "Include support for the Rose protocol ? [Y/n]: "; read answer
+# if [ "$answer" = "Y" -o "$answer" = "y" -o "$answer" = "" ]
+ if [ "$NON_INTERACTIVE" = 1 ]
+ then
+ echo "$@" | grep -vqe "--without-rose"
+ else
+ whiptail --title "URONode Options:" --yesno "Support ROSE?" 7 22
+ fi
+ if [ $? -ne 1 ]
+ then
+ HAVEAX25="#define HAVE_AX25 1"
+ HAVEROSE="#define HAVE_ROSE 1"
+ fi
+ #
+# echo -n "Include support for MHeard ports listen ? [Y/n]: "; read answer
+# if [ "$answer" = "Y" -o "$answer" = "y" -o "$answer" = "" ]
+ if [ "$NON_INTERACTIVE" = 1 ]
+ then
+ echo "$@" | grep -vqe "--without-mheard"
+ else
+ whiptail --title "URONode Options:" --yesno "Support MHeard?" 7 22
+ fi
+ if [ $? -ne 1 ]
+ then
+ HAVEAX25="#define HAVE_AX25 1"
+ HAVEMHEARD="#define HAVE_MHEARD 1"
+ fi
+ #
+# echo -n "Include support for TCP/IP functions ? [Y/n]: "; read answer
+# if [ "$answer" = "Y" -o "$answer" = "y" -o "$answer" = "" ]
+ if [ "$NON_INTERACTIVE" = 1 ]
+ then
+ echo "$@" | grep -vqe "--without-tcpip"
+ else
+ whiptail --title "URONode Options:" --yesno "Support TCP/IP?" 7 22
+ fi
+ if [ $? -ne 1 ]
+ then
+ HAVETCPIP="#define HAVE_TCPIP 1"
+ HAVEMOTD="#define HAVEMOTD"
+ MOTDPATH='"/etc/ax25/uronode.motd"'
+ fi
+
+echo "Creating Makefile"
+
+sed -e "s~@FLEXNET@~$FLEXNET~g; \
+ s~@IN@~$IN~g" <Makefile.in > Makefile
+
+echo "Creating Makefile.include"
+
+sed -e "s~@ARCH@~$ARCH~g; \
+ s~@ETC_DIR@~$ETC_DIR~g; \
+ s~@LIB_DIR@~$LIB_DIR~g; \
+ s~@SBIN_DIR@~$SBIN_DIR~g; \
+ s~@BIN_DIR@~$BIN_DIR~g; \
+ s~@VAR_DIR@~$VAR_DIR~g; \
+ s~@MAN_DIR@~$MAN_DIR~g; \
+ s~@ZLIB@~$ZLIB~g" <Makefile.include.in >Makefile.include
+
+echo "Creating config.h"
+
+sed -e "s~@ETC_DIR@~$ETC_DIR~g; \
+ s~@LIB_DIR@~$LIB_DIR~g; \
+ s~@SBIN_DIR@~$SBIN_DIR~g; \
+ s~@BIN_DIR@~$BIN_DIR~g; \
+ s~@VAR_DIR@~$VAR_DIR~g; \
+ s~@MAN_DIR@~$MAN_DIR~g; \
+ s~@HAVEAX25@~$HAVEAX25~g; \
+ s~@HAVEFLEX@~$HAVEFLEX~g; \
+ s~@HAVENETROM@~$HAVENETROM~g; \
+ s~@HAVEROSE@~$HAVEROSE~g; \
+ s~@HAVEMHEARD@~$HAVEMHEARD~g; \
+ s~@HAVETCPIP@~$HAVETCPIP~g; \
+ s~@HAVEMOTD@~$HAVEMOTD~g; \
+ s~@MOTDPATH@~$MOTDPATH~g; \
+ s~@HAVEZLIB@~$HAVEZLIB~g" <config.h.in >config.h
+
+echo "Creating dependancy files..."
+make depend > /dev/null 2>&1
+echo "Configuration successful!!"
+_sleep 1
+echo "about the authors..."
+_sleep 3
+echo "URONode is a combined effort of years worth of work. Those who's code"
+echo "is included in this flavor of a linux based node are:"
+_sleep 1
+echo "Brian Rogers N1URO (current maintainer), "
+_sleep 1
+echo "Marius Petrescu YO2LOJ (current team member),"
+_sleep 1
+echo "Bob Tenty VE3TOK (current team member),"
+_sleep 1
+echo "Stefano Noferi IZ5AWZ (AWZNode)"
+_sleep 1
+echo -n "Tomi Manninen OH2BNS, "
+_sleep 1
+echo -n "Alan Cox GW4PTS, "
+_sleep 1
+echo "and Roy Van Zundert PE1RJA"
+echo ""
+_sleep 1
+echo "Special thanks to: Morgan, sm6tky for his security report"
+echo "and Barry K2MF for his input on some of my routines and supplying"
+echo "some source code."
+_sleep 1
+echo ""
+#echo -n "Shall I run the make command for you ? [Y/n]: "
+ _whiptail --title "Shall I make URONode?" --yesno "Yes to make or No to exit" 7 30
+# if [ "$answer" = "Y" -o "$answer" = "y" -o "$answer" = "" ]
+ if [ "$NON_INTERACTIVE" != 1 -a $? -ne 1 ]
+ then
+# echo "Making URONode! Please be patient."
+# _sleep 1
+# echo "compile errors will be in make.debug."
+# echo ""
+# _sleep 1
+# echo "You may not see anything until the process is complete..."
+ _whiptail --title "Making URONODE..." --msgbox "Making. Check make.debug for errors. Hit OK to continue. You may not see anything for a minute..." 10 45
+ make >> make.debug
+ echo "let's check for binary errors..."
+ _sleep 1
+ echo -n "nodeusers: "
+ _sleep 1
+ if [ -x ./nodeusers ]; then
+ echo "SUCCESS!"
+ else
+ echo "FAILED!"
+ fi
+ _sleep 1
+ echo -n "uronode: "
+ _sleep 1
+ if [ -x ./uronode ]; then
+ echo "SUCCESS!"
+ else
+ echo "FAILED!"
+ fi
+ _sleep 1
+ echo -n "axdigi: "
+ _sleep 1
+ if [ -x ./axdigi ]; then
+ echo "SUCCESS!"
+ fi
+ _sleep 1
+ echo -n "flexd: "
+ _sleep 1
+ if [ -x ./flexd ]; then
+ echo "SUCCESS!"
+ _sleep 1
+ else
+ echo "FAILED! - perhaps you didn't want flexnet?"
+ echo "This is not an error if you chose NO to flexnet."
+ echo "This only means the flexnet daemon binary was not found."
+ echo ""
+ echo "Process complete!"
+ echo ""
+ fi
+ _sleep 1
+ _whiptail --title "URONode" --msgbox "Check the file make.debug if you had errors. If no errors, type: make install (new install) or make upgrade (existing install) and edit your files in /usr/local/etc/ax25/\n\n**WARNING: if you haven't already, add the following to your startup scripts:\n/usr/local/sbin/axdigi & \nto insure cross-port digipeating.\n\nFor help and release news join the forum at\nhttps://www.n1uro.net/forum\n\nEnjoy URONode - 73 de Brian N1URO" 20 50
+
+# echo "Check the file make.debug if you had errors."
+# echo "If no errors, type: make install or make upgrade"
+# echo "and edit your files in /etc/ax25/"
+# echo "**WARNING: if you haven't already, add the following to your"
+# echo "startup scripts:"
+# echo "/usr/sbin/axdigi &"
+# echo "to insure cross-port digipeating."
+# echo ""
+# echo "For support and release news join the forum"
+# echo "at https://www.n1uro.net/forum"
+# echo ""
+# echo "Enjoy URONode! 73 de N1URO."
+ fi
+exit 0
diff --git a/etc/axdigi.conf b/etc/axdigi.conf
new file mode 100644
index 0000000..55c809d
--- /dev/null
+++ b/etc/axdigi.conf
@@ -0,0 +1,20 @@
+# URONode axdigi module
+# load using /usr/sbin/axdigi &
+#
+#print debuginfo on/off
+Debug off
+#
+#The digi call
+MyCall xx0xx
+#
+# on use ssid 0-15 for digicall ,off use only ssid of mycall
+IgnoreSSID on
+#
+#number of entrys for autorouting
+lookupsize 100
+#
+#timeout auto routing data in sec.
+TIMEOUT 3600
+#
+DefaultPort ln.tue
+#
diff --git a/etc/flexd.conf b/etc/flexd.conf
new file mode 100644
index 0000000..b9e9190
--- /dev/null
+++ b/etc/flexd.conf
@@ -0,0 +1,14 @@
+# /etc/ax25/flexd.conf URONode example configuration file
+# see man flexd.conf
+
+# The callsign-ssid you wish to poll your flex neighbor with:
+
+MyCall xx0xx
+
+# How often do we poll our flex neighbor (in seconds):
+
+PollInterval 300
+
+# The FlexNet node we're to poll:
+
+FlexGate xx0xx-#
diff --git a/etc/gateways b/etc/gateways
new file mode 100644
index 0000000..e69de29
diff --git a/etc/help/bye.hlp b/etc/help/bye.hlp
new file mode 100644
index 0000000..9359a79
--- /dev/null
+++ b/etc/help/bye.hlp
@@ -0,0 +1,6 @@
+
+USAGE
+ Bye
+
+DESCRIPTION
+ Disconnects you from this node.
\ No newline at end of file
diff --git a/etc/help/color.hlp b/etc/help/color.hlp
new file mode 100644
index 0000000..443c251
--- /dev/null
+++ b/etc/help/color.hlp
@@ -0,0 +1,18 @@
+
+USAGE
+ <none>
+
+DESCRIPTION
+ Adds ANSI color to the system for you. Send a message to
+ the sysop and request that they add 512 to your permissions
+ flag for the interface(s) you connect in from to get the
+ color schema. You *must* use an ANSI compliant terminal such
+ as Qmodem, Telix, telnet, etc.
+ Interfaces available: Schema:
+ ax25 ax25 - yellow
+ netrom netrom - cyan
+ internet internet- magenta
+ amprnet system - white
+ localhost starts - green
+ stops - red
+ alarms - flashing red
diff --git a/etc/help/connect.hlp b/etc/help/connect.hlp
new file mode 100644
index 0000000..1fad0aa
--- /dev/null
+++ b/etc/help/connect.hlp
@@ -0,0 +1,25 @@
+
+USAGE
+ Connect <call | alias> [s|d] For NET/ROM or Links
+ Connect <intf> <call> [via <digi1> ...] [s|d] For AX25
+ Connect <call> <address> [<digi>] [d|s] For ROSE
+ Connect <destination> [s|d] For FlexNet
+
+DESCRIPTION
+ Initiates an AX25, NET/ROM, ROSE or Flexnet connection to a
+ remote host. If more than two parameters are entered and the
+ second parameter is ten charachers in length then it is
+ interpreted as a ROSE connection, otherwise the first
+ parameter is interpreted as a port name and AX25 is used
+ to make the connection via that port. If only one parameter
+ is given the connection is made searching for the callsign
+ in NET/ROM nodes, in AX25 Fixed links, in FlexNet destinations
+ and last in Mheard database in this order.
+
+ If a single `s' is entered as the last parameter, then when
+ the remote host disconnects you will be returned to this node.
+ If a single `d' is entered as the last parameter, you will
+ be disconnected from this node too. Default behaviour depends
+ on how the user connects in:
+ NetRom - defaults to disconnect
+ all others - defaults to reconnect
diff --git a/etc/help/desti.hlp b/etc/help/desti.hlp
new file mode 100644
index 0000000..5a92410
--- /dev/null
+++ b/etc/help/desti.hlp
@@ -0,0 +1,14 @@
+
+USAGE
+ Dest [*|<nodecall>]
+
+DESCRIPTION
+ Shows the FlexNet destination table of the local node. The
+ destinations on this list can be reached using the Connect
+ command without knowing the actual network path used
+ (assuming the network is OK).
+
+ The optional parameter * toggles verbose mode, showing the
+ ssid mask, the round-trip-time and the path used to reach each
+ node. You can also specify a node callsign to get the verbose
+ information for a single node.
\ No newline at end of file
diff --git a/etc/help/escape.hlp b/etc/help/escape.hlp
new file mode 100644
index 0000000..24f9bb4
--- /dev/null
+++ b/etc/help/escape.hlp
@@ -0,0 +1,16 @@
+
+USAGE
+ Escape <escape char>
+
+DESCRIPTION
+ Sets the character will be treated as the signal to close down any
+ open connection made from the node.
+
+ You can specify the escape character in a number of ways. They are:
+
+ <char> the actual binary character
+ ^T to set it to Control-T (or any other control character)
+ 0xNN to set it to hexadecimal value NN
+ 0NNN to set it to Octal value NNN
+ NNN to set it to decimal value NNN (no leading zero!)
+ -1 to disable this feature
\ No newline at end of file
diff --git a/etc/help/finger.hlp b/etc/help/finger.hlp
new file mode 100644
index 0000000..a5ac691
--- /dev/null
+++ b/etc/help/finger.hlp
@@ -0,0 +1,13 @@
+
+USAGE
+ Finger [<username>][@<hostname>]
+
+DESCRIPTION
+ Retrieves information about users of a system. If the user
+ name is omitted, shows the users currently logged on the
+ host. If the hostname is omitted, defaults to the local host.
+
+EXAMPLES
+ finger @aripisa.ampr.org
+ finger iz5awz at aripisa.ampr.org
+ finger iz5awz
\ No newline at end of file
diff --git a/etc/help/help.hlp b/etc/help/help.hlp
new file mode 100644
index 0000000..25afe58
--- /dev/null
+++ b/etc/help/help.hlp
@@ -0,0 +1,10 @@
+
+USAGE
+ Help [<command>]
+
+DESCRIPTION
+ Gives help for the specified command or this text if no
+ command is specified. Commands can not be abbreviated.
+ Use the "?" command to retrieve a list of available commands,
+ except for the COLOR command which you need to contact your
+ sysop to add. "Help color" to see about the color schema.
diff --git a/etc/help/host.hlp b/etc/help/host.hlp
new file mode 100644
index 0000000..cbf64fe
--- /dev/null
+++ b/etc/help/host.hlp
@@ -0,0 +1,11 @@
+
+USAGE
+ Host <hostname>|<ip address>
+
+DESCRIPTION
+ Tells information about an Internet host. The host can be identified
+ using a host name (for example, aripisa.ampr.org) or an IP
+ address (for example, 44.134.208.29).
+
+ Returns the host name, IP addresses and known aliases for the host.
+ The information is gathered from the DNS (domain name service).
\ No newline at end of file
diff --git a/etc/help/info.hlp b/etc/help/info.hlp
new file mode 100644
index 0000000..4ee8cb9
--- /dev/null
+++ b/etc/help/info.hlp
@@ -0,0 +1,8 @@
+
+USAGE
+ Info
+
+DESCRIPTION
+ Displays the version information and the contents of the
+ /etc/ax25/uronode.info file, which describes those aspects of
+ the system that the sysop likes to brag about.
diff --git a/etc/help/links.hlp b/etc/help/links.hlp
new file mode 100644
index 0000000..66480d3
--- /dev/null
+++ b/etc/help/links.hlp
@@ -0,0 +1,16 @@
+
+USAGE
+ Links [ d | n | v | <call>]
+
+DESCRIPTION
+ Shows the AX25 link table of the local node. The destinations
+ on this list can be reached using the Connect command without
+ knowing the actual network path used (assuming the network is OK).
+
+ The optional parameter d show the AX25 nodes directly linked.
+ The optional parameter n show the AX25 nodes linked connecting
+ another node and passing a string type "C XX0XX".
+ The optional parameter v show the AX25 links via digipeaters.
+
+ You can also specify a destination callsign to get the verbose
+ information for a single destination.
\ No newline at end of file
diff --git a/etc/help/mail.hlp b/etc/help/mail.hlp
new file mode 100644
index 0000000..003272c
--- /dev/null
+++ b/etc/help/mail.hlp
@@ -0,0 +1,12 @@
+
+USAGE
+ Mail
+
+DESCRIPTION
+ Access your mailbox and send mail to other users
+ if you have mail waiting.
+ (only available for sysops and some users).
+
+ Note: this feature is initially disabled, contact the sysop
+ if you like to have it enabled.
+
diff --git a/etc/help/message.hlp b/etc/help/message.hlp
new file mode 100644
index 0000000..44fe46d
--- /dev/null
+++ b/etc/help/message.hlp
@@ -0,0 +1,14 @@
+
+USAGE
+ MEssage <callsign or user at domain>
+
+DESCRIPTION
+
+ Send email to users (now only available for messages to sysop).
+ Note: sysop has to enable your mail flag for you to be able to
+ receive mail, otherwise you may only send from here.
+
+ *Sysop Note: use your adduser or userconf program and create
+ the users account as well as adding the mail flag to the
+ configuration file. Select: /bin/false for a shell.
+
diff --git a/etc/help/mheard.hlp b/etc/help/mheard.hlp
new file mode 100644
index 0000000..4a08386
--- /dev/null
+++ b/etc/help/mheard.hlp
@@ -0,0 +1,8 @@
+
+USAGE
+ Mheard [<port>]
+
+DESCRIPTION
+ Gives a list of heard AX25 stations on all ports and, if
+ specified, on the specified port.
+ Use the "Ports" command to get a list of available ports.
\ No newline at end of file
diff --git a/etc/help/msg.hlp b/etc/help/msg.hlp
new file mode 100644
index 0000000..1700183
--- /dev/null
+++ b/etc/help/msg.hlp
@@ -0,0 +1,15 @@
+
+USAGE
+ MSg <call> <message>
+
+DESCRIPTION
+ Sends a one-line message to another user of the node. The user
+ in question must be in idle state (ie. not connected/connecting
+ anywhere or running a program).
+
+ If the user has an SSID other than zero, the SSID must be
+ specified. If multiple users are logged in with the same
+ callsign/SSID pair, those who are in idle state, get the message.
+
+EXAMPLES
+ msg k2mf Hello, Bawee!
diff --git a/etc/help/netstat.hlp b/etc/help/netstat.hlp
new file mode 100644
index 0000000..54f598a
--- /dev/null
+++ b/etc/help/netstat.hlp
@@ -0,0 +1,7 @@
+
+USAGE
+ NEtstat
+
+DESCRIPTION
+ Gives a list of active TCP/IP connections to and from the local
+ host.
\ No newline at end of file
diff --git a/etc/help/nodes.hlp b/etc/help/nodes.hlp
new file mode 100644
index 0000000..93005de
--- /dev/null
+++ b/etc/help/nodes.hlp
@@ -0,0 +1,15 @@
+
+USAGE
+ Nodes [*|<nodecall>]
+
+DESCRIPTION
+ Shows the NET/ROM node table of the local host. The nodes on this
+ list can be reached using the Connect command without knowing the
+ actual network path used (assuming the network is OK).
+
+ The optional parameter * toggles verbose mode, showing the
+ Obsolescence counter, relative path quality and the port and
+ neighbour node used to reach each node. You can also specify
+ a node callsign to get the verbose information for a single node.
+ In that case a "which" field that tells what route the kernel
+ will use to reach the node is shown.
diff --git a/etc/help/ping.hlp b/etc/help/ping.hlp
new file mode 100644
index 0000000..30eb4ac
--- /dev/null
+++ b/etc/help/ping.hlp
@@ -0,0 +1,15 @@
+
+USAGE
+ PIng <hostname> [<length>]
+
+DESCRIPTION
+ Checks if a host can be reached trough the network by sending
+ an ICMP Echo Request packet to the host and waiting for it to
+ reply. If a reply is received the round-trip-time (RTT)
+ between the local and remote hosts is shown.
+
+ If an optional length is specified the data portion of the
+ packet is filled with length number of bytes.
+
+EXAMPLE
+ ping aripisa.ampr.org
diff --git a/etc/help/ports.hlp b/etc/help/ports.hlp
new file mode 100644
index 0000000..959db42
--- /dev/null
+++ b/etc/help/ports.hlp
@@ -0,0 +1,12 @@
+
+USAGE
+ Ports
+
+DESCRIPTION
+ Shows the available AX25 ports. Shown are the port name, a short
+ description for the port, the number of sessions via the port (qso)
+ and the number received and transmitted packets via the port.
+ The port name is used when using the Connect command to connect
+ to an user or service not running NET/ROM or FlexNet (eg. not visible
+ in the Nodes and Destinations lists). The port name is also visible
+ in the Route, MHeard and MSession lists.
\ No newline at end of file
diff --git a/etc/help/quit.hlp b/etc/help/quit.hlp
new file mode 100644
index 0000000..58cd7bc
--- /dev/null
+++ b/etc/help/quit.hlp
@@ -0,0 +1,6 @@
+
+USAGE
+ Quit
+
+DESCRIPTION
+ Disconnects you from this node.
diff --git a/etc/help/rose.hlp b/etc/help/rose.hlp
new file mode 100644
index 0000000..69c1f6e
--- /dev/null
+++ b/etc/help/rose.hlp
@@ -0,0 +1,2 @@
+<enter your rose routes here. Ex:>
+c n1uro-8 3100860906
diff --git a/etc/help/routes.hlp b/etc/help/routes.hlp
new file mode 100644
index 0000000..e1bf3ff
--- /dev/null
+++ b/etc/help/routes.hlp
@@ -0,0 +1,16 @@
+
+USAGE
+ Routes
+
+DESCRIPTION
+ Shows the NET/ROM route table of the local host (eg. the nodes
+ which the local node directly talks with). These nodes are used
+ to reach the other nodes on the node table. Fields shown are:
+
+ Link - Is there an AX25 connection active to this node
+ Port - Which port is this route on
+ Callsign - The callsign of the neighbour node
+ Quality - A relative quality for the path (0-255)
+ Destinations - Number of other nodes reached via this route
+ Lock - Is the quality of this route locked by the operator
+ QSO - Number of NET/ROM session enties
\ No newline at end of file
diff --git a/etc/help/sessions.hlp b/etc/help/sessions.hlp
new file mode 100644
index 0000000..ecd55ce
--- /dev/null
+++ b/etc/help/sessions.hlp
@@ -0,0 +1,10 @@
+
+USAGE
+ SEssions [* | <call>]
+
+DESCRIPTION
+ Gives a list of active AX25 and NET/ROM connections to and
+ from the local host. With an asterisk (*) as an argument
+ shows also AX25 and NET/ROM sockets in listening state. With
+ a callsign as an argument gives a list of all connections with
+ either source or destination callsign <call>.
diff --git a/etc/help/status.hlp b/etc/help/status.hlp
new file mode 100644
index 0000000..44c18c7
--- /dev/null
+++ b/etc/help/status.hlp
@@ -0,0 +1,14 @@
+
+USAGE
+ STatus
+
+DESCRIPTION
+ Returns information about the status of the Linux system which this
+ URONode runs on. All information is taken directly from the
+ operating system.
+
+ The "load average" values indicate the average amount of processes
+ waiting for processor time during the last 1, 5 and 15 minutes.
+ Load average of 1.0 would mean that the all of the processor time is
+ used by the processes, and all processes still get all of the time
+ they can use.
diff --git a/etc/help/telnet.hlp b/etc/help/telnet.hlp
new file mode 100644
index 0000000..26f474f
--- /dev/null
+++ b/etc/help/telnet.hlp
@@ -0,0 +1,26 @@
+
+USAGE
+ Telnet <host> [<port>] [s|d]
+
+DESCRIPTION
+ Initiates a telnet session to a remote host using TCP/IP.
+ You might not be able to connect to a given host due to the
+ local operator's policy of using this node, or simply because
+ the host is unreachable due to a network failure. You can use
+ the ping command to check if a host is reachable.
+
+ By default, the telnet command connects to the TCP port 23
+ (allocated for telnet). You can specify another TCP port or
+ a TCP port name.
+
+ If a single `s' is entered as the last parameter, then when
+ the remote host disconnects you will be returned to this node.
+ This is only valid if the user connects into your node via
+ NetRom, otherwise the user is automatically reconnected to
+ the node.
+
+EXAMPLES
+ telnet aripisa.ampr.org
+ telnet aripisa.ampr.org 1024
+ telnet 44.134.208.29 s
+ telnet 44.88.0.9 23 s
diff --git a/etc/help/users.hlp b/etc/help/users.hlp
new file mode 100644
index 0000000..8ac0cb1
--- /dev/null
+++ b/etc/help/users.hlp
@@ -0,0 +1,8 @@
+
+USAGE
+ Users
+
+DESCRIPTION
+ Shows a list of users currently connected to the local node,
+ where the users are coming from, and what are they doing at the
+ moment.
diff --git a/etc/help/version.hlp b/etc/help/version.hlp
new file mode 100644
index 0000000..a17ce1a
--- /dev/null
+++ b/etc/help/version.hlp
@@ -0,0 +1,6 @@
+
+USAGE
+ Version
+
+DESCRIPTION
+ Displays the software version information,
diff --git a/etc/help/who.hlp b/etc/help/who.hlp
new file mode 100644
index 0000000..8e8eef9
--- /dev/null
+++ b/etc/help/who.hlp
@@ -0,0 +1,8 @@
+
+USAGE
+ Who (<call> | *)
+
+DESCRIPTION
+ Shows a list when the user with the callsign <call> last
+ connected to this node. Use the asterisk to print out
+ the entire log table.
diff --git a/etc/help/zconnect.hlp b/etc/help/zconnect.hlp
new file mode 100644
index 0000000..c58fff0
--- /dev/null
+++ b/etc/help/zconnect.hlp
@@ -0,0 +1,23 @@
+
+USAGE
+ ZConnect <call | alias> [s|d] For NET/ROM or Links
+ ZConnect <port> <call> [via <digi1> ...] [s|d] For AX25
+ ZConnect <call> <address> [<digi>] [d|s] For ROSE
+ ZConnect <destination> [s|d] For FlexNet
+
+DESCRIPTION
+ Compresses an AX25, NET/ROM, ROSE or Flexnet connection to a
+ remote host. If more than two parameters are entered and the
+ second parameter is ten charachers in length then it is
+ interpreted as a ROSE connection, otherwise the first
+ parameter is interpreted as a port name and AX25 is used
+ to make the connection via that port. If only one parameter
+ is given the connection is made searching for the callsign
+ in NET/ROM nodes, in AX25 Fixed links, in FlexNet destinations
+ and last in Mheard database in this order.
+
+ If a single `s' is entered as the last parameter, then when
+ the remote host disconnects you will be returned to this node.
+ If a single `d' is entered as the last parameter, you will
+ be disconnected from this node too. Default behaviour (neither
+ `s' nor `d' entered) depends on sysop configuration.
diff --git a/etc/help/ztelnet.hlp b/etc/help/ztelnet.hlp
new file mode 100644
index 0000000..e4b36ee
--- /dev/null
+++ b/etc/help/ztelnet.hlp
@@ -0,0 +1,25 @@
+
+USAGE
+ ZTelnet <host> [<port>] [s|d]
+
+DESCRIPTION
+ Compresses a telnet session to a remote host using TCP/IP.
+ You might not be able to connect to a given host due to the
+ local operator's policy of using this node, or simply because
+ the host is unreachable due to a network failure. You can use
+ the ping command to check if a host is reachable.
+
+ By default, the telnet command connects to the TCP port 23
+ (allocated for telnet). You can specify another TCP port or
+ a TCP port name.
+
+ If a single `s' is entered as the last parameter, then when
+ the remote host disconnects you will be returned to this node.
+ If a single `d' is entered as the last parameter, you will
+ be disconnected from this node too. Default behaviour (neither
+ `s' nor `d' entered) depends on sysop configuration.
+
+EXAMPLES
+ ztelnet aripisa.ampr.org
+ ztelnet aripisa.ampr.org 1024
+ ztelnet 44.134.208.29
diff --git a/etc/lastlog b/etc/lastlog
new file mode 100644
index 0000000..e69de29
diff --git a/etc/loggedin b/etc/loggedin
new file mode 100644
index 0000000..e69de29
diff --git a/etc/uronode.conf b/etc/uronode.conf
new file mode 100644
index 0000000..e2af7f6
--- /dev/null
+++ b/etc/uronode.conf
@@ -0,0 +1,89 @@
+# /etc/ax25/uronode.conf - URONode example configuration file
+#
+# see uronode.conf(5)
+
+# Idle timeout (seconds).
+# This is how long we hold onto a dead link. 0 disables (this is NOT
+# recommended! Time is in seconds.
+
+IdleTimeout 900
+
+# Timeout when gatewaying (seconds).
+# This (in seconds) is a keep-alive for dead connects out of the node.
+
+ConnTimeout 600
+
+# Visible hostname. Will be shown at telnet login.
+# set this to your ampr.org hostname.
+
+HostName xx#xx.ampr.org
+
+# SysOp email address
+# Set this to your email address - preferred to use an ampr.org email.
+
+Email <your at email.ampr.org>
+
+# "Local" network.
+# This is your local amprnet subnet in full. Do NOT use 44.0.0.0/8!
+
+LocalNet 44.0.0.0/32
+
+# Command aliases. See uronode.conf(5) for the meaning of the uppercase
+# letters in the name of the alias. Examples below:
+
+Alias CAllbook "telnet %{3:144.167.99.66} 2000 %1 s"
+Alias CONVers "telnet %{2:44.88.0.9} 3600 \"/n %u %{1:1}\""
+Alias DXCluster "connect dxnet"
+Alias Quit "bye"
+Alias WX "telnet %{3:38.102.137.140} %1 s"
+
+# Hidden ports.
+# List interfaces you wish not to display. Not suggested.
+
+#HiddenPorts inet
+
+# External commands. See uronode.conf(5) for the meaning of the uppercase
+# letters in the name of the extcmd.
+#
+# Flags: 1 Run command through pipe
+# 2 Reconnected flag
+# 3 Run through pipe and reconnect
+#
+ExtCmd NEstat 1 nobody /bin/netstat netstat --inet
+#ExtCmd PMS 1 root /usr/sbin/pms pms -u %U -o XX0XX
+
+# Node ID.
+# This displays before all output texts when the user connects into
+# your node via NetRom. Set to "" to leave blank.
+# Note: This -must- be defined or will display as "(null)". A space
+# is hardcoded in. Example: UROHUB:N1URO-2 do NOT add the bracket
+# afterwards "}" this is predefined in URONode.
+#
+NodeId XXXXXX:XX#XX-#
+
+# Ax25/Flex ID.
+# This displays before some strings and at logout to the end user when
+# they connect in via ax25 as defined in your ax25d.conf file. If
+# you don't define this "(null)" will be presented to the end user. Its
+# suggested you take this from your ax25d config which either faces a
+# flexnet system OR your 2-meter user interface. Note: do NOT make this
+# ssid the same as your NetRom SSID here or in ax25d.conf.
+
+FlexId XX#XX-#
+
+# ROSE ssid at network - if none, enter in: none.
+
+RoseId XX#XX-#@####,######
+
+# Netrom port name. This port is used for outgoing netrom connects.
+
+NrPort nr0
+
+# Syslog Logging level - suggest leaving this at 3 for debugging. 0
+# halts logging.
+
+LogLevel 3
+
+# The default escape character (CTRL-T)
+#
+EscapeChar ^T
diff --git a/etc/uronode.info b/etc/uronode.info
new file mode 100644
index 0000000..f41b887
--- /dev/null
+++ b/etc/uronode.info
@@ -0,0 +1,3 @@
+This is a new system running URONode.
+*** please edit /etc/ax25/uronode.info to change this text to display
+ information about your system.
diff --git a/etc/uronode.motd b/etc/uronode.motd
new file mode 100644
index 0000000..048cf8a
--- /dev/null
+++ b/etc/uronode.motd
@@ -0,0 +1,4 @@
+This is copy of URONode is located in <town>,
+<county>, <state/province> [XX##xx] (grid)
+Type "?" for commands or H <command> for more detailed help on a command.
+*** please edit /etc/ax25/uronode.motd to change this text
diff --git a/etc/uronode.perms b/etc/uronode.perms
new file mode 100644
index 0000000..fcbe6e8
--- /dev/null
+++ b/etc/uronode.perms
@@ -0,0 +1,26 @@
+# /etc/ax25/uronode.perms - URONode example permissions file
+#
+# see uronode.perms(5)
+#
+# Note: The flags have been changed as of 2014/08/23
+#
+# user type port passwd perms
+
+# User oh2bns can login without password from anywhere else but 'inet'.
+#
+#xx0xx inet * qwerty 95
+#xx0xx * * * 95
+n1uro * * * 255
+
+# OH2RBI is a bbs so it needs escape disabled.
+#
+#xx0xx * * * 287
+
+# Default permissions per connection type.
+#
+* ax25 * * 31
+* netrom * * 31
+* local * * 31
+* ampr * * 31
+* inet * * 0
+* host * * 31
diff --git a/etc/uronode.routes b/etc/uronode.routes
new file mode 100644
index 0000000..9b94f1e
--- /dev/null
+++ b/etc/uronode.routes
@@ -0,0 +1,21 @@
+# /etc/ax25/uronode.routes URONode example configuration file
+# This is used for quick ax25 connects so users need not add an interface
+# when making a connect. You also need a statement in here for flexd to
+# poll your flexnet neighbor.
+
+# URONode shows links with this order. Examples below:
+
+# Direct Routing
+# route <call> <alias> <port> d 'description'
+#
+#route n1uro-1 fxuro ax0 d 'N1URO FlexNet Hub'
+
+# Routing across another node with sending a string "C <call>"
+# route <call> <alias> <port> n 'description' <node>
+#
+#route n1uro-14 WMASS ax0 n 'N1URO-NOS' n1uro-1
+
+# Routing via digipeaters
+# route <call> <alias> <port> v 'description' <digipeaters>
+#
+#route n1uro-9 MACTFX ax0 v 'N1URO Xnet' n1uro-1
diff --git a/etc/uronode.users b/etc/uronode.users
new file mode 100644
index 0000000..59d7dd0
--- /dev/null
+++ b/etc/uronode.users
@@ -0,0 +1,6 @@
+# /etc/ax25/uronode.users URONode example configuration file
+# Shell access for Sysop users
+
+# callsign:password:local linux username:shell
+# xx#xx:password:xx#xx:shell
+# yy#yy:password:thomas:shell
diff --git a/extcmd.c b/extcmd.c
new file mode 100644
index 0000000..e108cac
--- /dev/null
+++ b/extcmd.c
@@ -0,0 +1,203 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netax25/ax25.h>
+#include <netrose/rose.h>
+#include <grp.h>
+#include <sys/wait.h>
+#include <netax25/axlib.h>
+#include <netax25/axconfig.h>
+
+#include "node.h"
+
+#define ECMD_PIPE 1 /* Run through pipe */
+
+#ifdef HAVEMOTD
+#define ECMD_RECONN 2 /* */
+#endif
+
+static int norm_extcmd(struct cmd *cmdp, char **argv)
+{
+ int pid;
+
+ alarm(0L);
+ pid = fork();
+ if (pid == -1) {
+ /* fork error */
+ node_perror("norm_extcmd: fork", errno);
+ return 0;
+ }
+ if (pid == 0) {
+ /* child */
+ setgroups(0, NULL);
+ setgid(cmdp->gid);
+ setuid(cmdp->uid);
+ execve(cmdp->path, argv, NULL);
+ node_perror("norm_extcmd: execve", errno);
+ exit(1);
+ }
+ /* parent */
+ waitpid(pid, NULL, 0);
+ return 0;
+}
+
+static int pipe_extcmd(struct cmd *cmdp, char **argv)
+{
+ ax25io *iop;
+ int pipe_in[2], pipe_out[2];
+ int pid, c;
+ fd_set fdset;
+
+ if (pipe(pipe_in) == -1) {
+ node_perror("pipe_extcmd: pipe_in", errno);
+ return 0;
+ }
+ if (pipe(pipe_out) == -1) {
+ node_perror("pipe_extcmd: pipe_out", errno);
+ return 0;
+ }
+ signal(SIGCHLD, SIG_IGN);
+ pid = fork();
+ if (pid == -1) {
+ /* fork error */
+ node_perror("pipe_extcmd: fork", errno);
+ signal(SIGCHLD, SIG_DFL);
+ return 0;
+ }
+ if (pid == 0) {
+ /* child */
+ /*
+ * Redirect childs output to the pipes closing
+ * stdin/out/err as we go.
+ */
+ dup2(pipe_in[0], STDIN_FILENO);
+ dup2(pipe_out[1], STDOUT_FILENO);
+ dup2(pipe_out[1], STDERR_FILENO);
+ /* Close the other ends */
+ close(pipe_in[1]);
+ close(pipe_out[0]);
+ setgroups(0, NULL);
+ setgid(cmdp->gid);
+ setuid(cmdp->uid);
+ execve(cmdp->path, argv, NULL);
+ perror("pipe_extcmd: execve");
+ exit(1);
+ }
+ /* parent */
+ close(pipe_in[0]);
+ close(pipe_out[1]);
+ if (fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK) == -1 ||
+ fcntl(pipe_out[0], F_SETFL, O_NONBLOCK) == -1) {
+ node_perror("pipe_extcmd: fcntl - pipe_out", errno);
+ goto end;
+ }
+ iop = axio_init(pipe_out[0], pipe_in[1], 1024, UNSPEC_EOL);
+ if (iop == NULL) {
+ node_perror("pipe_extcmd: Error initializing I/O", -1);
+ goto end;
+ }
+ while (1) {
+ FD_ZERO(&fdset);
+ FD_SET(STDIN_FILENO, &fdset);
+ FD_SET(pipe_out[0], &fdset);
+ if (select(32, &fdset, 0, 0, 0) == -1) {
+ node_perror("pipe_extcmd: select", errno);
+ break;
+ }
+ if (FD_ISSET(STDIN_FILENO, &fdset)) {
+ alarm(ConnTimeout);
+ while((c = axio_getc(NodeIo)) != -1)
+ axio_putc(c, iop);
+ if (errno != EAGAIN)
+ break;
+ }
+ if (FD_ISSET(pipe_out[0], &fdset)) {
+ alarm(ConnTimeout);
+ while((c = axio_getc(iop)) != -1)
+ axio_putc(c, NodeIo);
+ if (errno != EAGAIN) {
+ if (errno)
+ node_msg("%s", strerror(errno));
+ break;
+ }
+ }
+ axio_flush(NodeIo);
+ axio_flush(iop);
+ }
+#ifdef HAVEMOTD
+ if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo, "%s} ", NodeId);
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo,"\e[01;31mWelcome back.\e[0m");
+ } else {
+ axio_printf(NodeIo, "Welcome back.");
+ }
+
+ } else if (User.ul_type == AF_INET) {
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[01;31m");
+ }
+ axio_printf(NodeIo, "Returning you to the shell... ");
+ } else if (User.ul_type == AF_AX25) {
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo,"\e[01;31m");
+ }
+ axio_printf(NodeIo,"Welcome back to %s.", FlexId);
+ } else if (User.ul_type == AF_ROSE) {
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo,"\e[01;31m");
+ }
+ axio_printf(NodeIo,"Back to %s", RoseId);
+ }
+
+#endif
+ axio_end(iop);
+ end:
+ signal(SIGCHLD, SIG_DFL);
+ kill(pid, SIGKILL);
+ close(pipe_in[1]);
+ close(pipe_out[0]);
+ if (fcntl(STDIN_FILENO, F_SETFL, 0) == -1)
+ node_perror("pipe_extcmd: fcntl - stdin", errno);
+ return 0;
+}
+
+int extcmd(struct cmd *cmdp, char **argv)
+{
+ int ret;
+
+ User.state = STATE_EXTCMD;
+ User.dl_type = AF_UNSPEC;
+ strcpy(User.dl_name, cmdp->name);
+ strupr(User.dl_name);
+ update_user();
+ if (cmdp->flags & ECMD_PIPE)
+ ret = pipe_extcmd(cmdp, argv);
+ else
+ ret = norm_extcmd(cmdp, argv);
+
+#ifdef HAVEMOTD
+ if (cmdp->flags & ECMD_RECONN) {
+ if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo, "%s} Welcome back.", NodeId);
+ }
+ }
+ else if (User.ul_type == AF_AX25) {
+ /* axio_printf(NodeIo, "Welcome back to %s.", FlexId); */
+ }
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+#else
+ if (cmdp->flags)
+ node_logout("");
+#endif
+ return ret;
+}
diff --git a/flexd.c b/flexd.c
new file mode 100644
index 0000000..b82e5bd
--- /dev/null
+++ b/flexd.c
@@ -0,0 +1,431 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <signal.h>
+
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netax25/ax25.h>
+#include <netrose/rose.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/ip.h>
+
+#include <netax25/axlib.h>
+#include <netax25/axconfig.h>
+#include <netax25/nrconfig.h>
+#include <netax25/rsconfig.h>
+#include <netax25/procutils.h>
+#include <netax25/daemon.h>
+
+#include "config.h"
+#include "procinfo.h"
+
+#define DEFAULT_POLL_TIME 600
+#define MINIMUM_POLL_TIME 300
+
+int poll_time=DEFAULT_POLL_TIME;
+char flexgate[10]="\0";
+char mycall[10]="\0";
+struct ax_routes *gw;
+int s;
+void (*sigterm_defhnd)(int);
+
+void read_conf(void)
+{
+ FILE *fp, *fgt;
+ char buf[1024], line[1024], *cp;
+ int i=0,k;
+ char digipath[AX25_MAX_DIGIS*10];
+
+ if ((fp=fopen(FLEXD_CONF_FILE, "r")) == NULL) {
+ fprintf(stderr, "flexd config: Cannot open config file: %s\n", FLEXD_CONF_FILE);
+ exit(1);
+ }
+ if ((fgt=fopen(FLEX_GT_FILE, "w")) == NULL) {
+ fprintf(stderr, "flexd config: Cannot open flexnet gateways file: %s\n", FLEX_GT_FILE);
+ fclose(fp);
+ exit(1);
+ }
+
+ fputs("addr callsign dev digipeaters\n", fgt);
+
+ while(fgets(buf, sizeof(buf), fp)) {
+ if(*buf=='#' || *buf==' ') continue; /* comment line/empty line */
+ cp=strchr(buf, '#');
+ if (cp) *cp='\0';
+ cp=strtok(buf, " \t\n\r");
+ if(cp==NULL) continue; /* empty line */
+
+ if(strcasecmp(cp,"pollinterval")==0) { /* set poll interval */
+ cp=strtok(NULL, " \t\n\r");
+ if(cp==NULL) {
+ fprintf(stderr, "flexd config: PollInterval needs an argument\n");
+ fclose(fp);
+ fclose(fgt);
+ exit(1);
+ }
+ poll_time=safe_atoi(cp);
+ if (poll_time<MINIMUM_POLL_TIME) poll_time=MINIMUM_POLL_TIME;
+ }
+ if(strcasecmp(cp,"mycall")==0) { /* set connect call for download */
+ cp=strtok(NULL, " \t\n\r");
+ if(cp==NULL) {
+ fprintf(stderr, "flexd config: MyCall needs an argument\n");
+ fclose(fp);
+ fclose(fgt);
+ exit(1);
+ }
+ safe_strncpy(mycall, cp, 9);
+ }
+ if(strcasecmp(cp,"flexgate")==0) { /* set flexnet gateway */
+ cp=strtok(NULL, " \t\n\r");
+ if(cp==NULL) {
+ fprintf(stderr, "flexd config: FlexGate needs an argument\n");
+ fclose(fp);
+ fclose(fgt);
+ exit(1);
+ }
+ safe_strncpy(flexgate, cp, 9);
+ gw=find_route(flexgate, NULL);
+ if (gw==NULL) {
+ fprintf(stderr, "flexd config: FlexGate %s not found in route file: %s\n", flexgate, AX_ROUTES_FILE);
+ fclose(fp);
+ fclose(fgt);
+ exit(1);
+ } else {
+ *digipath='\0';
+ for(k=0;k<AX25_MAX_DIGIS;k++) {
+ if (gw->digis[k]==NULL) break;
+ strcat(digipath," ");
+ strcat(digipath, gw->digis[k]);
+ }
+ sprintf(line, "%05d %-8s %4s %s\n", i++, gw->dest_call, ax25_config_get_dev(gw->dev), digipath);
+ fputs(line, fgt);
+ }
+ }
+ }
+
+ fclose(fgt);
+ fclose(fp);
+}
+
+int download_dest(char *gateway, char *fname)
+{
+ FILE *tmp;
+ char buffer[1024], port[14], path[AX25_MAX_DIGIS*10];
+ char *addr, *commands[10], *dlist[9]; /* Destination + 8 digipeaters */
+ fd_set read_fd;
+ int n, addrlen, cmd_send=0, cmd_ack=0, c, k;
+ struct full_sockaddr_ax25 axbind, axconnect;
+ struct timeval tv;
+
+ gw=find_route(gateway, NULL);
+ if (gw==NULL) {
+ fprintf(stderr, "flexd connect: FlexGate %s not found in route file: %s\n", gateway, AX_ROUTES_FILE);
+ return 1;
+ } else {
+ *path='\0';
+ for(k=0;k<AX25_MAX_DIGIS;k++) {
+ if (gw->digis[k][0]=='\0') dlist[k+1]=NULL;
+ else dlist[k+1]=gw->digis[k];
+ }
+ dlist[0]=gw->dest_call;
+ strcpy(port,gw->dev);
+ }
+
+ if ((addr = ax25_config_get_addr(port)) == NULL) {
+ sprintf(buffer, "flexd connect: invalid AX.25 port name - %s\r\n", port);
+ write(STDOUT_FILENO, buffer, strlen(buffer));
+ return 1;
+ }
+
+ /*
+ * Open the socket into the kernel.
+ */
+ if ((s = socket(AF_AX25, SOCK_SEQPACKET, 0)) < 0) {
+ sprintf(buffer, "flexd connect: cannot open AX.25 socket, %s\r\n", strerror(errno));
+ write(STDOUT_FILENO, buffer, strlen(buffer));
+ return 1;
+ }
+
+ /*
+ * Set our AX.25 callsign and AX.25 port callsign accordingly.
+ */
+ if (*mycall=='\0') sprintf(buffer, "%s %s", addr, addr);
+ else sprintf(buffer, "%s %s", mycall, addr);
+ ax25_aton(buffer, &axbind);
+ axbind.fsa_ax25.sax25_family = AF_AX25;
+ addrlen=sizeof(struct full_sockaddr_ax25);
+
+ if (bind(s, (struct sockaddr *)&axbind, addrlen) != 0) {
+ sprintf(buffer, "flexd connect: cannot bind AX.25 socket, %s\r\n", strerror(errno));
+ write(STDOUT_FILENO, buffer, strlen(buffer));
+ close(s);
+ return 1;
+ }
+
+ /*
+ * Lets try and connect to the far end.
+ */
+ addrlen=sizeof(struct full_sockaddr_ax25);
+ axconnect.fsa_ax25.sax25_family = AF_AX25;
+
+ if (fcntl(s, F_SETFL, O_NONBLOCK) == -1) {
+ sprintf(buffer, "flexd connect: fcntl on socket: %s\r\n", strerror(errno));
+ write(STDOUT_FILENO, buffer, strlen(buffer));
+ close(s);
+ return 1;
+ }
+
+ if (ax25_aton_arglist((const char **)dlist, &axconnect) == -1) {
+ sprintf(buffer, "flexd connect: invalid destination callsign or digipeater\r\n");
+ write(STDOUT_FILENO, buffer, strlen(buffer));
+ close(s);
+ return 1;
+ }
+
+ if (connect(s, (struct sockaddr *)&axconnect, addrlen) == -1 && errno != EINPROGRESS) {
+ switch (errno) {
+ case ECONNREFUSED:
+ strcpy(buffer, "*** Connection refused - aborting\r\n");
+ break;
+ case ENETUNREACH:
+ strcpy(buffer, "*** No known route - aborting\r\n");
+ break;
+ case EINTR:
+ strcpy(buffer, "*** Connection timed out - aborting\r\n");
+ break;
+ default:
+ sprintf(buffer, "*** Cannot connect, %s\r\n", strerror(errno));
+ break;
+ }
+
+ write(STDOUT_FILENO, buffer, strlen(buffer));
+ close(s);
+ return 1;
+ }
+
+ while (1) {
+ FD_ZERO(&read_fd);
+ FD_SET(s, &read_fd);
+
+ tv.tv_sec=180;
+ tv.tv_usec=0;
+
+ k=select(s + 3, &read_fd, NULL, 0, &tv);
+
+ if (k<1) { /* error or timeout */
+ break;
+ }
+ if (FD_ISSET(s, &read_fd)) {
+ int ret, retlen;
+ char *cp;
+
+ /* See if we got connected or if this was an error */
+ getsockopt(s, SOL_SOCKET, SO_ERROR, &ret, &retlen);
+ if (ret != 0) {
+ cp = strdup(strerror(ret));
+ strlwr(cp);
+ sprintf(buffer, "flexd connect: Failure with %s: %sr\r\n", gateway, cp);
+ write(STDOUT_FILENO, buffer, strlen(buffer));
+ free(cp);
+ close(s);
+ return 1;
+ }
+ break;
+ }
+ }
+
+ commands[0]="d\r\n";
+ commands[1]="q\r\n";
+ commands[2]=NULL;
+
+ /*
+ * Loop until one end of the connection goes away.
+ */
+
+ if ((tmp=fopen(fname, "w")) == NULL) {
+ fprintf(stderr, "flexd connect: Cannot open temporary file: %s\n", fname);
+ close(s);
+ return 1;
+ }
+
+ for (;;) {
+ FD_ZERO(&read_fd);
+ FD_SET(s, &read_fd);
+
+ tv.tv_sec=180;
+ tv.tv_usec=0;
+
+ k=select(s + 1, &read_fd, NULL, NULL, &tv);
+
+ if (k<1) { /* error or timeout */
+ break;
+ }
+
+ if (FD_ISSET(s, &read_fd)) {
+ if ((n = read(s, buffer, 512)) == -1) break;
+ for(c=0;c<n;c++) {
+ if (buffer[c]=='\r') buffer[c]='\n';
+ if (buffer[c]=='=' && c<n-1 && buffer[c+1]=='>') {
+ /* fprintf(stderr, "flex interact: ack[%d]\n", cmd_ack); */
+ cmd_ack++;
+ }
+ }
+ fwrite(buffer, sizeof(char), n, tmp);
+ }
+
+ if (cmd_ack!=0) {
+ if (commands[cmd_send]!=NULL) {
+ write(s, commands[cmd_send], 2);
+ /* fprintf(stderr, "flexd interact: send[%d]: %s\n", cmd_send, commands[cmd_send]); */
+ cmd_send++;
+ }
+ cmd_ack=0;
+ }
+ }
+
+ close(s);
+
+ fputs("\n",tmp);
+
+ fclose(tmp);
+ return 0;
+}
+
+int parse_dest(char *gateway, char *fname)
+{
+ FILE *fdst, *tmp;
+ char *call, *ssid, *rtt, *cp, buf[1024], line[1024], ax[10];
+ int i=0;
+
+ if ((tmp=fopen(fname, "r")) == NULL) {
+ fprintf(stderr, "flexd update: Cannot open temporary file: %s\n", fname);
+ return 1;
+ }
+
+ if ((fdst=fopen(FLEX_DST_FILE, "w")) == NULL) {
+ fprintf(stderr, "flexd update: Cannot open flexnet destinations file: %s\n", FLEX_DST_FILE);
+ fclose(tmp);
+ return 1;
+ }
+
+ fputs("callsign ssid rtt gateway\n", fdst);
+/* fprintf(fdst, "%s %s 0 00000\n", mygate, myrange); */
+ while(fgets(buf, sizeof(buf), tmp)) {
+ cp=strtok(buf, " \t\n\r");
+ if(cp==NULL) continue; /* empty line */
+ if(strstr(cp,"=>")) i++; /* system prompt */
+ if(i==0) continue; /* skip connect text */
+ if(*cp=='#' || *cp=='=' || *cp==' ' || *cp=='*' || *cp=='-' || *cp==':') continue; /* comment line/system prompt */
+ if(strncmp(cp,"73!",3)==0) continue; /* End greeting */
+
+ /* CALL SSID-ESID RTT */
+ do {
+ call=cp;
+ if (call==NULL) break;
+ if (strlen(call)>6) break;
+ if (strchr(call,'-')) break;
+ if (ax25_aton_entry(call,ax)!=0) break;
+ if (!ax25_validate(ax)) break;
+ ssid=strtok(NULL, " \t\n\r");
+ if (ssid==NULL) break;
+ if (!strchr(ssid,'-')) break;
+ rtt=strtok(NULL, " \t\n\r");
+ if (rtt==NULL) break;
+ if (atoi(rtt)==0) break;
+ sprintf(line, "%-8s %-5s %6d %05d\n", call, ssid, safe_atoi(rtt), 0);
+ fputs(line, fdst);
+ cp=strtok(NULL, " \t\n\r");
+ } while(cp!=NULL);
+ }
+
+ fclose(fdst);
+ fclose(tmp);
+
+ return 0;
+}
+
+int update_flex(void)
+{
+ char fname[80];
+
+ sprintf(fname, "%s/.session.%s", FLEXD_TEMP_PATH, flexgate);
+
+ if (download_dest(flexgate, fname)==0) parse_dest(flexgate, fname);
+ remove(fname);
+
+ return 0;
+}
+
+void hup_handler(int sig)
+{
+ signal(SIGHUP, SIG_IGN);
+
+ read_conf();
+
+ signal(SIGHUP, hup_handler); /* Restore hangup handler */
+}
+
+void alarm_handler(int sig)
+{
+ signal(SIGALRM, SIG_IGN);
+
+ update_flex();
+
+ signal(SIGALRM, alarm_handler); /* Restore alarm handler */
+ alarm(poll_time);
+}
+
+void quit_handler(int sig)
+{
+ signal(SIGTERM, SIG_IGN);
+
+ unlink(FLEXD_PID_FILE);
+
+ signal(SIGTERM, sigterm_defhnd);
+ raise(SIGTERM);
+}
+
+int main(int argc, char *argv[])
+{
+ FILE *pidfile;
+
+ signal(SIGPIPE, SIG_IGN);
+
+ if (ax25_config_load_ports() == 0) {
+ fprintf(stderr, "flexd error: No AX25 port data configured\n");
+ return 1;
+ }
+
+ read_conf();
+
+ if (!daemon_start(TRUE)) {
+ fprintf(stderr, "flexd: cannot become a daemon\n");
+ return 1;
+ }
+
+ signal(SIGTERM, quit_handler);
+ pidfile = fopen(FLEXD_PID_FILE, "w");
+ fprintf(pidfile, "%d\n", (int)getpid());
+ fclose(pidfile);
+
+ update_flex();
+
+ signal(SIGHUP, hup_handler);
+ signal(SIGALRM, alarm_handler);
+ sigterm_defhnd = signal(SIGTERM, quit_handler);
+ if (sigterm_defhnd == SIG_ERR)
+ sigterm_defhnd = SIG_DFL;
+ alarm(poll_time);
+
+ for(;;) pause();
+
+ return 0;
+}
+
diff --git a/gateway.c b/gateway.c
new file mode 100644
index 0000000..603201d
--- /dev/null
+++ b/gateway.c
@@ -0,0 +1,1131 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <time.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netax25/ax25.h>
+#include <netrose/rose.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/ip.h>
+
+#include <netax25/axlib.h>
+#include <netax25/axconfig.h>
+#include <netax25/nrconfig.h>
+#include <netax25/rsconfig.h>
+#include <netax25/procutils.h>
+
+#include "procinfo.h"
+#include "node.h"
+
+static void invert_ssid(char *out, char *in)
+{
+ char *cp;
+
+ if ((cp = strchr(in, '-')) != NULL) {
+ *cp = 0;
+ sprintf(out, "%s-%d", in, 15 - atoi(cp + 1));
+ *cp = '-';
+ } else {
+ sprintf(out, "%s-15", in);
+ }
+}
+
+/*
+ * Initiate a AX.25, NET/ROM, ROSE or TCP connection to the host
+ * specified by `address'.
+ */
+static ax25io *connect_to(char **addr, int family, int escape, int compr)
+{
+ int fd;
+ ax25io *riop;
+ fd_set read_fdset;
+ fd_set write_fdset;
+ int salen;
+ union {
+ struct full_sockaddr_ax25 ax;
+#ifdef HAVE_ROSE
+ struct sockaddr_rose rs;
+#endif
+ struct sockaddr_in in;
+ } sa;
+ char call[10], path[20], *cp, *eol;
+ int ret, retlen = sizeof(int);
+ int paclen;
+ struct hostent *hp;
+ struct servent *sp;
+ struct user u;
+#ifdef HAVE_NETROM
+ struct proc_nr_nodes *np;
+#endif
+
+ strcpy(call, User.call);
+ /*
+ * Fill in protocol spesific stuff.
+ */
+ switch (family) {
+#ifdef HAVE_ROSE
+ case AF_ROSE:
+ if (aliascmd==0) {
+ if (check_perms(PERM_ROSE, 0L) == -1) {
+ axio_printf(NodeIo,"Permission denied");
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ node_log(LOGLVL_GW, "Permission denied: rose");
+ return NULL;
+ }
+ }
+ if ((fd = socket(AF_ROSE, SOCK_SEQPACKET, 0)) < 0) {
+ node_perror("connect_to: socket", errno);
+ return NULL;
+ }
+ sa.rs.srose_family = AF_ROSE;
+ sa.rs.srose_ndigis = 0;
+ ax25_aton_entry(call, sa.rs.srose_call.ax25_call);
+ rose_aton(rs_config_get_addr(NULL), sa.rs.srose_addr.rose_addr);
+ salen = sizeof(struct sockaddr_rose);
+ if (bind(fd, (struct sockaddr *)&sa, salen) == -1) {
+ node_perror("connect_to: bind", errno);
+ close(fd);
+ return NULL;
+ }
+ memset(path, 0, 11);
+ memcpy(path, rs_config_get_addr(NULL), 4);
+ salen = strlen(addr[1]);
+ if ((salen != 6) && (salen != 10))
+ {
+ axio_printf(NodeIo,"Invalid ROSE address");
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ return(NULL);
+ }
+ memcpy(path + (10-salen), addr[1], salen);
+ sprintf(User.dl_name, "%s @ %s", addr[0], path);
+ sa.rs.srose_family = AF_ROSE;
+ sa.rs.srose_ndigis = 0;
+ if (ax25_aton_entry(addr[0], sa.rs.srose_call.ax25_call) < 0) {
+ close(fd);
+ return NULL;
+ }
+ if (rose_aton(path, sa.rs.srose_addr.rose_addr) < 0) {
+ close(fd);
+ return NULL;
+ }
+ if (addr[2] != NULL) {
+ if (ax25_aton_entry(addr[2], sa.rs.srose_digi.ax25_call) < 0) {
+ close(fd);
+ return NULL;
+ }
+ sa.rs.srose_ndigis = 1;
+ }
+ salen = sizeof(struct sockaddr_rose);
+ paclen = rs_config_get_paclen(NULL);
+ eol = ROSE_EOL;
+ /* Uncomment the below if you wish to have the node show a 'Trying' state */
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[01;35m");
+ }
+ axio_printf(NodeIo,"Trying %s... press <Enter> to abort", User.dl_name);
+
+ break;
+#endif
+#ifdef HAVE_NETROM
+ case AF_NETROM:
+ if (aliascmd==0) {
+ if (check_perms(PERM_NETROM, 0L) == -1) {
+ axio_printf(NodeIo,"Permission denied");
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ node_log(LOGLVL_GW, "Permission denied: netrom");
+ return NULL;
+ }
+ }
+ if ((fd = socket(AF_NETROM, SOCK_SEQPACKET, 0)) < 0) {
+ node_perror("connect_to: socket", errno);
+ return NULL;
+ }
+ /* Why on earth is this different from ax.25 ????? */
+ sprintf(path, "%s %s", nr_config_get_addr(NrPort), call);
+ ax25_aton(path, &sa.ax);
+ sa.ax.fsa_ax25.sax25_family = AF_NETROM;
+ salen = sizeof(struct full_sockaddr_ax25);
+ if (bind(fd, (struct sockaddr *)&sa, salen) == -1) {
+ node_perror("connect_to: bind", errno);
+ close(fd);
+ return NULL;
+ }
+ if ((np = find_node(addr[0], NULL)) == NULL) {
+ axio_printf(NodeIo,"No such node");
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ return NULL;
+ }
+ strcpy(User.dl_name, print_node(np->alias, np->call));
+ if (ax25_aton(np->call, &sa.ax) == -1) {
+ close(fd);
+ return NULL;
+ }
+ sa.ax.fsa_ax25.sax25_family = AF_NETROM;
+ salen = sizeof(struct sockaddr_ax25);
+ paclen = nr_config_get_paclen(NrPort);
+ eol = NETROM_EOL;
+ /* Uncomment the below if you wish the node to show a 'Trying' state */
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ if (User.ul_type == AF_NETROM) {
+ break;
+ }
+ node_msg("\e[01;36mTrying %s... hit <Enter> to abort", User.dl_name);
+ }
+ break;
+#endif
+#ifdef HAVE_AX25
+ case AF_FLEXNET:
+ case AF_AX25:
+ if (aliascmd==0) {
+ if (check_perms(PERM_AX25, 0L) == -1 || (is_hidden(addr[0]) && check_perms(PERM_HIDDEN, 0L) == -1)) {
+ axio_printf(NodeIo,"Permission denied");
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ node_log(LOGLVL_GW, "Permission denied: ax.25 port %s", addr[0]);
+ return NULL;
+ }
+ }
+ if (ax25_config_get_addr(addr[0]) == NULL) {
+ if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo,"%s} ", NodeId);
+ }
+ axio_printf(NodeIo,"Invalid port");
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ return NULL;
+ }
+ if ((fd = socket(AF_AX25, SOCK_SEQPACKET, 0)) < 0) {
+ node_perror("connect_to: socket", errno);
+ return NULL;
+ }
+ /*
+ * Invert the SSID only if user is coming in with AX.25
+ * and going out on the same port he is coming in via.
+ */
+/* if (User.ul_type == AF_AX25 && !strcasecmp(addr[0], User.ul_name)) */
+ invert_ssid(call, User.call);
+ sprintf(path, "%s %s", call, ax25_config_get_addr(addr[0]));
+ ax25_aton(path, &sa.ax);
+ sa.ax.fsa_ax25.sax25_family = AF_AX25;
+ salen = sizeof(struct full_sockaddr_ax25);
+ if (bind(fd, (struct sockaddr *)&sa, salen) < 0) {
+ node_perror("connect_to: bind", errno);
+ close(fd);
+ return NULL;
+ }
+ if (ax25_aton_arglist((const char **)addr+1, &sa.ax) < 0) {
+ close(fd);
+ return NULL;
+ }
+ strcpy(User.dl_name, strupr(addr[1]));
+ strcpy(User.dl_port, strlwr(addr[0]));
+ sa.ax.fsa_ax25.sax25_family = AF_AX25;
+ salen = sizeof(struct full_sockaddr_ax25);
+ paclen = ax25_config_get_paclen(addr[0]);
+ eol = AX25_EOL;
+ /* Uncomment the below if you wish the node to show a 'Trying' state */
+ /* if (family==AF_FLEXNET) node_msg("Trying %s via FlexNet... Type <RETURN> to abort", User.dl_name); */
+ if ((family==AF_FLEXNET) || (family == AF_AX25)) {
+ if (!strcmp(User.dl_port,User.ul_name)) {
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[05;31m");
+ }
+ axio_printf(NodeIo,"\aLoop detected on ");
+ }
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[0;m");
+ }
+ if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo, "%s} ", NodeId);
+ }
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[01;33m");
+ }
+ axio_printf(NodeIo,"link setup (%s)...", User.dl_port);
+ }
+ /* else node_msg("Trying %s on %s... Type <RETURN> to abort", User.dl_name, User.dl_port); */
+ break;
+#endif
+ case AF_INET:
+ if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+ node_perror("connect_to: socket", errno);
+ return NULL;
+ }
+ if ((hp = gethostbyname(addr[0])) == NULL) {
+ if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo, "%s} ", NodeId);
+ }
+ axio_printf(NodeIo,"Unknown host %s", addr[0]);
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ close(fd);
+ return NULL;
+ }
+ sa.in.sin_family = AF_INET;
+ sa.in.sin_addr.s_addr = ((struct in_addr *)(hp->h_addr))->s_addr;
+ sp = NULL;
+ if (addr[1] == NULL)
+ sp = getservbyname("telnet", "tcp");
+ if (sp == NULL)
+ sp = getservbyname(addr[1], "tcp");
+ if (sp == NULL)
+ sp = getservbyport(htons(atoi(addr[1])), "tcp");
+ if (sp != NULL) {
+ sa.in.sin_port = sp->s_port;
+ } else if (atoi(addr[1]) != 0) {
+ sa.in.sin_port = htons(atoi(addr[1]));
+ } else {
+ axio_printf(NodeIo,"%s Unknown service %s", NodeId, addr[1]);
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ close(fd);
+ return NULL;
+ }
+ strcpy(User.dl_name, inet_ntoa(sa.in.sin_addr));
+ if (sp != NULL)
+ strcpy(User.dl_port, sp->s_name);
+ else
+ sprintf(User.dl_port, "%d", ntohs(sa.in.sin_port));
+ salen = sizeof(struct sockaddr_in);
+ paclen = 1024;
+ eol = INET_EOL;
+ if (aliascmd==0) {
+ if (check_perms(PERM_TELNET, sa.in.sin_addr.s_addr) == -1) {
+ if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo,"%s} ", NodeId);
+ }
+ axio_printf(NodeIo,"Permission denied");
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ node_log(LOGLVL_GW, "Permission denied: telnet %s", User.dl_name);
+ close(fd);
+ return NULL;
+ }
+ }
+ /* if ((check_perms(PERM_ANSI, 0L) != -1) && (family == AF_NETROM)) {
+ axio_printf(NodeIo,"\e[01;36m%s Trying %s... Type <RETURN> to abort. (Escape: %s%c) \n",NodeId,
+ User.dl_name,
+ escape < 32 ? "CTRL-" : "",
+ escape < 32 ? (escape + 'A' - 1) : escape);
+ axio_flush(NodeIo);
+ } */
+ break;
+ default:
+ axio_printf(NodeIo,"%s Unsupported address family", NodeId);
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ return NULL;
+ }
+ axio_flush(NodeIo);
+ /*
+ * Ok. Now set up a non-blocking connect...
+ */
+ if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1) {
+ node_perror("connect_to: fcntl - fd", errno);
+ close(fd);
+ return NULL;
+ }
+ if (fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK) == -1) {
+ node_perror("connect_to: fcntl - stdin", errno);
+ close(fd);
+ return NULL;
+ }
+ if (connect(fd, (struct sockaddr *)&sa, salen) == -1 && errno != EINPROGRESS) {
+ node_perror("Duplicate connection not allowed", errno);
+ close(fd);
+ return NULL;
+ }
+ User.dl_type = family;
+ User.state = STATE_TRYING;
+ update_user();
+ /*
+ * ... and wait for it to finish (or user to abort).
+ */
+ while (1) {
+ FD_ZERO(&read_fdset);
+ FD_ZERO(&write_fdset);
+ FD_SET(fd, &write_fdset);
+ FD_SET(STDIN_FILENO, &read_fdset);
+ if (select(fd + 1, &read_fdset, &write_fdset, 0, 0) == -1) {
+ node_perror("connect_to: select", errno);
+ break;
+ }
+ if (FD_ISSET(fd, &write_fdset)) {
+ /* See if we got connected or if this was an error */
+ getsockopt(fd, SOL_SOCKET, SO_ERROR, &ret, &retlen);
+ if (ret != 0) {
+ /*
+ * This is STUPID !!!!
+ * FBB interprets "Connection refused" as
+ * success because it contains the string
+ * "Connect"...
+ * But I'm NOT going to toss away valuable
+ * information (the strerror() info).
+ * Fortunately (???) FBB is case sensitive
+ * when examining the return string so
+ * simply converting the strerror() message
+ * to lower case fixes the problem. Ugly
+ * but it _should_ work.
+ */
+ cp = strdup(strerror(ret));
+ strlwr(cp);
+ if (family==AF_FLEXNET) {
+ axio_printf(NodeIo,"\n*** failure with %s", User.dl_name);
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ }
+ else
+ if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo, "\n%s} Failure with %s: %s\n", NodeId, User.dl_name, cp);
+ } else {
+ axio_printf(NodeIo,"\nFailure with %s: %s", User.dl_name, cp);
+ }
+ node_log(LOGLVL_GW, "Failure with %s: %s", User.dl_name, cp);
+ free(cp);
+ close(fd);
+ return NULL;
+ }
+ break;
+ }
+ if (FD_ISSET(STDIN_FILENO, &read_fdset)) {
+ errno = 0;
+ if (axio_getline(NodeIo) != NULL) {
+ if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo,"%s} ", NodeId);
+ }
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[05;31m");
+ }
+ axio_printf(NodeIo,"Aborted");
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[0;m");
+ }
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ close(fd);
+ return NULL;
+ } else if (errno != EAGAIN) {
+ close(fd);
+ return NULL;
+ }
+ }
+ }
+ if (User.dl_type == AF_INET) {
+ if ((User.ul_type == AF_NETROM) || (User.ul_type == AF_ROSE)) {
+ axio_printf(NodeIo,"%s} ", NodeId);
+ }
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo,"\e[01;32m");
+ }
+ node_msg("Socket established to %s:%s", User.dl_name, User.dl_port);
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo,"\e[0;m");
+ }
+ }
+ else
+/* if (family==AF_FLEXNET) {
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo,"\e[01;32m");
+ }
+ node_msg("\n*** connected to %s", User.dl_name);
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo,"\e[0;m");
+ }
+ }
+ else */
+ if ((family==AF_AX25) || (family==AF_FLEXNET) || (family==AF_ROSE)) {
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo,"\e[01;32m");
+ }
+ if ((family==AF_AX25) || (family==AF_FLEXNET)) {
+/* node_msg("\n"); */
+ }
+ node_msg("\n*** connected to %s", User.dl_name);
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo,"\e[0;m");
+ }
+ }
+ else
+ if (family == AF_NETROM) {
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo,"\e[01;32m");
+ }
+ if (User.ul_type == AF_INET) {
+ axio_printf(NodeIo,"Virtual circuit established to %s\n", User.dl_name);
+ }
+ if (User.ul_type == AF_NETROM) {
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo,"\e[0;m");
+ }
+ axio_printf(NodeIo,"%s} ", NodeId);
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo,"\e[01;32m");
+ }
+ axio_printf(NodeIo, "Connected to %s\n", User.dl_name);
+ }
+ if ((User.ul_type == AF_AX25) || (User.ul_type == AF_ROSE)) {
+ axio_printf(NodeIo,"*** connected to %s\n", User.dl_name);
+ }
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo,"\e[0;m");
+ }
+ }
+ /*
+ else
+ if (family == AF_NETROM) {
+ node_msg("%s} Connected to %s\n", NodeId, User.dl_name);
+ } else {
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo,"\e[01;32m");
+ }
+ node_msg("*** connected to %s\n",
+ User.dl_name,
+ escape < 32 ? "CTRL-" : "",
+ escape < 32 ? (escape + 'A' - 1) : escape);
+ }
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[0;m");
+ }
+ */
+ axio_flush(NodeIo);
+ node_log(LOGLVL_GW, "%s Connected to %s", NodeId, User.dl_name);
+ errno = 0;
+ if ((riop = axio_init(fd, fd, paclen, eol)) == NULL) {
+ node_perror("connect_to: Initializing I/O failed", errno);
+ close(fd);
+ return NULL;
+ }
+
+ if (compr && axio_compr(riop, compr) < 0)
+ node_msg("connect_to: axio_compr failed");
+
+ User.state = STATE_CONNECTED;
+ update_user();
+ return riop;
+}
+
+int do_connect(int argc, char **argv)
+{
+ int i, k;
+ ax25io *riop;
+ struct ax_routes *ax;
+ struct flex_dst *flx;
+ struct flex_gt *flgt;
+ int c, compress, family = AF_UNSPEC, stay, escape;
+ char *nodoconn = NULL;
+ fd_set fdset;
+ char *connstr = NULL;
+ axio_puts("",NodeIo);
+
+ stay = ReConnectTo;
+ if (!strcasecmp(argv[argc - 1], "s")) {
+ stay = 1;
+ argv[--argc] = NULL;
+ } else if (!strcasecmp(argv[argc - 1], "d")) {
+ stay = 0;
+ argv[--argc] = NULL;
+ }
+ compress = 0;
+ c = argv[0][0];
+#ifdef HAVE_ZLIB_H
+ if (*argv[0] == 'z') {
+ compress = 1;
+ c = argv[0][1];
+ }
+#endif
+
+ if (argc < 2) {
+ if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo,"%s} ", NodeId);
+ }
+ if (c == 't')
+ axio_printf(NodeIo,"Usage: telnet <host> [<port>] [d|s]");
+ else
+ axio_printf(NodeIo,"Usage: connect [<port>] <call> [via <call1> ...] [d|s]");
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ return 0;
+ }
+ if (c == 't')
+ family = AF_INET;
+ else if (argc > 2) {
+ // #ifdef HAVE_ROSE
+ if (strspn(argv[2], "0123456789") == strlen(argv[2]))
+ family = AF_ROSE;
+ else
+ // #endif
+ family = AF_AX25;
+ }
+ else if (argc == 2) { /* Determine destination */
+ /* call buffer increased by VE3TOK */
+ static char call[10];
+ strncpy(call, strupr(argv[1]), 10);
+
+ /* if (find_node(argv[1], NULL)!=NULL) {
+ family = AF_NETROM;
+ }
+ else */
+
+ if ((flx=find_dest(argv[1], NULL))!=NULL) { /* Check FlexNet */
+ k=1;
+ flgt=find_gateway(flx->addr, NULL);
+ argv[k++]=ax25_config_get_name(flgt->dev);
+ argv[k++]=call;
+ while((k-3)<AX25_MAX_DIGIS&&flgt->digis[k-3][0]!='\0') argv[k]=flgt->digis[(k++)-3];
+ argv[k++]=flgt->call;
+ argv[k]=NULL;
+ argc=k;
+ family = AF_FLEXNET;
+ }
+ else if (find_node(argv[1], NULL)!=NULL) {
+ family = AF_NETROM;
+ }
+
+ else if ((ax=find_route(argv[1], NULL))!=NULL) { /* Check AX25 Links */
+ k=1;
+
+ switch(*ax->conn_type) {
+ case CONN_TYPE_DIRECT:
+ {
+ argv[k++]=ax->dev;
+ argv[k++]=ax->dest_call;
+ break;
+ }
+ case CONN_TYPE_DIGI:
+ {
+ argv[k++]=ax->dev;
+ argv[k++]=ax->dest_call;
+ while((k-3)<AX25_MAX_DIGIS&&ax->digis[k-3][0]!='\0') argv[k]=ax->digis[(k++)-3];
+ break;
+ }
+ case CONN_TYPE_NODE:
+ {
+ argv[k++]=ax->dev;
+ argv[k++]=ax->digis[0];
+ nodoconn=ax->dest_call;
+ break;
+ }
+ }
+ argv[k]=NULL;
+ argc=k;
+ family = AF_AX25;
+ }
+ /* else if ((flx=find_dest(argv[1], NULL))!=NULL) { Check FlexNet
+ k=1;
+ flgt=find_gateway(flx->addr, NULL);
+ argv[k++]=ax25_config_get_name(flgt->dev);
+ argv[k++]=call;
+ while((k-3)<AX25_MAX_DIGIS&&flgt->digis[k-3][0]!='\0') argv[k]=flgt->digis[(k++)-3];
+ argv[k++]=flgt->call;
+ argv[k]=NULL;
+ argc=k;
+ family = AF_FLEXNET;
+ else if (find_node(argv[1], NULL)!=NULL) {
+ family = AF_NETROM;
+ } */
+
+ else if ((ax=find_mheard(argv[1]))!=NULL) { /* Check Mheard database */
+ k=1;
+ /* K2MF supplied code */
+ /* This code *actually* reads mheard.dat and fixes
+ * the digi path the way it should be. -N1URO */
+ argv[k++] = ax->dev;
+ argv[k++] = ax->dest_call;
+
+ /* First count the number of digipeaters in the path
+ * from the destination */
+ i = k - 3;
+
+ while(i < AX25_MAX_DIGIS) {
+ if(ax->digis[i][0] == '\0')
+ break;
+
+ i++;
+ }
+ /* Then construct the reverse digipeater path back to
+ * the destination */
+ while(i && ax->digis[i - 1][0] != '\0')
+ argv[k++] = ax->digis[--i];
+ /* end K2MF code */
+ argv[k]=NULL;
+ argc=k;
+ family = AF_AX25;
+ } else { /* Give up */
+ if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo,"%s} ", NodeId);
+ }
+ axio_printf(NodeIo,"Remote not in Desti, NetRom, or MHeard tables. Retry your entry.");
+ family = AF_UNSPEC;
+ // free_flex_dst(flx);
+ // free_ax_routes(ax);
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ return 0;
+ }
+ }
+
+ if (family == AF_INET && argc > 3) connstr = argv[3];
+ escape = (check_perms(PERM_NOESC, 0L) == 0) ? -1 : EscChar;
+ riop = connect_to(++argv, family, escape, compress);
+ if (riop == NULL) {
+ if (fcntl(STDIN_FILENO, F_SETFL, 0) == -1)
+ node_perror("do_connect: fcntl - stdin", errno);
+ return 0;
+ }
+ if (family == AF_INET)
+ axio_tnmode(riop, 1);
+ if (connstr) {
+ axio_printf(riop, "%s\n", connstr);
+ axio_flush(riop);
+ }
+
+ /*
+ * If eol conventions are compatible, switch to binary mode,
+ * else switch to special gateway mode.
+ */
+ if (axio_cmpeol(riop, NodeIo) == 0) {
+ axio_eolmode(riop, EOLMODE_BINARY);
+ axio_eolmode(NodeIo, EOLMODE_BINARY);
+ } else {
+ axio_eolmode(riop, EOLMODE_GW);
+ axio_eolmode(NodeIo, EOLMODE_GW);
+ }
+ if (nodoconn != NULL) axio_printf(riop, "C %s\n",nodoconn);
+
+ while (1) {
+ FD_ZERO(&fdset);
+ FD_SET(riop->ifd, &fdset);
+ FD_SET(STDIN_FILENO, &fdset);
+ if (select(32, &fdset, 0, 0, 0) == -1) {
+ node_perror("do_connect: select", errno);
+ break;
+ }
+ if (FD_ISSET(riop->ifd, &fdset)) {
+ alarm(ConnTimeout);
+ while((c = axio_getc(riop)) != -1)
+ axio_putc(c, NodeIo);
+ if (errno != EAGAIN) {
+ if (errno && errno != ENOTCONN)
+ axio_printf(NodeIo,"%s", strerror(errno));
+ break;
+ }
+ }
+ if (FD_ISSET(STDIN_FILENO, &fdset)) {
+ alarm(ConnTimeout);
+ while((c = axio_getc(NodeIo)) != -1) {
+ if (escape != -1 && c == escape) break;
+ axio_putc(c, riop);
+ }
+ if (escape != -1 && c == escape) {
+ axio_eolmode(NodeIo, EOLMODE_TEXT);
+ axio_getline(NodeIo);
+ break;
+ }
+ if (errno != EAGAIN) {
+ stay = 0;
+ break;
+ }
+ }
+ axio_flush(riop);
+ axio_flush(NodeIo);
+ }
+ axio_end(riop);
+ node_log(LOGLVL_GW, "Disconnected from %s", User.dl_name);
+#ifdef HAVEMOTD
+ /* if (User.ul_type != AF_NETROM) { */
+ /* if (stay) { */
+ axio_eolmode(NodeIo, EOLMODE_TEXT);
+ if (fcntl(STDIN_FILENO, F_SETFL, 0) == -1)
+ node_perror("do_connect: fcntl - stdin", errno);
+ if (User.ul_type == AF_INET) {
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo,"\e[01;31m");
+ }
+ axio_printf(NodeIo,"\nReturning you to the shell... ");
+ } else
+ if (User.ul_type == AF_AX25) {
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo,"\e[01;31m");
+ }
+ axio_printf(NodeIo,"\r*** reconnected to %s", FlexId);
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo,"\e[0;m");
+ }
+ }
+ if (User.ul_type == AF_ROSE) {
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo,"\e[01;31m");
+ }
+ axio_printf(NodeIo,"\r*** reconnected to %s", RoseId);
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo,"\e[0;m");
+ }
+ }
+ if (User.ul_type == AF_INET) {
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[0m");
+ }
+ }
+ /* } */
+ /* } */
+ if ((User.ul_type == AF_NETROM) && (!stay)) {
+ node_logout("No reconnect");
+ }
+ if ((User.ul_type == AF_NETROM) && (stay)) {
+ axio_printf(NodeIo,"%s} ", NodeId);
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo,"\e[01;31mWelcome back.\n\e[0;m");
+ }
+ if (check_perms(PERM_ANSI, 0L) == -1) {
+ axio_printf(NodeIo,"Welcome back.\n");
+ }
+ }
+#else
+ node_logout("No reconnect");
+#endif
+ // free_flex_dst(flx);
+ // free_ax_routes(ax);
+ return 0;
+}
+int do_finger(int argc, char **argv)
+{
+ ax25io *riop;
+ int i, compress;
+ char *name, *addr[3], *cp;
+ compress = 0;
+
+ /* if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo,"%s} ", NodeId);
+ } */
+ axio_puts("",NodeIo);
+ if (argc < 2) {
+ if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo,"%s} ", NodeId);
+ }
+ axio_printf(NodeIo,"Usage: finger user@<hostname or ip address>.");
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ return 0;
+ } else if ((cp = strchr(argv[1], '@')) != NULL) {
+ *cp = 0;
+ name = argv[1];
+ addr[0] = ++cp;
+ } else {
+ name = argv[1];
+ addr[0] = "localhost";
+ if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo,"%s} ", NodeId);
+ }
+ axio_printf(NodeIo,"Usage: finger user@<hostname or ip address>.");
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ return 0;
+ }
+ addr[1] = "finger";
+ addr[2] = NULL;
+ riop = connect_to(addr, AF_INET, 0, compress);
+ /* If you uncommented 'Trying' state on, uncomment this also. */
+ /* escape = (check_perms(PERM_NOESC, 0L) == 0) ? -1 : EscChar; */
+ if (riop != NULL) {
+ if (fcntl(riop->ifd, F_SETFL, 0) == -1)
+ node_perror("do_finger: fcntl - fd", errno);
+ axio_printf(NodeIo,"[%s]\n", addr[0]);
+ axio_printf(riop, "%s\n", name);
+ axio_flush(riop);
+ while((i = axio_getc(riop)) != -1)
+ axio_putc(i, NodeIo);
+ axio_end(riop);
+ if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo,"%s} ", NodeId);
+ }
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo,"\e[01;31m");
+ }
+ axio_printf(NodeIo,"Finger complete.");
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[0;m");
+ }
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ }
+ axio_eolmode(NodeIo, EOLMODE_TEXT);
+ if (fcntl(STDIN_FILENO, F_SETFL, 0) == -1)
+ node_perror("do_finger: fcntl - stdin", errno);
+ return 0;
+}
+
+/*
+ * Returns difference of tv1 and tv2 in milliseconds.
+ */
+static long calc_rtt(struct timeval tv1, struct timeval tv2)
+{
+ struct timeval tv;
+
+ tv.tv_usec = tv1.tv_usec - tv2.tv_usec;
+ tv.tv_sec = tv1.tv_sec - tv2.tv_sec;
+ if (tv.tv_usec < 0) {
+ tv.tv_sec -= 1L;
+ tv.tv_usec += 1000000L;
+ }
+ return ((tv.tv_sec * 1000L) + (tv.tv_usec / 1000L));
+}
+
+/*
+ * Checksum routine for Internet Protocol family headers (C Version)
+ */
+static unsigned short in_cksum(unsigned char *addr, int len)
+{
+ register int nleft = len;
+ register unsigned char *w = addr;
+ register unsigned int sum = 0;
+ unsigned short answer = 0;
+
+ /*
+ * Our algorithm is simple, using a 32 bit accumulator (sum), we add
+ * sequential 16 bit words to it, and at the end, fold back all the
+ * carry bits from the top 16 bits into the lower 16 bits.
+ */
+ while (nleft > 1) {
+ sum += (*(w + 1) << 8) + *(w);
+ w += 2;
+ nleft -= 2;
+ }
+
+ /* mop up an odd byte, if necessary */
+ if (nleft == 1) {
+ sum += *w;
+ }
+
+ /* add back carry outs from top 16 bits to low 16 bits */
+ sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
+ sum += (sum >> 16); /* add carry */
+ answer = ~sum; /* truncate to 16 bits */
+ return answer;
+}
+
+int do_ping(int argc, char **argv)
+{
+ static int sequence = 0;
+ unsigned char buf[256];
+ struct hostent *hp;
+ struct sockaddr_in to, from;
+ struct protoent *prot;
+ struct icmphdr *icp;
+ struct timeval tv1, tv2;
+ struct iphdr *ip;
+ fd_set fdset;
+ int fd, i, id, len = sizeof(struct icmphdr);
+ int salen = sizeof(struct sockaddr);
+
+ /* if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo,"%s} ", NodeId);
+ } */
+ axio_puts("",NodeIo);
+ if (argc < 2) {
+ if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo,"%s} ", NodeId);
+ }
+ axio_printf(NodeIo,"Usage: ping <host> [<size>]");
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ return 0;
+ }
+ if (argc > 2) {
+ len = atoi(argv[2]) + sizeof(struct icmphdr);
+ if (len > 256) {
+ if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo,"%s} ", NodeId);
+ }
+ axio_printf(NodeIo,"Maximum size is %d", 256 - sizeof(struct icmphdr));
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ return 0;
+ }
+ }
+ if ((hp = gethostbyname(argv[1])) == NULL) {
+ if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo,"%s} ", NodeId);
+ }
+ axio_printf(NodeIo,"Unknown host %s", argv[1]);
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ return 0;
+ }
+ memset(&to, 0, sizeof(to));
+ to.sin_family = AF_INET;
+ to.sin_addr.s_addr = ((struct in_addr *)(hp->h_addr))->s_addr;
+ if ((prot = getprotobyname("icmp")) == NULL) {
+ if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo,"%s} ", NodeId);
+ }
+ axio_printf(NodeIo,"Unknown protocol icmp");
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ return 0;
+ }
+ if ((fd = socket(AF_INET, SOCK_RAW, prot->p_proto)) == -1) {
+ node_perror("do_ping: socket", errno);
+ return 0;
+ }
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo,"\e[01;35mICMP Echo request sent to: \e[0m");
+ }
+ if (check_perms(PERM_ANSI, 0L) == -1) {
+ axio_printf(NodeIo, "ICMP Echo request sent to: ");
+ }
+ node_msg("%s", inet_ntoa(to.sin_addr));
+ axio_flush(NodeIo);
+ strcpy(User.dl_name, inet_ntoa(to.sin_addr));
+ User.dl_type = AF_INET;
+ User.state = STATE_PINGING;
+ update_user();
+ /*
+ * Fill the data portion (if any) with some garbage.
+ */
+ for (i = sizeof(struct icmphdr); i < len; i++)
+ buf[i] = (i - sizeof(struct icmphdr)) & 0xff;
+ /*
+ * Fill in the icmp header.
+ */
+ id = getpid() & 0xffff;
+ icp = (struct icmphdr *)buf;
+ icp->type = ICMP_ECHO;
+ icp->code = 0;
+ icp->checksum = 0;
+ icp->un.echo.id = id;
+ icp->un.echo.sequence = sequence++;
+ /*
+ * Calculate checksum.
+ */
+ icp->checksum = in_cksum(buf, len);
+ /*
+ * Take the time and send the packet.
+ */
+ gettimeofday(&tv1, NULL);
+ if (sendto(fd, buf, len, 0, (struct sockaddr *)&to, salen) != len) {
+ node_perror("do_ping: sendto", errno);
+ close(fd);
+ return 0;
+ }
+ /*
+ * Now wait for it to come back (or user to abort).
+ */
+ if (fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK) == -1) {
+ node_perror("do_ping: fcntl - stdin", errno);
+ close(fd);
+ return 0;
+ }
+ while (1) {
+ FD_ZERO(&fdset);
+ FD_SET(fd, &fdset);
+ FD_SET(STDIN_FILENO, &fdset);
+ if (select(fd + 1, &fdset, 0, 0, 0) == -1) {
+ node_perror("do_ping: select", errno);
+ break;
+ }
+ if (FD_ISSET(fd, &fdset)) {
+ if ((len = recvfrom(fd, buf, 256, 0, (struct sockaddr *)&from, &salen)) == -1) {
+ node_perror("do_ping: recvfrom", errno);
+ break;
+ }
+ gettimeofday(&tv2, NULL);
+ ip = (struct iphdr *)buf;
+ /* Is it long enough? */
+ if (len >= (ip->ihl << 2) + sizeof(struct icmphdr)) {
+ len -= ip->ihl << 2;
+ icp = (struct icmphdr *)(buf + (ip->ihl << 2));
+ /* Is it ours? */
+ if (icp->type == ICMP_ECHOREPLY && icp->un.echo.id == id && icp->un.echo.sequence == sequence - 1) {
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo,"\e[01;35mICMP Echo reply received from: \e[0m");
+ }
+ if (check_perms(PERM_ANSI, 0L) == -1) {
+ axio_printf(NodeIo, "ICMP Echo reply received from: ");
+ }
+ node_msg("%s", inet_ntoa(to.sin_addr));
+ if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo,"%s} ", NodeId);
+ }
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[01;31m");
+ }
+ /* if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo,"%s} ", NodeId);
+ } */
+ axio_printf(NodeIo, "Ping completed in: %ldms (ttl=%d)", calc_rtt(tv2, tv1), ip->ttl);
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[0;m");
+ }
+ break;
+ }
+ }
+ }
+ if (FD_ISSET(STDIN_FILENO, &fdset)) {
+ if (axio_getline(NodeIo) != NULL) {
+ if (User.ul_type == AF_NETROM){
+ axio_printf(NodeIo,"%s} ", NodeId);
+ }
+ if (User.ul_type == AF_INET) {
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[05;38m");
+ }
+ }
+ axio_printf(NodeIo,"Aborted");
+ if (User.ul_type == AF_INET) {
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[0;m");
+ }
+ }
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ break;
+ } else if (errno != EAGAIN) {
+ break;
+ }
+ }
+ }
+ if (fcntl(STDIN_FILENO, F_SETFL, 0) == -1)
+ node_perror("do_ping: fcntl - stdin", errno);
+ close(fd);
+ return 0;
+}
+
diff --git a/ipc.c b/ipc.c
new file mode 100644
index 0000000..c171c34
--- /dev/null
+++ b/ipc.c
@@ -0,0 +1,193 @@
+/* oringinal by Heikki Hannikainen, modified by Brian Rogers */
+
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/msg.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <signal.h>
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+
+#include <netax25/ax25.h>
+#include <netrose/rose.h>
+#include <netax25/axlib.h>
+#include <netax25/axconfig.h>
+#include <netax25/nrconfig.h>
+#include <netax25/rsconfig.h>
+#include <netax25/procutils.h>
+
+#include "node.h"
+
+#define FIRST_KEY (3694 - 1) /* Where to start looking for a key */
+#define LAST_KEY (FIRST_KEY + 200) /* How far to search */
+#define M_LEN 1024 /* Largest message transferred */
+
+struct nmsgbuf {
+ long mtype; /* message type, must be > 0 */
+ char mtext[M_LEN]; /* message data */
+};
+
+static int ipc_id = -1;
+
+static void usr2_handler(int sig)
+{
+ struct nmsgbuf buf;
+
+ if (msgrcv(ipc_id, (struct msgbuf *)&buf, M_LEN, 0, IPC_NOWAIT|MSG_NOERROR) != -1) {
+ node_msg("%s", buf.mtext);
+ if (User.ul_type != AF_NETROM) {
+ node_prompt();
+ }
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ axio_flush(NodeIo);
+ } else
+ node_log(LOGLVL_ERROR, "usr2_handler: Caught SIGUSR2, but couldn't receive a message");
+
+ signal(SIGUSR2, usr2_handler); /* Restore handler */
+}
+
+int ipc_send(key_t key, long mtype, char *mtext)
+{
+ struct nmsgbuf buf;
+ int id;
+
+ if ((id = msgget(key, S_IRWXU)) == -1) {
+ node_perror("ipc_send: Could not get transmit channel", errno);
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ return -1;
+ }
+
+ buf.mtype = mtype;
+ strncpy(buf.mtext, mtext, M_LEN);
+
+ if (msgsnd(id, (struct msgbuf *)&buf, M_LEN, 0) == -1) {
+ node_perror("ipc_send: Could not send message", errno);
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ return -1;
+ }
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ return 0;
+}
+
+int ipc_open(void)
+{
+ key_t key = FIRST_KEY;
+
+ do {
+ key++;
+ ipc_id = msgget(key, S_IRWXU | IPC_CREAT | IPC_EXCL);
+ } while ((ipc_id == -1) && (key != LAST_KEY));
+
+ if (ipc_id == -1)
+ node_perror("ipc_open: Could not get an IPC channel", errno);
+
+#if 0
+ node_msg("debug: ipc_id=%d key=%d", ipc_id, key);
+#endif
+
+ User.ipc_key = key;
+
+ if (key != -1)
+ signal(SIGUSR2, usr2_handler);
+ else
+ signal(SIGUSR2, SIG_IGN);
+
+ return 0;
+}
+
+int ipc_close(void)
+{
+ struct msqid_ds buf;
+
+ if (ipc_id != -1) /* Remove the IPC channel */
+ if (msgctl(ipc_id, IPC_RMID, &buf) == -1) {
+ node_log(LOGLVL_ERROR, "ipc_close: Could not remove IPC channel: %s", strerror(errno));
+ return -1;
+ } else {
+ node_log(LOGLVL_ERROR, "ipc_close: Removing IPC channel for %s", User.call);
+ }
+ return 0;
+}
+
+int do_msg(int argc, char **argv)
+{
+ FILE *f;
+ struct user u;
+ char call[10];
+ char mtext[M_LEN];
+ int i, hits = 0, sent = 0;
+
+ if (argc < 3) {
+ node_msg("Usage: msg <call> <your text msg>");
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ return 0;
+ }
+
+ if ((f = fopen(DATA_NODE_LOGIN_FILE, "r")) == NULL) {
+ node_perror(DATA_NODE_LOGIN_FILE, errno);
+ return 0;
+ }
+ sprintf(mtext, "\n*** Msg from %s:\n\a", User.call);
+ for (i = 2; i < argc; i++) {
+ strncat(mtext, argv[i], M_LEN - strlen(mtext));
+ strncat(mtext, " ", M_LEN - strlen(mtext));
+ }
+ strncat(mtext, "\n*** End of msg.", M_LEN - strlen(mtext));
+ mtext[M_LEN - 1] = 0;
+
+ strncpy(call, argv[1], 9);
+ call[9] = 0;
+
+ while (fread(&u, sizeof(u), 1, f) == 1) {
+ if (u.pid == -1 || (kill(u.pid, 0) == -1 && errno == ESRCH))
+ continue;
+ if (!strcasecmp(u.call, call)) {
+ hits++;
+ if (u.ipc_key != -1 && u.state == STATE_IDLE) {
+ ipc_send(u.ipc_key, 1, mtext);
+ kill(u.pid, SIGUSR2);
+ sent++;
+ }
+ }
+ }
+ fclose(f);
+ if (hits == 0) {
+ if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo, "%s} ", NodeId);
+ }
+ axio_printf(NodeIo, "%s is not on the node now.\a", call);
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ } else if (sent == 0) {
+ if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo, "%s} ", NodeId);
+ }
+ axio_printf(NodeIo, "%s is busy and not accepting msgs now.\a", call);
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ } else if (sent != 0) {
+ if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo, "%s} ", NodeId);
+ }
+ axio_printf(NodeIo, "Msg sent to %s.\a", call);
+ }
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ axio_flush(NodeIo);
+ return 0;
+}
diff --git a/man/axdigi.8.gz b/man/axdigi.8.gz
new file mode 100644
index 0000000..a058441
Binary files /dev/null and b/man/axdigi.8.gz differ
diff --git a/man/flexd.conf.5.gz b/man/flexd.conf.5.gz
new file mode 100644
index 0000000..efa7cc8
Binary files /dev/null and b/man/flexd.conf.5.gz differ
diff --git a/man/nodeusers.1.gz b/man/nodeusers.1.gz
new file mode 100644
index 0000000..f5e2430
Binary files /dev/null and b/man/nodeusers.1.gz differ
diff --git a/man/uronode.8.gz b/man/uronode.8.gz
new file mode 100644
index 0000000..7d2e410
Binary files /dev/null and b/man/uronode.8.gz differ
diff --git a/man/uronode.conf.5.gz b/man/uronode.conf.5.gz
new file mode 100644
index 0000000..5ab80b0
Binary files /dev/null and b/man/uronode.conf.5.gz differ
diff --git a/man/uronode.perms.5.gz b/man/uronode.perms.5.gz
new file mode 100644
index 0000000..9e88876
Binary files /dev/null and b/man/uronode.perms.5.gz differ
diff --git a/mheard.c b/mheard.c
new file mode 100644
index 0000000..9c2ed9a
--- /dev/null
+++ b/mheard.c
@@ -0,0 +1,151 @@
+/* Routine rewritten mainly by Barry K2MF (Mr. MFNOS) and Brian N1URO */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netax25/ax25.h>
+#include <netrose/rose.h>
+
+#include <netax25/axlib.h>
+#include <netax25/axconfig.h>
+#include <netax25/mheard.h>
+
+#include "config.h" /* Bob VE3TOK 30Nov2014 */
+#include "procinfo.h"
+#include "node.h"
+
+struct mheard_list {
+ struct mheard_struct data;
+ struct mheard_list *next;
+};
+
+int do_mheard (int argc,char **argv) {
+ FILE *fp;
+ struct mheard_struct mh;
+ struct mheard_list *list = NULL, *new, *tmp, *p;
+ char *s, *t, *u;
+ int mhcount = 0;
+
+ axio_puts("",NodeIo);
+
+ if(User.ul_type == AF_NETROM)
+ axio_printf(NodeIo,"%s} ",NodeId);
+
+ if(argc > 1) {
+ if(ax25_config_get_dev(argv[1]) == NULL
+ || (check_perms(PERM_HIDDEN, 0) == -1
+ && is_hidden(argv[1]))) {
+ axio_printf(NodeIo,"Invalid port: %s",argv[1]);
+
+ if(User.ul_type == AF_NETROM)
+ node_msg("");
+
+ return 0;
+ }
+ }
+ if((fp = fopen(DATA_MHEARD_FILE,"r")) == NULL) {
+ node_perror(DATA_MHEARD_FILE,errno);
+ return 0;
+ }
+ while(mhcount < 20 && fread(&mh,sizeof(struct mheard_struct),1,fp)
+ == 1) {
+ if(argc > 1) {
+ if(strcmp(argv[1],mh.portname))
+ continue;
+ }
+ if(check_perms(PERM_HIDDEN,0) == -1 && is_hidden(mh.portname))
+ continue;
+
+ if((new = calloc(1,sizeof(struct mheard_list))) == NULL) {
+ node_perror("do_mheard: calloc",errno);
+ break;
+ }
+ new->data = mh;
+
+ if(list == NULL || mh.last_heard > list->data.last_heard) {
+ tmp = list;
+ list = new;
+ } else {
+ for(p = list; p->next != NULL; p = p->next) {
+ if(mh.last_heard > p->next->data.last_heard)
+ break;
+ }
+ tmp = p->next;
+ p->next = new;
+ }
+ new->next = tmp;
+ mhcount++;
+ }
+ fclose(fp);
+
+ if(check_perms(PERM_ANSI,0L) != -1)
+ axio_printf(NodeIo,"\e[01;33m");
+
+ node_msg("MHeard list:");
+
+ if(check_perms(PERM_ANSI,0L) != -1)
+ axio_printf(NodeIo,"\e[0;m");
+
+ axio_printf(NodeIo,"Callsign Device Packets Date & Time Frame Type(s)\n");
+ axio_printf(NodeIo,"--------- ------ -------- --------------- -------------");
+
+ while(list != NULL) {
+ s = ctime(&list->data.last_heard);
+ s[19] = 0;
+ s += 4;
+ t = ax25_ntoa(&list->data.from_call);
+
+ if((u = strstr(t,"-0")) != NULL)
+ *u = '\0';
+
+ axio_printf(NodeIo,"\n%-9s %-6s %-8d %s",t,list->data.portname,list->data.count,s);
+
+ if(list->data.mode & MHEARD_MODE_ARP)
+ axio_printf(NodeIo," ARP");
+
+ if(list->data.mode & MHEARD_MODE_FLEXNET)
+ axio_printf(NodeIo," FlexNet");
+
+ if(list->data.mode & MHEARD_MODE_IP_DG)
+ axio_printf(NodeIo," IP-DG");
+
+ if(list->data.mode & MHEARD_MODE_IP_VC)
+ axio_printf(NodeIo," IP-VC");
+
+ if(list->data.mode & MHEARD_MODE_NETROM)
+ axio_printf(NodeIo," NetRom");
+
+ if(list->data.mode & MHEARD_MODE_ROSE)
+ axio_printf(NodeIo," Rose");
+
+ if(list->data.mode & MHEARD_MODE_SEGMENT)
+ axio_printf(NodeIo," Segment");
+
+ if(list->data.mode & MHEARD_MODE_TEXNET)
+ axio_printf(NodeIo," TexNet");
+
+ if(list->data.mode & MHEARD_MODE_TEXT)
+ axio_printf(NodeIo," Text");
+
+ if(list->data.mode & MHEARD_MODE_PSATFT)
+ axio_printf(NodeIo," PacsatFT");
+
+ if(list->data.mode & MHEARD_MODE_PSATPB)
+ axio_printf(NodeIo," PacsatPB");
+
+ if(list->data.mode & MHEARD_MODE_UNKNOWN)
+ axio_printf(NodeIo," Unknown");
+
+ tmp = list;
+ list = list->next;
+ free(tmp);
+
+ }
+ if(User.ul_type == AF_NETROM)
+ node_msg("");
+ return 0;
+}
diff --git a/node.c b/node.c
new file mode 100644
index 0000000..f1ebafc
--- /dev/null
+++ b/node.c
@@ -0,0 +1,419 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <signal.h>
+#include <time.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <netax25/ax25.h>
+#include <netrose/rose.h>
+#include <netax25/axlib.h>
+#include <netax25/axconfig.h>
+#include <netax25/nrconfig.h>
+#include <netax25/rsconfig.h>
+#include <netax25/procutils.h>
+
+#include "node.h"
+
+ax25io *NodeIo = NULL;
+
+int aliascmd = 0;
+
+/*
+ * Do some validity checking for callsign pointed to by `s'.
+ */
+static int check_call(const char *s)
+{
+ int len = 0;
+ int nums = 0;
+ int ssid = 0;
+ char *p[1];
+
+ if (s == NULL)
+ return -1;
+ while (*s && *s != '-') {
+ if (!isalnum(*s))
+ return -1;
+ if (isdigit(*s))
+ nums++;
+ len++;
+ s++;
+ }
+ if (*s == '-') {
+ if (!isdigit(*++s))
+ return -1;
+ ssid = strtol(s, p, 10);
+ if (**p)
+ return -1;
+ }
+ if (len < 4 || len > 6 || !nums || nums > 2 || ssid < 0 || ssid > 15)
+ return -1;
+ return 0;
+}
+
+static void alarm_handler(int sig)
+{
+ axio_eolmode(NodeIo, EOLMODE_TEXT);
+ axio_puts("\n",NodeIo);
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo,"\e[05;31m");
+ }
+ if (User.ul_type == AF_NETROM) {
+ node_msg("%s} Inactivity timeout! Closing circuit... ", NodeId);
+ }
+ if ((User.ul_type == AF_AX25) || (User.ul_type == AF_ROSE)) {
+ node_msg("Inactivity timeout! Disconnecting you... ");
+ }
+ if (User.ul_type == AF_INET) {
+ node_msg("Inactivity timeout! Disconnecting you...");
+ }
+ if (User.ul_type == AF_INET) {
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo,"\e[0;m");
+ }
+ }
+ node_logout("User timed out");
+}
+
+static void term_handler(int sig)
+{
+ axio_eolmode(NodeIo, EOLMODE_TEXT);
+ if (User.ul_type == AF_NETROM) {
+ node_msg("%s} Termination received!", NodeId);
+ } else {
+ node_msg("%s - System going down! Disconnecting...", FlexId);
+ }
+ node_logout("SIGTERM");
+}
+
+static void quit_handler(int sig)
+{
+ axio_eolmode(NodeIo, EOLMODE_TEXT);
+ node_logout("User terminated at remote");
+}
+
+int main(int argc, char *argv[])
+{
+ union {
+ struct full_sockaddr_ax25 sax;
+#ifdef HAVE_ROSE
+ struct sockaddr_rose srose;
+#endif
+ struct sockaddr_in sin;
+ } saddr;
+ int i, slen = sizeof(saddr);
+#ifdef HAVEMOTD
+ char *p, buf[256], *pw;
+#else
+ char *p, *pw;
+#endif
+ int paclen;
+#ifdef HAVEMOTD
+ FILE *fp;
+#endif
+ int invalid_cmds = 0;
+ int no_password = 2;
+ int first_time = 1;
+
+ signal(SIGALRM, alarm_handler);
+ signal(SIGTERM, term_handler);
+ signal(SIGPIPE, quit_handler);
+ signal(SIGQUIT, quit_handler);
+
+#ifdef HAVE_AX25
+ if (ax25_config_load_ports() == 0) {
+ node_log(LOGLVL_ERROR, "No AX.25 port data configured");
+ return 1;
+ }
+#endif
+
+#ifdef HAVE_NETROM
+ nr_config_load_ports();
+#endif
+#ifdef HAVE_ROSE
+ rs_config_load_ports();
+#endif
+ if (getpeername(STDOUT_FILENO, (struct sockaddr *)&saddr, &slen) == -1) {
+ if (errno != ENOTSOCK) {
+ node_log(LOGLVL_ERROR, "getpeername: %s", strerror(errno));
+ return 1;
+ }
+ User.ul_type = AF_UNSPEC;
+ } else
+ User.ul_type = saddr.sax.fsa_ax25.sax25_family;
+ switch (User.ul_type) {
+ case AF_FLEXNET:
+ case AF_AX25:
+ strcpy(User.call, ax25_ntoa(&saddr.sax.fsa_ax25.sax25_call));
+ if (getsockname(STDOUT_FILENO, (struct sockaddr *)&saddr.sax, &slen) == -1) {
+ node_log(LOGLVL_ERROR, "getsockname: %s", strerror(errno));
+ return 1;
+ }
+ strcpy(User.ul_name, ax25_config_get_port(&saddr.sax.fsa_digipeater[0]));
+ paclen = ax25_config_get_paclen(User.ul_name);
+ p = AX25_EOL;
+ break;
+ case AF_NETROM:
+ strcpy(User.call, ax25_ntoa(&saddr.sax.fsa_ax25.sax25_call));
+ strcpy(User.ul_name, ax25_ntoa(&saddr.sax.fsa_digipeater[0]));
+ if (getsockname(STDOUT_FILENO, (struct sockaddr *)&saddr.sax, &slen) == -1) {
+ node_log(LOGLVL_ERROR, "getsockname: %s", strerror(errno));
+ return 1;
+ }
+ strcpy(User.ul_port, nr_config_get_port(&saddr.sax.fsa_ax25.sax25_call));
+ paclen = nr_config_get_paclen(User.ul_port);
+ p = NETROM_EOL;
+ break;
+#ifdef HAVE_ROSE
+ case AF_ROSE:
+ strcpy(User.call, ax25_ntoa(&saddr.srose.srose_call));
+ strcpy(User.ul_name, rose_ntoa(&saddr.srose.srose_addr));
+ paclen = rs_config_get_paclen(NULL);
+ p = ROSE_EOL;
+ break;
+#endif
+ case AF_INET:
+ case AF_INET6:
+ strcpy(User.ul_name, inet_ntoa(saddr.sin.sin_addr));
+ paclen = 1024;
+ p = INET_EOL;
+ break;
+ case AF_UNSPEC:
+ strcpy(User.ul_name, "local");
+ if ((p = get_call(getuid())) == NULL) {
+ node_log(LOGLVL_ERROR, "No uid->callsign association found", -1);
+ printf("Launching: telnet localhost 3694 ...\n");
+ printf("if this fails please RTFM to see how to properly configure it.\n - 73 de N1URO\a\n");
+ node_log(LOGLVL_ERROR, "Tool ran me from the console so I'm forcing", -1);
+ node_log(LOGLVL_ERROR, "a telnet session to port 3694/tcp on them.", -1);
+ /* axio_flush(NodeIo); */
+ if(NodeIo!=NULL)
+ axio_flush(NodeIo);
+ if (system("telnet 127.0.0.1 3694") < 0 ) { /* VE3TOK - 18Nov2014, return value */
+ syslog(LOG_DEBUG, "Can't \"execute telnet 127.0.0.1 3694\"");
+ return 1;
+ }
+ node_log(LOGLVL_ERROR,"Closing console telnet session.", -1);
+ return -1;
+ }
+ strcpy(User.call, p);
+ paclen = 1024;
+ p = UNSPEC_EOL;
+ break;
+ default:
+ node_log(LOGLVL_ERROR, "Unsupported address family %d", User.ul_type);
+ return 1;
+ }
+ NodeIo = axio_init(STDIN_FILENO, STDOUT_FILENO, paclen, p);
+ if (NodeIo == NULL) {
+ node_log(LOGLVL_ERROR, "Error initializing I/O");
+ return 1;
+ }
+#ifdef HAVE_ZLIB_H
+ if (argc > 1 && strcmp(argv[1], "-c") == 0) {
+ axio_compr(NodeIo, 1);
+ }
+#endif
+ if (User.ul_type == AF_INET) {
+ axio_tnmode(NodeIo, 1);
+ axio_tn_do_linemode(NodeIo);
+ }
+ init_nodecmds();
+ if (read_config() == -1) {
+ axio_end(NodeIo);
+ return 1;
+ }
+ for(i=1;i<argc;i++) {
+ if (strcmp(argv[i],"--delay")==0) {
+ axio_flush(NodeIo);
+ p = axio_getline(NodeIo);
+ }
+ }
+ User.state = STATE_LOGIN;
+ login_user();
+ if (User.call[0] == 0) {
+ axio_printf(NodeIo,"(%s:uronode) login: ", HostName);
+ axio_flush(NodeIo);
+ alarm(60L); /* 1 min timeout */
+ if ((p = axio_getline(NodeIo)) == NULL)
+ node_logout("User disconnected");
+ alarm(0L);
+ strncpy(User.call, p, 9);
+ User.call[9] = 0;
+ strlwr(User.call);
+ }
+ if ((p = strstr(User.call, "-0")) != NULL)
+ *p = 0;
+ if (check_call(User.call) == -1) {
+ node_msg("%s - Invalid callsign", FlexId);
+ node_log(LOGLVL_LOGIN, "Invalid callsign %s @ %s", User.call, User.ul_name);
+ node_logout("Invalid callsign");
+ }
+ if ((pw = read_perms(&User, saddr.sin.sin_addr.s_addr)) == NULL) {
+ node_msg("Sorry, I'm not allowed to talk to you.");
+ node_log(LOGLVL_LOGIN, "Login denied for %s @ %s", User.call, User.ul_name);
+ node_logout("Login denied");
+ } else if (strcmp(pw, "*") != 0) {
+ node_msg("*** Password required! If you don't have a password please email\r\n%s for a password you wish to use.", Email);
+ axio_printf(NodeIo,"\rPassword: ");
+ if (User.ul_type == AF_INET) {
+ axio_tn_will_echo(NodeIo);
+ axio_eolmode(NodeIo, EOLMODE_BINARY);
+ }
+ axio_flush(NodeIo);
+ p = axio_getline(NodeIo);
+ if (User.ul_type == AF_INET) {
+ axio_tn_wont_echo(NodeIo);
+ axio_eolmode(NodeIo, EOLMODE_TEXT);
+ /* axio_puts("\n",NodeIo); */
+ }
+ if (p == NULL || strcmp(p, pw) != 0) {
+ axio_printf(NodeIo, "\n");
+ if (User.ul_type == AF_NETROM) {
+ node_msg("%s} Invalid or incorrect password...", NodeId);
+ } else {
+ node_msg("%s Invalid or incorrect password...", FlexId);
+ }
+ node_log(LOGLVL_LOGIN, "Login failed for %s @ %s", User.call, User.ul_name);
+ node_logout("Login failed");
+ }
+ no_password = 0;
+ };
+ free(pw);
+ examine_user();
+ ipc_open();
+ node_log(LOGLVL_LOGIN, "%s @ %s logged in", User.call, User.ul_name);
+#ifdef HAVEMOTD
+ if (User.ul_type == AF_NETROM) {
+ /* axio_printf(NodeIo, "%s} Welcome.\n", NodeId); */
+ } else
+ if (User.ul_type == AF_INET) {
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ node_msg("\n\e[01;34m[\e[01;37m%s\e[01;34m]\e[0m\nWelcome %s to the %s packet shell.", VERSION, User.call, HostName);
+ } else if (check_perms(PERM_ANSI, 0L) == -1) {
+ node_msg("\n[%s]\nWelcome %s to the %s packet shell.", VERSION, User.call, HostName);
+ }
+ if ((fp = fopen(HAVEMOTD, "r")) != NULL) {
+ while (fgets(buf,256, fp) != NULL) axio_puts(buf,NodeIo);
+ axio_printf (NodeIo, "\n");
+ axio_flush(NodeIo);
+ }
+ } else if (User.ul_type == AF_AX25) {
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ node_msg("\e[01;34m[\e[01;37m%s\e[01;34m]\e[0m - Welcome to %s", VERSION, FlexId);
+ } else
+ node_msg("%s - Welcome to %s", VERSION, FlexId);
+ if ((fp = fopen(HAVEMOTD, "r")) != NULL) {
+ while (fgets(buf, 256, fp) != NULL) axio_puts(buf,NodeIo);
+ axio_puts ("\n",NodeIo);
+ axio_flush(NodeIo);
+ }
+ } else if (User.ul_type == AF_ROSE) {
+ node_msg("%s - Welcome to %s", VERSION, RoseId);
+ if ((fp = fopen(HAVEMOTD, "r")) != NULL) {
+ while (fgets(buf, 256, fp) != NULL) axio_puts(buf,NodeIo);
+ axio_puts ("\n",NodeIo);
+ axio_flush(NodeIo);
+ }
+ }
+ lastlog();
+#endif
+ axio_flush(NodeIo);
+ while (1) { if (User.ul_type != AF_NETROM) {
+ axio_flush(NodeIo);
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo,"\e[01;34");
+ }
+ if (no_password == 2) {
+ node_prompt();
+ }
+ if (no_password == 1) {
+ node_prompt();
+ no_password = 2;
+ }
+ if (no_password == 0)
+ {
+ if (first_time == 1)
+ {
+ first_time = 0;
+ if (User.ul_type != AF_NETROM) {
+ /* node_prompt("3"); */
+ if ((User.ul_type == AF_AX25) || (User.ul_type == AF_ROSE)) {
+ node_prompt();
+ }
+ }
+ }
+ else if ((User.ul_type != AF_NETROM) && (User.ul_type != AF_ROSE)) {
+ node_prompt();
+ } else if ((User.ul_type == AF_NETROM) || (User.ul_type == AF_ROSE)) {
+ axio_printf(NodeIo,"\n");
+ }
+ }
+ }
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ /* Not needed from what I see so far. */
+ if (User.ul_type == AF_AX25) {
+ axio_printf(NodeIo,"\e[0m");
+ }
+ }
+ axio_flush(NodeIo);
+ User.state = STATE_IDLE;
+ time(&User.cmdtime);
+ update_user();
+ alarm(IdleTimeout);
+ errno = 0;
+ if ((p = axio_getline(NodeIo)) == NULL) {
+ if (errno == EINTR)
+ continue;
+ node_logout("User disconnected");
+ };
+ alarm(IdleTimeout);
+ errno = 0;
+ time(&User.cmdtime);
+ update_user();
+ aliascmd = 0;
+ switch (cmdparse(Nodecmds, p))
+ {
+ case -1:
+ if (++invalid_cmds < 3) {
+ /* node_msg("%s Unknown command. Type ? for a list", NodeId); */
+ if (User.ul_type == AF_NETROM) {
+ node_msg("What?\007");
+ } else if (User.ul_type == AF_ROSE) {
+ axio_printf(NodeIo,"Que?\007");
+ } else if (User.ul_type == AF_INET) {
+ axio_printf(NodeIo, "Huh?\007");
+ } else {
+ axio_printf(NodeIo,"Eh?\007");
+ }
+ node_log(LOGLVL_ERROR,"%s Tool tried bogus command", NodeId);
+ }
+ else {
+ if (User.ul_type == AF_NETROM) {
+ node_msg("%s Too many invalid commands. Disconnecting...", NodeId);
+ node_logout("Too many invalid commands");
+ } else {
+ node_msg("Too many invalid commands, disconnecting you...");
+ node_logout("Too many invalid commands");
+ }
+ }
+ break;
+ case 0:
+ invalid_cmds = 0;
+ /* axio_puts ("\n",NodeIo); */
+ break;
+ case 1:
+ invalid_cmds = 0;
+ break;
+ case 2:
+ invalid_cmds = 0;
+ break;
+ }
+ }
+ node_logout("Out of main loop !?!?!?");
+}
diff --git a/node.h b/node.h
new file mode 100644
index 0000000..20a0f87
--- /dev/null
+++ b/node.h
@@ -0,0 +1,172 @@
+#define VERSION "URONode v2.3.1"
+#define COMPILING "February 14, 2015"
+
+#define STATE_IDLE 0
+#define STATE_TRYING 1
+#define STATE_CONNECTED 2
+#define STATE_PINGING 3
+#define STATE_EXTCMD 4
+#define STATE_LOGIN 5
+#define STATE_QUIT 6
+
+#define LOGLVL_NONE 0
+#define LOGLVL_ERROR 1
+#define LOGLVL_LOGIN 2
+#define LOGLVL_GW 3
+
+#define PERM_LOGIN 1 /* Permit login */
+#define PERM_AX25 2 /* AX.25 gatewaying */
+#define PERM_NETROM 4 /* NETROM gatewaying */
+#define PERM_TELNET_LOCAL 8 /* Telnet to "local" hosts */
+#define PERM_TELNET_AMPR 16 /* Telnet to 44.xx.xx.xx hosts */
+#define PERM_TELNET_INET 32 /* Telnet to other hosts */
+#define PERM_ANSI 64 /* Ansi Color graphics */
+#define PERM_ROSE 128 /* ROSE gatewaying */
+#define PERM_NOESC 256 /* No escape character */
+#define PERM_HIDDEN 512 /* Use hidden ports - to be removed */
+
+#define PERM_TELNET (PERM_TELNET_LOCAL & PERM_TELNET_AMPR & PERM_TELNET_INET)
+
+/* Fake id for Flexnet */
+#define AF_FLEXNET 128
+
+#include <sys/types.h>
+#include <sys/ipc.h> /* for key_t */
+#include <errno.h>
+
+#include <netax25/ax25io.h>
+
+#include "config.h"
+
+struct user
+{
+ pid_t pid;
+ key_t ipc_key;
+ time_t logintime;
+ time_t cmdtime;
+ unsigned char state;
+ char call[10];
+ unsigned short ul_type;
+ unsigned short dl_type;
+ char ul_name[32];
+ char dl_name[32];
+ char ul_port[32];
+ char dl_port[32];
+
+ char unused[92];
+};
+
+extern struct user User;
+
+extern ax25io *NodeIo;
+
+extern long IdleTimeout;
+extern long ConnTimeout;
+extern int ReConnectTo;
+extern int LogLevel;
+extern int EscChar;
+extern int aliascmd;
+
+extern char *Email;
+extern char *HostName;
+extern char *NodeId;
+extern char *FlexId;
+extern char *RoseId;
+extern char *NrPort;
+extern char *Prompt;
+extern char *PassPrompt;
+
+#define CMD_INTERNAL 1
+#define CMD_ALIAS 2
+#define CMD_EXTERNAL 3
+
+struct cmd {
+ char *name;
+ int len;
+ int type;
+ int (*function) (int argc, char **argv);
+ char *command;
+ int flags;
+ int uid;
+ int gid;
+ char *path;
+
+ struct cmd *next;
+};
+
+extern struct cmd *Nodecmds;
+
+#define min(a,b) ((a) < (b) ? (a) : (b))
+#define max(a,b) ((a) > (b) ? (a) : (b))
+
+/* in cmdparse.c */
+void free_cmdlist(struct cmd *list);
+extern void insert_cmd(struct cmd **list, struct cmd *new);
+extern int add_internal_cmd(struct cmd **list, char *name, int len, int (*function) (int argc, char **argv));
+/* extern char *expand_string(char *str, int argc, char **argv); */
+extern int parse_args(char **argv, char *cmd);
+extern int cmdparse(struct cmd *cmdp, char *cmdline);
+
+/* in util.c */
+extern void node_msg(const char *fmt, ...);
+extern void node_perror(char *str, int err);
+extern char *print_node(const char *alias, const char *call);
+extern void node_log(int, const char *, ...);
+
+/* in user.c */
+extern void login_user(void);
+extern void logout_user(void);
+extern void update_user(void);
+extern int user_list(int argc, char **argv);
+extern int user_count(void);
+extern int system_user_count(void);
+
+/* in config.c */
+extern int is_hidden(const char *port);
+extern int check_perms(int what, unsigned long peer);
+extern char *read_perms(struct user *up, unsigned long peer);
+extern int read_config(void);
+extern int get_escape(char *s);
+
+/* in command.c */
+void init_nodecmds(void);
+extern void node_logout(char *reason);
+extern int nuser_list(int argc, char **argv);
+extern int do_bye(int argc, char **argv);
+extern int do_escape(int argc, char **argv);
+extern int do_help(int argc, char **argv);
+extern int do_host(int argc, char **argv);
+extern int do_ports(int argc, char **argv);
+extern int do_sessions(int argc, char **argv);
+extern int do_routes(int argc, char **argv);
+extern int do_nodes(int argc, char **argv);
+extern int do_status(int argc, char **argv);
+extern int do_version(int argc, char **argv);
+extern int do_last(int argc, char **last);
+
+/* in gateway.c */
+extern int do_connect(int argc, char **argv);
+extern int do_finger(int argc, char **argv);
+extern int do_ping(int argc, char **argv);
+
+/* in router.c */
+extern int do_links(int argc, char **argv);
+extern int do_dest(int argc, char **argv);
+
+/* in ipc.c */
+extern int ipc_open(void);
+extern int ipc_close(void);
+extern int do_msg(int argc, char **argv);
+
+/* in extcmd.c */
+extern int extcmd(struct cmd *cmdp, char **argv);
+
+/* in system.c */
+extern int do_system(int argc, char **argv);
+extern int examine_user(void);
+extern void newmail(void);
+extern void mailcheck(void);
+extern void lastlog(void);
+
+/* in mheard.c */
+extern int do_mheard(int argc, char **argv);
diff --git a/nodeusers.c b/nodeusers.c
new file mode 100644
index 0000000..1190a20
--- /dev/null
+++ b/nodeusers.c
@@ -0,0 +1,82 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/file.h>
+#include <sys/socket.h>
+#include <signal.h>
+#include <syslog.h>
+#include <netax25/ax25.h>
+#include <netrose/rose.h>
+#include <netax25/axlib.h>
+#include <netax25/procutils.h>
+
+#include "node.h"
+#include "config.h"
+
+char *NodeId = "Nodeusers:";
+int LogLevel = LOGLVL_NONE;
+ax25io *NodeIo = NULL;
+static void pipe_handler(int sig)
+{
+ syslog(LOG_ERR, "received SIGPIPE");
+ axio_end(NodeIo);
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+ int n, len = 1024;
+ char *cp = UNSPEC_EOL;
+ int inet = 0;
+ int logging = 0;
+
+ while ((n = getopt(argc, argv, "ail")) != -1) {
+ switch (n) {
+ case 'a':
+ cp = AX25_EOL;
+ len = 128;
+ break;
+ case 'i':
+ cp = INET_EOL;
+ inet = 1;
+ break;
+ case 'l':
+ logging = 1;
+ break;
+
+ default:
+ fprintf(stderr, "usage: nodeusers [-a] [-i] [-l]\r\n");
+ return 1;
+ }
+ }
+ if (logging)
+ openlog("nodeusers", LOG_PID, LOG_DAEMON);
+ signal(SIGPIPE, pipe_handler);
+ NodeIo = axio_init(STDIN_FILENO, STDOUT_FILENO, len, cp);
+ if (NodeIo == NULL) {
+ fprintf(stderr, "nodeusers: axio_init failes\r\n");
+ return 1;
+ }
+ if (inet && axio_getline(NodeIo) == NULL) {
+ if (logging)
+ syslog(LOG_ERR, "axio_getline: %m");
+ axio_printf(NodeIo,"\n");
+ axio_end(NodeIo);
+ return 1;
+ }
+ n = user_count();
+ axio_printf(NodeIo,"\n%s (%s), %d user%s.\n",
+ VERSION, COMPILING, n, n == 1 ? "" : "s");
+ user_list(0, NULL);
+ if (n > 0)
+ axio_printf(NodeIo,"\n");
+ if (axio_flush(NodeIo) == -1 && logging)
+ syslog(LOG_ERR, "axio_flush: %m");
+ axio_end(NodeIo);
+ usleep(500000L);
+ closelog();
+ return 0;
+}
diff --git a/procinfo.c b/procinfo.c
new file mode 100644
index 0000000..7673cbb
--- /dev/null
+++ b/procinfo.c
@@ -0,0 +1,358 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+
+#include <netax25/ax25.h>
+#include <netrose/rose.h>
+#include <netax25/axlib.h>
+#include <netax25/axconfig.h>
+#include <netax25/mheard.h>
+
+#include "procinfo.h"
+
+#include "node.h"
+
+
+/*
+ * Version of atoi() that returns zero if s == NULL.
+ */
+int safe_atoi(const char *s)
+{
+ return (s == NULL) ? 0 : atoi(s);
+}
+
+/*
+ * Version of strncpy() that returns NULL if either src or dest is NULL
+ * and also makes sure destination string is always terminated.
+ */
+char *safe_strncpy(char *dest, char *src, int n)
+{
+ if (dest == NULL || src == NULL) return NULL;
+ dest[n] = 0;
+ return strncpy(dest, src, n);
+}
+
+struct proc_dev *read_proc_dev(void)
+{
+ FILE *fp;
+ char buffer[256];
+ struct proc_dev *p;
+ struct proc_dev *list = NULL;
+ int i = 0;
+
+ errno = 0;
+ if ((fp = fopen(PROC_DEV_FILE, "r")) == NULL) return NULL;
+ while (fgets(buffer, 256, fp) != NULL) {
+ if (i++<2) continue;
+ if ((p = calloc(1, sizeof(struct proc_dev))) == NULL) break;
+
+ safe_strncpy(p->interface, strtok(buffer, ":\n\r"), 6);
+ while (*p->interface==' ') strcpy(p->interface, p->interface+1);
+ p->rx_bytes = safe_atoi(strtok(NULL, " \t\n\r"));
+ p->rx_packets = safe_atoi(strtok(NULL, " \t\n\r"));
+ p->rx_errs = safe_atoi(strtok(NULL, " \t\n\r"));
+ p->rx_drop = safe_atoi(strtok(NULL, " \t\n\r"));
+ p->rx_fifo = safe_atoi(strtok(NULL, " \t\n\r"));
+ p->rx_frame = safe_atoi(strtok(NULL, " \t\n\r"));
+ p->rx_compressed = safe_atoi(strtok(NULL, " \t\n\r"));
+ p->rx_multicast = safe_atoi(strtok(NULL, " \t\n\r"));
+ p->tx_bytes = safe_atoi(strtok(NULL, " \t\n\r"));
+ p->tx_packets = safe_atoi(strtok(NULL, " \t\n\r"));
+ p->tx_errs = safe_atoi(strtok(NULL, " \t\n\r"));
+ p->tx_drop = safe_atoi(strtok(NULL, " \t\n\r"));
+ p->tx_fifo = safe_atoi(strtok(NULL, " \t\n\r"));
+ p->tx_colls = safe_atoi(strtok(NULL, " \t\n\r"));
+ p->tx_carrier = safe_atoi(strtok(NULL, " \t\n\r"));
+ p->tx_compressed = safe_atoi(strtok(NULL, " \t\n\r"));
+ p->next = list;
+ list = p;
+ }
+ fclose(fp);
+ return list;
+}
+
+void free_proc_dev(struct proc_dev *ap)
+{
+ struct proc_dev *p;
+
+ while (ap != NULL) {
+ p = ap->next;
+ free(ap);
+ ap = p;
+ }
+}
+
+struct flex_gt *read_flex_gt(void)
+{
+ FILE *fp;
+ char buffer[256], *cp;
+ struct flex_gt *p=NULL, *list = NULL, *new_el;
+ int i = 0, k;
+
+ errno = 0;
+ if ((fp = fopen(FLEX_GT_FILE, "r")) == NULL) return NULL;
+ while (fgets(buffer, 256, fp) != NULL) {
+ if (i++<1) continue;
+ if ((new_el = calloc(1, sizeof(struct flex_gt))) == NULL) break;
+
+ new_el->addr = safe_atoi(strtok(buffer, " \t\n\r"));
+ safe_strncpy(new_el->call, strtok(NULL, " \t\n\r"), 9);
+ safe_strncpy(new_el->dev, strtok(NULL, " \t\n\r"), 4);
+
+ k=0;
+ while((cp=strtok(NULL, " \t\n\r"))!=NULL&&k<AX25_MAX_DIGIS) safe_strncpy(new_el->digis[k++],cp,9);
+ while(k<AX25_MAX_DIGIS) strcpy(new_el->digis[k++],"\0");
+
+ if(list==NULL) {
+ list=new_el;
+ p=list;
+ } else {
+ p->next = new_el;
+ p=p->next;
+ }
+ }
+ fclose(fp);
+ return list;
+}
+
+void free_flex_gt(struct flex_gt *fp)
+{
+ struct flex_gt *p;
+
+ while (fp != NULL) {
+ p = fp->next;
+ free(fp);
+ fp = p;
+ }
+}
+
+struct flex_dst *read_flex_dst(void)
+{
+ FILE *fp;
+ char buffer[256];
+ struct flex_dst *p=NULL, *list = NULL, *new_el;
+ int i = 0;
+
+ errno = 0;
+ if ((fp = fopen(FLEX_DST_FILE, "r")) == NULL) return NULL;
+ while (fgets(buffer, 256, fp) != NULL) {
+ if (i++<1) continue;
+ if ((new_el = calloc(1, sizeof(struct flex_dst))) == NULL) break;
+
+ safe_strncpy(new_el->dest_call, strtok(buffer, " \t\n\r"), 9);
+ new_el->ssida = safe_atoi(strtok(NULL, " -\t\n\r"));
+ new_el->sside = safe_atoi(strtok(NULL, " -\t\n\r"));
+ new_el->rtt = safe_atoi(strtok(NULL, " \t\n\r"));
+ new_el->addr = safe_atoi(strtok(NULL, " \t\n\r"));
+
+ if(list==NULL) {
+ list=new_el;
+ p=list;
+ } else {
+ p->next = new_el;
+ p=p->next;
+ }
+ }
+ fclose(fp);
+ return list;
+}
+
+void free_flex_dst(struct flex_dst *fp)
+{
+ struct flex_dst *p;
+
+ while (fp != NULL) {
+ p = fp->next;
+ free(fp);
+ fp = p;
+ }
+}
+
+struct ax_routes *read_ax_routes(void)
+{
+ FILE *fp;
+ char buffer[256], *cp, *cmd;
+ struct ax_routes *p=NULL, *list = NULL, *new_el;
+ int i = 0, k;
+
+ errno = 0;
+ if ((fp = fopen(AX_ROUTES_FILE, "r")) == NULL) return NULL;
+ while (fgets(buffer, 256, fp) != NULL) {
+ if (i++<1) continue;
+
+ if(*buffer=='#' || *buffer==' ' ) continue; /* commented line */
+ cp=strchr(buffer, '#'); /* ignore comments */
+ if (cp) *cp='\0';
+
+ cmd=strtok(buffer, " \t\n\r");
+ if(cmd==NULL) continue; /* empty line */
+
+ if (strcasecmp(cmd,"route")==0) { /* add route */
+ if ((new_el = calloc(1, sizeof(struct ax_routes))) == NULL) break;
+ safe_strncpy(new_el->dest_call, strupr(strtok(NULL, " \t\n\r")), 9);
+ safe_strncpy(new_el->alias, strupr(strtok(NULL, " \t\n\r")), 9);
+ safe_strncpy(new_el->dev, strtok(NULL, " \t\n\r"), 13);
+ safe_strncpy(new_el->conn_type, strupr(strtok(NULL, " \t\n\r")), 1);
+ safe_strncpy(new_el->description, strtok(NULL, "'\t\n\r"), 50);
+ if (new_el->description==NULL) strcpy(new_el->description," ");
+
+ switch(*new_el->conn_type) {
+ case CONN_TYPE_DIRECT:
+ {
+ break;
+ }
+ case CONN_TYPE_NODE:
+ {
+ safe_strncpy(new_el->digis[0], strupr(strtok(NULL, " \t\n\r")), 9);
+
+ break;
+ }
+ case CONN_TYPE_DIGI:
+ {
+ k=0;
+ while((cp=strtok(NULL, " \t\n\r"))!=NULL&&k<AX25_MAX_DIGIS)
+ safe_strncpy(new_el->digis[k++],strupr(cp),9);
+ while(k<AX25_MAX_DIGIS) strcpy(new_el->digis[k++],"\0");
+ break;
+ }
+ default:
+ {
+ return NULL;
+ break;
+ }
+ }
+
+
+ if(list==NULL) {
+ list=new_el;
+ p=list;
+ } else {
+ p->next = new_el;
+ p=p->next;
+ }
+ }
+ }
+ fclose(fp);
+ return list;
+}
+
+void free_ax_routes(struct ax_routes *ap)
+{
+ struct ax_routes *p;
+
+ while (ap != NULL) {
+ p = ap->next;
+ free(ap);
+ ap = p;
+ }
+}
+
+struct ax_routes *find_route(char *dest_call, struct ax_routes *list)
+{
+ static struct ax_routes a;
+ struct ax_routes *axrt=NULL, *p;
+ char *cp, call[10];
+
+ safe_strncpy(call,dest_call,9);
+
+ if ((cp = strchr(call, '-')) != NULL && *(cp + 1) == '0') *cp = 0;
+ axrt=list?list:read_ax_routes();
+ for (p=axrt;p!=NULL;p=p->next) {
+ if (!strcasecmp(call, p->dest_call)) {
+ a = *p;
+ a.next = NULL;
+ p = &a;
+ break;
+ }
+ if (!strcasecmp(call, p->alias)) {
+ a = *p;
+ a.next = NULL;
+ p = &a;
+ break;
+ }
+
+ }
+ if (list==NULL) free_ax_routes(axrt);
+ return p;
+}
+
+struct flex_dst *find_dest(char *dest_call, struct flex_dst *list)
+{
+ static struct flex_dst f;
+ struct flex_dst *fdst=NULL, *p;
+ char *cp, call[10];
+ int ssid;
+
+ safe_strncpy(call, dest_call, 9);
+ cp=strchr(call,'-');
+ if (cp==NULL) ssid=0;
+ else {
+ ssid=safe_atoi(cp+1);
+ *cp='\0';
+ }
+
+ fdst=list?list:read_flex_dst();
+ for (p=fdst;p!=NULL;p=p->next) {
+ if (!strcasecmp(call, p->dest_call) && (ssid>=p->ssida && ssid<=p->sside)) {
+ f = *p;
+ f.next = NULL;
+ p = &f;
+ break;
+ }
+ }
+ if (list==NULL) free_flex_dst(fdst);
+ return p;
+}
+
+struct flex_gt *find_gateway(int addr, struct flex_gt *list)
+{
+ static struct flex_gt f;
+ struct flex_gt *flgt=NULL, *p;
+
+ flgt=list?list:read_flex_gt();
+ for (p=flgt;p!=NULL;p=p->next) {
+ if (addr==p->addr) {
+ f = *p;
+ f.next = NULL;
+ p = &f;
+ break;
+ }
+ }
+ if (list==NULL) free_flex_gt(flgt);
+ return p;
+}
+
+struct ax_routes *find_mheard(char *dest_call)
+{
+ FILE *fp;
+ static struct ax_routes a;
+ struct mheard_struct mh;
+ char call[12];
+ char *cp;
+ int k;
+
+ if ((fp = fopen(DATA_MHEARD_FILE, "r")) == NULL) {
+ return NULL;
+ }
+
+ safe_strncpy(call,dest_call,9);
+ cp=strchr(call, '-');
+ if (cp==NULL) strcat(call,"-0");
+
+ while (fread(&mh, sizeof(struct mheard_struct), 1, fp) == 1) {
+ if (strcasecmp(call, ax25_ntoa(&mh.from_call))==0) {
+ fclose(fp);
+ safe_strncpy(a.dest_call, ax25_ntoa(&mh.from_call), 9);
+ safe_strncpy(a.dev, mh.portname, 13);
+ for(k=0;k<AX25_MAX_DIGIS;k++) {
+ if (k<=mh.ndigis) safe_strncpy(a.digis[k],ax25_ntoa(&mh.digis[k]),9);
+ else strcpy(a.digis[k],"\0");
+ }
+ return &a;
+ }
+ }
+ fclose(fp);
+
+ return NULL;
+}
diff --git a/procinfo.h b/procinfo.h
new file mode 100644
index 0000000..366a7bd
--- /dev/null
+++ b/procinfo.h
@@ -0,0 +1,99 @@
+#ifndef _PROCINFO_H
+#define _PROCINFO_H
+
+#define PROC_NR_FILE "/proc/net/nr"
+#define PROC_DEV_FILE "/proc/net/dev"
+
+/* VE3TOK 30Nov2014 - A number of defines moved to config.h */
+
+#define CONN_TYPE_DIRECT 'D'
+#define CONN_TYPE_NODE 'N'
+#define CONN_TYPE_DIGI 'V'
+
+struct proc_dev {
+ char interface[6];
+ int rx_bytes;
+ int rx_packets;
+ int rx_errs;
+ int rx_drop;
+ int rx_fifo;
+ int rx_frame;
+ int rx_compressed;
+ int rx_multicast;
+ int tx_bytes;
+ int tx_packets;
+ int tx_errs;
+ int tx_drop;
+ int tx_fifo;
+ int tx_colls;
+ int tx_carrier;
+ int tx_compressed;
+
+ struct proc_dev *next;
+};
+
+
+/*
+ * /var/ax25/flex/gateways: (example)
+ * addr callsign dev dest digipeaters
+ * 00001 PI4TUE ax1 935
+ */
+
+struct flex_gt {
+ int addr;
+ char call[10];
+ char dev[14];
+ char digis[AX25_MAX_DIGIS][10];
+
+ struct flex_gt *next;
+};
+
+/*
+ * /usr/local/var/ax25/flex/destinations: (example)
+ * callsign ssid rtt gateway
+ * 9A0XZG 0-15 2575 00001
+ * DB0AAA 0-0 63 00001
+ */
+
+struct flex_dst {
+ char dest_call[10];
+ unsigned short ssida;
+ unsigned short sside;
+ unsigned long rtt;
+ int addr;
+
+ struct flex_dst *next;
+};
+
+struct ax_routes {
+ char dest_call[10];
+ char alias[10];
+ char dev[14];
+ char conn_type[1];
+ char description[50];
+ char digis[AX25_MAX_DIGIS][10];
+
+ struct ax_routes *next;
+};
+
+extern int safe_atoi(const char *s);
+extern char *safe_strncpy(char *dest, char *src, int n);
+
+extern struct proc_dev *read_proc_dev(void);
+extern void free_proc_dev(struct proc_dev *ap);
+
+extern struct flex_gt *read_flex_gt(void);
+extern void free_flex_gt(struct flex_gt *fp);
+
+extern struct flex_dst *read_flex_dst(void);
+extern void free_flex_dst(struct flex_dst *fp);
+
+extern struct ax_routes *read_ax_routes(void);
+extern void free_ax_routes(struct ax_routes *ap);
+
+extern struct ax_routes *find_route(char *dest_call, struct ax_routes *list);
+extern struct flex_dst *find_dest(char *dest_call, struct flex_dst *list);
+extern struct flex_gt *find_gateway(int addr, struct flex_gt *list);
+extern struct ax_routes *find_mheard(char *dest_call);
+
+#endif /* _PROCINFO_H */
diff --git a/router.c b/router.c
new file mode 100644
index 0000000..e68f54c
--- /dev/null
+++ b/router.c
@@ -0,0 +1,261 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <signal.h>
+
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netax25/ax25.h>
+#include <netrose/rose.h>
+
+#include <netax25/axlib.h>
+#include <netax25/axconfig.h>
+#include "procinfo.h"
+
+#include "node.h"
+
+
+int do_links(int argc, char **argv)
+{
+ struct ax_routes *axrt, *p;
+ char digipath[AX25_MAX_DIGIS*10];
+ char tipoconn[9];
+ int i=0;
+
+ axio_puts("",NodeIo);
+ if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo,"%s} ", NodeId);
+ }
+ if ((axrt=read_ax_routes()) == NULL) {
+ if (errno) node_perror("do_links: read_ax_routes", errno);
+ else axio_printf(NodeIo,"No known links");
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ return 0;
+ }
+
+ /* "links" */
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[01;33m");
+ }
+ if (argc == 1) {
+ node_msg("AX25 Links:");
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[0;m");
+ }
+ axio_printf(NodeIo,"Call Alias Description\n");
+ axio_printf(NodeIo,"--------- --------- -----------");
+ for(p=axrt;p!=NULL;p=p->next)
+ axio_printf(NodeIo,"\n%-9s %-9s %s", p->dest_call, p->alias, p->description);
+ free_ax_routes(axrt);
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ return 0;
+ }
+
+
+ /* "links d" */
+ if ((*argv[1]=='d') && (strlen(argv[1])==1)) {
+ node_msg("AX25 Direct Links:");
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[0;m");
+ }
+ axio_printf(NodeIo,"Call Alias Interf Description\n");
+ axio_printf(NodeIo,"--------- --------- ------- -----------");
+ for(p=axrt;p!=NULL;p=p->next)
+ { if (*p->conn_type==CONN_TYPE_DIRECT) axio_printf(NodeIo,"\n%-9s %-9s %-7s %s", p->dest_call, p->alias, p->dev, p->description); }
+ free_ax_routes(axrt);
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ return 0;
+ }
+
+
+ /* "links n" */
+ if ((*argv[1]=='n') && (strlen(argv[1])==1)) {
+ node_msg("AX25 Links via other nodes:");
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[0;m");
+ }
+ axio_printf(NodeIo,"Call Alias Interf Routing Description\n");
+ axio_printf(NodeIo,"--------- --------- ------- --------- -----------");
+ for(p=axrt;p!=NULL;p=p->next)
+ { if (*p->conn_type==CONN_TYPE_NODE) axio_printf(NodeIo,"\n%-9s %-9s %-7s %-9s %s", p->dest_call, p->alias, p->dev, p->digis[0], p->description); }
+ free_ax_routes(axrt);
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ return 0;
+ }
+
+
+
+ /* "links v" */
+ if ((*argv[1]=='v') && (strlen(argv[1])==1)) {
+ node_msg("AX25 Links via digipeaters:");
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[0;m");
+ }
+ axio_printf(NodeIo,"Call Alias Interf Digipeaters\n");
+ axio_printf(NodeIo,"--------- --------- ------- -----------");
+ for(p=axrt;p!=NULL;p=p->next) {
+ *digipath='\0';
+ for(i=0;i<AX25_MAX_DIGIS;i++) {
+ if (p->digis[i]==NULL) break;
+ if (i!=0) strcat(digipath," ");
+ strcat(digipath, p->digis[i]);
+ }
+ if (*p->conn_type==CONN_TYPE_DIGI) axio_printf(NodeIo,"\n%-9s %-9s %-7s %s", p->dest_call, p->alias, p->dev, digipath);
+ }
+ free_ax_routes(axrt);
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ return 0;
+ }
+
+ /* "links <call>" */
+ p=find_route(argv[1], axrt);
+ if(p!=NULL) {
+ node_msg("AX25 Link to %s:", p->dest_call);
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[0;m");
+ }
+ axio_printf(NodeIo,"Call Alias Interf Type Description\n");
+ axio_printf(NodeIo,"--------- --------- ------- -------- -----------");
+ switch(*p->conn_type) {
+ case CONN_TYPE_DIRECT:
+ { strcpy(tipoconn,"Direct"); break; }
+ case CONN_TYPE_NODE:
+ { strcpy(tipoconn,"Via Node"); break; }
+ case CONN_TYPE_DIGI:
+ { strcpy(tipoconn,"Via Digi"); break; }
+ }
+ axio_printf(NodeIo,"\n%-9s %-9s %-7s %-10s %s", p->dest_call, p->alias, p->dev, tipoconn, p->description);
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ } else {
+ axio_printf(NodeIo,"No such link");
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ }
+
+ free_ax_routes(axrt);
+ return 0;
+}
+
+/* ssid buffer increased by 1 by VE3TOK */
+int do_dest(int argc, char **argv)
+{
+ struct flex_dst *fdst, *p;
+ struct flex_gt *flgt, *q;
+ char ssid[6];
+ int i=0;
+
+ axio_puts("",NodeIo);
+ if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo,"%s} ", NodeId);
+ }
+ if ((fdst=read_flex_dst()) == NULL) {
+ axio_printf(NodeIo,"No known destinations");
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ return 0;
+ }
+
+ /* "dest" */
+ if (argc == 1) {
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo,"\e[01;33m");
+ }
+ if (User.ul_type != AF_AX25) {
+ axio_printf(NodeIo,"FlexNet Destinations:\n");
+ }
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[0;m");
+ }
+ for (p=fdst;p!=NULL;p=p->next) {
+ sprintf(ssid, "%d-%d", p->ssida, p->sside);
+ axio_printf(NodeIo,"%-7s %-5s %4ld%s",p->dest_call,ssid,p->rtt,(++i % 4) ? " " : "\n");
+ }
+ if ((i % 4) != 0) axio_printf(NodeIo,"");
+ free_flex_dst(fdst);
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ return 0;
+ }
+ if ((flgt=read_flex_gt()) == NULL) {
+ node_perror("do_dest: read_flex_gt", errno);
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ return 0;
+ }
+ /* "dest *" */
+ if (*argv[1]=='*') {
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo,"\e[01;33m");
+ }
+ node_msg("FlexNet Destinations:");
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[0;m");
+ }
+ axio_printf(NodeIo,"Dest SSID RTT Gateway\n");
+ axio_printf(NodeIo,"-------- ----- ----- --------");
+ for(p=fdst;p!=NULL;p=p->next) {
+ sprintf(ssid, "%d-%d", p->ssida, p->sside);
+ q=find_gateway(p->addr,flgt);
+ axio_printf(NodeIo,"\n%-8s %-5s %5ld %-8s", p->dest_call, ssid,
+ p->rtt, q!=NULL?q->call:"?");
+ }
+ free_flex_dst(fdst);
+ free_flex_gt(flgt);
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ return 0;
+ }
+ /* "dest <call>" */
+ p=find_dest(argv[1], fdst);
+ if(p!=NULL) {
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo,"\e[01;33m");
+ }
+ node_msg("FlexNet Destination %s:", p->dest_call);
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[0;m");
+ }
+ axio_printf(NodeIo,"Dest SSID RTT Gateway\n");
+ axio_printf(NodeIo,"-------- ----- ----- -------");
+ sprintf(ssid, "%d-%d", p->ssida, p->sside);
+ q=find_gateway(p->addr,flgt);
+ axio_printf(NodeIo,"\n%-8s %-5s %5ld %-8s", p->dest_call, ssid, p->rtt, q!=NULL?q->call:"?");
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ } else {
+ axio_printf(NodeIo,"No such destination");
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ }
+
+ free_flex_dst(fdst);
+ free_flex_gt(flgt);
+
+ return 0;
+}
+
+
diff --git a/sysinfo.c b/sysinfo.c
new file mode 100644
index 0000000..564164c
--- /dev/null
+++ b/sysinfo.c
@@ -0,0 +1,243 @@
+/*
+ * This code is slightly modified from the procps package.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <utmp.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <signal.h>
+
+#include "node.h"
+#include "sysinfo.h"
+
+char *xmalloc(size_t);
+char *fixup_null_alloc(size_t);
+int read_utmp(char *);
+int list_entries(int);
+int who(void);
+
+#define UPTIME_FILE "/proc/uptime"
+#define LOADAVG_FILE "/proc/loadavg"
+#define MEMINFO_FILE "/proc/meminfo"
+
+#define STRUCT_UTMP struct utmp
+static STRUCT_UTMP *utmp_contents;
+
+#ifndef UTMP_FILE
+#define UTMP_FILE "/var/run/utmp"
+#endif
+
+#ifndef EMAILLEN
+#define EMAILLEN 64
+#endif
+
+#ifndef MAXHOSTNAMELEN
+#define MAXHOSTNAMELEN 64
+#endif
+
+#ifndef S_IWGRP
+#define S_IWGRP 020
+#endif
+
+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) { \
+ close(fd); \
+ return 0; \
+ } \
+ lseek(fd, 0L, SEEK_SET); \
+ if ((n = read(fd, buf, sizeof buf - 1)) < 0) { \
+ 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) {
+ printf("Bad data in %s\n", 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) {
+ printf("Bad data in %s\n", LOADAVG_FILE );
+ return 0;
+ }
+ SET_IF_DESIRED(av1, avg_1);
+ SET_IF_DESIRED(av5, avg_5);
+ SET_IF_DESIRED(av15, avg_15);
+ return 1;
+}
+
+/* The following /proc/meminfo parsing routine assumes the following format:
+ [ <label> ... ] # header lines
+ [ <label> ] <num> [ <num> ... ] # table rows
+ [ repeats of above line ]
+
+ Any lines with fewer <num>s than <label>s get trailing <num>s set to zero.
+ The return value is a NULL terminated unsigned** which is the table of
+ numbers without labels. Convenient enumeration constants for the major and
+ minor dimensions are available in the header file. Note that this version
+ requires that labels do not contain digits. It is readily extensible to
+ labels which do not *begin* with digits, though.
+*/
+
+#define MAX_ROW 27 /* these are a little liberal for flexibility */
+#define MAX_COL 2
+
+unsigned** meminfo(void) {
+ static unsigned *row[MAX_ROW + 1]; /* row pointers */
+ static unsigned num[MAX_ROW * MAX_COL]; /* number storage */
+ char *p;
+ int i, j, k, l;
+
+ FILE_TO_BUF(MEMINFO_FILE)
+ if (!row[0]) /* init ptrs 1st time through */
+ for (i=0; i < MAX_ROW; i++) /* std column major order: */
+ row[i] = num + MAX_COL*i; /* A[i][j] = A + COLS*i + j */
+ p = buf;
+ for (i=0; i < MAX_ROW; i++) /* zero unassigned fields */
+ for (j=0; j < MAX_COL; j++)
+ row[i][j] = 0;
+ for (i=0; i < MAX_ROW && *p; i++) { /* loop over rows */
+ while(*p && !isdigit(*p)) p++; /* skip chars until a digit */
+ for (j=0; j < MAX_COL && *p; j++) { /* scanf column-by-column */
+ l = sscanf(p, "%u%n", row[i] + j, &k);
+ p += k; /* step over used buffer */
+ if (*p == '\n' || l < 1) /* end of line/buffer */
+ break;
+ }
+ }
+ /* row[i+1] = NULL; terminate the row list, currently unnecessary */
+ return row; /* NULL return ==> error */
+}
+
+int system_user_count(void)
+{
+ int users;
+
+ users=who();
+ return users;
+}
+
+int who(void)
+{
+ int users;
+
+ users=read_utmp(UTMP_FILE);
+ return list_entries(users);
+}
+
+int read_utmp (filename)
+ char *filename;
+{
+ FILE *utmp;
+ struct stat file_stats;
+ int n_read;
+ size_t size;
+
+ utmp = fopen (filename, "r");
+ if (utmp == NULL) return 0;
+
+ fstat (fileno (utmp), &file_stats);
+ size = file_stats.st_size;
+ if (size > 0)
+ utmp_contents = (STRUCT_UTMP *) xmalloc (size);
+ else
+ {
+ fclose (utmp);
+ return 0;
+ }
+
+ /* Use < instead of != in case the utmp just grew. */
+ n_read = fread (utmp_contents, 1, size, utmp);
+ if (ferror (utmp) || fclose (utmp) == EOF || n_read < size) return 0;
+
+ return size / sizeof (STRUCT_UTMP);
+}
+int list_entries (n)
+ int n;
+{
+ register STRUCT_UTMP *this = utmp_contents;
+ register int entries = 0;
+
+ while (n--)
+ {
+ if (this->ut_name[0]
+#ifdef USER_PROCESS
+ && this->ut_type == USER_PROCESS
+#endif
+ )
+ {
+ char trimmed_name[sizeof (this->ut_name) + 1];
+ int i;
+
+ strncpy (trimmed_name, this->ut_name, sizeof (this->ut_name));
+ trimmed_name[sizeof (this->ut_name)] = ' ';
+ for (i = 0; i <= sizeof (this->ut_name); i++)
+ {
+ if (trimmed_name[i] == ' ')
+ break;
+ }
+ trimmed_name[i] = '\0';
+
+ /* tprintf("%s ", trimmed_name); */
+ entries++;
+ }
+ this++;
+ }
+ return entries;
+}
+
+char *fixup_null_alloc (n)
+ size_t n;
+{
+ char *p;
+
+ p = 0;
+ if (n == 0)
+ p = malloc ((size_t) 1);
+ if (p == 0) return NULL;
+ return p;
+}
+
+/* Allocate N bytes of memory dynamically, with error checking. */
+
+char *xmalloc (n)
+ size_t n;
+{
+ char *p;
+
+ p = malloc (n);
+ if (p == 0)
+ p = fixup_null_alloc (n);
+ return p;
+}
diff --git a/sysinfo.h b/sysinfo.h
new file mode 100644
index 0000000..5d2e32f
--- /dev/null
+++ b/sysinfo.h
@@ -0,0 +1,26 @@
+#ifndef SYSINFO_H
+#define SYSINFO_H
+
+int loadavg(double *av1, double *av5, double *av15);
+int uptime (double *uptime_secs, double *idle_secs);
+
+unsigned** meminfo(void);
+
+enum meminfo_row { meminfo_main = 0, meminfo_free, meminfo_buffers,
+ meminfo_cached, meminfo_scached, meminfo_active,
+ meminfo_inactive, meminfo_htotal, meminfo_hfree,
+ meminfo_ltotal, meminfo_lfree, meminfo_stotal,
+ meminfo_sfree, meminfo_dirty, meminfo_writeback,
+ meminfo_anonpages, meminfo_mapped, meminfo_slab,
+ meminfo_sreclaim, meminfo_sunreclaim, meminfo_pagetables,
+ meminfo_nfs_unstab, meminfo_bounce, meminfo_climit,
+ meminfo_cas, meminfo_vmtotal, meminfo_vmused,
+ meminfo_vmchunk
+};
+
+enum meminfo_col { meminfo_total = 0
+};
+
+unsigned read_total_main(void);
+
+#endif /* SYSINFO_H */
diff --git a/system.c b/system.c
new file mode 100644
index 0000000..e7805fb
--- /dev/null
+++ b/system.c
@@ -0,0 +1,632 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/param.h>
+
+#include <fcntl.h>
+#include <ctype.h>
+#include <signal.h>
+
+#include <paths.h>
+#include <pwd.h>
+#include <utmp.h>
+#include <time.h>
+
+#include <termios.h>
+#include <unistd.h>
+
+#include <netax25/ax25.h>
+#include <netrose/rose.h>
+#include <netax25/axlib.h>
+#include <netax25/axconfig.h>
+
+#include "node.h"
+#include "procinfo.h"
+#include "config.h" /* VE3TOK - Dec20, 2014 */
+
+#define USER_NOBODY "nobody"
+
+#define NUMPTY 176
+#define SYSTEM_TIMEOUT 7200
+#define LAST_DATA_SIZE 120
+
+int shell=0;
+char *envp[16], *argp[16], mbox[40];
+char other_id[20];
+int in_queue=0;
+int pid=-1;
+char ptyname[80], Password[256];
+int ptyfd;
+
+/*---------------------------------------------------------------------------*/
+
+int cusgets(char *buf, int buflen, ax25io *iop)
+{
+ int c, len = 0;
+
+ while (len < (buflen - 1)) {
+ c = axio_getc(iop);
+ if (c == -1) {
+ if (len > 0) {
+ buf[len] = 0;
+ return (len);
+ } else return -1;
+ }
+ /* NULL also interpreted as EOL */
+ if (c == '\n' || c == '\r' || c == 0) {
+ buf[len++] = c;
+ buf[len] = 0;
+ return (len);
+ }
+ buf[len++] = c;
+ }
+ buf[buflen - 1] = 0;
+ return (buflen-1);
+}
+
+/*---------------------------------------------------------------------------*/
+
+int find_pty(char *ptyname)
+{
+ char master[80];
+ int fd;
+ int num;
+ static int lastnum = -1;
+
+ for(num = lastnum + 1; ; num++) {
+ if (num >= NUMPTY) num = 0;
+ sprintf(master, "/dev/pty%c%x", 'p' + (num >> 4), num & 0xf);
+/* sprintf(master, "/dev/pts/%x", num & 0xf); */
+ if ((fd = open(master, O_RDWR | O_NONBLOCK, 0600)) >= 0) {
+ sprintf(ptyname, "/dev/tty%c%x", 'p' + (num >> 4), num & 0xf);
+/* sprintf(ptyname, "/dev/pts/%x", num & 0xf); */
+ lastnum = num;
+ return fd;
+ }
+ if (num == lastnum) break;
+ }
+
+ return -1;
+}
+
+/*---------------------------------------------------------------------------*/
+
+void login_close(void)
+{
+ struct utmp utmpbuf, *ut;
+ FILE *fp;
+
+ if (ptyfd > 0) {
+ chown(ptyname, 0, 0);
+ chmod(ptyname, 0666);
+ ioctl(ptyfd, TCFLSH, 2);
+ close(ptyfd);
+ }
+ if (pid>0) {
+ kill(pid, SIGHUP);
+ pid=0;
+ }
+
+ memset(&utmpbuf, 0, sizeof(utmpbuf));
+ setutent();
+ utmpbuf.ut_type=LOGIN_PROCESS;
+ strcpy(utmpbuf.ut_line, ptyname+5);
+ strcpy(utmpbuf.ut_id, ptyname+strlen(ptyname)-2);
+ ut=getutid(&utmpbuf);
+ ut->ut_type=DEAD_PROCESS;
+ memset(ut->ut_host,0,UT_HOSTSIZE);
+ memset(ut->ut_user,0,UT_NAMESIZE);
+ time(&ut->ut_time);
+/* ut->ut_xtime = (unsigned int)time(NULL); */
+ pututline(ut);
+ endutent();
+ if ((fp = fopen(_PATH_WTMP, "r+")) != NULL) {
+ fseek(fp, 0L, SEEK_END);
+ fwrite(ut, sizeof(utmpbuf), 1, fp);
+ fclose(fp);
+ }
+ if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo,"%s} Welcome back.\n", NodeId);
+ } else {
+ axio_printf(NodeIo,"Welcome back.");
+ }
+}
+
+/*---------------------------------------------------------------------------*/
+
+int login_open(struct passwd *pw, char *command)
+{
+ if ((ptyfd=find_pty(ptyname)) < 0) {
+ syslog(LOG_ERR, "Error opening pseudo terminal for %s", pw->pw_name);
+ return -1;
+ }
+
+ syslog(LOG_INFO, "Opened pseudo terminal (%s) for %s", ptyname, pw->pw_name);
+
+ pid=fork();
+
+ if (pid==-1) {
+ syslog(LOG_ERR, "Cannot fork for %s", pw->pw_name);
+ return -1;
+ }
+
+ if (pid==0) { /* child */
+ struct termios termios;
+ struct utmp utmpbuf;
+ int i;
+
+ for(i=0;i<FD_SETSIZE;i++) close(i);
+ setsid();
+ open(ptyname, O_RDWR, 0666);
+ dup(0);
+ dup(0);
+ chmod(ptyname, 0622);
+ ioctl(0, TIOCSCTTY, 0);
+
+ memset(&termios, 0 , sizeof(termios));
+ termios.c_iflag = ICRNL | IXOFF;
+ termios.c_oflag = OPOST | ONLCR | TAB3;
+ 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, B38400);
+ cfsetospeed(&termios, B38400);
+ tcsetattr(0, TCSANOW, &termios);
+
+ memset(&utmpbuf, 0, sizeof(utmpbuf));
+ utmpbuf.ut_type=USER_PROCESS; /* Type of login */
+ utmpbuf.ut_pid=getpid(); /* Pid of login process */
+ strcpy(utmpbuf.ut_line, ptyname+5); /* Devicename of tty */
+ strcpy(utmpbuf.ut_id, ptyname+strlen(ptyname)-2); /* Inittab id */
+ strcpy(utmpbuf.ut_user, pw->pw_name); /* Username */
+ strcpy(utmpbuf.ut_host, "local:uronode");
+ utmpbuf.ut_addr=0x7f000000;
+ time(&utmpbuf.ut_time); /* Time entry was made */
+/* utmpbuf.ut_xtime = (unsigned int)time(NULL); */
+
+ setutent();
+ pututline(&utmpbuf);
+ endutent();
+
+ setgid(pw->pw_gid);
+ setuid(pw->pw_uid);
+
+ execve(command, argp, envp);
+ exit(1);
+ }
+
+ if (pid!=0) {
+ int k, cnt;
+ fd_set fds_read, fds_err;
+ struct timeval tv;
+ char buf[1500];
+
+ while(1) {
+ FD_ZERO(&fds_read);
+ FD_ZERO(&fds_err);
+ FD_SET(STDIN_FILENO, &fds_read);
+ /* FD_SET(User.fd, &fds_err); */
+ FD_SET(ptyfd, &fds_read);
+ /* FD_SET(ptyfd, &fds_err); */
+
+ if (User.ul_type==AF_INET) {
+ tv.tv_usec=25;
+ tv.tv_sec=0;
+ } else {
+ tv.tv_usec=750;
+ tv.tv_sec=0;
+ }
+
+ if (in_queue>0) k=select(ptyfd+1, &fds_read, NULL, &fds_err, &tv);
+ else k=select(ptyfd+1, &fds_read, NULL, &fds_err, NULL);
+
+ if (k == -1) {
+ if (errno!=EINTR) {
+ syslog(LOG_DEBUG,"I/O select");
+ break;
+ }
+ }
+
+ if (k == 0) {
+ if (in_queue>0) {
+ axio_flush(NodeIo);
+ in_queue=0;
+ }
+ }
+
+ /* if (FD_ISSET(User.fd, &fds_err)) {
+ syslog(LOG_DEBUG,"I/O end: error channel, user");
+ break;
+ }
+
+ if (FD_ISSET(ptyfd, &fds_err)) {
+ syslog(LOG_DEBUG,"I/O end: error channel, application");
+ break;
+ } */
+
+ if (FD_ISSET(STDIN_FILENO, &fds_read)) {
+ alarm(SYSTEM_TIMEOUT);
+ cnt=cusgets(buf, sizeof(buf), NodeIo);
+ if (cnt < 0)
+ {
+ syslog(LOG_DEBUG,"I/O end: stdio channel, user");
+ break;
+ } else {
+ write(ptyfd, buf, cnt);
+ }
+ }
+
+ if (FD_ISSET(ptyfd, &fds_read)) {
+ alarm(SYSTEM_TIMEOUT);
+ cnt = read(ptyfd, buf, sizeof(buf));
+ if (cnt < 0) {
+ syslog(LOG_DEBUG,"I/O end: stdio channel, application");
+ break;
+ }
+ for(k = 0 ; k < cnt ; k++) {
+ if (buf[k]=='\n' && (User.ul_type==AF_AX25 || User.ul_type==AF_FLEXNET || User.ul_type==AF_NETROM)) continue;
+ axio_putc(buf[k], NodeIo);
+ }
+ in_queue+=cnt;
+ }
+ }
+
+ login_close();
+ }
+
+ return 0;
+}
+
+/*---------------------------------------------------------------------------*/
+
+int check_passwd(void)
+{
+ char buffer[400]="",
+ tmp[100]="";
+ int pass[5],
+ level,i;
+ long timet;
+
+ char answer[81]="";
+ char buf[2048];
+
+ level=strlen(Password);
+ timet=time(NULL);
+ srandom((int) timet);
+ for(i=0;i<5;i++) pass[i]=(int) (level * (random()/(RAND_MAX+1.0)));
+
+ sprintf(buffer,"%10.10ld%s",timet,Password);
+ axio_printf(NodeIo,"%s %d %d %d %d %d [%010.10ld]\n",
+ PassPrompt,pass[0]+1,pass[1]+1,pass[2]+1,pass[3]+1,pass[4]+1,timet);
+
+ sprintf(answer,"%c%c%c%c%c",Password[pass[0]],Password[pass[1]],Password[pass[2]],Password[pass[3]],Password[pass[4]]);
+
+ axio_flush(NodeIo);
+ axio_gets(buf, sizeof(buf), NodeIo);
+
+
+ if(strlen(buf)==32) i=strcmp(buf,tmp);
+ else i=strcmp(buf,answer);
+
+ if(i) {
+ axio_printf(NodeIo,"Password incorrect!");
+ return 0;
+ }
+ if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo,"%s} ", NodeId);
+ }
+ axio_printf(NodeIo,"URONode Shell engaged - use EXTREME caution! \n\n");
+ return 1;
+}
+
+/*---------------------------------------------------------------------------*/
+
+int do_system(int argc, char **argv)
+{
+ int i;
+ struct passwd *pw=NULL;
+ argp[0]=argv[0];
+ for(i=1;i<(argc);i++) argp[i]=argv[i];
+ argp[argc]=NULL;
+
+ axio_puts("",NodeIo);
+ if (other_id!=NULL && strcmp(other_id, USER_NOBODY)!=0) pw=getpwnam(other_id);
+
+ if (pw==NULL) {
+ if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo,"%s} ", NodeId);
+ }
+ node_msg("Permission denied\n");
+ syslog(LOG_INFO, "system: %s attempted command %s", User.call, argv[0]);
+ axio_puts("",NodeIo);
+ return 1;
+ }
+ if (strncmp(argv[0],"sysop",strlen(argv[0]))==0)
+ {
+ if (shell==1) {
+ User.state = STATE_EXTCMD;
+ User.dl_type = AF_UNSPEC;
+ strcpy(User.dl_name, "sysop");
+ strupr(User.dl_name);
+ update_user();
+ if (check_passwd()==0) return 0;
+ login_open(pw, "/bin/bash");
+ axio_puts("",NodeIo);
+ return 0;
+ } else {
+ if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo,"%s} ", NodeId);
+ }
+ node_msg("permission denied");
+ axio_puts("",NodeIo);
+ return 1;
+ };
+ }
+ if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo,"%s} ", NodeId);
+ }
+ node_msg("unknown command");
+
+ return 0;
+}
+
+int examine_user(void)
+{
+ FILE *users;
+ char call[10], buf[1024], *cp, *ep;
+ char flags[40];
+
+ strcpy(other_id, USER_NOBODY);
+
+ if ((users=fopen(CONF_USERS_FILE, "r"))==NULL) {
+ node_msg("system: cannot open authority file: %s", CONF_USERS_FILE);
+ syslog(LOG_ERR, "system: cannot open authority file: %s", CONF_USERS_FILE);
+ axio_puts("",NodeIo);
+ return 1;
+ }
+
+ strcpy(call, User.call);
+ cp=strchr(call, '-');
+ if (cp) *cp='\0';
+
+ while(fgets(buf, 1024, users)) {
+ ep=strchr(buf, '#');
+ if (ep) *ep='\0';
+ if (*buf==0) continue;
+ cp=strtok(buf, ":\t\n\r");
+ if (cp==NULL) continue;
+ if (strcasecmp(cp, call)==0) {
+ cp=strtok(NULL, ":\t\n\r");
+ if (cp==NULL) continue;
+ strcpy(Password, cp);
+ cp=strtok(NULL, ":\t\n\r");
+ if (cp==NULL) continue;
+ strcpy(other_id, cp);
+ cp=strtok(NULL, ":\t\n\r");
+ if (cp==NULL) continue;
+ strcpy(flags, cp);
+ }
+ }
+
+ if (strcmp(other_id, USER_NOBODY)==0) return 0;
+
+ cp=strtok(flags, " ,;-/\t\n\r");
+ if (cp==NULL) return 0;
+ do {
+ if (strcmp(cp, "shell")==0) {
+ shell=1;
+ add_internal_cmd(&Nodecmds, "SYSop", 1, do_system);
+ }
+ cp=strtok(NULL, " ,;-/\t\n\r");
+ } while(cp!=NULL);
+
+ return 0;
+}
+
+struct nodelastlog {
+ char ll_user[8];
+ long ll_time;
+ char ll_line[LAST_DATA_SIZE];
+ char ll_host[LAST_DATA_SIZE];
+ int ll_count;
+};
+
+struct ipheardlastlog {
+ char ii_host[LAST_DATA_SIZE];
+};
+
+void lastlog(void)
+{
+ struct nodelastlog ll;
+ int last;
+ int count=0;
+ int hit=0;
+ int UserId=0;
+ char tty[LAST_DATA_SIZE];
+ char hostname[LAST_DATA_SIZE];
+ char usercall[10];
+ char *cp;
+ int escape;
+ strcpy(usercall, User.call);
+ cp=strchr(usercall, '-');
+ if (cp) *cp='\0';
+ strcpy(tty, "");
+ switch (User.ul_type) {
+ case AF_FLEXNET: strcpy(hostname, "FlexNet");
+ break;
+ case AF_AX25: strcpy(hostname, "[");
+ strcat(hostname, "AX25");
+ strcat(hostname, "] ");
+ strcat(hostname, User.call);
+ if (strlen(User.ul_name)>0) {
+ strcat(hostname, " via ");
+ strcat(hostname, User.ul_name);
+ }
+ break;
+ case AF_NETROM: strcpy(hostname, "<");
+ strcat(hostname, User.ul_port);
+ strcat(hostname, "> ");
+ strcat(hostname, User.call);
+ if (strlen(User.ul_name)>0) {
+ strcat(hostname, "@");
+ strcat(hostname, User.ul_name);
+ }
+ break;
+#ifdef HAVE_ROSE
+ case AF_ROSE: strcpy(hostname, User.call);
+ if (strlen(User.ul_name)>0) {
+ strcat(hostname, " at ");
+ strcat(hostname, User.ul_name);
+ }
+ break;
+#endif
+ case AF_INET: strcpy(hostname, User.ul_name);
+ break;
+ case AF_UNSPEC: strcpy(hostname, User.call);
+ strcat(hostname, " on local");
+ break;
+ default: strcpy(hostname, "");
+ break;
+ }
+
+ if ((last = open(DATA_NODE_LAST_FILE, O_RDWR, 0)) >= 0) {
+ lseek(last, (off_t)UserId * sizeof(ll), L_SET);
+ while (read(last, (char *)&ll, sizeof(ll)) == sizeof(ll) && ll.ll_time != 0) {
+ if (strcmp(ll.ll_user,usercall)==0) {
+ escape = (check_perms(PERM_NOESC, 0L) == 0) ? -1 : EscChar;
+#ifdef HAVEMOTD
+ /*
+ if (User.ul_type != AF_NETROM) {
+ axio_printf(NodeIo," Escape is: %s%c\n", escape < 32 ? "CTRL-" : "", escape < 32 ? (escape + 'A' - 1) : escape);
+ axio_printf(NodeIo,"Last login: %.*s ",24-5,(char *)ctime(&ll.ll_time));
+ if (*ll.ll_host != '\0') axio_printf(NodeIo,"\n From: %.*s\n",(int)sizeof(ll.ll_host), ll.ll_host);
+ else axio_printf(NodeIo," on %.*s\n",(int)sizeof(ll.ll_line), ll.ll_line);
+ }
+ */
+#endif
+ count=ll.ll_count;
+ hit++;
+ break;
+ } else UserId++;
+ }
+ lseek(last, (off_t)UserId * sizeof(ll), L_SET);
+ }
+ memset((char *)&ll, 0, sizeof(ll));
+ if ((hit==0) && (User.ul_type != AF_NETROM)) {
+ axio_printf(NodeIo,"Welcome, new user! Please use the Info and ? commands.\n\n");
+ count=0;
+ }
+ ll.ll_count=count+1;
+ (void)time(&ll.ll_time);
+ strncpy(ll.ll_line, tty, sizeof(ll.ll_line));
+ strncpy(ll.ll_user, usercall, sizeof(ll.ll_user));
+ if (hostname) strncpy(ll.ll_host, hostname, sizeof(ll.ll_host));
+ write(last, (char *)&ll, sizeof(ll));
+ close(last);
+}
+
+int do_last(int argc, char **argv)
+{
+ int last;
+ struct nodelastlog ll;
+ int Entries=0;
+ char call[10], *cp;
+
+ if ((last = open(DATA_NODE_LAST_FILE, O_RDONLY, 0)) <= 0) {
+ node_perror(DATA_NODE_LAST_FILE, errno);
+ return -1;
+ }
+
+ if (argc < 2) {
+ if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo,"%s} ", NodeId);
+ }
+ axio_printf(NodeIo,"Usage: Who <callsign or *>");
+ close(last);
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ return 0;
+ }
+
+ if (strcmp(argv[1],"*")==0) {
+ cp=NULL;
+ if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo,"%s} ", NodeId);
+ }
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[01;37m");
+ }
+ axio_printf(NodeIo,"Logins for ALL:\n", call);
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[0m");
+ }
+ } else {
+ if (!ax25_aton_entry(argv[1], call)) {
+ strcpy(call,strupr(argv[1]));
+ cp=strchr(call,'-');
+ if (cp) *cp='\0';
+ cp=call;
+ if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo,"%s} ", NodeId);
+ }
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[01;37m");
+ }
+ axio_printf(NodeIo,"Last online information for %s:\n", call);
+ if (check_perms(PERM_ANSI, 0L) != -1) {
+ axio_printf(NodeIo, "\e[0m");
+ }
+ } else {
+ if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo,"%s} ", NodeId);
+ }
+ axio_printf(NodeIo,"Usage: Who <callsign or *>\n");
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ close(last);
+ return -1;
+ }
+ }
+
+ lseek(last, (off_t)Entries * sizeof(ll), L_SET);
+ /* while (Entries < 20 && (read(last, (char *)&ll, sizeof(ll)) == sizeof(ll) && ll.ll_time != 0)) { */
+ while (read(last, (char *)&ll, sizeof(ll)) == sizeof(ll) && ll.ll_time !=0) {
+ if (cp && strcasecmp(cp,ll.ll_user)!=0) continue;
+ if (Entries==0) {
+ axio_printf(NodeIo,"User Last Online Count From\n");
+ axio_printf(NodeIo,"------ -------------------- ----- -----------------------------");
+ }
+ axio_printf(NodeIo,"\n%-10s ", ll.ll_user);
+ axio_printf(NodeIo,"%.*s ",24-5,(char *)ctime(&ll.ll_time));
+ axio_printf(NodeIo,"%-5d ",ll.ll_count);
+ if (*ll.ll_host != '\0') axio_printf(NodeIo," %.*s",(int)sizeof(ll.ll_host), ll.ll_host);
+ else axio_printf(NodeIo," on %.*s",(int)sizeof(ll.ll_line), ll.ll_line);
+ Entries++;
+ }
+ lseek(last, (off_t)Entries * sizeof(ll), L_SET);
+
+ close(last);
+ if (!cp && Entries==0) axio_printf(NodeIo,"No users in the lastlog database.");
+ if (cp && Entries==0) axio_printf(NodeIo,"%s Never logged in.", call);
+
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ return 0;
+}
diff --git a/user.c b/user.c
new file mode 100644
index 0000000..2b1fb44
--- /dev/null
+++ b/user.c
@@ -0,0 +1,289 @@
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/utsname.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <sys/socket.h>
+#include <signal.h>
+#include <netax25/procutils.h>
+#include <netax25/axlib.h>
+
+#include "node.h"
+#include "sysinfo.h"
+
+struct user User = {0};
+static long CallerPos = -1L;
+
+void login_user(void)
+{
+ FILE *f;
+ struct user u;
+ long pos = 0L;
+ long free = -1L;
+ struct stat statbuf;
+
+ if (stat(DATA_NODE_LOGIN_FILE, &statbuf) == -1) {
+ node_perror(DATA_NODE_LOGIN_FILE, errno);
+ return;
+ }
+ if (statbuf.st_size % sizeof(struct user) != 0) {
+ node_msg("%s: Incorrect size", DATA_NODE_LOGIN_FILE);
+ node_log(LOGLVL_ERROR, "%s: Incorrect size", DATA_NODE_LOGIN_FILE);
+ return;
+ }
+ time(&User.logintime);
+ User.cmdtime = User.logintime;
+ User.pid = getpid();
+ if ((f = fopen(DATA_NODE_LOGIN_FILE, "r+")) == NULL) {
+ node_perror(DATA_NODE_LOGIN_FILE, errno);
+ return;
+ }
+ if (flock(fileno(f), LOCK_EX) == -1) {
+ node_perror("login_user: flock", errno);
+ fclose(f);
+ return;
+ }
+ while (fread(&u, sizeof(u), 1, f) == 1) {
+ if (u.pid == -1 || (kill(u.pid, 0) == -1 && errno == ESRCH)) {
+ free = pos;
+ break;
+ }
+ pos += sizeof(u);
+ }
+ if (free != -1L && fseek(f, free, 0L) == -1) {
+ node_perror("login_user: fseek", errno);
+ fclose(f);
+ return;
+ }
+ fflush(f);
+ CallerPos = ftell(f);
+ fwrite(&User, sizeof(User), 1, f);
+ fflush(f);
+ flock(fileno(f), LOCK_UN);
+ fclose(f);
+}
+
+void logout_user(void)
+{
+ FILE *f;
+
+ if (CallerPos == -1L)
+ return;
+ if ((f = fopen(DATA_NODE_LOGIN_FILE, "r+")) == NULL) {
+ node_perror(DATA_NODE_LOGIN_FILE, errno);
+ return;
+ }
+ if (fseek(f, CallerPos, 0) == -1) {
+ node_perror("logout_user: fseek", errno);
+ fclose(f);
+ return;
+ }
+ User.pid = -1;
+ fwrite(&User, sizeof(User), 1, f);
+ fclose(f);
+}
+
+void update_user(void)
+{
+ FILE *f;
+
+ if (CallerPos == -1L)
+ return;
+ if ((f = fopen(DATA_NODE_LOGIN_FILE, "r+")) == NULL) {
+ node_perror(DATA_NODE_LOGIN_FILE, errno);
+ return;
+ }
+ if (fseek(f, CallerPos, 0) == -1) {
+ node_perror("update_user: fseek", errno);
+ fclose(f);
+ return;
+ }
+ fwrite(&User, sizeof(User), 1, f);
+ fclose(f);
+}
+
+int user_count(void)
+{
+ FILE *f;
+ struct user u;
+ int cnt = 0;
+
+ if ((f = fopen(DATA_NODE_LOGIN_FILE, "r")) == NULL) {
+ node_perror(DATA_NODE_LOGIN_FILE, errno);
+ return 0;
+ }
+ while (fread(&u, sizeof(u), 1, f) == 1)
+ if (u.pid != -1 && (kill(u.pid, 0) != -1 || errno != ESRCH))
+ cnt++;
+ fclose(f);
+ return cnt;
+}
+
+int user_list(int argc, char **argv)
+{
+ FILE *f;
+ struct user u;
+ struct tm *tp;
+ struct proc_nr_nodes *np;
+ char buf[80];
+ long l;
+ axio_puts("",NodeIo);
+ if ((f = fopen(DATA_NODE_LOGIN_FILE, "r")) == NULL) {
+ node_perror(DATA_NODE_LOGIN_FILE, errno);
+ return 0;
+ }
+ if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo, "%s} %s", NodeId, VERSION);
+ }
+ if (User.ul_type == AF_INET) {
+ axio_printf(NodeIo, "\e[01;35m");
+ } else {
+ axio_printf(NodeIo, "Current users:");
+ }
+ if (user_count() == 0) {
+ axio_printf(NodeIo, " No users online.\n");
+ }
+ if (User.ul_type == AF_INET) {
+ axio_printf(NodeIo,"\e[0;m");
+ }
+ if (user_count() != 0) /* axio_printf(NodeIo,"") */ ;
+ while (fread(&u, sizeof(u), 1, f) == 1) {
+ if (u.pid == -1 || (kill(u.pid, 0) == -1 && errno == ESRCH))
+ continue;
+ switch (u.ul_type) {
+ case AF_FLEXNET:
+ sprintf(buf, "\nFlexNet (%.9s)",
+ u.call);
+ break;
+ case AF_AX25:
+ sprintf(buf, "\nUplink (%.9s on interface %.10s)",
+ u.call, u.ul_name);
+ break;
+ case AF_NETROM:
+ if ((np = find_node(u.ul_name, NULL)) != NULL) {
+ sprintf(buf, "\nCircuit (%.9s %.18s)",
+ u.call,
+ print_node(np->alias, np->call));
+ } else {
+ sprintf(buf, "\nCircuit (%.9s %.18s)",
+ u.call, u.ul_name);
+ }
+ break;
+#ifdef HAVE_ROSE
+ case AF_ROSE:
+ sprintf(buf, "\nROSE (%.9s %.18s)",
+ u.call, u.ul_name);
+ break;
+#endif
+ case AF_INET:
+ sprintf(buf, "\nTelnet (%.9s @ %.16s)",
+ u.call, u.ul_name);
+ break;
+ case AF_UNSPEC:
+ sprintf(buf, "\nHost (%.9s on local)",
+ u.call);
+ break;
+ default:
+ sprintf(buf, "\n?????? (%.9s %.18s)",
+ u.call, u.ul_name);
+ break;
+ }
+ axio_printf(NodeIo,"%-37.37s ", buf);
+ switch (u.state) {
+ case STATE_QUIT:
+ logout_user();
+ break;
+ case STATE_LOGIN:
+ axio_puts(" -> Logging in",NodeIo);
+ break;
+ case STATE_IDLE:
+ time(&l);
+ l -= u.cmdtime;
+ tp = gmtime(&l);
+ axio_printf(NodeIo," -> Idle (%d:%02d:%02d:%02d)",
+ tp->tm_yday, tp->tm_hour,
+ tp->tm_min, tp->tm_sec);
+ break;
+ case STATE_TRYING:
+ switch (u.dl_type) {
+ case AF_FLEXNET:
+ axio_printf(NodeIo," -> Trying (%s)",
+ u.dl_name);
+ break;
+ case AF_AX25:
+ axio_printf(NodeIo," -> Trying (%s on interface %s)",
+ u.dl_name, u.dl_port);
+ break;
+ case AF_NETROM:
+ axio_printf(NodeIo," -> Trying (%s)",
+ u.dl_name);
+ break;
+#ifdef HAVE_ROSE
+ case AF_ROSE:
+ axio_printf(NodeIo," -> Trying (%s)",
+ u.dl_name);
+ break;
+#endif
+ case AF_INET:
+ axio_printf(NodeIo," -> Trying (%s:%s)",
+ u.dl_name, u.dl_port);
+ break;
+ default:
+ axio_puts(" -> ???",NodeIo);
+ break;
+ }
+ break;
+ case STATE_CONNECTED:
+ switch (u.dl_type) {
+ case AF_FLEXNET:
+ axio_printf(NodeIo,"<--> FlexNet (%s)",
+ u.dl_name);
+ break;
+ case AF_AX25:
+ axio_printf(NodeIo,"<--> Downlink (%s on interface %s)",
+ u.dl_name, u.dl_port);
+ break;
+ case AF_NETROM:
+ axio_printf(NodeIo,"<--> Circuit (%s)",
+ u.dl_name);
+ break;
+#ifdef HAVE_ROSE
+ case AF_ROSE:
+ axio_printf(NodeIo,"<--> ROSE (%s)",
+ u.dl_name);
+ break;
+#endif
+ case AF_INET:
+ axio_printf(NodeIo,"<--> Telnet (%s:%s)",
+ u.dl_name, u.dl_port);
+ break;
+ default:
+ axio_printf(NodeIo,"<--> ???");
+ break;
+ }
+ break;
+ case STATE_PINGING:
+ axio_printf(NodeIo,"<--> Pinging (%s)", u.dl_name);
+ break;
+ case STATE_EXTCMD:
+ axio_printf(NodeIo,"<--> Extcmd (%s)", u.dl_name);
+ break;
+ default:
+ axio_puts(" -> ??????",NodeIo);
+ break;
+ }
+ axio_puts("",NodeIo);
+ }
+ if (User.ul_type == AF_NETROM) {
+ node_msg("");
+ }
+ fclose(f);
+ return 0;
+}
+
diff --git a/util.c b/util.c
new file mode 100644
index 0000000..a7e8e37
--- /dev/null
+++ b/util.c
@@ -0,0 +1,115 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <string.h>
+#include <time.h>
+#include <sys/file.h>
+
+#include <sys/socket.h>
+#include <netax25/ax25.h>
+#include <netrose/rose.h>
+#include <netax25/axlib.h>
+
+#include "node.h"
+#include "sysinfo.h"
+#include "procinfo.h"
+
+static char buf[256];
+char *HostName;
+char *Prompt;
+
+void node_msg(const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ vsprintf(buf, fmt, args);
+ va_end(args);
+ axio_printf(NodeIo,"%s\n", buf);
+}
+/*
+ void node_prompt(const char *fmt, ...)
+ {
+ va_list args;
+ va_start(args, fmt);
+ vsprintf(buf, fmt, args);
+ va_end(args);
+ if (User.ul_type == AF_NETROM) {
+ axio_printf(NodeIo,"%s} ", NodeId);
+ }
+ if ((User.ul_type == AF_INET) && (check_perms(PERM_ANSI, 0L) != -1)) {
+ axio_printf(NodeIo,"\n\e[01;31m%s\e[0m@\e[01;34m%s\e[0m:/uronode$ ",User.call, HostName);
+ }
+ if ((User.ul_type == AF_INET) && (check_perms(PERM_ANSI, 0L) == -1)) {
+ axio_printf(NodeIo,"\n%s@%s:/uronode$ ", User.call, HostName);
+ }
+ if (User.ul_type == AF_AX25) {
+ axio_printf(NodeIo,"%s",Prompt);
+ }
+ }
+*/
+void node_perror(char *str, int err)
+{
+ int oldmode;
+
+ oldmode = axio_eolmode(NodeIo, EOLMODE_TEXT);
+ buf[0] = 0;
+ if (str)
+ strcpy(buf, str);
+ if (str && err != -1)
+ strcat(buf, ": ");
+ if (err != -1)
+ strcat(buf, strerror(err));
+ axio_printf(NodeIo,"\nERROR; %s\n", buf);
+ axio_eolmode(NodeIo, oldmode);
+ axio_flush(NodeIo);
+ node_log(LOGLVL_ERROR, buf);
+}
+
+char *print_node(const char *alias, const char *call)
+{
+ static char node[17];
+
+ sprintf(node, "%s%s%s",
+ !strcmp(alias, "*") ? "" : alias,
+ !strcmp(call, "*") ? "" : ":", call);
+
+ return node;
+}
+
+void node_log(int loglevel, const char *fmt, ...)
+{
+ static int opened = 0;
+ va_list args;
+ int pri;
+
+ if (LogLevel < loglevel)
+ return;
+ if (!opened) {
+ openlog("uronode", LOG_PID, LOG_LOCAL7);
+ opened = 1;
+ }
+ switch (loglevel) {
+ case LOGLVL_ERROR:
+ pri = LOG_ERR;
+ break;
+ case LOGLVL_LOGIN:
+ pri = LOG_NOTICE;
+ break;
+ case LOGLVL_GW:
+ pri = LOG_INFO;
+ break;
+ default:
+ pri = LOG_INFO;
+ break;
+ }
+ va_start(args, fmt);
+ vsnprintf(buf, sizeof(buf), fmt, args);
+ buf[sizeof(buf) - 1] = 0;
+ va_end(args);
+ syslog(pri, "%s", buf);
+
+}
+
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-hamradio/uronode.git
More information about the pkg-hamradio-commits
mailing list