Blame view

net/ipv4/arp.c 36 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
   */
91df42bed   Joe Perches   net: ipv4 and ipv...
75
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
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
  #include <linux/netdevice.h>
  #include <linux/etherdevice.h>
  #include <linux/fddidevice.h>
  #include <linux/if_arp.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
92
93
94
95
96
97
98
  #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: ...
99
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
100
101
102
  #ifdef CONFIG_SYSCTL
  #include <linux/sysctl.h>
  #endif
457c4cbc5   Eric W. Biederman   [NET]: Make /proc...
103
  #include <net/net_namespace.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
104
105
106
107
108
109
110
  #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
111
  #include <net/ax25.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
112
  #include <net/netrom.h>
63d008a4e   Jiri Benc   ipv4: send arp re...
113
114
  #include <net/dst_metadata.h>
  #include <net/ip_tunnels.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
115

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);
60395a20f   Eric W. Biederman   neigh: Factor out...
124
  static bool arp_key_eq(const struct neighbour *n, const void *pkey);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
125
126
127
128
  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...
129
  static const struct neigh_ops arp_generic_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
130
131
132
133
134
  	.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
135
  };
89d69d2b7   Stephen Hemminger   net: make neigh_o...
136
  static const struct neigh_ops arp_hh_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
137
138
139
140
141
  	.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
142
  };
89d69d2b7   Stephen Hemminger   net: make neigh_o...
143
  static const struct neigh_ops arp_direct_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
144
  	.family =		AF_INET,
8f40b161d   David S. Miller   neigh: Pass neigh...
145
146
  	.output =		neigh_direct_output,
  	.connected_output =	neigh_direct_output,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
147
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
148
  struct neigh_table arp_tbl = {
deffd7775   Changli Gao   net: arp: code cl...
149
  	.family		= AF_INET,
deffd7775   Changli Gao   net: arp: code cl...
150
  	.key_len	= 4,
bdf53c584   Eric W. Biederman   neigh: Don't requ...
151
  	.protocol	= cpu_to_be16(ETH_P_IP),
deffd7775   Changli Gao   net: arp: code cl...
152
  	.hash		= arp_hash,
60395a20f   Eric W. Biederman   neigh: Factor out...
153
  	.key_eq		= arp_key_eq,
deffd7775   Changli Gao   net: arp: code cl...
154
155
156
157
158
  	.constructor	= arp_constructor,
  	.proxy_redo	= parp_redo,
  	.id		= "arp_cache",
  	.parms		= {
  		.tbl			= &arp_tbl,
deffd7775   Changli Gao   net: arp: code cl...
159
  		.reachable_time		= 30 * HZ,
1f9248e56   Jiri Pirko   neigh: convert pa...
160
161
162
163
164
165
166
  		.data	= {
  			[NEIGH_VAR_MCAST_PROBES] = 3,
  			[NEIGH_VAR_UCAST_PROBES] = 3,
  			[NEIGH_VAR_RETRANS_TIME] = 1 * HZ,
  			[NEIGH_VAR_BASE_REACHABLE_TIME] = 30 * HZ,
  			[NEIGH_VAR_DELAY_PROBE_TIME] = 5 * HZ,
  			[NEIGH_VAR_GC_STALETIME] = 60 * HZ,
eaa72dc47   Eric Dumazet   neigh: increase q...
167
  			[NEIGH_VAR_QUEUE_LEN_BYTES] = SK_WMEM_MAX,
1f9248e56   Jiri Pirko   neigh: convert pa...
168
169
170
171
172
  			[NEIGH_VAR_PROXY_QLEN] = 64,
  			[NEIGH_VAR_ANYCAST_DELAY] = 1 * HZ,
  			[NEIGH_VAR_PROXY_DELAY]	= (8 * HZ) / 10,
  			[NEIGH_VAR_LOCKTIME] = 1 * HZ,
  		},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
173
  	},
deffd7775   Changli Gao   net: arp: code cl...
174
175
176
177
  	.gc_interval	= 30 * HZ,
  	.gc_thresh1	= 128,
  	.gc_thresh2	= 512,
  	.gc_thresh3	= 1024,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
178
  };
4bc2f18ba   Eric Dumazet   net/ipv4: EXPORT_...
179
  EXPORT_SYMBOL(arp_tbl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
180

714e85be3   Al Viro   [IPV6]: Assorted ...
181
  int arp_mc_map(__be32 addr, u8 *haddr, struct net_device *dev, int dir)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
182
183
184
185
186
187
  {
  	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...
188
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
189
  	case ARPHRD_INFINIBAND:
a9e527e3f   Rolf Manderscheid   IPoIB: improve IP...
190
  		ip_ib_mc_map(addr, dev->broadcast, haddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
191
  		return 0;
93ca3bb5d   Timo Teräs   net: gre: provide...
192
193
194
  	case ARPHRD_IPGRE:
  		ip_ipgre_mc_map(addr, dev->broadcast, haddr);
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
195
196
197
198
199
200
201
202
  	default:
  		if (dir) {
  			memcpy(haddr, dev->broadcast, dev->addr_len);
  			return 0;
  		}
  	}
  	return -EINVAL;
  }
d6bf78171   Eric Dumazet   net neigh: RCU co...
203
204
  static u32 arp_hash(const void *pkey,
  		    const struct net_device *dev,
2c2aba6c5   David S. Miller   ipv6: Use univers...
205
  		    __u32 *hash_rnd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
206
  {
60395a20f   Eric W. Biederman   neigh: Factor out...
207
208
209
210
211
212
  	return arp_hashfn(pkey, dev, hash_rnd);
  }
  
  static bool arp_key_eq(const struct neighbour *neigh, const void *pkey)
  {
  	return neigh_key_eq32(neigh, pkey);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
213
214
215
216
  }
  
  static int arp_constructor(struct neighbour *neigh)
  {
42d68bf2a   Jim Westfall   ipv4: Make neigh ...
217
  	__be32 addr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
218
219
220
  	struct net_device *dev = neigh->dev;
  	struct in_device *in_dev;
  	struct neigh_parms *parms;
42d68bf2a   Jim Westfall   ipv4: Make neigh ...
221
  	u32 inaddr_any = INADDR_ANY;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
222

42d68bf2a   Jim Westfall   ipv4: Make neigh ...
223
224
225
226
  	if (dev->flags & (IFF_LOOPBACK | IFF_POINTOPOINT))
  		memcpy(neigh->primary_key, &inaddr_any, arp_tbl.key_len);
  
  	addr = *(__be32 *)neigh->primary_key;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
227
  	rcu_read_lock();
e5ed63991   Herbert Xu   [IPV4]: Replace _...
228
  	in_dev = __in_dev_get_rcu(dev);
51456b291   Ian Morris   ipv4: coding styl...
229
  	if (!in_dev) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
230
231
232
  		rcu_read_unlock();
  		return -EINVAL;
  	}
30bbaa195   David Ahern   net: Fix up inet_...
233
  	neigh->type = inet_addr_type_dev_table(dev_net(dev), dev, addr);
a79878f00   Denis V. Lunev   [ARP]: Move inet_...
234

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
235
236
237
238
  	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...
239
  	if (!dev->header_ops) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
240
241
  		neigh->nud_state = NUD_NOARP;
  		neigh->ops = &arp_direct_ops;
8f40b161d   David S. Miller   neigh: Pass neigh...
242
  		neigh->output = neigh_direct_output;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
  	} 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.
  		 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
258
259
260
  		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...
261
  		} else if (dev->flags & (IFF_NOARP | IFF_LOOPBACK)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
262
263
  			neigh->nud_state = NUD_NOARP;
  			memcpy(neigh->ha, dev->dev_addr, dev->addr_len);
deffd7775   Changli Gao   net: arp: code cl...
264
265
  		} else if (neigh->type == RTN_BROADCAST ||
  			   (dev->flags & IFF_POINTOPOINT)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
266
267
268
  			neigh->nud_state = NUD_NOARP;
  			memcpy(neigh->ha, dev->broadcast, dev->addr_len);
  		}
