概述
arp_rcv是ARP包的入口函数,ARP模块在二层注册了类型为ETH_P_ARP的数据包回调函数arp_rcv,当收到ARP包时,二层进行分发,调用arp_rcv;
arp_rcv对ARP输入包的合法性进行检查,然后经过netfilter的ARP_IN钩子点,之后调用arp_process处理输出包;
源码分析
1 /* 2 * Called once on startup. 3 */ 4 5 static struct packet_type arp_packet_type __read_mostly = { 6 .type = cpu_to_be16(ETH_P_ARP), 7 .func = arp_rcv, 8 };
1 /* 2 * Receive an arp request from the device layer. 3 */ 4 5 static int arp_rcv(struct sk_buff *skb, struct net_device *dev, 6 struct packet_type *pt, struct net_device *orig_dev) 7 { 8 const struct arphdr *arp; 9 10 /* do not tweak dropwatch on an ARP we will ignore */ 11 /* 不支持ARP,非本机包,回环包,不处理 */ 12 if (dev->flags & IFF_NOARP || 13 skb->pkt_type == PACKET_OTHERHOST || 14 skb->pkt_type == PACKET_LOOPBACK) 15 goto consumeskb; 16 17 /* skb如果是共享的,则克隆一个 */ 18 skb = skb_share_check(skb, GFP_ATOMIC); 19 if (!skb) 20 goto out_of_mem; 21 22 /* ARP header, plus 2 device addresses, plus 2 IP addresses. */ 23 /* 检查arp包完整性 */ 24 if (!pskb_may_pull(skb, arp_hdr_len(dev))) 25 goto freeskb; 26 27 /* 获取arp头 */ 28 arp = arp_hdr(skb); 29 30 /* 地址长度和协议长度检查 */ 31 if (arp->ar_hln != dev->addr_len || arp->ar_pln != 4) 32 goto freeskb; 33 34 /* 清空neighCB */ 35 memset(NEIGH_CB(skb), 0, sizeof(struct neighbour_cb)); 36 37 /* 经过NF的ARP_IN钩子点,然后调用arp_process */ 38 return NF_HOOK(NFPROTO_ARP, NF_ARP_IN, 39 dev_net(dev), NULL, skb, dev, NULL, 40 arp_process); 41 42 consumeskb: 43 consume_skb(skb); 44 return NET_RX_SUCCESS; 45 freeskb: 46 kfree_skb(skb); 47 out_of_mem: 48 return NET_RX_DROP; 49 }