# 3. FUNCTIONS (1)

The following pages contain a list of routines were tailored in the process of porting NicheLite to this particular target and are listed here as they may also be useful to the programmer writing customized applications with the InterNiche stack. It is anticipated that the bulk of the API of interest to the application writer are contained in Chapter 4 - MINI-SOCKETS TCP API

The following pages contain a list of InterNiche internal routines which may be useful to programmers writing customized applications with the InterNiche stack.

## 3.1 Port Tailored Functions

Name

`port_prep`

Syntax

`extern int (* port_prep)(int already_found);`

Parameters

`int already_found /* index for nets[ ] structure to use */`

Description

This is a pointer to a function. It should be initialized in `pre_task_setup()` to the actual function (implemented by the porting engineer). This function should prepare the `nets[ ]` structures for the network interfaces that the target system will want to use. The integer passed is the `nets[ ]` index of the interface to set up.

The `nets[ ]` members which need to be filled in are described in Section 2.2.2, entitled "The net Structure, the nets[ ] Array"

Returns

Returns the `nets[ ]` index of the next interface to be set up. If no interfaces were set up, the returned value is the same as the passed value.

Name

`npalloc`

`npfree`

Syntax

`void *npalloc(int size);`

`void *npfree(void *);`

Description

All the IP stack's dynamic memory is allocated by calls to `npalloc()` and released by calls to `npfree()`. The syntax for these is exactly the same as the standard C library calls `malloc()` and `free()`, with the exception that buffers returns from `npalloc()` are assumed to be pre-initialized to all zeros. In this respect `npalloc()` is like `calloc()`.

If the target system already supports standard `calloc()` and `free()` calls, all that is necessary is to add the following lines to `ipport.h_h`:

    #define npalloc(size)  calloc(1, size)
    #define npfree(ptr)    free(ptr)

In the event your target system does not support `calloc()` and `free()`, you will need to implement them. An exhaustive description of how these functions work and sample code is available in "The C Programming Language" by Kernighan and Ritchie.

The great majority of the calls to `npalloc()` are made at initialization time. Only the UDP and TCP layers require these calls during runtime. If your system has severe memory shortages, then these layers can be modified to use pre-allocated blocks of static memory rather than implement a fully functional `npalloc()` and `npfree()`, but this is invariably more work and puts limits on the number of simultaneous connections which can be supported.

One issue that must be dealt with on some target processors is memory alignment. Some processors will generate faults if instructions to read or write more than one byte of memory at a time from odd numbered addresses are executed. Even if the target processor supports 2 or 4 byte reads and writes to odd numbered addresses, instructions of this sort usually execute more slowly than accesses to addresses that are an integer multiple of the number of bytes accessed by the instruction. System performance can suffer. If the target system supports the standard `calloc()` and `free()` calls then the C library vendors have probably already made sure that the buffers returned by `calloc()` are properly aligned for the target processor. However if you need to implement `npalloc()` and `npfree()` without the standard C library memory allocation functions then you should implement these functions such that the memory blocks are aligned on addresses that are a multiple of the data bus width of the target processor. If you don't know the data bus width of the target processor, 4 is usually a safe guess.

Returns

`npalloc()` returns a pointer to the block allocated or `NULL` if memory is unavailable.

Name

`dtrap()`

Syntax

`void dtrap(void);`

Description

This primitive is intended to hook a debugger whenever it is called.

Returns

Usually nothing, depends on porting engineer modifications.

Name

`dprintf()`

`initmsg()`

Syntax

`void dprintf(char *, ...);`

`void initmsg(char *, ...);`

Description

These two routines are functionally the same as the standard C library `printf()` function and are called by the stack code to inform the porting engineer or end user of system status. `initmsg()` prints status messages at initialization time. `dprintf()` prints error warnings during runtime.

InterNiche provides an version of `printf()` in `misclib/ttyio.c`. This implementation does not support floating point formats, but is otherwise consistent with standard specifications for the function. The compile-time macro `NATIVE_PRINTF` (`ipport.h`) determines whether this code, or a user/library implementation is to be used.

Name

`dputchar()`

Syntax

`void dputchar(int chr);`

Description