3b04ddde0   Stephen Hemminger   [NET]: Move hardw...
269
270
  
  		if (dev->header_ops->cache)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
271
272
273
  			neigh->ops = &arp_hh_ops;
  		else
  			neigh->ops = &arp_generic_ops;
3b04ddde0   Stephen Hemminger   [NET]: Move hardw...
274

deffd7775   Changli Gao   net: arp: code cl...
275
  		if (neigh->nud_state & NUD_VALID)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
276
277
278
279
280
281
282
283
284
285
286
287
  			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);
  }
0accfc268   Thomas Graf   arp: Inherit meta...
288
289
290
291
292
  /* Create and send an arp packet. */
  static void arp_send_dst(int type, int ptype, __be32 dest_ip,
  			 struct net_device *dev, __be32 src_ip,
  			 const unsigned char *dest_hw,
  			 const unsigned char *src_hw,
63d008a4e   Jiri Benc   ipv4: send arp re...
293
294
  			 const unsigned char *target_hw,
  			 struct dst_entry *dst)
0accfc268   Thomas Graf   arp: Inherit meta...
295
296
297
298
299
300
301
302
303
304
305
  {
  	struct sk_buff *skb;
  
  	/* arp on this interface. */
  	if (dev->flags & IFF_NOARP)
  		return;
  
  	skb = arp_create(type, ptype, dest_ip, dev, src_ip,
  			 dest_hw, src_hw, target_hw);
  	if (!skb)
  		return;
181a4224a   Jiri Benc   ipv4: fix reply_d...
306
  	skb_dst_set(skb, dst_clone(dst));
0accfc268   Thomas Graf   arp: Inherit meta...
307
308
309
310
311
312
313
314
315
316
317
318
  	arp_xmit(skb);
  }
  
  void arp_send(int type, int ptype, __be32 dest_ip,
  	      struct net_device *dev, __be32 src_ip,
  	      const unsigned char *dest_hw, const unsigned char *src_hw,
  	      const unsigned char *target_hw)
  {
  	arp_send_dst(type, ptype, dest_ip, dev, src_ip, dest_hw, src_hw,
  		     target_hw, NULL);
  }
  EXPORT_SYMBOL(arp_send);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
