本文主要是介绍GARP(Gratuitous ARP),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
内核函数arp_is_garp判断ARP报文是否为GARP,先决条件是发送者IP和目标IP地址相同,另外,对于ARP回复(REPLAY)报文,要求如果目标硬件地址存在,需要与发送者硬件地址相等。最后,要求ARP报文的发送者IP为单播地址,否则,判定报文不是garp。
static bool arp_is_garp(struct net *net, struct net_device *dev,int *addr_type, __be16 ar_op,__be32 sip, __be32 tip,unsigned char *sha, unsigned char *tha)
{bool is_garp = tip == sip;/* Gratuitous ARP _replies_ also require target hwaddr to be* the same as source.*/if (is_garp && ar_op == htons(ARPOP_REPLY))is_garp =/* IPv4 over IEEE 1394 doesn't provide target* hardware address field in its ARP payload.*/tha &&!memcmp(tha, sha, dev->addr_len);if (is_garp) {*addr_type = inet_addr_type_dev_table(net, dev, sip);if (*addr_type != RTN_UNICAST)is_garp = false;}return is_garp;
如下PROC文件控制对GARP报文的接收,default目录的文件仅在初始化时使用,是否接收GARP,由另外all和网络设备ens33目录下文件确定。
# cat /proc/sys/net/ipv4/conf/all/drop_gratuitous_arp
0
# cat /proc/sys/net/ipv4/conf/default/drop_gratuitous_arp
0
# cat /proc/sys/net/ipv4/conf/ens33/drop_gratuitous_arp
0
在ARP报文处理函数arp_process中,宏IN_DEV_ORCONF对all和网络设备(ens33)设置的drop_gratuitous_arp值进行或操作,如果结果为真,对其此报文。特别是在802.11无线网络环境中,如果存在一个恶意的ARP代理,发送GARP攻击报文,需要开启drop_gratuitous_arp选项。
static int arp_process(struct net *net, struct sock *sk, struct sk_buff *skb)
{bool is_garp = false;/** For some 802.11 wireless deployments (and possibly other networks),* there will be an ARP proxy and gratuitous ARP frames are attacks* and thus should not be accepted.*/if (sip == tip && IN_DEV_ORCONF(in_dev, DROP_GRATUITOUS_ARP))goto out_free_skb;...
如下PROC文件控制对于GARP报文,是否创建邻居表项。如果arp_accept为真,创建新的表项,否则,仅对已有表项进行更新。
# cat /proc/sys/net/ipv4/conf/all/arp_accept
0
# cat /proc/sys/net/ipv4/conf/default/arp_accept
0
# cat /proc/sys/net/ipv4/conf/ens33/arp_accept
0
如果邻居系统已经存在此报文发送者IP对应的邻居信息,或者arp_accept为真,调用函数arp_is_garp判断是否为GARP报文。
/* Update our ARP tables */n = __neigh_lookup(&arp_tbl, &sip, dev, 0);addr_type = -1;if (n || IN_DEV_ARP_ACCEPT(in_dev)) {is_garp = arp_is_garp(net, dev, &addr_type, arp->ar_op,sip, tip, sha, tha);}
如果arp_accept为真,并且确定为GARP报文(is_garp为真),将邻居查找函数__neigh_lookup的最后一个参数设置为1,找不到的情况下创建新的邻居表项。另外,对于非garp报文,如果其为回复(REPLY)报文,并且发送者IP为单播地址,而且发送者IP和目标IP不相等(addr_type<0),也创建新的邻居表项。
if (IN_DEV_ARP_ACCEPT(in_dev)) {/* Unsolicited ARP is not accepted by default.It is possible, that this option should be enabled for somedevices (strip is candidate)*/if (!n &&(is_garp ||(arp->ar_op == htons(ARPOP_REPLY) &&(addr_type == RTN_UNICAST ||(addr_type < 0 &&/* postpone calculation to as late as possible */inet_addr_type_dev_table(net, dev, sip) == RTN_UNICAST)))))n = __neigh_lookup(&arp_tbl, &sip, dev, 1);}
如果邻居表项已经存在,不在进行arp_accept的判断,将邻居表项更新为NUD_REACHABLE状态,但是对于ARP请求报文或者广播回复报文,表项状态设置为NUD_STALE。
if (n) {int state = NUD_REACHABLE;int override;/* If several different ARP replies follows back-to-back,use the FIRST one. It is possible, if several proxyagents are active. Taking the first reply preventsarp trashing and chooses the fastest router.*/override = time_after(jiffies,n->updated + NEIGH_VAR(n->parms, LOCKTIME)) ||is_garp;/* Broadcast replies and request packets do not assert neighbour reachability.*/if (arp->ar_op != htons(ARPOP_REPLY) ||skb->pkt_type != PACKET_HOST)state = NUD_STALE;neigh_update(n, sha, state, override ? NEIGH_UPDATE_F_OVERRIDE : 0, 0);
内核版本 5.0
这篇关于GARP(Gratuitous ARP)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!