This chapter describes the programming interface for creating interface filters, which are associated with a particular network interface, as shown in Figure 6-1.
Interface Filter Functions and Callbacks
An interface filter defines the following callbacks:
iff_input_func, which is used to process packets after they are demuxed.
iff_output_func, which is used to process packets before they are sent out from an interface to a network.
iff_event_func, which is used to filter events specific to an interface.
iff_ioctl_func, which is used to filter ioctls sent to an interface. All undefined ioctls are reserved for future Apple use. You should use
kern_controlif you need to add additional control mechanisms.
iff_detached_func, which is called when your filter is detached from an interface. When this callback is called, you should perform any cleanup related to the interface. If this is called as a result of the interface itself being detached, it will occur after you receive the interface detach notification.
To attach and detach an interface filter, the following functions are defined by the interface filter KPI:
There are a number of surprises that you may run into when writing an interface filter. Several of these follow:
- Packet injection
When your filter injects packets, it should use the
ifnet_output_rawfunctions. If you do this, your filter should be prepared to ignore the packet it just injected, as your filter’s
iff_output_funccallback will see this packet again immediately. You should use the
mbuf_tag_allocate, for example) to track these packets. If multiple filters are swallowing and reinjecting packets, you may see a given packet multiple times.
Note: When reinjecting packets, the filter must ensure that the packet header field is set in the first mbuf structure. Otherwise, the call to
ifnet_inputwill result in a kernel panic (
iff_input_funccallback is called, you may find that the
packet_headerfield has been set to
iff_input_funccan be used to set the
packet_headerfield if the packet must be reinjected. To do this, use the
mbuf_pkthdr_setheaderfunction to set the
packet_headerfield in the mbuf.
iff_input_funccallback does not swallow a packet, it is not necessary to set the
- Input callbacks: Header pointers and mbufs
Your filter’s input callback receives an mbuf pointer to the packet contents and a separate header pointer. The header pointer references the link-layer header, as defined by the relevant interface.
For most interfaces, the length of this header can be determined by inspecting the header length (
ifnet_hdrlen) defined by the interface. For some interfaces, however, such as PPP, the header length is variable.
- Output callbacks: Header pointers and mbufs
Your filter’s output callback receives the entire packet in the mbuf chain. To get the protocol layer information, your filter must know how to parse the link-layer header. For this reason, if you are writing a filter that needs to work with IP packets, you should consider writing an IP filter unless it is absolutely necessary to access link-layer information.