概述
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 }