The InterNiche CUI routines call `dputchar()` in order to display a character on the target system display or monitor port. If such output is not desired, `dputchar()` can be implemented as a no-op. Its parameter is an ASCII character that should be displayed on the target system display or monitor device.

`dputchar()` should perform newline expansion. If the value of `chr` is an ASCII newline character (`0xa`) then a newline followed by a carriage return should be output to the display device.

Returns

Nothing.

Name

`kbhit()`

Syntax

`int kbhit(void);`

Description

`kbhit()` should return a non-zero value if a keystroke has been entered by a user at the CUI of the target system. It should not dequeue the character itself from the input device, rather the return value from `kbhit()` should simply poll the device to determine if a character is present. The entered character is retrieved using the `getch()` function.

Returns

`0` if no character had been entered at the input monitor device, non-zero if at least one character is available.

Name

`getch()`

Syntax

`int getch(void);`

Description

`kbhit()` and `getch()` are used together to effect CUI input. The stack code calls `kbhit()` to determine if a character is available and then if a character is available, calls `getch()` to return the value of the character. `getch()` should never block for user input.

Returns

If a character is available at the CUI or system monitor device, `getch()` returns the ASCII value of that character. Its return value is undefined if no character is available.

Name

`ENTER_CRIT_SECTION()`

`EXIT_CRIT_SECTION()`

Syntax

`#define ENTER_CRIT_SECTION(p);`

`#define EXIT_CRIT_SECTION(p);`

Parameters

None that are currently used.

Description

These two entry points should be designed to be paired around sections of code that must not be interrupted or pre-empted. Usually, `ENTER_CRIT_SECTION()` should save the processor interrupt state and disable interrupts, whereas `EXIT_CRIT_SECTION()` should restore the processor interrupt state to as it was before the most recent call to `ENTER_CRIT_SECTION()`. On UNIX-like systems they can be mapped to the `spl()` primitive. Only the definitions are given here; for examples see the source code.

The stack source code always pairs these two in the same routines. For example, one common architecture takes advantage of this to push the existing flags register onto the processor stack, saving the interrupt flag state and retrieves the value for the flags register later, restoring the interrupt flag as it was before the `ENTER_CRIT_SECTION()` call.

The parameter `p` is currently unused.

Returns

These return no meaningful value.

Name

`LOCK_NET_RESOURCE()`

`UNLOCK_NET_RESOURCE()`

Syntax

`void LOCK_NET_RESOURCE(int resID);`

`void UNLOCK_NET_RESOURCE(int resID);`

Parameters

The integer defined constants, `NET_RESID`, `RXQ_RESID` or `FREEQ_RESID`.

Description

Returns

Nothing.

Name

`cksum()`

Syntax

`unsigned short cksum (char *buffer, unsigned word_count);`

Parameters

`char *buffer /* pointer to buffer to checksum */`

`unsigned word_count /* number of 16 bit words in buffer */`

Description

Returns 16 bit Internet checksum of buffer. Algorithms for this are described in RFC1071.

NOTE: A portable C language version of this routine is provided with the demo packages, however TCP implementations can spend a significant portion of their CPU cycles in the checksum routine. This routine is described here to encourage porting engineers to optimize their ports by implementing their checksum routines in assembly language.

Returns

The 16 bit checksum.

Name

`panic()`

Syntax

`void panic(char *msg);`

Parameters

`char *msg /* short test message describing the fault */`

Description

`panic()` is called if the InterNiche stack software detects a fatal system error. `msg` is a string describing problem. What this should do varies with the implementation. In a testing or development environment it should print messages, hook debuggers, etc. In an embedded controller, it should try to restart (i.e. warm boot) the system.

Sample for a DOS application is shown below.

Returns

Generally there is no return from this routine, however it is sometimes useful to allow a return under control of a debugger.

Example

    void
    panic (msg)
       char *msg;
    {
       dprintf("panic: %s\n", msg);
       dtrap();      /* try to hook debugger */
       netexit(1);   /* try to clean up */
    }

Name

`sysuptime()`

Syntax

`unsigned long sysuptime(void);`

Parameters

None

Description

Returns the number of 1/100ths of a second that have elapsed since the target system was last booted.

Returns

See above.

Example

    unsigned long sysuptime()
    {
       return ((cticks/TPS)*100);   /* 100ths of a sec since boot time */
    }

