Blame view

net/ipv4/arp.c 35.2 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
116
  #if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
  #include <net/atmclip.h>
  struct neigh_table *clip_tbl_hook;
4bc2f18ba   Eric Dumazet   net/ipv4: EXPORT_...
117
  EXPORT_SYMBOL(clip_tbl_hook);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
118
119
120
  #endif
  
  #include <asm/system.h>
deffd7775   Changli Gao   net: arp: code cl...
121
  #include <linux/uaccess.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
122
123
124
125
126
127
  
  #include <linux/netfilter_arp.h>
  
  /*
   *	Interface to generic neighbour cache.
   */
d6bf78171   Eric Dumazet   net neigh: RCU co...
128
  static u32 arp_hash(const void *pkey, const struct net_device *dev, __u32 rnd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
129
130
131
132
  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...
133
  static const struct neigh_ops arp_generic_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
134
135
136
137
138
  	.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
139
  };
89d69d2b7   Stephen Hemminger   net: make neigh_o...
140
  static const struct neigh_ops arp_hh_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
141
142
143
144
145
  	.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
146
  };
89d69d2b7   Stephen Hemminger   net: make neigh_o...
147
  static const struct neigh_ops arp_direct_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
148
  	.family =		AF_INET,
8f40b161d   David S. Miller   neigh: Pass neigh...
149
150
  	.output =		neigh_direct_output,
  	.connected_output =	neigh_direct_output,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
151
  };
a64de47c0   stephen hemminger   arp: remove unnec...
152
  static const struct neigh_ops arp_broken_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
153
154
155
156
157
  	.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
158
159
160
  };
  
  struct neigh_table arp_tbl = {
deffd7775   Changli Gao   net: arp: code cl...
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
  	.family		= AF_INET,
  	.entry_size	= sizeof(struct neighbour) + 4,
  	.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,
  		.queue_len		= 3,
  		.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
182
  	},
deffd7775   Changli Gao   net: arp: code cl...
183
184
185
186
  	.gc_interval	= 30 * HZ,
  	.gc_thresh1	= 128,
  	.gc_thresh2	= 512,
  	.gc_thresh3	= 1024,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
187
  };
4bc2f18ba   Eric Dumazet   net/ipv4: EXPORT_...
188
  EXPORT_SYMBOL(arp_tbl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
189

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
236
237
238
239
  	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...
240
  	if (!dev->header_ops) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
241
242
  		neigh->nud_state = NUD_NOARP;
  		neigh->ops = &arp_direct_ops;
8f40b161d   David S. Miller   neigh: Pass neigh...
243
  		neigh->output = neigh_direct_output;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
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
  	} 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...
275
  		case ARPHRD_ROSE:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
276
277
278
279
280
281
282
283
  #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
  		case ARPHRD_AX25:
  #if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE)
  		case ARPHRD_NETROM:
  #endif
  			neigh->ops = &arp_broken_ops;
  			neigh->output = neigh->ops->output;
  			return 0;
deffd7775   Changli Gao   net: arp: code cl...
284
285
  #else
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
286
  #endif
deffd7775   Changli Gao   net: arp: code cl...
287
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
288
289
290
291
  #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...
292
  		} else if (dev->flags & (IFF_NOARP | IFF_LOOPBACK)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
293
294
  			neigh->nud_state = NUD_NOARP;
  			memcpy(neigh->ha, dev->dev_addr, dev->addr_len);
deffd7775   Changli Gao   net: arp: code cl...
295
296
  		} else if (neigh->type == RTN_BROADCAST ||
  			   (dev->flags & IFF_POINTOPOINT)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
297
298
299
  			neigh->nud_state = NUD_NOARP;
  			memcpy(neigh->ha, dev->broadcast, dev->addr_len);
  		}
3b04ddde0   Stephen Hemminger   [NET]: Move hardw...
300
301
  
  		if (dev->header_ops->cache)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
302
303
304
  			neigh->ops = &arp_hh_ops;
  		else
  			neigh->ops = &arp_generic_ops;
3b04ddde0   Stephen Hemminger   [NET]: Move hardw...
305

deffd7775   Changli Gao   net: arp: code cl...
306
  		if (neigh->nud_state & NUD_VALID)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
  			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...
322
  	__be32 saddr = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
323
324
  	u8  *dst_ha = NULL;
  	struct net_device *dev = neigh->dev;
