Spru 524 A
Spru 524 A
Spru 524 A
Texas Instruments Incorporated and its subsidiaries (TI) reserve the right to make corrections,
modifications, enhancements, improvements, and other changes to its products and services at
any time and to discontinue any product or service without notice. Customers should obtain the
latest relevant information before placing orders and should verify that such information is current
and complete. All products are sold subject to TI’s terms and conditions of sale supplied at the
time of order acknowledgment.
TI warrants performance of its hardware products to the specifications applicable at the time of
sale in accordance with TI’s standard warranty. Testing and other quality control techniques are
used to the extent TI deems necessary to support this warranty. Except where mandated by
government requirements, testing of all parameters of each product is not necessarily performed.
TI assumes no liability for applications assistance or customer product design. Customers are
responsible for their products and applications using TI components. To minimize the risks
associated with customer products and applications, customers should provide adequate design
and operating safeguards.
TI does not warrant or represent that any license, either express or implied, is granted under any
TI patent right, copyright, mask work right, or other TI intellectual property right relating to any
combination, machine, or process in which TI products or services are used. Information
published by TI regarding third party products or services does not constitute a license from TI
to use such products or services or a warranty or endorsement thereof. Use of such information
may require a license from a third party under the patents or other intellectual property of that third
party, or a license from TI under the patents or other intellectual property of TI.
Resale of TI products or services with statements different from or beyond the parameters stated
by TI for that product or service voids all express and any implied warranties for the associated
TI product or service and is an unfair and deceptive business practice. TI is not responsible or
liable for any such statements.
Mailing Address:
Texas Instruments
Post Office Box 655303
Dallas, Texas 75265
- Chapter 3 – Sockets and Stream IO API, describes the file and sockets
API functions.
Text Conventions
- Program source code, function and macro names, parameters, and com-
mand line commands are shown in a mono-spaced font.
Trademarks
iv
Contents
Contents
1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-1
1.1 This Document . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-2
1.2 Additional Documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-3
v
Contents
vi
Figures
Figures
A–1 Packet and Packet Fragment Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A-6
A–2 FRAG Object Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A-15
B–1 Basic Home Network Configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B-2
B–2 Public Servers on the Home Network . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B-7
C–1 Standard PPP Frame Over Serial Line . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . C-2
C–2 PPP Frame Processed by PPP API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . C-2
C–3 Serial Interface (SI) Abstraction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . C-3
Contents vii
Chapter 1
Introduction
Topic Page
1-1
This Document
1-2
Additional Documentation
system and CGI POST functionality. This appendix describes how to add
web page content and CGI functions to a network application using the
HTTP server, including documenting the HTTP server’s web content API.
The TCP/IP NDK User’s Guide contains the following information about the
TCP/IP NDK:
The stack is hardware dependent at its HAL and SERIAL interface layers, but
even these layers are divided into hardware dependent and independent por-
tions. The NDK Porting Guide describes these layers, and discusses how to
port device drivers for Ethernet, system timers, and serial devices.
Introduction 1-3
Chapter 2
In order to keep the stack system portable, it was coded to a very compact Op-
erating System Abstraction. The stack can execute in any operating environ-
ment by porting the functions described here. Most of these functions will map
directly to a native OS counterpart.
Applications programmers that program to this API are assured that their ap-
plications will execute on any system to which this abstraction is ported.
Topic Page
2-1
Operating System Configuration
2.1.1 Synopsis
The OS has a couple of configuration options that regulate its behavior. These
are stored in a data structure. The types of properties defined in the structure
are those that would typically be macros, but using a data structure allows the
values to be changed without rebuilding the libraries.
The structure is described here for completeness, but applications should use
the configuration system to make alterations to these values. The configura-
tion system is described later in this document.
The stack internal configuration structure is _oscfg. Any element in this struc-
ture may be modified before the system is booted. System initialization is cov-
ered later in this document.
Description This is the lowest severity level of a system debug message (call to DbgPrintf()
function) that will be recorded into the debug log. The threshold may be raised.
The legal values for this variable are: DBG_INFO, DBG_WARN,
DBG_ERROR, and DBG_NONE.
2-2
Operating System Configuration
Default Value 3
Description This is the priority at which low priority stack task threads are set. Setting a
thread to a lower priority than this will not disrupt the system, but no system
or service supplied in this package will attempt it.
Default Value 5
Description This is the priority at which most stack task threads are set. Task threads that
are created by the system or services will usually run at this level.
Default Value 7
Description This is the priority at which high priority stack task threads are set. Setting a
thread at a higher priority than this may disrupt the system and cause unpre-
dictable behavior if the thread calls any stack related functions. High priority
tasks (like interrupts) can execute at higher priority levels, but should signal
lower priority tasks to perform any required stack functions.
Default Value 8
Description This is the priority that tasks threads execute at when they are inside the ker-
nel. Setting tasks to this priority level ensures that they will not be disrupted
by another task calling stack functions. The proper method of entering the ker-
nel is to call llEnter() and llExit(). This functions are discussed in the appen-
dices, as they are not required for the applications programmer.
Description This is the stack size used for network task that do very little network process-
ing, or do not use TCP.
Description This is the stack size used for a network task with an average network band-
width using TCP. It is used for the majority of network tasks in the network tools
library that use TCP.
Description This is the stack size used to network tasks that require a high network band-
width using TCP. It is also used for tasks calling HTTP CGI functions.
2-4
Task Support
Syntax HANDLE TaskCreate( void(*pFun)(), char *Name, int Priority, uint Stack-
Size,UINT32 Arg1, UINT32 Arg2, UINT32 Arg3 );
Parameter(s) pFun Pointer to task entry-point function
Name NULL terminated task name (truncated after 11 characters)
Description Creates a new task object. If successful, TaskCreate() returns a handle to the
newly created task.
The task name supplied in Name is used for informational purposes only, and
does not need to be unique.
The task priority specified in Priority determines the task thread’s priority rela-
tive to other tasks in the system. The value of Priority is constrained only by
the size of an int on the target environment, but a range of 0 to 15 is recom-
mended. 0 is the lowest priority and should be reserved for an idle task. If the
specified priority is negative, the task is blocked.
The task stack size specified by StackSize is not examined or adjusted by the
create function. The size should be made compatible with the native environ-
ment (a multiple of 4 bytes should be sufficient).
Arg1 through Arg3 are optional arguments that can be passed to the calling
function (they are always pushed onto the stack, but the task function need not
reference them).
There is no limit to the number of tasks that can be installed in the system. The
only possible failure on TaskCreate() is a memory allocation error.
If the priority level of the new task is higher than the priority level of the current
task. The entrypoint function pFun is executed immediately (before Task-
Create() returns to the caller).
2-6
Task Support
Parameter(s) none
Description Returns the task handle of the currently executing task thread. This function
is used mainly in other task object calls where the caller wishes to operate on
the current thread, but does not know the current thread’s handle.
If called on an illegal (system) thread, this function returns NULL. Only certain
implementations of the OS even have a system thread, and then, no user code
should ever be executed on it. A NULL may also result if Task functions are
called before the operating system is initialized.
Sets and stores a private environment handle for the supplied task handle
hTask. This handle can be later retrieved by TaskGetEnv(). The slot specified
in Slot assigns an address (1–3) to the environment handle. There are actually
four slots, but slot 0 is reserved.
Environment handles can be used to associate private data with a task thread.
This is useful when multiple threads share the same code base, but require
their own instance of static data.
2-8
Task Support
Description Sets the priority of the target task to the specified value. The value of Priority
is constrained only by the size of an int on the target environment, but a range
of 0 to 15 is recommended. 0 is the lowest priority and should be reserved for
an idle task. If the specified priority is negative, the task is blocked.
Description Sleeps the calling task for a period of time as supplied in Delay. The sleep time
can not be zero.
Parameter(s) none
Description This function is used to yield execution to another thread. Its only function is
to cause a round-robin task switch among “ready” task threads executing at
the same priority level.
This function always causes a task switch, however the original calling task
may be the next to execute.
2.3.1 Synopsis
The semaphore object provides a method of manipulating counting sema-
phores using a generic handle.
Semaphores can be used for both task synchronization and mutual exclusion.
2-10
Semaphore Support
Any task currently waiting on this semaphore is blocked forever – even if it orig-
inally specified a timeout to SemPend(). With a little care in programming, this
will not occur.
If the semaphore count is zero, the task is placed on a waiting list for the sema-
phore and blocked. If the semaphore becomes available in the time period
specified in Timeout, the function returns. However the function returns re-
gardless once the timeout has expired. A timeout value of 0 always returns
without blocking or yielding. A timeout value of SEM_FOREVER causes the
caller to wait on the semaphore without timeout.
The waiting list is “first in, first out”, without regard to priority. Thus semaphores
can be used to round-robin task threads at different priority levels.
Calling this function may cause a task switch (unless called with Timeout set
to 0).
If the semaphore count is greater than 0 (or is equal to 0, but without any pend-
ing task threads), the semaphore count is incremented and this function imme-
diately returns.
If the semaphore count is zero and there are tasks threads pending on it, the
count remains at zero, and the first thread in the pending list is unblocked.
Description This function resets the semaphore, first setting an initial semaphore count,
and then unblocking all tasks that are pending on the semaphore.
This function should be used with care. Tasks that are pending on the sema-
phore may exhibit unexpected behavior since all tasks pending on the sema-
phore will return from their respective SemPend() calls regardless of re-
quested timeout. The return value for the respective SemPend() calls will al-
ways be correct in that one or more tasks may get the semaphore (depending
on the value of Count), but tasks that called SemPend() without a timeout may
assume they have obtained the semaphore without checking the SemPend()
return value.
2-12
Memory Allocation Support
2.4.1 Synopsis
As part of normal stack operation, memory will be allocated and freed on a reg-
ular basis. It is therefore recommended that a memory support system have
the ability to allocate and free small memory blocks in a variety of sizes, without
memory fragmentation. The functions described here work on a memory buck-
et system of predefined fixed sizes. Although it allocates more memory than
requested, when the memory is released, it can be reused without fragmenta-
tion.
Description Allocates a memory block of at least size bytes in length. The function should
return a pointer to the new memory block, or NULL if memory is not available.
The size of the allocation cannot be more than 3068 bytes.
Return Value If a memory tracking error occurs, this function returns 0, else it returns 1
Description Frees a previously allocated memory block by supplying the pointer that
mmAlloc() originally returned.
2-14
Print and Debug Support
2.5.1 Synopsis
The OS abstraction includes a family of compact printf() functions that print us-
ing a fixed buffer. The size of the buffer (max printf() length) is defined in the
OS abstraction layer. The code to print to the standard output device is also
provided, and this function can be modified to print or log as required.
The stack also provides another form of the printf function called DbgPrintf().
This function is used to print debug messages to a global debug log. The se-
verity threshold at which the debug message is recorded can be adjusted as
well as at what point the error causes a system shutdown.
Description This function prints a debug message to the global debug log buffer. The log
buffer is defined as follows:
#define LL_DEBUG_LOG_MAX 1024
extern char DebugLog[LL_DEBUG_LOG_MAX]; // DebugLog
Buffer
extern int DebugLogSize; // Bytes of data currently
in DebugLog
The buffer behaves like one large NULL terminated string. The contents are
cleared by setting DebugLogSize to 0.
2-16
File I/O Support for Embedded Systems
2.6.1 Synopsis
The next section of this document discusses the support for stream IO that is
built into the stack library. The support documented in that section is intended
to augment the basic functions provided by the native operating system (in the
case where the stack is ported to a new environment).
This section details functionality required by the Network Tools services deal-
ing with File IO. The functionality described here is much more likely to have
a local counterpart. The API described in this section must be ported to allow
the network services that use it to operate.
Please Note: This API is unrelated to the stream API provided for Sockets. If
the services that require this API are not required, then this module can be dis-
carded from the OS abstraction. Currently, only the HTTP Server service
makes use of this API.
The API described here was taken from the Unix standard. The names of the
functions have been prefixed with the designation “efs_” which stands for em-
bedded file system. This was done so that the functions would not conflict with
any existing file system. The EFS API is a very simple RAM based file system.
A couple of new functions are included which allow the creation of RAM ”files”
by supplying pointers to static data buffers.
For systems with existing file systems most of the functions in this API become
shims to their standard IO counterparts.
As previously mentioned, most of the API closely matches its standard C coun-
terpart:
efs_fclose() Close file
efs_feof() Check for end of file
efs_fopen() Open file
Description This function creates an internal record of the RAM based file with the indi-
cated filename, file length, and data pointer. The file data is not copied, so the
buffer must be statically allocated. The filename is copied, so it does not need
to be static.
A static buffer based system is more efficient for embedded systems since the
data must already be present in RAM or ROM. However, the efs_createfile()
function could easily be altered to use allocated buffers which are later freed
when efs_destroyfile() is called. These create and destroy functions are only
called by the sample application code, and thus the system programmer is free
to alter the operation of these functions – so long as they create “files” that are
compatible with the rest of this API.
Description This function deletes the internal file record associating the filename with the
static data pointer as originally passed to efs_createfile().
2-18
File I/O Support for Embedded Systems
A static buffer based system is more efficient for embedded systems since the
data must already be present in RAM or ROM. However, the efs_createfile()
function could easily be altered to use allocated buffers which are later freed
when efs_destroyfile() is called. These create and destroy functions are only
called by the sample application code, and thus the system programmer is free
to alter the operation of these functions – so long as they create ”files” that are
compatible with the rest of this API.
Description This function returns the length in bytes of the indicated file. The file must al-
ready have been opened via a call to efs_fopen().
Description This function “loads” an executable file and returns a pointer to the entrypoint
function. The type EFSFUN is declared as:
typedef void (*EFSFUN)();
The application is really free to treat this function in whatever manner is re-
quired. This executable file is created with a call to efs_createfile() where the
pData parameter points to a function that is already loaded in memory. This
allows the HTTP server to call services “contained” in CGI files.
A static buffer based system is more efficient for embedded systems since the
data must already be present in RAM or ROM. However, the HTTP can be
made to work with physical CGI files by porting this function to load CGI.
Return Value Returns EOF if any errors occurred, and zero otherwise
Description This function performs a logical “close” on an open file. It is functionally equiva-
lent to fclose().
Return Value Returns non-zero if EOF has been reached, and zero otherwise
Description This function tests to see is the file position has reached the end of the file. It
is functionally equivalent to feof().
Description This function performs a logical “open” on the named file and returns a stream
or NULL if the attempt fails. It is functionally equivalent to fopen().
The mode parameter determines the mode for with the file is opened. In the
embedded file system version of this function, the list of supported modes is
quite simple:
“rb” – open binary file for reading
The flags are still passed though to ensure compatibility with a full file system.
2-20
File I/O Support for Embedded Systems
Syntax size_t efs_fread( void *ptr, size_t size, size_t nobj, EFS_FILE *stream );
Parameter(s) ptr Pointer to data buffer to receive data
size Size in bytes of a read “object”
nobj Number of objects to read
stream Pointer to open stream (file)
Return Value Returns the number of objects read
Description This function reads from the indicated stream in the array ptr at most nobj ob-
jects of a length specified by size. It returns the number of objects read; this
may be less than the number of objects requested. It is functionally equivalent
to fread().
efs_feof() can be used to detect end of file.
Syntax size_t efs_fwrite( void *ptr, size_t size, size_t nobj, EFS_FILE *stream );
Description This function writes to the indicated stream from the array ptr, up to nobj ob-
jects of a length specified by size. It returns the number of objects written; this
may be less than the number of objects requested on an error. It is functionally
equivalent to fwrite().
Nothing in the stack package requires write capability, thus this function al-
ways returns zero.
Description This sets the position of the indicated stream to zero, and clears any current
error. (Errors are not tracked in this implementation.)
2-22
Chapter 3
Topic Page
3-1
File Descriptor Environment
Since this stack supports the standard sockets interface functions, and these
functions require file descriptor support, the stack provides its own small file
system. This section describes the basic mechanics of the file system.
3.1.1 Organization
The basic building block of the stack code internally is an object handle. Inter-
nally to the stack, both sockets and pipes are addressed by object handles.
However, at the application level, sockets and pipes are treated as file descrip-
tors, which are integer indices. Integer representation is necessary to support
the classic Unix concept of the select() call.
The stack API supports the use of integer file descriptors, by adding a file des-
criptor layer of abstraction to the native operating environment. It is this layer
that implements the standard sockets and file IO functions. The stack works
by associating a file descriptor table with each caller’s thread (or in our ter-
minology, ’task’). In this system, each task has its own file descriptor table. The
file descriptor index passed to a file function is used to lookup the actual file
handle contained in the task’s associated file descriptor table. This enables the
stack to support both an object oriented and the classical Unix sockets API.
Note again that file descriptors are private to each particular task thread while
the actual pipe and socket objects are addressed by object handles. It is some-
times necessary to convert a file descriptor to a handle and back again in order
to pass the object to another task.
In order to use the file system and socket functions provided by the stack, a
task must first allocate a file descriptor table (called a file descriptor session).
This is accomplished at the application layer by calling the file descriptor func-
tion fdOpenSession(). When the task is finished using the file descriptor API,
or when it is about to terminate, fdCloseSession() is called.
3-2
File Descriptor Environment
All that is required for correct stack operation, is that a task must open a file
descriptor session before calling any file descriptor related functions, and
close it when it is done.
For example, the most straightforward approach would be for a task to open
its file session when it starts, and close it when it completes. For example:
Socket Task:
void socket_task( int IPAddr, int TcpPort )
{
SOCKET s;
// Open the file session
fdOpenSession( TaskSelf() );
< socket application code >
// Close the file session
fdCloseSession( TaskSelf() );
}
A second option would be for the task that creates the socket task to also open
the file descriptor session. Note that the parent task must guarantee that the
child task’s file session is open before the child task has had a chance to exe-
cute. This can be done via task priority, but it can be messy. Thus, it is not a
very common approach.
A third, more common option is to allow a child task to open its own file session,
but where a parent task monitors its children and has the ability to destroy
them. Here, the parent task must close the file session of the children it de-
stroys. Thus the child task must block when finished instead of terminating.
The following example illustrates this concept:
The parent task functions would look something like the following:
3-4
File Descriptor Programming Interface
3.2.1 Synopsis
The purpose of supporting a file system is to support the sockets API. Unfortu-
nately, the sockets API is not a complete IO API as it was originally designed
to integrate into the Unix file system. Thus, several file descriptor functions that
have become very important to the application programmer are not really
socket calls at all. The stack library supports a handful of what would normally
considered file functions so that sockets applications can be programmed in
a more traditional sense. In order that these functions will not conflict with any
other file functions in the system, their names have been altered slightly from
the standard definitions.
The stream IO object can take two forms. In the vast majority of cases, it will
be in the form of a local file descriptor. The following functions can operate on
file descriptors:
The file descriptor can be converted to a global file handle, which can then be
passed to another task thread. The handle is usually converted back to a file
descriptor by the receiving task thread. The following functions can operate on
file handles:
The fdSelect() function uses file descriptor sets to specify which file descrip-
tors are being checked for activity and which have activity detected. There is
a small set of MACRO functions for manipulating file descriptor sets. These
include the following:
FD_SET() Add a file descriptor to a file descriptor set
FD_CLR() Remove a file descriptor from a file descriptor set
FD_ISSET() Test to see if a file descriptor is included in a file
descriptor set
FD_COPY() Copy a file descriptor set
FD_ZERO() Clear (initialize) a file descriptor set
Description This function opens a file descriptor session on a task thread so that the task
can begin using file descriptor and other stream IO functions.
Description This function closes a file descriptor session that was previously opened with
fdOpenSession(). When called, any remaining open file descriptors are
closed.
3-6
File Descriptor Programming Interface
Syntax int fdSelect( int maxfd, fd_set *readset, fd_set *writeset, fd_set *exceptset,
struct timeval *timeout );
Parameter(s) maxfd The highest index contained in any of the three supplied
descriptor sets
readset Set of file descriptors to check for reading
writeset Set of file descriptors to check for writing
exceptset Set of file descriptors to check for exceptional conditions
(OOB data)
timeout Pointer to timeval structure of time to wait (or NULL)
Return Value Returns a positive count of ready descriptors (combined from all three possible
sets), 0 on timeout, or –1 on error. When an error occurs, the error type can
be obtained by calling fdError().
Description This function allows the task to instruct the stack to wait for any one of multiple
events to occur and to wake up the process only when one of more of these
events occurs or when a specified amount of time has passed.
The definition of the timeval structure is:
struct timeval {
INT32 tv_sec;
INT32 tv_usec;
};
Passing in a NULL pointer for timeout specifies an infinite wait period. Passing
a valid pointer to a timeval structure with both tv_sec and tv_usec set to zero
specifies that the function should not block.
Note: The error code returned via fdError() is stored in the file descriptor ses-
sion associated with a task. If a task calls a file or socket function before it
opens a file descriptor session, an error condition results. Obviously however,
no error code can be stored for retrieval by fdError() since the file descriptor
session doesn’t exist to hold it.
Syntax int fdTransfer( HANDLE hSrcTask, int fdsrc, HANDLE hDstTask, int *pfddst
);
Parameter(s) hSrcTask Handle of task which currently owns the file descriptor
fdsrc File descriptor to transfer
3-8
File Descriptor Programming Interface
Return Value Returns zero on success or –1 on error. If an error occurs, the state of the file
descriptor is not altered.
Description Although file descriptors are nice for functions like fdSelect(), they have a dis-
advantage in that they are not global across tasks. However, a file descriptor
can be transferred from one task to another so long as the task handles for both
tasks are known. This is an alternative to using the fdGetFileHandle() function.
This function transfers the file descriptor from the descriptor of hSrcTask to the
descriptor table of hDstTask. Note that after this call, the file descriptor be-
comes invalid for hSrcTask and can no longer be used by that task.
Note: Both the source and destination tasks must have called fdOpen-
Session() before the transfer can take place. This can make using
fdTransfer() tricky when one of the two tasks has been recently created.
In a parent/child relationship, it is safer for the child to call fdTransfer()
and then signal the parent if necessary to allow it to terminate.
Return Value File descriptor or –1 on error. This function is not strictly part of the file descrip-
tor function set, and does not elaborate on error conditions via fdError().
Description When a file is in handle form (i.e., does not belong to any task), there is not
much that can be done with it. However, in some cases it may be necessary
to close the handle without converting back to a file descriptor. This occurs
mostly when shutting down an application where multiple children share a
common file handle.
Return Value File descriptor or –1 on error. This function is not strictly part of the file descrip-
tor function set, and does not elaborate on error conditions via fdError().
Description Although file descriptors are nice for functions like fdSelect(), they have a dis-
advantage in that they are not global across tasks. However, file handles are
global and can be passed from one task to another. This function converts a
global file handle to a file descriptor that is local to the calling task. The returned
file descriptor can then be used in other file or socket calls.
This function converts a file handle to a file descriptor. Note that after this call,
the file handle should no longer be used.
Return Value Should be treated as a void function. The true return value is dependent on the
implementation of the macro.
Description This function is used to add a file descriptor to a file descriptor set, typically
before using the set in a call to fdSelect(). Note that after declaring a fd_set
data type, it should be initialized using FD_ZERO() before attempting to set
individual file descriptors.
3-10
File Descriptor Programming Interface
Return Value Should be treated as a void function. The true return value is dependent on the
implementation of the macro.
Description This function is used to remove a file descriptor from a file descriptor set, typi-
cally after the file descriptor has been “processed” in a loop that continuously
checks a file descriptor set.
Return Value Returns an int value which should be treated as a TRUE/FALSE condition.
Description This function returns TRUE if the supplied file descriptor is contained in the in-
dicated file descriptor set. This function is typically called after a call to fdSe-
lect() to determine on what file descriptors select has detected activity.
Description This function is called to make a copy of a file descriptor set. This is typically
done is a set needs to be modified, but this original information needs to be
maintained.
Description This function is called clear all bits in a file descriptor set. This should be the
first call made on a newly declared fd_set variable.
3-12
Sockets Programming Interfaces
Although TCP sockets that use the SOCK_STREAMNC stream type are 100%
compatible with the standard TCP socket type, they can also be used with the
recvnc() and recvncfrom() functions that UDP and RAW sockets use to elimi-
nate the final data copy from the stack to the sockets application. Using the “no
copy” functions with SOCK_STREAMNC eliminates two data copies from the
standard TCP socket. Note however that when recvnc() and recvncfrom() are
used with TCP, out of band data is not supported. If the SO_OOBINLINE sock-
et option is set, the out of band data is retained, but the out of band data mark
is discarded. If not using the inline socket option, the out of band data is dis-
carded.
3-14
Sockets Programming Interfaces
Parameter(s) s Socket
pName Name (address) of desired local address
len Size of pName
Return Value If it succeeds, the function returns 0. Otherwise, a value of –1 is returned and
the function fdError() can be called to determine the error:
EBADF The file descriptor (socket) is invalid.
ENOTSOCK The descriptor does not reference a socket.
EINVAL Listen has not been called on the socket or
name arguments are invalid.
EADDRNOTAVAIL The specified address is not available from the
local machine.
EADDRINUSE The specified address is already in use.
Description The bind() function assigns a name to an unnamed socket. When a socket is
created with socket() it exists in a name space (address family) but has no
name assigned. The bind() function requests that name be assigned to the
socket.
The argument s is a socket that has been created with the socket() function.
The argument pName is a structure of type sockaddr that contains the desired
local address. The len parameter contains the size of pName which is si-
zeof(struct sockaddr).
Parameter(s) s Socket
pName Name (address) of desired peer
len Size of pName
Return Value If it succeeds, the function returns 0. Otherwise, a value of –1 is returned and
the function fdError() can be called to determine the error:
EBADF The file descriptor (socket) is invalid.
ENOTSOCK The file descriptor does not reference a socket.
EINVAL Name arguments are invalid.
EADDRNOTAVAIL The specified address is not available from the
local machine.
Description The connect() function establishes a logical (and potentially physical) connec-
tion from the socket specified by s to the foreign name (address) specified by
pName.
If sock is of type SOCK_DGRAM, this call specifies the peer address with
which the socket is to be associated; this address is that to which datagrams
are to be sent, and the only address from which datagrams are to be received.
If the socket is of type SOCK_STREAM, the function attempts to make a con-
nection to another socket.
The argument s is a socket that has been created with the socket() function.
The argument pName is a structure of type sockaddr that contains the desired
foreign address. The len parameter contains the size of pName which is si-
zeof( struct sockaddr ).
Stream sockets may connect only once; while datagram sockets may re-con-
nect multiple times to change their association. The connection may be dis-
solved by attempting to connect to an illegal address (say NULL IP and Port).
Datagram sockets that require multiple connections may consider using the
recvfrom() and sendto() functions instead of connect().
Parameter(s) s Socket
pName Name (address) of connected peer
plen Pointer to size of pName
Return Value If it succeeds, the function returns 0. Otherwise, a value of –1 is returned and
the function fdError() can be called to determine the error:
EBADF The file descriptor (socket) is invalid.
ENOTSOCK The file descriptor does not reference a socket.
3-16
Sockets Programming Interfaces
Description The getpeername() function returns the name (address) of the connected
peer.
The argument pName is a result parameter that is filled in with the address of
the connecting entity as known to the communications layer. The domain in
which the communication is occurring determines the exact format of the
pName parameter. The plen is a value-result parameter; it should initially con-
tain at least sizeof( struct sockaddr ), the amount of space pointed to by
pName; on return it will contain the actual length (in bytes) of the address re-
turned.
Parameter(s) s Socket
pName Name (address) of connected peer
plen Pointer to size of pName
Return Value If it succeeds, the function returns 0. Otherwise, a value of –1 is returned and
the function fdError() can be called to determine the error:
EBADF The file descriptor (socket) is invalid.
ENOTSOCK The file descriptor does not reference a socket.
EINVAL Name arguments are invalid.
Description The getsockname() function returns the local name (address) of the socket.
The argument pName is a result parameter that is filled in with the address of
the connecting entity as known to the communications layer. The domain in
which the communication is occurring determines the exact format of the
pName parameter. The plen is a value-result parameter; it should initially con-
tain at least sizeof(struct sockaddr), the amount of space pointed to by pName;
on return it will contain the actual length (in bytes) of the address returned.
Syntax int getsockopt( int s, int level, int op, void *pbuf, int *pbufsize );
Parameter(s) s Socket
level Option level (SOL_SOCKET, IPPROTO_IP, IPPROTO_TCP)
Description The getsockopt() function returns the options associated with a socket. Op-
tions may exist at multiple protocol levels; they are always present at the up-
permost socket level.
When manipulating socket options, the level at which the option resides and
the name of the option must be specified. To manipulate options at the socket
level, level is specified as SOL_SOCKET. To manipulate options at any other
level the protocol number of the appropriate protocol controlling the option is
supplied. In this implementation, only SOL_SOCKET, IPPROTO_IP, and
IPROTO_TCP are supported.
The parameters pbuf and pbufsize identify a buffer in which the value for the
requested option(s) are to be returned. pbufsize is a value-result parameter,
initially containing the size of the buffer pointed to by pbuf, and modified on re-
turn to indicate the actual size of the value returned.
Most socket-level options utilize an int parameter for pbuf. SO_LINGER uses
a struct linger parameter, defined in INC\SOCKET.H, which specifies the de-
sired state of the option and the linger interval (see below). SO_SNDTIMEO
and SO_RCVTIMEO use a struct timeval parameter.
The following options are recognized at the socket level:
SO_REUSEADDR Specifies that the rules used in validating addresses
supplied in a bind call should allow reuse of local
addresses.
SO_REUSEPORT Allows completely duplicate bindings by multiple
processes if they all set SO_REUSEPORT before
binding the port. This option permits multiple
instances of a program to each receive UDP/IP mul-
ticast or broadcast datagrams destined for the
bound port.
SO_KEEPALIVE Enables the periodic transmission of messages on a
connected socket. Should the connected party fail
to respond to these messages, the connection is
considered broken and processes using the socket
are notified when attempting to send data.
3-18
Sockets Programming Interfaces
3-20
Sockets Programming Interfaces
Parameter(s) s Socket
maxcon Maximum number of connects to queue
Return Value If it succeeds, the function returns 0. Otherwise, a value of –1 is returned and
the function fdError() can be called to determine the error:
To accept connections, a socket is first created with socket(), The listen() func-
tion is called to specify a willingness to accept incoming connections and a
queue limit for incoming. New connections are accepted by calling the accept()
function. The listen() function applies only to sockets of type SOCK_STREAM.
The maxcon parameter defines the maximum length the queue of pending
connections may grow to. If a connection request arrives with the queue full,
the client receives an error with an indication of ECONNREFUSED.
Syntax int recv( int s, void *pbuf, int size, int flags );
Parameter(s) s Socket
pbuf Data buffer to place received data
size Size of desired data
flags Option flags
Return Value If it succeeds, the function returns the number of bytes received. Otherwise,
a value of –1 is returned and the function fdError() can be called to determine
the error:
3-22
Sockets Programming Interfaces
Description The recv() function attempts to receive data from a socket. It is normally used
on a connected socket (see connect()). The data is placed into the buffer spe-
cified by pbuf, up to a maximum length specified by size. The options in flags
can be used to change the default behavior of the operation.
For a datagram type socket, the receive operation always copies one packet’s
worth of data. If the buffer is too short to hold the entire packet, the data is trun-
cated and lost.
If no messages are available at the socket, it waits for a message to arrive, un-
less the socket is non-blocking. The function normally returns any data avail-
able, up to the requested amount, rather than waiting for receipt of the full
amount requested; this behavior is affected by the options specified in flags
as well as the socket-level options SO_RCVLOWAT and SO_RCVTIMEO de-
scribed in getsockopt().
The select call (fdSelect()) may be used to determine when more data arrives.
The flags argument to a recv() call is formed by combining one or more of the
following flags:
recvfrom Receive Data from a Socket with the Sender’s Name (address)
Syntax int recvfrom( int s, void *pbuf, int size, int flags, PSA pName, int *plen );
Parameter(s) s Socket
pbuf Data buffer to place received data
size Size of desired data
flags Option flags
pName Pointer to place name (address) of sender
plen Pointer to size of pName
Return Value If it succeeds, the function returns the number of bytes received. Otherwise,
a value of –1 is returned and the function fdError() can be called to determine
the error:
EBADF The file descriptor (socket) is invalid.
ENOTSOCK The file descriptor does not reference a socket.
EINVAL Name arguments are invalid.
ENOTCONN The socket is connection oriented and not con-
nected.
EWOULDBLOCK The socket is specified as non-blocking, or the
timeout has expired.
Description The recvfrom() function attempts to receive data from a socket. It is normally
called with unconnected, non-connection oriented sockets. The data is placed
into the buffer specified by pbuf, up to a maximum length specified by size. The
options in flags can be used to change the default behavior of the operation.
The name (address) of the sender is written to pName.
The argument pName is a result parameter that is filled in with the address of
the sending entity as known to the communications layer. The domain in which
the communication is occurring determines the exact format of the pName pa-
rameter. The plen is a value-result parameter; it should initially contain at least
sizeof( struct sockaddr ), the amount of space pointed to by pName; on return
it will contain the actual length (in bytes) of the address returned.
For a datagram type socket, the receive operation always copies one packet’s
worth of data. If the buffer is too short to hold the entire packet, the data is trun-
cated and lost.
If no messages are available at the socket, it waits for a message to arrive, un-
less the socket is non-blocking. The function normally returns any data avail-
able, up to the requested amount, rather than waiting for receipt of the full
amount requested; this behavior is affected by the options specified in flags
3-24
Sockets Programming Interfaces
The select call (fdSelect()) may be used to determine when more data arrive.
The flags argument to a recv() call is formed by combining one or more of the
following flags:
Syntax int recvnc( int s, void **ppbuf, int flags, HANDLE *phBuffer );
Parameter(s) s Socket
ppbuf Pointer to receive data buffer pointer
flags Option flags
phBuffer Pointer to receive buffer handle
Return Value If it succeeds, the function returns the number of bytes received. Otherwise,
a value of –1 is returned and the function fdError() can be called to determine
the error:
3-26
Sockets Programming Interfaces
recvncfrom Receive Data and Sender’s Name from Socket without Buffer Copy
Syntax int recvncfrom( int s, void **ppbuf, int flags, HANDLE *phBuffer, PSA pName,
int *plen );
Parameter(s) s Socket
ppbuf Pointer to receive data buffer pointer
flags Option flags
phBuffer Pointer to receive buffer handle
pName Pointer to place name (address) of sender
plen Pointer to size of pName
Return Value If it succeeds, the function returns the number of bytes received. Otherwise,
a value of –1 is returned and the function fdError() can be called to determine
the error:
EBADF The file descriptor (socket) is invalid.
ENOTSOCK The file descriptor does not reference a socket.
ENOTCONN The socket is connection oriented and not con-
nected.
Description The recvfrom() function attempts to receive a data buffer from a socket. It is
normally called with unconnected, non-connection oriented sockets. A pointer
to the data buffer is returned in ppbuf. A system handle used to free the buffer
is returned in phBuffer. Both of these pointers must be valid. The options in
flags can be used to change the default behavior of the operation. The name
(address) of the sender is written to pName.
The argument pName is a result parameter that is filled in with the address of
the sending entity as known to the communications layer. The domain in which
the communication is occurring determines the exact format of the pName pa-
rameter. The plen is a value-result parameter; it should initially contain at least
sizeof( struct sockaddr ), the amount of space pointed to by pName; on return
it will contain the actual length (in bytes) of the address returned.
The receive operation always returns one packet buffer. The caller has no con-
trol over the size of the data returned in this buffer.
If no messages are available at the socket, this call waits for a message to ar-
rive, unless the socket is non-blocking. The function returns the data buffer
available.
When the caller no longer needs the data buffer, it is returned to the system
by calling recvncfree(). Repeated failure to free buffers will eventually cause
the stack to stop receiving data.
This function can not be used with sockets of type SOCK_STREAM. When
used with sockets of type SOCK_STREAMNC, out of band data marks are
cleared.
The select call (fdSelect()) may be used to determine when more data arrives.
The flags argument to a recv() call can be one of the following flags:
Syntax int send( int s, void *pbuf, int size, int flags );
Parameter(s) s Socket
pbuf Data buffer holding data to transmit
size Size of data
flags Option flags
Return Value If it succeeds, the function returns the number of bytes sent. Otherwise, a value
of –1 is returned and the function fdError() can be called to determine the error:
EBADF The file descriptor (socket) is invalid.
ENOTSOCK The file descriptor does not reference a socket.
ENOTCONN The socket is connection oriented and not con-
nected.
EWOULDBLOCK The socket is specified as non-blocking, or the
timeout has expired.
EMSGSIZE The specified size exceeds the limit of the un-
derlying protocol.
ENOBUFS Memory allocation failure while attempting to
send data.
EHOSTUNREACH The remote host was unreachable.
Description The send() function attempts to send data on a socket. It is used on a con-
nected sockets only (see connect()). The data to send is contained in the buffer
specified by pbuf, with a length specified by size. The options in flags can be
used to change the default behavior of the operation.
The functions returns the length of the data transmitted on successful comple-
tion.
3-28
Sockets Programming Interfaces
For a datagram type socket, the send operation always copies one packet’s
worth of data. If the buffer is too long to hold the entire packet an error code
of EMSGSIZE is returned.
If there is not transmit buffer space available on a stream type socket, the func-
tion waits for space to become available, unless the socket is non-blocking.
The function normally transmits all the specified data.
The select call (fdSelect()) may be used to determine when the socket is “able
to write”.
The flags argument to a send() call is formed by combining one or more of the
following flags:
Syntax int sendto( int s, void *pbuf, int size, int flags, PSA pName, int len );
Parameter(s) s Socket
pbuf Data buffer holding data to transmit
size Size of data
flags Option flags
pName Pointer to name (address) of destination
len Size of data pointed to by pName
Return Value If it succeeds, the function returns the number of bytes sent. Otherwise, a value
of –1 is returned and the function fdError() can be called to determine the error:
EBADF The file descriptor (socket) is invalid.
ENOTSOCK The file descriptor does not reference a socket.
Description The sendto() function attempts to send data on a socket to a specified destina-
tion. It is used on a unconnected, non-connection oriented sockets only (see
connect()). The data to send is contained in the buffer specified by pbuf, with
a length specified by size. The options in flags can be used to change the de-
fault behavior of the operation.
The functions returns the length of the data transmitted on successful comple-
tion.
For a datagram type socket, the send operation always copies one packet’s
worth of data. If the buffer is too long to hold the entire packet an error code
of EMSGSIZE is returned.
The select call (fdSelect()) may be used to determine when the socket is “able
to write”.
The flags argument to a send() call is formed by combining one or more of the
following flags:
3-30
Sockets Programming Interfaces
Syntax int setsockopt( int s, int level, int op, void *pbuf, int bufsize );
Parameter(s) s Socket
level Option level (SOL_SOCKET, IPPROTO_IP, IPPROTO_TCP)
op Socket option to get
pbuf Pointer to memory buffer
bufsize Size of memory buffer pointed to by pbuf
Return Value If it succeeds, the function returns 0. Otherwise, a value of –1 is returned and
the function fdError() can be called to determine the error:
EBADF The file descriptor (socket) is invalid.
ENOTSOCK The file descriptor does not reference a socket.
EINVAL Buffer arguments are invalid.
Description The setsockopt() function sets option values associated with a socket. Options
may exist at multiple protocol levels; they are always present at the uppermost
socket level.
When manipulating socket options, the level at which the option resides and
the name of the option must be specified. To manipulate options at the socket
level, level is specified as SOL_SOCKET. To manipulate options at any other
level the protocol number of the appropriate protocol controlling the option is
supplied. In this implementation, only SOL_SOCKET, IPPROTO_IP, and
IPROTO_TCP are supported.
The parameters pbuf and bufsize identify a buffer which holds the value for the
specified option.
Most socket-level options utilize an int parameter for pbuf. SO_LINGER uses
a struct linger parameter, defined in INC\SOCKET.H, which specifies the de-
sired state of the option and the linger interval (see below). SO_SNDTIMEO
and SO_RCVTIMEO use a struct timeval parameter.
The socket options supported for setsockopt() are the same as defined for get-
sockopt() with the exception of SO_TYPE and SO_ERROR, which can not be
set.
Description The shutdown() function causes all or part of a full-duplex connection on the
socket associated with a socket to be shut down. If how is SHUT_RD (0), fur-
ther receives will be disallowed. If how is SHUT_WR (1), further sends will be
disallowed. If how is SHUT_RDWR (2), further sends and receives will be dis-
allowed.
Description The socket() function creates a socket, an endpoint for communication and re-
turns the socket in the form of a file descriptor.
The domain parameter specifies a communications domain within which com-
munication will take place; this selects the protocol/address family that should
3-32
Sockets Programming Interfaces
be used. These families are defined in the include file INC\SOCKET.H. This
will always be PF_INET (AF_INET) in this implementation.
3.4.1 Synopsis
Although sockets can be used for inter-task communications, it is not the most
efficient method. The stack provides a second data communications model
called pipes, which allow for local connection oriented communications.
Communications is performed using the standard file and sockets API func-
tions. All the file descriptor functions are supported with pipes: fdSelect(),
fdClose(), fdError(), and fdGetFileHandle().
Also, socket functions send() and recv() are used to write and read data
through the pipe. Both functions also support the following standard sockets
message flags when using pipes:
Pipes are connection oriented, thus when one end closes the other end is al-
tered by an error return from send() or recv(). It is therefore possible to make
a blocking call on recv() without concern that the function will be deadlocked
if the other end terminates the connection.
3-34
Full Duplex Pipes Programming Interface
Return Value File descriptor or –1 on error. A more detailed error code can be found by call-
ing fdError().
Description Creates a pre-connected full duplex pipe. The returned file descriptors can be
used with all the “fd” file descriptor functions, as well as the send() and recv()
socket functions.
Pipes are connection oriented, so like TCP, a read or write call can return EN-
OTCONN when the connection is broken by one side or the other.
Note that BOTH file descriptors must be closed to correctly close down
(and free) a pipe.
The first step in launching a network application is the initialization and configu-
ration of the network stack. This section covers Configuration Manager API
used to maintain system configurations, the Network Control module that uses
the configuration to initialize the network, and the specification of the individual
configuration components available.
Topic Page
4-1
Configuration Overview
The TCP/IP stack is supplied with three things that make the configuration and
boot process a little easier for the programmer. First, there is a programming
API for creating, walking, and editing a system configurations Secondly, initiali-
zation software is provided (with source code) that boots the system using a
configuration created with the configuration API, and completely initializes the
stack environment. Lastly, a user-expandable standard configuration specifi-
cation is defined.
4-2
Configuration Manager
4.2.1 Synopsis
The configuration manager is a collection of API functions that allow a user to
create and manipulate a configuration. The manager API is independent of the
configuration specification.
The configuration is based on an active database. That is, any change to the
database can cause an immediate reaction in the system. For example, if a
route is added to the configuration, it is added to the system route table. If the
route is then removed from the configuration, it is removed from the system
route table.
Configuration entry handles are referenced. This means that each handle con-
tains an internal reference count. This is used so that the handle is not de-
stroyed by one task while another task expects it to stay valid. Functions that
return a configuration entry handle supply a “referenced” handle in that its ref-
erence count had already been incremented for the caller. The caller can hold
this handle indefinitely, but should dereference it when it is through. There are
three calls that dereference a configuration entry handle. These are: CfgRe-
moveEntry(), CfgGetNextEntry(), and most simply CfgEntryDeRef(). See indi-
vidual function descriptions for more information.
The PPP module in the stack library and several modules in the NETTOOLS
library make use of a default configuration to store and search for data. The
default configuration is accessed by passing in a NULL configuration handle
to any function that takes the hCfg parameter (except CfgFree()). The default
configuration is specified by calling CfgSetDefault().
Configuration Functions:
CfgNew() Create a new configuration
CfgFree() Destroy a configuration
CfgSetDefault() Set Default Configuration
CfgGetDefault() Get Default Configuration
CfgLoad() Load configuration from a linear memory
buffer
CfgSave() Save configuration to a linear memory buffer
CfgSetExecuteOrder() Set the Tag Initialization and Shutdown Order
on Execute
CfgExecute() Make the configuration active or inactive
CfgSetService() Sets service callback function for a particular
tag
CfgAddEntry() Add a configuration entry to a configuration
CfgRemoveEntry() Remove entry from configuration
CfgGetEntryCnt() Get the number of item instances for a tag/
item pair
CfgGetEntry() Get a referenced handle to a configuration
entry
CfgGetNextEntry() Return supplied entry handle and get next
entry handle
CfgGetImmediate() Get configuration entry data w/o getting entry
handle
4-4
Configuration Manager
Syntax int CfgAddEntry( HANDLE hCfg, uint Tag, uint Item, uint Mode, uint Size,
UINT8 *pData, HANDLE *phCfgEntry );
Return Value Returns 1 on success with successful processing by a service callback func-
tion (see CfgSetService()).
Description This function creates a new configuration entry and adds it to the configuration.
the function writes the referenced handle of the new configuration entry to the
location specified by this parameter. It is then the caller’s responsibility to der-
eference this handle when it is finished with it. When the parameter phCfgEntry
is NULL, no entry handle is returned, but the function return value is still valid.
Configuration entry handles are dereferenced by the calling one of the follow-
ing:
CfgEntryDeRef() Stop using the entry
CfgRemoveEntry() Stop using entry and remove it from the configuration
CfgGetNextEntry() Stop using entry and get next entry
If the execution state of the configuration is active (see CfgExecute()), then the
addition of the configuration entry is immediately reflected in the operating
state of the system.
Multiple configuration entries can exist with the same Tag and Item key values.
The system creates a third key (Instance) to track these duplicate keyed en-
tries. However, by default, the configuration system does not allow for fully du-
plicate entries. Entries are full duplicates if there exists another entry with the
same Tag and Item key values and an exact duplicate data section (size and
content). When a full duplicate entry is detected, the new (duplicate) entry is
not created.
The user has some options in how the entry is added to the configuration. This
is done with flags that can be set in the Mode parameter. The default behavior
when adding an object is as follows:
- Multiple instances with the same Tag and Item values are allowed,
however
- Duplicate instances with the same Tag, Item, Size, and pData contents are
ignored.
- New entries are saved to the linear buffer if/when CfgSave() is used.
To modify the default behavior, one, or more of the following flags can be set:
CFG_ADDMODE_UNIQUE Replace all previous entry instances
with this single entry.
CFG_ADDMODE_DUPLICATE Allow full duplicate entry (duplicate Tag,
Item, and entry data). Requests to add
duplicates are normally ignored.
CFG_ADDMODE_NOSAVE Don’t include this entry in the linear
buffer in CfgSave().
4-6
Configuration Manager
Return Value Returns 0 on success, or less than 0 on an operation error. The possible errors
are:
CFGERROR_BADHANDLE Invalid hCfg handle
CFGERROR_BADPARAM Invalid function parameter
CFGERROR_ALREADY Configuration is already in desired
state
Description When a configuration is first created, it is in an inactive state. This means that
changes to the configuration are not reflected by changes to the system.
Description Destroys a configuration. Unloads and frees all configuration entries and frees
the configuration handle. After this call, the configuration handle hCfg is inval-
id.
Parameter(s) none
Return Value Returns a handle to the current default configuration, or NULL if none.
Description This function returns the current default configuration handle. The default han-
dle is used in any function that takes a hCfg parameter, when the specified pa-
rameter is NULL. At initialization, there is no default configuration. It must be
allocated by CfgNew() and then specified via CfgSetDefault(). Normally, the
default configuration is reserved for system use.
Syntax int CfgGetEntry( HANDLE hCfg, uint Tag, uint Item, uint Index, HANDLE
*phCfgEntry );
Description This function searches the configuration for entries matching the supplied Tag
and Item parameters and returns the item matching the supplied Index param-
eter. For example if Index is 1, the first instance is returned, if Index is 2, the
second instance is returned. The total number of instances can be found by
calling CfgGetEntryCnt().
The phCfgEntry parameter is an optional pointer which can return the handle
to the configuration entry found by this function. When the phCfgEntry param-
eter is valid, the function writes the referenced handle of the configuration
entry found to the location specified by this parameter. It is then the caller’s re-
4-8
Configuration Manager
sponsibility to dereference this handle when it is finished with it. When the pa-
rameter phCfgEntry is NULL, no entry handle is returned, but the function re-
turn value is still valid (“found” or “not found”).
Configuration entry handles are dereferenced by the calling one of the follow-
ing:
CfgEntryDeRef() Stop using the entry
CfgRemoveEntry() Stop using entry and remove it from the configuration
CfgGetNextEntry() Stop using entry and get next entry
Note: Do not attempt to use the Index value to enumerate all entry instances
in the configuration. The index of an entry handle is valid only at the time of the
call as an item can move up and down in the list as configuration changes are
made. To enumerate every entry for a Tag/Item pair, start with index 1, and then
use CfgGetNextEntry() to get additional entries.
CfgGetEntryCnt Get the Number of Entry Instances for the Supplied Tag/Item Pair
Return Value Returns 0 or greater on success (number if instances found) or less than 0 on
error. The possible errors are:
CFGERROR_BADHANDLE Invalid hCfg handle
CFGERROR_BADPARAM Invalid function parameter
Description This function searches the configuration for all instances matching the sup-
plied Tag and Item parameters and returns the number of instances found.
Syntax int CfgGetImmediate( HANDLE hCfg, uint Tag, uint Item, uint Index, int Size,
UINT8 *pData );
CfgGetNextEntry Get the Next Entry Instance Matching the Supplied Entry Handle
4-10
Configuration Manager
When the phCfgEntryNext parameter is not NULL, the function writes a refer-
enced handle to the configuration entry to the location specified by this param-
eter. It is then the caller’s responsibility to dereference this handle when it is
finished with it.
Configuration entry handles are dereferenced by the calling one of the follow-
ing:
Return Value Returns the number of bytes loaded, or less than 0 on an error. The possible
errors are:
CFGERROR_BADHANDLE Invalid hCfg handle
CFGERROR_BADPARAM Invalid function parameter
Description One of the features of the configuration system is the ability for the manager
to convert a configuration database to a linear block of memory for storage in
non-volatile memory. The configuration can then be converted back on reboot.
Parameter(s) none
Return Value Returns handle to new configuration or NULL on memory allocation error.
Description Creates a configuration handle that can be used with other configuration func-
tions. The new handle defaults to the inactive state (see CfgExecute()).
Return Value Returns 0 on success or less than 0 on error. The possible errors are:
CFGERROR_BADHANDLE Invalid hCfg handle
CFGERROR_BADPARAM Invalid function parameter
If the execution state of the configuration is active (see CfgExecute()), then the
removal of the configuration entry is immediately reflected in the operating
state of the system.
4-12
Configuration Manager
Syntax int CfgSetService( HANDLE hCfg, uint Tag, int (*pCb) (HANDLE, uint, uint,
uint, HANDLE) );
Return Value Returns 0 on success, or less than 0 on error. The possible errors are:
CFGERROR_BADHANDLE Invalid hCfg handle
CFGERROR_BADPARAM Invalid function parameter
Description In order to give the configuration the ability to be “active” – i.e., to make real-
time changes to the system as the configuration changes, the configuration
manager must have the ability to make changes to the system. To enable this
in a generic fashion, the configuration manager allows for the installation of
service callback functions for each configuration tag value.
This function sets the service function for a particular configuration tag. Ser-
vice function pointers default to NULL, and when they are NULL, no service
is performed for the configuration entry (it becomes information data only).
When invoked, the service callback function is passed back information about
the affected entry. The callback function is defined as:
int CbSrv( HANDLE hCfg, uint Tag, uint Item, uint Op,
HANDLE hCfgEntry );
hCfg HANDLE to Config
Tag Tag value of entry changed
Item Item value of entry changed
Op Operation (CFGOP_ADD or CFGOP_REMOVE)
hCfgEntry Non-Referenced HANDLE to entry added or removed
Note: The configuration entry handle passed to the callback function is NOT
referenced in that its scope expires when the callback function returns.
Syntax int CfgSetExecuteOrder( HANDLE hCfg, uint Tags, uint *pOpenOrder, uint
*pCloseOrder );
4-14
Configuration Manager
Return Value Returns zero on success, or less than 0 on an operation error. The possible
errors are:
CFGERROR_BADHANDLE Invalid hCfg handle
CFGERROR_BADPARAM Invalid function parameter
Description The configuration API has no knowledge of the configuration database specifi-
cation. Thus, it has no concept of a priority in loading and unloading configura-
tion entries. The default order for both loading and unloading is by ascending
tag value.
An application may wish to specify the exact order in which entries should be
initialized ( specified in pOpenOrder) and shutdown (specified in pCloseOder).
Both arrays must be provided – even if they are identical pointers. The number
of elements in each array is specified by the Tags parameter. This must exactly
match the max number of tags in the system defined by CFGTAG_MAX. An
entry of 0 in either order array is used as a placeholder for tags that have not
yet been defined.
Return Value Returns 0 on success, or less than 0 on an operation error. The possible errors
are:
CFGERROR_BADHANDLE Invalid hCfgEntry handle
Description This function removes a reference to the configuration entry handle supplied
in hCfgEntry. It is called by an application when it wishes to discard a refer-
enced configuration entry handle. Once this function is called, the handle
should no longer be used.
Description This function is used to get the entry data of the configuration entry specified
by the entry handle in hCfgEntry.
The value pointed to by pSize is set to the size of the supplied buffer, or zero
to get the required size (the pointer pSize must be valid, but the value at the
pointer can be zero). If the value at pSize is zero, or less than the number of
bytes required to hold the entry data, this function returns 0, and the number
of bytes required to hold the data is stored at pSize.
The pData parameter points to the data buffer to receive the configuration
entry data. This pointer can be null if *pSize is zero.
Description This function is used to get the size and pointer to a configuration entry’s data
buffer.
The entry handle is supplied hCfgEntry. A pointer to receive the size of the
entry’s data buffer is supplied in pSize, and a pointer to receive a pointer to the
entry’s data buffer is supplied in ppData. Either pointer parameter can be left
NULL if the information is not required.
4-16
Configuration Manager
This function should be used with great care. Direct manipulation of the config-
uration entry data should only be attempted on informational tags, and only
when the caller holds a referenced handle to the configuration entry. This func-
tion is used in configuration service callback functions, which are called only
when the configuration is in a protected state.
Return Value Returns 0 on success, or less than 0 on an operation error. The possible errors
are:
CFGERROR_BADHANDLE Invalid hCfgEntry handle
Description This function adds a reference to the configuration entry handle supplied in
hCfgEntry. It is called by an application when it intends to use an configuration
entry handle beyond the scope of the function which obtained it from the con-
figuration. This normally occurs when one user function calls another and
passes it a handle.
Return Value Returns the number of bytes written, 0 on a “size error” (new size does not
match old size), or less than 0 on an operation error. The possible errors are:
CFGERROR_BADHANDLE Invalid hCfgEntry handle
CFGERROR_BADPARAM Invalid function parameter
Description This function is used to replace the entry data of the configuration entry speci-
fied by the entry handle in hCfgEntry.
The new entry data is pointed to by the pData parameter with a size indicated
by Size. Note that the new data must be an exact replacement for the old. The
size of the new buffer must exactly match the old size.
This function should be used for configuration entries that are for information
purposes only. Note that if a service provider callback is associated with the
Tag value of this entry, the processing function is not called as a result of this
data update. This function only updates the data stored for this configuration
entry.
4-18
Network Control Initialization Procedure (NETCTRL)
4.3.1 Synopsis
4.3.2 Basics
3) Build the new configuration via configuration API calls, or load a previous
configuration from non-volatile memory using CfgLoad().
6) Under normal operation, the network does not shutdown until the
NC_NetStop() function is called. At some point after a call to
NC_NetStop(), the original NC_NetStart() thread calls the user supplied
callback function for the “stop” operation. In this callback function, the
application shuts down any operation it initiated in the “start” callback
function and frees any allocated resources. After the “stop” callback
function returns, TCP/IP stack functionality is no longer available.
7) The original call to NC_NetStart() returns with the return value as set by
the return parameter passed in the call to NC_NetStop(). The application
can immediately reboot the TCP/IP stack by calling NC_NetStart() again
with or without reloading a new configuration. This is useful for a reboot”
command.
When the system is ready for a final shutdown, the following actions are per-
formed:
8) When NC_NetStart() returns and the session is over, call the CfgFree()
function to free the configuration handle created with CfgNew().
9) After all resources have been freed, call the NC_SystemClose() function
to complete the system shutdown.
4-20
Network Control Initialization Procedure (NETCTRL)
Description This function is called to boot up the network using the network configuration
supplied in hCfg. Along with the network configuration, three callback function
pointers are provided. These callback functions are called at distinct times.
NetStartCb() is called when the system is first ready for the creation of applica-
tion supplied network tasks, and NetStopCb() is called when the network is
about to shutdown, and NetIPCb() is call when an IP address is added or re-
moved from the system. If any of these callback functions are not required, the
function pointers can be set to NULL.
The NC_NetStart() function will not return until the entire network session has
completed. Thus all user supplied network code (creation of user tasks) should
be included in the NetStartCb() function.
The user has the option of immediately calling NC_NetStart() again upon re-
turn. This makes for a good stack reboot function. Optionally, the configuration
can also be reloaded. This allows the stack to be restarted after a major config-
uration change.
Description This function is called to shutdown a network initiated with NC_NetStart(). The
return value supplied in the StopCode parameter becomes the return value for
NC_NetStart(). See the description of NC_NetStart() for more detail.
Parameter(s) none
Description This is the first function that should be called when using the stack. It initializes
the stack’s memory manager, and the OS (or OS translation layer).
Parameter(s) none
Description This is the last function that should be called when using the stack. It shuts
down the memory manager and performs a final memory analysis.
4-22
Configuration Specification
4.4.1 Synopsis
The specification of all the various configuration options for the stack would
require a separate document. This section details that part of the configuration
that is relied upon by the Network Control (NC) initialization functions, or the
services contained in the NETTOOLS library. The stack itself does not refer-
ence the configuration system. It has its own (vastly simpler) method that is
detailed in the appendix, but it is redundant when using the configuration API
(in fact they conflict as the Net Control functions assume full control of it).
4.4.2 Organization
As already mentioned, the configuration is arranged as a database with the
value “Tag” as a major key, and the value “Item” as a minor key. Every major
stack configuration component has a major key (“Tag”) value, including: net-
work services (protocol servers), connected IP networks, gateway routes,
connected client entities, global system information, and low-level stack con-
figuration.
Most of these tags require service callback functions to implement the system
functionality. For example, when a user adds an IP network using the
CFGTAG_IPNET tag, there must be a function that makes the corresponding
system calls that actually adds the network to the system route table. All these
server callback functions are contained in the NETCTRL directory. Although
source code to these functions is provided, many of the system calls they make
can only be understood by reading the attached appendices.
The tag values currently defined are:
CFGTAG_SERVICE Network Service
CFGTAG_IPNET IP Network (Address, subnet mask, etc.)
CFGTAG_ROUTE IP Gateway Route
CFGTAG_CLIENT IP Client (Client IP, Hostname, etc.)
CFGTAG_ACCT Client user account (name, password, etc.)
CFGTAG_SYSINFO Global System Information
CFGTAG_STACK Low-level Stack Configuration
CFGTAG_OS Operating System Configuration Entry
CFGTAG_IP IP Stack Configuration Entry
Note that all these services are obtained directly from the NETTOOLS services
API. The configuration system adds a level of abstraction so that a list of ser-
vices can be added to a configuration, and then the service provider callback
functions contained in the Net Control initialization routines can automatically
load the services at runtime without the user calling the NETTOOLS API direct-
ly.
The type of service is indicated by the value of the Item parameter supplied
to the CfgAddEntry() function. The defined service types include (by Item):
CFGITEM_SERVICE_TELNET Telnet Server
CFGITEM_SERVICE_HTTP HTTP Server
CFGITEM_SERVICE_NAT Network Address Translation
System
CFGITEM_SERVICE_DHCPSERVER DHCP Server
CFGITEM_SERVICE_DHCPCLIENT DHCP Client
CFGITEM_SERVICE_DNSSERVER DNS Server
Each individual service has its own specific configuration instance structure,
but they all share a generic argument structure. This is defined as follows:
// Common Service Arguments
typedef struct _ci_srvargs {
uint Item; // Copy of Item value (init to NULL)
HANDLE hService; // Handle to service (init to NULL)
uint Mode; // Flags
uint Status; // Service Status (init to NULL)
uint ReportCode; // Standard NETTOOLS Report Code
uint IfIdx; // If physical index
IPN IPAddr; // Host IP Address
void(*pCbSrv)(uint, uint, uint, HANDLE); // CbFun for status change
} CISARGS;
- uint Item;
This is a copy of the Item value used when the entry is added to the config-
uration. Its initial value should be NULL, but it is overwritten by the service
provider callback. It is used so that the status callback function can be pro-
vided with the original Item value.
4-24
Configuration Specification
- HANDLE hService;
- uint Mode;
- uint Status;
The status parameter contains the service status as detected by the Net
Control service callback function that initiates the service with NET-
TOOLS. The value of status should be initialized to NULL. Its defined val-
ues are:
J CIS_SRV_STATUS_DISABLED – Service not active (NULL state)
J CIS_SRV_STATUS_WAIT – Net Control is waiting on IP resolution to
start service
J CIS_SRV_STATUS_IPTERM – Service was terminated because it
lost its IP address
J CIS_SRV_STATUS_FAILED – Service failed to initialize via its NET-
TOOLS open function
J CIS_SRV_STATUS_ENABLED – Service enabled and initialized
properly
- uint ReportCode;
All the services available via the configuration can also be launched direct-
ly via a NETTOOLS API. The NETTOOLS service API has a standard ser-
vice reporting callback function that is mirrored by the configuration sys-
tem via the Net Control service provider callback. This variable holds the
last report code reported by the NETTOOLS service invoked by this con-
figuration entry.
- uint IfIdx;
- IPN IPAddr;
This is the IP address (in network format) on which to initiate the service.
This IP address can specify the wildcard INADDR_ANY, in which case the
service will accept connections to any valid IP address on any device. Note
that some services (like DHCP sever) do not support being launched by IP
address and require a device index (supplied in IfIdx) on which to execute.
void(*pCbSrv)(uint, uint, uint, HANDLE);
The pCbSrv parameter contains a callback function that is called when the
status of the service changes. It can be set to NULL if a callback is not re-
quired. The specification of the callback function is as follows:
void StatusCallback( uint Item, uint Status, uint
Code, HANDLE hCfgEntry )
Note that the Status parameter is the same as the Status field described in
this structure. The Code parameter is that returned by the NETTOOLS
service callback, which is a lower-level status callback function used by
Net Control.
4-26
Configuration Specification
- uint NetType;
This is type of network that appears on the interface. The network type de-
termines how the network is treated by some services like NAT, DHCP, and
DNS. The value is a collection of one or more of the following flags:
J CFG_NETTYPE_DYNAMIC – Address created by DHCP CLIENT
J CFG_NETTYPE_VIRTUAL – Virtual Network used by DNS resolver
J CFG_NETTYPE_DHCPS – Virtual Net Server reported by DHCP
SERVER
Most of the flags deal with the virtual network (or home network). If none of
these flags are set, the network is a normal physical network. Note that
virtual and non-virtual networks should not appear on the same interface.
Also, only one network entry on each interface can have any of these flags
set, although more than one of these flags can be set in that one entry.
- IPN IPAddr;
This is the IP address of the stack on the designated interface. When the
NetType flag “DHCPS” is set, this address is also the “gateway” address
reported to DHCP clients served by the DHCP server service.
- IPN IPMask;
- HANDLE hBind;
This is the stack’s internal binding handle for the network. Each connected
network is represented as a binding internally to the stack. This is dis-
cussed further in the appendices at the end of this document. The value
should be initialized to NULL.
- char Domain[CFG_DOMAIN_MAX];
This is the domain name of the network. It should be a full domain like
“home1.net”, not just “home1”.
4-28
Configuration Specification
The ROUTE entry specifies a route from one network to another via a specified
IP gateway. When specifying a ROUTE entry to the configuration, the Tag pa-
rameter is set to CFGTAG_ROUTE, and the Item parameter is not used (set
to zero).
// Route Instance
typedef struct _ci_route {
IPN IPDestAddr; // Destination Network Address
IPN IPDestMask; // Subnet Mask of Destination
IPN IPGateAddr; // Gateway IP Address
HANDLE hRoute; // Route handle (initially NULL)
} CI_ROUTE;
- IPN IPDestAddr;
This is the IP base address of the IP network of the network that is made
accessible via the IP gateway. This value should be pre-masked with the
IPDestMask so that:
This is used as a sanity check by the system. For a default route, the value
is zero.
- IPN IPDestMask;
- IPN IPGateAddr;
This the IP address of the gateway through which the specified IP network
is accessible. It must be an IP address that is available on a locally con-
nected network, i.e., one gateway can not point to another.
- HANDLE hRoute;
This is a handle to the route created by this configuration entry. All routes
are represented as route handles internally to the stack. This is discussed
further in the appendices at the end of this document. The value should be
initialized to NULL.
2) They are used by the DHCP server service to track DHCP clients on the
serviced virtual network.
- uint ClientType;
This is type of client record. There are only two types – those created by
DHCP server from an address pool, and those created manually by an ap-
plication.
J CFG_CLIENTTYPE_DYNAMIC – Entry created via DHCPS
J CFG_CLIENTTYPE_STATIC – Entry created manually
- uint Status;
This is status of the client record. It is used by the DHCP server to track the
state of the client and its lease to its IP address. The status can also be
NULL for STATIC entries.
J CFG_CLIENTSTATUS_PENDING – Supplied via DHCP OFFER
J CFG_CLIENTSTATUS_VALID – Validated by DHCP REQUEST
4-30
Configuration Specification
- IPN IPAddr;
- char MacAddr[6];
- char Hostname[CFG_HOSTNAME_MAX];
This is the hostname of the client. It is recorded by the DHCP server ser-
vice, even if the record is STATIC. Thus, when running DHCP server, even
with a fixed client list, DHCP clients can specify their own host names, and
this names will be available to the DNS resolver – i.e., DNS server and
DNS client.
- UINT32 TimeStatus;
This is the last time that the Status parameter was validated. It is thus the
start time of a DHCP client lease.
- UINT32 TimeExpire;
This is the total time in seconds of a DHCP client lease reported by the
DHCP server to its clients. When using an address pool for the DHCP
server, the server chooses this value.
- uint Flags;
The flags determine the access granted by channel or group. The chan-
nels or groups that any given PPP server will allow is determined when the
PPP server is invoked. A singe client account can be a member of one or
more groups, thus one or more of the following flags can be set:
J CFG_ACCTFLG_CH1 – Allow access to channel/group 1
J CFG_ACCTFLG_CH2 – Allow access to channel/group 2
J CFG_ACCTFLG_CH3 – Allow access to channel/group 3
J CFG_ACCTFLG_CH4 – Allow access to channel/group 4
- char Username[CFG_ACCTSTR_MAX];
This is the username of the client.
- char Password[CFG_ACCTSTR_MAX];
This is the password corresponding to the supplied client username.
4-32
Configuration Specification
When Tag is CFGTAG_IP, the value of Item can be one of the following:
4-34
Configuration Specification
Included with the stack package is a library of network tools. It provides auxilia-
ry functionality to the stack library and contains source written to the socket
layer that would normally be considered application level code. The library file
is called NETTOOLS.LIB, and can be accessed by an application that includes
the file NETTOOLS.H.
Topic Page
5-1
Generic Support Calls
5.1.1 Synopsis
This section contains a selection of functions that can be very useful when pro-
gramming network applications. Some are standard Berkeley while others are
custom to the stack – designed to save the programmer the time and trouble
of programming directly to the stack API.
Description This function converts an IP address printed in a character string to a 32bit net-
work ordered IP address value. Note that leading 0’s in the address string are
interpreted as octal. The function returns NULL on failure.
5-2
Generic Support Calls
This function actually calls inet_aton(), which is the better form of the function.
Description This function adds a static gateway route to the system route table.
This is used as a sanity check by the system. For a default route, the value is
zero.
IPGateAddr is the IP address of the gateway though which the specified IP net-
work is accessible. It must be an IP address that is available on a locally con-
nected network. I.e.: one gateway can not point to another.
The function returns a handle to the route created by this configuration entry.
All routes are represented as route handles internally to the stack. This is dis-
cussed further in the appendices at the end of this document. Note that the
handle returned here is not referenced (see the appendix for more details). All
it means the purposes of this function is that the handle can be discarded by
the caller. It will remain valid until the route is removed via NtRemoveStatic-
Gateway().
Note: In place of this function, the caller should consider using the con-
figuration system with the CFGTAG_ROUTE configuration entry (see
section 4.4.5).
5-4
Generic Support Calls
Return Value Returns 1 if the route was removed or 0 if it was not found.
Description This function removes a static gateway route from the system route table. It
searches for the route by destination IP address and will remove the first
matching static route it finds. Note that only routes with both the GATEWAY
and STATIC flags set are considered for removal.
Description This function obtains the first IP host address found that is assigned to the sup-
plied interface index. The host address (in network format) is written to the
pointer pIPAddr.
Description This function gets the “best” IP address and domain name to use for access
to the external network. For determining the “best” address and domain name,
public addresses and domain names are preferred over IP addresses and do-
main names of virtual networks. The IP address (in network format) is written
to pIPAddr, and the domain name is copied to pDomain.
Description This function performs an sprintf() of the IP address supplied in IPAddr to the
buffer supplied in pStrBuffer. Note, no buffer size is provided. This is because
the size is deterministic, and won’t exceed 16 characters (including the NULL
terminator).
5-6
DNS Support Calls
5.2.1 Synopsis
The concepts and code behind the Unix gethostbyname() and gethostby-
addr() functions is extensive. And there are public domain versions available,
can be easily run on the IP stack library.
Although the code to support the whole name, address and server database
is quite large, the basic name resolution functions are quite useful. For this rea-
son, the stack provides a basic form of these function calls, without incurring
the overhead associated with a full implementation. The DNS ”resolver” used
by these client functions is the same as accessed by the DNS server. When
the configuration contains ”client” machine records (i.e.: controls local domain
names), these entries are checked when the matching domain is encountered.
Otherwise (and for all other queries); the query is resolved via external DNS
servers.
The DNS client functions all take a pointer to a buffer. They treat this buffer as
a pointer to a host entry structure. In the case where the function takes a point-
er to a “scrap” buffer, a host entry structure is allocated from the start of this
scrap buffer. Thus on successful return from one of these calls, the pointer to
the scrap buffer may be treated as a pointer to a host entry structure.
Description This function is quite similar to BSD’s gethostname(). It requests the hostname
of the system’s public IP address (as obtained from NtGetPublicHost()). The
hostname is copied into the buffer pointed to by ‘pNameBuf’ with a max size
of ‘size’. The name is NULL terminated when space allows.
5-8
DNS Support Calls
Description This function is quite similar to BSD’s gethostbyaddr(). It uses DNS to resolve
a hostname from the supplied IP address. On a successful return, ‘pScrapBuf’
can be treated as a HOSTENT structure. The size of the scrap buffer (‘size’)
must be greater than the size of the structure as the structure will contain point-
ers into the scrap buffer, and the scrap buffer is also used for temporary name
storage. 512 bytes should be sufficient for most requests.
Description This function is quite similar to BSD’s gethostbyname(). It uses DNS to resolve
an official hostname and address from the supplied hostname. On a success-
ful return, ‘pScrapBuf’ can be treated as a HOSTENT structure. The size of the
scrap buffer (’size’) must be greater than the size of the structure as the struc-
ture will contain pointers into the scrap buffer, and the scrap buffer is also used
for temporary name storage. 512 bytes should be sufficient for most requests.
If the hostname Name is terminated with a dot (‘.’), the dot is removed prior to
lookup. If a dot appears anywhere in Name, an initial lookup on the unaltered
name is attempted. If Name does not contain a dot, or if the initial lookup fails,
the default domain name (from NtGetPublicHost()) is appended to the end of
the supplied name. For example, if the domain name obtained from NtGetPu-
blicHost() was “ti.com”, then a request for “host.sc” would attempt to resolve
“host.sc” first, and then “host.sc.ti.com”, while a request for “host” would at-
tempt to resolve “host.sc.ti.com” on the initial attempt.
5.3.1 Synopsis
TFTP is supported via the received function. More information on TFTP can
be found in rfc783.
Syntax int NtTftpRecv( UINT32 TftpIp, char *szFileName, char *pFileBuffer, UINT32
*pFileSize, UINT16 *pErrorCode );
Return Value This function returns an error code indicating the results of the operation. Neg-
ative codes are error conditions.
In the following cases, pFileSize is set to the actual number of bytes copied:
TFTPERROR_ERRORREPLY Error returned by TFTP server (see
below)
TFTPERROR_BADPARAM Invalid calling parameters
TFTPERROR_RESOURCES Memory allocation error during trans-
fer
TFTPERROR_SOCKET Internal socket error during transfer
TFTPERROR_FAILED TFTP failed (e.g., server didn’t reply)
5-10
TFTP Support Calls
Description TFTP (Trivial File Transfer Protocol), allows files to be transferred from a re-
mote machine.
This function attempts to receive the file with the filename designated by szFi-
leName from the TFTP server with the IP address in TftpIp, any copy the data
into the memory buffer pointed to by pFileBuffer. Note that when specifying the
name of the file in szFileName, certain operating systems have case sensitive
naming conventions.
On entry, the parameter pFileSize must point the size of the buffer pointed to
by pFileBuffer. If the value at *pFileSize is null, the pFileBuffer parameter can
be NULL.
This function attempts to receive the entire file, even if the buffer space is insuf-
ficient. The return value indicates if the file was received.
A return value of 1 indicates that the file was received and copied into the buff-
er. A return value of 0 indicates that the file was received, but was too large
for the specified buffer. In both these cases, the actual size of the file in bytes
is written back to *pFileSize.
A negative return value indicates that an error has occurred during transfer.
In this case, the number of bytes actually consumed in the buffer is written back
to *pFileSize. An error return of TFTPERROR_ERRORREPLY is a special re-
turn value that indicates that an error code was returned from the TFTP server.
In this case, the server’s TFTP error code is written to *pErrorCode, and the
server’s TFTP error message string is copied to the data buffer pointer to by
pFileBuffer.
Included with the stack package is a library of network tools. It provides auxilia-
ry functionality to the stack library and contains source written to the socket
layer that would normally be considered application level code. The library file
is called NETTOOLS.LIB, and can be accessed by an application that includes
the file NETTOOLS.H.
Topic Page
6-1
Service Calling Conventions
Note that this function relies on the physical value of items in the configuration
specification found in the file: src\nettools\netcfg.h
static void ServiceReport( uint Item, uint Status, uint Report, HANDLE h )
{
printf( ”Service Status: %–9s: %–9s: %–9s: %03d\n”,
TaskName[Item–1], StatusStr[Status],
ReportStr[Report/256], Report&0xFF );
}
The common calling interface consists of a simple Open and Close concept.
The Open function initiates the service and returns a service handle, while the
Close function shuts down the service using the service handle returned from
the Open call.
Each service Open call takes at least one parameter. This parameter is a point-
er to a common argument structure called NTARGS. The specification of this
structure is as follows:
6-2
Service Calling Conventions
Note that this structure is a simplified version of that provided by the configura-
tion system. This structure also contains a callback function. The callback
function is a subset of that in the configuration system, and codes returned by
this callback are passed through the configuration callback to the application.
- int CallMode;
This parameter determines how the service is launched, either by IP ad-
dress or by interface index (1 to n).
Some services can be launched either on a specific interface (1 to n) or on
a specific IP address (which can also be the wildcard INADDR_ANY).
Generally, any service that accepts an IP address can also accept an inter-
face. The service will simply lookup the IP address for the specified inter-
face.
Other services can only be executed by interface and are independent of
IP address. These are said to be compatible with NT_MODE_IFIDX only.
The value of CallMode can be one of the following:
J NT_MODE_IFIDX – Call by specifying the interface index (1 to n)
J NT_MODE_IPADDR – Call by specifying IP address in network for-
mat
- int IfIdx;
This is the physical interface index (1 to n) on which the service is to be
executed. For example, when launching a DHCP server service, the
physical interface is that connected to the home network. For more gener-
ic services (like Telnet), the service can be launched by a pre–defined IP
address (or INADDR_ANY as a wildcard). When launching by IP address
only, this field is left NULL. When this field is used, CallMode should be set
to NT_MODE_IFIDX.
- IPN IPAddr;
This is the IP address (in network format) on which to initiate the service.
This IP address can specify the wildcard INADDR_ANY, in which case the
service will accept connections to any valid IP address on any device. Note
that some services (like DHCP sever) do not support being launched by IP
address. When this field is used, CallMode should be set to
NT_MODE_IPADDR.
- HANDLE hCallback;
This is the caller supplied handle that is passed back to the caller when the
status callback function is invoked (see below).
6-4
Telnet Server Service
6.2.1 Synopsis
The following structure defines the unique parameters of the Telnet service.
It is located in the file: src\nettools\inc\telnetif.h.
//
// Telnet Parameter Structure
//
typedef struct _ntparam_telnet {
int MaxCon; // Max number of telnet connections
int (*Callback)(PSA); // Connect function returns local pipe
} NTPARAM_TELNET;
This structure is used both when specifying the service to the configuration
system or when bypassing the configuration and invoking the service API di-
rectly.
The service can be specified as public in that it can connect using any IP ad-
dress, or an IP address of a specific interface. When accepting connections
to any system IP address, the service is specified with the “CALLBYIP” flag
and an IP address of INADDR_ANY. When a private connection is desired, the
service is specified by the physical interface on which connections are allowed
to occur. Since an IP address is required to initialize the service, the ”RESOL-
VEIP” flag should also be set in the latter case.
For example, the following code specifies that the telnet server should run us-
ing the IP address INADDR_ANY.
telnet_example()
{
CI_SERVICE_TELNET telnet;
The above code is all that is required when using the configuration system to
invoke this service.
In addition to the configuration option, this service can also be created and de-
stroyed directly through this NETTOOLS API. If an application wishes to by-
pass the configuration system and launch the service directly, these calls can
be used.
6-6
Telnet Server Service
Return Value Returns a handle to the new telnet server instance, or NULL if the service could
not be created. This handle is used with TelnetClose() to shutdown the server
when its no longer needed.
Description When a telnet session is established, a telnet child task is spawned which will
call the supplied callback function. This callback function should return a local
file descriptor of one end of a full duplex pipe. If the callback function returns
–1, the connection is aborted. When either the terminal or telnet connection
end of the pipe is broken, the other connection is closed and the session is en-
ded.
Description Destroys the instance of the telnet sever indicated by the supplied handle.
Once called, the server is shutdown and no more telnet sessions can be estab-
lished. Also, all spawned connections are immediately terminated.
6.3.1 Synopsis
When acting as a router, the TCP/IP stack may also need to maintain the net-
work configuration on one of its network devices. A DHCP server allows the
stack to maintain the IP address of multiple Ethernet client devices. When
combined with Network Address Translation (NAT), the DHCP server can be
used to establish client membership in a private virtual network.
6.3.2 Operation
The DHCP server can be optionally configured to allocate IP addresses out
of a pool that is specified by an IP base address and the number of addresses
in the pool. If no pool is specified, the server will use static client entries in the
configuration system to resolve client address requests.
The sever will respond to DHCP requests from a single Ethernet device. This
allows for isolation of clients for a given interface, and allows multiple instances
of the DHCP server to manage different IP address pools for different inter-
faces.
- PoolBase – The first IP address (in network format) of the address pool
6-8
DHCP Server Service
This structure is used both when specifying the service to the configuration
system or when bypassing the configuration and invoking the service API di-
rectly.
Return Value Returns a HANDLE to a DHCPS instance structure which is used in calls to
other DHCPS functions like DHCPSClose().
Description This function is called to initiate DHCPS control of an IP address pool on a giv-
en interface. The base address of the address pool does not have to be the
first IP address in the subnet.
Description This function is called to terminate DHCPS control of the previously supplied
interface. This call also destroys the supplied DHCP server instance handle
hDHCPS.
6-10
DHCP Client Support
6.4.1 Synopsis
At system startup the DHCP client will try and acquire an IP address from the
DHCP servers available on the network.
Note that the client will accept the first IP address offered and that the INIT-RE-
BOOT State (which requests a previously assigned IP address) is not currently
implemented.
6.4.2 Operation
The DHCP client is a special service in that it always executes immediately in
a system. If is usually after DHCP client obtains a public IP address that most
of the other services in the system can initialize.
The DHCP client code makes additional use of the service status report call-
back function than most of the other services. Recall from the beginning of this
section that the least significant byte of the report code is reserved for service
specific information.
The following report codes are returned in the LSB of the report code sent by
the DHCP service:
DHCPCODE_IPADD An IP client address had been added to
the system
DHCPCODE_IPREMOVE An IP client address has been removed
from the system
DHCPCODE_IPRENEW An IP client address has been renewed
Note that in each of the above cases, the DHCP portion of the system
information configuration (the first 256 entries of CFGTAG_SYSINFO) has
been erased and potentially reprogrammed. If an application needs to share
the DHCP portion of the system information configuration, these DHCP report
codes can be used to signal when to add additional application specific tags.
For more information on DHCP and the CFGTAG_SYSINFO tag, see
section 4.4.8.
Note: The DHCP client will never erase nor attempt to modify the value of the
DHCP tag, CFGITEM_DHCP_HOSTNAME. As an exception to the behavior
stated above, the system hostname is treated as read-only, and can only be
set by the application programmer.
This structure is used both when specifying the service to the configuration
system or when bypassing the configuration and invoking the service API di-
rectly.
For example, the following code specifies that the DHCP client should run on
the interface specified by the physical index dhcpIdx.
dhcp_client_example()
{
CI_SERVICE_DHCPC dhcpc;
The above code is all that is required when using the configuration system to
invoke this service.
6-12
DHCP Client Support
6.5.1 Synopsis
An HTTP (Hypertext Transfer Protocol) server allows a remote browser to view
content on the server file system. Files can be stored for viewing and forms can
also be stored to allow remote interaction with the system. Form POST func-
tions become calls to application defined C functions that allow the embedded
system to be remotely controlled via a HTTP browser.
6.5.2 Operation
The HTTP Server service provides a mechanism for serving HTTP content to
remote HTTP client applications. It uses the “embedded file system” contained
in the OS adaptation layer. These functions in the EFS programming API in-
clude a prefix of “efs_”. Modifying the EFS functions in the OS adaptation layer
allows the system programmer to support a variety of file storage options, in-
cluding memory, flash cards and hard drives.
For example, the following code specifies that the HTTP server should run us-
ing the IP address INADDR_ANY.
6-14
HTTP Server Support
http_example()
{
CI_SERVICE_HTTP http;
bzero( &http, sizeof(http) );
http.cisargs.IPAddr = INADDR_ANY;
http.cisargs.pCbSrv = &ServiceReport;
CfgAddEntry( hCfg, CFGTAG_SERVICE, CFGITEM_SERVICE_HTTP, 0,
sizeof(http), (UINT8 *)&http, 0 );
}
The above code is all that is required when using the configuration system to
invoke this service.
Return Value Returns a handle to the HTTP Server instance, or NULL if the HTTP Server
task could not be created. This handle is used with HTTPClose() to shutdown
the client when its no longer needed.
Description HTTPOpen() starts the HTTP server process. This process will create a con-
nection to the HTTP Port and listen. When a connection is made, another task
will be created to service the request.
Description Destroys the instance of the HTTP Server indicated by the supplied handle.
Once called, the Server is shutdown.
6.6.1 Synopsis
The DNS server service allows clients on a home network to resolve host
names and addresses for clients on both the home and public networks.
6.6.2 Operation
The TCP/IP stack contains a small DNS resolver which can resolve host-
names and addresses that are local to the system via the configuration, or
those outside the system by using an external DNS server.
The DNS server service described here allows the same internal DNS resolver
to be accessed by clients on a virtual (home) network. This allows clients on
a home network to lookup peers on the home network using the same DNS
server that is used for external lookups. Thus, DNS service for the home net-
work is transparent to these clients.
Since the DNS server service uses the same internal DNS resolver as the cli-
ent services discussed earlier, the server adds very little overhead to the sys-
tem.
For example, the following code specifies that the server should run using the
IP address INADDR_ANY.
6-16
DNS Server Service
dns_server_example()
{
CI_SERVICE_DNSSERVER dnss;
bzero( &dnss, sizeof(dnss) );
dnss.cisargs.IPAddr = INADDR_ANY;
dnss.cisargs.pCbSrv = &ServiceReport;
CfgAddEntry( hCfg, CFGTAG_SERVICE, CFGITEM_SERVICE_DNSSERVER, 0,
sizeof(dnss), (UINT8 *)&dnss, 0 );
}
The above code is all that is required when using the configuration system to
invoke this service.
Return Value Returns a handle to the new server instance, or NULL if the service could not
be created. This handle is used with DNSServerClose() to shutdown the serv-
er when its no longer needed.
Description Creates a DNS server task which can service external DNS requests using
UDP.
Description Destroys the instance of the DNS server indicated by the supplied handle.
Once called, the server is shutdown. It waits for all spawned sessions to com-
plete.
6.7.1 Synopsis
The NAT service allows for the establishment of a home virtual network that
is isolated from and protected from the external public network. It provides a
port based address translation function that allows all the clients on the home
network to share a single public IP address. Thus, multiple clients can share
the same ISP account.
6.7.2 Operation
The TCP/IP stack contains both a network address translation module as well
as an IP filtering model. When the translation service is enabled, any packet
received from a client on a virtual network that is destined for the external pub-
lic network is adjusted to use the stack’s public IP client address.
The NAT service is executed on the public interface – i.e., the interface which
is assigned valid public IP host address (used to carry traffic for the virtual cli-
ent addresses). There can only be one instance and Thus, only one public IP
address, but the service will can serve multiple the virtual (home) networks in
the system so long as they can be combined and still exclude the public IP. If
the combination of these networks results in an overlap with the public net-
work, the service fails.
6-18
Network Address Translation (NAT) Service
For more information on NAT operation, including how to program proxy filters,
see the Network Address Translation appendix at the end of this document.
This structure is used both when specifying the service to the configuration
system or when bypassing the configuration and invoking the service API di-
rectly.
For example, the following code specifies that the NAT service should run on
the interface specficied by the physical index natIdx. Here, we use the DHCP
client service to obtain our public IP address (the address assigned to natIdx),
so at this point we don’t know what our IP address is going to be. We thus set
the “RESOLVEIP” flag in the execution mode parameter. This informs the con-
figuration service manager not to invoke NAT until it has resolved an IP ad-
dress for the target interface. We also set the “RESTART” flag to tell the service
to restart NAT if we lose and then regain a public IP address. In this example,
we assume all networks in the 192.168.x.x/255.255.0.0 subnet are part of the
NAT group to be translated.
nat_service_example()
{
CI_SERVICE_NAT nat;
bzero( &nat, sizeof(nat) );
// Don’t start NAT until we resolve an IP address on its IF
nat.cisargs.Mode = CIS_FLG_IFIDXVALID |
CIS_FLG_RESOLVEIP | CIS_FLG_RESTARTIPTERM;
nat.cisargs.IfIdx = natIdx;
nat.cisargs.pCbSrv = &ServiceReport;
// Include all 192.168.x.x addresses in NAT group
nat.param.IPVirt = htonl(0xc0a80000);
nat.param.IPMask = htonl(0xffff0000);
CfgAddEntry( hCfg, CFGTAG_SERVICE, CFGITEM_SERVICE_NAT, 0,
sizeof(nat), (UINT8 *)&nat, 0 );
}
The above code is all that is required when using the configuration system to
invoke this service.
6-20
Network Address Translation (NAT) Service
In the source code to the network control functions there are several calls to
internal stack functions. This is similar to calling the kernel in other operating
environments. This section contains a partial list of internal stack functions
provided to aid in the comprehension of kernel oriented calls.
There are two points the reader should keep in mind while browsing this sec-
tion:
1) This section is required only for system programmers who need low level
access to the stack for configuration and monitoring. This API does not
apply to general sockets application programming.
2) In addition to the internal functions described here, there are scheduling
and configurations tools available that make any direct coding to these
functions unnecessary.
Topic Page
A.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A-2
A.2 Stack Executive (Exec) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A-5
A.3 Packet (Pkt) Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A-6
A.4 Packet Fragment (Frag) Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A-14
A.5 Link Layer Address (LLA) Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A-20
A.6 Link Layer Information (LLI) Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . A-22
A.7 Interface (IF) Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A-24
A.8 Ether Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A-28
A.9 Binding Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A-32
A.10 Timer Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A-34
A.11 Route Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A-36
A.12 Route Control Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A-46
A.13 Configuring the Stack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A-50
A.14 Network Address Translation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A-57
A.15 Obtaining Stack Statistics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A-59
A-1
Overview
A.1 Overview
The control API is the collection of functions supplied in the stack library. The
entire API is exposed, although the vast majority of functions and objects will
only be used internally to the stack.
It should be noted that no part of the stack is interrupt driven. Neither can any
stack function be called at interrupt time. All interrupt processing is performed
in the HAL or OS, and is thus externally-defined code. This allows the system
programmer to develop a HAL/OS architecture that is best suited for a given
operating environment, without affecting the operation of the stack.
The stack may or may not be pre-empted, depending on the operating environ-
ment in use. A non-preemptive architecture is possible since the stack code
does not uses polling loops nor make any blocking type calls, but preemption
is also supported.
The internal stack functions are not designed to be reentrant. This allows the
stack to operate freely without the concept of a “critical section”, which is imple-
mentation dependent. Thus access to stack functions must be strictly con-
trolled. The form of this control is dependant on the system environment, and
is embodied as two low level OS functions; llEnter() and llExit(). These func-
tions are called before and after a section of code where any stack functions
are called. For example:
llEnter();
StackFunction1();
StackFunction2();
llExit();
A-2
Overview
With a little care, use these functions should be of no concern. The following
are good general guidelines:
- Always call llEnter() before calling a stack function, and llExit() when done
calling stack functions.
- Try and keep all code that requires llEnter() and llExit() in a single module.
They are only required for system maintenance.
- Don’t call a normal user function (like a socket function) between an llEnt-
er() / llExit() pair.
A.1.3 Events
Communicating what action needs to be performed by the stack is done by
sending event messages to the stack. Event messages are tracked by a
scheduling task implemented in the HAL. This task then alerts the stack to new
pending events. There are currently two event types defined:
- LL_EVENT_TIMER – One half second has elapsed since the last TIMER
event.
The HAL scheduler uses the stack’s “Exec” API to communicate to the stack.
A.1.4 Objects
Many of the control API functions deal with object handles. These handles are
created by a variety of class functions contained in the stack. When using an
object handle, it is important to realize how the object handle will be treated
by the function being called.
Associated with every object is the concept of who owns it, who is using it, and
who will eventually free it. In general, when an application creates an object,
the app owns it, the app is the only one using it, and the app must eventually
free it. Unfortunately, the matter becomes somewhat confused when object
handles are shared between applications – especially when the scope of the
handle creator may be shorter than the handle itself.
A-4
Stack Executive (Exec)
A.2.1 Synopsis
At the heart of the stack is the Executive API (Exec). The Executive acts as a
message dispatcher for the internal stack components. This action is mostly
hidden from the application, but there are some public functions.
Description Prepares the stack for execution by initializing the individual components. Until
ExecOpen() is called, the system can not actually do any work, but after calling
this function, objects like routes and bindings can be created.
Description Completes stack execution. This function is called to perform final cleanup on
the system after all user objects (like devices and bindings) have been de-
stroyed.
Description Informs the stack that memory resources are getting dangerously low. As a re-
sult of this call, the stack will abandon certain operations that hold excessive
resources. (Pending ARP packets are thrown away, IP packet fragments
pending reassembly are abandoned, etc.)
A.3.1 Synopsis
In order to fit nicely into an object oriented environment, network packets are
abstracted into two data objects, packets and packet fragments.
The packet object (PKT) is comprised of information about the packet charac-
teristics, like the ingress and egress device, the route associated with the
packet, the size and state of various protocol headers, etc. The packet frag-
ment object (FRAG) abstracts the actual packet data and information about
data buffer containing the packet.
The figure below illustrates the relationship between packets, fragments, and
the various buffer pools from which fragment data buffers can be allocated.
This section deals with the packet object, and the following section describes
the frag object and buffer pools.
The packet object is the container used for all packet data. The entire Ethernet
packet (MAC header, IP header and Options, Transport header, and payload)
is contained in the packet object. As each successive network layer builds or
decodes that packet, the information contained in the packet object becomes
more and more specific. The packet object flags is the best place to start when
determining packet status.
// Packet Flags
#define FLG_PKT_LLC_VALID 0x0001 // LLC Packet Header is present
#define FLG_PKT_IP_VALID 0x0002 // IP Pkt Header is present
#define FLG_PKT_NET_VALID 0x0004 // Network/Transport Header present
#define FLG_PKT_MACBCAST 0x0008 // Pkt Received as a LL BCast
#define FLG_PKT_MACMCAST 0x0010 // Pkt Received as a LL MCast
When a particular layer header is marked as valid or “present”, it means that
the header is incorporated into the “valid” portion of the packet fragment (see
A-6
Packet (Pkt) Object
the section on the FRAG object). The size of the individual layers can be ob-
tained from the size properties SizeLLCHdr, SizeNetHdr, and SizeTPHdr.
When a packet is created with the generic interface (IF) API (discussed later),
these properties are initialized with the standard header sizes for their respec-
tive types. So even when the headers are not “valid”, an appropriate header
size can usually be found in the header size property. This allows higher level
protocols to leave sufficient room in the packet data area to place the lower
level headers. In the event that a header is larger than the default size, the
packet data will have to be moved.
Building and decoding packet data is discussed further in the following Frag-
ment object section.
Create/Destroy Functions:
PktNew() Create New Packet Handle
PktFree() Destroy Packet Handle
Description This function is called to create a new packet handle. When first created, the
packet is entirely uninitialized.
Description This function is called to destroy a packet. When called, all objects associated
with the packet are dereferenced or destroyed.
Description This function is called to get the ethertype for the packet. The ethertype is a
two byte value that is contained in the Ethernet header along with the destina-
tion and source MAC addresses. For a packet being transmitted, this type is
used to construct the Ethernet header. For packets that have been received,
this value contains the ethertype found in the ingress header.
A-8
Packet (Pkt) Object
A-10
Packet (Pkt) Object
Description This function is called to attach a packet fragment (FRAG) handle to a packet.
The FRAG is the object which abstracts the physical memory buffer containing
the packet data. For more information, see the synopsis of this section and that
of the following section on the FRAG object.
Description This function is called to set the ingress or receive interface handle for the
packet. This function is typically called by the Ether object to mark which Ether-
net device originally received the packet. For packets that are generated local-
ly, this value is left NULL.
Description This function is called to set the egress or transmit interface handle for the
packet. In order for a packet to be sent via Ethernet, both the transmit interface
and the destination link-layer address (LLA) must be known. As an alternative,
the link-level info (LLI) module can derive these values from a route handle.
Description This function is called to set a link-level destination address for the packet. The
link-level address is abstracted into an object of type LLA, which is discussed
later in this document. To send a packet to an Ethernet device, both the des-
tination LLA and transmission interface handle must be set.
A-12
Packet (Pkt) Object
A.4.1 Synopsis
A Fragment object is a container for packet data. The concept behind the frag
is that a packet data buffer can be represented by the following properties:
- The size (in bytes) of the data which is currently valid in the buffer
- The offset from the start of the buffer to the current valid data
- An “invisible” amount of padding at the end of the buffer (only used when
buffer is allocated)
When a packet buffer is properly created, sufficient room is left at the head of
the buffer to insert network protocol headers. In most cases, only the minimum
header size will be allocated. Applications building packets that will use things
like IP options, must specify the size of the options in advance. When the buffer
is allocated, the offset parameter contains the cumulative size of all the re-
served space. The data payload is copied to this offset.
As network layers are added on the packet, the offset is decreased according
to the size requirements of the packet. A protocol can check to see if its header
has already been incorporated into the packet by checking the packet status
flags (as discussed in the previous section). IP is intended to deviate from strict
layering restrictions such that any code can build any portion of the packet
header it wishes.
The figure below illustrates this concept. The five parameters illustrated (buffer
pointer, buffer size, offset, valid size, and pad) along with the buffer pool indica-
tor make up a FRAG object.
A-14
Packet Fragment (Frag) Object
Unused
Offset Buffer
Space
Length
Free
Valid Valid
Buffers Data Size
Unused
Space Pad
Static – Packet fragment (FRAG) objects are owned and destroyed by a single
entity. Passing a packet handle to a function is considered transfer of owner-
ship.
Description This function is called to create a Frag object and allocate a Frag memory buff-
er. The argument PoolID is used to indicate the source of the buffer. The pool
id can be set to one of the following:
The BufferLen parameter is the total size of the buffer. PadLen is invisible
space added to the end of the buffer that is used when the buffer is allocated.
The pad value is then discarded.
The parameters ValidLen and DataOffset indicate the portion of the buffer that
has valid data. Obviously a newly allocated buffer can not have valid data, but
these values can be specified if the valid region of the packet is known in ad-
vance (i.e.: to set the amount of reserved space at the head of the buffer).
Description This function is called to create a Frag object to wrap an existing buffer. The
argument PoolID is used to indicate the original source of the buffer.
The BufferLen parameter is the total size of the buffer. The parameters Valid-
Len and DataOffset indicate the portion of the buffer that has valid data.
A-16
Packet Fragment (Frag) Object
Description This function is called to create a Frag object by copying an existing Frag ob-
ject. The buffer pool id of the source Frag is not used to allocate the buffer for
the new Frag. The source of the new buffer is always
FRAG_POOL_MEMORY.
Description Called to free a Frag object. The buffer associated with the Frag is also freed.
If one or more Frag objects are chained via the FragSetNext() function, they
are also freed.
Description Called to get auxiliary data associated with the Frag. This is used by TCP and
UDP to track buffer data and should not be used for other purposes.
Description Called to get auxiliary data associated with the Frag. This is used by TCP and
UDP to track buffer data and should not be used for other purposes.
Description Called to get information about the buffer associated with the Frag. The func-
tion always returns a pointer to the buffer. The remaining parameters are re-
turned to the supplied pointers when supplied. See the synopsis section for
more detail.
Description Called to get a handle to the next Frag object in a chain of Frag objects. Frag
objects are kept in chains in several areas of the stack including IP reassembly,
TCP reassembly, and UDP/RAW socket buffering.
Description Called to get a handle to the previous Frag object in a chain of Frag objects.
Frag objects are kept in chains in several areas of the stack including IP reas-
sembly, TCP reassembly, and UDP/RAW socket buffering.
Description Called to set auxiliary data associated with the Frag. This is used by TCP and
UDP to track buffer data and should not be used for other purposes.
A-18
Packet Fragment (Frag) Object
Description Called to set auxiliary data associated with the Frag. This is used by TCP and
UDP to track buffer data and should not be used for other purposes.
Description Called to set update the valid size and data offset properties of the data buffer
associated with a Frag. See the synopsis section for more information.
Description Called to set a handle to the next Frag object in a chain of Frag objects. Frag
objects are kept in chains in several areas of the stack including IP reassembly,
TCP reassembly, and UDP/RAW socket buffering. When the Frag at the head
of a chain is freed, all Frag objects in the chain are freed.
Description Called to set a handle to the previous Frag object in a chain of Frag objects.
Frag objects are kept in chains in several areas of the stack including IP reas-
sembly, TCP reassembly, and UDP/RAW socket buffering. When the Frag at
the head of a chain is freed, all Frag objects in the chain are freed.
A.5.1 Synopsis
In order to make full use of the stack objects described in this section, it is nec-
essary to understand some of the stack’s basic building block components.
One such component is the Link Layer Address Object, or LLA for short.
In essence, and LLA is an abstracted MAC address. It is used in places where
it is more convenient to treat such addresses generically instead of as fixed
length byte arrays.
A-20
Link Layer Address (LLA) Object
Syntax void LLASet( HANDLE hLLA, uint Type, uint Size, UINT8 *pData );
Description This function is called to set the properties of an LLA object. The object type
is the type of address the data represents. Valid values for the Type argument
are:
TYPE_LLA_UNICAST Object is a unicast MAC address
TYPE_LLA_BROADCAST Object is a broadcast MAC address
TYPE_LLA_MULTICAST Object is a multicast MAC address
The Size parameter is the length of the MAC address data (usually 6), and the
address data is pointed to by pData.
Description This function is called to get the LLA address data from the LLA object. The
number of bytes to copy is supplied in Size. The exact size of the address data
can be found by calling LLAGetLength().
Description This function returns the MAC address type represented by the LLA object.
The return value will be one of the following:
TYPE_LLA_UNICAST Object is a unicast MAC address
TYPE_LLA_BROADCAST Object is a broadcast MAC address
TYPE_LLA_MULTICAST Object is a multicast MAC address
LLAGetLength Get the Length of the LLA Object’s MAC Address Data
Description This function is returns the byte length of the MAC address data contained in
the object. For LLA objects representing Ethernet MAC addresses, this length
will be 6.
A.6.1 Synopsis
In order to make full use of the stack objects described in this section, it is nec-
essary to understand some of the stack’s basic building block components.
One such component is the Link Layer Information Object, or LLI for short.
In essence a LLI object is an ARP table entry. This implementation of the IP
stack combines the traditional route table and ARP table into a single table with
a single API. Routes that need use the ARP function include an ARP status
object, called LLI. In fact, the only reason a programmer need know about the
LLI object is to inspect the ARP status of the route table.
A-22
Link Layer Information (LLI) Object
This function also updates the route in the LLI (ARP) expiration list. It allows
an application to change the state of the ARP entry even if the stack has al-
ready created the route. It should be used when it is unclear if the route (really
ARP table entry) already exists or not.
Note that this function returns a referenced route handle. This handle must be
dereferenced using the RtDeRef() function when it is no longer required. Since
the route is treated as a standard ARP entry (with a standard expiration time
as supplied in the configuration structure), the route can be dereferenced im-
mediately.
A.7.1 Synopsis
The Interface (or IF) object is an abstraction of any physical interface in the
system capable of transmitting and receiving packet (PKT) objects. In the cur-
rent software, an interface object can represent either a PPP based device or
and Ethernet (Ether) based device. In actuality, there is no interface “object”,
but rather PPP device objects and Ether device objects can both be treated
as IF type objects for a small collection of functions. This section documents
these API functions.
The IF object API covers three general areas. First, is provides a couple of ge-
neric functions to obtain information about a device, like its type, MTU, etc. In
addition, the API is also charged with tracking physical device indices for de-
vice handles, and mapping from one to the other. This is useful for the applica-
tion programming environment and configuration system, which deals in de-
vice indices instead of device handles. The last function of the IF API is to pro-
vide a generic way of creating packets for the system, keeping track of all de-
vice’s header and padding requirements.
A-24
Interface (IF) Object
Description This function is called from ExecOpen(), before any physical devices are ini-
tialized. It will prepare the IF system to correctly process IFIndexNew() com-
mands which are called when Ether and PPP devices are created.
Description This function is called from PPP and Ether when new physical device handles
are created. IF allocates and returns a physical index for the supplied device
handle. If a specific index is required, it is passed in the Index parameter, else
Index is set to NULL.
Description This function is called from PPP and Ether when physical device handles are
destroyed. IF frees the supplied physical index, and can reallocate it in future
calls to IFIndexNew(). The index should not be used once freed.
Description This function returns the highest device index that is currently in use in the sys-
tem. When there are no “holes” in the index map, this value is also the number
of devices currently active.
A-26
Interface (IF) Object
Description This function is probably the most useful of the IF functions. It is called to create
a packet object to send packets out of the stack. It uses information collected
from the physical devices to create a packet that can be transmitted on any of
the physical devices in the system. It does this by applying worst case header
and padding sizes. A packet Frag object is also created and attached to the
packet.
The value of SizePayload is the size of the packet without the layer 2 header.
The value of SizeNet and SizeTP is the size of the network header and trans-
port to be associated with the packet (see the section of the Packet object for
more information). These latter two parameters are informational only, and
can be NULL. They don’t affect the size of the buffer (they are included in the
SizePayload parameter).
A.8.1 Synopsis
The Ether object is really just the “generic” portion of the packet driver. It knows
how to process an Ethernet MAC header, and handles incoming and outgoing
packets. It interfaces directly to the HAL packet driver. For each Ethernet
based packet device in the system, an Ether object is created to represent this
device to the stack.
Create/Destroy Functions:
EtherNew() Create New Ether Object
EtherFree() Destroy Ether Object
EtherConfig() Configure Ether Object Header Parameters
Addressing Functions:
EtherGetLLADirect() Get the directed Link Level Address of the
Ether Object
EtherGetLLABCast() Get the broadcast Link Level Address of the
Ether Object
EtherAddMCast() Add Multicast Ethernet Address
EtherDelMCast() Delete Multicast Ethernet Address
EtherClearMCast() Clear All Multicast Ethernet Addresses
Filtering Functions:
EtherSetPktFilter() Set Receive Packet Filter Value
EtherGetPktFilter() Get Current Receive Packet Filter Value
A-28
Ether Object
Return Value Returns a handle to the Ether object, or NULL on a memory allocation error.
Description Installs a new Ether object in the system. This call should be made for every
ethernet device installed. Once called, the stack will make calls to the HAL
packet driver interface to get more information about the device. The argument
is the physical device id used by the HAL to identify the device.
Description Destroys the indicated Ether object, and frees its associated memory. This
function should be called to remove devices after the stack has shut down.
Calling this function will not result in any calls to the HAL.
Syntax void EtherConfig( HANDLE hEther, uint PhysMTU, uint EthHdrSize, uint
OffDstMac, uint OffSrcMac, uint OffEthType, uint PacketPad );
Description Describes to the Ether object how the Ethernet header is constructed on this
device. Although the MAC address is assumed to be 6 bytes long, various de-
vices have a small variety of packet variances. The Ether device object must
know this information to both process and construct packets in buffers that are
native to the physical device.
EtherGetLLADirect Get the directed Link Level Address of the Ether Object
Description Returns an LLA object handle containing the Ethernet MAC address of the
physical device represented by the indicated Ether object. The MAC address
is obtained from the physical interface when the Ether object is first created.
EtherGetLLABCast Get the broadcast Link Level Address of the Ether Object
Description Returns an LLA object handle containing the Ethernet broadcast address of
the physical device represented by the indicated Ether object. This is normally
a string of 6 (0xFF)s.
Description Called to add an Ethernet multicast address to the list of addresses to be re-
ceived by the Ethernet hardware when the Rx filter is set to
ETH_PKTFLT_MULTICAST. The multicast address is specified as an LLA ob-
ject. The multicast address list can also be manipulated in its raw form at the
llPacket layer (see section D.3).
Description Called to remove an Ethernet multicast address to the list of multicast address-
es previously added via a call to EtherAddMCast(). The multicast address to
remove is specified as an LLA object. The multicast address list can also be
manipulated in its raw form at the llPacket layer (see section D.3).
A-30
Ether Object
A.9.1 Synopsis
In order for a device object to live on the network, it must have an IP address
and knowledge of its IP subnet. The process of assigning an IP address and
subnet to a device is to create a binding to the device with the desired IP ad-
dressing.
Description Binds the indicated IP address and mask to the supplied Ether device. The
handle to the Ether device object is specified as hIF – or an handle to an inter-
face, since the interface may or may not be an Ethernet device (but always is
in this version).
The IP address and mask arguments are given the type IPN which is an un-
signed 32 bit value. “IPN” stands for “IP Network format”, meaning that the IP
data must be supplied in network format. If unsure of the network format for
your hardware, use the htonl() macro function on the ”native” format (where
1.2.3.4 == 0x01020304 ).
Description Destroys the indicated Bind object, and frees its associated memory. This
function removes IP address and subnet association in the system route table.
It has no effect on the Ether object involved in the binding.
A-32
Binding Object
Description Returns a handle to the first binding installed in the system (or NULL if not bind-
ings exist).
Description Returns a handle to the binding in the installed binding list that follows the indi-
cated binding (or NULL if no more bindings exist). Note that bindings are not
internally kept in chronological order as to how they were installed.
BindGetIF Get the Ether Object that is Bound by this Binding Object
Description Returns a handle to the Ether object that is bound by this binding object. Recall
a binding is nothing more than an assignment of an Ether object to an IP ad-
dress/network.
Syntax void BindGetIP( HANDLE hBind, IPN *pIPHost, IPN *pIPNet, IPN *pIPMask
);
Description Returns the IP addresses and mask as requested by the calling arguments.
Any of the pointer arguments can be NULL if the information is not required.
A.10.1 Synopsis
The timer object is used to time events in kernel layer by installing a kernel call-
back function which is called at set intervals. The resolution of the timer is 0.5
seconds, and the callback is not deterministic. The most common use of the
timer callback is to implement timeout conditions that are usually measured
in seconds.
Description This function creates a new timer instance, with a timeout period in half second
units, specified by HSCount. When the timeout period has elapsed, the call-
back function pointed to by pHandler is called. The parameter to the callback
is a single uint, and the value passed to the callback is that passed in the pa-
rameter Msg.
The timer will continue to call the callback function until the timer handle is de-
stroyed via TimerFree().
Description Destroys the indicated timer object, and frees its associated memory. Once
called, the timer will no longer execute the callback function supplied to Timer-
New().
A-34
Timer Object
Description Called by the stack scheduler to notify the stack that a half second has elapsed
since the last call.
A.11.1 Synopsis
The route manager maintains IP routing information. It is called by various rou-
tines to get and set route information. A route object is a “destination” on the
network. Locally, it consists of an egress interface and a next hop IP address.
This section describes a subset of the route object. Flags, features, and API
calls have been omitted in an attempt to make this section a little less imposing.
Also, documenting the entire API would require to documentation of other
stack objects that are not covered in this document.
A-36
Route Object
When set, indicates that the route is to an invalid address. All packets des-
tined for this address are discarded with an error indication.
When set, indicates that the route has been modified as a result of an
ICMP redirect message. This can occur only to GATEWAY routes, and
only if ICMP modifications are enabled in the stack configuration.
When set, indicates that the route has been created as a result of an ICMP
redirect message. ICMP can only create GATEWAY routes, and may do so
only if ICMP modifications are enabled in the stack configuration.
This flag indicates that the router is a proxy publisher of another entity’s
MAC address. When set, the ARP protocol will respond to ARP requests
for the route’s IP address with the supplied static MAC address when the
host is on the same IF device as the incoming ARP request. This allows
support of hosts that do not implement ARP but are on the same physical
Ethernet network (as if this is going to happen). PROXYPUB entries are
always created with an LLA (link-layer address), and contain a static LLI
(link-layer info, i.e., ARP entry). (Note: PROXY and PROXYPUB have
nothing in common other than the word PROXY in their name.)
Note: This flag will be very rarely specified (if at all).
This flag indicates that the router is acting as a proxy for this host or net-
work route. When set, the ARP protocol will respond to ARP requests for
the associated IP host or network when the network appears on a IF de-
vice which is different from that of the incoming ARP request. The MAC
address supplied in the reply is the MAC of the IF device on which the ARP
request was received. A PROXY entry has no LLI (link-layer info, i.e., ARP
entry). This technique is used to “trick” clients into sending packets to the
router when subnets are split across physical devices on a router. (Note:
PROXY and PROXYPUB have nothing in common other than the word
PROXY in their name.)
Note: This flag will be very rarely specified, and is only useful when the
stack is acting as a router. One potential use applies when the stack is act-
ing as a PPP server and a PPP client is made part of the same IP subnet as
an Ethernet based interface. Here, the stack acts as the PPP client’s proxy
A-38
Route Object
Without writing another chapter on the theory of routing, here are some gener-
al guidelines to use when creating new routes. Use the definitions listed above
with the following legal flag combinations:
- Setting FLG_RTE_BLACKHOLE
- Setting FLG_RTE_REJECT
- Setting FLG_RTE_CLONING
- Setting FLG_RTE_HOST
- Setting FLG_RTE_GATEWAY
- Setting FLG_RTE_IFLOCAL
FLG_RTE_HOST – must be ON
FLG_RTE_CLONING – must be OFF
FLG_RTE_GATEWAY – must be OFF
- Setting FLG_RTE_PROXYPUB
FLG_RTE_HOST – must be ON
FLG_RTE_CLONING – must be OFF
FLG_RTE_GATEWAY – must be OFF
- Setting FLG_RTE_PROXY
Description Called to add one to the reference count of a route. An application that keeps
a route it did not create itself should reference the route before it uses it, and
dereference it when it is through.
Description Called to remove one from the reference count of a route. An application deref-
erences a route when it is through with it. This is the same (to the application)
as destroying the route. The route is actually destroyed when its reference
count reaches zero.
Syntax HANDLE RtCreate( uint CallFlags, uint RtFlags, IPN IPAddr, IPN IPMask,
HANDLE hIF, IPN IPGateway, HANDLE hLLA );
A-40
Route Object
Description Called to create a new host or network route and add it to the route table. Exist-
ing routes can not be modified via this call.
Some flag combinations make no sense, and the following are strictly en-
forced:
Description This call searches the route table for a route that matches the supplied IP ad-
dress. The search always returns the “best” match for a route. The best match
is a match with the most bits in the subnet mask. Thus, a host match takes
priority over a network match.
When there is more than one route with the same subnet mask, the following
matching guidelines are used (listed from BEST to WORST):
- Route has a local destination (occurs with host addresses only).
Sometimes a search is desired where particular matches are desired. The fol-
lowing flags can be combined with the value of CallFlags to change the behav-
ior of the seach:
FLG_RTF_CLONE Clone a network route to a host route if host not
found
FLG_RTF_HOST Find only non-gateway host routes
A-42
Route Object
Description This function returns the specified route’s IP address in network format.
Description This function returns the specified route’s IP subnet mask in network format.
Description This function returns the Gateway IP address for the specified route (assuming
the FLG_RTF_GATEWAY bit is set in the route flags).
Description This function returns an Ether device handle to the egress (target) device of
the route. Even local IP addresses have target devices (the device they are
bound to).
Description This function returns the MTU (not including layer 2 header) of a packet sent
via the supplied route.
A-44
Route Object
Return Value HANDLE to first route in system route table or NULL if no routes.
Description This function initiates a walk of the route table. It returns the first route in the
table. The walk must be terminated with RtWalkEnd() for the system to behave
properly.
Return Value HANDLE to next route in system route table or NULL if no routes.
Description This function gets the next route (based off the previous route supplied) in a
walk of the route table. The walk must be terminated with RtWalkEnd() for the
system to behave properly.
Description This function completes the walk of the route table. The last route (if any) ob-
tained from RtWalkBegin() or RtWalkNext() is specified in the calling argu-
ment. Otherwise, NULL is used.
A-46
Route Control Object
MSG_RTC_NEW New Route has been Entered into the Route Table
Parameter(s) Param1 = Route IP
Param2 = Route IP Mask (all ones for host route)
Description Called when a new route is created and entered into the route table. Routes
can be created by applications, when new bindings are created, by ICMP redi-
rects, or when local host routes are cloned from local subnet routes.
A-48
Route Control Object
A.13.1 Synopsis
The stack has multiple configuration options that can be changed by the sys-
tem programmer. This is possible by altering the default values in a stack con-
figuration structure before the stack is initialized.
The stack internal configuration structure is _ipcfg. Any element in this struc-
ture may be modified before the initial system call to ExecOpen(). This struc-
ture should not be modified after this initial call.
A-50
Configuring the Stack
Description When set, causes ICMP to automatically create a route to perform redirects
on an IP host to the gateway supplied in the redirect message. If set to false
(0), the system programmer can take whatever action they feel necessary as
the ICMP redirect will also generate a route control message.
Default Value 64
Description This is the TTL value ICMP will use in messages it generates as a result of rout-
ing IP packets. Legal values are in the range of (1–255).
Description This is the TTL value ICMP will use in echo reply messages it generates in re-
sponse to receiving echo requests. Legal values are in the range of (1–255).
Default Value 1
Description This is the initial value that is placed in the IP Id field for IP packets generated
by the system. Legal values are in the range of (1–65535).
Description When set to true (1), this allows the stack to forward packets it receives for oth-
er IP address to their next hop destination. I.E.: it allows the stack to act as a
router.
Default Value 10
Description This is the maximum time that the stack will hold IP packet fragments while at-
tempting to assemble a complete packet. If the time expires before all the frag-
ments arrive, the packet is discarded.
A-52
Configuring the Stack
Description If sending router advertisements (see above), this is the route lifetime that will
be sent in the ICMP message.
Default Value 0
Description If sending router advertisements (see above), this is the route preference level
that will be sent in the ICMP message. This value is signed.
Default Value 20
Description In order to stop an application from sending endless packets to a route that is
not responding to ARP, the route is brought “down” for a period of time so that
the application will receive an error when IP attempts to send. After the desig-
nated time, the route is brought back up and will attempt more ARP requests
if used again.
Description Routes should not be held indefinitely. Use of a route is also not sufficient to
keep the route alive. This value represents the time an ARP validated route
is held before it expires. If the route is revalidated via ARP during this period,
the period is extended for this interval from that point in time.
Description When a host route is first cloned from a network route, it is assigned this default
timeout. Once the route is validated via ARP, the timeout is extended (see
above).
Description When a route is created, it gets its MTU from the egress device. However, if
the route is local to the system, there is no egress device. In this case, a default
MTU is used.
Default Value 64
Description This is the default IP packet TTL value of packets sent via a socket. Note that
the application can override this value with the sockets API.
Default Value 0
Description This is the default IP packet TOS value of packets sent via a socket. Note that
the application can override this value with the sockets API.
Default Value 8
Description This is max number of connects a socket will pend waiting for a sockets ac-
cept() call from the application. Note: This value is also the upper bounds of
the ”max connection” argument supplied by an application via the sockets lis-
ten() function (calls with higher values are silently rounded down).
Default Value 80
Description This is max amount to time the sockets layer will wait on an actively connecting
socket. The default value of 80 is a few seconds longer than the TCP keep
time, so TCP will generate the official (more accurate) timeout error.
A-54
Configuring the Stack
Default Value 1
Description This is the size in bytes required to be present in a socket buffer to be regarded
as “able to read” by the system. (Affects how the “read fd set” behaves in a se-
lect() call.) Alter at you own risk.
Description This is the size of a Pipe send and receive buffer. This value is only examined
when pipes are created, so changing this value will not affect the buffering of
existing pipes.
Description This is the size in bytes required to be free in the Pipe buffer before it is re-
garded as “able to write” by the system. (Affects how the “write fd set” behaves
in a select() call.) It is usually about 25% to 50% of the send buffer size. This
value is only examined when pipes are created, so changing this value will not
affect the buffering of existing pipes.
Default Value 1
Description This is the size in bytes required to be present in the Pipe receive buffer to be
regarded as “able to read” by the system. (Affects how the “read fd set” be-
haves in a select() call.) Alter at you own risk. This value is only examined when
pipes are created, so changing this value will not affect the buffering of existing
pipes.
A-56
Network Address Translation
A.14.1 Synopsis
The stack includes a small network address translation (NAT) function which
can be used to setup virtual networks when the stack it acting as a router.
When enabled, NAT will translate routed packets sent from or to a targeted
virtual network.
A.14.2 Operation
NAT works by altering the TCP/UDP port numbers of a packet sent from a virtu-
al network, and then using an alternate IP on the physical network to transfer
the packet. For ICMP packets, the Id field of ICMP requests is used.
When configured, NAT will have a target virtual network that consists of a IP
base address and a subnet mask. It also has a physical IP address which is
used as a type of proxy for the translated packets.
- ICMP EHCO and TSTAMP packets sent from the virtual network
The translation entries are created dynamically, and have a lifetime based on
their protocol. ICMP and UDP translation entries have a fixed time limit based
off the last time they were accessed. TCP entry expiration is based on the state
of the TCP connection.
Note that some protocols (like FTP) communicate TCP/UDP port information
in the packet payload. These types of protocols will not function under NAT
without a custom proxy program to alter the packet payload. Individual proxies
are not provided.
Note that when using the NAT service feature in NETTOOLS or when using
the configuration system, this low-level configuration is not required.
Description This function configures NAT with a virtual network and a physical server. Note
that both the virtual and physical addresses must also be contain in the stack’s
route table. NAT should only be used when the stack is acting as a router, and
when there are more than one ethernet devices present.
A-58
Obtaining Stack Statistics
This section is required only for system programmers who need low level ac-
cess to the Network Address Translation (NAT) Layer. This API does not ap-
ply to sockets application programming.
This section describes functions that are callable from the kernel layer. Users
should familiarize themselves with the operation of the operation of llEnt-
er()/llExit() functions before attempting to use the APIs described in this sec-
tion.
NAT has a unique status in the stack software in that it can be an integral part
of programming at both the user and kernel levels, or can be entirely redundant
and even purged from the stack build.
This section describes the operation of the Network Address Translation soft-
ware included in the TCP/IP stack, how to configure it, how to install port map-
pings, and how to program proxy filter routines to support protocols like FTP.
Topic Page
B-1
NAT Operation
Internet
192.168.0.1
192.168.0.32 192.168.0.33
Home
Host 1 LAN Host 2
(H1) (H2)
192.168.0.x
B-2
NAT Operation
As packets traverse from the LAN to the WAN across the router, the source
IP address of the packet (a LAN address) is replaced with the public IP address
of the router. The result is that all packets sent to the WAN appear to have origi-
nated from the router with the public IP address obtained from the ISP.
As packets traverse from the WAN to the LAN across the router, the destination
IP address of the packet (the router’s WAN IP as obtained from the ISP) is re-
placed with the home LAN IP address of the physical client machine to which
the packet is ultimately destined.
Every time a LAN client sends a packet to the WAN, the local IP address, port/
id, and protocol is recorded for reverse mapping, as well as the destination IP
address and port for security. When a packet is received from the WAN, the
destination port/id is checked against the current database of NAT entries to
see if the packet’s destination address and port/id should be translated to a
LAN client.
For example, when accessing the Internet, all communications is normally ini-
tiated by the client. In this case, communications will be initiated by H1 or H2.
Assume that H1 attempts to establish an HTTP connection with the Internet
host (IH). It will send a connection request to the IP address assigned to IH,
and a TCP port value of 80, which is HTTP. The request will be from its own
IP address with an ephemeral port value that is picked from a pool (consider
it random for our purposes – say 1001). So the request will be addressed as
follows:
Packet 1
To From Protocol
When the router HR receives this packet, it searches for a NAT entry that
matches the From address of the packet. Since this is the first packet, assume
the table is empty. When no entry is found, (skipping proxies for now) the router
will create a new entry. It does this by recording information from packet 1, as
well as picking a new port value from its own pool that has been specifically
reserved for NAT (assume the range is 50000 to 55000, and that it chooses
50001). The new port is used as the packets source port. The NAT entry record
would look like the following:
The Local IP and Local Port values are those that are local to hosts on the
home LAN. The Foreign IP value is the foreign side of the connection as
viewed by hosts on the home LAN. The Mapped Port value is the source port
when the packet is sent from HR. The source IP address used in the packet
is that assigned to HR by the ISP. The IP protocol of the packet is recorded,
and when using TCP, the state of the TCP connection is tracked to establish
a reasonable timeout value. The SYNSENT value indicates that a connection
request was sent. Before a full connection is established, the timeout is set fair-
ly low – say 1 minute.
As the packet is transmitted from HR to the ISP, it would look like the following:
Packet 1 (modified)
To From Protocol
When IH receives the packet, it believes that the connection request came
from HR. It thus sends the response packet to HR. The packet would be ad-
dressed as follows:
To From Protocol
B-4
NAT Operation
When HR receives the packet, it checks the NAT entry table for an entry with
a Mapped Port value equal to the destination port of the packet (in this case
50001). The value of Protocol and the source IP address/port values must also
match the Protocol, Foreign IP, and Foreign Port fields of the NAT entry. This
helps ensure that the reply is from the desired server.
Here, HR finds the entry and proceeds to modify the packet. It replaces the
destination address/port with the “local” address/port stored in the entry. It also
resets the timeout of the entry. After modification, the packet would be ad-
dressed as follows:
Packet 2 (modified)
To From Protocol
Once a connection is established, the timeout of the entry is set quite high (say
five hours). This is because TCP connections can stay connected for an indefi-
nite period of time without exchanging any packets.
If H2 attempts to connect to the same host simultaneously, there is no problem
sharing the public IP address assigned to HR. For example, H2 sends a con-
nection request to IH addressed as follows:
Packet 3
To From Protocol
HR would not find a NAT entry for 192.168.0.33:1024, so it would create one:
The modified packet and its reply would proceed similar to packets 1 and 2.
Packets that pass from the LAN to the WAN are searched based on Local IP
combined with Local Port. Packets that pass from the WAN to the LAN are
searched based on Mapped Port. Note that for all entries on the NAT entry
table, these values are unique.
So far we’ve only examined communications that has been initiated by hosts
on the home LAN. Note that any unsolicited packets sent to HR from the WAN
will not match any entry in the NAT table. These packets will be forwarded to
the internal protocol stacks on HR, where they may or may not be used.
Now assume that a host on the home LAN (say H2) wishes to place an HTTP
server on the Internet. With what we’ve examined so far, it would be impossible
to contact such a sever from the WAN since no unsolicited traffic (like an HTTP
connect request) can pass from the WAN to the LAN. However, H2 can acquire
a portion of HR’s WAN presence by mapping one of the well-known port values
on the public WAN IP address to itself through port mapping.
In port mapping, a NAT entry is created to send all traffic destined for a specific
port on the public IP address to an alternate destination. For well known ports
like HTTP, the port value is not usually altered. Only the destination IP address
changes. In this case, port 80 (HTTP) on the public IP address is mapped to
port 80 of the LAN host H2. The entry would look as follows:
When a connection request arrives from a remote host for the public IP ad-
dress assigned to HR, as with the basic NAT discussion of the previous sec-
tion, the destination port of the packet is matched with the Mapped Port value
of the NAT entry. Normally, the Foreign IP and Port of the NAT entry must also
match for source IP and port of the packet, but here the values are ”wild”. This
is because when the entry is created, the foreign peer is unknown. Since, ev-
ery TCP connection state must be tracked in its own NAT entry, a second entry
must be spawned. Any match of a wild NAT entry will spawn a fully qualified
entry. For example, assume the following packet arrives:
Packet 4
To From Protocol
B-6
NAT Operation
Packet 4 (modified)
To From Protocol
Note that the wildcard entry’s timeout is STATIC. This means that the entry will
never expire. Note that when the new entry is spawned, it acquires a timeout.
One last point to note here is that the installation of a port map for port 80 does
not prohibit HR from running its own HTTP server hosted on its private LAN
IP address (192.168.0.1). This means that local hosts could get to a local
HTTP server on 192.168.0.1, and the public HTTP server on 192.168.0.32, but
outside hosts connecting to 128.1.2.12 could only get to the public HTTP serv-
er on 192.168.0.32.
For example, assume the same topology as before, with the HR running both
and HTTP and Telnet servers, H1 running an HTTP server, and H2 running a
Telnet server. This is illustrated below:
Internet
192.168.0.1
192.168.0.32 192.168.0.33
Home
Host 1 LAN Host 2
(H1) (H2)
192.168.0.x
HTTP Telnet
server server
In order to make the servers on H1 and H2 public, the following NAT port map-
ping entries are installed on HR:
With these mappings, the externally available HTTP server and Telnet server
publicly accessible on the WAN IP (128.1.2.12) are actually executing on H1
and H2. However HR can have its own HTTP and Telnet servers and make
them available to hosts on the LAN.
Also note that regardless of how hosts on the LAN access HR (either through
192.168.0.1 or 128.1.2.12), their packets are not processed via NAT. Thus
they are never altered. The following are some connection examples:
B-8
NAT Operation
Packet 1
To From Protocol
HR would not find a NAT entry for 192.168.0.33:1137, so it would create one:
The modified packet and its reply would proceed as discussed in section B.1.2.
The modified packet would be:
Packet 1 (modified)
To From Protocol
Now assume that eventually the FTP server on IH attempts to establish a data
connection back to what it thinks is the FTP client’s ephemeral port (50003).
Note classic FTP uses port 20 to establish data connections. Its connection
request packet would be:
Since there is no NAT entry record that will match the address values in this
packet (specifically port 20 in the From field), this packet will not be forwarded
to the FTP client. In order for this to work, there must be a port mapping
installed for 64.1.1.100 that has a wildcard port value (we can’t be sure that
the connection request will arrive on port 20). The NAT entry table would be
as follows:
With such a mapping, if a connection request from port 20 arrived, the wild card
entry would be matched, and another entry spawned for port 20 on IH. The
table would look as follows:
The second issue in dealing with an FTP client is that the client can change
the port on which the FTP server attempts connection. This is done via a PORT
command sent from the client to the server. The PORT command contains in-
formation about the client in the packet payload.
For example, assume the FTP client (H1) creates a new socket for the data
connection, and its ephemeral port value is 1142. H1 would then send an FTP
PORT command on the control connection to the server. The server would
then attempt a connection. The following is an approximation of the operation
(it is not the exact syntax of the port command).
B-10
NAT Operation
As a reminder, the FTP server would normally see the packet as:
This packet creates a couple problems. First, the IP address in the PORT com-
mand does not match the IP address of the FTP server’s connected peer. This
would produce an error. Plus, the IP address in the PORT command is not a
real Internet address. Lastly, even if the FTP server tried to connect to
128.1.2.12:1142, there is no mapping for the port number in the NAT entry
table.
The correct procedure for modifying this packet is to solve all the above prob-
lems. First, a new NAT entry is created for 192.168.0.32:1142. The foreign IP
address is left as a wildcard since as before, we don’t know what port the FTP
server will use. The NAT entry table would then look as follows:
In recap, note that we have the original NAT entry for the FTP control connec-
tion, and now two wildcard entries for possible FTP data connection requests.
The final step of the modification is to alter the payload of the packet so that
the information in the PORT command matches the WAN IP address of HR
(128.1.1.21) and the Mapped Port of the new NAT entry (50004). The correctly
modified packet would be:
It is also possible for a client to request the FTP server to create a new port
(the PASV command), but that does not create any issues for FTP clients on
the LAN. If the FTP server were on the LAN and the client on the WAN, the
proxy process would key off the PASV command.
The bad news for the modification procedure discussed above is multifaceted:
1) The creation of the first data connection wildcard entry depends on the
knowledge by some entity that an FTP control connection has occurred,
and what IP/PORT the connection occurred on.
2) The creation of the second data connection wildcard entry depends on the
detection of a PORT command being passed from the client to the server.
3) The modification of the data payload of the packet containing the PORT
command requires that some entity is examining packet payloads.
The first three problems are very specific to FTP, and the fourth problem (TCP
sequence) is specific to any alteration of a TCP packet payload. The good
news is that the proxy filter support routines remove much of the burden of sup-
porting these transformations.
The solution is twofold. First, the stack allows a programmer to install “proxy
filter” callback functions on specified TCP/UDP port values, either outgoing
(for clients) or incoming (for servers). There are three callback functions in-
volved.
The first callback function “Enable” is called when a new connected is at-
tempted, or when the NAT entry expires. This function allows the programmer
to establish the basic connection state for the protocol in question. In the case
of the FTP client example, the first wildcard data connection mapping would
be installed here. Note that this function can also be used to filter connection
requests. If this function returns zero, the connection request is ignored.
The second and third callback functions are mirrors of the other. They are the
“Tx” and “Rx” functions. The “Tx” callback is called with the IP header of every
packet that passes from the LAN to the WAN for the connection in question,
while the “Rx” callback is called with the IP header of every packet that passes
from the WAN to the LAN. While in these functions, the programmer can call
a “packet modify” function to modify the payload of the packet. The system will
automatically track and perform modifications to the TCP sequence values
(when using TCP).
B-12
NAT Operation
In the case of the FTP client, there would be no “Rx” callback since only pack-
ets from the client need be examined. The “Tx” callback would look for PORT
commands from the client, and when one was detected, it would install the sec-
ond wildcard port mapping as discussed in the previous section, and then
modify the packet payload so that the PORT command reflected the WAN IP
of HR, and the Mapped Port of the NAT entry.
From the discussion in this section, it would be easy to draw the conclusion
that developing proxy filter code would be horribly complicated. However, the
actual implementation is straightforward. The code to implement the filter dis-
cussed in section B.1.4.3 is shown below. The API for NAT and Proxy is dis-
cussed in the following sections.
//
// GetVal – Convert ASCII decimal string to integer
//
static uint GetVal( UINT8 **pData )
{
uint v = 0;
while( **pData >= ’0’ && **pData <= ’9’ )
v = v*10 + (*(*pData)++ – ’0’);
(*pData)++;
return(v);
}
//
// FTPCProxyEnable – Proxy for FTP Clients behind firewall
//
// NOTE: Proxy callback function operate at the kernel level. They
// may not make calls to user–level functions.
//
int FTPCProxyEnable( NATINFO *pin, uint Enable )
{
HANDLE hNat;
NatFree( pNI–>pUserData );
}
return(1);
}
//
// FTPCProxyTx – Proxy for FTP Clients behind firewall
//
// NOTE: Proxy callback function operate at the kernel level. They
// may not make calls to user–level functions.
//
int FTPCProxyTx( NATINFO *pNI, IPHDR *pIpHdr )
{
UINT16 Length, Offset;
TCPHDR *pTcpHdr;
UINT8 *pData;
HANDLE hNAT;
NATINFO *pNINew;
char tmpstr[32];
UINT16 PortNew;
IPN IPNew;
pData = (UINT8*)pIpHdr;
// Get the offset into the TCP payload and payload size
Offset += pTcpHdr–>HdrLen >> 2;
Length –= pTcpHdr–>HdrLen >> 2;
//
// For clients, we only care about sending PORT commands
//
// For example, if our client IP is 192.138.139.32, and it reports
// port 384, the form of the command sent to the FTP server would
// be: ”PORT 192,138,139,32,1,128\r\n”
//
// We replace the Client IP with the router’s IP, and the client
// port with a NAT port which is mapped to the client port.
//
if( !strncmp( pData, ”PORT ”, 5 ) )
{
// Get the IP/Port declared by sender
// Form is ”i1,i2,i3,i4,p1,p2”
pData += 5;
IPNew = ((UINT32)GetVal(&pData)) << 24;
B-14
NAT Operation
return(1);
}
B-16
NAT Port Mapping
- IPN IPLocal;
This is the IP address (in network format) of the peer host on the local net-
work (LAN). It is the entity that has been assigned a virtual IP address be-
hind the firewall.
- UINT16 PortLocal;
This is the port in use by the peer host on the local network (LAN). It is the
entity that has been assigned a virtual IP address behind the firewall.
- IPN IPForeign;
This is the IP address (in network format) of the peer host on the public
network (WAN). It is the entity that is on the physical network outside the
firewall.
- UINT16 PortForeign;
This is the port in use by the peer host on the public network (WAN). It is the
entity that is on the physical network outside the firewall.
- UINT8 – Protocol;
- UINT16 PortMapped;
This is the port in use by the router on its public (WAN) IP address. It is this
port that maps back to a specific local IP/port on the LAN.
- HANDLE hProxyEntry;
- UINT32 Timeout;
This is time in seconds when the proxy entry will expire. The system
checks with a fairly large granularity, so the actual expiration can occur 10
to 20 seconds later. If this value is ZERO, the entry is static. A NAT entry
must be specified as STATIC when it is created. Setting Timeout to ZERO
will cause the entry to expire in 0 to 20 seconds.
- void * pUserData;
This field is reserved for use by proxy filter callback functions. It is not used
by the system software.
The NAT information structure of little importance when only port mapping is
required. Its real function is for use in NAT proxy filters.
Parameter(s) IPLocal IP address (in network format) of host on the LAN to map
PortLocal TCP/UDP port value of host on the LAN to map
IPForeign IP address of WAN peer (usually NULL/wild for port
mappings)
PortForeign TCP/UDP port of WAN peer (usually NULL/wild)
Protocol IP protocol (IPPROTO_TCP or IPPROTO_UDP)
PortMapped Port on router’s public WAN to map (usually a “well-known”
port)
Timeout Timeout of entry in seconds (NULL for STATIC)
Description This function creates a NAT entry with the parameters as specified.
The function returns a handle to the NAT entry created. This handle should be
freed with NatFree() when the mapping is no longer desired.
B-18
NAT Port Mapping
Description This function frees the supplied NAT entry. It is called to remove a STATIC NAT
entry that is no longer required.
Description This function returns a pointer to the NATINFO structure defined above in sec-
tion B.2.3. It is used mainly by NAT proxy filter callback functions.
B-20
NAT Proxy Filters
Return Value 1 to allow normal operation, or NULL to abort the supplied packet.
Description This function is called when a packet is crossing the router from the WAN to
the LAN (“Rx” callback) or from the LAN to the WAN (“Tx” callback). The NAT
entry containing a proxy which matched the packet is described by the sup-
plied NATINFO structure. This structure was described in section B.2.3 above.
The purpose of the callback is to examine the packet and take appropriate ac-
tion based on its contents. The packet payload can be easily modified by the
ProxyPacketMod() function described later in this section. The translation of
the IP address and port information can not be altered by this callback, howev-
er the callback can act as a packet filter and discard unwanted packets by re-
turning a value of NULL.
Syntax HANDLE ProxyNew( uint NatMode, UINT8 Protocol, UINT16 Port, IPN
IPTarget,
int (*pfnEnableCb)( NATINFO *, uint ),
int (*pfnTxCb)( NATINFO *, IPHDR * ),
int (*pfnRxCb)( NATINFO *, IPHDR * ) );
Description This function creates a “hook” that is examined whenever a new NAT entry is
created.
The Protocol and Port value is the IP protocol and ”well know” port of the proto-
col to proxy.
The three pointers to callback functions correspond to the proxy filter callback
functions described in the previous section.
The function returns a handle to the new proxy. Note that a proxy handle is not
the same as (or compatible with) a NAT entry handle.
Description This function frees the supplied Proxy Filter entry. It is called to remove an
entry that is no longer required.
B-22
NAT Proxy Filters
Parameter(s) Offset Offset in bytes from start of IP header to first modified byte
OldSize Size of old data at Offset
NewSize Size of new data to replace old data at Offset
pNewData Pointer to new data to replace old data
Return Value Pointer to new IP header of packet. This pointer is used for further modifica-
tions (if needed).
Description This function may only be called from a proxy filter callback function. Its pur-
pose is to modify the contents of a TCP or UDP packet, and perform the neces-
sary adjustments for packet size – including TCP sequencing adjustment.
The TCP/IP stack has built in support for both PPP severs and clients. The
PPP support API is designed to be shared by one or more physical devices.
One obvious device that can be hooked to PPP is a serial line, but the stack
also contains support for PPP over Ethernet (PPPoE). The low level PPP API
as well as Serial HDLC and PPPoE are all discussed in this appendix.
Topic Page
C-1
Low-Level PPP Support
Flag (7E) Addr (FF) Control (03) Protocol Payload CRC Flag (7E)
1 1 1 2 1500 2 1
In order to abstract out the actual processing of the PPP data from the process-
ing of the PPP frame encoding, the PPP support included in the TCP/IP stack
expects a smaller frame, consisting of the protocol and payload fields only.
This format is shown in Figure C–2.
Protocol Payload
The abstraction of PPP from the layer 2 encoding allows PPP to be carried by
a variety of physical devices. The programming interface to the PPP layer
called by the application is actually exposed by the layer 2 encoder. This layer
2 encoder is referred to as a serial interface (SI), but does not have to be a seri-
al port. This interoperation between PPP and the SI is shown in Figure C–3.
The functions shown in the dotted rectangle are those provided by the serial
interface software.
C-2
Low-Level PPP Support
ÎÎÎ
Application Software
PPP Connect
ÎÎÎ
Session API
ÎÎÎ
Timer
ÎÎÎ
ÎÎÎ
Hardware
ÎÎÎ
Packet Decoding TCP/IP
Stack
ÎÎÎ
Packet Encoding
ÎÎÎ
TX Packet Call Status
ÎÎÎ
Serial Interface
(SI) Callback
As shown in Figure C–3, the SI interface has the responsibility of providing for
connection control, a timer used by PPP for timeout, packet encoding and de-
coding, and a SI callback function for status messages and packet transmis-
sion. Note that the SI driver developer also defines the actual API used by the
application software to establish and tear down PPP connection sessions.
There is no specific requirements in specifying the session API for any particu-
lar PPP device, but the APIs defined for HDLC and PPPoE can be used guide.
NOTE: These functions can only be called in kernel mode. Please refer to Ap-
pendix A for programming in kernel mode.
NOTE: This function is called in kernel mode. Please refer to Appendix A for
programming in kernel mode.
Syntax void SIControl( HANDLE hSI, uint Message, UINT32 Data, HANDLE hPkt );
Description This function is called when a PPP needs to notify the serial interface (SI) of
a change in status, or when it needs SI to transmit a packet.
The purpose of the callback is determined by the value of the Message param-
eter. The following message values are defined for the this parameter:
C-4
Low-Level PPP Support
In the case that Data is set to any of disconnect messages, pppFree() should
be called to destroy the connection instance. For all other status values, no ac-
tion is required.
Note: It is always safe to assume that then the value of Data >= SI_CSTA-
TUS_DISCONNECT, that the message is some type of disconnect.
and which do not. The default value of the peer CMAP should be 0xffffffff, and
updated only when this message is received. Whether or not PPP will attempt
to exchange CMAP information with its peer, is determined by passing flags
to pppNew() when the connection instance is created.
//––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
// SI Control Callback Function for PPPoE
//––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
void pppoeSI( HANDLE hSI, uint Msg, UINT32 Aux, HANDLE hPkt )
{
// hSI is really a pointer to our private data structure
PPPOE_INST *ppi = (PPPOE_INST *)hSI;
HANDLE hFrag;
uint Offset,ValidSize,Payload;
UINT8 *pb;
ETHHDR *pEth;
switch( Msg )
{
case SI_MSG_CALLSTATUS:
// Record status so client can call ”GetStatus” function
ppi–>Status = (uint)Aux;
}
break;
case SI_MSG_PEERCMAP:
// PPPoE does not use async translation maps. The peer map in Aux
DbgPrintf( DBG_WARN, ”PPPOE: Unexpected Peer CMAP %08lx”,Aux );
C-6
Low-Level PPP Support
break;
case SI_MSG_SENDPACKET:
// Make sure packet is valid
if( !hPkt || !(hFrag = PktGetFrag( hPkt )) )
{
DbgPrintf(DBG_ERROR,”pppoeSI: Bad packet”);
goto TxDone;
}
break;
}
}
C.1.6 Tips for Implementing a PPP Serial Interface (SI) Module Instance
When new data arrives from the hardware, it is the responsibility of the SI mod-
ule to associate that data with a specific SI instance. The SI instance can then
be accessed to retrieve the handle to the PPP instance to use with any PPP
function calls.
PPP requires that its pppTimer() function be called once every second. The
easiest way to implement this requirement is to use the timer object built into
the kernel. The timer can be allocated when the SI instance is allocated, asso-
ciated with the instance, and then freed when the SI instance is destroyed. The
timer object is supplied a callback function that is called in kernel mode. In this
callback function, the pppTimer() function is called for all known instances of
PPP. This is shown later on in the example code.
Although a serial interface will probably not have any special requirements for
packets from the stack, it must at least be able to construct valid packets to
send to the pppInput() function. In order to use the packet allocation function
provided by the IF API (see Appendix A), the SI module should declare its pad-
ding requirements via the IFSetPad() function. For a serial interface that does
not use the packet buffer to physically send the packet, the size of the PPP
“header” would be 2 bytes (protocol field), and the padding would be 2 bytes
(checksum).
As an example of a system that does use the packet to send, consider PPPoE.
It uses the Ethernet device to send a PPPoE encapsulated packet. Its padding
requirements are 14 bytes for the Ethernet header, plus 6 bytes for the PPPoE
header, plus 2 bytes for the PPP header (protocol field), for a total of 22 bytes.
C-8
Low-Level PPP Support
Along with decoding any packet that is received on the physical hardware and
stripping off all but the protocol and payload fields, the SI module must supply
the received data as a packet (PKT) object to the pppInput() function. The fol-
lowing example code illustrates the creation of a packet object for holding new
packet data. This function assumes a packet with a max payload (MRU) of
1500 bytes
//–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
// Fill in the packet buffer here. The pointer ’pb’ now
// where the 2 byte protocol field should start.
//–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
//
// Fixup packet frag info
//
// The value of ’Offset’ is already valid, but we need to provide
// the size of the data. This size includes 2 byte protocol
// value. For example, for a 1500 byte IP packet, the value
// of ’PACKETSIZE’ is 1502
//
FragSetBufParams( hFrag, PACKETSIZE, Offset );
// This handle is what we give to PPP
return( hPkt );
}
Syntax HANDLE pppNew( HANDLE hSI, uint pppFlags, uint mru, IPN IPServer, IPN
IPMask, IPN IPClient, char *Username, char *Password,
UINT32 cmap,
void (*pfnSICtrl)( HANDLE, uint, UINT32, HANDLE ) );
Parameter(s) hSI Handle to SI module to be passed back to callback functio
pppFlags Connection option flags
mru Maximum receive unit (max size of Payload)
IPServer IP address of server in server mode (NULL in client mode)
IPMask IP subnet mask of client in server mode (NULL in client mode)
IPClient IP address of client in server mode (NULL in client mode)
Username Pointer to username in client mode (NULL in server mode)
Password Pointer to password in client mode (NULL in server mode)
cmap 32 bit local CMAP to pass to peer
pfnSICtrl Pointer to SI module callback function
Return Value Handle to new PPP connection instance, or NULL on error.
Description This function is called to create a new PPP connection instance. The type of
connection created is determined by the calling parameters.
- hSI – This is a private handle to created by the caller that points back to
the caller’s instance data. It is passed back to the caller via the callback
function pointed to by pfnSICtrl, and can be used to link back to caller’s
instance data when the callback is executed.
- pppFlags – The flags determine what type of connection instance to
create, and what type of options to support in the connection instance. In
the pppFlags parameter, one and only one of the following flags must be
set:
PPPFLG_SERVER Create PPP server connection instance
PPPFLG_CLIENT Create PPP client connection instance
C-10
Low-Level PPP Support
When operating in SERVER mode, any of the following flags can also be
set:
PPPFLG_OPT_AUTH_PAP Require PAP authentication
PPPFLG_OPT_AUTH_CHAP Require CHAP authentication
PPPFLG_OPT_USE_MSE Use MS extensions as server
PPPFLG_OPT_LOCALDNS Claim Local IP as DNS server
PPPFLG_SIOPT_SENDCMAP Send an async character map
PPPFLG_SIOPT_RECVCMAP Accept an async character map
PPPFLG_CH1 Allow server channel/group 1
account users
PPPFLG_CH2 Allow server channel/group 2
account users
PPPFLG_CH3 Allow server channel/group 3
account users
PPPFLG_CH4 Allow server channel/group 4
account users
When operating in CLIENT mode, any of the following flags can also be
set:
PPPFLG_OPT_USE_MSE Use MS extensions as client
PPPFLG_SIOPT_SENDCMAP Send an async character map
PPPFLG_SIOPT_RECVCMAP Accept an async character map
- mru – The MRU is maximum receive unit, or the max size of the payload
portion of a PPP packet. For a standard serial link, the MRU is typically
1500, but can be smaller.
- IPServer – When creating the PPP instance in SERVER mode, this is the
IP address in network format of the TCP/IP stack reported to the peer.
When operating in CLIENT mode, this value is NULL.
- IPMask – When creating the PPP instance in SERVER mode, this is the
IP subnet mask of the peer’s IP network reported to the peer. When oper-
ating in CLIENT mode, this value is NULL.
- IPClient – When creating the PPP instance in SERVER mode, this is the
IP address in network format of the peer reported to the peer. When oper-
ating in CLIENT mode, this value is NULL.
- Username – When creating the PPP instance in CLIENT mode, this is a
pointer to a NULL terminated string containing the username to use in PAP
or CHAP authentication. The maximum string length is defined by
PPPNAMELEN. When operating in SERVER mode, this value is NULL.
When successful, this function returns a handle to a new PPP instance. This
handle is used by the caller when calling other function in the PPP API.
Description This function is called to close and destroy a PPP connection instance created
with pppNew(). This function MUST be called to free the PPP handle, even if
the PPP connection itself is already disconnected.
Description This function is called when a PPP packet is received on a active serial inter-
face. The packet is data decoded into the PPP protocol and payload fields, and
given to PPP as a packet object. The handle hPPP is the PPP connection
instance returned from pppNew() for this connection, and hPkt is a packet ob-
ject created by using the kernel API (see section C.1.6.4).
C-12
Low-Level PPP Support
Description This function is called on an active PPP instance to notify PPP that one second
has elapsed. Since the PPP API is entirely stateless, it relies on the serial inter-
face for time tick notification.
C.2.2 Synopsis
The implementation of HDLC supplied in the TCP/IP stack library is available
in an optional serial support library that includes the HAL layer serial driver
(llSerial). The HDLC module is all that is required to enable PPP over the serial
port. There is no need to call the PPP API directly.
Syntax HANDLE hdlcNew( uint Dev, uint pppFlags, UINT32 cmap, char *Username,
char *Password );
C-14
Serial HDLC Client and Server Support
Return Value If it succeeds, the function returns a handle to a PPPoE client instance. Else,
it returns NULL.
Description This function is called to create a new serial HDLC client instance on the physi-
cal serial interface specified by the index Dev.
- cmap – This is the desired value of the async character control map that
is sent to the peer to allow frame compression by skipping the escape cod-
ing of characters when it is not required. The mask contains set bit for each
character (0 to 31) that must be escaped when sent by the peer. If the
PPPFLG_SIOPT_SENDCMAP option is not set, it is assumed that all 32
characters must be sent via the escape sequence.
When successful, this function returns a handle to a new serial HDLC instance
The current status of the connection can be queried at any time by calling
hdlcGetStatus().
Description This function is called to close and destroy a serial HDLC client session that
was created with hdlcNew(). This function is always called once for every
HDLC instance handle. If the connection is no longer active, it frees the
instance memory. If the connection is still active, it first disconnects the call
first.
Return Value This function returns a uint that will be set to one of the following values:
SI_CSTATUS_WAITING Connection is idle (PPPoE
session opening)
SI_CSTATUS_NEGOTIATE Connection in LCP negotiation
stage
SI_CSTATUS_AUTHORIZE Connection in authorization
stage
SI_CSTATUS_CONFIGURE Connection in IP configuration
stage
SI_CSTATUS_CONNECTED Connection is fully connected
and operational
SI_CSTATUS_DISCONNECT Connection dropped
SI_CSTATUS_DISCONNECT_LCP Connection dropped in LCP
stage
SI_CSTATUS_DISCONNECT_AUTH Connection dropped in
authorization stage
SI_CSTATUS_DISCONNECT_IPCP Connection dropped in IP
configuration stage
Description This function is called to get the connection status of a serial HDLC client ses-
sion using the HDLC instance handle returned from hdlcNew(). This function
can be called anytime after the handle is created with hdlcNew(), and before
it is destroyed with hdlcFree().
C-16
Serial HDLC Client and Server Support
Syntax HANDLE hdlcsNew( uint Dev, uint pppFlags, UINT32 cmap, IPN IPServer,
IPN IPMask, IPN IPClient );
Return Value If it succeeds, the function returns a handle to a serial HDLC server instance.
Else, it returns NULL.
Description This function is called to create a new serial HDLC server instance on the
physical serial interface specified by the index Dev.
- cmap – This is the desired value of the async character control map that
is sent to the peer to allow frame compression by skipping the escape cod-
ing of characters when it is not required. The mask contains set bit for each
character (0 to 31) that must be escaped when sent by the peer. If the
PPPFLG_SIOPT_SENDCMAP option is not set, it is assumed that all 32
characters must be sent via the escape sequence.
When successful, this function returns a handle to a new serial HDLC instance
The current status of the connection can be queried at any time by calling
hdlcGetStatus().
Description This function is called to close and destroy a serial HDLC server session that
was created with hdlcsNew(). This function is always called once for every
HDLC instance handle. If the connection is no longer active, it frees the
instance memory. If the connection is still active, it first disconnects the call
first.
Return Value This function returns a uint that will be set to one of the following values:
SI_CSTATUS_WAITING Connection is idle (PPPoE
session opening)
SI_CSTATUS_NEGOTIATE Connection in LCP negotiation
stage
SI_CSTATUS_AUTHORIZE Connection in authorization
stage
C-18
Serial HDLC Client and Server Support
Description This function is called to get the connection status of a serial HDLC server ses-
sion using the HDLC instance handle returned from hdlcsNew(). This function
can be called anytime after the handle is created with hdlcsNew(), and before
it is destroyed with hdlcsFree().
C.3.2 Synopsis
The PPPoE (PPP over Ethernet) specification allows for PPP packets to be
transmitted in a peer to peer method over an Ethernet tunnel. The standard
has gained in popularity since it allows for the use of multiple user accounts
on a single Ethernet network.
The implementation of PPPoE supplied in the TCP/IP stack library is built into
the stack library code, and linked to the Ether object which handles packets
from all Ethernet devices in the HAL layer. Thus is it not necessary to access
or alter the HAL to use PPPoE.
The software can be used as a PPP server or PPP client, but not both simulta-
neously. In both cases, PPPoE makes use of the the PPP programming inter-
faces described earlier in this section. Thus for server mode, the PPP sever
will make use of the same user account information as a serial based server.
Syntax HANDLE pppoeNew( HANDLE hEther, uint pppFlags, INT8 *Username, INT8
*Password );
Parameter(s) hEther Handle to Ether device on which to look for a PPPoE server
pppFlags Connection option flags
C-20
PPPoE Client and Server Support
Return Value If it succeeds, the function returns a handle to a PPPoE client instance. Else,
it returns NULL.
Description This function is called to create a new PPPoE client instance on the Ether type
interface specified by the handle hEther.
When successful, this function returns a handle to a new PPPoE instance The
current status of the PPPoE connection can be queried at any time by calling
pppoeGetStatus().
Description This function is called to close and destroy a PPPoE client session that was
created with pppoeNew(). This function is always called once for every PPPoE
instance handle. If the connection is no longer active, it frees the instance
memory. If the connection is still active, it first disconnects the call.
Return Value This function returns a uint that will be set to one of the following values:
SI_CSTATUS_WAITING Connection is idle (PPPoE
session opening)
SI_CSTATUS_NEGOTIATE Connection in LCP negotiation
stage
SI_CSTATUS_AUTHORIZE Connection in authorization
stage
SI_CSTATUS_CONFIGURE Connection in IP configuration
stage
SI_CSTATUS_CONNECTED Connection is fully connected
and operational
SI_CSTATUS_DISCONNECT Connection dropped
SI_CSTATUS_DISCONNECT_LCP Connection dropped in LCP
stage
SI_CSTATUS_DISCONNECT_AUTH Connection dropped in
authorization stage
SI_CSTATUS_DISCONNECT_IPCP Connection dropped in IP
configuration stage
Description This function is called to get the connection status of a PPPoE client session
using the PPPoE instance handle returned from pppoeNew(). This function
can be called anytime after the handle is created with pppoeNew(), and before
it is destroyed with pppoeFree().
Syntax HANDLE pppoesNew( HANDLE hEther, uint pppFlags, uint SessionMax, IPN
IPServer, IPN IPMask, IPN IPClientBase, INT8
*ServerName, INT8 *ServiceName );
Parameter(s) hEther Handle to Ether device on which to invoke the PPPoE server
pppFlags Connection option flags
SessionMax Max number of client connections allowed
IPServer IP address of server in network format
IPMask IP subnet mask in network format of the client address pool
IPClientBase IP base address in network format of the client address pool
C-22
PPPoE Client and Server Support
Return Value If it succeeds, the function returns a handle to a PPPoE server instance. Else,
it returns NULL.
Description This function is called to create a new PPPoE sever instance on the Ether type
interface specified by the handle hEther.
Description This function is called to close and destroy a PPPoE server session that was
created with pppoesNew(). This function is always called once to shutdown
the PPPoE server. Any external client currently connected to the server is dis-
connected.
C-24
Creating PPP Sever User Accounts
C.4.1 Synopsis
In order to use the PPP or PPPoE protocol in server mode, it advisable to pro-
tect access to the system through the use of a PPP authentication protocol.
The PPP supplied in the stack library allows for the use of either PAP or CHAP
in user authentication. The database of authorized users (name and pass-
word) is stored in the configuration system.
return;
}
C-26
Creating PPP Sever User Accounts
CfgEntryDeRef( hAcct );
return(0);
}
The following uses the AcctFind() function to find the target account.
void AcctDelete( char *name )
{
HANDLE hAcct;
// Find the account to delete
hAcct = AcctFind( name );
This section is required only for system programmers who need low level ac-
cess to the hardware for configuration and monitoring. This API does not ap-
ply to sockets application programming.
Topic Page
D-1
Overview
D.1 Overview
The function of the HAL is to provide resources to the stack library functions
and allow them to operate independently of the current run–time environment.
The HAL contains the functionality required by the stack that depends directly
on the hardware in a particular environment.
D-2
Low-Level Timer Driver (llTimer)
D.2.1 Synopsis
The stack code requires a very basic simple time function. It consists of two
parts: a function API, which can be called from the stack to get the current time,
and a “scheduler” which sends timer event notifications every 500ms.
Description This function is called when shutting down the system to shutdown and clean-
up the timer environment.
Description This function is called by the network scheduler to determine if there has been
timer activity since the last call. When called, the timer returns 1 if a half-sec-
ond has elapsed since the last event, and 0 otherwise. On a return of 1, the
event is cleared and the function will not return 1 for another half second. Multi-
ple half second events are not “queued up”.
Description Returns the number of seconds that have elapsed since the timer driver was
started. If the pointer pMSFrac is non-zero, the function writes the fractional
seconds (in milliseconds) to this location (0 to 999).
Note: Although the stack does not require “real time”, take care not to simply
use a millisecond timer and divide by 1000 as the value will “wrap” every 50
days.
Description Returns the initial start time that was passed to _llTimerOpen().
D-4
Low-Level Packet Driver (llPacket)
llPacketClose Close Driver and Unbind Logical Ether Object from Device Id
D-6
Low-Level Packet Driver (llPacket)
Syntax void llPacketSend( uint dev, UINT8 *pb, uint offset, uint size, HANDLE hFrag
);
Description Called to send a packet out the physical packet device indicated by dev. The
size of the valid data is in size. The byte offset to the valid data in the supplied
buffer is in offset. Once the packet has been sent, the memory is returned by
calling FragFree( hFrag ), where hFrag is the handle to the packet fragment
supplied in the calling parameters.
Note: Although it is normally illegal to call any stack function from an interrupt
routine, calling FragFree() at interrupt time is allowed.
D-8
Low-Level Packet Driver (llPacket)
Description Called to return a packet buffer to the system, which was previously obtained
from a call to llPacketGetBuffer(). This is done so packet drivers that use their
own buffer pools can support passing buffer ownership without copying buffer
data.
D.4.1 Synopsis
In the current directory structure, the serial port driver (llSerial) may or may not
be part of the HAL directory (as it is an optional component). However, it is part
of the HAL architecture, and should be programmed using the same guide-
lines used for the llTimer and llPacket drivers.
Description This function is called by NETCTRL initializes the system to use the serial port.
It also enumerates all the physical devices in the system, and returns a device
count. The stack will then call the llSerialOpenCharmode() and/or llSerialO-
penHDLC() functions for each physical device it requires.
D-10
Low-Level Serial Port Driver (llSerial)
Description This function is called by NETCTRL to indicate a final shutdown of the serial
driver environment. When called, there should be no currently open serial driv-
ers, and _llSerialInit() will be called again before any call to llSerialOpenChar-
mode() or llSerialOpenHDLC().
Return Value Returns 1 if there are HDLC input buffers available, 0 if not.
First, if there are characters for the “character mode” device waiting, they are
passed into the user application by calling character mode input callback func-
tion passed to llSerialOpenCharmode().
Second, if the device has been opened in HDLC mode, this function returns
1 if there are HDLC buffers pending. In this case, no additional “character
mode” input is received, however some queue character mode data may still
be passed to the callback function.
Description Opens the low level serial driver specified by the one’s based index dev in
character mode. The maximum value of dev is the number of devices returned
from the _llSerialInit() function.
Character mode input simply passes all characters received at the port to the
character mode receiver.
When opening the device, the driver should save the callback function pointer
pCharmodeRxCb. This function should be called for each character received
while in character mode. When the driver is opened in HDLC mode, no charac-
ter mode input is received. When the HDLC mode is closed, the character
mode becomes active again.
D-12
Low-Level Serial Port Driver (llSerial)
Syntax void llSerialConfig( uint dev, uint baud, uint mode, uint flowctrl );
Description This function is called by NETCTRL to configure the serial port attributes for
the indicated device.
The value of baud is the baud rate, and must be an even denominator of
230400, up to a max baud rate of 230400. For example: 230400, 115200,
57600, 38400, 28800, and 19200 are all legal values, while 56000 it not.
The value of mode indicates the mode of the device including data bits, parity,
and stop bits. Only the two most commonly used modes are defined:
HAL_SERIAL_MODE_8N1 8 Data Bits, No Parity, 1 Stop Bit
HAL_SERIAL_MODE_7E1 7 Data Bits, Even Parity, 1 Stop Bit
The value of flowctrl indicates the desired flow control operation. Legal values
for this parameter are:
HAL_SERIAL_FLOWCTRL_NONE No Flow Control
HAL_SERIAL_FLOWCTRL_HARDWARE Hardware Flow Control
Description This function is called to inform the driver that it may now indicate any queued
HDLC buffers to the HDLC object corresponding to the physical ingress de-
vice. Serial drivers must internally queue their own buffers. Queued buffers
cause events to be sent to the scheduler which will in turn call this function.
Description Called to get a serial buffer from the system, which will eventually be sent via
llSerialSend(), or returned to the driver via llSerialReturnBuffer(). Buffering is
done in this fashion so drivers that use their own buffer pools can support pass-
ing buffer ownership without copying data.
All buffers are of a fixed size. They have a usable size in bytes indicated by the
#define: HAL_SERIAL_BUFFERSIZE (currently 3052 bytes).
Syntax void llSerialSend( uint dev, UINT8 *pb, uint offset, uint size );
Description Called to send a serial buffer out the physical serial device indicated by dev.
The size of the valid data is in size. The byte offset to the valid data in the sup-
plied buffer is in offset. Once the buffer has been sent, the memory is returned
internally to the serial port’s free queue. Only buffers allocated via llSerialGet-
Buffer() can be used in this call.
Description Called to return a serial buffer to the system, which was previously obtained
from a call to llSerialGetBuffer(). This is done so drivers that use their own buff-
er pools can support passing buffer ownership without copying buffer data.
D-14
Appendix
AppendixEA
The easiest way for a user to get information from an embedded network de-
vice is through the web server. The HTTP server pulls files from the embedded
file system (EFS) that is included in the NDK software package’s OS adapta-
tion layer. These files can be compiled into the DSP application, located on a
network file system, a memory-based file system, or on a physical disk inter-
faced to the DSP. The NDK HTTP server accesses files through the EFS ap-
plication interface, which can be ported to any file system desired. The server
currently supports the HTTP/1.0 protocol.
The CGI program is built from a single C callable entrypoint (or CGI function).
Each CGI function is called on its own independent task thread. The task
threads are created with a priority of OS_TASKPRINORM and a stack size of
OS_TASKSTKHIGH. Note that consecutive calls to the same CGI function will
not be on the same task thread. Thus CGI functions can not share sockets from
one call to the next. In general, there is no persistent data in a CGI function.
Topic Page
E-1
Adding WEB Content
E.1.1 Operation
As previously mentioned, the HTTP server allows access to files using the em-
bedded file system (EFS) API. The default instantiation of this API is a RAM
based file system that resides in the OS adaptation layer. This OS adaptation
layer allows the HTTP server to work on any file storage device contained in
the system.
The default RAM based file system is built up mainly from a standard file i/o
API, with the addition of some private functions. These private functions allow
files to be created and destroyed by passing in memory pointers to where they
are stored. These functions are fully documented in section 2.6.
E-2
Adding WEB Content
One the above code is run, the EFS system is ready for the HTTP server to
serve up the content. Note the inclusion of the #pragma to place the converted
WEB page into a memory section named HTMLDATA. This allows the page
to be place out of the way by specifying the section’s location in the linker com-
mand file.
Since the EFS system uses memory records to simulate file content from static
data, the system should be flushed or cleaned when the shutting down or re-
booting. In the example code, the function RemoveWebFiles() is called when
the EFS files are no longer required.
void RemoveWebFiles(void)
{
efs_destroyfile(”sample.cgi”);
efs_destroyfile(”404.htm”);
efs_destroyfile(”index.html”);
}
Parameter(s) htmlSock The network socket on which the HTTP POST was issued
ContentLength The size of the POST content waiting on socket htmlSock
Return Value All CGI functions return one if the input socket is left open, and zero if it is
closed or transferred to another thread.
Description This function reads in the HTTP POST content from the socket htmlSock, and
writes out an HTML reply based on the function and the form content read. The
size of the form content is specified by ContentLength.The CGI function must
decide whether or not to close the socket on which the POST arrived. By de-
fault, the socket is normally left open, but in some cases may need to be
closed. It is also possible that the CGI function may wish to take control of the
socket an close it at a later point in time. Note in this latter case, the socket
would be transferred to another thread, using the fdGetFileHandle() and File-
HandleGetFd() function calls.
The function must return either “0” or “1” to indicate the status of the socket
htmlSock. If the socket is closed or passed on to another task, the function re-
turns “0”. If the socket is still active, the function returns “1”.
When there is any doubt whether or not to close the socket, the socket is typi-
cally left open for the HTTP server to close when appropriate.
E-4
Writing CGI Functions
After reading in the data from the socket, each form entry can be parsed from
the from by using the supplied example function: cgiParseVars(). The formal
definition of the function is shown below.
Note that this function replaces parsePostVars(), a similar function that was
included in earlier versions of the Network Developer’s Kit. The parsePost-
Vars() function was not re-entrant, and has been purged from the NDK re-
lease. The source code to cgiParseVars() is included in the example applica-
tion code shipped with the NDK.
Parameter(s) PostInput[] Pointer to the form data read in from the HTTP request socket
pParseIndex Pointer to an int holding the current parse position (initially
zero)
Return Value A pointer to a NULL terminated string within PostInput[], signifying the name
or value of a form entry. Also updates the value pointed to by pParseIndex.
Description Reads input from a CGI POST operation pointed to by PostInput[] at an offset
pointed to by pParseIndex and returns in sequence a pointer the name and
then the value of each post entry. This function modifies the data in PostInput[].
It also updates the current parsing position in the variable pParseIndex. The
parse index must be set to 0 on initial call.On the initial call to this function, the
integer value pointed to by pParseIndex should contain zero.
On reaching the end of the input, the function sets pParseIndex to –1. If called
again, the function will return a NULL pointer and leave the value of pParseIn-
dex unchanged.
The HTTP server supplies several functions to aid in building and sending both
HTTP data over the socket. In addition, the example applications contain vari-
ous MACROS than can also help in initially developing a CGI function. The
HTTP functions are fully described at the end of this section, but the main reply
functions are usually one of the following:
or
The first MACRO, http404() is used to send a “file not found” response to the
client. This includes the HTML text defined for the 404 error. An example of
creating a 404.htm file appears earlier in this appendix.
The second MACRO, http501() is used to send a 501 – Not Implemented error
to the HTTP client. Here, no additional data is sent.
Under normal circumstances, the CGI function will use the httpSendStatus-
Line() function to send an OK message to the client, followed by the httpSend-
ClientStr() function to send client data in the form of a NULL terminated string.
Note that an additional carriage return and line feed are required to separate
the header from the HTML data.
E-6
CGI Function Example
The next step we perform is to convert this HTML file to C source file. We did
this back in section E.1.2. Once we have the page in C source code form, we
can add it to our program.
3) Process request in some meaningful way. Make sure the inputs are valid
before processing them to avoid crashes or security violations. This may
involve querying or updating the configuration, making a network request,
or updating a file.
4) Send a response. Keep in mind the first line of the response should indi-
cate whether the request was successful or not.
E-8
CGI Function Example
E-10
HTTP Sever Exported Functions
The HTTP server module exports several functions and strings to aid in the
creation of a CGI function. This section contains the formal specification for
these functions. The first part of this appendix describes how to use these func-
tions in creating a HTTP CGI function in C.
To aid in the creation of the response data, some commonly used HTML
strings can be defined. Some of these are already defined in the HTTPIF.H file.
These include the following (note that all entries except the first three include
a trailing space character.):
E-12
Index
Index
CfgEntrySetData() 4-17
A CfgExecute() 4-7
accept() 3-14 CfgFree() 4-7
CfgGetDefault() 4-8
B CfgGetEntry() 4-8
CfgGetEntryCnt() 4-9
bind() 3-15 CfgGetImmediate() 4-9
BindFree() A-32 CfgGetNextEntry() 4-10
BindGetFirst() A-33 CFGITEM_ACCT_PPP 4-31
BindGetIF() A-33 CFGITEM_DHCP_DOMAINNAMESERVER 4-32
BindGetIP() A-33 CFGITEM_DHCP_HOSTNAME 4-32
BindGetNext() A-33 CFGITEM_IP_ICMPDOREDIRECT 4-34
BindNew() A-32 CFGITEM_IP_ICMPTTL 4-34
CFGITEM_IP_ICMPTTLECHO 4-34
C CFGITEM_IP_IPFORWARDING 4-34
CFGITEM_IP_IPINDEXSTART 4-34
CFG_ADDMODE_DUPLICATE 4-6 CFGITEM_IP_IPNATENABLE 4-34
CFG_ADDMODE_NOSAVE 4-6 CFGITEM_IP_IPREASMMAXSIZE 4-34
CFG_ADDMODE_UNIQUE 4-6 CFGITEM_IP_IPREASMMAXTIME 4-34
CFG_CLIENTSTATUS_INVALID 4-31 CFGITEM_IP_PIPEBUFMAX 4-35
CFG_CLIENTSTATUS_PENDING 4-30 CFGITEM_IP_PIPEMINRX 4-35
CFG_CLIENTSTATUS_STATIC 4-31 CFGITEM_IP_PIPEMINTX 4-35
CFG_CLIENTSTATUS_VALID 4-30 CFGITEM_IP_PIPETIMEIO 4-35
CFG_CLIENTTYPE_DYNAMIC 4-30 CFGITEM_IP_RTARPDOWNTIME 4-34
CFG_CLIENTTYPE_STATIC 4-30 CFGITEM_IP_RTCADVLIFE 4-34
CFG_DOMAIN_MAX 4-28 CFGITEM_IP_RTCADVPREF 4-34
CFG_HOSTNAME_MAX 4-30 CFGITEM_IP_RTCADVTIME 4-34
CFG_NETTYPE_DHCPS 4-28 CFGITEM_IP_RTCENABLEDEBUG 4-34
CFG_NETTYPE_DYNAMIC 4-28 CFGITEM_IP_RTCLONETIMEOUT 4-34
CFG_NETTYPE_VIRTUAL 4-28 CFGITEM_IP_RTDEFAULTMTU 4-34
CfgAddEntry() 4-5 CFGITEM_IP_RTKEEPALIVETIME 4-34
CfgEntryDeRef() 4-15 CFGITEM_IP_SOCKBUFMAX 4-34
CfgEntryGetData() 4-16 CFGITEM_IP_SOCKMAXCONNECT 4-34
CfgEntryInfo() 4-16 CFGITEM_IP_SOCKMINRX 4-34
CfgEntryRef() 4-17 CFGITEM_IP_SOCKMINTX 4-34
Index-1
Index
Index-2
Index
F G
getpeername() 3-16
fclose(). See efs_fclose()
getsockname() 3-17
FD_CLR() 3-10
getsockopt() 3-17
FD_COPY() 3-11
FD_ISSET() 3-11
fd_set 3-10 H
FD_SET() 3-10 HDLC C-14
FD_ZERO() 3-11 hdlcFree() C-16
fdClose() 3-7 hdlcGetStatus() C-16
fdCloseSession() 3-6 hdlcNew() C-14
fdError() 3-7 hdlcsFree() C-18
fdGetFileHandle() 3-8 hdlcsGetStatus() C-18
fdOpenSession() 3-6 hdlcsNew() C-17
fdSelect() 3-7 HOSTENT 5-8
fdSelectAbort() 3-8 HTTP Exported Functions E-12
fdTransfer() 3-8 HTTP Server E-1
File Descriptor Functions 3-6 HTTP Server Support 6-14
Index-3
Index
Index-4
Index
Index-5
Index
R SO_ERROR 3-20
SO_IFDEVICE 3-21
recv() 3-22 SO_KEEPALIVE 3-18
recvfrom() 3-24 SO_LINGER 3-19
recvnc() 3-12, 3-25 SO_OOBINLINE 3-13, 3-19
recvncfree() 3-12, 3-26 SO_RCVBUF 3-19
recvncfrom() 3-12, 3-27 SO_RCVLOWAT 3-20
RTCAddHook() A-48 SO_RCVTIMEO 3-20
RtCreate() A-40 SO_REUSEADDR 3-18
Index-6
Index
Index-7