## 3.2 ARP

Name

`etainit()`

Syntax

`int etainit (void);`

Parameters

None

File

`ip/et_arp.c`

Description

This needs to be called once at initialization time to initialize the ARP layer. It registers the ARP types with the hardware drivers and sets up an ARP timer.

Returns

General error codes as described in Error Codes in section 2.1.

Name

`make_arp_entry()`

Syntax

`struct arptabent *make_arp_entry(ip_addr dest_ip, NET net);`

Parameters

`ip_addr dest_ip /* IP address to make entry for */`

`NET net /* associated network interface */`

File

`ip/et_arp.c`

Description

Finds the first unused (or the oldest) ARP table entry and makes a new entry to prepare it for an ARP reply. If the IP address already has an ARP entry, the entry is returned with only the time stamp modified. The MAC address of the created entry is not resolved but left as zeros. The eventual ARP reply will fill in the MAC address.

Returns

Returns pointer to ARP table entry selected.

Name

`arprcv()`

Syntax

`int arprcv(PACKET pkt);`

Parameters

`PACKET pkt /* the PACKET containing the incoming ARP packet */`

File

`ip/et_arp.c`

Description

The upcall for received ARP packets. Called by the interface layer.

Returns

Returns `0` if it was for us, else a negative error code.

## 3.3 IP

Name

`ip_write()`

Syntax

`int ip_write(u_char prot, PACKET p);`

Parameters

`u_char prot /*indication of which protocol the packet is carrying TCP,UDP,ICMP */`

`PACKET p /* a packet to send */`

File

`ip/ip.c`

Description

Fills in the Internet header in the packet p and sends the packet through the appropriate `net` interface. This will involve using routing. Call with `p->nb_plen and p->nb_prot` fields set to start of upper (UDP) layer and `p->fhost` set to target IP address.

Returns

Returns `0` if sent OK, `ENP_SEND_PENDING` if waiting for ARP, else negative error code if error detected.

Name

`ip2mac()`

Syntax

`int ip2mac(PACKET pkt, ip_addr dest_ip);`

Parameters

`PACKET pkt /* the packet itself, all set but for dest MAC addr */`

`ip_addr dest_ip /* the IP host or gateway to get MAC address for */`

File

`ip/ipnet.c`

Description

Takes as input an outgoing IP packet with no MAC information and tries to resolve an Ethernet address matching the passed IP address. If the MAC address is not already cached, we broadcast an ARP request for the missing IP address and attach the packet to the "pending" pointer. The packet will be sent when the ARP reply comes in, or freed if we time out.

Returns

Returns `SUCCESS` (0) if packet went to MAC sender; `ENP_SEND_PENDING` if awaiting. ARP reply, or `SEND_FAILED` if error.

Name

`ip_mymach()`

Syntax

`ip_addr ip_mymach(ip_addr host);`

Parameters

`ip_addr host /* IP address of foreign host to find */`

File

`ip/ip.c`

Description

Returns the address of our machine relative to a given foreign host IP address. On a single homed host this will always return the sole interface's IP address.

Returns

Our IP address on one of our networks interfaces.

Name

`ip_rcv()`

Syntax

`int ip_rcv(PACKET p);`

Parameters

`PACKET p /* the received packet, with p->nb_prot and p->nb_plen pointing to the start of the IP header and Mac information fields filled in. */`

File

`ip/ipdemux.c`

Description

This is the IP receive upcall routine. It handles packets received by network ISRs, etc., verifies their IP headers, and does the upcall to the upper layer that should receive the packet.

Returns

Returns `0` if packet was processed successfully, `ENP_NOT_MINE` if not for me, or a negative error code if packet was badly formed.

Name

`parse_ipad()`

Syntax

`char * parse_ipad(ip_addr * ipout, unsigned * sbits, char * stringin);`

Parameters

`ip_addr * ipout /* pointer to IP address to set */`

`unsigned * sbits /* default subnet bit number */`

`char * stringin /* buffer with ascii to parse */`

File

`misclib/parseip.c`

Description

Looks for an IP address in `stringin` buffer, makes an IP address (in big-endian) in `ipout`.

Returns

Returns `NULL` upon success, else returns a pointer to a string describing the syntax problem in the input string.