deffd7775   Changli Gao   net: arp: code cl...
325
  	__be32 target = *(__be32 *)neigh->primary_key;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
326
  	int probes = atomic_read(&neigh->probes);
4b4194c40   Eric Dumazet   arp: RCU change i...
327
  	struct in_device *in_dev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
328

4b4194c40   Eric Dumazet   arp: RCU change i...
329
330
331
332
  	rcu_read_lock();
  	in_dev = __in_dev_get_rcu(dev);
  	if (!in_dev) {
  		rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
333
  		return;
4b4194c40   Eric Dumazet   arp: RCU change i...
334
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
335
336
337
  	switch (IN_DEV_ARP_ANNOUNCE(in_dev)) {
  	default:
  	case 0:		/* By default announce any local IP */
deffd7775   Changli Gao   net: arp: code cl...
338
339
  		if (skb && inet_addr_type(dev_net(dev),
  					  ip_hdr(skb)->saddr) == RTN_LOCAL)
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
340
  			saddr = ip_hdr(skb)->saddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
341
342
343
344
  		break;
  	case 1:		/* Restrict announcements of saddr in same subnet */
  		if (!skb)
  			break;
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
345
  		saddr = ip_hdr(skb)->saddr;
c346dca10   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
346
  		if (inet_addr_type(dev_net(dev), saddr) == RTN_LOCAL) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
347
348
349
350
351
352
353
354
355
  			/* 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...
356
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
357

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
358
359
  	if (!saddr)
  		saddr = inet_select_addr(dev, target, RT_SCOPE_LINK);
deffd7775   Changli Gao   net: arp: code cl...
360
361
362
363
364
365
  	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
366
  		dst_ha = neigh->ha;
9ff566074   David S. Miller   Revert "[NDISC]: ...
367
  		read_lock_bh(&neigh->lock);
deffd7775   Changli Gao   net: arp: code cl...
368
369
370
  	} else {
  		probes -= neigh->parms->app_probes;
  		if (probes < 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
371
  #ifdef CONFIG_ARPD
deffd7775   Changli Gao   net: arp: code cl...
372
  			neigh_app_ns(neigh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
373
  #endif
deffd7775   Changli Gao   net: arp: code cl...
374
375
  			return;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
376
377
378
379
  	}
  
  	arp_send(ARPOP_REQUEST, ETH_P_ARP, target, dev, saddr,
  		 dst_ha, dev->dev_addr, NULL);
9ff566074   David S. Miller   Revert "[NDISC]: ...
380
381
  	if (dst_ha)
  		read_unlock_bh(&neigh->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
382
  }
9bd85e326   Denis V. Lunev   [IPV4]: Remove ex...
383
  static int arp_ignore(struct in_device *in_dev, __be32 sip, __be32 tip)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
  {
  	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
403
404
405
406
407
408
409
410
411
412
413
  		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...
414
  	return !inet_confirm_addr(in_dev, sip, tip, scope);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
415
  }
ed9bad06e   Al Viro   [IPV4] net/ipv4/a...
416
  static int arp_filter(__be32 sip, __be32 tip, struct net_device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
417
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
418
  	struct rtable *rt;
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
419
  	int flag = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
420
  	/*unsigned long now; */
ca12a1a44   Pavel Emelyanov   inet: prepare net...
421
  	struct net *net = dev_net(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
422

78fbfd8a6   David S. Miller   ipv4: Create and ...
423
  	rt = ip_route_output(net, sip, tip, 0, 0);
b23dd4fe4   David S. Miller   ipv4: Make output...
424
  	if (IS_ERR(rt))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
425
  		return 1;
d8d1f30b9   Changli Gao   net-next: remove ...
426
  	if (rt->dst.dev != dev) {
de0744af1   Pavel Emelyanov   mib: add net to N...
427
  		NET_INC_STATS_BH(net, LINUX_MIB_ARPFILTER);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
428
  		flag = 1;
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
429
430
431
432
  	}
  	ip_rt_put(rt);
  	return flag;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
433
434
435
436
437
438
439
440
441
442
443
  
  /* 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...
444
445
  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
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
  {
  	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...
467
  	__be32 paddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
468
  	struct neighbour *n;
adf30907d   Eric Dumazet   net: skb->dst acc...
469
  	if (!skb_dst(skb)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
470
471
472
473
474
  		printk(KERN_DEBUG "arp_find is called with dst==NULL
  ");
  		kfree_skb(skb);
  		return 1;
  	}
511c3f92a   Eric Dumazet   net: skb->rtable ...
475
  	paddr = skb_rtable(skb)->rt_gateway;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
476

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

a02cec215   Eric Dumazet   net: return opera...
521
  	return omi != imi && omi != -1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
522
523
524
  }
  
  /*
65324144b   Jesper Dangaard Brouer   net: RFC3069, pri...
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
   * 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 ...
548
  	if (rt->dst.dev != dev)
65324144b   Jesper Dangaard Brouer   net: RFC3069, pri...
549
550
551
552
553
554
555
556
557
558
559
560
561
  		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
562
563
564
565
566
567
568
   *	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...
569
570
  struct sk_buff *arp_create(int type, int ptype, __be32 dest_ip,
  			   struct net_device *dev, __be32 src_ip,
abfdf1c48   Jan Engelhardt   [NETFILTER]: ebta...
571
572
573
  			   const unsigned char *dest_hw,
  			   const unsigned char *src_hw,
  			   const unsigned char *target_hw)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
574
575
576
577
578
579
580
581
  {
  	struct sk_buff *skb;
  	struct arphdr *arp;
  	unsigned char *arp_ptr;
  
  	/*
  	 *	Allocate a buffer
  	 */
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
582

f5184d267   Johannes Berg   net: Allow netdev...
583
  	skb = alloc_skb(arp_hdr_len(dev) + LL_ALLOCATED_SPACE(dev), GFP_ATOMIC);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
584
585
586
587
  	if (skb == NULL)
  		return NULL;
  
  	skb_reserve(skb, LL_RESERVED_SPACE(dev));
c1d2bbe1c   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
588
  	skb_reset_network_header(skb);
988b70507   Pavel Emelyanov   [ARP]: Introduce ...
589
  	arp = (struct arphdr *) skb_put(skb, arp_hdr_len(dev));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
590
591
592
593
594
595
596
597
598
599
  	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...
600
  	if (dev_hard_header(skb, dev, ptype, dest_hw, src_hw, skb->len) < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
  		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;
  
  #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
  	case ARPHRD_AX25:
  		arp->ar_hrd = htons(ARPHRD_AX25);
  		arp->ar_pro = htons(AX25_P_IP);
  		break;
  
  #if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE)
  	case ARPHRD_NETROM:
  		arp->ar_hrd = htons(ARPHRD_NETROM);
  		arp->ar_pro = htons(AX25_P_IP);
  		break;
  #endif
  #endif
f0ecde146   David S. Miller   net: Fix FDDI and...
632
  #if defined(CONFIG_FDDI) || defined(CONFIG_FDDI_MODULE)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
633
634
635
636
637
  	case ARPHRD_FDDI:
  		arp->ar_hrd = htons(ARPHRD_ETHER);
  		arp->ar_pro = htons(ETH_P_IP);
  		break;
  #endif
f0ecde146   David S. Miller   net: Fix FDDI and...
638
  #if defined(CONFIG_TR) || defined(CONFIG_TR_MODULE)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
639
640
641
642
643
644
645
646
647
648
  	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...
649
  	arp_ptr = (unsigned char *)(arp + 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
650
651
  
  	memcpy(arp_ptr, src_hw, dev->addr_len);
f4cca7ffb   Jianjun Kong   net: clean up net...
652
653
654
  	arp_ptr += dev->addr_len;
  	memcpy(arp_ptr, &src_ip, 4);
  	arp_ptr += 4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
655
656
657
658
  	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...
659
  	arp_ptr += dev->addr_len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
660
661
662
663
664
665
666
667
  	memcpy(arp_ptr, &dest_ip, 4);
  
  	return skb;
  
  out:
  	kfree_skb(skb);
  	return NULL;
  }
4bc2f18ba   Eric Dumazet   net/ipv4: EXPORT_...
668
  EXPORT_SYMBOL(arp_create);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
669
670
671
672
673
674
675
  
  /*
   *	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...
676
  	NF_HOOK(NFPROTO_ARP, NF_ARP_OUT, skb, NULL, skb->dev, dev_queue_xmit);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
677
  }
4bc2f18ba   Eric Dumazet   net/ipv4: EXPORT_...
678
  EXPORT_SYMBOL(arp_xmit);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
679
680
681
682
  
  /*
   *	Create and send an arp packet.
   */
ed9bad06e   Al Viro   [IPV4] net/ipv4/a...
683
684
  void arp_send(int type, int ptype, __be32 dest_ip,
  	      struct net_device *dev, __be32 src_ip,
abfdf1c48   Jan Engelhardt   [NETFILTER]: ebta...
685
686
  	      const unsigned char *dest_hw, const unsigned char *src_hw,
  	      const unsigned char *target_hw)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
687
688
689
690
691
692
  {
  	struct sk_buff *skb;
  
  	/*
  	 *	No arp on this interface.
  	 */
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
693

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
694
695
696
697
698
  	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...
699
  	if (skb == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
700
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
701
702
703
  
  	arp_xmit(skb);
  }
4bc2f18ba   Eric Dumazet   net/ipv4: EXPORT_...
704
  EXPORT_SYMBOL(arp_send);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
705

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
706
707
708
709
710
711
712
  /*
   *	Process an arp request.
   */
  
  static int arp_process(struct sk_buff *skb)
  {
  	struct net_device *dev = skb->dev;
faa9dcf79   Eric Dumazet   arp: RCU changes
713
  	struct in_device *in_dev = __in_dev_get_rcu(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
714
715
716
  	struct arphdr *arp;
  	unsigned char *arp_ptr;
  	struct rtable *rt;
e0260fedd   Mark Ryden   [IPV4] ARP: Remov...
717
  	unsigned char *sha;
9e12bb22e   Al Viro   [IPV4]: ip_route_...
718
  	__be32 sip, tip;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
719
720
721
  	u16 dev_type = dev->type;
  	int addr_type;
  	struct neighbour *n;
c346dca10   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
722
  	struct net *net = dev_net(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
723
724
725
726
727
728
729
  
  	/* 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...
730
  	arp = arp_hdr(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
731
732
  
  	switch (dev_type) {
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
733
  	default:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
734
735
736
737
  		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
738
  	case ARPHRD_ETHER:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
739
  	case ARPHRD_IEEE802_TR:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
740
  	case ARPHRD_FDDI:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
741
  	case ARPHRD_IEEE802:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
742
743
744
745
746
747
748
749
750
751
752
753
754
755
  		/*
  		 * 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
756
757
758
759
760
  	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
761
762
763
764
765
  	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
766
767
768
769
770
771
772
773
774
775
776
  	}
  
  	/* 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...
777
  	arp_ptr = (unsigned char *)(arp + 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
778
779
780
781
  	sha	= arp_ptr;
  	arp_ptr += dev->addr_len;
  	memcpy(&sip, arp_ptr, 4);
  	arp_ptr += 4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
782
783
  	arp_ptr += dev->addr_len;
  	memcpy(&tip, arp_ptr, 4);
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
784
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
785
786
787
   *	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: ...
788
  	if (ipv4_is_loopback(tip) || ipv4_is_multicast(tip))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
789
790
791
792
793
794
795
796
797
798
799
800
  		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...
801
802
803
804
   *  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
805
   *  our cache, since ours is not in their cache.)
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
806
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
807
808
809
   *  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...
810
   *  and in the case of requests for us we add the requester to the arp
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
811
812
   *  cache.
   */
f8a68e752   Eric W. Biederman   Revert "ipv4: arp...
813
814
  	/* Special case: IPv4 duplicate address detection packet (RFC2131) */
  	if (sip == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
815
  		if (arp->ar_op == htons(ARPOP_REQUEST) &&
49e8a279a   Denis V. Lunev   [NETNS]: Process ...
816
  		    inet_addr_type(net, tip) == RTN_LOCAL &&
9bd85e326   Denis V. Lunev   [IPV4]: Remove ex...
817
  		    !arp_ignore(in_dev, sip, tip))
b4a9811c4   Jonas Danielsson   [ARP]: Fix arp re...
818
819
  			arp_send(ARPOP_REPLY, ETH_P_ARP, sip, dev, tip, sha,
  				 dev->dev_addr, sha);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
820
821
822
823
  		goto out;
  	}
  
  	if (arp->ar_op == htons(ARPOP_REQUEST) &&
4a94445c9   Eric Dumazet   net: Use ip_route...
824
  	    ip_route_input_noref(skb, tip, sip, 0, dev) == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
825

511c3f92a   Eric Dumazet   net: skb->rtable ...
826
  		rt = skb_rtable(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
827
828
829
  		addr_type = rt->rt_type;
  
  		if (addr_type == RTN_LOCAL) {
deffd7775   Changli Gao   net: arp: code cl...
830
  			int dont_send;
8164f1b79   Ben Greear   ipv4: Fix ARP beh...
831

deffd7775   Changli Gao   net: arp: code cl...
832
  			dont_send = arp_ignore(in_dev, sip, tip);
8164f1b79   Ben Greear   ipv4: Fix ARP beh...
833
  			if (!dont_send && IN_DEV_ARPFILTER(in_dev))
ae9c416d6   Changli Gao   net: arp: use ass...
834
  				dont_send = arp_filter(sip, tip, dev);
8164f1b79   Ben Greear   ipv4: Fix ARP beh...
835
836
837
  			if (!dont_send) {
  				n = neigh_event_ns(&arp_tbl, sha, &sip, dev);
  				if (n) {
deffd7775   Changli Gao   net: arp: code cl...
838
839
840
  					arp_send(ARPOP_REPLY, ETH_P_ARP, sip,
  						 dev, tip, sha, dev->dev_addr,
  						 sha);
8164f1b79   Ben Greear   ipv4: Fix ARP beh...
841
842
  					neigh_release(n);
  				}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
843
844
845
  			}
  			goto out;
  		} else if (IN_DEV_FORWARD(in_dev)) {
65324144b   Jesper Dangaard Brouer   net: RFC3069, pri...
846
847
848
  			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...
849
  			     pneigh_lookup(&arp_tbl, net, &tip, dev, 0))) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
850
851
852
  				n = neigh_event_ns(&arp_tbl, sha, &sip, dev);
  				if (n)
  					neigh_release(n);
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
853
  				if (NEIGH_CB(skb)->flags & LOCALLY_ENQUEUED ||
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
854
855
  				    skb->pkt_type == PACKET_HOST ||
  				    in_dev->arp_parms->proxy_delay == 0) {
deffd7775   Changli Gao   net: arp: code cl...
856
857
858
  					arp_send(ARPOP_REPLY, ETH_P_ARP, sip,
  						 dev, tip, sha, dev->dev_addr,
  						 sha);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
859
  				} else {
deffd7775   Changli Gao   net: arp: code cl...
860
861
  					pneigh_enqueue(&arp_tbl,
  						       in_dev->arp_parms, skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
862
863
864
865
866
867
868
869
870
871
  					return 0;
  				}
  				goto out;
  			}
  		}
  	}
  
  	/* Update our ARP tables */
  
  	n = __neigh_lookup(&arp_tbl, &sip, dev, 0);
c346dca10   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
872
  	if (IPV4_DEVCONF_ALL(dev_net(dev), ARP_ACCEPT)) {
abd596a4b   Neil Horman   [IPV4] ARP: Alloc...
873
874
875
876
877
  		/* 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...
878
879
  		    (arp->ar_op == htons(ARPOP_REPLY) ||
  		     (arp->ar_op == htons(ARPOP_REQUEST) && tip == sip)) &&
49e8a279a   Denis V. Lunev   [NETNS]: Process ...
880
  		    inet_addr_type(net, sip) == RTN_UNICAST)
1b1ac759d   Jean Delvare   [IPV4]: Cleanup c...
881
  			n = __neigh_lookup(&arp_tbl, &sip, dev, 1);
abd596a4b   Neil Horman   [IPV4] ARP: Alloc...
882
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
  
  	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...
901
902
  		neigh_update(n, sha, state,
  			     override ? NEIGH_UPDATE_F_OVERRIDE : 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
903
904
905
906
  		neigh_release(n);
  	}
  
  out:
ead2ceb0e   Neil Horman   Network Drop Moni...
907
  	consume_skb(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
908
909
  	return 0;
  }
444fc8fc3   Herbert Xu   [IPV4]: Fix "Prox...
910
911
912
913
  static void parp_redo(struct sk_buff *skb)
  {
  	arp_process(skb);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
914
915
916
917
  
  /*
   *	Receive an arp request from the device layer.
   */
6c97e72a1   Adrian Bunk   [IPV4]: Possible ...
918
919
  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
920
921
922
923
  {
  	struct arphdr *arp;
  
  	/* ARP header, plus 2 device addresses, plus 2 IP addresses.  */
988b70507   Pavel Emelyanov   [ARP]: Introduce ...
924
  	if (!pskb_may_pull(skb, arp_hdr_len(dev)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
925
  		goto freeskb;
d0a92be05   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
926
  	arp = arp_hdr(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
927
928
929
930
931
932
  	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...
933
934
  	skb = skb_share_check(skb, GFP_ATOMIC);
  	if (skb == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
935
  		goto out_of_mem;
a61bbcf28   Patrick McHardy   [NET]: Store skb-...
936
  	memset(NEIGH_CB(skb), 0, sizeof(struct neighbour_cb));
fdc9314cb   Jan Engelhardt   netfilter: replac...
937
  	return NF_HOOK(NFPROTO_ARP, NF_ARP_IN, skb, dev, NULL, arp_process);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
938
939
940
941
942
943
944
945
946
947
948
949
950
951
  
  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 ...
952
  static int arp_req_set_proxy(struct net *net, struct net_device *dev, int on)
f8b33fdfa   Pavel Emelyanov   [ARP]: Consolidat...
953
954
  {
  	if (dev == NULL) {
586f12115   Pavel Emelyanov   [IPV4]: Switch us...
955
  		IPV4_DEVCONF_ALL(net, PROXY_ARP) = on;
f8b33fdfa   Pavel Emelyanov   [ARP]: Consolidat...
956
957
  		return 0;
  	}
c506653d3   Eric Dumazet   net: arp_ioctl() ...
958
959
  	if (__in_dev_get_rtnl(dev)) {
  		IN_DEV_CONF_SET(__in_dev_get_rtnl(dev), PROXY_ARP, on);
f8b33fdfa   Pavel Emelyanov   [ARP]: Consolidat...
960
961
962
963
  		return 0;
  	}
  	return -ENXIO;
  }
32e569b72   Pavel Emelyanov   [IPV4]: Pass the ...
964
965
  static int arp_req_set_public(struct net *net, struct arpreq *r,
  		struct net_device *dev)
43dc17011   Pavel Emelyanov   [ARP]: Minus one ...
966
967
968
969
970
971
972
  {
  	__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...
973
  		dev = dev_getbyhwaddr_rcu(net, r->arp_ha.sa_family,
deffd7775   Changli Gao   net: arp: code cl...
974
  				      r->arp_ha.sa_data);
43dc17011   Pavel Emelyanov   [ARP]: Minus one ...
975
976
977
978
  		if (!dev)
  			return -ENODEV;
  	}
  	if (mask) {
2db82b534   Denis V. Lunev   [NETNS]: Make arp...
979
  		if (pneigh_lookup(&arp_tbl, net, &ip, dev, 1) == NULL)
43dc17011   Pavel Emelyanov   [ARP]: Minus one ...
980
981
982
  			return -ENOBUFS;
  		return 0;
  	}
f8b33fdfa   Pavel Emelyanov   [ARP]: Consolidat...
983

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

43dc17011   Pavel Emelyanov   [ARP]: Minus one ...
995
  	ip = ((struct sockaddr_in *)&r->arp_pa)->sin_addr.s_addr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
996
997
998
  	if (r->arp_flags & ATF_PERM)
  		r->arp_flags |= ATF_COM;
  	if (dev == NULL) {
78fbfd8a6   David S. Miller   ipv4: Create and ...
999
  		struct rtable *rt = ip_route_output(net, ip, 0, RTO_ONLINK, 0);
b23dd4fe4   David S. Miller   ipv4: Make output...
1000
1001
1002
  
  		if (IS_ERR(rt))
  			return PTR_ERR(rt);
d8d1f30b9   Changli Gao   net-next: remove ...
1003
  		dev = rt->dst.dev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1004
1005
1006
1007
1008
  		ip_rt_put(rt);
  		if (!dev)
  			return -EINVAL;
  	}
  	switch (dev->type) {
f0ecde146   David S. Miller   net: Fix FDDI and...
1009
  #if defined(CONFIG_FDDI) || defined(CONFIG_FDDI_MODULE)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
  	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...
1035
  		err = neigh_update(neigh, (r->arp_flags & ATF_COM) ?
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
1036
  				   r->arp_ha.sa_data : NULL, state,
deffd7775   Changli Gao   net: arp: code cl...
1037
  				   NEIGH_UPDATE_F_OVERRIDE |
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1038
1039
1040
1041
1042
1043
1044
1045
  				   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
1046
  	if (neigh->nud_state&NUD_PERMANENT)
deffd7775   Changli Gao   net: arp: code cl...
1047
  		return ATF_PERM | ATF_COM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1048
  	else if (neigh->nud_state&NUD_VALID)
deffd7775   Changli Gao   net: arp: code cl...
1049
1050
1051
  		return ATF_COM;
  	else
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1052
1053
1054
1055
1056
1057
1058
1059
  }
  
  /*
   *	Get an ARP cache entry.
   */
  
  static int arp_req_get(struct arpreq *r, struct net_device *dev)
  {
ed9bad06e   Al Viro   [IPV4] net/ipv4/a...
1060
  	__be32 ip = ((struct sockaddr_in *) &r->arp_pa)->sin_addr.s_addr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
  	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...
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
  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 ...
1093
1094
  static int arp_req_delete_public(struct net *net, struct arpreq *r,
  		struct net_device *dev)
46479b432   Pavel Emelyanov   [ARP]: Minus one ...
1095
1096
1097
1098
1099
  {
  	__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...
1100
  		return pneigh_delete(&arp_tbl, net, &ip, dev);
46479b432   Pavel Emelyanov   [ARP]: Minus one ...
1101

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

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

46479b432   Pavel Emelyanov   [ARP]: Minus one ...
1114
  	ip = ((struct sockaddr_in *)&r->arp_pa)->sin_addr.s_addr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1115
  	if (dev == NULL) {
78fbfd8a6   David S. Miller   ipv4: Create and ...
1116
  		struct rtable *rt = ip_route_output(net, ip, 0, RTO_ONLINK, 0);
b23dd4fe4   David S. Miller   ipv4: Make output...
1117
1118
  		if (IS_ERR(rt))
  			return PTR_ERR(rt);
d8d1f30b9   Changli Gao   net-next: remove ...
1119
  		dev = rt->dst.dev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1120
1121
1122
1123
  		ip_rt_put(rt);
  		if (!dev)
  			return -EINVAL;
  	}
545ecdc3b   Maxim Levitsky   arp: allow to inv...
1124
  	return arp_invalidate(dev, ip);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1125
1126
1127
1128
1129
  }
  
  /*
   *	Handle an ARP layer I/O control request.
   */
32e569b72   Pavel Emelyanov   [IPV4]: Pass the ...
1130
  int arp_ioctl(struct net *net, unsigned int cmd, void __user *arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1131
1132
1133
1134
1135
1136
  {
  	int err;
  	struct arpreq r;
  	struct net_device *dev = NULL;
  
  	switch (cmd) {
deffd7775   Changli Gao   net: arp: code cl...
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
  	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
1148
1149
1150
1151
1152
1153
  	}
  
  	if (r.arp_pa.sa_family != AF_INET)
  		return -EPFNOSUPPORT;
  
  	if (!(r.arp_flags & ATF_PUBL) &&
deffd7775   Changli Gao   net: arp: code cl...
1154
  	    (r.arp_flags & (ATF_NETMASK | ATF_DONTPUB)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1155
1156
1157
1158
  		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() ...
1159
  	rtnl_lock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1160
1161
  	if (r.arp_dev[0]) {
  		err = -ENODEV;
c506653d3   Eric Dumazet   net: arp_ioctl() ...
1162
  		dev = __dev_get_by_name(net, r.arp_dev);
deffd7775   Changli Gao   net: arp: code cl...
1163
  		if (dev == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
  			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
1176
  	switch (cmd) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1177
  	case SIOCDARP:
32e569b72   Pavel Emelyanov   [IPV4]: Pass the ...
1178
  		err = arp_req_delete(net, &r, dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1179
1180
  		break;
  	case SIOCSARP:
32e569b72   Pavel Emelyanov   [IPV4]: Pass the ...
1181
  		err = arp_req_set(net, &r, dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1182
1183
1184
  		break;
  	case SIOCGARP:
  		err = arp_req_get(&r, dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1185
1186
1187
  		break;
  	}
  out:
c506653d3   Eric Dumazet   net: arp_ioctl() ...
1188
  	rtnl_unlock();
941666c2e   Eric Dumazet   net: RCU conversi...
1189
1190
  	if (cmd == SIOCGARP && !err && copy_to_user(arg, &r, sizeof(r)))
  		err = -EFAULT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1191
1192
  	return err;
  }
deffd7775   Changli Gao   net: arp: code cl...
1193
1194
  static int arp_netdev_event(struct notifier_block *this, unsigned long event,
  			    void *ptr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1195
1196
1197
1198
1199
1200
  {
  	struct net_device *dev = ptr;
  
  	switch (event) {
  	case NETDEV_CHANGEADDR:
  		neigh_changeaddr(&arp_tbl, dev);
76e6ebfb4   Denis V. Lunev   netns: add namesp...
1201
  		rt_cache_flush(dev_net(dev), 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
  		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...
1227
  static struct packet_type arp_packet_type __read_mostly = {
09640e636   Harvey Harrison   net: replace uses...
1228
  	.type =	cpu_to_be16(ETH_P_ARP),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
  	.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...
1241
  	neigh_sysctl_register(NULL, &arp_tbl.parms, "ipv4", NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
  #endif
  	register_netdevice_notifier(&arp_netdev_notifier);
  }
  
  #ifdef CONFIG_PROC_FS
  #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
  
  /* ------------------------------------------------------------------------ */
  /*
   *	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...
1260
1261
  		if (c != ' ')
  			*s++ = c;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1262
  	}
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
1263

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1264
  	*s++ = '-';
deffd7775   Changli Gao   net: arp: code cl...
1265
1266
  	n = (a->ax25_call[6] >> 1) & 0x0F;
  	if (n > 9) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1267
1268
1269
  		*s++ = '1';
  		n -= 10;
  	}
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
1270

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1271
1272
1273
1274
  	*s++ = n + '0';
  	*s++ = '\0';
  
  	if (*buf == '\0' || *buf == '-')
deffd7775   Changli Gao   net: arp: code cl...
1275
  		return "*";
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1276
1277
  
  	return buf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1278
1279
1280
1281
1282
1283
1284
1285
1286
  }
  #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
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
  	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. */
  #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
  	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...
1300
1301
  		hbuffer[k++] = hex_asc_hi(n->ha[j]);
  		hbuffer[k++] = hex_asc_lo(n->ha[j]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1302
1303
  		hbuffer[k++] = ':';
  	}
a3e8ee682   roel kluin   ipv4: ARP neigh p...
1304
1305
1306
  	if (k != 0)
  		--k;
  	hbuffer[k] = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1307
1308
1309
  #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
  	}
  #endif
673d57e72   Harvey Harrison   net: replace NIPQ...
1310
  	sprintf(tbuf, "%pI4", n->primary_key);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
  	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...
1323
  	sprintf(tbuf, "%pI4", n->key);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
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
1350
1351
1352
1353
1354
1355
1356
  	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...
1357
  static const struct seq_operations arp_seq_ops = {
deffd7775   Changli Gao   net: arp: code cl...
1358
1359
1360
1361
  	.start	= arp_seq_start,
  	.next	= neigh_seq_next,
  	.stop	= neigh_seq_stop,
  	.show	= arp_seq_show,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1362
1363
1364
1365
  };
  
  static int arp_seq_open(struct inode *inode, struct file *file)
  {
426b5303e   Eric W. Biederman   [NETNS]: Modify t...
1366
1367
  	return seq_open_net(inode, file, &arp_seq_ops,
  			    sizeof(struct neigh_seq_state));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1368
  }
9a32144e9   Arjan van de Ven   [PATCH] mark stru...
1369
  static const struct file_operations arp_seq_fops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1370
1371
1372
1373
  	.owner		= THIS_MODULE,
  	.open           = arp_seq_open,
  	.read           = seq_read,
  	.llseek         = seq_lseek,
426b5303e   Eric W. Biederman   [NETNS]: Modify t...
1374
  	.release	= seq_release_net,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1375
  };
ffc31d3d7   Denis V. Lunev   [NETNS]: /proc/ne...
1376
1377
  
  static int __net_init arp_net_init(struct net *net)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1378
  {
ffc31d3d7   Denis V. Lunev   [NETNS]: /proc/ne...
1379
  	if (!proc_net_fops_create(net, "arp", S_IRUGO, &arp_seq_fops))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1380
1381
1382
  		return -ENOMEM;
  	return 0;
  }
ffc31d3d7   Denis V. Lunev   [NETNS]: /proc/ne...
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
  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
1397
1398
1399
1400
1401
1402
1403
1404
  #else /* CONFIG_PROC_FS */
  
  static int __init arp_proc_init(void)
  {
  	return 0;
  }
  
  #endif /* CONFIG_PROC_FS */