[comp.protocols.appletalk] IF Beta specification

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.