8.  Protocol/protocol interface

      The interface between protocol modules is through the pr_usrreq, pr_input, pr_output, pr_ctlinput, and pr_ctloutput routines. The calling conventions for all but the pr_usrreq routine are expected to be specific to the protocol modules and are not guaranteed to be consistent across protocol families. We will examine the conventions used for some of the Internet protocols in this section as an example.

8.1.  pr_output

      The Internet protocol UDP uses the convention,

error = udp_output(inp, m);
int error; struct inpcb *inp; struct mbuf *m;
where the inp, ``internet protocol control block'', passed between modules conveys per connection state information, and the mbuf chain contains the data to be sent. UDP performs consistency checks, appends its header, calculates a checksum, etc. before passing the packet on. UDP is based on the Internet Protocol, IP [Postel81a], as its transport. UDP passes a packet to the IP module for output as follows:
error = ip_output(m, opt, ro, flags);
int error; struct mbuf *m, *opt; struct route *ro; int flags;

      The call to IP's output routine is more complicated than that for UDP, as befits the additional work the IP module must do. The m parameter is the data to be sent, and the opt parameter is an optional list of IP options which should be placed in the IP packet header. The ro parameter is is used in making routing decisions (and passing them back to the caller for use in subsequent calls). The final parameter, flags contains flags indicating whether the user is allowed to transmit a broadcast packet and if routing is to be performed. The broadcast flag may be inconsequential if the underlying hardware does not support the notion of broadcasting.

      All output routines return 0 on success and a UNIX error number if a failure occurred which could be detected immediately (no buffer space available, no route to destination, etc.).

8.2.  pr_input

      Both UDP and TCP use the following calling convention,

(void) (*protosw[].pr_input)(m, ifp);
struct mbuf *m; struct ifnet *ifp;
Each mbuf list passed is a single packet to be processed by the protocol module. The interface from which the packet was received is passed as the second parameter.

      The IP input routine is a VAX software interrupt level routine, and so is not called with any parameters. It instead communicates with network interfaces through a queue, ipintrq, which is identical in structure to the queues used by the network interfaces for storing packets awaiting transmission. The software interrupt is enabled by the network interfaces when they place input data on the input queue.

8.3.  pr_ctlinput

      This routine is used to convey ``control'' information to a protocol module (i.e. information which might be passed to the user, but is not data).

      The common calling convention for this routine is,

(void) (*protosw[].pr_ctlinput)(req, addr);
int req; struct sockaddr *addr;
The req parameter is one of the following,
#define	PRC_IFDOWN	0	/* interface transition */
#define	PRC_ROUTEDEAD	1	/* select new route if possible */
#define	PRC_QUENCH	4	/* some said to slow down */
#define	PRC_MSGSIZE	5	/* message size forced drop */
#define	PRC_HOSTDEAD	6	/* normally from IMP */
#define	PRC_HOSTUNREACH	7	/* ditto */
#define	PRC_UNREACH_NET	8	/* no route to network */
#define	PRC_UNREACH_HOST	9	/* no route to host */
#define	PRC_UNREACH_PROTOCOL	10	/* dst says bad protocol */
#define	PRC_UNREACH_PORT	11	/* bad port # */
#define	PRC_UNREACH_NEEDFRAG	12	/* IP_DF caused drop */
#define	PRC_UNREACH_SRCFAIL	13	/* source route failed */
#define	PRC_REDIRECT_NET	14	/* net routing redirect */
#define	PRC_REDIRECT_HOST	15	/* host routing redirect */
#define	PRC_REDIRECT_TOSNET	14	/* redirect for type of service & net */
#define	PRC_REDIRECT_TOSHOST	15	/* redirect for tos & host */
#define	PRC_TIMXCEED_INTRANS	18	/* packet lifetime expired in transit */
#define	PRC_TIMXCEED_REASS	19	/* lifetime expired on reass q */
#define	PRC_PARAMPROB	20	/* header incorrect */
while the addr parameter is the address to which the condition applies. Many of the requests have obviously been derived from ICMP (the Internet Control Message Protocol [Postel81c]), and from error messages defined in the 1822 host/IMP convention [BBN78]. Mapping tables exist to convert control requests to UNIX error codes which are delivered to a user.

8.4.  pr_ctloutput

      This is the routine that implements per-socket options at the protocol level for getsockopt and setsockopt. The calling convention is,

error = (*protosw[].pr_ctloutput)(op, so, level, optname, mp);
int op; struct socket *so; int level, optname; struct mbuf **mp;
where op is one of PRCO_SETOPT or PRCO_GETOPT, so is the socket from whence the call originated, and level and optname are the protocol level and option name supplied by the user. The results of a PRCO_GETOPT call are returned in an mbuf whose address is placed in mp before return. On a PRCO_SETOPT call, mp contains the address of an mbuf containing the option data; the mbuf should be freed before return.