home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-06-30 | 78.8 KB | 1,679 lines |
- ; LANLIB.TXT -- Documentation for LANLIB
- ; Copyright (c) 1994 by Allen Brunson version 1.00 06/30/94
-
-
- ******************************************************************************
- * *
- *** Trademarks ***
- * *
- ******************************************************************************
-
- Borland is a registered trademark of Borland International, Inc.
-
- Microsoft and MS-DOS are registered trademarks and Windows is a trademark
- of Microsoft Corporation.
-
- Netware and Novell are registered trademarks and IPX is a trademark
- of Novell, Inc.
-
-
-
- ******************************************************************************
- * *
- *** Introduction ***
- * *
- ******************************************************************************
-
- LANLIB is a library of routines written in assembler for communication
- amongst multiple PCs using the IPX protocol, the low-level language spoken
- by Novell's NetWare. It is designed to be called from C, but if you know
- what you're doing, you can get it to work with assembler, C++, Pascal, or
- any other language that can be made to support the C calling convention and
- works with standard object file formats. Since LANLIB is written in
- assembler, its impact on the size of your program is minimal; it has only
- 2.8k of code and requires about 12k of memory for communication buffers.
-
- IPX is a fast and very low-level protocol, designed for maximum speed. It
- does not guarantee delivery, but Novell claims IPX packets properly arrive
- at their destinations about 95 percent of the time.
-
- IPX can be quite cumbersome to use. Given its orientation, a great many
- details of NetWare networks must be known by the programmer to use it
- properly. This library takes care of almost all of those details, allowing
- you to concentrate on your program's main function rather than worrying
- about IPX specifics.
-
- This library is geared towards the needs of smaller projects, where perhaps
- up to 20 or so PCs will be exchanging data. Larger projects would probably
- be best served if the programmer were to learn how to make IPX calls
- directly or by some other product.
-
- This library does not offer any NetWare-related services, such as logging in,
- logging out, copying files, getting lists of logged-on users, and so on.
- Its only purpose is to allow programs running on multiple PCs to share data.
-
- This document covers issues specific to using LANLIB. It assumes that you
- are familiar with NetWare and IPX concepts. It would be a good idea to
- read NETWORK.TXT before tackling this file.
-
- The file LANTEST.TXT explains the LANLIB demo program, LANTEST. LANTEST
- uses every LANLIB routine, so it is a good reference for implementation
- details.
-
-
- Shareware Version Restrictions
- ------------------------------
-
- The shareware version of LANLIB does everything that the registered version
- does, with one exception: the procedure ipxRouteFind() has been removed,
- so the shareware version is limited to only one network segment.
-
- The shareware version is provided for evaluation purposes only. You are
- NOT free to distribute programs you create with it.
-
-
-
- ******************************************************************************
- * *
- *** Adding LANLIB To Your Program ***
- * *
- ******************************************************************************
-
- LANLIB has been tested with both Microsoft and Borland C++ compilers. One
- small snag is that the Microsoft C++ compiler won't be able to use the Tiny
- model version of LANLIB; its linker reports that far segment accesses are not
- allowed in that model. Other compilers will probably work if they can deal
- with standard object files.
-
- LANLIB's use is limited to real-mode DOS executables. I am working on a
- version for the Watcom 32-bit compiler, but at this writing I don't have a
- release date.
-
- Novell's documented method for determining the presence of IPX requires the
- use of the DOS multiplex interrupt, which was introduced with DOS version
- 3.0. Therefore, LANLIB will not work with any DOS version earlier than 3.0.
-
- Special note for users of Microsoft compilers: Microsoft C defaults to
- two-byte (one word) structure member alignment. This will NOT WORK with
- LANLIB, which uses one-byte aligned structures. (It HAS to; IPX itself
- uses one-byte aligned structures.) You must set the compiler to one-byte
- structure alignment for it to work with LANLIB.
-
- LANLIB is contained in one of four .LIB files, depending on your chosen
- memory model:
-
- LANLIBT.LIB Tiny model
- LANLIBSC.LIB Small and Compact models
- LANLIBML.LIB Medium and Large models
- LANLIBH.LIB Huge model
-
- Include one of these .LIB files in your project.
-
- LANLIB always uses far pointers for passed data parameters, so there's no
- distinction between Small and Compact (near code calls) or between Medium and
- Large (far code calls). The Tiny model code never makes direct references to
- the data segment, so a program built with LANLIBT.LIB can be turned into a
- .COM file. The Huge memory model has special considerations for the data
- segment register, so it requires its own .LIB file.
-
- Include the file LANLIB.H in any module that will be calling the LANLIB
- routines. It is important that you follow this rule: LANLIB routines all
- take far pointers to data structures, and pointers in the small data
- memory models are by default near, so messy crashes will result if you don't
- perform this step.
-
- Defines in LANCFG.H are used to set the number of send and receive packet
- buffers, the number of bytes per packet, the socket number, and the number
- of networks to allow. Make a copy of this file for each program that will
- use LANLIB and then include LANCFG.H in each source file that will call
- LANLIB routines. See a later section called "Configuring LANLIB With Defines
- in LANCFG.H" for more details.
-
- The routines in LANUTIL.C can be used to work with IPXADDRFULL structures.
- While I was writing the demo program I had to manage the addresses of many
- PCs; each requires an IPXADDRFULL structure. Since this is a large
- hunk of data with several unwieldy fields, I wrote routines to copy one
- address to another, convert an address to a string, compare two addresses for
- equality, and so on. LANUTIL.C is the result. See a later section in this
- file for reference.
-
-
-
- ******************************************************************************
- * *
- *** Calling LANLIB from Assembler ***
- * *
- ******************************************************************************
-
- While LANLIB was being beta-tested, I was contacted by a programmer who was
- interested in using it with a pure assembler program. This is entirely
- possible; LANLIB is written in assembler itself. I've included the file
- LANLIB.INC, which contains the same defines as LANLIB.H but in assembler
- format, and LANCFG.INC, which duplicates LANCFG.H.
-
- All the LANLIB procedures use the C calling convention so you must do the
- same when calling them from assembler. Each procedure's arguments are
- pushed on the stack in right-to-left order; after the call, you must get rid
- of them by POPing them off (or by adding a value to SP, the stack pointer).
- If a procedure returns a value, it will be in AX on return (this is standard
- C procedure). Since C compilers don't require procedures to save many
- registers, the LANLIB procedures trash most of them. All registers except
- BP, SP, SI, DI, SS, and DS might be trashed.
-
- You won't be able to use the utility routines in LANUTIL.C in an assembler
- program, of course. But their use is optional; you may discover you don't
- need them; and if you do, they are all quite simple and easy to port to
- assembler.
-
-
-
- ******************************************************************************
- * *
- *** An Overview Of LANLIB Structures ***
- * *
- ******************************************************************************
-
- You don't need to know a whole lot about IPX structures to use LANLIB; it
- pretty much takes care of the details for you. However, a general overview
- of the seven structures defined in LANLIB.H (and LANLIB.INC) seems
- appropriate.
-
- struct IPXADDR: This is the network, node, and socket number for a PC. It
- is enough to uniquely identify a process on a PC, but not enough info to
- be able to send a packet to any process on any PC anywhere on an
- internetwork. Note that the socket field is high-low (Motorola) format.
- This structure is defined only for inclusion in the IPXPKTHDR structure.
-
- struct IPXADDRFULL: This is a superset of the IPXADDR structure, adding an
- immediate address field. Therefore it contains enough address info to send
- a packet anywhere. I kind of "made up" this structure; nowhere in "official"
- IPX do you find all four of these fields grouped together; however it seems
- quite convenient for storing the addresses of other PCs you wish to
- communicate with. LANTEST uses a group of these structures to keep track
- of all other LANTEST users; it is assumed that LANLIB users will employ a
- similar scheme. Keep in mind that the socket field MUST be maintained in
- high-low byte order or sends and receives will not complete properly.
- Routines for manipulating IPXADDRFULLs are given in LANUTIL.C.
-
- struct IPXDIAG: This is the structure of the data portion of the IPX
- diagnostic packet. It is used by ipxRouteFind() to locate other network
- segments.
-
- struct IPXDIAGREPLY: This is the format of the data portion of IPX diagnostic
- reply packets received in response to diagnostic requests; again, it is used
- by ipxRouteFind().
-
- struct IPXEVENT: This is another structure I "made up." LANLIB contains
- two ESRs (Event Service Routines), one which IPX calls when a send is
- completed, the other when a receive is completed. Each of these ESRs
- maintains a queue of events that it has been notified of (except that the
- send ESR simply throws away events if the send completed without errors).
- Each event is stored in a queue of IPXEVENT structures. These queues are
- maintained and processed entirely by internal LANLIB functions.
-
- struct IPXPKTHDR: This is the 30-byte packet header that all IPX packets
- must have. You don't need to directly concern yourself with it; LANLIB
- will fill out the fields in IPX packet headers where necessary.
-
- struct ECB: This is the standard IPX Event Control Block. It contains
- pointers to two "fragments," the packet header and the packet data. An
- ECB can actually have fields for any number of "fragments," but LANLIB
- always uses two, one for the header and one for the data. Again, LANLIB
- will take care of filling out ECB fields, so you don't have to worry about
- them.
-
-
-
- ******************************************************************************
- * *
- *** Configuring LANLIB with Defines In LANCFG.H ***
- * *
- ******************************************************************************
-
- LANLIB is tailored to the needs of your program by setting the defines in
- LANCFG.H (or LANCFG.INC for assembly programmers). In this way, you
- determine how many ECB/packet pairs are available for sending and receiving,
- the size of the packets, the socket number, and the maximum number of network
- segments allowed. (These defines are then used as parameters to ipxStart()
- and ipxRouteFind(), described below.) You will also indirectly be setting
- how much memory the communication data will take.
-
- Set IPXSOCKET to the socket number you want your program to use. This
- value will be passed as a parameter to ipxStart(). Novell states that
- "dynamic" socket numbers, that is, ones not officially reserved, start at
- 4000h and end at 7FFFh. The default socket number is 51E7h, but you should
- open up the file and change it right now, because everybody else who uses
- LANLIB will also be getting that as the default, and two programs running on
- the same network with the same socket number will bump heads. See the file
- NETWORK.TXT for more information on socket numbers.
-
- Set IPXNETCNT to the maximum number of network segments you will want LANLIB
- to be aware of. The default is 10. Most NetWare networks have six or fewer
- segments. Setting it to higher numbers means that networks further away
- will be found, but communicating with PCs farther away will take longer and
- will require a bigger structure for managing network segment addresses.
- The shareware version of LANLIB is effectively limited to 1 regardless of
- what you set this value to. LANLIB imposes no upper limit on this value,
- but generally speaking, setting it higher than 300 seems pointless.
-
- Set IPXRECVCNT to the total number of ECB/packet pairs you wish to make
- available for receiving incoming packets. The default is 30. The minimum
- value is 0; the maximum is 250. If you are planning to use ipxRouteFind()
- to locate other network segments, then the minimum is 30. It is passed as
- a parameter to ipxStart() and is used to set the number of receive ECBs,
- packet headers, packet data buffers, and the receive event queue size. You
- can make your program completely "deaf" to incoming packets by setting this
- value to 0. If your program will only receive packets infrequently and
- you're prepared to retrieve them quickly, you might get by with setting this
- value to 1. If you anticipate receiving lots of data and your program's
- main loop might not get around to processing incoming packets for several
- seconds, set this value to a high number, perhaps as high as 200. It's far
- better to set this number too high than too low, because if a data packet
- arrives and all the ECBs are already full, IPX will simply throw it away
- without so much as an error. Each ECB/packet pair requires one ECB
- (48 bytes), one packet header (30 bytes), one entry in the receive event
- queue (4 bytes), and one packet buffer, the size of which is set by
- IPXDATASIZE (see below).
-
- Set IPXSENDCNT to the total number of ECB/packet pairs you wish to use for
- sending packets. The default is 8. The minimum value is 0; the maximum is
- 250. If you're going to use ipxRouteFind(), the minimum is 2. It is passed
- as a parameter to ipxStart(). It is used to set the number of send ECBs,
- send packet headers, send packet buffers, and the size of the send event
- queue. You can make your program listen-only by setting this value to 0.
- Generally this number can be lower than IPXRECVCNT because most network
- programs send less data than they receive and send requests are usually
- carried out very quickly. Even if all send ECBs are in use when you want to
- do another send, you'll simply get an error; you're free to retry the send a
- few milliseconds later. Setting this value to 1 is plenty enough for
- programs with light send needs. Even if your program does nothing but sit in
- a loop sending packets, you probably shouldn't need more than 20. Each send
- ECB/packet pair takes the same number of bytes as a receive ECB/packet pair
- (see above).
-
- Set IPXDATASIZE to the number of bytes of data you want to be able to send
- (and receive) in each packet. Don't take the 30-byte IPX packet header
- into account here; this number is only for data bytes. The default is 256.
- The minimum size is 0; the maximum is 546. If you're going to use
- ipxRouteFind(), the minimum is 256. It's entirely possible to send packets
- with zero data bytes; the receiver will know nothing more than the sender's
- address, but in some contexts this might be enough. If you'll be sending
- lots of little packets, set IPXDATASIZE to a small number; big streams of
- data would be better-served by large packet sizes (but this will require
- more memory). It's possible to send packets that are smaller than
- IPXDATASIZE, but it's never possible to send one that's bigger than this
- value. The amount of memory taken up by this setting depends on the values
- of IPXRECVCNT and IPXSENDCNT; each ECB/packet pair used for both sending and
- receiving will have one buffer of this size.
-
-
-
- ******************************************************************************
- * *
- *** Dealing with Network Segments ***
- * *
- ******************************************************************************
-
- Network segments involve some of the most difficult concepts of IPX
- programming, and therefore also some of the most difficult concepts in LANLIB
- programming.
-
- There are two general approaches you can take: Operate only on one segment,
- or operate with many or all accessible segments. Naturally there are
- advantages and disadvantages to each approach.
-
- If ROUTE is not defined (in LANTEST.H), then LANTEST will be a single-segment
- program. If ROUTE is defined, then it will function as a multiple-segment
- program (after ipxRouteFind() has been called, which is accomplished with
- the R command). Look for the conditional compile directive "#ifdef ROUTE"
- which appears in several places in NETWORK.C to see what's different for each
- approach.
-
-
- The Single Segment Approach
- ---------------------------
-
- Operating on only one segment is easiest, fastest, and simplest to manage,
- and the only mode available for LANLIB programs if you're using the
- shareware version. There are no worries about finding other network
- segments. Since no routers will be involved, you can rest assured that
- packets will arrive as quickly as possible. Every IPX-aware game I've ever
- seen operates in this manner (excepting games in development using LANLIB, of
- course). When you need to broadcast packets to find potential users in
- single segment mode, you merely call ipxAddrLocal() with a pointer to an
- IPXADDRFULL structure, then pass that structure to ipxAddrBrd() to set it
- up as a broadcast address, then pass that address to ipxSendPkt() for the
- broadcast. You don't need to concern yourself further with the concept
- of network segments.
-
-
- The Multiple Segment Approach
- -----------------------------
-
- Operating with multiple segments is more complicated to manage and
- potentially slower if more than a few routers are involved, but far more
- flexible, and also better in tune with the size and scope of today's
- networks. I've installed and managed NetWare networks for many years now,
- and I can say for certain that networks with multiple segments are far more
- common than single-segment networks. It doesn't seem particularly sporting
- to restrict users from interacting with each other via your program simply
- because their PCs are attached to different network segments.
-
- The method for discovering network segments other than your own in NetWare
- environments is accomplished through "NetWare diagnostics." It's an
- interesting bit of trivia that NetWare file servers, routers, and PCs
- running NetWare's shell TSRs keep quite a few statistics on their
- performance, and are willing to give up this information (via SPX
- diagnostics) to anyone on the network who requests it, with absolutely no
- security checks whatever. You don't even have to be logged in to gather
- NetWare statistics.
-
- Another use for the statistics functions is to gather network segment
- information. When an IPX diagnostic request is broadcast on a network
- segment, PCs will respond with a simple list of "components" installed:
- IPX/SPX, shell, shell driver, and so on. Routers will return this
- information as well, but will also give information about all network
- segments they are attached to. Then the diagnostic request can be
- rebroadcast on these newly discovered segments, which will probably turn
- up more routers with information on more segments, and so on. This method
- is used by ipxRouteFind() to locate network segments.
-
- ipxRouteFind() is called with a structure of two or more IPXADDRFULLs. (If
- you were only interested in knowing about one network segment, you wouldn't
- need ipxRouteFind().) It sets up the first of these structures to be
- a broadcast address suitable for use on the local segment; it will have its
- node and immediate address fields set to FFFFFFFFFFFFh. In other words, it
- will be set up exactly as you would set it up yourself in a single segment
- program with a call to ipxAddrLocal() and then ipxAddrBrd().
-
- This first broadcast address is used to send a diagnostic request on the
- local segment. PCs will respond with their diagnostic information, but they
- are ignored, and in fact subsequent diagnostic packets are filled with a list
- of "exclusion addresses," or nodes that should not respond to the request;
- all known PC addresses are added to this list. ipxRouteFind() only cares
- about routers.
-
- If there are routers on the segment, they will respond with more network
- segment numbers. These segments are all added to the table of network
- addresses; the node address fields will all be set to FFFFFFFFFFFh,
- suitable for broadcasting, and the immediate address fields will be filled
- in with a call to ipxAddrImmed(), which is the officially sanctioned
- method of determining the "correct" immediate address to use. Remember
- that packets sent to other network segments must first be sent to a router,
- which in turn sends the packet on its way towards its destination. The
- immediate address indicates the node number on the local segment of the
- router that will do the first part of the routing.
-
- Each new broadcast address set up in this fashion is used to send a
- diagnostic request on that segment. Newly discovered segments will continue
- to be added. ipxRouteFind() works its way through the list with the aid of
- two pointers: one that indicates the network segment currently being
- investigated and another that indicates the first free slot in the table for
- storing a newly discovered address. When the two pointers point to the same
- location, router-finding is finished; all known network segments have been
- investigated.
-
- So, when it's time to broadcast queries looking for other users of your
- program, you do not send out a request only on your network segment, as
- you would in a single-segment program. You send out a request on all
- segments in all the IPXADDRFULL structures you passed to ipxRouteFind(),
- using those addresses as the address parameter to ipxSendPkt(). You can use
- the sending addresses of received replies just as you would in a single-
- segment program, even though some will probably contain network numbers other
- than your own.
-
- If you want to allow your program to work with a few segments for
- flexibility, but not a huge number so as to keep the speed up, you can limit
- the number of IPXADDRFULL structures you pass to ipxRouteFind(). You could
- even save this number as a run-time variable and let the user change it
- according to his or her needs (obviously the user would have to be rather
- technically astute to understand this option, however). You could perhaps
- set a reasonable default, or maybe have two radio buttons in your "network
- options" dialogue, one labeled "favor speed" which would allow up to six
- network segments, the other labeled "find all possible users" which would
- allow up to 60.
-
-
- "Virtual" Network Segments
- --------------------------
-
- It is likely that at least one of the segments that ipxRouteFind() locates
- for you will be a "virtual" segment. Starting with NetWare v3.0, servers
- must be assigned something called an "IPX Internal Network Number;" this
- is normally set in the server's AUTOEXEC.NCF command file with the command
- "IPX Internal Net xxxxxxxx". Internal network numbers are eight hexadecimal
- digits long, just like "real" network numbers. The server always makes
- itself node address 000000000001 on this network. This is its "official"
- network address and there will be no other nodes on the virtual network.
- Prior to version 3.x, a NetWare server's address was the network and node
- address of the first NIC installed in it (the one referred to as "LAN A").
-
- Network information returned from routers has one byte that indicates the
- type of each known network, and so virtual networks can be distinguished
- from "real" networks. It would at first seem logical for ipxRouteFind() to
- throw away information on these virtual networks, but there are two catches
- that make this a bad idea.
-
- First is the fact that there is another type of "virtual" network. Servers
- running version 2.x of non-dedicated NetWare all have a virtual network
- segment that is used for the DOS side of the server itself. (Non-dedicated
- servers function as both a file server and as a normal DOS PC through the
- magic of multitasking.) Therefore this type of virtual network will have a
- PC on it that you might want to communicate with. From the standpoint of
- NetWare diagnostics, this type of virtual network is indistinguishable from a
- NetWare v3.x server's virtual network.
-
- Second is the fact that one possible use of LANLIB is to poke around inside
- NetWare itself. Filtering out the server's network segment would make it
- impossible to send requests directly to a NetWare file server.
-
-
- NetWare Diagnostics Cautions
- ----------------------------
-
- In testing LANLIB, I have noticed that if lots of PCs are running diagnostic
- searches at the same time, one or more may end up with incomplete network
- information. I ran LANTEST on 16 PCs attached to a two-segment Ethernet
- network with one NetWare v3.12 server acting as the router. I sent a command
- to all PCs to start diagnostics at the exact same moment. Seven ended up
- with incomplete network information; they knew about their own network
- segment (of course), but did not find the second one or the server's
- "virtual" segment. Since each PC sends three diagnostic requests on each
- segment, and the server exists on all three segments, it had to (try to) send
- nine diagnostic replies to each PC. My guess is that the IPX drivers at each
- workstation were so busy sending and receiving diagnostic requests and
- replies that some were lost, or the server/router could not keep up with the
- demand. (Almost all the PCs were 486s; there were only two 386s.) Obviously
- this is a worst case scenario, but it's not unlikely that several people
- could start up your program at the same time. A possible option would be to
- allow the user to re-scan if all expected users do not appear, or perhaps to
- have a secondary diagnostic phase where all copies of your program ask all
- other known copies for their network info; if even one PC on a segment got
- all the information, then it could pass it on to all others whose knowledge
- might be incomplete.
-
- "Diagnostic inundation" is not the only reason that using NetWare diagnostics
- to locate network segments is not totally foolproof. It will work reliably
- almost all of the time in small- to medium-sized networks, where the only
- type of routers in use are probably NetWare file servers. Larger
- environments can be trickier. Some standalone routers may route NetWare
- packets from segment to segment and yet not respond to standard NetWare
- diagnostic requests. Given my resources, there's no way I can support
- non-standard routers in LANLIB.
-
- There is another method that can be used for locating network segments: the
- list of logged-in users (the "connection list") on a NetWare file server can
- be examined. This method has a big disadvantage, however: it requires that
- everybody who will use the program must be logged in to a file server. Ad
- hoc networks can spring up solely for the purpose of running a favorite
- network-aware game; many of these networks may be too small to even have a
- file server, so this would not be a good approach in those situations.
- Still, if a LANLIB user tells me that ipxRouteFind() isn't working in a
- particular environment she wants to support, I would probably write a
- secondary ipxRouteFind()-like procedure that operated via a server's
- connection list that could be used in troublesome environments.
-
-
-
- ******************************************************************************
- * *
- *** ECB Usage Statistics ***
- * *
- ******************************************************************************
-
- While I was writing LANTEST, I found myself wondering how many ECBs the
- program was actually using. It had the default total of 8 send ECBs, but
- was there ever a time when that many were in use? The LANLIB procedure for
- sending packets will report an error if there are no send ECBs free, but
- that doesn't tell you much. Receive ECBs are even harder to gauge; if you
- run out, IPX simply starts throwing away packets.
-
- That's when I built ECB usage statistics into LANLIB. It keeps track of
- how many receive and send ECBs are in use at any given moment in variables,
- and makes two other word-sized variables available to your program,
- "ipxRecvMax" and "ipxSendMax," that contain the maximum number of receive
- and send ECBs that have been in use so far. For the purposes of the
- statistics, a send ECB is considered "in use" between the time when you post
- it to IPX and the time that IPX notifies LANLIB that it has been sent; a
- receive ECB is considered "in use" beginning at the moment when IPX uses it
- to receive a packet and is no longer in use once you collect that packet and
- the ECB is put back into service. All the LANLIB procedures update these
- variables dynamically as packets are sent and received, when the Event
- Service Routines are notified that sends and receives have completed, and so
- on, so they will always be correct.
-
- You can reset the values of "ipxRecvMax" and "ipxSendMax" to zeroes at any
- time you like to start over again.
-
- I ran LANTEST with "flurry mode" turned on (which means it continually
- sends out packets as fast as it can) and checked the statistics. What I
- discovered is that it is very rare for LANTEST to need more than one send
- ECB. If the main loop is jiggered to favor sends over receives, then it
- might need as many as four, but not usually.
-
- Receive ECBs are a different matter. I discovered that normally the program
- gets along just fine with four or fewer receive ECBs in "flurry mode," but
- that every now and then some event will steal time normally used for
- processing incoming packets, like dealing with a lot of keyboard input, and
- the max receive ECB value will spike up to a value as high as 50 or 60. In
- fact, no matter how high I set the receive value, I could eventually get the
- program into a jam bad enough that it would use every last one of its receive
- ECBs. That's bad news, because it almost certainly means that there were at
- least one or two more packets that were lost. This is a good argument for
- writing your program to send acknowledges for all packet transactions.
-
-
-
- ******************************************************************************
- * *
- *** LANLIB Error Values ***
- * *
- ******************************************************************************
-
- LANLIB routines generally return zero to indicate no error or some positive
- error value otherwise (some routines take a pointer to a word-sized variable
- and return errors there). Possible error values are defined in LANLIB.H and
- LANLIB.INC along with a brief description for each. All defines begin with
- the letters "ipxe", or "IPX Error." ipxeNOERR is defined as 0; other values
- begin at 2 and head upward from there. Further treatment of the error values
- is given in the descriptions of the LANLIB routines.
-
- It is strongly recommended that you use the error defines in your program
- rather than the numerical values of the defines, because I reserve the right
- to change the numerical values in future versions of LANLIB.
-
- It was my original intention to use IPX's own error return values, but this
- proved to be unworkable. Almost every IPX call can return the error code
- FFh, for instance, but it means something different in every case. I wanted
- one set of error codes that always meant the same thing, so procedures in
- LANLIB all "translate" IPX's errors into one of the LANLIB error values.
-
- Note that, in some very rare cases, you may get an error return value other
- than the ones listed in LANLIB.H. Novell has released many, many different
- versions of the IPX TSRs over the years, and I wouldn't be surprised if some
- of them return error values not given in Novell's documentation.
-
- Naturally LANLIB can only translate error values that it knows about. It is
- programmed so that if IPX returns an unrecognized error value, it will pass
- the unknown value straight through to your program untranslated. Chances
- are good that such an error would be in the E0h to FDh range; IPX calls
- tend to return high-numbered errors. If you get such an error value, I'd
- be interested in hearing about it so I can incorporate it into future
- versions of LANLIB.
-
-
-
- ******************************************************************************
- * *
- *** Using The Routines in LANLIB ***
- * *
- ******************************************************************************
-
- The following is a reference guide for all the routines in LANLIB that your
- program can use. This is NOT the place to start if you don't understand the
- concepts involved. Begin by reading NETWORK.TXT, then the earlier parts of
- this file. Use this section as a day-to-day reference for the routines.
-
-
-
- ipxAddrImmed()
- --------------
-
- Prototype: word ipxAddrImmed(struct IPXADDRFULL far *ipxAddr,
- word far *ticks);
-
- This procedure calls the IPX routine known as IPX Get Local Target to get the
- preferred immediate address for a network address. At minimum, the network
- and node address fields in "ipxAddr" should be filled in before calling this
- procedure. If successful, it will fill in the immediate address field. If
- the address is on the same network segment, then the immediate address will
- be the same as the node address; if it's on a different segment, then the
- immediate address will be that of the router that is best suited for the
- task.
-
- Parameters:
-
- * struct IPXADDRFULL far *ipxAddr: A pointer to an address containing
- a network number and node number which are known to be valid. It's
- okay if the node number is FFFFFFFFFFFFh (a broadcast address).
-
- * word far *ticks: A pointer to a word to receive the estimated time
- of arrival to this destination address, in IBM PC clock ticks
- (approximately 1/18th of a second). This time is only an estimate;
- actual transport time will vary depending on network traffic.
-
- Return values:
-
- * ipxeNOERR (FALSE): The immediate address was filled in without errors.
-
- * ipxeIPXNOTSTARTED: ipxStart() hasn't yet been called.
-
- * ipxeNOPATHFOUND: No path to the destination address could be found;
- the immediate address field hasn't been set.
-
- You should use this procedure only once for each address, rather than
- before each send, because it requires IPX to do some spelunking out on the
- network, which can create network traffic as well as take time.
-
- Generally speaking, use of this procedure is optional, because there is a
- more direct method for determining the immediate address for a network
- address: When a packet is received, simply save the full address of the
- sender, including the immediate address, and use that. However, there are
- some occasions where this procedure comes in useful.
-
- Since there can be more than one route to a given destination, there can
- be more than one immediate address that will work for a given address. When
- this procedure is used, IPX tries to determine the "best" route, taking
- network traffic and hop distance into account.
-
- This procedure is also useful if you know the network and node address of a
- PC you want to talk to but don't also know the immediate address.
-
- Finally, its estimate of time necessary to reach an address can be helpful
- if transport speed is important to your program.
-
- ipxRouteFind() uses this procedure to determine the best immediate address
- to use for each network address that it finds.
-
-
-
- ipxAddrLocal()
- --------------
-
- Prototype: word ipxAddrLocal(struct IPXADDRFULL far *ipxAddr);
-
- This procedure gets the IPX address of the PC that your program is running
- on. It fills in every field of the IPXADDRFULL structure. The immediate
- address will be the same as the node address.
-
- Parameters:
-
- * struct IPXADDRFULL far *ipxAddr: A pointer to a structure to receive
- the address. It doesn't have to be initialized in any way, as every
- field will be filled in.
-
- Return values:
-
- * ipxeNOERR (FALSE): The address was collected without errors.
-
- * ipxeIPXNOTSTARTED: ipxStart() has not yet been called; the local
- address can't be retrieved until it is.
-
-
-
- ipxLibVer()
- -----------
-
- Prototype: word ipxLibVer(void);
-
- This procedure gets the version number of LANLIB. It is the only LANLIB
- function that can be called before ipxStart() or after ipxStop(). The major
- version number is returned in the high byte and the minor version in the low
- byte. For example, a return value of 0100h would mean major version 1, minor
- version 0, or 1.0.
-
-
-
- ipxRecvChk()
- ------------
-
- Prototype: word ipxRecvChk(void);
-
- This procedure checks to see if any packets have been received and are
- waiting to be picked up. If there are, you can retrieve them with
- ipxRecvPkt().
-
- Return values:
-
- * FALSE: No packets are waiting.
-
- * TRUE: At least one packet is waiting.
-
- * ipxeIPXNOTSTARTED: ipxStart() hasn't been called; it isn't possible
- to check for packets yet.
-
- If IPXRECVCNT is 0, then this procedure will always indicate that no packets
- are waiting.
-
-
-
- ipxRecvPkt()
- ------------
-
- Prototype: word ipxRecvPkt(void far *data,
- word dataSize,
- struct IPXADDRFULL far *ipxAddr,
- word far *pktSize,
- word far *error);
-
- This procedure checks to see if a packet has arrived, and if it has, it
- passes the data in the packet and the IPX address of the PC it was
- received from to your program.
-
- Parameters:
-
- * void far *data: A pointer to your buffer for receiving the data.
-
- * word dataSize: The size, in bytes, of your buffer.
-
- * struct IPXADDRFULL far *ipxAddr: A structure for receiving the
- address of the sending PC.
-
- * word far *pktSize: The address of a word that will receive the total
- size of the data in the packet.
-
- * word far *error: The address of a word that will receive the error
- code associated with this packet.
-
- Return values:
-
- * FALSE: No packets are waiting and nothing was copied to your data
- buffer or ipxAddr structure. "pktSize" is zero. "error" is also
- zero, unless ipxStart() hasn't yet been called.
-
- * TRUE: A packet has been received. The sending address has been
- copied to ipxAddr and "error" has been set accordingly. If "error"
- is set to ipxeNOERR (zero) or ipxeSOCKETNOTOPEN, a packet has been
- copied to your buffer and "pktSize" has been set to the number of
- data bytes received. If "error" has some other nonzero value, no
- packet data has been copied and "pktSize" is set to zero.
-
- Return values for "error:"
-
- * ipxeNOERR (FALSE): A packet was received and copied to your buffer
- without any errors.
-
- * ipxeIPXNOTSTARTED: ipxStart() has not been called so no packets can
- be received.
-
- * ipxeRECVPKTTOOBIG: A packet was received but it was too big to fit
- in the buffer associated with the ECB (in other words, it was larger
- than IPXDATASIZE), so IPX threw it away. No data was copied to your
- buffer, but your IPXADDRFULL structure has been filled in with the
- sender's address.
-
- * ipxeRECVCANCEL: IPX reports that the receive event was canceled.
- No packet data was copied. The sender's address has been copied, but
- is probably meaningless in this case. This should never happen under
- normal circumstances.
-
- * ipxeSOCKETNOTOPEN: The packet was received okay and has been copied
- to your buffer, as well as the sender's address. While LANLIB was
- attempting to put the ECB back into service to receive more packets,
- IPX reported that the socket referenced by the ECB is not open. This
- should never happen under normal circumstances.
-
- If the size of your buffer isn't large enough to hold all the received data
- (this can only happen if your buffer is smaller than IPXDATASIZE), then as
- much data as would fit was copied (and no error will be returned). You can
- tell this has happened if the value of "pktSize" is greater than the value
- you passed as "dataSize."
-
- If IPXRECVCNT is 0, then this procedure will always indicate that no packets
- have been received.
-
-
-
- ipxRouteFind()
- --------------
-
- Prototype: word ipxRouteFind(struct IPXADDRFULL far *network,
- word netCnt,
- word (*ipxWaitProc)(word netsFound),
- word far *netsFound);
-
- This is a complicated procedure which finds other network segments in the
- internetwork. It fills in a structure of IPXADDRFULLs with broadcast
- addresses for all the segments it finds, including the network segment the
- program is running on. See the earlier section "Dealing with Network
- Segments" for details on using this information. This procedure is not
- available in the shareware version of LANLIB.
-
- Parameters:
-
- * struct IPXADDRFULL far *network: A pointer to at least two
- IPXADDRFULL structures. It is suggested that you use the define
- IPXNETCNT from LANCFG.H when determining how big to make this
- structure (or how much memory to allocate for it), rather than
- using a fixed number.
-
- * word netCnt: The total number of IPXADDRFULLs pointed to by
- "network." It is suggested that you use the define IPXNETCNT
- rather than a fixed number.
-
- * word (*ipxWaitProc)(word netsFound): A pointer to a procedure
- that will be called repeatedly while the router-finding is taking
- place. This will be a near pointer in small code models and a far
- pointer in large code models. Since ipxRouteFind() might conceivably
- take quite a long time to do its work, this gives you a chance to
- display something on the screen to let the user know the program
- hasn't crashed and to allow an opportunity to abort the procedure, if
- need be. See the description for ipxWaitProc() for details. If this
- pointer is NULL, then no external procedure will be called.
-
- * word far *netsFound: A pointer to a word that will receive the
- number of network segments that were located.
-
- Return values:
-
- * ipxeNOERR (FALSE): The procedure completed without errors.
- "network" has been filled in with all known networks, and the
- total count has been placed in "netsFound."
-
- * TRUE (1): A send error occurred either at some point before
- ipxRouteFind() was called or while sending out diagnostic requests.
- The send error(s) are still waiting to be picked up via calls to
- ipxSendErr().
-
- * ipxeNETOVERFLOW: The procedure aborted because it found at least one
- more network segment than would fit in the "network" structure that
- was passed to it. This is not really an "error" per se; you might
- purposefully wish to keep the number of networks your program will
- work with to a minimum to ensure fast response.
-
- * ipxeBADCOMMPARMS: "netCnt" is less than two, or one or more of the
- values IPXRECVCNT, IPXSENDCNT, or IPXDATASIZE passed to ipxStart()
- are too small to allow the procedure to run. See below for details.
-
- * ipxeNOFREESENDECB: While trying to send out a diagnostic request,
- ipxSendPkt() reported that there were no free send ECBs. If you get
- this error during testing, you should increase the value of
- IPXSENDCNT.
-
- * ipxeROUTEFINDABORT: The procedure was aborted because "ipxWaitProc()"
- returned TRUE. See below for details.
-
- * ipxeIPXNOTSTARTED: ipxStart() has not yet been called.
-
- * ipxeNOPATHFOUND: When ipxRouteFind() called ipxAddrImmed() to get
- the immediate address for a discovered network, ipxAddrImmed()
- returned this value. This shouldn't happen under normal
- circumstances.
-
- * ipxeRECVPKTTOOBIG: While receiving diagnostic replies, ipxRecvPkt()
- reported this error. See ipxRecvPkt() for more details.
-
- * ipxeRECVCANCEL: See explanation for ipxeRECVPKTTOOBIG above.
-
- * ipxeSOCKETNOTOPEN: See explanation for ipxeRECVPKTTOOBIG above.
-
- If the procedure returns with some value other than FALSE, the network
- information in the "network" structure and the "netCnt" variable will be
- accurate but not necessarily complete; the procedure might not have found
- all networks before it had to abort. If the value returned is
- ipxeBADCOMMPARMS or ipxeIPXNOTSTARTED, then "network" will contain no
- network information at all.
-
- ipxRouteFind() performs the following steps:
-
- * It calls ipxAddrLocal() to fill in the first IPXADDRFULL structure
- pointed to by "network" with the network address of the network that
- it is running on. Then it sets the node and immediate address fields
- of this first structure to all F's, making the address suitable for
- broadcasting.
-
- * It calls ipxSendChk() to make sure there are no send errors in the
- send queue. If there are, it aborts and returns to your program,
- leaving the send errors in the queue.
-
- * It calls ipxSendPkt() to send out a diagnostic request on the local
- network segment.
-
- * It calls ipxRecvPkt() repeatedly to get diagnostic replies. Packets
- from anything that routes packets to other segments (standalone
- routers or file servers) are examined for other network segments.
- Replies from other PCs are ignored. Non-diagnostic packets are also
- ignored (this is determined by examining the socket that the packet
- came from). The addresses of other networks discovered are saved,
- and ipxAddrImmed() is called for each to fill in the best immediate
- address. To avoid clogging the network with diagnostic replies,
- each node will wait for a period of time up to half a second before
- sending a diagnostic response, so this procedure will wait at least
- that long to give all nodes a chance to respond. It only checks the
- elapsed time when no replies are coming in, so the actual time used
- might be greater than half a second.
-
- * If a pointer to a procedure of type ipxWaitProc() was given, it is
- called at this point.
-
- * The cycle is repeated twice more, starting with the call to
- ipxSendChk(), to ensure that all routers are heard from and to allow
- enough time to receive responses from routers that might take longer
- than half a second to arrive. Therefore, about 1.5 seconds are spent
- analyzing the network segment from start to finish, and ipxWaitProc()
- will be called three times.
-
- * The entire 1.5 second three-cycle ordeal is repeated for each new
- segment that is discovered. It is possible that late replies from
- earlier diagnostic requests on other segments might arrive during
- this time; if so, they will be properly processed as well. This
- process continues until all segments have been discovered and
- analyzed or until a new segment is discovered and the structure
- for saving the segment information is full, whichever comes first.
-
- * After all discovered segments have been analyzed, the procedure waits
- one more full second to see if any more late diagnostic responses
- will arrive. If one or more such responses arrive, and they contain
- the addresses of one or more new network segments, then the 1.5
- second analysis procedure is again run for those segments and the
- full second final wait will be repeated.
-
- Since ipxRouteFind() is basically a small LANLIB-using application unto
- itself, it has certain requirements that must be met for it to be used:
- IPXRECVCNT must be at least 30, IPXSENDCNT must be at least 2, and
- IPXDATASIZE must be at least 256. If these conditions aren't met, then
- ipxRouteFind() will return ipxeBADCOMMPARMS, no network segment data
- will be copied to "network," and "netsFound" will be zero.
-
- If a procedure was given as "ipxWaitProc()", then ipxRouteFind() will call it
- at the end of each send/receive cycle, approximately every half second. The
- procedure is called with one word-sized parameter, netsFound, which indicates
- the number of networks found so far. This number will not be incremented on
- every call to "ipxWaitProc()". If the ipxWaitProc() procedure returns FALSE,
- then router-finding continues; if it returns TRUE, then ipxRouteFind() will
- abort and return ipxeROUTEFINDABORT. See ipxWaitProc() for more details.
-
- You shouldn't have any "conversations" with other PCs going on when you call
- this procedure, because it will "eat" any and all packets that are received
- while it is running and throw away any that aren't diagnostic responses.
-
- It's okay to call this procedure more than once during the run of a program;
- for instance, it might need to be called a second time with a higher number
- for netCnt if a particular expected address was not found or ipxeNETOVERFLOW
- was returned.
-
- It is possible but unlikely that your program will receive a late diagnostic
- response at some point after ipxRouteFind() completes. You can check for
- this condition by examining the socket number in the sending address;
- diagnostic replies come from socket 0456h. If this happens consistently,
- let me know; it probably means that I need to tweak the code inside
- ipxRouteFind() to wait a little longer for replies to arrive.
-
- If a router does not respond to standard NetWare diagnostic requests, then
- this procedure won't recognize it and won't be able to access the networks
- it knows about. I am told that routers like this exist in some NetWare
- environments. Routers of this type are not supported by LANLIB.
-
- If a router claims to be attached to more than 32 networks, its information
- is ignored. Values higher than 32 probably indicate an error of some sort.
-
- Since it must take real time into account, ipxRouteFind() examines the word
- at 0040:006Ch in the BIOS data segment, which is the least significant word
- of the number of timer ticks that have elapsed since midnight.
-
- This procedure uses almost 1k of stack space for temporary variables, so you
- should ensure that this much is available.
-
-
-
- ipxSendChk()
- ------------
-
- Prototype: word ipxSendChk(void);
-
- This procedure checks to see if any errors were encountered while trying
- to send packets, and therefore whether those packets are waiting around
- for you to pick them up. If there are unsent packets, you can pick them up
- with ipxSendErr(). This should be done periodically, because ECB/packet
- pairs that were used for unsuccessful sends are unusable until retrieved
- with ipxSendErr().
-
- Return values:
-
- * FALSE: No undelivered packets are waiting.
-
- * TRUE: At least one undelivered packet is waiting.
-
- * ipxeIPXNOTSTARTED: ipxStart() hasn't been called; it isn't possible
- to check for send packet errors yet.
-
- If IPXSENDCNT is 0, then this procedure will always indicate that no send
- errors are waiting.
-
-
-
- ipxSendErr()
- ------------
-
- Prototype: word ipxSendErr(void far *data,
- word dataSize,
- struct IPXADDRFULL far *ipxAddr,
- word far *pktSize,
- word far *error);
-
- This procedure checks for IPX send errors. It is unlikely that you'll get
- any, but if you do, this routine in effect gives your packet back to you so
- you can retry the send or take other steps as necessary. It should be called
- every now and then even if you don't want to process send errors, because a
- send ECB/packet pair that had an error is taken out of service indefinitely
- until you call ipxSendErr() to free it up. If all send ECBs are taken out
- of service due to errors, then you won't be able to send any more data.
-
- Parameters:
-
- * void far *data: A pointer to your buffer that will receive the
- packet that couldn't be sent (if an error is reported).
-
- * word dataSize: The size of your buffer, in bytes.
-
- * struct IPXADDRFULL far *ipxAddr: A structure to receive the address
- of the PC that the packet should have been sent to.
-
- * word far *pktSize: A pointer to a word to receive the size of the
- data that is being returned.
-
- * word far *error: A pointer to a word to receive the error value
- associated with the packet.
-
- Return values:
-
- * FALSE: No undelivered packets are waiting. "error" will be set to
- ipxeNOERR (zero) unless ipxStart() hasn't been called.
-
- * TRUE: An undelivered packet has been copied to your buffer, the
- total size has been set in "pktSize," and the intended recipient's
- address has been copied to "ipxAddr." The ECB with the error is
- returned to service, ready to be used for the next send request.
-
- Return values for "error:"
-
- * ipxeNOERR (FALSE): There are no undelivered packets to be processed.
-
- * ipxeIPXNOTSTARTED: ipxStart() has not been called.
-
- * ipxeSENDBADROUTE: The packet was undeliverable. This can happen
- if you send a packet to yourself (broadcasts count as "sending a
- packet to yourself") and there are no free receive ECBs. If the
- packet was to another PC, then IPX could not find a route to the
- destination node; this probably indicates a problem with the
- immediate address.
-
- * ipxeSENDCANCEL: IPX reported that the send event was canceled. This
- shouldn't happen under normal circumstances.
-
- * ipxeSENDPKTBAD: The packet was "malformed," to use Novell's term.
- It was either too short, too long, or the fragment count was wrong.
- LANLIB takes care of all this, so this error should never be
- returned under normal circumstances.
-
- * ipxeSENDNETFAIL: IPX reports that the local network hardware or the
- network itself has failed.
-
- If IPXSENDCNT is 0, then this procedure will always indicate that no send
- errors are waiting.
-
-
-
- ipxSendPkt()
- ------------
-
- Prototype: word ipxSendPkt(void far *data,
- word dataSize,
- struct IPXADDRFULL far *ipxAddr);
-
- This procedure posts a send request with IPX. No error associated with
- the send will be returned, because ipxSendPkt() will return before IPX
- has actually sent the packet.
-
- Parameters:
-
- * void far *data: A pointer to your buffer filled with packet data to
- be sent.
-
- * word dataSize: The number of bytes in your buffer to be sent. This
- does not have to be the same as the size of the buffer, if you want
- to send fewer bytes.
-
- * struct IPXADDRFULL far *ipxAddr: The full IPX address of the PC to
- send the packet to. If you set the node address to FFFFFFFFFFFFh,
- the packet will be sent to all nodes on the selected network segment.
-
- Return values:
-
- * ipxeNOERR (FALSE): The request was posted without errors. This DOES
- NOT mean that the packet has been sent.
-
- * ipxeIPXNOTSTARTED: ipxStart() has not been called.
-
- * ipxeNOFREESENDECB: All send ECBs are currently in use, waiting to be
- sent by IPX (or else IPXSENDCNT is set to 0, which shouldn't be true
- if your program ever sends any packets). You can retry the send at
- some point later in time. If you get this error during testing, you
- can increase the number of send ECBs by setting the define IPXSENDCNT
- in LANCFG.H to a higher value.
-
- If the value of "dataSize" given is bigger than the value of IPXDATASIZE,
- then you've given more data than the procedure can send; the number of
- bytes sent will be truncated to IPXDATASIZE and no error will be returned.
-
- The procedure ipxSendErr() should be called occasionally to check for send
- errors. If all packets are sent successfully, then ipxSendErr() will return
- nothing, but keep in mind that this does NOT mean that the packet was
- successfully received; it could have been lost in transit. IPX does not
- guarantee that all packets sent will be received.
-
- IPX allows you to "send packets to yourself," so to speak. You could call
- ipxSendPkt() to send some data, setting "ipxAddr" to your own IPX address,
- and then receive that same packet with ipxRecvPkt(). IPX is smart enough
- to figure out that the packet doesn't have to go out onto the network and
- merely copies it in memory. This can be useful for debugging.
-
- If a program "broadcasts" a packet to all addresses on its own network
- segment by sending to node address FFFFFFFFFFFFh, then the program will
- receive a copy of its own sent packet.
-
-
-
- ipxStart()
- ----------
-
- Prototype: word ipxStart(word recvCnt,
- word sendCnt,
- word dataSize,
- word socket,
- void far *memPtr,
- word memSize);
-
- Call this as the very first IPX-related routine in your program. No other
- IPX functions except ipxLibVer() may be used until ipxStart() has been
- called. It performs the following functions:
-
- * It checks all parameters for validity except "socket." It also
- checks to make sure that the amount of memory given is large enough
- to hold everything.
-
- * It checks to make sure that the IPX driver is loaded. If not, it
- returns with an error code. If IPX is available, it saves the entry
- point used to make far calls to the IPX driver, which is needed by
- all other LANLIB routines except ipxLibVer().
-
- * It opens the IPX socket number given as the parameter "socket"
- for sending and receiving packets.
-
- * It registers all receive ECBs and their associated packet buffers
- with IPX, making them available to receive incoming data packets.
-
- Parameters:
-
- * word recvCnt: The number of receive ECB/buffer pairs to use. Legal
- values are 0 to 250. The minimum is 30 if ipxRouteFind() will be
- used. It is suggested that you use the define IPXRECVCNT from
- LANCFG.H rather than passing a number directly. Each receive
- ECB/buffer pair will require IPXCOMMSIZE bytes (a define in
- LANLIB.H).
-
- * word sendCnt: The number of send ECB/buffer pairs to use. Legal
- values are 0 to 250. The minimum is 2 if ipxRouteFind() will be
- used. It is suggested that you use the define IPXSENDCNT from
- LANCFG.H rather than passing a number directly. Each send
- ECB/buffer pair will require IPXCOMMSIZE bytes.
-
- * dataSize: The maximum number of data bytes per packet. Legal values
- are 0 to 546. The minimum is 256 if ipxRouteFind() will be used.
- It is suggested that you use the define IPXDATASIZE in LANCFG.H
- rather than passing a number directly.
-
- * void far *memPtr: This is a far pointer to an allocated block of
- memory that LANLIB will use for ECBs, buffers, queues, and so on.
- This can be memory allocated from the near heap with malloc() or from
- the far heap with farmalloc(), memory obtained with a direct call to
- DOS, a pointer to a block of memory in an initialized or
- uninitialized data segment, or just about anything else, just so long
- as it's big enough to hold everything (see below). It doesn't have
- to be set to all zeroes; LANLIB does that itself. The memory block
- must be less than 64k.
-
- * word memSize: The size of the memory block pointed to by memPtr, in
- bytes. This value can be calculated by using the define IPXMEMSIZE
- located in LANLIB.H.
-
- Return values:
-
- * ipxeNOERR (FALSE): All operations were completed without errors.
-
- * ipxeNOIPX: The IPX driver TSR (or TSRs) are not loaded. IPX
- communication is not possible.
-
- * ipxeIPXSTARTED: ipxStart() has already been called. It should not
- be called twice.
-
- * ipxeBADCOMMPARMS: One of the communication parameters given was set
- to an illegal value. All are checked for validity except "socket."
- This value will be returned if "memPtr" is NULL.
-
- * ipxeMEMTOOSMALL: The value of memSize indicates that the memory
- block given is not big enough to hold all the communication data
- (see below).
-
- * ipxeMEMABOVE64K: The amount of memory required for all requested
- ECBs and buffers would exceed 64k. This is not allowed (see
- below).
-
- * ipxeSOCKETTABLEFULL: The selected socket cannot be opened because
- the IPX driver's socket table is full. IPX defaults to allowing up
- to 20 open sockets. To increase this amount, add the line
- "IPX SOCKETS = xx" to the NET.CFG file, where "xx" is the number of
- sockets required. Sockets use some of the PC's memory, so don't
- increase the number any higher than necessary.
-
- * ipxeSOCKETOPEN: The requested socket was already open; ipxStart()
- did not complete. Some other program is probably using the socket.
- This can also happen if the user "crashes out" of your program, so
- ipxStop() was never called and the socket was left open, and then
- the user tries to start it again. In this case, a reboot will fix
- the trouble.
-
- * ipxeSOCKETNOTOPEN: While setting up the listen ECBs to receive
- incoming packets, IPX reported that the selected socket was not open,
- despite the fact that the socket was opened earlier with no error.
- It is extremely unlikely that this error will be reported under
- normal circumstances.
-
- The formula for determining how much memory to pass to ipxStart() is as
- follows (and is also defined as IPXMEMSIZE in LANLIB.H):
-
- (IPXRECVCNT + IPXSENDCNT) * IPXCOMMSIZE
-
- This is the total number of send and receive ECB/buffer pairs times the
- amount of memory for each, IPXCOMMSIZE. This is the total overhead bytes
- for each plus IPXDATASIZE. IPXCOMMSIZE is defined in LANLIB.H. The user
- must ensure that the total amount of memory needed is less than 64k. If
- it's greater, reduce the size of one or all of IPXRECVCNT, IPXSENDCNT, or
- IPXDATASIZE, defined in LANCFG.H, until the required size is less than
- 64k.
-
- There is no point in passing more memory than the amount given by this
- formula. LANLIB will not use any excess memory.
-
-
-
- ipxStop()
- ---------
-
- Prototype: word ipxStop(void);
-
- Call this as the last IPX function in your program. If you end your program
- without calling it, your computer may well crash later on when IPX tries to
- store an incoming packet in a memory buffer that no longer belongs to you.
-
- ipxStop() performs the following function:
-
- * It closes the IPX socket passed to ipxStart() as the parameter
- "socket." This has the effect of canceling any pending send
- requests and all receive ECBs. The IPX close socket function never
- returns an error, so no form of IPX error will be passed to your
- program.
-
- Return values:
-
- * ipxeNOERR (FALSE): The procedure completed without errors.
-
- * ipxeIPXNOTSTARTED: ipxStart() was never called, so there is nothing
- to stop.
-
- If memory was allocated for ipxStart() (as opposed to passing a pointer to
- an area of a data segment), then the memory should be freed after the call
- to ipxStop().
-
-
-
- ipxWaitProc()
- -------------
-
- Prototype: word ipxWaitProc(word netsFound);
-
- This is not a procedure in LANLIB, but rather one that can exist in your
- program.
-
- Since ipxRouteFind() takes about 1.5 seconds to process each network segment,
- and an internetwork might well contain 20 or more segments, it would be easy
- for a user of your program to assume that it had crashed and reboot the PC.
- To get around this problem, ipxRouteFind() takes as one of its parameters a
- pointer to a procedure of this type that it will call approximately every
- half second.
-
- Your procedure will receive one word-sized variable, netsFound, which will
- be the number of network segments discovered so far. This number will
- never be less than one, since the network segment that your program is
- running on is counted, and it is "discovered" before your procedure is
- called the first time. This value might be two or higher on the very first
- call to your procedure since one diagnostic cycle will have been completed
- at that point.
-
- Your procedure must return one word-sized variable that indicates whether
- or not ipxRouteFind() should continue. If your procedure returns FALSE (0),
- then ipxRouteFind() will continue. If it returns any other value then
- ipxRouteFind() will abort.
-
- This procedure is not subject to the restrictions imposed on interrupt
- service routines. At the time it is called the PC is in a stable state.
- The procedure can call other procedures in the program, collect keyboard
- or mouse input, call DOS and perform file I/O if need be, display information
- on the screen (perhaps the running total of networks it was called with), and
- take as long as it likes to complete; any amount of time up to a second or so
- is reasonable. It should not call any LANLIB procedures, however (or call
- other procedures that call LANLIB); ipxRouteFind() is using LANLIB at the
- moment; LANLIB calls should wait until after ipxRouteFind() has finished.
-
- This procedure can be written in any language, but it must follow the C
- calling convention. Its lone parameter will be on the stack at the time it
- is called, it must put its return value in the AX register, and
- ipxRouteFind() will clean up the stack afterwards. It doesn't have to save
- any registers except SP, BP, SI, DI, DS, and SS. This is all according to
- the standard C calling convention. ipxRouteFind() will access it with a near
- call in small code models and with a far call in large code models, so it
- must use the default return type (near or far) for the current memory model.
-
- The LANLIB demo program LANTEST contains a procedure of this type, called
- routeWait(), in the file NETWORK.C.
-
-
-
- ******************************************************************************
- * *
- *** LANUTIL Routines ***
- * *
- ******************************************************************************
-
- Programs using LANLIB will almost certainly have to keep track of at least a
- few other PCs out on the network. This requires keeping track of those PC's
- IPX addresses, which are best kept in IPXADDRFULL structures. You might
- have to copy one address to another, compare two addresses to see if they're
- the same or to sort a list, or print an address to the screen. Since an
- IPXADDRFULL structure is large and complicated, these sorts of tasks are made
- more difficult. This is exactly the problem I found myself up against when
- I wrote LANTEST. The LANUTIL routines are the solution I came up with.
-
- The LANUTIL routines are written in C and the source code is included in the
- file LANUTIL.C. You can use or modify this code as you see fit.
-
-
-
- ipxAddrBrd()
- ------------
-
- Prototype: struct IPXADDRFULL *ipxAddrBrd(struct IPXADDRFULL *ipxAddr);
-
- This procedure sets the node address and immediate address fields in an
- IPXADDR structure to FFFFFFFFFFFFh, which makes the address suitable for
- broadcasting packets to all PCs on the local network segment. It does
- nothing at all to the network and socket fields, so those values should
- already be set before performing this call.
-
- A convenient way to set up an IPXADDRFULL structure suitable for
- broadcasting packets on your local segment is to first get your local
- address from the LANLIB procedure ipxAddrLocal(), then pass that address
- to ipxAddrBrd() to set the node and immediate address fields.
-
- Note that if you broadcast a packet to all PCs on your network segment,
- you yourself will also get a copy of that packet.
-
- This procedure returns a pointer to the IPXADDRFULL structure.
-
-
-
- ipxAddrCmp()
- ------------
-
- Prototype: int ipxAddrCmp(struct IPXADDRFULL *ipxAddr1,
- struct IPXADDRFULL *ipxAddr2)
-
- This procedure compares the network, node, and socket numbers of two
- IPXADDRFULL structures. It can be used to sort addresses into numerical
- order or simply to determine if two addresses are identical. It returns
- -1 if the first address is less than the second, 0 if the addresses are
- the same, or 1 if the first address is greater than the second.
-
-
-
- ipxAddrCpy()
- ------------
-
- Prototype: struct IPXADDRFULL *ipxAddrCpy(struct IPXADDRFULL *ipxAddrDst,
- struct IPXADDRFULL *ipxAddrSrc)
-
- This procedure copies the entire contents of one IPXADDRFULL structure
- to another. It returns a pointer to the destination address.
-
-
-
- ipxAddrSocket()
- ---------------
-
- Prototype: struct IPXADDRFULL *ipxAddrSocket(struct IPXADDRFULL *ipxAddr,
- word socket)
-
- This procedure accepts a pointer to an IPXADDRFULL structure and a socket
- number in normal Intel low-high format. It flips the socket number to
- high-low format, as required by IPX, and puts it in the structure. It
- returns a pointer to the structure.
-
-
-
- ipxAddrStr()
- ------------
-
- Prototype: char *ipxAddrStr(char *str, struct IPXADDRFULL *ipxAddr)
-
- This procedure creates a string representation of the network and node
- address in an IPXADDRFULL structure in the string pointed to by "str"
- in the format xxxxxxxx:yyyyyyyyyyyy, where the x's are the network number
- and the y's are the node number. The string given as "str" must contain at
- least 22 bytes. The network and node are all that's needed to uniquely
- identify one PC from any other, so many of NetWare's own utilites use
- this format for displaying addresses. It returns a pointer to the string.
-
-
-
- ipxAddrStrLong()
- ----------------
-
- Prototype: char *ipxAddrStrLong(char *str, struct IPXADDRFULL *ipxAddr)
-
- This procedure creates a string representation of all four components of
- the IPXADDRFULL structure, all separated by colons. The string given as
- "str" must contain at least 40 bytes. This is probably not too useful
- for production programs, but it sometimes comes in handy for debugging. It
- returns a pointer to the string.
-
-
-
- ipxByteSwap()
- -------------
-
- Prototype: word ipxByteSwap(word socket)
-
- This procedure takes a word parameter (typically a socket number), swaps
- its high byte with its low byte, and returns the modified value. This
- will convert a socket number in low-high Intel format to high-low Motorola
- format, or vice versa. This can be useful because IPX requires that the
- socket field of IPXADDRFULLs be maintained in high-low (Motorola) format.
-
-
-
- ******************************************************************************
- * *
- *** The Future of LANLIB ***
- * *
- ******************************************************************************
-
- I am planning to do a 32-bit version of LANLIB compatible with the Watcom
- 32-bit compiler.
-
- I expect to eventually do a NetBIOS library as well, devise a common API
- layer that both the NetBIOS version and LANLIB will share, and figure out
- a way that a program can load one or the other but not both at runtime.
- Eventually I might also round out the situation with a serial communication
- library that uses the same API and can be loaded in place of one of the
- network drivers.
-
- I may also do a Windows version of LANLIB, and also the NetBIOS library.
-
- If you have an interest in any of these potential projects, please let me
- know. User interest will play a big part in whether or not I get around
- to them.
-
- If you would like to do something with LANLIB that I haven't taken into
- account, such as use it with a different compiler, or with overlays, or
- whatever, let me know. If it's feasible, I can probably be talked into it.
-
-
- Allen Brunson
- 6500 East 21st #2
- Wichita, Kansas 67206
- U.S.A.
-
- CompuServe: 74464,3472
- Internet: 74464.3472@compuserve.com
-
-
-
- ******************************************************************************
- * *
- *** Special Thanks ***
- * *
- ******************************************************************************
-
- Like any good piece of software, LANLIB was not created in a vacuum. I had
- a lot of help and feedback from many people. Two in particular stand out and
- deserve special mention:
-
- Bart Stewart. He performed countless tests on my behalf using his company's
- huge NetWare internetwork and various buggy versions of LANTEST.EXE. His
- knowledge of and experience with IPX diagnostics directly shaped the
- architecture of LANLIB.
-
- Doug Goldner. Unless somebody else gets into an EXTREME hurry, it looks like
- he will produce the first ever LANLIB-using program, a text-based adventure
- game called Multi-Venture that uses a client-server architecture. He figured
- out tricks to using LANLIB that didn't even occur to me, and in the process
- helped validate the whole LANLIB concept. You can contact Doug about his
- game at his CIS address, 76702,1257.
-
-
-
- ******************************************************************************
- * *
- *** Release History ***
- * *
- ******************************************************************************
-
-
- Version 1.00, June 30, 1994
-
- First public general release.
-
- Changes:
-
- * A little legalese, courtesy of my mom the lawyer, is about all that's
- new.
-
-
- Version 0.40, June 23, 1994
-
- Fourth public beta release.
-
- Changes:
-
- * Novell's legal department wouldn't let me use their trademark in my
- product's name, so I can't call it IPXLIB; now it's LANLIB, and all
- the files and so on were renamed.
-
- * LANTEST (formerly IPXTEST) can now write its network info to a file.
- This is useful (to me, at least) for debugging ipxRouteFind() if it
- fails to find all network segments on a given internetwork.
-
- * I added the procedure ipxAddrImmed(), which calls IPX to get the
- preferred immediate address for a given network address, and one
- new error value for it, ipxeNOPATHFOUND. ipxRouteFind() and LANTEST
- were both upgraded to use it.
-
- * I added a new error value, ipxeMEMABOVE64K, which ipxStart() will
- now return if the amount of memory required is above 64k (an error).
-
-
- Version 0.30, June 10, 1994
-
- Third public beta release.
-
- Changes:
-
- * IPX.H was renamed IPXLIB.H, IPX.ASM was renamed IPXLIB.ASM, and the
- .LIB files were also appropriately renamed.
-
- * The define IPXMEMSIZE was added to IPXLIB.H to calculate the memory
- size needed to pass to ipxStart().
-
- * IPXLIB.INC and IPXCFG.INC, the assembler versions of IPXLIB.H and
- IPXCFG.H, were added for programmers wishing to use IPXLIB with
- assembler programs.
-
- * I finally finished ipxRouteFind(), the procedure that finds network
- segments, and added one more IPXLIB error value for it,
- ipxeROUTEFINDABORT. I got rid of the never-used define IPXHOPS and
- replaced it with the new IPXNETCNT, given as a parameter to
- ipxRouteFind(). IPXTEST was upgraded to use the new procedure.
- "Dealing with Network Segments" was added to the documentation.
-
- * ipxeBADCOMMPARMS now also applies to ipxRouteFind(), which will
- return this value if the communication parameters aren't to its
- liking.
-
- * I added two new procedures in IPXUTIL.C for dealing with
- IPXADDRFULLs, ipxAddrSocket() and ipxByteSwap().
-
-
- Version 0.20, June 1, 1994
-
- Second public beta release.
-
- Changes:
-
- * The code in IPX.ASM was streamlined considerably, eliminating many
- small bugs.
-
- * ipxStart() was changed from taking no parameters to taking all
- communication parameters, including a far pointer to memory to
- use for ECBs, buffers, and so on. IPXTEST was modified so that
- if DEBUG is defined it passes a pointer to an IPXDATA structure
- to use for communication memory; it will allocate memory from
- the heap instead if DEBUG is not defined.
-
- * IPXDATA.C was eliminated; all communication data is now passed as
- variables to ipxStart(), including a pointer to memory that is used
- for the data that formerly was in this file.
-
- * Code was added to keep track of the maximum number of ECBs that have
- been used. IPXTEST was upgraded to display or reset this information
- and to send it to other IPXTEST users.
-
- * Two new IPXLIB error codes were added, ipxeBADCOMMPARMS and
- ipxeMEMTOOSMALL, which ipxStart() can return if the communication
- parameters given are wrong or if the size of the memory block given
- isn't big enough to hold everything, respectively. This shifted the
- values of all the other error codes.
-
- * The ECB pointer field in the IPXEVENT structure was changed from a
- far (4-byte) to a near (2-byte) pointer.
-
- * IPXLIB was tested with Microsoft C++ version 8.0 and proven to work
- in all memory models except Tiny. IPXTEST was modified to work with
- Microsoft C as well, although a few minor things didn't get ported,
- like the variable-length wait before sending a ping response and
- screen scrolling, because there weren't functions in the Microsoft
- run-time libraries equivalent to the ones I used in Borland C.
-
- * "Flurry mode," that is to say, sending as many packets as time will
- allow, was added to IPXTEST, so as to stress-test IPXLIB.
-
- * IPXTEST can now be "remote controlled:" It attempts to interpret the
- text of broadcast messages and directed messages as commands.
-
- * Several extra IPX programming considerations were added to the IPXTEST
- documentation.
-
-
- Version 0.10, May 27, 1994
-
- First public beta release.
-