Name

`print_ipad()`

Syntax

`char *print_ipad(unsigned long ipaddr);`

Parameters

`unsigned long ipaddr /* IP address to print, in Big-Endian (net order) */`

File

`misclib/in_utils.c`

Description

Accepts a 32 bit IP address in big-endian format and returns a pointer to a volatile buffer with a printable version of the address. The buffer will be overwritten by each subsequent call to `print_ipad`, so the caller should copy it or use it immediately.

Note that the current implementation of `print_ipad()` is not re-entrant, and should not be used on a port to a pre-emptive RTOS.

Returns

Returns a pointer to the buffer with the printable IP address text.

Name

`pk_alloc()`

Syntax

`PACKET pk_alloc(unsigned int len);`

Parameters

`unsigned int len /* length in bytes of packet data to be stored in buffer */`

File

`net/pktalloc.c`

Description

`pk_alloc()` allocates a `netbuf` structure and associated packet buffer that the caller can use to store data to be transmitted or data that has been received. `pk_alloc()` is used internally by the InterNiche stack to pass data between the various protocol layers. The porting engineer should use `pk_alloc()` in his network interface software to pass packets received on the interface up to the InterNiche stack.

Note that if you happen to be implementing Mutual Exclusion using the Net Resource Method, then the `FREEQ_RESID` resource would need to be locked and unlocked while making calls to `pk_alloc()`.

Returns

If the allocation was successful, a pointer to the allocated `netbuf` structure is returned. If allocation was unsuccessful, `NULL` is returned.

Name

`pk_free()`

Syntax

`void pk_free(PACKET pkt);`

Parameters

`PACKET pkt /* ptr to netbuf structure previously allocated by pk_alloc() */`

File

`net/pktalloc.c`

Description

`pk_free()` is used to return a previously allocated `netbuf` structure to the pool of such structures that is maintained by the InterNiche stack. The porting engineer should include a call to `pk_free()` in his network interface code in order to return a `netbuf` structure and its associated packet buffer to the free pool after the packet has been transmitted by the network device.

Note that if you happen to be implementing Mutual Exclusion using the Net Resource Method, then the FREEQ_RESID resource would need to be locked and unlocked while making calls to `pk_free()`.

Returns

Nothing.

## 3.4 ICMP

Name

`icmprcv()`

Syntax

`int icmprcv(PACKET p);`

Parameters

`PACKET p /* the received packet, with p->nb_prot and p->nb_plen pointing to the start of the ICMP header. p->fhost filled in. */`

File

`ip/icmp.c`

Description

ICMP received packet upcall handler.

Returns

Returns `0` if we processed the packet, `ENP_NOT_MINE`, or a negative error code.

Name

`icmp_destun()`

Syntax

`void icmp_destun(ip_addr host, struct ip *ip, unsigned type, NET net);`

Parameters

`ip_addr host /* host to complain to */`

`struct ip * ip /* IP header of offending packet */`

`unsigned type /* type of DU to send (PROT, PORT, HOST) */`

`NET net /* interface that this packet came in on */`

File

`ip/icmp.c`

Description

Send an ICMP "destination unreachable" packet, where type indicates the type of the message. It should be one of the following defined constants:

`DSTNET`

`DSTHOST`

`DSTPROT`

`DSTPORT`

`DSTFRAG`

`DSTSRC`

Returns

No meaningful return value.

Name

`icmpEcho()`

Syntax

`int icmpEcho(ip_addr host, char * data, unsigned length, unshort pingseq);`

Parameters

`ip_addr host /* host to ping - 32 bit, local-endian */`

`char * data /* ping data, NULL if don't care */`

`unsigned length /* total desired length of packet on media */`

`unshort pingseq /* ping sequence number */`

File

`net/ping.c`

Description

Send an ICMP echo request (the guts of "ping"). Callable from Applications. Sends a single "ping" (ICMP echo request) to the specified `host`. The application must provide an appropriate `pingDemux()` routine if ping replies are to be checked.

Returns

Returns `0` if ping sent OK, else negative error code.

## 3.5 UDP

These calls to the UDP layer are provided for systems which do not implement Sockets. They are much more lightweight, but do not offer the portability of Sockets.

