Blame view

net/ipv4/arp.c 34.8 KB
f30c22695   Uwe Zeisberger   fix file specific...
1
  /* linux/net/ipv4/arp.c
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3
4
5
6
7
8
9
10
11
12
13
14
15
   * Copyright (C) 1994 by Florian  La Roche
   *
   * This module implements the Address Resolution Protocol ARP (RFC 826),
   * which is used to convert IP addresses (or in the future maybe other
   * high-level addresses) into a low-level hardware address (like an Ethernet
   * address).
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public License
   * as published by the Free Software Foundation; either version
   * 2 of the License, or (at your option) any later version.
   *
   * Fixes:
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
16
   *		Alan Cox	:	Removed the Ethernet assumptions in
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
17
   *					Florian's code
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
18
   *		Alan Cox	:	Fixed some small errors in the ARP
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
   *					logic
   *		Alan Cox	:	Allow >4K in /proc
   *		Alan Cox	:	Make ARP add its own protocol entry
   *		Ross Martin     :       Rewrote arp_rcv() and arp_get_info()
   *		Stephen Henson	:	Add AX25 support to arp_get_info()
   *		Alan Cox	:	Drop data when a device is downed.
   *		Alan Cox	:	Use init_timer().
   *		Alan Cox	:	Double lock fixes.
   *		Martin Seine	:	Move the arphdr structure
   *					to if_arp.h for compatibility.
   *					with BSD based programs.
   *		Andrew Tridgell :       Added ARP netmask code and
   *					re-arranged proxy handling.
   *		Alan Cox	:	Changed to use notifiers.
   *		Niibe Yutaka	:	Reply for this device or proxies only.
   *		Alan Cox	:	Don't proxy across hardware types!
   *		Jonathan Naylor :	Added support for NET/ROM.
   *		Mike Shaver     :       RFC1122 checks.
   *		Jonathan Naylor :	Only lookup the hardware address for
   *					the correct hardware type.
   *		Germano Caronni	:	Assorted subtle races.
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
40
   *		Craig Schlenter :	Don't modify permanent entry
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41
42
43
   *					during arp_rcv.
   *		Russ Nelson	:	Tidied up a few bits.
   *		Alexey Kuznetsov:	Major changes to caching and behaviour,
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
44
   *					eg intelligent arp probing and
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45
46
47
48
49
50
   *					generation
   *					of host down events.
   *		Alan Cox	:	Missing unlock in device events.
   *		Eckes		:	ARP ioctl control errors.
   *		Alexey Kuznetsov:	Arp free fix.
   *		Manuel Rodriguez:	Gratuitous ARP.
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
51
   *              Jonathan Layes  :       Added arpd support through kerneld
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
52
53
54
55
56
57
   *                                      message queue (960314)
   *		Mike Shaver	:	/proc/sys/net/ipv4/arp_* support
   *		Mike McLagan    :	Routing by source
   *		Stuart Cheshire	:	Metricom and grat arp fixes
   *					*** FOR 2.1 clean this up ***
   *		Lawrence V. Stefani: (08/12/96) Added FDDI support.
deffd7775   Changli Gao   net: arp: code cl...
58
   *		Alan Cox	:	Took the AP1000 nasty FDDI hack and
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
59
60
61
62
63
64
65
66
67
68
69
70
71
72
   *					folded into the mainstream FDDI code.
   *					Ack spit, Linus how did you allow that
   *					one in...
   *		Jes Sorensen	:	Make FDDI work again in 2.1.x and
   *					clean up the APFDDI & gen. FDDI bits.
   *		Alexey Kuznetsov:	new arp state machine;
   *					now it is in net/core/neighbour.c.
   *		Krzysztof Halasa:	Added Frame Relay ARP support.
   *		Arnaldo C. Melo :	convert /proc/net/arp to seq_file
   *		Shmulik Hen:		Split arp_send to arp_create and
   *					arp_xmit so intermediate drivers like
   *					bonding can change the skb before
   *					sending (e.g. insert 8021q tag).
   *		Harald Welte	:	convert to make use of jenkins hash
65324144b   Jesper Dangaard Brouer   net: RFC3069, pri...
73
   *		Jesper D. Brouer:       Proxy ARP PVLAN RFC 3069 support.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
74
75
76
77
78
79
   */
  
  #include <linux/module.h>
  #include <linux/types.h>
  #include <linux/string.h>
  #include <linux/kernel.h>
4fc268d24   Randy Dunlap   [PATCH] capable/c...
80
  #include <linux/capability.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
81
82
83
84
85
86
  #include <linux/socket.h>
  #include <linux/sockios.h>
  #include <linux/errno.h>
  #include <linux/in.h>
  #include <linux/mm.h>
  #include <linux/inet.h>
14c850212   Arnaldo Carvalho de Melo   [INET_SOCK]: Move...
87
  #include <linux/inetdevice.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
88
89
90
91
92
93
94
95
96
97
98
99
  #include <linux/netdevice.h>
  #include <linux/etherdevice.h>
  #include <linux/fddidevice.h>
  #include <linux/if_arp.h>
  #include <linux/trdevice.h>
  #include <linux/skbuff.h>
  #include <linux/proc_fs.h>
  #include <linux/seq_file.h>
  #include <linux/stat.h>
  #include <linux/init.h>
  #include <linux/net.h>
  #include <linux/rcupdate.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
100
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
101
102
103
  #ifdef CONFIG_SYSCTL
  #include <linux/sysctl.h>
  #endif
457c4cbc5   Eric W. Biederman   [NET]: Make /proc...
104
  #include <net/net_namespace.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
105
106
107
108
109
110
111
  #include <net/ip.h>
  #include <net/icmp.h>
  #include <net/route.h>
  #include <net/protocol.h>
  #include <net/tcp.h>
  #include <net/sock.h>
  #include <net/arp.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
112
  #include <net/ax25.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
113
  #include <net/netrom.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
114
115
  
  #include <asm/system.h>
deffd7775   Changli Gao   net: arp: code cl...
116
  #include <linux/uaccess.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
117
118
119
120
121
122
  
  #include <linux/netfilter_arp.h>
  
  /*
   *	Interface to generic neighbour cache.
   */
2c2aba6c5   David S. Miller   ipv6: Use univers...
123
  static u32 arp_hash(const void *pkey, const struct net_device *dev, __u32 *hash_rnd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
124
125
126
127
  static int arp_constructor(struct neighbour *neigh);
  static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb);
  static void arp_error_report(struct neighbour *neigh, struct sk_buff *skb);
  static void parp_redo(struct sk_buff *skb);
89d69d2b7   Stephen Hemminger   net: make neigh_o...
128
  static const struct neigh_ops arp_generic_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
129
130
131
132
133
  	.family =		AF_INET,
  	.solicit =		arp_solicit,
  	.error_report =		arp_error_report,
  	.output =		neigh_resolve_output,
  	.connected_output =	neigh_connected_output,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
134
  };
89d69d2b7   Stephen Hemminger   net: make neigh_o...
135
  static const struct neigh_ops arp_hh_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
136
137
138
139
140
  	.family =		AF_INET,
  	.solicit =		arp_solicit,
  	.error_report =		arp_error_report,
  	.output =		neigh_resolve_output,
  	.connected_output =	neigh_resolve_output,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
141
  };
89d69d2b7   Stephen Hemminger   net: make neigh_o...
142
  static const struct neigh_ops arp_direct_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
143
  	.family =		AF_INET,
8f40b161d   David S. Miller   neigh: Pass neigh...
144
145
  	.output =		neigh_direct_output,
  	.connected_output =	neigh_direct_output,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
146
  };
a64de47c0   stephen hemminger   arp: remove unnec...
147
  static const struct neigh_ops arp_broken_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
148
149
150
151
152
  	.family =		AF_INET,
  	.solicit =		arp_solicit,
  	.error_report =		arp_error_report,
  	.output =		neigh_compat_output,
  	.connected_output =	neigh_compat_output,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
153
154
155
  };
  
  struct neigh_table arp_tbl = {
deffd7775   Changli Gao   net: arp: code cl...
156
  	.family		= AF_INET,
deffd7775   Changli Gao   net: arp: code cl...
157
158
159
160
161
162
163
164
165
166
167
168
  	.key_len	= 4,
  	.hash		= arp_hash,
  	.constructor	= arp_constructor,
  	.proxy_redo	= parp_redo,
  	.id		= "arp_cache",
  	.parms		= {
  		.tbl			= &arp_tbl,
  		.base_reachable_time	= 30 * HZ,
  		.retrans_time		= 1 * HZ,
  		.gc_staletime		= 60 * HZ,
  		.reachable_time		= 30 * HZ,
  		.delay_probe_time	= 5 * HZ,
8b5c171bb   Eric Dumazet   neigh: new unreso...
169
  		.queue_len_bytes	= 64*1024,
deffd7775   Changli Gao   net: arp: code cl...
170
171
172
173
174
175
  		.ucast_probes		= 3,
  		.mcast_probes		= 3,
  		.anycast_delay		= 1 * HZ,
  		.proxy_delay		= (8 * HZ) / 10,
  		.proxy_qlen		= 64,
  		.locktime		= 1 * HZ,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
176
  	},
deffd7775   Changli Gao   net: arp: code cl...
177
178
179
180
  	.gc_interval	= 30 * HZ,
  	.gc_thresh1	= 128,
  	.gc_thresh2	= 512,
  	.gc_thresh3	= 1024,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
181
  };
