Int ip_rcv (struct sk_buff * SKB, struct net_device * Dev, struct packet_type * PT)
// Several structures: sk_buff socket cache. The net_device network device structure is the basic data structure of all network structures.
, Packet_type prototype
Struct packet_type
{
Unsigned short type;/* this is really htons (ether_type ).*/
Struct net_device * dev;/* null is wildcarded here */
INT (* func) (struct sk_buff *, struct net_device *,
Struct packet_type *);
Void * data;/* private to the packet type */
Struct packet_type * next;
};
{
Struct iphdr * IPH;
// Structure pointer pointing to the IP protocol header
/* When the interface is in promisc. mode, drop all the crap
* That it has es, do not try to analyze it.
*/
If (SKB-> pkt_type = packet_otherhost)
Goto drop;
// Pkt_type indicates the message type. Packet_otherhost indicates the packets that are not sent to the local machine but are accepted in a specific mode.
// The purpose here is to discard packets not going to the local path based on the package type.
Ip_inc_stats_bh (ipinreceives );
If (SKB = skb_share_check (SKB, gfp_atomic) = NULL)
Goto out;
/* Skb_share_check is defined in Linux/skbuff. H. If users is one, false is returned, and others return true.
[
Static inline struct sk_buff * skb_0000_check (struct sk_buff * SKB, int PRI)
{
If (skb_shared (SKB )){
Struct sk_buff * nskb;
Nskb = skb_clone (SKB, PRI); // a cloned socket cache is returned.
Kfree_skb (SKB); // free an skbuff
Return nskb;
}
Return SKB;
}
]
# Define gfp_atomic (_ gfp_high)
# DEFINE _ gfp_high 0x20
*/
Note: The prototype of skb_clone is struct sk_buff * skb_clone (struct sk_buff * SKB, int gfp_mask)
Gfp_mask: get_free_pages mask, passed to alloc_skb
If (! Pskb_may_pull (SKB, sizeof (struct iphdr )))
Goto inhdr_error;
//
Static inline int pskb_may_pull (struct sk_buff * SKB, unsigned int Len)
{
If (LEN <= skb_headlen (SKB ))
Return 1;
If (LEN> SKB-> Len)
Return 0;
Return (_ pskb_pull_tail (SKB, len-skb_headlen (SKB ))! = NULL );
}
Before calling skb_pull () to remove the outer protocol header, pskb_may_pull usually calls this function to determine whether there is enough data for "pull ".
If the linear buffer is pull enough, 1 is returned;
If pull data exceeds SKB-> Len, 0 is returned;
Finally, call _ pskb_pull_tail () to check whether the page buffer has enough data for pull.
*/
IPH = SKB-> NH. iph;
/*
* Rfc1122: 3.1.2.2 must silently discard any IP frame that fails the checksum.
*
* Is the datax acceptable?
*
* 1. length at least the size of an IP Header
* 2. version of 4
* 3. checksums correctly. [speed optimisation for later, skip loopback checksums]
* 4. doesn' t have a bogus Length
*/
If (IPH-> IHL <5 | IPH-> version! = 4)
Goto inhdr_error;
// IPH-> IHL <5 description IPH-> IHL refers to the length of the IP packet header. The first line is 32bit, which is 4 bytes. Note: 1 byte = 8 bit, byte is the smallest file in the computer.
Unit. The value of the header length (excluding any options) of a common IP packet is 5.
If (! Pskb_may_pull (SKB, IPH-> IHL * 4 ))
Goto inhdr_error;
// IPH-> IHL * 4 is 20, which is the longest length of the header. This statement indicates that if the header length cannot be pull, an error occurs.
IPH = SKB-> NH. iph;
If (ip_fast_csum (u8 *) IPH, IPH-> IHL )! = 0)
Goto inhdr_error;
// Use assembly for checksum
{
_ U32 Len = ntohs (IPH-> tot_len );
If (SKB-> Len <Len | Len <(IPH-> IHL <2 ))
Goto inhdr_error;
/* Our transport medium may have padded the Buffer out. Now we know it
* Is IP we can trim to the true length of the frame.
* Note this now means SKB-> Len holds ntohs (IPH-> tot_len ).
*/
If (SKB-> Len ){
_ Pskb_trim (SKB, Len );
If (SKB-> ip_summed = checksum_hw)
SKB-> ip_summed = checksum_none;
}
}
Return nf_hook (pf_inet, NF_IP_PRE_ROUTING, SKB, Dev, null,
Ip_rcv_finish );
Inhdr_error:
Ip_inc_stats_bh (ipinhdrerrors );
Drop:
Kfree_skb (SKB );
Out:
Return net_rx_drop;
}