Name

`udp_send()`

Syntax

`int udp_send(unshort fport, unshort lport, PACKET p);`

Parameters

`unshort fport /* target UDP port */`

`unshort lport /* local UDP port */`

`PACKET p /* packet to send, nb_prot ... nb_plen set to data, fhost set */`

File

`ip/udp.c`

Description

Send a UDP datagram to the foreign host in `p->fhost`. local and remote ports in the UDP header are set from the values passed. Note: This will work just fine without doing a previous `udp_open()` on the associated ports, but any response to the packet will not be up-called since the UDP layer will have no data to de-multiplex it.

Returns

`0` is OK, or a negative `ENP_` error code.

Name

`udp_alloc()`

Syntax

`PACKET udp_alloc(int datalen, int optlen);`

Parameters

`int datalen /* length of UDP data (not including udp header) */`

`int optlen /* length of IP options if any. Usually 0. */`

File

`ip/udp.c`

Description

This returns a `PACKET` big enough for the UDP data. It works by adding the space needed for UDP, IP, and MAC headers to the `datalen` passed and calling `pk_alloc()`. It also ensures that the FREEQ_RESID resource is locked around the call to `pk_alloc()`.

Returns

Returns a `PACKET` (pointer to struct `netbuf`) if OK, else `NULL` if a big enough packet was not available.

Name

`udp_free()`

Syntax

`void udp_free(PACKET p);`

Parameters

`PACKET p /* ptr to netbuf structure previously allocated by udp_alloc() */`

File

`ip/udp.c`

Description

`udp_free()` is used to return a previously allocated `PACKET` to the InterNiche stack's free pool. It works by calling `pk_free()`, but like `udp_alloc()` it ensures that the `FREEQ_RESID` resource is locked around the access to the free packet pool.

Returns

Void.

Name

`udpdemux()`

Syntax

`int udpdemux(PACKET p);`

Parameters

`PACKET p /* received UDP PACKET, with nb_prot, nb_plen, set to start of UDP header; and fhost set to foreign host IP address */`

File

`ip/udp.c`

Description

This is upcalled by `ip_demux()` when it has verified a received UDP packet.

Returns

`0` if packet accepted, `ENP_NOT_MINE` if packet was not for us, or a negative `ENP_` error code.

Name

`udp_open()`

Syntax

`UDPCONN udp_open(ip_addr fhost, unshort fsock, unshort lsock, int (*handler) (PACKET, void *), void * data);`

Parameters

`ip_addr fhost /* host to receive from, 0 if any is OK */`

`unshort fsock /*foreign socket (port) number, 0 if any is OK*/`

`unshort lsock /* local socket (port) to receive on */`

`int * handler /* udp received callback function */`

`void * data /* returned on upcalls to aid de-muxing */`

File

`ip/udp_open.c`

Description

This routine creates a structure in the UDP layer to receive and upcall UDP packets which match the parameter passed. The foreign host and socket can use `0` as a wild card. This allows us to start "listens" for incoming SNMP Stations, TFTP applications, etc. The handler routine passed is similar to the other upcall handler routines in this section except that it is also passed a copy of the "`data`" pointer which is passed to `udp_open()`. This can be any random data the programmer desires, such as a pointer to another routine or control structure to aid in de-multiplexing the received UDP packet.

Returns

`NULL` on failure, non-NULL on success.

Name

`udp_close()`

Syntax

`void udp_close(UDPCONN con);`

Parameters

`UDPCONN con /* an open UDP connection */`

File

`net/udp_open.c`

Description

`udp_close()` closes a udp connection, by removing the connection from UDP's list of connections and deallocating its internal structures.

Returns

Nothing.

## 3.6 MISCLIB

Name

`ns_printf()`

Syntax

`int ns_printf(void * vio, char * format,...);`

Parameters

`void * vio /* pointer to output device structure */`

`char * format /* printf() style format string */`

File

`misclib/in_utils.c`

Description

This function is called by various statistics reporting functions. Its usage is similar to that of the standard C library `printf()` function. The `vio` parameter addresses a structure that can be used to redirect the output of the function to some device other than the system console. When `vio` is `NULL`, output is directed to the system console.

Returns

A negative value if some error occurred, a non-negative number if successful.