1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
| /**
* arp_rcv - ARP数据包接收处理
* @skb: 接收到的数据包
* @dev: 接收设备
* @pt: 数据包类型结构
* @orig_dev: 原始设备
*
* 处理接收到的ARP数据包
* 返回值:NET_RX_SUCCESS表示成功处理
*/
static int arp_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt, struct net_device *orig_dev)
{
const struct arphdr *arp;
/* 检查数据包合法性 */
if (dev->flags & IFF_NOARP)
goto freeskb;
if (!pskb_may_pull(skb, arp_hdr_len(dev)))
goto freeskb;
arp = arp_hdr(skb);
/* 检查ARP头部有效性 */
if (arp->ar_hln != dev->addr_len ||
arp->ar_pln != 4 ||
arp->ar_pro != htons(ETH_P_IP) ||
arp->ar_hrd != htons(dev->type))
goto freeskb;
/* 确保数据包足够长 */
if (!pskb_may_pull(skb, sizeof(struct arphdr) +
(2 * (dev->addr_len + sizeof(u32)))))
goto freeskb;
/* 处理ARP请求和应答 */
return arp_process(dev_net(dev), NULL, skb);
freeskb:
kfree_skb(skb);
return NET_RX_DROP;
}
/**
* arp_process - ARP数据包核心处理函数
* @net: 网络命名空间
* @sock: 套接字(通常为NULL)
* @skb: ARP数据包
*
* 处理ARP请求和应答数据包的核心逻辑
*/
static int arp_process(struct net *net, struct sock *sk, struct sk_buff *skb)
{
struct net_device *dev = skb->dev;
struct in_device *in_dev = __in_dev_get_rcu(dev);
struct arphdr *arp;
unsigned char *arp_ptr;
struct rtable *rt;
unsigned char *sha; /* 发送方硬件地址 */
unsigned char *tha; /* 目标硬件地址 */
__be32 sip, tip; /* 发送方IP,目标IP */
u16 dev_type = dev->type;
int addr_type;
struct neighbour *n;
struct dst_entry *dst = NULL;
if (!in_dev)
goto out;
arp = arp_hdr(skb);
switch (dev_type) {
default:
if (arp->ar_pro != htons(ETH_P_IP) ||
htons(dev_type) != arp->ar_hrd)
goto out;
break;
case ARPHRD_ETHER:
case ARPHRD_FDDI:
case ARPHRD_IEEE802:
/*
* 以太网(10Mb)
* FDDI
* IEEE 802网络
*/
if (arp->ar_pro != htons(ETH_P_IP) ||
arp->ar_hrd != htons(ARPHRD_ETHER))
goto out;
break;
case ARPHRD_AX25:
if (arp->ar_pro != htons(AX25_P_IP) ||
arp->ar_hrd != htons(ARPHRD_AX25))
goto out;
break;
case ARPHRD_NETROM:
if (arp->ar_pro != htons(AX25_P_IP) ||
arp->ar_hrd != htons(ARPHRD_NETROM))
goto out;
break;
}
/* 解析ARP数据包内容 */
arp_ptr = (unsigned char *)(arp + 1);
sha = arp_ptr; /* 发送方硬件地址 */
arp_ptr += dev->addr_len;
memcpy(&sip, arp_ptr, 4); /* 发送方IP地址 */
arp_ptr += 4;
tha = arp_ptr; /* 目标硬件地址 */
arp_ptr += dev->addr_len;
memcpy(&tip, arp_ptr, 4); /* 目标IP地址 */
/*
* 检查是否为我们的地址
*/
if (tip == sip && inet_addr_type_dev_table(net, dev, sip) == RTN_LOCAL) {
/* 自己给自己发ARP,忽略 */
goto out;
}
if (arp->ar_op == htons(ARPOP_REQUEST) &&
ip_route_input_noref(skb, tip, sip, 0, dev) == 0) {
rt = skb_rtable(skb);
addr_type = rt->rt_type;
if (addr_type == RTN_LOCAL) {
int dont_send;
dont_send = arp_ignore(in_dev, sip, tip);
if (!dont_send && IN_DEV_ARPFILTER(in_dev))
dont_send = arp_filter(sip, tip, dev);
if (!dont_send) {
n = neigh_event_ns(&arp_tbl, sha, &sip, dev);
if (n) {
arp_send_dst(ARPOP_REPLY, ETH_P_ARP,
sip, dev, tip, sha,
dev->dev_addr, sha, dst);
neigh_release(n);
}
}
goto out;
} else if (IN_DEV_FORWARD(in_dev)) {
if (addr_type == RTN_UNICAST &&
(arp_fwd_proxy(in_dev, dev, rt) ||
arp_fwd_pvlan(in_dev, dev, rt, sip, tip) ||
(rt->dst.dev != dev &&
pneigh_lookup(&arp_tbl, net, &tip, dev, 0)))) {
n = neigh_event_ns(&arp_tbl, sha, &sip, dev);
if (n)
neigh_release(n);
if (NEIGH_CB(skb)->flags & LOCALLY_ENQUEUED ||
skb->pkt_type == PACKET_HOST ||
NEIGH_VAR(in_dev->arp_parms, PROXY_DELAY) == 0) {
arp_send_dst(ARPOP_REPLY, ETH_P_ARP,
sip, dev, tip, sha,
dev->dev_addr, sha, dst);
} else {
pneigh_enqueue(&arp_tbl, in_dev->arp_parms, skb);
goto out_consume_skb;
}
goto out;
}
}
}
/* 更新发送方的ARP缓存条目 */
n = __neigh_lookup(&arp_tbl, &sip, dev, 0);
if (IN_DEV_ARP_ACCEPT(in_dev)) {
addr_type = inet_addr_type_dev_table(net, dev, sip);
if (addr_type == RTN_UNICAST)
n = __neigh_lookup(&arp_tbl, &sip, dev, 1);
}
if (n) {
int state = NUD_REACHABLE;
int override;
/* 如果地址来源被覆盖或者我们没有地址,使用应答地址 */
override = time_after(jiffies,
n->updated + NEIGH_VAR(n->parms, LOCKTIME)) ||
is_garp;
/* 确认此地址 */
if (n->nud_state == NUD_INCOMPLETE) {
if (skb && arp->ar_op == htons(ARPOP_REPLY))
neigh_update(n, sha, state,
override ? NEIGH_UPDATE_F_OVERRIDE : 0, 0);
} else {
neigh_update(n, sha, state,
override ? NEIGH_UPDATE_F_OVERRIDE : 0, 0);
}
neigh_release(n);
}
out:
consume_skb(skb);
return NET_RX_SUCCESS;
out_consume_skb:
consume_skb(skb);
return NET_RX_SUCCESS;
}
/**
* arp_send_dst - 发送ARP数据包
* @type: ARP操作类型
* @ptype: 包类型
* @dest_ip: 目标IP地址
* @dev: 发送设备
* @src_ip: 源IP地址
* @dest_hw: 目标硬件地址
* @src_hw: 源硬件地址
* @target_hw: 目标硬件地址(在ARP头部中)
* @dst: 目标路由
*/
static void arp_send_dst(int type, int ptype, __be32 dest_ip,
struct net_device *dev, __be32 src_ip,
const unsigned char *dest_hw,
const unsigned char *src_hw,
const unsigned char *target_hw,
struct dst_entry *dst)
{
struct sk_buff *skb;
/* 分配sk_buff */
skb = arp_create(type, ptype, dest_ip, dev, src_ip,
dest_hw, src_hw, target_hw);
if (!skb)
return;
skb_dst_set(skb, dst_clone(dst));
arp_xmit(skb);
}
/**
* arp_create - 创建ARP数据包
* @type: ARP操作类型
* @ptype: 以太网协议类型
* @dest_ip: 目标IP地址
* @dev: 发送设备
* @src_ip: 源IP地址
* @dest_hw: 目标硬件地址
* @src_hw: 源硬件地址
* @target_hw: ARP目标硬件地址
*
* 创建一个ARP数据包
* 返回值:成功返回sk_buff指针,失败返回NULL
*/
static struct sk_buff *arp_create(int type, int ptype, __be32 dest_ip,
struct net_device *dev, __be32 src_ip,
const unsigned char *dest_hw,
const unsigned char *src_hw,
const unsigned char *target_hw)
{
struct sk_buff *skb;
struct arphdr *arp;
unsigned char *arp_ptr;
int hlen = LL_RESERVED_SPACE(dev);
int tlen = dev->needed_tailroom;
/*
* 分配缓冲区
*/
skb = alloc_skb(arp_hdr_len(dev) + hlen + tlen, GFP_ATOMIC);
if (!skb)
return NULL;
skb_reserve(skb, hlen);
skb_reset_network_header(skb);
arp = (struct arphdr *)skb_put(skb, arp_hdr_len(dev));
skb->dev = dev;
skb->protocol = htons(ETH_P_ARP);
if (!src_hw)
src_hw = dev->dev_addr;
if (!dest_hw)
dest_hw = dev->broadcast;
/*
* 填充ARP头部
*/
if (dev_hard_header(skb, dev, ptype, dest_hw, src_hw, skb->len) < 0)
goto out;
/*
* 填充ARP操作码等字段
*/
arp->ar_hrd = htons(dev->type);
arp->ar_pro = htons(ETH_P_IP);
arp->ar_hln = dev->addr_len;
arp->ar_pln = 4;
arp->ar_op = htons(type);
arp_ptr = (unsigned char *)(arp + 1);
/* 发送方硬件地址 */
memcpy(arp_ptr, src_hw, dev->addr_len);
arp_ptr += dev->addr_len;
/* 发送方协议地址 */
memcpy(arp_ptr, &src_ip, 4);
arp_ptr += 4;
/* 目标硬件地址 */
if (target_hw)
memcpy(arp_ptr, target_hw, dev->addr_len);
else
memset(arp_ptr, 0, dev->addr_len);
arp_ptr += dev->addr_len;
/* 目标协议地址 */
memcpy(arp_ptr, &dest_ip, 4);
return skb;
out:
kfree_skb(skb);
return NULL;
}
|