Date: Tue, 22 Nov 88 00:35:09 EST From: karn@ka9q.bellcore.com (Phil Karn) To: tcp-group@ucsd.edu Subject: nos.arc on flash.bellcore.com I'm uploading the file nos.arc to flash.bellcore.com under the /pub/ka9q directory. This contains the current source of the new version I've been working on. Although it is *NOT* yet complete, I thought I should make it available so people can see how it's shaping up. Go ahead and give it a try on the Internet. I have NOT yet finished the implementation of AX.25 sockets, so don't bug me about that part yet. I know, I know, there's no documentation yet. The main thing you need to know is that \hosts.net has been replaced with \domain.txt, and the format is that of a domain server database, not UNIX /etc/hosts. Phil Unfortunately, I just haven't had the time to update the documentation for NOS. Actually, the user interface isn't that much different; the main difference is the use of a domain resolver. As part of this work I got rid of hosts.net in favor of a local domain cache called domain.txt. A word of warning about the domain stuff in NOS: the domain.txt file is intended only as a local CACHE for the resolver. I have not yet done a domain SERVER, so the content of domain.txt is not necessarily the same as you would put in a server database. This particular version tries to grab 200K from the system at startup time for the heap; if less is available, it'll get whatever it can. If you want to use more, modify the call to grabcore() in pc.c. Eventually this will probably be a easily configurable value. 1. I've made the final switch to Turbo. You need Turbo C 2.0 Professional to compile and assemble this package from scratch. 2. The command line now accepts several arguments that are best illustrated by example: net /m200 /s40 /d\ /autoexec.net In this case, net is told to grab 200K of memory from MS-DOS for the heap, to allow a maximum of 40 active sockets, and to make the directory prefix for all files (configuration, domain.txt, mail spool files, etc) the root. These particular values all happen to be the defaults for their corresponding parameters, so of course you'd get the same effect by just typing "net". I decided that command line parameters were a better way to go than environment variables. The latter don't necessarily exist on systems other than MS-DOS and UNIX. You can always create a batch (shell script) file to invoke net with the parameters you want. If you call net with the -d option, you can specify the parent directory of all the various files used by net. Interesting. Well, one thing you might try is giving NOS less memory than the default, which is 200K for the heap. On my 640K system with no major TSRs running (just MS-DOS, COMMAND.COM and TRW PC-2000 packet driver) this leaves about 155K unused. (I also have a disk cache and ram disk, but they all run in extended memory). Depending on what else you might have loaded, the problem might well be as simple as running out of memory, e.g., if your driver tries to request memory from DOS when it is all taken but doesn't bother checking (or behaving rationally) when this happens. To specify less memory, invoke NOS like this: net /m100 That would cause it to grab only 100K. NOS does not deliberately "barf" if it requests more memory space than was available. It will simply use whatever is available. The only problem this creates is when you try to shell out to run a subcommand; there won't be any memory left to run command.com. 2. As you can probably tell from the foregoing example, NET is now large model by default. The code will still compile and run under small model if you want. In large model you can use as much memory as the system has available for buffering, but the downside of this is that there may be none left for other activities, e.g., running under a multitasker or shelling to a subprogram. Hence the option of specifying how much memory should be used. You can now run many more sessions, run much larger windows, etc, and it all works! 2. The domain receiver task is now started immediately after the very first "domain addserver" command is executed. This allows subsequent lines in the autoexec.net file to refer to domain names that aren't yet in domain.txt -- IF sufficient routing entries are already in place to reach the domain server. Formerly, the use in autoexec.net of any domain name that wasn't already in domain.txt caused net to hang at startup. Note, however, that domain.txt still needs a few "seed" entries if you use domain names for the "ip address" and "domain addserver" commands, or for "route add" commands necessary to reach the domain server. The ip address must be set before the first "domain addserver" command. 1. A finger server has been added. It works similarly to the pre-NOS finger server by KA7AXD *except* that the files under /finger do NOT have ".txt" appended to them. If you finger "foo@machine.name", finger will send back the contents of "/finger/foo". 2. I finally got tired of the schizophrenic MS-DOS use of either backslash (\) or forward slash (/) as the path separator in file names. The code now deals strictly with forward slashes just as though it's running under UNIX; MS-DOS system calls that return pathnames now have any backslashes in their return values immediately converted to forward slashes for consistency. This requires ONE IMPORTANT CHANGE -- you must edit your /ftpusers file to change all instances of backslash in the allowable prefix field to forward slash, or you will not be able to access any files. The symptoms of not doing this are that you will be allowed to log in via FTP, but every operation you try will be rejected with a "permission denied" message -- even if you are supposed to have full access to the system. 3. The session summary command ("session" without arguments) now shows any active data connections that are associated with FTP sessions. 3. Added the "delete" and "rename" top-level commands. Lately I've been receiving an increasing number of messages asking questions about the UNIX ports of my code, particularly Xenix and AT&T Unix System V (e.g., Microport). I need to point out a few things: 1. I did not do these ports. In fact, all of my TCP/IP development work is done on an AT clone running MS-DOS 3.3. That is the ONLY version of NET about which I can answer questions. 2. As a matter of personal principle, I avoid all AT&T-based UNIX systems. All of the UNIX systems I use run Berkeley or Berkeley-derived code (e.g., SunOS, Ultrix). Since all BSD-based UNIX systems already have full TCP/IP support, there is little reason to run my code on those systems. 3. Bob Hoffman, hoffman@vax.cs.pittsburgh.edu, has graciously agreed to act as coordinator of those working with UNIX ports of my code. Please direct any questions about these versions to him, not to me. 1. The "remote" server and client are completely reworked. The "reset" and "exit" functions no longer depend on the secrecy of the control port number, but use a password text string instead. (Not that this makes things any more secure against someone merely watching the channel, of course. Someday this will be replaced with a cryptographic authenticator.) I did this because I just added a "remote kick" command and I wanted to make it available to everyone without also making the more disruptive "exit" and "reset" functions also freely available. I therefore recommend that people use the default port number (0x1234) whenever possible. As before, there are no explicit acknowledgements to any of the "remote" commands. Here are a few sample commands: net> remote pc.ka9q.ampr.org kick Tell pc.ka9q.ampr.org to kick all TCP connections it has with me. If there aren't any, do nothing. net> remote -p 555 pc.ka9q.ampr.org kick As above, but send the command to UDP port 555 on the remote system. (You won't have to use this if everybody uses the default port when starting the remote server.) net> remote -a ka9q.bellcore.com pc.ka9q.ampr.org kick Tell pc.ka9q.ampr.org to kick all TCP connections it may have with ka9q.bellcore.com. net> remote -k key pc.ka9q.ampr.org exit Tell the copy of net.exe on pc.ka9q.ampr.org to exit. (If the specified key is incorrect, the remote system will log that fact and take no other action, giving you half a chance to detect nasty people before they do actual damage.) "reset" may be substituted for "exit"; this causes a cold reboot of the remote system (MS-DOS only). net> remote -s mykey Set the key for the local system's "remote" server. (This command does not generate any network packets.) NB: Until a key is set for the local system, it will refuse ALL remote requests except those for TCP kicks. I.e., you can allow remote kicks while disallowing remote resets and exits altogether by not setting a key. The protocol formats for the new "remote" command are reasonably backward compatible with the old. The commands are sent in UDP datagrams, as before, with the first byte of the data field containing the command (1 == reset, 2 == exit, 3 == kick). In the case of reset or exit, the variable length key must immediately follow the command byte. For the kick command, an optional 4-byte target IP address to kick follows the command byte; there is no key field. If the target IP address is missing, the system will default to kicking the source address in the UDP command packet. This version includes the NET/ROM layer 3 and 4 protocols as integrated into NOS by SM0RGV. I had to fix a few ANSI function prototypes and delint a few other places, but I've adopted Anders' code pretty much as is. It seems to work, although I did notice one occasion that the NET/ROM routing table got garbled. I would like reports from others on how well this code works before we put it into wide circulation. I just fixed a typo in nr3.c that kept IP-over-NET/ROM from working, and I also added a remote kick feature to SMTP. This latter feature is coupled with the remote tcp kick server I added the other week, in that now when you kick a remote station it will not only do a TCP kick on any existing TCP connections it may have with you, but it will also run through the SMTP queue and start up a session for anything that's waiting for you. This feature should be very useful to those who want to run mail gateways with manually dialed SLIP links (with Tomcat being the prime example). All you'll have to do is dial the connection to Tom's machine and send it the remote kick command (which is encapsulated in a UDP datagram). His system will then immediately send you any mail it has waiting for you. I've updated the version of nos on flash. I incorporated some bug fixes to the NET/ROM socket interface code from Anders, and I added a new command to the ip layer: "ip rtimer". This allows you to set the IP level reassembly timeout interval. This is the length of time that IP will keep the fragments of an incomplete datagram around while waiting for additional fragments to arrive; the reassembly timer is restarted each time a new fragment arrives. The timeout value was formerly hard-coded at 30 seconds. This is now the default for the new command, so if you do nothing the system will continue to behave exactly as before. NB: the value for rtimer, as with other timer values, is in MILLISECONDS. I added this in response to some observations by WB0MPQ that indicated that IP reassembly timeouts were occurring before subsequent fragments could be delivered successfully over a NET/ROM network (yes, it's really that slow). But be careful: if you set the timeout too long and you get a lot of fragmentary datagrams that never complete, you'll tie up a lot of memory. I'm uploading the version of NOS on flash.bellcore.com. This version supports RIP, the interior routing protocol made popular by Berkeley UNIX. To enable the reception of RIP broadcasts, merely say start rip If you're not acting as a gateway to anyone, this is all you need do -- your system will begin to passively monitor its interfaces for broadcast routing packets and it will automatically add routes to the routing table. It may take up to 30 seconds on an ethernet for the table to be built (this assumes a broadcast rate of 30 seconds, which is standard on Ethernet). If you want to get started faster, you can give an optional IP address to the command: start rip [128.96.160.0] This broadcasts a RIP "request" packet on the local subnet, which triggers each gateway within earshot to send you its routing tables. (This requires knowledge of the local IP broadcast address, plus an ARP entry for same. Read on to find out about both of these things.) If you are also acting as a gateway, then you'll want to enable the transmit routines. First add ARP entries that map the local broadcast address for each of your networks to the correct hardware address. For example, the IP broadcast address on my shack Ethernet is 128.96.160.0, so I include the line arp add [128.96.160.0] ethernet ff:ff:ff:ff:ff:ff in my /autoexec.net file. Then I enable the broadcasting of routing info with the line rip add [128.96.160.0] ethernet 30 6 This means "broadcast your routing tables every 30 seconds on the interface named 'ethernet', using IP destination address 128.96.160.0. Generate triggered updates as necessary, and use the split horizon method." On a packet radio channel, I might use the following lines: arp add [44.64.0.0] com1 qst-0 rip add [44.64.0.0] com1 600 7 The last parameter in the "rip add" command is the flag parameter. It is the sum of the following possible flag values: 1 - Include a host-specific route to yourself in each update. (Not needed if you're already advertising a route to the network you're on.) 2 - Use split horizon updating; that is, omit all routing entries that point to the interface being used for the broadcast. (This reduces the chances of routing loops forming). 4 - Generate triggered updates as necessary on this interface, i.e., whenever a metric changes in the routing table, immediately generate a broadcast on this interface with the changed entries. If split horizon (bit 2) is also set, use "poisoned reverse", i.e., for any routing table entries that point to this interface, include them with an infinite metric (RIP defines 16 to be infinity) instead of leaving them out as happens during a normal routing broadcast when split horizon is set. Triggered updates helps spread the word faster when links fail, reducing the chances of a temporary loop forming. For Ethernet, I recommend a flag value of 6 (triggered updates and split horizon). On SLIP links, use 6 or 7, depending on whether you need to emit a host-specific route to yourself. On a packet radio channel where everyone is not fully connected (the usual case), use 7 and DON'T advertise any routes to the subnet unless you can reach everyone in that subnet. (A packet radio channel is best modeled as a collection of point-to-point links since it rarely fits the model of a fully interconnected subnet like Ethernet.) Note that you don't have to broadcast your routes; you can direct them to a specific set of stations by using their names or addresses in the "rip add" command. You can have any number of such commands per interface, with the only limit being channel traffic overhead. An experimental parameter is available to control something I call "route merging". If you say "rip merge on", then an incoming route that is more specific than one you already have in your table is ignored if they both point to the same gateway. For example, if you already have a default route that points to gateway "foobar", then any route that arrives from gateway foobar will be ignored because to put it in the table would not cause any change in the routing of packets -- they'd still go to foobar anyway. Properly used, this should save a lot of routing table space. You can trace the automatic routing messages and controls by the "rip trace" command; it takes a numeric parameter. "rip trace 0" disables tracing, "rip trace 1" generates messages only when routes change, and "rip trace 2" shows you everything, even when things are stable. If you want to ignore routing broadcasts from a certain gateway (e.g., because it can't hear you), say rip refuse hostname where 'hostname' is the domain name or [ip address] of the offending gateway. To reverse this, just say rip accept hostname This manual filtering will probably do until I'm able to devise some sort of link connectivity algorithm and protocol that can analyze the quality of the path between your station and each of your neighbors so routing packets can be filtered automatically. I have an idea of how to do this -- by broadcasting periodic status packets containing received and transmitted packet count statistics and using such packets to determine how well you're being heard. Ooops, I think I made a minor error in my discussion of RIP over radio. The flag setting for RIP broadcasts over a radio channel should probably be 5, not 7. You don't want to use split horizon over a radio subnetwork unless it is internally fully connected, since there may well be relay routes that enter and leave an intermediate station by the same interface. Split horizon would suppress such routes, which would preclude same-channel relay hops. I've updated the NOS code on flash. I've been doing a lot of work on the RIP code to fix bugs and make things more stable. I changed the command syntax for a couple of the rip commands; look at the help messages or read the source for details until I can document things further. Note! This version REQUIRES that you set the default local IP address (i.e., issue the "ip addr" command) BEFORE you attach any interfaces. So edit your autoexec.net file appropriately. The reason for this requirement is the major change in this version: each interface can now have its own IP address. An interface's IP address can be specified in the attach command, but if it is omitted the IP address given earlier in the "ip address" command will be used by default. (Hence the requirement given above. I considered doing away with the "ip address" command altogether and making the ip address argument on each attach command required, but this would have been a more disruptive change.) This architectural change brings the NET package into line with standard Internet practice. This is mainly for the benefit of those who use NET as a router between Ethernets in a regular Internet environment, where the other hosts and routers lack NET's extensions to the standard Internet routing and subnetting facilities. Although it was possible to make the earlier code work in such situations through a combination of proxy arp and static routes, it was a little unclean. With this version, the machine can be set up to act just like a conventional Internet router and multi-homed host. I.e., if you have NET running with several interfaces, each with its own unique IP address, the system will accept packets addressed to any of its interfaces' addresses. When the system originates packets, the local address appropriate for the sending interface will be used, all in accordance with standard Internet practice. Note that when you do a "tcp stat" the local IP addresses for connections in LISTEN state are 0.0.0.0; this is normal. The appropriate IP address is used when the connection is actually opened. The BSD constant "INADDR_ANY" is provided in a header file, and it can be used just as it is in BSD when binding local socket addresses in an application. Note that you are definitely NOT required to have a unique IP address for each interface. If you specify the same IP address for each interface (or allow each interface to use the global default set with the "ip address" command), then the package behaves just as it did before. Therefore this change is largely irrelevant to most AMPRNET users. It is also irrelevant whose NET configurations have only a single interface (i.e., all end-user systems that don't operate as gateways). I've added a new command, "iface", that lists the interfaces on the system along with their parameters (e.g., IP address, send and receive packet counts, etc.) There's also a "domain listservers" command that displays the list of domain servers along with various statistics measured for each. Subject: lost first characters I haven't investigated Tom's specific problem, but I've seen similar things in the past and it's almost always been due to null characters inbedded in the stream being sent to the terminal. The ANSI.SYS and NANSI.SYS drivers both display a null (0) character exactly as though it were a space, and this I consider a bug. Every other terminal I've ever seen treats null as a no-op. One of these days I'll dig into the NANSI.SYS source and fix it. 1. KY3B's port of PE1CHL's generic 8530 driver. Ken did all the work of porting Rob's driver to NOS. I took his code, reformatted and delinted it a bit and added ANSI-style function prototypes, but I have not actually tested it. Those of you using DRSI cards with slow speed modems, please give this driver a try and let us know if it works. There's a flag in config.h for configuring out this code if you don't need it and want to save the space. 2. I added an option in config.h for turning off the mailbox code. When the mailbox has been configured out, the following commands are removed: mbox start telnet/netrom/ax25 stop telnet/netrom/ax25 The "mbox y" command is gone. It didn't seem to make sense to keep it around given the presence of a separate "ttylink" server that goes straight to the console. So whenever the mailbox is configured into the system the telnet, netrom and ax25 servers all get the mailbox automatically. One less thing you have to remember to put in your autoexec.net files... I'm currently updating the NOS on flash. This incorporates the latest mbox and netrom patches by Anders, the latest DRSI driver from Stu, and the vector-saving fix to ec.c suggested by Ron Henderson. The only change I made myself was to add an #ifdef MAILBOX in fingerd.c around a reference to the mailbox code.