A raw socket is an object which allows users direct access to a lower-level protocol. Raw sockets are intended for knowledgeable processes which wish to take advantage of some protocol feature not directly accessible through the normal interface, or for the development of new protocols built atop existing lower level protocols. For example, a new version of TCP might be developed at the user level by utilizing a raw IP socket for delivery of packets. The raw IP socket interface attempts to provide an identical interface to the one a protocol would have if it were resident in the kernel.
The raw socket support is built around a generic raw socket interface, (possibly) augmented by protocol-specific processing routines. This section will describe the core of the raw socket interface.
Every raw socket has a protocol control block of the following form:
struct rawcb { struct rawcb *rcb_next; /* doubly linked list */ struct rawcb *rcb_prev; struct socket *rcb_socket; /* back pointer to socket */ struct sockaddr rcb_faddr; /* destination address */ struct sockaddr rcb_laddr; /* socket's address */ struct sockproto rcb_proto; /* protocol family, protocol */ caddr_t rcb_pcb; /* protocol specific stuff */ struct mbuf *rcb_options; /* protocol specific options */ struct route rcb_route; /* routing information */ short rcb_flags; };
A raw socket interface is datagram oriented. That is, each send or receive on the socket requires a destination address. This address may be supplied by the user or stored in the control block and automatically installed in the outgoing packet by the output routine. Since it is not possible to determine whether an address is present or not in the control block, two flags, RAW_LADDR and RAW_FADDR, indicate if a local and foreign address are present. Routing is expected to be performed by the underlying protocol if necessary.
Input packets are ``assigned'' to raw sockets based on a simple pattern matching scheme. Each network interface or protocol gives unassigned packets to the raw input routine with the call:
raw_input(m, proto, src, dst) struct mbuf *m; struct sockproto *proto, struct sockaddr *src, *dst;
struct raw_header { struct sockproto raw_proto; struct sockaddr raw_dst; struct sockaddr raw_src; };
A basic assumption is that addresses present in the control block and packet header (as constructed by the network interface and any raw input protocol module) are in a canonical form which may be ``block compared''.
On output the raw pr_usrreq routine
passes the packet and a pointer to the raw control block to the
raw protocol output routine for any processing required before
it is delivered to the appropriate network interface. The
output routine is normally the only code required to implement
a raw socket interface.