概述
arp_process为ARP输入包的核心处理流程;
若输入为ARP请求且查路由成功,则进行如下判断:输入到本地,则进行应答;否则,允许转发,则转发,本文代码不包含转发流程;
若输入为ARP应答或者查路由失败,则更新邻居项;
源码分析
1 static int arp_process(struct net *net, struct sock *sk, struct sk_buff *skb) 2 { 3 struct net_device *dev = skb->dev; 4 struct in_device *in_dev = __in_dev_get_rcu(dev); 5 struct arphdr *arp; 6 unsigned char *arp_ptr; 7 struct rtable *rt; 8 unsigned char *sha; 9 unsigned char *tha = NULL; 10 __be32 sip, tip; 11 u16 dev_type = dev->type; 12 int addr_type; 13 struct neighbour *n; 14 struct dst_entry *reply_dst = NULL; 15 bool is_garp = false; 16 17 /* arp_rcv below verifies the ARP header and verifies the device 18 * is ARP'able. 19 */ 20 /* 获取ip配置块 */ 21 if (!in_dev) 22 goto out_free_skb; 23 24 /* 获取arp头 */ 25 arp = arp_hdr(skb); 26 27 /* 根据设备类型做检查 */ 28 switch (dev_type) { 29 default: 30 if (arp->ar_pro != htons(ETH_P_IP) || 31 htons(dev_type) != arp->ar_hrd) 32 goto out_free_skb; 33 break; 34 case ARPHRD_ETHER: 35 case ARPHRD_FDDI: 36 case ARPHRD_IEEE802: 37 /* 38 * ETHERNET, and Fibre Channel (which are IEEE 802 39 * devices, according to RFC 2625) devices will accept ARP 40 * hardware types of either 1 (Ethernet) or 6 (IEEE 802.2). 41 * This is the case also of FDDI, where the RFC 1390 says that 42 * FDDI devices should accept ARP hardware of (1) Ethernet, 43 * however, to be more robust, we'll accept both 1 (Ethernet) 44 * or 6 (IEEE 802.2) 45 */ 46 if ((arp->ar_hrd != htons(ARPHRD_ETHER) && 47 arp->ar_hrd != htons(ARPHRD_IEEE802)) || 48 arp->ar_pro != htons(ETH_P_IP)) 49 goto out_free_skb; 50 break; 51 case ARPHRD_AX25: 52 if (arp->ar_pro != htons(AX25_P_IP) || 53 arp->ar_hrd != htons(ARPHRD_AX25)) 54 goto out_free_skb; 55 break; 56 case ARPHRD_NETROM: 57 if (arp->ar_pro != htons(AX25_P_IP) || 58 arp->ar_hrd != htons(ARPHRD_NETROM)) 59 goto out_free_skb; 60 break; 61 } 62 63 /* Understand only these message types */ 64 65 /* 操作码不是应答也不是请求 */ 66 if (arp->ar_op != htons(ARPOP_REPLY) && 67 arp->ar_op != htons(ARPOP_REQUEST)) 68 goto out_free_skb; 69 70 /* 71 * Extract fields 72 */ 73 /* 获取arp指针 */ 74 arp_ptr = (unsigned char *)(arp + 1); 75 /* 源mac */ 76 sha = arp_ptr; 77 /* 源ip */ 78 arp_ptr += dev->addr_len; 79 memcpy(&sip, arp_ptr, 4); 80 arp_ptr += 4; 81 82 /* 设备类型 */ 83 switch (dev_type) { 84 #if IS_ENABLED(CONFIG_FIREWIRE_NET) 85 case ARPHRD_IEEE1394: 86 break; 87 #endif 88 default: 89 /* 目的mac */ 90 tha = arp_ptr; 91 arp_ptr += dev->addr_len; 92 } 93 /* 目的ip */ 94 memcpy(&tip, arp_ptr, 4); 95 /* 96 * Check for bad requests for 127.x.x.x and requests for multicast 97 * addresses. If this is one such, delete it. 98 */ 99 /* 目的ip是组播||回环地址但是没有启用route_localnet */ 100 if (ipv4_is_multicast(tip) || 101 (!IN_DEV_ROUTE_LOCALNET(in_dev) && ipv4_is_loopback(tip))) 102 goto out_free_skb; 103 104 /* 105 * For some 802.11 wireless deployments (and possibly other networks), 106 * there will be an ARP proxy and gratuitous ARP frames are attacks 107 * and thus should not be accepted. 108 */ 109 /* 源ip和目的ip相同,设置了免费arp丢包 */ 110 if (sip == tip && IN_DEV_ORCONF(in_dev, DROP_GRATUITOUS_ARP)) 111 goto out_free_skb; 112 113 /* 114 * Special case: We must set Frame Relay source Q.922 address 115 */ 116 /* 设备类型为q.922,则设置源地址为广播地址 */ 117 if (dev_type == ARPHRD_DLCI) 118 sha = dev->broadcast; 119 120 /* 121 * Process entry. The idea here is we want to send a reply if it is a 122 * request for us or if it is a request for someone else that we hold 123 * a proxy for. We want to add an entry to our cache if it is a reply 124 * to us or if it is a request for our address. 125 * (The assumption for this last is that if someone is requesting our 126 * address, they are probably intending to talk to us, so it saves time 127 * if we cache their address. Their address is also probably not in 128 * our cache, since ours is not in their cache.) 129 * 130 * Putting this another way, we only care about replies if they are to 131 * us, in which case we add them to the cache. For requests, we care 132 * about those for us and those for our proxies. We reply to both, 133 * and in the case of requests for us we add the requester to the arp 134 * cache. 135 */ 136 137 if (arp->ar_op == htons(ARPOP_REQUEST) && skb_metadata_dst(skb)) 138 reply_dst = (struct dst_entry *) 139 iptunnel_metadata_reply(skb_metadata_dst(skb), 140 GFP_ATOMIC); 141 142 /* Special case: IPv4 duplicate address detection packet (RFC2131) */ 143 /* 源ip为0,用于检测地址冲突 */ 144 if (sip == 0) { 145 /* ARP请求 && 地址是本地地址 && 不忽略该ARP请求,则发送ARP应答 */ 146 if (arp->ar_op == htons(ARPOP_REQUEST) && 147 inet_addr_type_dev_table(net, dev, tip) == RTN_LOCAL && 148 !arp_ignore(in_dev, sip, tip)) 149 arp_send_dst(ARPOP_REPLY, ETH_P_ARP, sip, dev, tip, 150 sha, dev->dev_addr, sha, reply_dst); 151 goto out_consume_skb; 152 } 153 154 /* ARP请求 && 查路由成功 */ 155 if (arp->ar_op == htons(ARPOP_REQUEST) && 156 ip_route_input_noref(skb, tip, sip, 0, dev) == 0) { 157 158 /* 获取路由缓存 */ 159 rt = skb_rtable(skb); 160 addr_type = rt->rt_type; 161 162 /* 输入到本地 */ 163 if (addr_type == RTN_LOCAL) { 164 int dont_send; 165 166 /* 忽略检查 */ 167 dont_send = arp_ignore(in_dev, sip, tip); 168 169 /* 不忽略,配置了过滤,则判断过滤 */ 170 if (!dont_send && IN_DEV_ARPFILTER(in_dev)) 171 dont_send = arp_filter(sip, tip, dev); 172 /* 允许输入 */ 173 if (!dont_send) { 174 /* 查找邻居项,更新状态 */ 175 n = neigh_event_ns(&arp_tbl, sha, &sip, dev); 176 177 /* 邻居项存在,则回复ARP应答 */ 178 if (n) { 179 arp_send_dst(ARPOP_REPLY, ETH_P_ARP, 180 sip, dev, tip, sha, 181 dev->dev_addr, sha, 182 reply_dst); 183 neigh_release(n); 184 } 185 } 186 goto out_consume_skb; 187 } else if (IN_DEV_FORWARD(in_dev)) { 188 /* ARP代理 */ 189 } 190 } 191 192 /* ARP应答或者查路由失败 */ 193 194 /* Update our ARP tables */ 195 /* 查找邻居项 */ 196 n = __neigh_lookup(&arp_tbl, &sip, dev, 0); 197 198 addr_type = -1; 199 /* 邻居项存在,或者启用了接收非请求应答 */ 200 if (n || IN_DEV_ARP_ACCEPT(in_dev)) { 201 /* 检查是否为免费ARP */ 202 is_garp = arp_is_garp(net, dev, &addr_type, arp->ar_op, 203 sip, tip, sha, tha); 204 } 205 206 /* 启用了接收非请求应答 */ 207 if (IN_DEV_ARP_ACCEPT(in_dev)) { 208 /* Unsolicited ARP is not accepted by default. 209 It is possible, that this option should be enabled for some 210 devices (strip is candidate) 211 */ 212 /* 213 邻居项不存在,免费ARP || 邻居项不存在,不是免费ARP,则类型为应答,且为单播 214 创建邻居项 215 */ 216 if (!n && 217 (is_garp || 218 (arp->ar_op == htons(ARPOP_REPLY) && 219 (addr_type == RTN_UNICAST || 220 (addr_type < 0 && 221 /* postpone calculation to as late as possible */ 222 inet_addr_type_dev_table(net, dev, sip) == 223 RTN_UNICAST))))) 224 n = __neigh_lookup(&arp_tbl, &sip, dev, 1); 225 } 226 227 /* 存在邻居表项 */ 228 if (n) { 229 int state = NUD_REACHABLE; 230 int override; 231 232 /* If several different ARP replies follows back-to-back, 233 use the FIRST one. It is possible, if several proxy 234 agents are active. Taking the first reply prevents 235 arp trashing and chooses the fastest router. 236 */ 237 /* 当前时间超过了下次更新时间 或者 为免费ARP */ 238 override = time_after(jiffies, 239 n->updated + 240 NEIGH_VAR(n->parms, LOCKTIME)) || 241 is_garp; 242 243 /* Broadcast replies and request packets 244 do not assert neighbour reachability. 245 */ 246 /* 不是ARP应答,或者不是本机包,设置状态为STALE */ 247 if (arp->ar_op != htons(ARPOP_REPLY) || 248 skb->pkt_type != PACKET_HOST) 249 state = NUD_STALE; 250 /* 更新邻居项 */ 251 neigh_update(n, sha, state, 252 override ? NEIGH_UPDATE_F_OVERRIDE : 0, 0); 253 neigh_release(n); 254 } 255 256 out_consume_skb: 257 consume_skb(skb); 258 259 out_free_dst: 260 dst_release(reply_dst); 261 return NET_RX_SUCCESS; 262 263 out_free_skb: 264 kfree_skb(skb); 265 return NET_RX_DROP; 266 }