4bc2f18ba   Eric Dumazet   net/ipv4: EXPORT_...
182
  EXPORT_SYMBOL(arp_tbl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
183

714e85be3   Al Viro   [IPV6]: Assorted ...
184
  int arp_mc_map(__be32 addr, u8 *haddr, struct net_device *dev, int dir)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
185
186
187
188
189
190
  {
  	switch (dev->type) {
  	case ARPHRD_ETHER:
  	case ARPHRD_FDDI:
  	case ARPHRD_IEEE802:
  		ip_eth_mc_map(addr, haddr);
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
191
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
192
193
194
195
  	case ARPHRD_IEEE802_TR:
  		ip_tr_mc_map(addr, haddr);
  		return 0;
  	case ARPHRD_INFINIBAND:
a9e527e3f   Rolf Manderscheid   IPoIB: improve IP...
196
  		ip_ib_mc_map(addr, dev->broadcast, haddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
197
  		return 0;
93ca3bb5d   Timo Teräs   net: gre: provide...
198
199
200
  	case ARPHRD_IPGRE:
  		ip_ipgre_mc_map(addr, dev->broadcast, haddr);
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
201
202
203
204
205
206
207
208
  	default:
  		if (dir) {
  			memcpy(haddr, dev->broadcast, dev->addr_len);
  			return 0;
  		}
  	}
  	return -EINVAL;
  }
d6bf78171   Eric Dumazet   net neigh: RCU co...
209
210
  static u32 arp_hash(const void *pkey,
  		    const struct net_device *dev,
2c2aba6c5   David S. Miller   ipv6: Use univers...
211
  		    __u32 *hash_rnd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
212
  {
2c2aba6c5   David S. Miller   ipv6: Use univers...
213
  	return arp_hashfn(*(u32 *)pkey, dev, *hash_rnd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
214
215
216
217
  }
  
  static int arp_constructor(struct neighbour *neigh)
  {
deffd7775   Changli Gao   net: arp: code cl...
218
  	__be32 addr = *(__be32 *)neigh->primary_key;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
219
220
221
  	struct net_device *dev = neigh->dev;
  	struct in_device *in_dev;
  	struct neigh_parms *parms;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
222
  	rcu_read_lock();
e5ed63991   Herbert Xu   [IPV4]: Replace _...
223
  	in_dev = __in_dev_get_rcu(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
224
225
226
227
  	if (in_dev == NULL) {
  		rcu_read_unlock();
  		return -EINVAL;
  	}
c346dca10   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
228
  	neigh->type = inet_addr_type(dev_net(dev), addr);
a79878f00   Denis V. Lunev   [ARP]: Move inet_...
229

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
230
231
232
233
  	parms = in_dev->arp_parms;
  	__neigh_parms_put(neigh->parms);
  	neigh->parms = neigh_parms_clone(parms);
  	rcu_read_unlock();
3b04ddde0   Stephen Hemminger   [NET]: Move hardw...
234
  	if (!dev->header_ops) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
235
236
  		neigh->nud_state = NUD_NOARP;
  		neigh->ops = &arp_direct_ops;
8f40b161d   David S. Miller   neigh: Pass neigh...
237
  		neigh->output = neigh_direct_output;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
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
  	} else {
  		/* Good devices (checked by reading texts, but only Ethernet is
  		   tested)
  
  		   ARPHRD_ETHER: (ethernet, apfddi)
  		   ARPHRD_FDDI: (fddi)
  		   ARPHRD_IEEE802: (tr)
  		   ARPHRD_METRICOM: (strip)
  		   ARPHRD_ARCNET:
  		   etc. etc. etc.
  
  		   ARPHRD_IPDDP will also work, if author repairs it.
  		   I did not it, because this driver does not work even
  		   in old paradigm.
  		 */
  
  #if 1
  		/* So... these "amateur" devices are hopeless.
  		   The only thing, that I can say now:
  		   It is very sad that we need to keep ugly obsolete
  		   code to make them happy.
  
  		   They should be moved to more reasonable state, now
  		   they use rebuild_header INSTEAD OF hard_start_xmit!!!
  		   Besides that, they are sort of out of date
  		   (a lot of redundant clones/copies, useless in 2.1),
  		   I wonder why people believe that they work.
  		 */
  		switch (dev->type) {
  		default:
  			break;
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
269
  		case ARPHRD_ROSE:
40e4783ee   Igor Maravic   ipv4: arp: Cleanu...
270
  #if IS_ENABLED(CONFIG_AX25)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
271
  		case ARPHRD_AX25:
40e4783ee   Igor Maravic   ipv4: arp: Cleanu...
272
  #if IS_ENABLED(CONFIG_NETROM)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
273
274
275
276
277
  		case ARPHRD_NETROM:
  #endif
  			neigh->ops = &arp_broken_ops;
  			neigh->output = neigh->ops->output;
  			return 0;
deffd7775   Changli Gao   net: arp: code cl...
278
279
  #else
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
280
  #endif
deffd7775   Changli Gao   net: arp: code cl...
281
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
282
283
284
285
  #endif
  		if (neigh->type == RTN_MULTICAST) {
  			neigh->nud_state = NUD_NOARP;
  			arp_mc_map(addr, neigh->ha, dev, 1);
deffd7775   Changli Gao   net: arp: code cl...
286
  		} else if (dev->flags & (IFF_NOARP | IFF_LOOPBACK)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
287
288
  			neigh->nud_state = NUD_NOARP;
  			memcpy(neigh->ha, dev->dev_addr, dev->addr_len);
deffd7775   Changli Gao   net: arp: code cl...
289
290
  		} else if (neigh->type == RTN_BROADCAST ||
  			   (dev->flags & IFF_POINTOPOINT)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
291
292
293
  			neigh->nud_state = NUD_NOARP;
  			memcpy(neigh->ha, dev->broadcast, dev->addr_len);
  		}
3b04ddde0   Stephen Hemminger   [NET]: Move hardw...
294
295
  
  		if (dev->header_ops->cache)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
296
297
298
  			neigh->ops = &arp_hh_ops;
  		else
  			neigh->ops = &arp_generic_ops;
3b04ddde0   Stephen Hemminger   [NET]: Move hardw...
299

deffd7775   Changli Gao   net: arp: code cl...
300
  		if (neigh->nud_state & NUD_VALID)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
  			neigh->output = neigh->ops->connected_output;
  		else
  			neigh->output = neigh->ops->output;
  	}
  	return 0;
  }
  
  static void arp_error_report(struct neighbour *neigh, struct sk_buff *skb)
  {
  	dst_link_failure(skb);
  	kfree_skb(skb);
  }
  
  static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb)
  {
a61ced5d1   Al Viro   [IPV4]: inet_sele...
316
  	__be32 saddr = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
317
318
  	u8  *dst_ha = NULL;
  	struct net_device *dev = neigh->dev;
deffd7775   Changli Gao   net: arp: code cl...
319
  	__be32 target = *(__be32 *)neigh->primary_key;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
320
  	int probes = atomic_read(&neigh->probes);
4b4194c40   Eric Dumazet   arp: RCU change i...
321
  	struct in_device *in_dev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
322

4b4194c40   Eric Dumazet   arp: RCU change i...
323
324
325
326
  	rcu_read_lock();
  	in_dev = __in_dev_get_rcu(dev);
  	if (!in_dev) {
  		rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
327
  		return;
4b4194c40   Eric Dumazet   arp: RCU change i...
328
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
329
330
331
  	switch (IN_DEV_ARP_ANNOUNCE(in_dev)) {
  	default:
  	case 0:		/* By default announce any local IP */
deffd7775   Changli Gao   net: arp: code cl...
332
333
  		if (skb && inet_addr_type(dev_net(dev),
  					  ip_hdr(skb)->saddr) == RTN_LOCAL)
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
334
  			saddr = ip_hdr(skb)->saddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
335
336
337
338
  		break;
  	case 1:		/* Restrict announcements of saddr in same subnet */
  		if (!skb)
  			break;
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
339
  		saddr = ip_hdr(skb)->saddr;
c346dca10   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
340
  		if (inet_addr_type(dev_net(dev), saddr) == RTN_LOCAL) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
341
342
343
344
345
346
347
348
349
  			/* saddr should be known to target */
  			if (inet_addr_onlink(in_dev, target, saddr))
  				break;
  		}
  		saddr = 0;
  		break;
  	case 2:		/* Avoid secondary IPs, get a primary/preferred one */
  		break;
  	}
4b4194c40   Eric Dumazet   arp: RCU change i...
350
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
351

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
352
353
  	if (!saddr)
  		saddr = inet_select_addr(dev, target, RT_SCOPE_LINK);
deffd7775   Changli Gao   net: arp: code cl...
354
355
356
357
358
359
  	probes -= neigh->parms->ucast_probes;
  	if (probes < 0) {
  		if (!(neigh->nud_state & NUD_VALID))
  			printk(KERN_DEBUG
  			       "trying to ucast probe in NUD_INVALID
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
360
  		dst_ha = neigh->ha;
9ff566074   David S. Miller   Revert "[NDISC]: ...
361
  		read_lock_bh(&neigh->lock);
deffd7775   Changli Gao   net: arp: code cl...
362
363
364
  	} else {
  		probes -= neigh->parms->app_probes;
  		if (probes < 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
365
  #ifdef CONFIG_ARPD
deffd7775   Changli Gao   net: arp: code cl...
366
  			neigh_app_ns(neigh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
367
  #endif
deffd7775   Changli Gao   net: arp: code cl...
368
369
  			return;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
370
371
372
373
  	}
  
  	arp_send(ARPOP_REQUEST, ETH_P_ARP, target, dev, saddr,
  		 dst_ha, dev->dev_addr, NULL);
9ff566074   David S. Miller   Revert "[NDISC]: ...
374
375
  	if (dst_ha)
  		read_unlock_bh(&neigh->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
376
  }
9bd85e326   Denis V. Lunev   [IPV4]: Remove ex...
377
  static int arp_ignore(struct in_device *in_dev, __be32 sip, __be32 tip)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
  {
  	int scope;
  
  	switch (IN_DEV_ARP_IGNORE(in_dev)) {
  	case 0:	/* Reply, the tip is already validated */
  		return 0;
  	case 1:	/* Reply only if tip is configured on the incoming interface */
  		sip = 0;
  		scope = RT_SCOPE_HOST;
  		break;
  	case 2:	/*
  		 * Reply only if tip is configured on the incoming interface
  		 * and is in same subnet as sip
  		 */
  		scope = RT_SCOPE_HOST;
  		break;
  	case 3:	/* Do not reply for scope host addresses */
  		sip = 0;
  		scope = RT_SCOPE_LINK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
397
398
399
400
401
402
403
404
405
406
407
  		break;
  	case 4:	/* Reserved */
  	case 5:
  	case 6:
  	case 7:
  		return 0;
  	case 8:	/* Do not reply */
  		return 1;
  	default:
  		return 0;
  	}
9bd85e326   Denis V. Lunev   [IPV4]: Remove ex...
408
  	return !inet_confirm_addr(in_dev, sip, tip, scope);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
409
  }
ed9bad06e   Al Viro   [IPV4] net/ipv4/a...
410
  static int arp_filter(__be32 sip, __be32 tip, struct net_device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
411
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
412
  	struct rtable *rt;
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
413
  	int flag = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
414
  	/*unsigned long now; */
ca12a1a44   Pavel Emelyanov   inet: prepare net...
415
  	struct net *net = dev_net(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
416

78fbfd8a6   David S. Miller   ipv4: Create and ...
417
  	rt = ip_route_output(net, sip, tip, 0, 0);
b23dd4fe4   David S. Miller   ipv4: Make output...
418
  	if (IS_ERR(rt))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
419
  		return 1;
d8d1f30b9   Changli Gao   net-next: remove ...
420
  	if (rt->dst.dev != dev) {
de0744af1   Pavel Emelyanov   mib: add net to N...
421
  		NET_INC_STATS_BH(net, LINUX_MIB_ARPFILTER);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
422
  		flag = 1;
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
423
424
425
426
  	}
  	ip_rt_put(rt);
  	return flag;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
427
428
429
430
431
432
433
434
435
436
437
  
  /* OBSOLETE FUNCTIONS */
  
  /*
   *	Find an arp mapping in the cache. If not found, post a request.
   *
   *	It is very UGLY routine: it DOES NOT use skb->dst->neighbour,
   *	even if it exists. It is supposed that skb->dev was mangled
   *	by a virtual device (eql, shaper). Nobody but broken devices
   *	is allowed to use this function, it is scheduled to be removed. --ANK
   */
deffd7775   Changli Gao   net: arp: code cl...
438
439
  static int arp_set_predefined(int addr_hint, unsigned char *haddr,
  			      __be32 paddr, struct net_device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
  {
  	switch (addr_hint) {
  	case RTN_LOCAL:
  		printk(KERN_DEBUG "ARP: arp called for own IP address
  ");
  		memcpy(haddr, dev->dev_addr, dev->addr_len);
  		return 1;
  	case RTN_MULTICAST:
  		arp_mc_map(paddr, haddr, dev, 1);
  		return 1;
  	case RTN_BROADCAST:
  		memcpy(haddr, dev->broadcast, dev->addr_len);
  		return 1;
  	}
  	return 0;
  }
  
  
  int arp_find(unsigned char *haddr, struct sk_buff *skb)
  {
  	struct net_device *dev = skb->dev;
fd6832220   Al Viro   [IPV4]: inet_addr...
461
  	__be32 paddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
462
  	struct neighbour *n;
adf30907d   Eric Dumazet   net: skb->dst acc...
463
  	if (!skb_dst(skb)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
464
465
466
467
468
  		printk(KERN_DEBUG "arp_find is called with dst==NULL
  ");
  		kfree_skb(skb);
  		return 1;
  	}
511c3f92a   Eric Dumazet   net: skb->rtable ...
469
  	paddr = skb_rtable(skb)->rt_gateway;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
470

deffd7775   Changli Gao   net: arp: code cl...
471
472
  	if (arp_set_predefined(inet_addr_type(dev_net(dev), paddr), haddr,
  			       paddr, dev))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
473
474
475
476
477
478
  		return 0;
  
  	n = __neigh_lookup(&arp_tbl, &paddr, dev, 1);
  
  	if (n) {
  		n->used = jiffies;
0ed8ddf40   Eric Dumazet   neigh: Protect ne...
479
480
  		if (n->nud_state & NUD_VALID || neigh_event_send(n, skb) == 0) {
  			neigh_ha_snapshot(haddr, n, dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
481
482
483
484
485
486
487
488
  			neigh_release(n);
  			return 0;
  		}
  		neigh_release(n);
  	} else
  		kfree_skb(skb);
  	return 1;
  }
4bc2f18ba   Eric Dumazet   net/ipv4: EXPORT_...
489
  EXPORT_SYMBOL(arp_find);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
490
491
  
  /* END OF OBSOLETE FUNCTIONS */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
492
493
494
  /*
   * Check if we can use proxy ARP for this path
   */
65324144b   Jesper Dangaard Brouer   net: RFC3069, pri...
495
496
  static inline int arp_fwd_proxy(struct in_device *in_dev,
  				struct net_device *dev,	struct rtable *rt)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
497
498
499
  {
  	struct in_device *out_dev;
  	int imi, omi = -1;
d8d1f30b9   Changli Gao   net-next: remove ...
500
  	if (rt->dst.dev == dev)
65324144b   Jesper Dangaard Brouer   net: RFC3069, pri...
501
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
502
503
  	if (!IN_DEV_PROXY_ARP(in_dev))
  		return 0;
deffd7775   Changli Gao   net: arp: code cl...
504
505
  	imi = IN_DEV_MEDIUM_ID(in_dev);
  	if (imi == 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
506
507
508
509
510
  		return 1;
  	if (imi == -1)
  		return 0;
  
  	/* place to check for proxy_arp for routes */
d8d1f30b9   Changli Gao   net-next: remove ...
511
  	out_dev = __in_dev_get_rcu(rt->dst.dev);
faa9dcf79   Eric Dumazet   arp: RCU changes
512
  	if (out_dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
513
  		omi = IN_DEV_MEDIUM_ID(out_dev);
faa9dcf79   Eric Dumazet   arp: RCU changes
514

a02cec215   Eric Dumazet   net: return opera...
515
  	return omi != imi && omi != -1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
516
517
518
  }
  
  /*
65324144b   Jesper Dangaard Brouer   net: RFC3069, pri...
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
   * Check for RFC3069 proxy arp private VLAN (allow to send back to same dev)
   *
   * RFC3069 supports proxy arp replies back to the same interface.  This
   * is done to support (ethernet) switch features, like RFC 3069, where
   * the individual ports are not allowed to communicate with each
   * other, BUT they are allowed to talk to the upstream router.  As
   * described in RFC 3069, it is possible to allow these hosts to
   * communicate through the upstream router, by proxy_arp'ing.
   *
   * RFC 3069: "VLAN Aggregation for Efficient IP Address Allocation"
   *
   *  This technology is known by different names:
   *    In RFC 3069 it is called VLAN Aggregation.
   *    Cisco and Allied Telesyn call it Private VLAN.
   *    Hewlett-Packard call it Source-Port filtering or port-isolation.
   *    Ericsson call it MAC-Forced Forwarding (RFC Draft).
   *
   */
  static inline int arp_fwd_pvlan(struct in_device *in_dev,
  				struct net_device *dev,	struct rtable *rt,
  				__be32 sip, __be32 tip)
  {
  	/* Private VLAN is only concerned about the same ethernet segment */
d8d1f30b9   Changli Gao   net-next: remove ...
542
  	if (rt->dst.dev != dev)
65324144b   Jesper Dangaard Brouer   net: RFC3069, pri...
543
544
545
546
547
548
549
550
551
552
553
554
555
  		return 0;
  
  	/* Don't reply on self probes (often done by windowz boxes)*/
  	if (sip == tip)
  		return 0;
  
  	if (IN_DEV_PROXY_ARP_PVLAN(in_dev))
  		return 1;
  	else
  		return 0;
  }
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
556
557
558
559
560
561
562
   *	Interface to link layer: send routine and receive handler.
   */
  
  /*
   *	Create an arp packet. If (dest_hw == NULL), we create a broadcast
   *	message.
   */
ed9bad06e   Al Viro   [IPV4] net/ipv4/a...
563
564
  struct sk_buff *arp_create(int type, int ptype, __be32 dest_ip,
  			   struct net_device *dev, __be32 src_ip,
abfdf1c48   Jan Engelhardt   [NETFILTER]: ebta...
565
566
567
  			   const unsigned char *dest_hw,
  			   const unsigned char *src_hw,
  			   const unsigned char *target_hw)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
568
569
570
571
  {
  	struct sk_buff *skb;
  	struct arphdr *arp;
  	unsigned char *arp_ptr;
660882432   Herbert Xu   ipv4: Remove all ...
572
573
  	int hlen = LL_RESERVED_SPACE(dev);
  	int tlen = dev->needed_tailroom;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
574
575
576
577
  
  	/*
  	 *	Allocate a buffer
  	 */
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
578

660882432   Herbert Xu   ipv4: Remove all ...
579
  	skb = alloc_skb(arp_hdr_len(dev) + hlen + tlen, GFP_ATOMIC);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
580
581
  	if (skb == NULL)
  		return NULL;
660882432   Herbert Xu   ipv4: Remove all ...
582
  	skb_reserve(skb, hlen);
c1d2bbe1c   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
583
  	skb_reset_network_header(skb);
988b70507   Pavel Emelyanov   [ARP]: Introduce ...
584
  	arp = (struct arphdr *) skb_put(skb, arp_hdr_len(dev));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
585
586
587
588
589
590
591
592
593
594
  	skb->dev = dev;
  	skb->protocol = htons(ETH_P_ARP);
  	if (src_hw == NULL)
  		src_hw = dev->dev_addr;
  	if (dest_hw == NULL)
  		dest_hw = dev->broadcast;
  
  	/*
  	 *	Fill the device header for the ARP frame
  	 */
0c4e85813   Stephen Hemminger   [NET]: Wrap netde...
595
  	if (dev_hard_header(skb, dev, ptype, dest_hw, src_hw, skb->len) < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
  		goto out;
  
  	/*
  	 * Fill out the arp protocol part.
  	 *
  	 * The arp hardware type should match the device type, except for FDDI,
  	 * which (according to RFC 1390) should always equal 1 (Ethernet).
  	 */
  	/*
  	 *	Exceptions everywhere. AX.25 uses the AX.25 PID value not the
  	 *	DIX code for the protocol. Make these device structure fields.
  	 */
  	switch (dev->type) {
  	default:
  		arp->ar_hrd = htons(dev->type);
  		arp->ar_pro = htons(ETH_P_IP);
  		break;
40e4783ee   Igor Maravic   ipv4: arp: Cleanu...
613
  #if IS_ENABLED(CONFIG_AX25)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
614
615
616
617
  	case ARPHRD_AX25:
  		arp->ar_hrd = htons(ARPHRD_AX25);
  		arp->ar_pro = htons(AX25_P_IP);
  		break;
40e4783ee   Igor Maravic   ipv4: arp: Cleanu...
618
  #if IS_ENABLED(CONFIG_NETROM)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
619
620
621
622
623
624
  	case ARPHRD_NETROM:
  		arp->ar_hrd = htons(ARPHRD_NETROM);
  		arp->ar_pro = htons(AX25_P_IP);
  		break;
  #endif
  #endif
40e4783ee   Igor Maravic   ipv4: arp: Cleanu...
625
  #if IS_ENABLED(CONFIG_FDDI)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
626
627
628
629
630
  	case ARPHRD_FDDI:
  		arp->ar_hrd = htons(ARPHRD_ETHER);
  		arp->ar_pro = htons(ETH_P_IP);
  		break;
  #endif
40e4783ee   Igor Maravic   ipv4: arp: Cleanu...
631
  #if IS_ENABLED(CONFIG_TR)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
632
633
634
635
636
637
638
639
640
641
  	case ARPHRD_IEEE802_TR:
  		arp->ar_hrd = htons(ARPHRD_IEEE802);
  		arp->ar_pro = htons(ETH_P_IP);
  		break;
  #endif
  	}
  
  	arp->ar_hln = dev->addr_len;
  	arp->ar_pln = 4;
  	arp->ar_op = htons(type);
deffd7775   Changli Gao   net: arp: code cl...
642
  	arp_ptr = (unsigned char *)(arp + 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
643
644
  
  	memcpy(arp_ptr, src_hw, dev->addr_len);
f4cca7ffb   Jianjun Kong   net: clean up net...
645
646
647
  	arp_ptr += dev->addr_len;
  	memcpy(arp_ptr, &src_ip, 4);
  	arp_ptr += 4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
648
649
650
651
  	if (target_hw != NULL)
  		memcpy(arp_ptr, target_hw, dev->addr_len);
  	else
  		memset(arp_ptr, 0, dev->addr_len);
f4cca7ffb   Jianjun Kong   net: clean up net...
652
  	arp_ptr += dev->addr_len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
653
654
655
656
657
658
659
660
  	memcpy(arp_ptr, &dest_ip, 4);
  
  	return skb;
  
  out:
  	kfree_skb(skb);
  	return NULL;
  }
4bc2f18ba   Eric Dumazet   net/ipv4: EXPORT_...
661
  EXPORT_SYMBOL(arp_create);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
662
663
664
665
666
667
668
  
  /*
   *	Send an arp packet.
   */
  void arp_xmit(struct sk_buff *skb)
  {
  	/* Send it off, maybe filter it using firewalling first.  */
fdc9314cb   Jan Engelhardt   netfilter: replac...
669
  	NF_HOOK(NFPROTO_ARP, NF_ARP_OUT, skb, NULL, skb->dev, dev_queue_xmit);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
670
  }
4bc2f18ba   Eric Dumazet   net/ipv4: EXPORT_...
671
  EXPORT_SYMBOL(arp_xmit);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
672
673
674
675
  
  /*
   *	Create and send an arp packet.
   */
ed9bad06e   Al Viro   [IPV4] net/ipv4/a...
676
677
  void arp_send(int type, int ptype, __be32 dest_ip,
  	      struct net_device *dev, __be32 src_ip,
abfdf1c48   Jan Engelhardt   [NETFILTER]: ebta...
678
679
  	      const unsigned char *dest_hw, const unsigned char *src_hw,
  	      const unsigned char *target_hw)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
680
681
682
683
684
685
  {
  	struct sk_buff *skb;
  
  	/*
  	 *	No arp on this interface.
  	 */
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
686

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
687
688
689
690
691
  	if (dev->flags&IFF_NOARP)
  		return;
  
  	skb = arp_create(type, ptype, dest_ip, dev, src_ip,
  			 dest_hw, src_hw, target_hw);
deffd7775   Changli Gao   net: arp: code cl...
692
  	if (skb == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
693
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
694
695
696
  
  	arp_xmit(skb);
  }
4bc2f18ba   Eric Dumazet   net/ipv4: EXPORT_...
697
  EXPORT_SYMBOL(arp_send);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
698

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
699
700
701
702
703
704
705
  /*
   *	Process an arp request.
   */
  
  static int arp_process(struct sk_buff *skb)
  {
  	struct net_device *dev = skb->dev;
faa9dcf79   Eric Dumazet   arp: RCU changes
706
  	struct in_device *in_dev = __in_dev_get_rcu(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
707
708
709
  	struct arphdr *arp;
  	unsigned char *arp_ptr;
  	struct rtable *rt;
e0260fedd   Mark Ryden   [IPV4] ARP: Remov...
710
  	unsigned char *sha;
9e12bb22e   Al Viro   [IPV4]: ip_route_...
711
  	__be32 sip, tip;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
712
713
714
  	u16 dev_type = dev->type;
  	int addr_type;
  	struct neighbour *n;
c346dca10   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
715
  	struct net *net = dev_net(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
716
717
718
719
720
721
722
  
  	/* arp_rcv below verifies the ARP header and verifies the device
  	 * is ARP'able.
  	 */
  
  	if (in_dev == NULL)
  		goto out;
d0a92be05   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
723
  	arp = arp_hdr(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
724
725
  
  	switch (dev_type) {
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
726
  	default:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
727
728
729
730
  		if (arp->ar_pro != htons(ETH_P_IP) ||
  		    htons(dev_type) != arp->ar_hrd)
  			goto out;
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
731
  	case ARPHRD_ETHER:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
732
  	case ARPHRD_IEEE802_TR:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
733
  	case ARPHRD_FDDI:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
734
  	case ARPHRD_IEEE802:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
735
736
737
738
739
740
741
742
743
744
745
746
747
748
  		/*
  		 * ETHERNET, Token Ring and Fibre Channel (which are IEEE 802
  		 * devices, according to RFC 2625) devices will accept ARP
  		 * hardware types of either 1 (Ethernet) or 6 (IEEE 802.2).
  		 * This is the case also of FDDI, where the RFC 1390 says that
  		 * FDDI devices should accept ARP hardware of (1) Ethernet,
  		 * however, to be more robust, we'll accept both 1 (Ethernet)
  		 * or 6 (IEEE 802.2)
  		 */
  		if ((arp->ar_hrd != htons(ARPHRD_ETHER) &&
  		     arp->ar_hrd != htons(ARPHRD_IEEE802)) ||
  		    arp->ar_pro != htons(ETH_P_IP))
  			goto out;
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
749
750
751
752
753
  	case ARPHRD_AX25:
  		if (arp->ar_pro != htons(AX25_P_IP) ||
  		    arp->ar_hrd != htons(ARPHRD_AX25))
  			goto out;
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
754
755
756
757
758
  	case ARPHRD_NETROM:
  		if (arp->ar_pro != htons(AX25_P_IP) ||
  		    arp->ar_hrd != htons(ARPHRD_NETROM))
  			goto out;
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
759
760
761
762
763
764
765
766
767
768
769
  	}
  
  	/* Understand only these message types */
  
  	if (arp->ar_op != htons(ARPOP_REPLY) &&
  	    arp->ar_op != htons(ARPOP_REQUEST))
  		goto out;
  
  /*
   *	Extract fields
   */
deffd7775   Changli Gao   net: arp: code cl...
770
  	arp_ptr = (unsigned char *)(arp + 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
771
772
773
774
  	sha	= arp_ptr;
  	arp_ptr += dev->addr_len;
  	memcpy(&sip, arp_ptr, 4);
  	arp_ptr += 4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
775
776
  	arp_ptr += dev->addr_len;
  	memcpy(&tip, arp_ptr, 4);
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
777
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
778
779
780
   *	Check for bad requests for 127.x.x.x and requests for multicast
   *	addresses.  If this is one such, delete it.
   */
f97c1e0c6   Joe Perches   [IPV4] net/ipv4: ...
781
  	if (ipv4_is_loopback(tip) || ipv4_is_multicast(tip))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
782
783
784
785
786
787
788
789
790
791
792
793
  		goto out;
  
  /*
   *     Special case: We must set Frame Relay source Q.922 address
   */
  	if (dev_type == ARPHRD_DLCI)
  		sha = dev->broadcast;
  
  /*
   *  Process entry.  The idea here is we want to send a reply if it is a
   *  request for us or if it is a request for someone else that we hold
   *  a proxy for.  We want to add an entry to our cache if it is a reply
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
794
795
796
797
   *  to us or if it is a request for our address.
   *  (The assumption for this last is that if someone is requesting our
   *  address, they are probably intending to talk to us, so it saves time
   *  if we cache their address.  Their address is also probably not in
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
798
   *  our cache, since ours is not in their cache.)
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
799
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
800
801
802
   *  Putting this another way, we only care about replies if they are to
   *  us, in which case we add them to the cache.  For requests, we care
   *  about those for us and those for our proxies.  We reply to both,
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
803
   *  and in the case of requests for us we add the requester to the arp
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
804
805
   *  cache.
   */
f8a68e752   Eric W. Biederman   Revert "ipv4: arp...
806
807
  	/* Special case: IPv4 duplicate address detection packet (RFC2131) */
  	if (sip == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
808
  		if (arp->ar_op == htons(ARPOP_REQUEST) &&
49e8a279a   Denis V. Lunev   [NETNS]: Process ...
809
  		    inet_addr_type(net, tip) == RTN_LOCAL &&
9bd85e326   Denis V. Lunev   [IPV4]: Remove ex...
810
  		    !arp_ignore(in_dev, sip, tip))
b4a9811c4   Jonas Danielsson   [ARP]: Fix arp re...
811
812
  			arp_send(ARPOP_REPLY, ETH_P_ARP, sip, dev, tip, sha,
  				 dev->dev_addr, sha);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
813
814
815
816
  		goto out;
  	}
  
  	if (arp->ar_op == htons(ARPOP_REQUEST) &&
4a94445c9   Eric Dumazet   net: Use ip_route...
817
  	    ip_route_input_noref(skb, tip, sip, 0, dev) == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
818

511c3f92a   Eric Dumazet   net: skb->rtable ...
819
  		rt = skb_rtable(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
820
821
822
  		addr_type = rt->rt_type;
  
  		if (addr_type == RTN_LOCAL) {
deffd7775   Changli Gao   net: arp: code cl...
823
  			int dont_send;
8164f1b79   Ben Greear   ipv4: Fix ARP beh...
824

deffd7775   Changli Gao   net: arp: code cl...
825
  			dont_send = arp_ignore(in_dev, sip, tip);
8164f1b79   Ben Greear   ipv4: Fix ARP beh...
826
  			if (!dont_send && IN_DEV_ARPFILTER(in_dev))
ae9c416d6   Changli Gao   net: arp: use ass...
827
  				dont_send = arp_filter(sip, tip, dev);
8164f1b79   Ben Greear   ipv4: Fix ARP beh...
828
829
830
  			if (!dont_send) {
  				n = neigh_event_ns(&arp_tbl, sha, &sip, dev);
  				if (n) {
deffd7775   Changli Gao   net: arp: code cl...
831
832
833
  					arp_send(ARPOP_REPLY, ETH_P_ARP, sip,
  						 dev, tip, sha, dev->dev_addr,
  						 sha);
8164f1b79   Ben Greear   ipv4: Fix ARP beh...
834
835
  					neigh_release(n);
  				}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
836
837
838
  			}
  			goto out;
  		} else if (IN_DEV_FORWARD(in_dev)) {
65324144b   Jesper Dangaard Brouer   net: RFC3069, pri...
839
840
841
  			if (addr_type == RTN_UNICAST  &&
  			    (arp_fwd_proxy(in_dev, dev, rt) ||
  			     arp_fwd_pvlan(in_dev, dev, rt, sip, tip) ||
deffd7775   Changli Gao   net: arp: code cl...
842
  			     pneigh_lookup(&arp_tbl, net, &tip, dev, 0))) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
843
844
845
  				n = neigh_event_ns(&arp_tbl, sha, &sip, dev);
  				if (n)
  					neigh_release(n);
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
846
  				if (NEIGH_CB(skb)->flags & LOCALLY_ENQUEUED ||
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
847
848
  				    skb->pkt_type == PACKET_HOST ||
  				    in_dev->arp_parms->proxy_delay == 0) {
deffd7775   Changli Gao   net: arp: code cl...
849
850
851
  					arp_send(ARPOP_REPLY, ETH_P_ARP, sip,
  						 dev, tip, sha, dev->dev_addr,
  						 sha);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
852
  				} else {
deffd7775   Changli Gao   net: arp: code cl...
853
854
  					pneigh_enqueue(&arp_tbl,
  						       in_dev->arp_parms, skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
855
856
857
858
859
860
861
862
863
864
  					return 0;
  				}
  				goto out;
  			}
  		}
  	}
  
  	/* Update our ARP tables */
  
  	n = __neigh_lookup(&arp_tbl, &sip, dev, 0);
c346dca10   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
865
  	if (IPV4_DEVCONF_ALL(dev_net(dev), ARP_ACCEPT)) {
abd596a4b   Neil Horman   [IPV4] ARP: Alloc...
866
867
868
869
870
  		/* Unsolicited ARP is not accepted by default.
  		   It is possible, that this option should be enabled for some
  		   devices (strip is candidate)
  		 */
  		if (n == NULL &&
6d955180b   Octavian Purdila   ipv4: allow warmi...
871
872
  		    (arp->ar_op == htons(ARPOP_REPLY) ||
  		     (arp->ar_op == htons(ARPOP_REQUEST) && tip == sip)) &&
49e8a279a   Denis V. Lunev   [NETNS]: Process ...
873
  		    inet_addr_type(net, sip) == RTN_UNICAST)
1b1ac759d   Jean Delvare   [IPV4]: Cleanup c...
874
  			n = __neigh_lookup(&arp_tbl, &sip, dev, 1);
abd596a4b   Neil Horman   [IPV4] ARP: Alloc...
875
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
  
  	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 proxy
  		   agents are active. Taking the first reply prevents
  		   arp trashing and chooses the fastest router.
  		 */
  		override = time_after(jiffies, n->updated + n->parms->locktime);
  
  		/* 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;
deffd7775   Changli Gao   net: arp: code cl...
894
895
  		neigh_update(n, sha, state,
  			     override ? NEIGH_UPDATE_F_OVERRIDE : 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
896
897
898
899
  		neigh_release(n);
  	}
  
  out:
ead2ceb0e   Neil Horman   Network Drop Moni...
900
  	consume_skb(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
901
902
  	return 0;
  }
444fc8fc3   Herbert Xu   [IPV4]: Fix "Prox...
903
904
905
906
  static void parp_redo(struct sk_buff *skb)
  {
  	arp_process(skb);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
907
908
909
910
  
  /*
   *	Receive an arp request from the device layer.
   */
6c97e72a1   Adrian Bunk   [IPV4]: Possible ...
911
912
  static int arp_rcv(struct sk_buff *skb, struct net_device *dev,
  		   struct packet_type *pt, struct net_device *orig_dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
913
914
915
916
  {
  	struct arphdr *arp;
  
  	/* ARP header, plus 2 device addresses, plus 2 IP addresses.  */
988b70507   Pavel Emelyanov   [ARP]: Introduce ...
917
  	if (!pskb_may_pull(skb, arp_hdr_len(dev)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
918
  		goto freeskb;
d0a92be05   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
919
  	arp = arp_hdr(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
920
921
922
923
924
925
  	if (arp->ar_hln != dev->addr_len ||
  	    dev->flags & IFF_NOARP ||
  	    skb->pkt_type == PACKET_OTHERHOST ||
  	    skb->pkt_type == PACKET_LOOPBACK ||
  	    arp->ar_pln != 4)
  		goto freeskb;
deffd7775   Changli Gao   net: arp: code cl...
926
927
  	skb = skb_share_check(skb, GFP_ATOMIC);
  	if (skb == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
928
  		goto out_of_mem;
a61bbcf28   Patrick McHardy   [NET]: Store skb-...
929
  	memset(NEIGH_CB(skb), 0, sizeof(struct neighbour_cb));
fdc9314cb   Jan Engelhardt   netfilter: replac...
930
  	return NF_HOOK(NFPROTO_ARP, NF_ARP_IN, skb, dev, NULL, arp_process);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
931
932
933
934
935
936
937
938
939
940
941
942
943
944
  
  freeskb:
  	kfree_skb(skb);
  out_of_mem:
  	return 0;
  }
  
  /*
   *	User level interface (ioctl)
   */
  
  /*
   *	Set (create) an ARP cache entry.
   */
32e569b72   Pavel Emelyanov   [IPV4]: Pass the ...
945
  static int arp_req_set_proxy(struct net *net, struct net_device *dev, int on)
f8b33fdfa   Pavel Emelyanov   [ARP]: Consolidat...
946
947
  {
  	if (dev == NULL) {
586f12115   Pavel Emelyanov   [IPV4]: Switch us...
948
  		IPV4_DEVCONF_ALL(net, PROXY_ARP) = on;
f8b33fdfa   Pavel Emelyanov   [ARP]: Consolidat...
949
950
  		return 0;
  	}
c506653d3   Eric Dumazet   net: arp_ioctl() ...
951
952
  	if (__in_dev_get_rtnl(dev)) {
  		IN_DEV_CONF_SET(__in_dev_get_rtnl(dev), PROXY_ARP, on);
f8b33fdfa   Pavel Emelyanov   [ARP]: Consolidat...
953
954
955
956
  		return 0;
  	}
  	return -ENXIO;
  }
32e569b72   Pavel Emelyanov   [IPV4]: Pass the ...
957
958
  static int arp_req_set_public(struct net *net, struct arpreq *r,
  		struct net_device *dev)
43dc17011   Pavel Emelyanov   [ARP]: Minus one ...
959
960
961
962
963
964
965
  {
  	__be32 ip = ((struct sockaddr_in *)&r->arp_pa)->sin_addr.s_addr;
  	__be32 mask = ((struct sockaddr_in *)&r->arp_netmask)->sin_addr.s_addr;
  
  	if (mask && mask != htonl(0xFFFFFFFF))
  		return -EINVAL;
  	if (!dev && (r->arp_flags & ATF_COM)) {
941666c2e   Eric Dumazet   net: RCU conversi...
966
  		dev = dev_getbyhwaddr_rcu(net, r->arp_ha.sa_family,
deffd7775   Changli Gao   net: arp: code cl...
967
  				      r->arp_ha.sa_data);
43dc17011   Pavel Emelyanov   [ARP]: Minus one ...
968
969
970
971
  		if (!dev)
  			return -ENODEV;
  	}
  	if (mask) {
2db82b534   Denis V. Lunev   [NETNS]: Make arp...
972
  		if (pneigh_lookup(&arp_tbl, net, &ip, dev, 1) == NULL)
43dc17011   Pavel Emelyanov   [ARP]: Minus one ...
973
974
975
  			return -ENOBUFS;
  		return 0;
  	}
f8b33fdfa   Pavel Emelyanov   [ARP]: Consolidat...
976

32e569b72   Pavel Emelyanov   [IPV4]: Pass the ...
977
  	return arp_req_set_proxy(net, dev, 1);
43dc17011   Pavel Emelyanov   [ARP]: Minus one ...
978
  }
32e569b72   Pavel Emelyanov   [IPV4]: Pass the ...
979
  static int arp_req_set(struct net *net, struct arpreq *r,
deffd7775   Changli Gao   net: arp: code cl...
980
  		       struct net_device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
981
  {
43dc17011   Pavel Emelyanov   [ARP]: Minus one ...
982
  	__be32 ip;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
983
984
  	struct neighbour *neigh;
  	int err;
43dc17011   Pavel Emelyanov   [ARP]: Minus one ...
985
  	if (r->arp_flags & ATF_PUBL)
32e569b72   Pavel Emelyanov   [IPV4]: Pass the ...
986
  		return arp_req_set_public(net, r, dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
987

43dc17011   Pavel Emelyanov   [ARP]: Minus one ...
988
  	ip = ((struct sockaddr_in *)&r->arp_pa)->sin_addr.s_addr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
989
990
991
  	if (r->arp_flags & ATF_PERM)
  		r->arp_flags |= ATF_COM;
  	if (dev == NULL) {
78fbfd8a6   David S. Miller   ipv4: Create and ...
992
  		struct rtable *rt = ip_route_output(net, ip, 0, RTO_ONLINK, 0);
b23dd4fe4   David S. Miller   ipv4: Make output...
993
994
995
  
  		if (IS_ERR(rt))
  			return PTR_ERR(rt);
d8d1f30b9   Changli Gao   net-next: remove ...
996
  		dev = rt->dst.dev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
997
998
999
1000
1001
  		ip_rt_put(rt);
  		if (!dev)
  			return -EINVAL;
  	}
  	switch (dev->type) {
40e4783ee   Igor Maravic   ipv4: arp: Cleanu...
1002
  #if IS_ENABLED(CONFIG_FDDI)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
  	case ARPHRD_FDDI:
  		/*
  		 * According to RFC 1390, FDDI devices should accept ARP
  		 * hardware types of 1 (Ethernet).  However, to be more
  		 * robust, we'll accept hardware types of either 1 (Ethernet)
  		 * or 6 (IEEE 802.2).
  		 */
  		if (r->arp_ha.sa_family != ARPHRD_FDDI &&
  		    r->arp_ha.sa_family != ARPHRD_ETHER &&
  		    r->arp_ha.sa_family != ARPHRD_IEEE802)
  			return -EINVAL;
  		break;
  #endif
  	default:
  		if (r->arp_ha.sa_family != dev->type)
  			return -EINVAL;
  		break;
  	}
  
  	neigh = __neigh_lookup_errno(&arp_tbl, &ip, dev);
  	err = PTR_ERR(neigh);
  	if (!IS_ERR(neigh)) {
  		unsigned state = NUD_STALE;
  		if (r->arp_flags & ATF_PERM)
  			state = NUD_PERMANENT;
deffd7775   Changli Gao   net: arp: code cl...
1028
  		err = neigh_update(neigh, (r->arp_flags & ATF_COM) ?
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
1029
  				   r->arp_ha.sa_data : NULL, state,
deffd7775   Changli Gao   net: arp: code cl...
1030
  				   NEIGH_UPDATE_F_OVERRIDE |
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1031
1032
1033
1034
1035
1036
1037
1038
  				   NEIGH_UPDATE_F_ADMIN);
  		neigh_release(neigh);
  	}
  	return err;
  }
  
  static unsigned arp_state_to_flags(struct neighbour *neigh)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1039
  	if (neigh->nud_state&NUD_PERMANENT)
deffd7775   Changli Gao   net: arp: code cl...
1040
  		return ATF_PERM | ATF_COM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1041
  	else if (neigh->nud_state&NUD_VALID)
deffd7775   Changli Gao   net: arp: code cl...
1042
1043
1044
  		return ATF_COM;
  	else
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1045
1046
1047
1048
1049
1050
1051
1052
  }
  
  /*
   *	Get an ARP cache entry.
   */
  
  static int arp_req_get(struct arpreq *r, struct net_device *dev)
  {
ed9bad06e   Al Viro   [IPV4] net/ipv4/a...
1053
  	__be32 ip = ((struct sockaddr_in *) &r->arp_pa)->sin_addr.s_addr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
  	struct neighbour *neigh;
  	int err = -ENXIO;
  
  	neigh = neigh_lookup(&arp_tbl, &ip, dev);
  	if (neigh) {
  		read_lock_bh(&neigh->lock);
  		memcpy(r->arp_ha.sa_data, neigh->ha, dev->addr_len);
  		r->arp_flags = arp_state_to_flags(neigh);
  		read_unlock_bh(&neigh->lock);
  		r->arp_ha.sa_family = dev->type;
  		strlcpy(r->arp_dev, dev->name, sizeof(r->arp_dev));
  		neigh_release(neigh);
  		err = 0;
  	}
  	return err;
  }
545ecdc3b   Maxim Levitsky   arp: allow to inv...
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
  int arp_invalidate(struct net_device *dev, __be32 ip)
  {
  	struct neighbour *neigh = neigh_lookup(&arp_tbl, &ip, dev);
  	int err = -ENXIO;
  
  	if (neigh) {
  		if (neigh->nud_state & ~NUD_NOARP)
  			err = neigh_update(neigh, NULL, NUD_FAILED,
  					   NEIGH_UPDATE_F_OVERRIDE|
  					   NEIGH_UPDATE_F_ADMIN);
  		neigh_release(neigh);
  	}
  
  	return err;
  }
  EXPORT_SYMBOL(arp_invalidate);
32e569b72   Pavel Emelyanov   [IPV4]: Pass the ...
1086
1087
  static int arp_req_delete_public(struct net *net, struct arpreq *r,
  		struct net_device *dev)
46479b432   Pavel Emelyanov   [ARP]: Minus one ...
1088
1089
1090
1091
1092
  {
  	__be32 ip = ((struct sockaddr_in *) &r->arp_pa)->sin_addr.s_addr;
  	__be32 mask = ((struct sockaddr_in *)&r->arp_netmask)->sin_addr.s_addr;
  
  	if (mask == htonl(0xFFFFFFFF))
2db82b534   Denis V. Lunev   [NETNS]: Make arp...
1093
  		return pneigh_delete(&arp_tbl, net, &ip, dev);
46479b432   Pavel Emelyanov   [ARP]: Minus one ...
1094

f8b33fdfa   Pavel Emelyanov   [ARP]: Consolidat...
1095
1096
  	if (mask)
  		return -EINVAL;
32e569b72   Pavel Emelyanov   [IPV4]: Pass the ...
1097
  	return arp_req_set_proxy(net, dev, 0);
46479b432   Pavel Emelyanov   [ARP]: Minus one ...
1098
  }
32e569b72   Pavel Emelyanov   [IPV4]: Pass the ...
1099
  static int arp_req_delete(struct net *net, struct arpreq *r,
deffd7775   Changli Gao   net: arp: code cl...
1100
  			  struct net_device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1101
  {
46479b432   Pavel Emelyanov   [ARP]: Minus one ...
1102
  	__be32 ip;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1103

46479b432   Pavel Emelyanov   [ARP]: Minus one ...
1104
  	if (r->arp_flags & ATF_PUBL)
32e569b72   Pavel Emelyanov   [IPV4]: Pass the ...
1105
  		return arp_req_delete_public(net, r, dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1106

46479b432   Pavel Emelyanov   [ARP]: Minus one ...
1107
  	ip = ((struct sockaddr_in *)&r->arp_pa)->sin_addr.s_addr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1108
  	if (dev == NULL) {
78fbfd8a6   David S. Miller   ipv4: Create and ...
1109
  		struct rtable *rt = ip_route_output(net, ip, 0, RTO_ONLINK, 0);
b23dd4fe4   David S. Miller   ipv4: Make output...
1110
1111
  		if (IS_ERR(rt))
  			return PTR_ERR(rt);
d8d1f30b9   Changli Gao   net-next: remove ...
1112
  		dev = rt->dst.dev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1113
1114
1115
1116
  		ip_rt_put(rt);
  		if (!dev)
  			return -EINVAL;
  	}
545ecdc3b   Maxim Levitsky   arp: allow to inv...
1117
  	return arp_invalidate(dev, ip);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1118
1119
1120
1121
1122
  }
  
  /*
   *	Handle an ARP layer I/O control request.
   */
32e569b72   Pavel Emelyanov   [IPV4]: Pass the ...
1123
  int arp_ioctl(struct net *net, unsigned int cmd, void __user *arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1124
1125
1126
1127
1128
1129
  {
  	int err;
  	struct arpreq r;
  	struct net_device *dev = NULL;
  
  	switch (cmd) {
deffd7775   Changli Gao   net: arp: code cl...
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
  	case SIOCDARP:
  	case SIOCSARP:
  		if (!capable(CAP_NET_ADMIN))
  			return -EPERM;
  	case SIOCGARP:
  		err = copy_from_user(&r, arg, sizeof(struct arpreq));
  		if (err)
  			return -EFAULT;
  		break;
  	default:
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1141
1142
1143
1144
1145
1146
  	}
  
  	if (r.arp_pa.sa_family != AF_INET)
  		return -EPFNOSUPPORT;
  
  	if (!(r.arp_flags & ATF_PUBL) &&
deffd7775   Changli Gao   net: arp: code cl...
1147
  	    (r.arp_flags & (ATF_NETMASK | ATF_DONTPUB)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1148
1149
1150
1151
  		return -EINVAL;
  	if (!(r.arp_flags & ATF_NETMASK))
  		((struct sockaddr_in *)&r.arp_netmask)->sin_addr.s_addr =
  							   htonl(0xFFFFFFFFUL);
c506653d3   Eric Dumazet   net: arp_ioctl() ...
1152
  	rtnl_lock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1153
1154
  	if (r.arp_dev[0]) {
  		err = -ENODEV;
c506653d3   Eric Dumazet   net: arp_ioctl() ...
1155
  		dev = __dev_get_by_name(net, r.arp_dev);
deffd7775   Changli Gao   net: arp: code cl...
1156
  		if (dev == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
  			goto out;
  
  		/* Mmmm... It is wrong... ARPHRD_NETROM==0 */
  		if (!r.arp_ha.sa_family)
  			r.arp_ha.sa_family = dev->type;
  		err = -EINVAL;
  		if ((r.arp_flags & ATF_COM) && r.arp_ha.sa_family != dev->type)
  			goto out;
  	} else if (cmd == SIOCGARP) {
  		err = -ENODEV;
  		goto out;
  	}
132adf546   Stephen Hemminger   [IPV4]: cleanup
1169
  	switch (cmd) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1170
  	case SIOCDARP:
32e569b72   Pavel Emelyanov   [IPV4]: Pass the ...
1171
  		err = arp_req_delete(net, &r, dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1172
1173
  		break;
  	case SIOCSARP:
32e569b72   Pavel Emelyanov   [IPV4]: Pass the ...
1174
  		err = arp_req_set(net, &r, dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1175
1176
1177
  		break;
  	case SIOCGARP:
  		err = arp_req_get(&r, dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1178
1179
1180
  		break;
  	}
  out:
c506653d3   Eric Dumazet   net: arp_ioctl() ...
1181
  	rtnl_unlock();
941666c2e   Eric Dumazet   net: RCU conversi...
1182
1183
  	if (cmd == SIOCGARP && !err && copy_to_user(arg, &r, sizeof(r)))
  		err = -EFAULT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1184
1185
  	return err;
  }
deffd7775   Changli Gao   net: arp: code cl...
1186
1187
  static int arp_netdev_event(struct notifier_block *this, unsigned long event,
  			    void *ptr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1188
1189
1190
1191
1192
1193
  {
  	struct net_device *dev = ptr;
  
  	switch (event) {
  	case NETDEV_CHANGEADDR:
  		neigh_changeaddr(&arp_tbl, dev);
76e6ebfb4   Denis V. Lunev   netns: add namesp...
1194
  		rt_cache_flush(dev_net(dev), 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
  		break;
  	default:
  		break;
  	}
  
  	return NOTIFY_DONE;
  }
  
  static struct notifier_block arp_netdev_notifier = {
  	.notifier_call = arp_netdev_event,
  };
  
  /* Note, that it is not on notifier chain.
     It is necessary, that this routine was called after route cache will be
     flushed.
   */
  void arp_ifdown(struct net_device *dev)
  {
  	neigh_ifdown(&arp_tbl, dev);
  }
  
  
  /*
   *	Called once on startup.
   */
7546dd97d   Stephen Hemminger   net: convert usag...
1220
  static struct packet_type arp_packet_type __read_mostly = {
09640e636   Harvey Harrison   net: replace uses...
1221
  	.type =	cpu_to_be16(ETH_P_ARP),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
  	.func =	arp_rcv,
  };
  
  static int arp_proc_init(void);
  
  void __init arp_init(void)
  {
  	neigh_table_init(&arp_tbl);
  
  	dev_add_pack(&arp_packet_type);
  	arp_proc_init();
  #ifdef CONFIG_SYSCTL
54716e3be   Eric W. Biederman   net neigh: Decoup...
1234
  	neigh_sysctl_register(NULL, &arp_tbl.parms, "ipv4", NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1235
1236
1237
1238
1239
  #endif
  	register_netdevice_notifier(&arp_netdev_notifier);
  }
  
  #ifdef CONFIG_PROC_FS
40e4783ee   Igor Maravic   ipv4: arp: Cleanu...
1240
  #if IS_ENABLED(CONFIG_AX25)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
  
  /* ------------------------------------------------------------------------ */
  /*
   *	ax25 -> ASCII conversion
   */
  static char *ax2asc2(ax25_address *a, char *buf)
  {
  	char c, *s;
  	int n;
  
  	for (n = 0, s = buf; n < 6; n++) {
  		c = (a->ax25_call[n] >> 1) & 0x7F;
deffd7775   Changli Gao   net: arp: code cl...
1253
1254
  		if (c != ' ')
  			*s++ = c;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1255
  	}
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
1256

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1257
  	*s++ = '-';
deffd7775   Changli Gao   net: arp: code cl...
1258
1259
  	n = (a->ax25_call[6] >> 1) & 0x0F;
  	if (n > 9) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1260
1261
1262
  		*s++ = '1';
  		n -= 10;
  	}
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
1263

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1264
1265
1266
1267
  	*s++ = n + '0';
  	*s++ = '\0';
  
  	if (*buf == '\0' || *buf == '-')
deffd7775   Changli Gao   net: arp: code cl...
1268
  		return "*";
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1269
1270
  
  	return buf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1271
1272
1273
1274
1275
1276
1277
1278
1279
  }
  #endif /* CONFIG_AX25 */
  
  #define HBUFFERLEN 30
  
  static void arp_format_neigh_entry(struct seq_file *seq,
  				   struct neighbour *n)
  {
  	char hbuffer[HBUFFERLEN];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1280
1281
1282
1283
1284
1285
1286
  	int k, j;
  	char tbuf[16];
  	struct net_device *dev = n->dev;
  	int hatype = dev->type;
  
  	read_lock(&n->lock);
  	/* Convert hardware address to XX:XX:XX:XX ... form. */
40e4783ee   Igor Maravic   ipv4: arp: Cleanu...
1287
  #if IS_ENABLED(CONFIG_AX25)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1288
1289
1290
1291
1292
  	if (hatype == ARPHRD_AX25 || hatype == ARPHRD_NETROM)
  		ax2asc2((ax25_address *)n->ha, hbuffer);
  	else {
  #endif
  	for (k = 0, j = 0; k < HBUFFERLEN - 3 && j < dev->addr_len; j++) {
51f82a2b1   Denis Cheng   net/ipv4/arp.c: U...
1293
1294
  		hbuffer[k++] = hex_asc_hi(n->ha[j]);
  		hbuffer[k++] = hex_asc_lo(n->ha[j]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1295
1296
  		hbuffer[k++] = ':';
  	}
a3e8ee682   roel kluin   ipv4: ARP neigh p...
1297
1298
1299
  	if (k != 0)
  		--k;
  	hbuffer[k] = 0;
40e4783ee   Igor Maravic   ipv4: arp: Cleanu...
1300
  #if IS_ENABLED(CONFIG_AX25)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1301
1302
  	}
  #endif
673d57e72   Harvey Harrison   net: replace NIPQ...
1303
  	sprintf(tbuf, "%pI4", n->primary_key);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
  	seq_printf(seq, "%-16s 0x%-10x0x%-10x%s     *        %s
  ",
  		   tbuf, hatype, arp_state_to_flags(n), hbuffer, dev->name);
  	read_unlock(&n->lock);
  }
  
  static void arp_format_pneigh_entry(struct seq_file *seq,
  				    struct pneigh_entry *n)
  {
  	struct net_device *dev = n->dev;
  	int hatype = dev ? dev->type : 0;
  	char tbuf[16];
673d57e72   Harvey Harrison   net: replace NIPQ...
1316
  	sprintf(tbuf, "%pI4", n->key);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
  	seq_printf(seq, "%-16s 0x%-10x0x%-10x%s     *        %s
  ",
  		   tbuf, hatype, ATF_PUBL | ATF_PERM, "00:00:00:00:00:00",
  		   dev ? dev->name : "*");
  }
  
  static int arp_seq_show(struct seq_file *seq, void *v)
  {
  	if (v == SEQ_START_TOKEN) {
  		seq_puts(seq, "IP address       HW type     Flags       "
  			      "HW address            Mask     Device
  ");
  	} else {
  		struct neigh_seq_state *state = seq->private;
  
  		if (state->flags & NEIGH_SEQ_IS_PNEIGH)
  			arp_format_pneigh_entry(seq, v);
  		else
  			arp_format_neigh_entry(seq, v);
  	}
  
  	return 0;
  }
  
  static void *arp_seq_start(struct seq_file *seq, loff_t *pos)
  {
  	/* Don't want to confuse "arp -a" w/ magic entries,
  	 * so we tell the generic iterator to skip NUD_NOARP.
  	 */
  	return neigh_seq_start(seq, pos, &arp_tbl, NEIGH_SEQ_SKIP_NOARP);
  }
  
  /* ------------------------------------------------------------------------ */
f690808e1   Stephen Hemminger   [NET]: make seq_o...
1350
  static const struct seq_operations arp_seq_ops = {
deffd7775   Changli Gao   net: arp: code cl...
1351
1352
1353
1354
  	.start	= arp_seq_start,
  	.next	= neigh_seq_next,
  	.stop	= neigh_seq_stop,
  	.show	= arp_seq_show,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1355
1356
1357
1358
  };
  
  static int arp_seq_open(struct inode *inode, struct file *file)
  {
426b5303e   Eric W. Biederman   [NETNS]: Modify t...
1359
1360
  	return seq_open_net(inode, file, &arp_seq_ops,
  			    sizeof(struct neigh_seq_state));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1361
  }
9a32144e9   Arjan van de Ven   [PATCH] mark stru...
1362
  static const struct file_operations arp_seq_fops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1363
1364
1365
1366
  	.owner		= THIS_MODULE,
  	.open           = arp_seq_open,
  	.read           = seq_read,
  	.llseek         = seq_lseek,
426b5303e   Eric W. Biederman   [NETNS]: Modify t...
1367
  	.release	= seq_release_net,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1368
  };
ffc31d3d7   Denis V. Lunev   [NETNS]: /proc/ne...
1369
1370
  
  static int __net_init arp_net_init(struct net *net)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1371
  {
ffc31d3d7   Denis V. Lunev   [NETNS]: /proc/ne...
1372
  	if (!proc_net_fops_create(net, "arp", S_IRUGO, &arp_seq_fops))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1373
1374
1375
  		return -ENOMEM;
  	return 0;
  }
ffc31d3d7   Denis V. Lunev   [NETNS]: /proc/ne...
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
  static void __net_exit arp_net_exit(struct net *net)
  {
  	proc_net_remove(net, "arp");
  }
  
  static struct pernet_operations arp_net_ops = {
  	.init = arp_net_init,
  	.exit = arp_net_exit,
  };
  
  static int __init arp_proc_init(void)
  {
  	return register_pernet_subsys(&arp_net_ops);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1390
1391
1392
1393
1394
1395
1396
1397
  #else /* CONFIG_PROC_FS */
  
  static int __init arp_proc_init(void)
  {
  	return 0;
  }
  
  #endif /* CONFIG_PROC_FS */