[comp.protocols.appletalk] IF specification

saf@CITI.UMICH.EDU (10/06/87)

				IF DRIVER INTERFACE SPECIFICATION (Beta Draft  10/6/87)



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 union if_addrrange {
		struct if_num_mask {		/* Address range specified by */
			unsigned long	netnumber;	/*   Netnumber and */
			unsigned long	netmask;	/*   Netmask */
		} nm;
		struct if_start_end {		/* Address range specified by */
			unsigned long	start;	/*   Start and */
			unsigned long	end;	/*   End */
		} se;
	} if_addrrange_t, *if_addrrange_p;

	typedef struct if_redirect {	/* IF redirect array element */
		unsigned short	rd_rtype;		/* Range specification 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.*/
		unsigned short	hr_rtype;		/* Range specification format */
		if_addrrange_t	hr_range;		/* Address range */
		unsigned long	hr_broadaddr;	/* Broadcast address */
		unsigned long	hr_default;		/* Default route */
		unsigned short	hr_cost;		/* Relative 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) (name, refnum, 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.

Special behavior can be specified with flags.  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	lhost;		IP address of network connection
	->	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.

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 does not have to 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 not set, buffer points to the beginning of the IP 
						packet and buflen contains the length of the packet.  In this 
						case, IP must guarante that there will be at least headersz 
						bytes before *buffer and trailersz bytes after 
						*(buffer+buflen) for IF headers and trailers.

	IF_FLAG_BROADCAST	If set, the packet will be broadcast on the local network.  In 
						this case fhost is ignored.  Alternatly, 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;	Data used by control call
	->	unsigned long	*buflen;	Size of buffer (bytes)
	->	unsigned long	lhost;		Header space requirements
	->	unsigned long	headersz;	Trailer 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 can 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 insure 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.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 interface module must 
provide nextbuf routine which the IF call 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).  Since the 
packet is in a buffer that IF got from the client and IF has already allocated another buffer, 
(*input) keeps the buffer that the packet is in.

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.