saf@CITI.UMICH.EDU (10/23/87)
A number of people have complained about the wide-body format
of CITI's specification documents for IP, UDP, TCP, and IF,
so I am reposting them here in a narrower format.
Steve Fram
saf@citi.umich.edu
-------------------------------------------------------------
IF DRIVER INTERFACE SPECIFICATION
Beta Draft
MacIP project
University of Michigan, CITI
2901 Hubbard
Ann Arbor, MI 48103
macip@citi.umich.edu
ABOUT THE IF DRIVER
The IF driver provides IP with a standard interface to the services provided by
a local network. This document describes the program interface to the IF
driver. Through this interface IP receives network configuration information
and sends and receive packets. Driver requests are made by preparing a driver
parameter block and a protocol parameter block, and issuing a driver control
call. The driver parameter block is described in [CITI MacIP].
IF DRIVER NAMES
All IF Drivers have a name in the format: ".IF_*". IP finds the available
interfaces by searching the unit table for drivers with names beginning with
IF_.
IF DATA STRUCTURES
The reader should be familiar with the common C derived types, such as those
described in <sys/types.h>, <sys/time.h>, MPW C, and Inside Macintosh
hwid is a pointer to a structure that identifies which hardware driver this
interface module should attach to. The length and format of a hardware
identifier is particular to each interface module and the hardware driver that it
interfaces to. It is assumed that clients that use hwid will know the format
used by the IF they are calling.
Routing information is given in the following structures:
typedef if_addrrange {
unsigned long type; /* specify nummask or range */
union {
struct if_num_mask { /* Specify range by... */
unsigned long netnumber; /* Netnumber and */
unsigned long netmask; /* Netmask */
} nm;
struct if_start_end { /* Specify range by... */
unsigned long start; /* Start and */
unsigned long end; /* End */
} se;
} type;
} if_addrrange_t, *if_addrrange_p;
typedef struct if_redirect { /* IF redirect array element */
format */
if_addrrange_t rd_range; /* Address range */
unsigned long rd_to; /* New IP address */
} if_redirect_t, *if_redirect_p;
typedef struct if_routing { /* IF routing information */
unsigned long hr_lhost; /* Local IP address.*/
if_addrrange_t hr_range; /* Address range */
unsigned long hr_broadaddr; /* Broadcast address */
unsigned long hr_default; /* Default route */
unsigned short hr_cost; /* Cost of network */
unsigned long hr_name[4]; /* IP address of 4 name
servers */
unsigned long hr_spare[4]; /* 4 spare IP addresses.*/
if_redirect_t hr_redirect[10];/* Variable array of
redirects */
} if_routing_t, *if_routing_p;
hr_redirect is an array of redirect records. If there are fewer than 10
records, the records are terminated by a zero record. hr_rtype selects the
if_addrrange_t union, either IF_R_NUMMASK, or IF_R_STARTEND.
IF FUNCTIONS
The following functions provide a program interface to the IP driver layer.
Each function returns success (0) or an error code. Error code identifiers are
defined in net_errno.h. The return type for all functions is long.
Some IF routines take refnum as their first parameter. refnum is not actually
passed to the routine. Rather, it is used by the glue library to demultiplex on
the available interface modules. The parameters following refnum are passed
to the IF following the conventions described in CITI's Driver Calling
Conventions.
Right and left arrows indicate values passed to and from the driver functions,
respectively.
if_find (uproc, udata)
-> ProcPtr uproc; Address of client routine
-> long udata; User data
(*uproc) (refnum, name, udata)
-> long refnum; IF reference number
-> char *name; Interface's name
-> long udata; User data
if_find searches the unit table for interface modules, calling (*uproc) for
each interface found. This routine resides in the glue library, not the interface
modules.
(*uproc) is called with the reference number (refnum) and the driver name
(name) of each interface module found. There are no restrictions on what
(*uproc) can do. udata is a long word of user data that if_find passes to
(*uproc).
if_get_info (refnum, output, flags, headersz, trailersz,
obmaxpaksz, ibmaxpaksz, maxfragsz, connections,
version)
-> long refnum IF reference number
<- ProcPtr *output Packet output routine
<- unsigned long *flags Control flags
<- unsigned long *headersz Header space requirements
<- unsigned long *trailersz Trailer space requirements
<- unsigned long *obmaxpaksz Maximum IP packet size
<- unsigned long *ibmaxpaksz Maximum IP packet size
<- unsigned long *maxfragsz Maximum lan packet size (IP
fragment)
<- unsigned long *connections Number of network
connections
<> unsigned long *version Interface versions
if_get_info returns global information about an interface module. refnum is
the reference number of the IF the client wants to call. hwindex is the
hardware index of the network connection the client wants information on.
output is the address of the packet output routine, defined below, that IP can
call to write packets. headersz and trailersz are the space that IP needs to
preallocate for this IF's headers an trailers. maxpaksz is the largest IP packet
(possibly fragmented) that this network can successfully transmit. maxfragsz
is the largest packet (IP fragment) that this network will transmit.
connections is the number of network connections (devices) that this
interface is controlling. IP should call if_get_hwinfo(conn_i) for each
connection, where conn_i is a connection index from 1 to connections.
version allows IP and the interface module to agree upon which version of
this interface they are using. On input, IP sets one or more bits in version
indicating (bit 1 for version 1, bit 2 for version 2) which versions it will
handle. On output IF clears all but one of the bits in version, indicating
which version of this interface will be used. If IP and the IF have no common
version, version will be zero and an error code is returned.
The following flags are defined:
IF_FLAG_NOCOPY Indicates which buffer management scheme this
interface uses.
IF_FLAG_CANSETINFO Indicates that the routing information can be set
with the if_set_hwinfo routine.
if_get_hwinfo (refnum, hwindex, hwid, routing, flags)
-> long refnum; IF reference number
-> long hwindex; Hardware number
<- Ptr hwid; Hardware ID
<- if_routing_t *routing; Routing information
<- unsigned long *flags; Control flags
if_get_hwinfo returns information specific to a network connection. refnum
is the reference number of the IF the client wants to call. hwindex is the
hardware index of the network connection the client wants information on.
The map from indexes to network connections will be consistent during one
boot of the machine.
routing is the address of a routing structure allocated by IP and filled with
information specific to this connection with IF.
hwid is a pointer to some memory that will hold this connection's hardware
ID. The format of the hardware ID is specific to the type of interface and is
intended to be meaningful to people. In general, the hwid will be used by
chooser modules that control the configuration information for network
connections IP can ignore the hardware id by passing a NULL pointer.
Special behavior can be specified with flags. The following flags are
defined:
IF_FLAG_PROXARP Indicates that this network has a default host that
does proxy ARP for hosts on other networks.
IF_FLAG_RIP Indicates that IP should lookup the default host
on this network using the RIP protocol.
if_set_hwinfo (refnum, hwindex, routing)
-> long refnum; IF reference number
-> long hwindex; Hardware number
-> if_routing_t *routing; Routing information
if_set_hwinfo sets the local IP address and routing information for a
network connection. refnum is the reference number of the IF the client wants
to call. hwindex is the hardware index of the network connection the client
wants to set information for. routing points to an if_routing_t structure
that contains the new information.
if_open (refnum, hwindex, input, nextbuf)
-> long refnum; IF reference number
-> long hwindex; Hardware number
-> ProcPtr input; Packet input routine
-> ProcPtr nextbuf; Buffer allocation routine
if_open opens a network connection for packet input/output. refnum is the
reference number of the IF the client wants to call. hwindex is the hardware
index of the network connection the client wants to open. input is the address
of an IP routine that IF can call to deliver packets. nextbuf is the address of
an IP routine that IF can call to allocate packets. The interfaces to (*input)
and (*nextbuf) are defined below.
if_close (refnum, hwindex)
-> long refnum; IF reference number
-> long hwindex; Hardware number
if_close closes a network connection . refnum is the reference number of
the IF the client wants to call. hwindex is the hardware index of the network
connection the client wants to close.
if_control (refnum, hwindex, buffer, buflen, control)
-> long refnum; IF reference number
-> long hwindex; Hardware number
<> Ptr *buffer; Data used by control call
<> unsigned long *buflen; Size of buffer (bytes)
-> unsigned long control; Specifies control operation
if_control performs various operations for an IF. refnum is the reference
number of the IF the client wants to call. hwindex is the hardware index of the
network connection the client wants to control. control selects an operation
and is the only mandatory parameter. Parameters that are not required by
individual control operations may be passed as NULL.
No control operations are currently defined for if_control.
(*output) (hwindex, buffer, buflen, lhost, flags)
-> long hwindex; Hardware number
-> Ptr buffer; Pointer to buffer
-> short buflen; Length of buffer
-> unsigned long fhost; IP address of host to send to
-> long flags; Control flags
(*output) sends a datagram to the IP address specified by fhost. The
address of this routine is returned to the client by if_info. It can not
be called through PBControl.
buffer points to the beginning of the IP packet and buflen contains the
length of the packet. IP must guarante that there will be at least headersz
bytes before *buffer and trailersz bytes after *(buffer+buflen) for IF headers
and trailers. hwindex is the hardware index of the network connection
the client wants send data on. fhost is the IP address of the host this
packet is sent to. If fhost matches the broadcast address returned in
routing, the packet will be broadcast on the local network Unless this
network has a gateway that does proxy ARP, fhost must be on the local area
network (or the boadcast address). fhost need not be the final destination
of the IP packet.
Special behavior can be specified with flags. The following flags are
defined:
IF_FLAG_USEWDS If set, buffer points to a Write Data Structure
and buflen is ignored.
IF_FLAG_BROADCAST If set, the packet will be broadcast on the local
network. In this case fhost is ignored. If the
broadcast address is in fhost this flag is
ignored.
CLIENT-SUPPLIED FUNCTIONS
(*nextbuf) (buffer, headersz, trailersz, maxfragsz)
<- Ptr *buffer; Data used by control call
-> unsigned long headersz; Header space requirements
-> unsigned long trailersz; Trailer space requirements
-> unsigned long maxfragsz; Maximum IP packet size
(*nextbuf) is the client supplied routine IF drivers call to allocate buffers.
headersz, trailersz and maxfragsz indicate how big the buffer should be.
On output, buffer points to a buffer of size maxfragsz + trailersz with at
least headersz writeable bytes before buffer.
If no buffer could be allocated (*nextbuf) should return NULL in buffer
and the proper error code as the function result. The IF will try again later.
Packets will very likely be lost.
(*nextbuf) executes in the IF module's context and should not rely on A5 for
addressing globals or the jump table. This routine may be called from an
interrupt.
(*input) (buffer, buflen, lhost, headersz, flags)
-> Ptr buffer; Buffer
-> unsigned long buflen; Size of buffer (bytes)
-> unsigned long lhost; Delivered to...
-> unsigned long headersz; Header space requirements
-> long flags; Control flags
(*input) is the client supplied routine IF drivers call to deliver packets.
buffer points to a buffer containing an IP packet of length buflen.
If the IF_F_NOCOPY bit of flags is set buffer points to a buffer that was
previously allocated by IF via the nextbuf routine. IP keeps this buffer; IF will
call (*nextbuf) for another. IP should back off from buffer by headersz bytes
to find the beginning of the actual memory block.
If the IF_F_NOCOPY bit of flags is clear (*input) must copy the packet into a
local buffer.
lhost is the IP address of the network connection on which the packet
arrived.
If this packet was broadcast IF_F_BROADCAST bit of flags is set.
(*input) executes in the IF module's context and should not rely on A5 for
addressing globals or the jump table. This routine may be called from an
interrupt.
BUFFER MANAGEMENT
On output (calls to (*output)), clients may pass the address of a buffer
containing the packet or the address of a Write Data Structure, indicating
which with the flags parameter.
If the client is passing a buffer to (*output), the client must ensure that
there are at least headersz writeable bytes before the location *buffer and
trailersz writeable bytes after the location *(buffer + buflen). The
hardware protocols use these for their headers and trailers.
If the client is passing a Write Data Structure to (*output), the client must
insure that there is at least xxx (one) empty entry at the beginning
(wds.wds_index >= 1) and one empty entry at the end. The hardware
protocols use this for their headers and trailers.
On input, the interface module may expect the client to provide buffers to
it or the interface module may have it's own internal buffer.
If the interface module expects the client to provide the buffers, the client
must provide a (*nextbuf) routine which the IF calls to get buffers. The IF
always keeps one buffer ready for the next packet. When a packet arrives, the
IF first allocates another buffer by calling (*nextbuf), then delivers the
packet to the client by calling (*input). (*input) is responsible for
deallocating or reallocating the buffer.
If the interface module keeps it's own buffers (*input) must quickly copy the
packet out of the buffer so that the IF can prepare to receive the next
packet. (*nextbuf) is never called.
ADDRESS RESOLUTION
Address resolution is the translation of IP address to physical network
addresses. All Interface modules are responsible for address resolution .
BROADCASTS
A packet will be broadcast on the local network if either the broadcast flag is
set or fhost is the broadcast address for ths network.
OUTSTANDING ISSUES
I have set the hr_redirect array to be 10 elements, no more. This is not
expandable. If you ever imagine having a network that requires more than 10
initial route statements, speak now.
The buffer schemes, copy and no copy, need a clearer description.