319
320
  static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb)
  {
a61ced5d1   Al Viro   [IPV4]: inet_sele...
321
  	__be32 saddr = 0;
cf0be8805   Cong Wang   arp: fix a regres...
322
  	u8 dst_ha[MAX_ADDR_LEN], *dst_hw = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
323
  	struct net_device *dev = neigh->dev;
deffd7775   Changli Gao   net: arp: code cl...
324
  	__be32 target = *(__be32 *)neigh->primary_key;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
325
  	int probes = atomic_read(&neigh->probes);
4b4194c40   Eric Dumazet   arp: RCU change i...
326
  	struct in_device *in_dev;
63d008a4e   Jiri Benc   ipv4: send arp re...
327
  	struct dst_entry *dst = NULL;
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 */
30bbaa195   David Ahern   net: Fix up inet_...
338
  		if (skb && inet_addr_type_dev_table(dev_net(dev), dev,
deffd7775   Changli Gao   net: arp: code cl...
339
  					  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;
30bbaa195   David Ahern   net: Fix up inet_...
346
347
  		if (inet_addr_type_dev_table(dev_net(dev), dev,
  					     saddr) == RTN_LOCAL) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
348
349
350
351
352
353
354
355
356
  			/* 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...
357
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
358

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
359
360
  	if (!saddr)
  		saddr = inet_select_addr(dev, target, RT_SCOPE_LINK);
1f9248e56   Jiri Pirko   neigh: convert pa...
361
  	probes -= NEIGH_VAR(neigh->parms, UCAST_PROBES);
deffd7775   Changli Gao   net: arp: code cl...
362
363
  	if (probes < 0) {
  		if (!(neigh->nud_state & NUD_VALID))
91df42bed   Joe Perches   net: ipv4 and ipv...
364
365
  			pr_debug("trying to ucast probe in NUD_INVALID
  ");
9650388b5   Eric Dumazet   ipv4: arp: fix a ...
366
  		neigh_ha_snapshot(dst_ha, neigh, dev);
cf0be8805   Cong Wang   arp: fix a regres...
367
  		dst_hw = dst_ha;
deffd7775   Changli Gao   net: arp: code cl...
368
  	} else {
1f9248e56   Jiri Pirko   neigh: convert pa...
369
  		probes -= NEIGH_VAR(neigh->parms, APP_PROBES);
deffd7775   Changli Gao   net: arp: code cl...
370
  		if (probes < 0) {
deffd7775   Changli Gao   net: arp: code cl...
371
  			neigh_app_ns(neigh);
deffd7775   Changli Gao   net: arp: code cl...
372
373
  			return;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
374
  	}
63d008a4e   Jiri Benc   ipv4: send arp re...
375
  	if (skb && !(dev->priv_flags & IFF_XMIT_DST_RELEASE))
181a4224a   Jiri Benc   ipv4: fix reply_d...
376
  		dst = skb_dst(skb);
0accfc268   Thomas Graf   arp: Inherit meta...
377
  	arp_send_dst(ARPOP_REQUEST, ETH_P_ARP, target, dev, saddr,
63d008a4e   Jiri Benc   ipv4: send arp re...
378
  		     dst_hw, dev->dev_addr, NULL, dst);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
379
  }
9bd85e326   Denis V. Lunev   [IPV4]: Remove ex...
380
  static int arp_ignore(struct in_device *in_dev, __be32 sip, __be32 tip)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
381
  {
b601fa197   Nicolas Dichtel   ipv4: fix wildcar...
382
  	struct net *net = dev_net(in_dev->dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
  	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;
b601fa197   Nicolas Dichtel   ipv4: fix wildcar...
401
  		in_dev = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
402
403
404
405
406
407
408
409
410
411
412
  		break;
  	case 4:	/* Reserved */
  	case 5:
  	case 6:
  	case 7:
  		return 0;
  	case 8:	/* Do not reply */
  		return 1;
  	default:
  		return 0;
  	}
b601fa197   Nicolas Dichtel   ipv4: fix wildcar...
413
  	return !inet_confirm_addr(net, in_dev, sip, tip, scope);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
414
  }
ed9bad06e   Al Viro   [IPV4] net/ipv4/a...
415
  static int arp_filter(__be32 sip, __be32 tip, struct net_device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
416
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
417
  	struct rtable *rt;
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
418
  	int flag = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
419
  	/*unsigned long now; */
ca12a1a44   Pavel Emelyanov   inet: prepare net...
420
  	struct net *net = dev_net(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
421

cdd74d6ac   Miguel Fadon Perlines   arp: fix arp_filt...
422
  	rt = ip_route_output(net, sip, tip, 0, l3mdev_master_ifindex_rcu(dev));
b23dd4fe4   David S. Miller   ipv4: Make output...
423
  	if (IS_ERR(rt))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
424
  		return 1;
d8d1f30b9   Changli Gao   net-next: remove ...
425
  	if (rt->dst.dev != dev) {
02a1d6e7a   Eric Dumazet   net: rename NET_{...
426
  		__NET_INC_STATS(net, LINUX_MIB_ARPFILTER);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
427
  		flag = 1;
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
428
429
430
431
  	}
  	ip_rt_put(rt);
  	return flag;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
432

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
433
434
435
  /*
   * Check if we can use proxy ARP for this path
   */
65324144b   Jesper Dangaard Brouer   net: RFC3069, pri...
436
437
  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
438
439
440
  {
  	struct in_device *out_dev;
  	int imi, omi = -1;
d8d1f30b9   Changli Gao   net-next: remove ...
441
  	if (rt->dst.dev == dev)
65324144b   Jesper Dangaard Brouer   net: RFC3069, pri...
442
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
443
444
  	if (!IN_DEV_PROXY_ARP(in_dev))
  		return 0;
deffd7775   Changli Gao   net: arp: code cl...
445
446
  	imi = IN_DEV_MEDIUM_ID(in_dev);
  	if (imi == 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
447
448
449
450
451
  		return 1;
  	if (imi == -1)
  		return 0;
  
  	/* place to check for proxy_arp for routes */
d8d1f30b9   Changli Gao   net-next: remove ...
452
  	out_dev = __in_dev_get_rcu(rt->dst.dev);
faa9dcf79   Eric Dumazet   arp: RCU changes
453
  	if (out_dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
454
  		omi = IN_DEV_MEDIUM_ID(out_dev);
faa9dcf79   Eric Dumazet   arp: RCU changes
455

a02cec215   Eric Dumazet   net: return opera...
456
  	return omi != imi && omi != -1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
457
458
459
  }
  
  /*
65324144b   Jesper Dangaard Brouer   net: RFC3069, pri...
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
   * 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 ...
483
  	if (rt->dst.dev != dev)
65324144b   Jesper Dangaard Brouer   net: RFC3069, pri...
484
485
486
487
488
489
490
491
492
493
494
495
496
  		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
497
498
499
500
   *	Interface to link layer: send routine and receive handler.
   */
  
  /*
51456b291   Ian Morris   ipv4: coding styl...
501
   *	Create an arp packet. If dest_hw is not set, we create a broadcast
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
502
503
   *	message.
   */
ed9bad06e   Al Viro   [IPV4] net/ipv4/a...
504
505
  struct sk_buff *arp_create(int type, int ptype, __be32 dest_ip,
  			   struct net_device *dev, __be32 src_ip,
abfdf1c48   Jan Engelhardt   [NETFILTER]: ebta...
506
507
508
  			   const unsigned char *dest_hw,
  			   const unsigned char *src_hw,
  			   const unsigned char *target_hw)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
509
510
511
512
  {
  	struct sk_buff *skb;
  	struct arphdr *arp;
  	unsigned char *arp_ptr;
660882432   Herbert Xu   ipv4: Remove all ...
513
514
  	int hlen = LL_RESERVED_SPACE(dev);
  	int tlen = dev->needed_tailroom;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
515
516
517
518
  
  	/*
  	 *	Allocate a buffer
  	 */
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
519

660882432   Herbert Xu   ipv4: Remove all ...
520
  	skb = alloc_skb(arp_hdr_len(dev) + hlen + tlen, GFP_ATOMIC);
51456b291   Ian Morris   ipv4: coding styl...
521
  	if (!skb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
522
  		return NULL;
660882432   Herbert Xu   ipv4: Remove all ...
523
  	skb_reserve(skb, hlen);
c1d2bbe1c   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
524
  	skb_reset_network_header(skb);
4df864c1d   Johannes Berg   networking: make ...
525
  	arp = skb_put(skb, arp_hdr_len(dev));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
526
527
  	skb->dev = dev;
  	skb->protocol = htons(ETH_P_ARP);
51456b291   Ian Morris   ipv4: coding styl...
528
  	if (!src_hw)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
529
  		src_hw = dev->dev_addr;
51456b291   Ian Morris   ipv4: coding styl...
530
  	if (!dest_hw)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
531
532
533
534
535
  		dest_hw = dev->broadcast;
  
  	/*
  	 *	Fill the device header for the ARP frame
  	 */
0c4e85813   Stephen Hemminger   [NET]: Wrap netde...
536
  	if (dev_hard_header(skb, dev, ptype, dest_hw, src_hw, skb->len) < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
  		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...
554
  #if IS_ENABLED(CONFIG_AX25)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
555
556
557
558
  	case ARPHRD_AX25:
  		arp->ar_hrd = htons(ARPHRD_AX25);
  		arp->ar_pro = htons(AX25_P_IP);
  		break;
40e4783ee   Igor Maravic   ipv4: arp: Cleanu...
559
  #if IS_ENABLED(CONFIG_NETROM)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
560
561
562
563
564
565
  	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...
566
  #if IS_ENABLED(CONFIG_FDDI)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
567
568
569
570
571
  	case ARPHRD_FDDI:
  		arp->ar_hrd = htons(ARPHRD_ETHER);
  		arp->ar_pro = htons(ETH_P_IP);
  		break;
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
572
573
574
575
576
  	}
  
  	arp->ar_hln = dev->addr_len;
  	arp->ar_pln = 4;
  	arp->ar_op = htons(type);
deffd7775   Changli Gao   net: arp: code cl...
577
  	arp_ptr = (unsigned char *)(arp + 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
578
579
  
  	memcpy(arp_ptr, src_hw, dev->addr_len);
f4cca7ffb   Jianjun Kong   net: clean up net...
580
581
582
  	arp_ptr += dev->addr_len;
  	memcpy(arp_ptr, &src_ip, 4);
  	arp_ptr += 4;
6752c8db8   YOSHIFUJI Hideaki / 吉藤英明   firewire net, ipv...
583
584
585
586
587
588
589
  
  	switch (dev->type) {
  #if IS_ENABLED(CONFIG_FIREWIRE_NET)
  	case ARPHRD_IEEE1394:
  		break;
  #endif
  	default:
00db41243   Ian Morris   ipv4: coding styl...
590
  		if (target_hw)
6752c8db8   YOSHIFUJI Hideaki / 吉藤英明   firewire net, ipv...
591
592
593
594
595
  			memcpy(arp_ptr, target_hw, dev->addr_len);
  		else
  			memset(arp_ptr, 0, dev->addr_len);
  		arp_ptr += dev->addr_len;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
596
597
598
599
600
601
602
603
  	memcpy(arp_ptr, &dest_ip, 4);
  
  	return skb;
  
  out:
  	kfree_skb(skb);
  	return NULL;
  }
4bc2f18ba   Eric Dumazet   net/ipv4: EXPORT_...
604
  EXPORT_SYMBOL(arp_create);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
605

0c4b51f00   Eric W. Biederman   netfilter: Pass n...
606
  static int arp_xmit_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
f9e4306fd   Eric W. Biederman   arp: Introduce ar...
607
608
609
  {
  	return dev_queue_xmit(skb);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
610
611
612
613
614
615
  /*
   *	Send an arp packet.
   */
  void arp_xmit(struct sk_buff *skb)
  {
  	/* Send it off, maybe filter it using firewalling first.  */
29a26a568   Eric W. Biederman   netfilter: Pass s...
616
617
618
  	NF_HOOK(NFPROTO_ARP, NF_ARP_OUT,
  		dev_net(skb->dev), NULL, skb, NULL, skb->dev,
  		arp_xmit_finish);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
619
  }
4bc2f18ba   Eric Dumazet   net/ipv4: EXPORT_...
620
  EXPORT_SYMBOL(arp_xmit);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
621

d9ef2e7bf   Ihar Hrachyshka   arp: postpone add...
622
623
  static bool arp_is_garp(struct net *net, struct net_device *dev,
  			int *addr_type, __be16 ar_op,
6fd05633b   Ihar Hrachyshka   arp: decompose is...
624
625
626
  			__be32 sip, __be32 tip,
  			unsigned char *sha, unsigned char *tha)
  {
d9ef2e7bf   Ihar Hrachyshka   arp: postpone add...
627
  	bool is_garp = tip == sip;
6fd05633b   Ihar Hrachyshka   arp: decompose is...
628
629
630
631
632
633
634
635
636
637
638
  
  	/* Gratuitous ARP _replies_ also require target hwaddr to be
  	 * the same as source.
  	 */
  	if (is_garp && ar_op == htons(ARPOP_REPLY))
  		is_garp =
  			/* IPv4 over IEEE 1394 doesn't provide target
  			 * hardware address field in its ARP payload.
  			 */
  			tha &&
  			!memcmp(tha, sha, dev->addr_len);
d9ef2e7bf   Ihar Hrachyshka   arp: postpone add...
639
640
641
642
643
  	if (is_garp) {
  		*addr_type = inet_addr_type_dev_table(net, dev, sip);
  		if (*addr_type != RTN_UNICAST)
  			is_garp = false;
  	}
6fd05633b   Ihar Hrachyshka   arp: decompose is...
644
645
  	return is_garp;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
646
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
647
648
   *	Process an arp request.
   */
0c4b51f00   Eric W. Biederman   netfilter: Pass n...
649
  static int arp_process(struct net *net, struct sock *sk, struct sk_buff *skb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
650
651
  {
  	struct net_device *dev = skb->dev;
faa9dcf79   Eric Dumazet   arp: RCU changes
652
  	struct in_device *in_dev = __in_dev_get_rcu(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
653
654
655
  	struct arphdr *arp;
  	unsigned char *arp_ptr;
  	struct rtable *rt;
e0260fedd   Mark Ryden   [IPV4] ARP: Remov...
656
  	unsigned char *sha;
23d268eb2   Ihar Hrachyshka   arp: honour gratu...
657
  	unsigned char *tha = NULL;
9e12bb22e   Al Viro   [IPV4]: ip_route_...
658
  	__be32 sip, tip;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
659
660
661
  	u16 dev_type = dev->type;
  	int addr_type;
  	struct neighbour *n;
63d008a4e   Jiri Benc   ipv4: send arp re...
662
  	struct dst_entry *reply_dst = NULL;
56022a8fd   Salam Noureddine   ipv4: arp: update...
663
  	bool is_garp = false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
664
665
666
667
  
  	/* arp_rcv below verifies the ARP header and verifies the device
  	 * is ARP'able.
  	 */
51456b291   Ian Morris   ipv4: coding styl...
668
  	if (!in_dev)
8dfd329fb   Zhang Shengju   arp: correct retu...
669
  		goto out_free_skb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
670

d0a92be05   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
671
  	arp = arp_hdr(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
672
673
  
  	switch (dev_type) {
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
674
  	default:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
675
676
  		if (arp->ar_pro != htons(ETH_P_IP) ||
  		    htons(dev_type) != arp->ar_hrd)
8dfd329fb   Zhang Shengju   arp: correct retu...
677
  			goto out_free_skb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
678
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
679
  	case ARPHRD_ETHER:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
680
  	case ARPHRD_FDDI:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
681
  	case ARPHRD_IEEE802:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
682
  		/*
211ed8651   Paul Gortmaker   net: delete all i...
683
  		 * ETHERNET, and Fibre Channel (which are IEEE 802
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
684
685
686
687
688
689
690
691
692
693
  		 * 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))
8dfd329fb   Zhang Shengju   arp: correct retu...
694
  			goto out_free_skb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
695
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
696
697
698
  	case ARPHRD_AX25:
  		if (arp->ar_pro != htons(AX25_P_IP) ||
  		    arp->ar_hrd != htons(ARPHRD_AX25))
8dfd329fb   Zhang Shengju   arp: correct retu...
699
  			goto out_free_skb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
700
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
701
702
703
  	case ARPHRD_NETROM:
  		if (arp->ar_pro != htons(AX25_P_IP) ||
  		    arp->ar_hrd != htons(ARPHRD_NETROM))
8dfd329fb   Zhang Shengju   arp: correct retu...
704
  			goto out_free_skb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
705
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
706
707
708
709
710
711
  	}
  
  	/* Understand only these message types */
  
  	if (arp->ar_op != htons(ARPOP_REPLY) &&
  	    arp->ar_op != htons(ARPOP_REQUEST))
8dfd329fb   Zhang Shengju   arp: correct retu...
712
  		goto out_free_skb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
713
714
715
716
  
  /*
   *	Extract fields
   */
deffd7775   Changli Gao   net: arp: code cl...
717
  	arp_ptr = (unsigned char *)(arp + 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
718
719
720
721
  	sha	= arp_ptr;
  	arp_ptr += dev->addr_len;
  	memcpy(&sip, arp_ptr, 4);
  	arp_ptr += 4;
6752c8db8   YOSHIFUJI Hideaki / 吉藤英明   firewire net, ipv...
722
723
724
725
726
727
  	switch (dev_type) {
  #if IS_ENABLED(CONFIG_FIREWIRE_NET)
  	case ARPHRD_IEEE1394:
  		break;
  #endif
  	default:
23d268eb2   Ihar Hrachyshka   arp: honour gratu...
728
  		tha = arp_ptr;
6752c8db8   YOSHIFUJI Hideaki / 吉藤英明   firewire net, ipv...
729
730
  		arp_ptr += dev->addr_len;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
731
  	memcpy(&tip, arp_ptr, 4);
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
732
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
733
734
735
   *	Check for bad requests for 127.x.x.x and requests for multicast
   *	addresses.  If this is one such, delete it.
   */
d0daebc3d   Thomas Graf   ipv4: Add interfa...
736
737
  	if (ipv4_is_multicast(tip) ||
  	    (!IN_DEV_ROUTE_LOCALNET(in_dev) && ipv4_is_loopback(tip)))
8dfd329fb   Zhang Shengju   arp: correct retu...
738
  		goto out_free_skb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
739

97daf3314   Johannes Berg   ipv4: add option ...
740
741
742
743
744
745
   /*
    *	For some 802.11 wireless deployments (and possibly other networks),
    *	there will be an ARP proxy and gratuitous ARP frames are attacks
    *	and thus should not be accepted.
    */
  	if (sip == tip && IN_DEV_ORCONF(in_dev, DROP_GRATUITOUS_ARP))
8dfd329fb   Zhang Shengju   arp: correct retu...
746
  		goto out_free_skb;
97daf3314   Johannes Berg   ipv4: add option ...
747

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
748
749
750
751
752
753
754
755
756
757
  /*
   *     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...
758
759
760
761
   *  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
762
   *  our cache, since ours is not in their cache.)
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
763
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
764
765
766
   *  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...
767
   *  and in the case of requests for us we add the requester to the arp
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
768
769
   *  cache.
   */
63d008a4e   Jiri Benc   ipv4: send arp re...
770
771
772
773
  	if (arp->ar_op == htons(ARPOP_REQUEST) && skb_metadata_dst(skb))
  		reply_dst = (struct dst_entry *)
  			    iptunnel_metadata_reply(skb_metadata_dst(skb),
  						    GFP_ATOMIC);
f8a68e752   Eric W. Biederman   Revert "ipv4: arp...
774
775
  	/* Special case: IPv4 duplicate address detection packet (RFC2131) */
  	if (sip == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
776
  		if (arp->ar_op == htons(ARPOP_REQUEST) &&
30bbaa195   David Ahern   net: Fix up inet_...
777
  		    inet_addr_type_dev_table(net, dev, tip) == RTN_LOCAL &&
9bd85e326   Denis V. Lunev   [IPV4]: Remove ex...
778
  		    !arp_ignore(in_dev, sip, tip))
63d008a4e   Jiri Benc   ipv4: send arp re...
779
780
  			arp_send_dst(ARPOP_REPLY, ETH_P_ARP, sip, dev, tip,
  				     sha, dev->dev_addr, sha, reply_dst);
8dfd329fb   Zhang Shengju   arp: correct retu...
781
  		goto out_consume_skb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
782
783
784
  	}
  
  	if (arp->ar_op == htons(ARPOP_REQUEST) &&
c6cffba4f   David S. Miller   ipv4: Fix input r...
785
  	    ip_route_input_noref(skb, tip, sip, 0, dev) == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
786

511c3f92a   Eric Dumazet   net: skb->rtable ...
787
  		rt = skb_rtable(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
788
789
790
  		addr_type = rt->rt_type;
  
  		if (addr_type == RTN_LOCAL) {
deffd7775   Changli Gao   net: arp: code cl...
791
  			int dont_send;
8164f1b79   Ben Greear   ipv4: Fix ARP beh...
792

deffd7775   Changli Gao   net: arp: code cl...
793
  			dont_send = arp_ignore(in_dev, sip, tip);
8164f1b79   Ben Greear   ipv4: Fix ARP beh...
794
  			if (!dont_send && IN_DEV_ARPFILTER(in_dev))
ae9c416d6   Changli Gao   net: arp: use ass...
795
  				dont_send = arp_filter(sip, tip, dev);
8164f1b79   Ben Greear   ipv4: Fix ARP beh...
796
797
798
  			if (!dont_send) {
  				n = neigh_event_ns(&arp_tbl, sha, &sip, dev);
  				if (n) {
63d008a4e   Jiri Benc   ipv4: send arp re...
799
800
801
802
  					arp_send_dst(ARPOP_REPLY, ETH_P_ARP,
  						     sip, dev, tip, sha,
  						     dev->dev_addr, sha,
  						     reply_dst);
8164f1b79   Ben Greear   ipv4: Fix ARP beh...
803
804
  					neigh_release(n);
  				}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
805
  			}
8dfd329fb   Zhang Shengju   arp: correct retu...
806
  			goto out_consume_skb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
807
  		} else if (IN_DEV_FORWARD(in_dev)) {
65324144b   Jesper Dangaard Brouer   net: RFC3069, pri...
808
809
810
  			if (addr_type == RTN_UNICAST  &&
  			    (arp_fwd_proxy(in_dev, dev, rt) ||
  			     arp_fwd_pvlan(in_dev, dev, rt, sip, tip) ||
70620c46a   Thomas Graf   net: Don't proxy ...
811
812
  			     (rt->dst.dev != dev &&
  			      pneigh_lookup(&arp_tbl, net, &tip, dev, 0)))) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
813
814
815
  				n = neigh_event_ns(&arp_tbl, sha, &sip, dev);
  				if (n)
  					neigh_release(n);
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
816
  				if (NEIGH_CB(skb)->flags & LOCALLY_ENQUEUED ||
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
817
  				    skb->pkt_type == PACKET_HOST ||
1f9248e56   Jiri Pirko   neigh: convert pa...
818
  				    NEIGH_VAR(in_dev->arp_parms, PROXY_DELAY) == 0) {
63d008a4e   Jiri Benc   ipv4: send arp re...
819
820
821
822
  					arp_send_dst(ARPOP_REPLY, ETH_P_ARP,
  						     sip, dev, tip, sha,
  						     dev->dev_addr, sha,
  						     reply_dst);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
823
  				} else {
deffd7775   Changli Gao   net: arp: code cl...
824
825
  					pneigh_enqueue(&arp_tbl,
  						       in_dev->arp_parms, skb);
181a4224a   Jiri Benc   ipv4: fix reply_d...
826
  					goto out_free_dst;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
827
  				}
8dfd329fb   Zhang Shengju   arp: correct retu...
828
  				goto out_consume_skb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
829
830
831
832
833
834
835
  			}
  		}
  	}
  
  	/* Update our ARP tables */
  
  	n = __neigh_lookup(&arp_tbl, &sip, dev, 0);
5990baaa6   Ihar Hrachyshka   arp: fixed -Wunin...
836
  	addr_type = -1;
7d472a59c   Ihar Hrachyshka   arp: always overr...
837
  	if (n || IN_DEV_ARP_ACCEPT(in_dev)) {
7d472a59c   Ihar Hrachyshka   arp: always overr...
838
839
840
  		is_garp = arp_is_garp(net, dev, &addr_type, arp->ar_op,
  				      sip, tip, sha, tha);
  	}
30bbaa195   David Ahern   net: Fix up inet_...
841

7d472a59c   Ihar Hrachyshka   arp: always overr...
842
  	if (IN_DEV_ARP_ACCEPT(in_dev)) {
abd596a4b   Neil Horman   [IPV4] ARP: Alloc...
843
844
845
846
  		/* Unsolicited ARP is not accepted by default.
  		   It is possible, that this option should be enabled for some
  		   devices (strip is candidate)
  		 */
51456b291   Ian Morris   ipv4: coding styl...
847
  		if (!n &&
d9ef2e7bf   Ihar Hrachyshka   arp: postpone add...
848
849
850
851
852
853
854
  		    (is_garp ||
  		     (arp->ar_op == htons(ARPOP_REPLY) &&
  		      (addr_type == RTN_UNICAST ||
  		       (addr_type < 0 &&
  			/* postpone calculation to as late as possible */
  			inet_addr_type_dev_table(net, dev, sip) ==
  				RTN_UNICAST)))))
1b1ac759d   Jean Delvare   [IPV4]: Cleanup c...
855
  			n = __neigh_lookup(&arp_tbl, &sip, dev, 1);
abd596a4b   Neil Horman   [IPV4] ARP: Alloc...
856
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
857
858
859
860
861
862
863
864
865
866
  
  	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.
  		 */
56022a8fd   Salam Noureddine   ipv4: arp: update...
867
868
869
870
  		override = time_after(jiffies,
  				      n->updated +
  				      NEIGH_VAR(n->parms, LOCKTIME)) ||
  			   is_garp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
871
872
873
874
875
876
877
  
  		/* 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...
878
  		neigh_update(n, sha, state,
7b8f7a402   Roopa Prabhu   neighbour: fix nl...
879
  			     override ? NEIGH_UPDATE_F_OVERRIDE : 0, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
880
881
  		neigh_release(n);
  	}
8dfd329fb   Zhang Shengju   arp: correct retu...
882
  out_consume_skb:
ead2ceb0e   Neil Horman   Network Drop Moni...
883
  	consume_skb(skb);
8dfd329fb   Zhang Shengju   arp: correct retu...
884

181a4224a   Jiri Benc   ipv4: fix reply_d...
885
886
  out_free_dst:
  	dst_release(reply_dst);
8dfd329fb   Zhang Shengju   arp: correct retu...
887
888
889
890
891
  	return NET_RX_SUCCESS;
  
  out_free_skb:
  	kfree_skb(skb);
  	return NET_RX_DROP;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
892
  }
444fc8fc3   Herbert Xu   [IPV4]: Fix "Prox...
893
894
  static void parp_redo(struct sk_buff *skb)
  {
0c4b51f00   Eric W. Biederman   netfilter: Pass n...
895
  	arp_process(dev_net(skb->dev), NULL, skb);
444fc8fc3   Herbert Xu   [IPV4]: Fix "Prox...
896
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
897
898
899
900
  
  /*
   *	Receive an arp request from the device layer.
   */
6c97e72a1   Adrian Bunk   [IPV4]: Possible ...
901
902
  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
903
  {
044453b3e   Eric Dumazet   arp: fix possible...
904
  	const struct arphdr *arp;
825bae5d9   Rick Jones   arp: Do not pertu...
905
  	/* do not tweak dropwatch on an ARP we will ignore */
044453b3e   Eric Dumazet   arp: fix possible...
906
907
908
  	if (dev->flags & IFF_NOARP ||
  	    skb->pkt_type == PACKET_OTHERHOST ||
  	    skb->pkt_type == PACKET_LOOPBACK)
825bae5d9   Rick Jones   arp: Do not pertu...
909
  		goto consumeskb;
044453b3e   Eric Dumazet   arp: fix possible...
910
911
912
913
  
  	skb = skb_share_check(skb, GFP_ATOMIC);
  	if (!skb)
  		goto out_of_mem;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
914
915
  
  	/* ARP header, plus 2 device addresses, plus 2 IP addresses.  */
988b70507   Pavel Emelyanov   [ARP]: Introduce ...
916
  	if (!pskb_may_pull(skb, arp_hdr_len(dev)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
917
  		goto freeskb;
d0a92be05   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
918
  	arp = arp_hdr(skb);
044453b3e   Eric Dumazet   arp: fix possible...
919
  	if (arp->ar_hln != dev->addr_len || arp->ar_pln != 4)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
920
  		goto freeskb;
a61bbcf28   Patrick McHardy   [NET]: Store skb-...
921
  	memset(NEIGH_CB(skb), 0, sizeof(struct neighbour_cb));
29a26a568   Eric W. Biederman   netfilter: Pass s...
922
923
924
  	return NF_HOOK(NFPROTO_ARP, NF_ARP_IN,
  		       dev_net(dev), NULL, skb, dev, NULL,
  		       arp_process);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
925

825bae5d9   Rick Jones   arp: Do not pertu...
926
927
  consumeskb:
  	consume_skb(skb);
8dfd329fb   Zhang Shengju   arp: correct retu...
928
  	return NET_RX_SUCCESS;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
929
930
931
  freeskb:
  	kfree_skb(skb);
  out_of_mem:
8dfd329fb   Zhang Shengju   arp: correct retu...
932
  	return NET_RX_DROP;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
933
934
935
936
937
938
939
940
941
  }
  
  /*
   *	User level interface (ioctl)
   */
  
  /*
   *	Set (create) an ARP cache entry.
   */
32e569b72   Pavel Emelyanov   [IPV4]: Pass the ...
942
  static int arp_req_set_proxy(struct net *net, struct net_device *dev, int on)
f8b33fdfa   Pavel Emelyanov   [ARP]: Consolidat...
943
  {
51456b291   Ian Morris   ipv4: coding styl...
944
  	if (!dev) {
586f12115   Pavel Emelyanov   [IPV4]: Switch us...
945
  		IPV4_DEVCONF_ALL(net, PROXY_ARP) = on;
f8b33fdfa   Pavel Emelyanov   [ARP]: Consolidat...
946
947
  		return 0;
  	}
c506653d3   Eric Dumazet   net: arp_ioctl() ...
948
949
  	if (__in_dev_get_rtnl(dev)) {
  		IN_DEV_CONF_SET(__in_dev_get_rtnl(dev), PROXY_ARP, on);
f8b33fdfa   Pavel Emelyanov   [ARP]: Consolidat...
950
951
952
953
  		return 0;
  	}
  	return -ENXIO;
  }
32e569b72   Pavel Emelyanov   [IPV4]: Pass the ...
954
955
  static int arp_req_set_public(struct net *net, struct arpreq *r,
  		struct net_device *dev)
43dc17011   Pavel Emelyanov   [ARP]: Minus one ...
956
957
958
959
960
961
962
  {
  	__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...
963
  		dev = dev_getbyhwaddr_rcu(net, r->arp_ha.sa_family,
deffd7775   Changli Gao   net: arp: code cl...
964
  				      r->arp_ha.sa_data);
43dc17011   Pavel Emelyanov   [ARP]: Minus one ...
965
966
967
968
  		if (!dev)
  			return -ENODEV;
  	}
  	if (mask) {
51456b291   Ian Morris   ipv4: coding styl...
969
  		if (!pneigh_lookup(&arp_tbl, net, &ip, dev, 1))
43dc17011   Pavel Emelyanov   [ARP]: Minus one ...
970
971
972
  			return -ENOBUFS;
  		return 0;
  	}
f8b33fdfa   Pavel Emelyanov   [ARP]: Consolidat...
973

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

43dc17011   Pavel Emelyanov   [ARP]: Minus one ...
985
  	ip = ((struct sockaddr_in *)&r->arp_pa)->sin_addr.s_addr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
986
987
  	if (r->arp_flags & ATF_PERM)
  		r->arp_flags |= ATF_COM;
51456b291   Ian Morris   ipv4: coding styl...
988
  	if (!dev) {
78fbfd8a6   David S. Miller   ipv4: Create and ...
989
  		struct rtable *rt = ip_route_output(net, ip, 0, RTO_ONLINK, 0);
b23dd4fe4   David S. Miller   ipv4: Make output...
990
991
992
  
  		if (IS_ERR(rt))
  			return PTR_ERR(rt);
d8d1f30b9   Changli Gao   net-next: remove ...
993
  		dev = rt->dst.dev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
994
995
996
997
998
  		ip_rt_put(rt);
  		if (!dev)
  			return -EINVAL;
  	}
  	switch (dev->type) {
40e4783ee   Igor Maravic   ipv4: arp: Cleanu...
999
  #if IS_ENABLED(CONFIG_FDDI)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
  	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)) {
95c961747   Eric Dumazet   net: cleanup unsi...
1022
  		unsigned int state = NUD_STALE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1023
1024
  		if (r->arp_flags & ATF_PERM)
  			state = NUD_PERMANENT;
deffd7775   Changli Gao   net: arp: code cl...
1025
  		err = neigh_update(neigh, (r->arp_flags & ATF_COM) ?
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
1026
  				   r->arp_ha.sa_data : NULL, state,
deffd7775   Changli Gao   net: arp: code cl...
1027
  				   NEIGH_UPDATE_F_OVERRIDE |
7b8f7a402   Roopa Prabhu   neighbour: fix nl...
1028
  				   NEIGH_UPDATE_F_ADMIN, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1029
1030
1031
1032
  		neigh_release(neigh);
  	}
  	return err;
  }
95c961747   Eric Dumazet   net: cleanup unsi...
1033
  static unsigned int arp_state_to_flags(struct neighbour *neigh)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1034
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1035
  	if (neigh->nud_state&NUD_PERMANENT)
deffd7775   Changli Gao   net: arp: code cl...
1036
  		return ATF_PERM | ATF_COM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1037
  	else if (neigh->nud_state&NUD_VALID)
deffd7775   Changli Gao   net: arp: code cl...
1038
1039
1040
  		return ATF_COM;
  	else
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1041
1042
1043
1044
1045
1046
1047
1048
  }
  
  /*
   *	Get an ARP cache entry.
   */
  
  static int arp_req_get(struct arpreq *r, struct net_device *dev)
  {
ed9bad06e   Al Viro   [IPV4] net/ipv4/a...
1049
  	__be32 ip = ((struct sockaddr_in *) &r->arp_pa)->sin_addr.s_addr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1050
1051
1052
1053
1054
  	struct neighbour *neigh;
  	int err = -ENXIO;
  
  	neigh = neigh_lookup(&arp_tbl, &ip, dev);
  	if (neigh) {
11c91ef98   Eric Dumazet   arp: filter NOARP...
1055
1056
1057
1058
1059
1060
1061
1062
1063
  		if (!(neigh->nud_state & NUD_NOARP)) {
  			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));
  			err = 0;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1064
  		neigh_release(neigh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1065
1066
1067
  	}
  	return err;
  }
7195cf722   Stephen Hemminger   arp: make arp_inv...
1068
  static int arp_invalidate(struct net_device *dev, __be32 ip)
545ecdc3b   Maxim Levitsky   arp: allow to inv...
1069
1070
1071
  {
  	struct neighbour *neigh = neigh_lookup(&arp_tbl, &ip, dev);
  	int err = -ENXIO;
5071034e4   Sowmini Varadhan   neigh: Really del...
1072
  	struct neigh_table *tbl = &arp_tbl;
545ecdc3b   Maxim Levitsky   arp: allow to inv...
1073
1074
1075
1076
1077
  
  	if (neigh) {
  		if (neigh->nud_state & ~NUD_NOARP)
  			err = neigh_update(neigh, NULL, NUD_FAILED,
  					   NEIGH_UPDATE_F_OVERRIDE|
7b8f7a402   Roopa Prabhu   neighbour: fix nl...
1078
  					   NEIGH_UPDATE_F_ADMIN, 0);
5071034e4   Sowmini Varadhan   neigh: Really del...
1079
  		write_lock_bh(&tbl->lock);
545ecdc3b   Maxim Levitsky   arp: allow to inv...
1080
  		neigh_release(neigh);
5071034e4   Sowmini Varadhan   neigh: Really del...
1081
1082
  		neigh_remove_one(neigh, tbl);
  		write_unlock_bh(&tbl->lock);
545ecdc3b   Maxim Levitsky   arp: allow to inv...
1083
1084
1085
1086
  	}
  
  	return err;
  }
545ecdc3b   Maxim Levitsky   arp: allow to inv...
1087

32e569b72   Pavel Emelyanov   [IPV4]: Pass the ...
1088
1089
  static int arp_req_delete_public(struct net *net, struct arpreq *r,
  		struct net_device *dev)
46479b432   Pavel Emelyanov   [ARP]: Minus one ...
1090
1091
1092
1093
1094
  {
  	__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...
1095
  		return pneigh_delete(&arp_tbl, net, &ip, dev);
46479b432   Pavel Emelyanov   [ARP]: Minus one ...
1096

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

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

46479b432   Pavel Emelyanov   [ARP]: Minus one ...
1109
  	ip = ((struct sockaddr_in *)&r->arp_pa)->sin_addr.s_addr;
51456b291   Ian Morris   ipv4: coding styl...
1110
  	if (!dev) {
78fbfd8a6   David S. Miller   ipv4: Create and ...
1111
  		struct rtable *rt = ip_route_output(net, ip, 0, RTO_ONLINK, 0);
b23dd4fe4   David S. Miller   ipv4: Make output...
1112
1113
  		if (IS_ERR(rt))
  			return PTR_ERR(rt);
d8d1f30b9   Changli Gao   net-next: remove ...
1114
  		dev = rt->dst.dev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1115
1116
1117
1118
  		ip_rt_put(rt);
  		if (!dev)
  			return -EINVAL;
  	}
545ecdc3b   Maxim Levitsky   arp: allow to inv...
1119
  	return arp_invalidate(dev, ip);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1120
1121
1122
1123
1124
  }
  
  /*
   *	Handle an ARP layer I/O control request.
   */
32e569b72   Pavel Emelyanov   [IPV4]: Pass the ...
1125
  int arp_ioctl(struct net *net, unsigned int cmd, void __user *arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1126
1127
1128
1129
1130
1131
  {
  	int err;
  	struct arpreq r;
  	struct net_device *dev = NULL;
  
  	switch (cmd) {
deffd7775   Changli Gao   net: arp: code cl...
1132
1133
  	case SIOCDARP:
  	case SIOCSARP:
52e804c6d   Eric W. Biederman   net: Allow userns...
1134
  		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
deffd7775   Changli Gao   net: arp: code cl...
1135
1136
1137
1138
1139
1140
1141
1142
  			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
1143
1144
1145
1146
1147
1148
  	}
  
  	if (r.arp_pa.sa_family != AF_INET)
  		return -EPFNOSUPPORT;
  
  	if (!(r.arp_flags & ATF_PUBL) &&
deffd7775   Changli Gao   net: arp: code cl...
1149
  	    (r.arp_flags & (ATF_NETMASK | ATF_DONTPUB)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1150
1151
1152
1153
  		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() ...
1154
  	rtnl_lock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1155
1156
  	if (r.arp_dev[0]) {
  		err = -ENODEV;
c506653d3   Eric Dumazet   net: arp_ioctl() ...
1157
  		dev = __dev_get_by_name(net, r.arp_dev);
51456b291   Ian Morris   ipv4: coding styl...
1158
  		if (!dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
  			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
1171
  	switch (cmd) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1172
  	case SIOCDARP:
32e569b72   Pavel Emelyanov   [IPV4]: Pass the ...
1173
  		err = arp_req_delete(net, &r, dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1174
1175
  		break;
  	case SIOCSARP:
32e569b72   Pavel Emelyanov   [IPV4]: Pass the ...
1176
  		err = arp_req_set(net, &r, dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1177
1178
1179
  		break;
  	case SIOCGARP:
  		err = arp_req_get(&r, dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1180
1181
1182
  		break;
  	}
  out:
c506653d3   Eric Dumazet   net: arp_ioctl() ...
1183
  	rtnl_unlock();
941666c2e   Eric Dumazet   net: RCU conversi...
1184
1185
  	if (cmd == SIOCGARP && !err && copy_to_user(arg, &r, sizeof(r)))
  		err = -EFAULT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1186
1187
  	return err;
  }
deffd7775   Changli Gao   net: arp: code cl...
1188
1189
  static int arp_netdev_event(struct notifier_block *this, unsigned long event,
  			    void *ptr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1190
  {
351638e7d   Jiri Pirko   net: pass info st...
1191
  	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
6c8b4e3ff   Timo Teräs   arp: flush arp ca...
1192
  	struct netdev_notifier_change_info *change_info;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1193
1194
1195
1196
  
  	switch (event) {
  	case NETDEV_CHANGEADDR:
  		neigh_changeaddr(&arp_tbl, dev);
bafa6d9d8   Nicolas Dichtel   ipv4/route: arg d...
1197
  		rt_cache_flush(dev_net(dev));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1198
  		break;
6c8b4e3ff   Timo Teräs   arp: flush arp ca...
1199
1200
1201
1202
1203
  	case NETDEV_CHANGE:
  		change_info = ptr;
  		if (change_info->flags_changed & IFF_NOARP)
  			neigh_changeaddr(&arp_tbl, dev);
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
  	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...
1228
  static struct packet_type arp_packet_type __read_mostly = {
09640e636   Harvey Harrison   net: replace uses...
1229
  	.type =	cpu_to_be16(ETH_P_ARP),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1230
1231
1232
1233
1234
1235
1236
  	.func =	arp_rcv,
  };
  
  static int arp_proc_init(void);
  
  void __init arp_init(void)
  {
d7480fd3b   WANG Cong   neigh: remove dyn...
1237
  	neigh_table_init(NEIGH_ARP_TABLE, &arp_tbl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1238
1239
1240
1241
  
  	dev_add_pack(&arp_packet_type);
  	arp_proc_init();
  #ifdef CONFIG_SYSCTL
73af614ae   Jiri Pirko   neigh: use tbl->f...
1242
  	neigh_sysctl_register(NULL, &arp_tbl.parms, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1243
1244
1245
1246
1247
  #endif
  	register_netdevice_notifier(&arp_netdev_notifier);
  }
  
  #ifdef CONFIG_PROC_FS
40e4783ee   Igor Maravic   ipv4: arp: Cleanu...
1248
  #if IS_ENABLED(CONFIG_AX25)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1249
1250
1251
1252
1253
  
  /* ------------------------------------------------------------------------ */
  /*
   *	ax25 -> ASCII conversion
   */
4872e57c8   Ralf Baechle   NET: Fix /proc/ne...
1254
  static void ax2asc2(ax25_address *a, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1255
1256
1257
1258
1259
1260
  {
  	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...
1261
1262
  		if (c != ' ')
  			*s++ = c;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1263
  	}
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
1264

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1272
1273
  	*s++ = n + '0';
  	*s++ = '\0';
4872e57c8   Ralf Baechle   NET: Fix /proc/ne...
1274
1275
1276
1277
  	if (*buf == '\0' || *buf == '-') {
  		buf[0] = '*';
  		buf[1] = '\0';
  	}
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
  	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...
1294
  #if IS_ENABLED(CONFIG_AX25)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1295
1296
1297
1298
1299
  	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;
40e4783ee   Igor Maravic   ipv4: arp: Cleanu...
1307
  #if IS_ENABLED(CONFIG_AX25)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1308
1309
  	}
  #endif
673d57e72   Harvey Harrison   net: replace NIPQ...
1310
  	sprintf(tbuf, "%pI4", n->primary_key);
4872e57c8   Ralf Baechle   NET: Fix /proc/ne...
1311
1312
  	seq_printf(seq, "%-16s 0x%-10x0x%-10x%-17s     *        %s
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
  		   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
  {
d4beaa66a   Gao feng   net: proc: change...
1379
  	if (!proc_create("arp", S_IRUGO, net->proc_net, &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
  static void __net_exit arp_net_exit(struct net *net)
  {
ece31ffd5   Gao feng   net: proc: change...
1385
  	remove_proc_entry("arp", net->proc_net);
ffc31d3d7   Denis V. Lunev   [NETNS]: /proc/ne...
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
  }
  
  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 */