Commit 4a94445c9a5cf5461fb41d80040033b9a8e2a85a
Committed by
David S. Miller
1 parent
407eadd996
Exists in
master
and in
7 other branches
net: Use ip_route_input_noref() in input path
Use ip_route_input_noref() in ip fast path, to avoid two atomic ops per incoming packet. Note: loopback is excluded from this optimization in ip_rcv_finish() Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Showing 3 changed files with 5 additions and 5 deletions Inline Diff
net/ipv4/arp.c
1 | /* linux/net/ipv4/arp.c | 1 | /* linux/net/ipv4/arp.c |
2 | * | 2 | * |
3 | * Copyright (C) 1994 by Florian La Roche | 3 | * Copyright (C) 1994 by Florian La Roche |
4 | * | 4 | * |
5 | * This module implements the Address Resolution Protocol ARP (RFC 826), | 5 | * This module implements the Address Resolution Protocol ARP (RFC 826), |
6 | * which is used to convert IP addresses (or in the future maybe other | 6 | * which is used to convert IP addresses (or in the future maybe other |
7 | * high-level addresses) into a low-level hardware address (like an Ethernet | 7 | * high-level addresses) into a low-level hardware address (like an Ethernet |
8 | * address). | 8 | * address). |
9 | * | 9 | * |
10 | * This program is free software; you can redistribute it and/or | 10 | * This program is free software; you can redistribute it and/or |
11 | * modify it under the terms of the GNU General Public License | 11 | * modify it under the terms of the GNU General Public License |
12 | * as published by the Free Software Foundation; either version | 12 | * as published by the Free Software Foundation; either version |
13 | * 2 of the License, or (at your option) any later version. | 13 | * 2 of the License, or (at your option) any later version. |
14 | * | 14 | * |
15 | * Fixes: | 15 | * Fixes: |
16 | * Alan Cox : Removed the Ethernet assumptions in | 16 | * Alan Cox : Removed the Ethernet assumptions in |
17 | * Florian's code | 17 | * Florian's code |
18 | * Alan Cox : Fixed some small errors in the ARP | 18 | * Alan Cox : Fixed some small errors in the ARP |
19 | * logic | 19 | * logic |
20 | * Alan Cox : Allow >4K in /proc | 20 | * Alan Cox : Allow >4K in /proc |
21 | * Alan Cox : Make ARP add its own protocol entry | 21 | * Alan Cox : Make ARP add its own protocol entry |
22 | * Ross Martin : Rewrote arp_rcv() and arp_get_info() | 22 | * Ross Martin : Rewrote arp_rcv() and arp_get_info() |
23 | * Stephen Henson : Add AX25 support to arp_get_info() | 23 | * Stephen Henson : Add AX25 support to arp_get_info() |
24 | * Alan Cox : Drop data when a device is downed. | 24 | * Alan Cox : Drop data when a device is downed. |
25 | * Alan Cox : Use init_timer(). | 25 | * Alan Cox : Use init_timer(). |
26 | * Alan Cox : Double lock fixes. | 26 | * Alan Cox : Double lock fixes. |
27 | * Martin Seine : Move the arphdr structure | 27 | * Martin Seine : Move the arphdr structure |
28 | * to if_arp.h for compatibility. | 28 | * to if_arp.h for compatibility. |
29 | * with BSD based programs. | 29 | * with BSD based programs. |
30 | * Andrew Tridgell : Added ARP netmask code and | 30 | * Andrew Tridgell : Added ARP netmask code and |
31 | * re-arranged proxy handling. | 31 | * re-arranged proxy handling. |
32 | * Alan Cox : Changed to use notifiers. | 32 | * Alan Cox : Changed to use notifiers. |
33 | * Niibe Yutaka : Reply for this device or proxies only. | 33 | * Niibe Yutaka : Reply for this device or proxies only. |
34 | * Alan Cox : Don't proxy across hardware types! | 34 | * Alan Cox : Don't proxy across hardware types! |
35 | * Jonathan Naylor : Added support for NET/ROM. | 35 | * Jonathan Naylor : Added support for NET/ROM. |
36 | * Mike Shaver : RFC1122 checks. | 36 | * Mike Shaver : RFC1122 checks. |
37 | * Jonathan Naylor : Only lookup the hardware address for | 37 | * Jonathan Naylor : Only lookup the hardware address for |
38 | * the correct hardware type. | 38 | * the correct hardware type. |
39 | * Germano Caronni : Assorted subtle races. | 39 | * Germano Caronni : Assorted subtle races. |
40 | * Craig Schlenter : Don't modify permanent entry | 40 | * Craig Schlenter : Don't modify permanent entry |
41 | * during arp_rcv. | 41 | * during arp_rcv. |
42 | * Russ Nelson : Tidied up a few bits. | 42 | * Russ Nelson : Tidied up a few bits. |
43 | * Alexey Kuznetsov: Major changes to caching and behaviour, | 43 | * Alexey Kuznetsov: Major changes to caching and behaviour, |
44 | * eg intelligent arp probing and | 44 | * eg intelligent arp probing and |
45 | * generation | 45 | * generation |
46 | * of host down events. | 46 | * of host down events. |
47 | * Alan Cox : Missing unlock in device events. | 47 | * Alan Cox : Missing unlock in device events. |
48 | * Eckes : ARP ioctl control errors. | 48 | * Eckes : ARP ioctl control errors. |
49 | * Alexey Kuznetsov: Arp free fix. | 49 | * Alexey Kuznetsov: Arp free fix. |
50 | * Manuel Rodriguez: Gratuitous ARP. | 50 | * Manuel Rodriguez: Gratuitous ARP. |
51 | * Jonathan Layes : Added arpd support through kerneld | 51 | * Jonathan Layes : Added arpd support through kerneld |
52 | * message queue (960314) | 52 | * message queue (960314) |
53 | * Mike Shaver : /proc/sys/net/ipv4/arp_* support | 53 | * Mike Shaver : /proc/sys/net/ipv4/arp_* support |
54 | * Mike McLagan : Routing by source | 54 | * Mike McLagan : Routing by source |
55 | * Stuart Cheshire : Metricom and grat arp fixes | 55 | * Stuart Cheshire : Metricom and grat arp fixes |
56 | * *** FOR 2.1 clean this up *** | 56 | * *** FOR 2.1 clean this up *** |
57 | * Lawrence V. Stefani: (08/12/96) Added FDDI support. | 57 | * Lawrence V. Stefani: (08/12/96) Added FDDI support. |
58 | * Alan Cox : Took the AP1000 nasty FDDI hack and | 58 | * Alan Cox : Took the AP1000 nasty FDDI hack and |
59 | * folded into the mainstream FDDI code. | 59 | * folded into the mainstream FDDI code. |
60 | * Ack spit, Linus how did you allow that | 60 | * Ack spit, Linus how did you allow that |
61 | * one in... | 61 | * one in... |
62 | * Jes Sorensen : Make FDDI work again in 2.1.x and | 62 | * Jes Sorensen : Make FDDI work again in 2.1.x and |
63 | * clean up the APFDDI & gen. FDDI bits. | 63 | * clean up the APFDDI & gen. FDDI bits. |
64 | * Alexey Kuznetsov: new arp state machine; | 64 | * Alexey Kuznetsov: new arp state machine; |
65 | * now it is in net/core/neighbour.c. | 65 | * now it is in net/core/neighbour.c. |
66 | * Krzysztof Halasa: Added Frame Relay ARP support. | 66 | * Krzysztof Halasa: Added Frame Relay ARP support. |
67 | * Arnaldo C. Melo : convert /proc/net/arp to seq_file | 67 | * Arnaldo C. Melo : convert /proc/net/arp to seq_file |
68 | * Shmulik Hen: Split arp_send to arp_create and | 68 | * Shmulik Hen: Split arp_send to arp_create and |
69 | * arp_xmit so intermediate drivers like | 69 | * arp_xmit so intermediate drivers like |
70 | * bonding can change the skb before | 70 | * bonding can change the skb before |
71 | * sending (e.g. insert 8021q tag). | 71 | * sending (e.g. insert 8021q tag). |
72 | * Harald Welte : convert to make use of jenkins hash | 72 | * Harald Welte : convert to make use of jenkins hash |
73 | * Jesper D. Brouer: Proxy ARP PVLAN RFC 3069 support. | 73 | * Jesper D. Brouer: Proxy ARP PVLAN RFC 3069 support. |
74 | */ | 74 | */ |
75 | 75 | ||
76 | #include <linux/module.h> | 76 | #include <linux/module.h> |
77 | #include <linux/types.h> | 77 | #include <linux/types.h> |
78 | #include <linux/string.h> | 78 | #include <linux/string.h> |
79 | #include <linux/kernel.h> | 79 | #include <linux/kernel.h> |
80 | #include <linux/capability.h> | 80 | #include <linux/capability.h> |
81 | #include <linux/socket.h> | 81 | #include <linux/socket.h> |
82 | #include <linux/sockios.h> | 82 | #include <linux/sockios.h> |
83 | #include <linux/errno.h> | 83 | #include <linux/errno.h> |
84 | #include <linux/in.h> | 84 | #include <linux/in.h> |
85 | #include <linux/mm.h> | 85 | #include <linux/mm.h> |
86 | #include <linux/inet.h> | 86 | #include <linux/inet.h> |
87 | #include <linux/inetdevice.h> | 87 | #include <linux/inetdevice.h> |
88 | #include <linux/netdevice.h> | 88 | #include <linux/netdevice.h> |
89 | #include <linux/etherdevice.h> | 89 | #include <linux/etherdevice.h> |
90 | #include <linux/fddidevice.h> | 90 | #include <linux/fddidevice.h> |
91 | #include <linux/if_arp.h> | 91 | #include <linux/if_arp.h> |
92 | #include <linux/trdevice.h> | 92 | #include <linux/trdevice.h> |
93 | #include <linux/skbuff.h> | 93 | #include <linux/skbuff.h> |
94 | #include <linux/proc_fs.h> | 94 | #include <linux/proc_fs.h> |
95 | #include <linux/seq_file.h> | 95 | #include <linux/seq_file.h> |
96 | #include <linux/stat.h> | 96 | #include <linux/stat.h> |
97 | #include <linux/init.h> | 97 | #include <linux/init.h> |
98 | #include <linux/net.h> | 98 | #include <linux/net.h> |
99 | #include <linux/rcupdate.h> | 99 | #include <linux/rcupdate.h> |
100 | #include <linux/jhash.h> | 100 | #include <linux/jhash.h> |
101 | #include <linux/slab.h> | 101 | #include <linux/slab.h> |
102 | #ifdef CONFIG_SYSCTL | 102 | #ifdef CONFIG_SYSCTL |
103 | #include <linux/sysctl.h> | 103 | #include <linux/sysctl.h> |
104 | #endif | 104 | #endif |
105 | 105 | ||
106 | #include <net/net_namespace.h> | 106 | #include <net/net_namespace.h> |
107 | #include <net/ip.h> | 107 | #include <net/ip.h> |
108 | #include <net/icmp.h> | 108 | #include <net/icmp.h> |
109 | #include <net/route.h> | 109 | #include <net/route.h> |
110 | #include <net/protocol.h> | 110 | #include <net/protocol.h> |
111 | #include <net/tcp.h> | 111 | #include <net/tcp.h> |
112 | #include <net/sock.h> | 112 | #include <net/sock.h> |
113 | #include <net/arp.h> | 113 | #include <net/arp.h> |
114 | #include <net/ax25.h> | 114 | #include <net/ax25.h> |
115 | #include <net/netrom.h> | 115 | #include <net/netrom.h> |
116 | #if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE) | 116 | #if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE) |
117 | #include <net/atmclip.h> | 117 | #include <net/atmclip.h> |
118 | struct neigh_table *clip_tbl_hook; | 118 | struct neigh_table *clip_tbl_hook; |
119 | #endif | 119 | #endif |
120 | 120 | ||
121 | #include <asm/system.h> | 121 | #include <asm/system.h> |
122 | #include <asm/uaccess.h> | 122 | #include <asm/uaccess.h> |
123 | 123 | ||
124 | #include <linux/netfilter_arp.h> | 124 | #include <linux/netfilter_arp.h> |
125 | 125 | ||
126 | /* | 126 | /* |
127 | * Interface to generic neighbour cache. | 127 | * Interface to generic neighbour cache. |
128 | */ | 128 | */ |
129 | static u32 arp_hash(const void *pkey, const struct net_device *dev); | 129 | static u32 arp_hash(const void *pkey, const struct net_device *dev); |
130 | static int arp_constructor(struct neighbour *neigh); | 130 | static int arp_constructor(struct neighbour *neigh); |
131 | static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb); | 131 | static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb); |
132 | static void arp_error_report(struct neighbour *neigh, struct sk_buff *skb); | 132 | static void arp_error_report(struct neighbour *neigh, struct sk_buff *skb); |
133 | static void parp_redo(struct sk_buff *skb); | 133 | static void parp_redo(struct sk_buff *skb); |
134 | 134 | ||
135 | static const struct neigh_ops arp_generic_ops = { | 135 | static const struct neigh_ops arp_generic_ops = { |
136 | .family = AF_INET, | 136 | .family = AF_INET, |
137 | .solicit = arp_solicit, | 137 | .solicit = arp_solicit, |
138 | .error_report = arp_error_report, | 138 | .error_report = arp_error_report, |
139 | .output = neigh_resolve_output, | 139 | .output = neigh_resolve_output, |
140 | .connected_output = neigh_connected_output, | 140 | .connected_output = neigh_connected_output, |
141 | .hh_output = dev_queue_xmit, | 141 | .hh_output = dev_queue_xmit, |
142 | .queue_xmit = dev_queue_xmit, | 142 | .queue_xmit = dev_queue_xmit, |
143 | }; | 143 | }; |
144 | 144 | ||
145 | static const struct neigh_ops arp_hh_ops = { | 145 | static const struct neigh_ops arp_hh_ops = { |
146 | .family = AF_INET, | 146 | .family = AF_INET, |
147 | .solicit = arp_solicit, | 147 | .solicit = arp_solicit, |
148 | .error_report = arp_error_report, | 148 | .error_report = arp_error_report, |
149 | .output = neigh_resolve_output, | 149 | .output = neigh_resolve_output, |
150 | .connected_output = neigh_resolve_output, | 150 | .connected_output = neigh_resolve_output, |
151 | .hh_output = dev_queue_xmit, | 151 | .hh_output = dev_queue_xmit, |
152 | .queue_xmit = dev_queue_xmit, | 152 | .queue_xmit = dev_queue_xmit, |
153 | }; | 153 | }; |
154 | 154 | ||
155 | static const struct neigh_ops arp_direct_ops = { | 155 | static const struct neigh_ops arp_direct_ops = { |
156 | .family = AF_INET, | 156 | .family = AF_INET, |
157 | .output = dev_queue_xmit, | 157 | .output = dev_queue_xmit, |
158 | .connected_output = dev_queue_xmit, | 158 | .connected_output = dev_queue_xmit, |
159 | .hh_output = dev_queue_xmit, | 159 | .hh_output = dev_queue_xmit, |
160 | .queue_xmit = dev_queue_xmit, | 160 | .queue_xmit = dev_queue_xmit, |
161 | }; | 161 | }; |
162 | 162 | ||
163 | const struct neigh_ops arp_broken_ops = { | 163 | const struct neigh_ops arp_broken_ops = { |
164 | .family = AF_INET, | 164 | .family = AF_INET, |
165 | .solicit = arp_solicit, | 165 | .solicit = arp_solicit, |
166 | .error_report = arp_error_report, | 166 | .error_report = arp_error_report, |
167 | .output = neigh_compat_output, | 167 | .output = neigh_compat_output, |
168 | .connected_output = neigh_compat_output, | 168 | .connected_output = neigh_compat_output, |
169 | .hh_output = dev_queue_xmit, | 169 | .hh_output = dev_queue_xmit, |
170 | .queue_xmit = dev_queue_xmit, | 170 | .queue_xmit = dev_queue_xmit, |
171 | }; | 171 | }; |
172 | 172 | ||
173 | struct neigh_table arp_tbl = { | 173 | struct neigh_table arp_tbl = { |
174 | .family = AF_INET, | 174 | .family = AF_INET, |
175 | .entry_size = sizeof(struct neighbour) + 4, | 175 | .entry_size = sizeof(struct neighbour) + 4, |
176 | .key_len = 4, | 176 | .key_len = 4, |
177 | .hash = arp_hash, | 177 | .hash = arp_hash, |
178 | .constructor = arp_constructor, | 178 | .constructor = arp_constructor, |
179 | .proxy_redo = parp_redo, | 179 | .proxy_redo = parp_redo, |
180 | .id = "arp_cache", | 180 | .id = "arp_cache", |
181 | .parms = { | 181 | .parms = { |
182 | .tbl = &arp_tbl, | 182 | .tbl = &arp_tbl, |
183 | .base_reachable_time = 30 * HZ, | 183 | .base_reachable_time = 30 * HZ, |
184 | .retrans_time = 1 * HZ, | 184 | .retrans_time = 1 * HZ, |
185 | .gc_staletime = 60 * HZ, | 185 | .gc_staletime = 60 * HZ, |
186 | .reachable_time = 30 * HZ, | 186 | .reachable_time = 30 * HZ, |
187 | .delay_probe_time = 5 * HZ, | 187 | .delay_probe_time = 5 * HZ, |
188 | .queue_len = 3, | 188 | .queue_len = 3, |
189 | .ucast_probes = 3, | 189 | .ucast_probes = 3, |
190 | .mcast_probes = 3, | 190 | .mcast_probes = 3, |
191 | .anycast_delay = 1 * HZ, | 191 | .anycast_delay = 1 * HZ, |
192 | .proxy_delay = (8 * HZ) / 10, | 192 | .proxy_delay = (8 * HZ) / 10, |
193 | .proxy_qlen = 64, | 193 | .proxy_qlen = 64, |
194 | .locktime = 1 * HZ, | 194 | .locktime = 1 * HZ, |
195 | }, | 195 | }, |
196 | .gc_interval = 30 * HZ, | 196 | .gc_interval = 30 * HZ, |
197 | .gc_thresh1 = 128, | 197 | .gc_thresh1 = 128, |
198 | .gc_thresh2 = 512, | 198 | .gc_thresh2 = 512, |
199 | .gc_thresh3 = 1024, | 199 | .gc_thresh3 = 1024, |
200 | }; | 200 | }; |
201 | 201 | ||
202 | int arp_mc_map(__be32 addr, u8 *haddr, struct net_device *dev, int dir) | 202 | int arp_mc_map(__be32 addr, u8 *haddr, struct net_device *dev, int dir) |
203 | { | 203 | { |
204 | switch (dev->type) { | 204 | switch (dev->type) { |
205 | case ARPHRD_ETHER: | 205 | case ARPHRD_ETHER: |
206 | case ARPHRD_FDDI: | 206 | case ARPHRD_FDDI: |
207 | case ARPHRD_IEEE802: | 207 | case ARPHRD_IEEE802: |
208 | ip_eth_mc_map(addr, haddr); | 208 | ip_eth_mc_map(addr, haddr); |
209 | return 0; | 209 | return 0; |
210 | case ARPHRD_IEEE802_TR: | 210 | case ARPHRD_IEEE802_TR: |
211 | ip_tr_mc_map(addr, haddr); | 211 | ip_tr_mc_map(addr, haddr); |
212 | return 0; | 212 | return 0; |
213 | case ARPHRD_INFINIBAND: | 213 | case ARPHRD_INFINIBAND: |
214 | ip_ib_mc_map(addr, dev->broadcast, haddr); | 214 | ip_ib_mc_map(addr, dev->broadcast, haddr); |
215 | return 0; | 215 | return 0; |
216 | default: | 216 | default: |
217 | if (dir) { | 217 | if (dir) { |
218 | memcpy(haddr, dev->broadcast, dev->addr_len); | 218 | memcpy(haddr, dev->broadcast, dev->addr_len); |
219 | return 0; | 219 | return 0; |
220 | } | 220 | } |
221 | } | 221 | } |
222 | return -EINVAL; | 222 | return -EINVAL; |
223 | } | 223 | } |
224 | 224 | ||
225 | 225 | ||
226 | static u32 arp_hash(const void *pkey, const struct net_device *dev) | 226 | static u32 arp_hash(const void *pkey, const struct net_device *dev) |
227 | { | 227 | { |
228 | return jhash_2words(*(u32 *)pkey, dev->ifindex, arp_tbl.hash_rnd); | 228 | return jhash_2words(*(u32 *)pkey, dev->ifindex, arp_tbl.hash_rnd); |
229 | } | 229 | } |
230 | 230 | ||
231 | static int arp_constructor(struct neighbour *neigh) | 231 | static int arp_constructor(struct neighbour *neigh) |
232 | { | 232 | { |
233 | __be32 addr = *(__be32*)neigh->primary_key; | 233 | __be32 addr = *(__be32*)neigh->primary_key; |
234 | struct net_device *dev = neigh->dev; | 234 | struct net_device *dev = neigh->dev; |
235 | struct in_device *in_dev; | 235 | struct in_device *in_dev; |
236 | struct neigh_parms *parms; | 236 | struct neigh_parms *parms; |
237 | 237 | ||
238 | rcu_read_lock(); | 238 | rcu_read_lock(); |
239 | in_dev = __in_dev_get_rcu(dev); | 239 | in_dev = __in_dev_get_rcu(dev); |
240 | if (in_dev == NULL) { | 240 | if (in_dev == NULL) { |
241 | rcu_read_unlock(); | 241 | rcu_read_unlock(); |
242 | return -EINVAL; | 242 | return -EINVAL; |
243 | } | 243 | } |
244 | 244 | ||
245 | neigh->type = inet_addr_type(dev_net(dev), addr); | 245 | neigh->type = inet_addr_type(dev_net(dev), addr); |
246 | 246 | ||
247 | parms = in_dev->arp_parms; | 247 | parms = in_dev->arp_parms; |
248 | __neigh_parms_put(neigh->parms); | 248 | __neigh_parms_put(neigh->parms); |
249 | neigh->parms = neigh_parms_clone(parms); | 249 | neigh->parms = neigh_parms_clone(parms); |
250 | rcu_read_unlock(); | 250 | rcu_read_unlock(); |
251 | 251 | ||
252 | if (!dev->header_ops) { | 252 | if (!dev->header_ops) { |
253 | neigh->nud_state = NUD_NOARP; | 253 | neigh->nud_state = NUD_NOARP; |
254 | neigh->ops = &arp_direct_ops; | 254 | neigh->ops = &arp_direct_ops; |
255 | neigh->output = neigh->ops->queue_xmit; | 255 | neigh->output = neigh->ops->queue_xmit; |
256 | } else { | 256 | } else { |
257 | /* Good devices (checked by reading texts, but only Ethernet is | 257 | /* Good devices (checked by reading texts, but only Ethernet is |
258 | tested) | 258 | tested) |
259 | 259 | ||
260 | ARPHRD_ETHER: (ethernet, apfddi) | 260 | ARPHRD_ETHER: (ethernet, apfddi) |
261 | ARPHRD_FDDI: (fddi) | 261 | ARPHRD_FDDI: (fddi) |
262 | ARPHRD_IEEE802: (tr) | 262 | ARPHRD_IEEE802: (tr) |
263 | ARPHRD_METRICOM: (strip) | 263 | ARPHRD_METRICOM: (strip) |
264 | ARPHRD_ARCNET: | 264 | ARPHRD_ARCNET: |
265 | etc. etc. etc. | 265 | etc. etc. etc. |
266 | 266 | ||
267 | ARPHRD_IPDDP will also work, if author repairs it. | 267 | ARPHRD_IPDDP will also work, if author repairs it. |
268 | I did not it, because this driver does not work even | 268 | I did not it, because this driver does not work even |
269 | in old paradigm. | 269 | in old paradigm. |
270 | */ | 270 | */ |
271 | 271 | ||
272 | #if 1 | 272 | #if 1 |
273 | /* So... these "amateur" devices are hopeless. | 273 | /* So... these "amateur" devices are hopeless. |
274 | The only thing, that I can say now: | 274 | The only thing, that I can say now: |
275 | It is very sad that we need to keep ugly obsolete | 275 | It is very sad that we need to keep ugly obsolete |
276 | code to make them happy. | 276 | code to make them happy. |
277 | 277 | ||
278 | They should be moved to more reasonable state, now | 278 | They should be moved to more reasonable state, now |
279 | they use rebuild_header INSTEAD OF hard_start_xmit!!! | 279 | they use rebuild_header INSTEAD OF hard_start_xmit!!! |
280 | Besides that, they are sort of out of date | 280 | Besides that, they are sort of out of date |
281 | (a lot of redundant clones/copies, useless in 2.1), | 281 | (a lot of redundant clones/copies, useless in 2.1), |
282 | I wonder why people believe that they work. | 282 | I wonder why people believe that they work. |
283 | */ | 283 | */ |
284 | switch (dev->type) { | 284 | switch (dev->type) { |
285 | default: | 285 | default: |
286 | break; | 286 | break; |
287 | case ARPHRD_ROSE: | 287 | case ARPHRD_ROSE: |
288 | #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) | 288 | #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) |
289 | case ARPHRD_AX25: | 289 | case ARPHRD_AX25: |
290 | #if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE) | 290 | #if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE) |
291 | case ARPHRD_NETROM: | 291 | case ARPHRD_NETROM: |
292 | #endif | 292 | #endif |
293 | neigh->ops = &arp_broken_ops; | 293 | neigh->ops = &arp_broken_ops; |
294 | neigh->output = neigh->ops->output; | 294 | neigh->output = neigh->ops->output; |
295 | return 0; | 295 | return 0; |
296 | #endif | 296 | #endif |
297 | ;} | 297 | ;} |
298 | #endif | 298 | #endif |
299 | if (neigh->type == RTN_MULTICAST) { | 299 | if (neigh->type == RTN_MULTICAST) { |
300 | neigh->nud_state = NUD_NOARP; | 300 | neigh->nud_state = NUD_NOARP; |
301 | arp_mc_map(addr, neigh->ha, dev, 1); | 301 | arp_mc_map(addr, neigh->ha, dev, 1); |
302 | } else if (dev->flags&(IFF_NOARP|IFF_LOOPBACK)) { | 302 | } else if (dev->flags&(IFF_NOARP|IFF_LOOPBACK)) { |
303 | neigh->nud_state = NUD_NOARP; | 303 | neigh->nud_state = NUD_NOARP; |
304 | memcpy(neigh->ha, dev->dev_addr, dev->addr_len); | 304 | memcpy(neigh->ha, dev->dev_addr, dev->addr_len); |
305 | } else if (neigh->type == RTN_BROADCAST || dev->flags&IFF_POINTOPOINT) { | 305 | } else if (neigh->type == RTN_BROADCAST || dev->flags&IFF_POINTOPOINT) { |
306 | neigh->nud_state = NUD_NOARP; | 306 | neigh->nud_state = NUD_NOARP; |
307 | memcpy(neigh->ha, dev->broadcast, dev->addr_len); | 307 | memcpy(neigh->ha, dev->broadcast, dev->addr_len); |
308 | } | 308 | } |
309 | 309 | ||
310 | if (dev->header_ops->cache) | 310 | if (dev->header_ops->cache) |
311 | neigh->ops = &arp_hh_ops; | 311 | neigh->ops = &arp_hh_ops; |
312 | else | 312 | else |
313 | neigh->ops = &arp_generic_ops; | 313 | neigh->ops = &arp_generic_ops; |
314 | 314 | ||
315 | if (neigh->nud_state&NUD_VALID) | 315 | if (neigh->nud_state&NUD_VALID) |
316 | neigh->output = neigh->ops->connected_output; | 316 | neigh->output = neigh->ops->connected_output; |
317 | else | 317 | else |
318 | neigh->output = neigh->ops->output; | 318 | neigh->output = neigh->ops->output; |
319 | } | 319 | } |
320 | return 0; | 320 | return 0; |
321 | } | 321 | } |
322 | 322 | ||
323 | static void arp_error_report(struct neighbour *neigh, struct sk_buff *skb) | 323 | static void arp_error_report(struct neighbour *neigh, struct sk_buff *skb) |
324 | { | 324 | { |
325 | dst_link_failure(skb); | 325 | dst_link_failure(skb); |
326 | kfree_skb(skb); | 326 | kfree_skb(skb); |
327 | } | 327 | } |
328 | 328 | ||
329 | static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb) | 329 | static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb) |
330 | { | 330 | { |
331 | __be32 saddr = 0; | 331 | __be32 saddr = 0; |
332 | u8 *dst_ha = NULL; | 332 | u8 *dst_ha = NULL; |
333 | struct net_device *dev = neigh->dev; | 333 | struct net_device *dev = neigh->dev; |
334 | __be32 target = *(__be32*)neigh->primary_key; | 334 | __be32 target = *(__be32*)neigh->primary_key; |
335 | int probes = atomic_read(&neigh->probes); | 335 | int probes = atomic_read(&neigh->probes); |
336 | struct in_device *in_dev = in_dev_get(dev); | 336 | struct in_device *in_dev = in_dev_get(dev); |
337 | 337 | ||
338 | if (!in_dev) | 338 | if (!in_dev) |
339 | return; | 339 | return; |
340 | 340 | ||
341 | switch (IN_DEV_ARP_ANNOUNCE(in_dev)) { | 341 | switch (IN_DEV_ARP_ANNOUNCE(in_dev)) { |
342 | default: | 342 | default: |
343 | case 0: /* By default announce any local IP */ | 343 | case 0: /* By default announce any local IP */ |
344 | if (skb && inet_addr_type(dev_net(dev), ip_hdr(skb)->saddr) == RTN_LOCAL) | 344 | if (skb && inet_addr_type(dev_net(dev), ip_hdr(skb)->saddr) == RTN_LOCAL) |
345 | saddr = ip_hdr(skb)->saddr; | 345 | saddr = ip_hdr(skb)->saddr; |
346 | break; | 346 | break; |
347 | case 1: /* Restrict announcements of saddr in same subnet */ | 347 | case 1: /* Restrict announcements of saddr in same subnet */ |
348 | if (!skb) | 348 | if (!skb) |
349 | break; | 349 | break; |
350 | saddr = ip_hdr(skb)->saddr; | 350 | saddr = ip_hdr(skb)->saddr; |
351 | if (inet_addr_type(dev_net(dev), saddr) == RTN_LOCAL) { | 351 | if (inet_addr_type(dev_net(dev), saddr) == RTN_LOCAL) { |
352 | /* saddr should be known to target */ | 352 | /* saddr should be known to target */ |
353 | if (inet_addr_onlink(in_dev, target, saddr)) | 353 | if (inet_addr_onlink(in_dev, target, saddr)) |
354 | break; | 354 | break; |
355 | } | 355 | } |
356 | saddr = 0; | 356 | saddr = 0; |
357 | break; | 357 | break; |
358 | case 2: /* Avoid secondary IPs, get a primary/preferred one */ | 358 | case 2: /* Avoid secondary IPs, get a primary/preferred one */ |
359 | break; | 359 | break; |
360 | } | 360 | } |
361 | 361 | ||
362 | if (in_dev) | 362 | if (in_dev) |
363 | in_dev_put(in_dev); | 363 | in_dev_put(in_dev); |
364 | if (!saddr) | 364 | if (!saddr) |
365 | saddr = inet_select_addr(dev, target, RT_SCOPE_LINK); | 365 | saddr = inet_select_addr(dev, target, RT_SCOPE_LINK); |
366 | 366 | ||
367 | if ((probes -= neigh->parms->ucast_probes) < 0) { | 367 | if ((probes -= neigh->parms->ucast_probes) < 0) { |
368 | if (!(neigh->nud_state&NUD_VALID)) | 368 | if (!(neigh->nud_state&NUD_VALID)) |
369 | printk(KERN_DEBUG "trying to ucast probe in NUD_INVALID\n"); | 369 | printk(KERN_DEBUG "trying to ucast probe in NUD_INVALID\n"); |
370 | dst_ha = neigh->ha; | 370 | dst_ha = neigh->ha; |
371 | read_lock_bh(&neigh->lock); | 371 | read_lock_bh(&neigh->lock); |
372 | } else if ((probes -= neigh->parms->app_probes) < 0) { | 372 | } else if ((probes -= neigh->parms->app_probes) < 0) { |
373 | #ifdef CONFIG_ARPD | 373 | #ifdef CONFIG_ARPD |
374 | neigh_app_ns(neigh); | 374 | neigh_app_ns(neigh); |
375 | #endif | 375 | #endif |
376 | return; | 376 | return; |
377 | } | 377 | } |
378 | 378 | ||
379 | arp_send(ARPOP_REQUEST, ETH_P_ARP, target, dev, saddr, | 379 | arp_send(ARPOP_REQUEST, ETH_P_ARP, target, dev, saddr, |
380 | dst_ha, dev->dev_addr, NULL); | 380 | dst_ha, dev->dev_addr, NULL); |
381 | if (dst_ha) | 381 | if (dst_ha) |
382 | read_unlock_bh(&neigh->lock); | 382 | read_unlock_bh(&neigh->lock); |
383 | } | 383 | } |
384 | 384 | ||
385 | static int arp_ignore(struct in_device *in_dev, __be32 sip, __be32 tip) | 385 | static int arp_ignore(struct in_device *in_dev, __be32 sip, __be32 tip) |
386 | { | 386 | { |
387 | int scope; | 387 | int scope; |
388 | 388 | ||
389 | switch (IN_DEV_ARP_IGNORE(in_dev)) { | 389 | switch (IN_DEV_ARP_IGNORE(in_dev)) { |
390 | case 0: /* Reply, the tip is already validated */ | 390 | case 0: /* Reply, the tip is already validated */ |
391 | return 0; | 391 | return 0; |
392 | case 1: /* Reply only if tip is configured on the incoming interface */ | 392 | case 1: /* Reply only if tip is configured on the incoming interface */ |
393 | sip = 0; | 393 | sip = 0; |
394 | scope = RT_SCOPE_HOST; | 394 | scope = RT_SCOPE_HOST; |
395 | break; | 395 | break; |
396 | case 2: /* | 396 | case 2: /* |
397 | * Reply only if tip is configured on the incoming interface | 397 | * Reply only if tip is configured on the incoming interface |
398 | * and is in same subnet as sip | 398 | * and is in same subnet as sip |
399 | */ | 399 | */ |
400 | scope = RT_SCOPE_HOST; | 400 | scope = RT_SCOPE_HOST; |
401 | break; | 401 | break; |
402 | case 3: /* Do not reply for scope host addresses */ | 402 | case 3: /* Do not reply for scope host addresses */ |
403 | sip = 0; | 403 | sip = 0; |
404 | scope = RT_SCOPE_LINK; | 404 | scope = RT_SCOPE_LINK; |
405 | break; | 405 | break; |
406 | case 4: /* Reserved */ | 406 | case 4: /* Reserved */ |
407 | case 5: | 407 | case 5: |
408 | case 6: | 408 | case 6: |
409 | case 7: | 409 | case 7: |
410 | return 0; | 410 | return 0; |
411 | case 8: /* Do not reply */ | 411 | case 8: /* Do not reply */ |
412 | return 1; | 412 | return 1; |
413 | default: | 413 | default: |
414 | return 0; | 414 | return 0; |
415 | } | 415 | } |
416 | return !inet_confirm_addr(in_dev, sip, tip, scope); | 416 | return !inet_confirm_addr(in_dev, sip, tip, scope); |
417 | } | 417 | } |
418 | 418 | ||
419 | static int arp_filter(__be32 sip, __be32 tip, struct net_device *dev) | 419 | static int arp_filter(__be32 sip, __be32 tip, struct net_device *dev) |
420 | { | 420 | { |
421 | struct flowi fl = { .nl_u = { .ip4_u = { .daddr = sip, | 421 | struct flowi fl = { .nl_u = { .ip4_u = { .daddr = sip, |
422 | .saddr = tip } } }; | 422 | .saddr = tip } } }; |
423 | struct rtable *rt; | 423 | struct rtable *rt; |
424 | int flag = 0; | 424 | int flag = 0; |
425 | /*unsigned long now; */ | 425 | /*unsigned long now; */ |
426 | struct net *net = dev_net(dev); | 426 | struct net *net = dev_net(dev); |
427 | 427 | ||
428 | if (ip_route_output_key(net, &rt, &fl) < 0) | 428 | if (ip_route_output_key(net, &rt, &fl) < 0) |
429 | return 1; | 429 | return 1; |
430 | if (rt->u.dst.dev != dev) { | 430 | if (rt->u.dst.dev != dev) { |
431 | NET_INC_STATS_BH(net, LINUX_MIB_ARPFILTER); | 431 | NET_INC_STATS_BH(net, LINUX_MIB_ARPFILTER); |
432 | flag = 1; | 432 | flag = 1; |
433 | } | 433 | } |
434 | ip_rt_put(rt); | 434 | ip_rt_put(rt); |
435 | return flag; | 435 | return flag; |
436 | } | 436 | } |
437 | 437 | ||
438 | /* OBSOLETE FUNCTIONS */ | 438 | /* OBSOLETE FUNCTIONS */ |
439 | 439 | ||
440 | /* | 440 | /* |
441 | * Find an arp mapping in the cache. If not found, post a request. | 441 | * Find an arp mapping in the cache. If not found, post a request. |
442 | * | 442 | * |
443 | * It is very UGLY routine: it DOES NOT use skb->dst->neighbour, | 443 | * It is very UGLY routine: it DOES NOT use skb->dst->neighbour, |
444 | * even if it exists. It is supposed that skb->dev was mangled | 444 | * even if it exists. It is supposed that skb->dev was mangled |
445 | * by a virtual device (eql, shaper). Nobody but broken devices | 445 | * by a virtual device (eql, shaper). Nobody but broken devices |
446 | * is allowed to use this function, it is scheduled to be removed. --ANK | 446 | * is allowed to use this function, it is scheduled to be removed. --ANK |
447 | */ | 447 | */ |
448 | 448 | ||
449 | static int arp_set_predefined(int addr_hint, unsigned char * haddr, __be32 paddr, struct net_device * dev) | 449 | static int arp_set_predefined(int addr_hint, unsigned char * haddr, __be32 paddr, struct net_device * dev) |
450 | { | 450 | { |
451 | switch (addr_hint) { | 451 | switch (addr_hint) { |
452 | case RTN_LOCAL: | 452 | case RTN_LOCAL: |
453 | printk(KERN_DEBUG "ARP: arp called for own IP address\n"); | 453 | printk(KERN_DEBUG "ARP: arp called for own IP address\n"); |
454 | memcpy(haddr, dev->dev_addr, dev->addr_len); | 454 | memcpy(haddr, dev->dev_addr, dev->addr_len); |
455 | return 1; | 455 | return 1; |
456 | case RTN_MULTICAST: | 456 | case RTN_MULTICAST: |
457 | arp_mc_map(paddr, haddr, dev, 1); | 457 | arp_mc_map(paddr, haddr, dev, 1); |
458 | return 1; | 458 | return 1; |
459 | case RTN_BROADCAST: | 459 | case RTN_BROADCAST: |
460 | memcpy(haddr, dev->broadcast, dev->addr_len); | 460 | memcpy(haddr, dev->broadcast, dev->addr_len); |
461 | return 1; | 461 | return 1; |
462 | } | 462 | } |
463 | return 0; | 463 | return 0; |
464 | } | 464 | } |
465 | 465 | ||
466 | 466 | ||
467 | int arp_find(unsigned char *haddr, struct sk_buff *skb) | 467 | int arp_find(unsigned char *haddr, struct sk_buff *skb) |
468 | { | 468 | { |
469 | struct net_device *dev = skb->dev; | 469 | struct net_device *dev = skb->dev; |
470 | __be32 paddr; | 470 | __be32 paddr; |
471 | struct neighbour *n; | 471 | struct neighbour *n; |
472 | 472 | ||
473 | if (!skb_dst(skb)) { | 473 | if (!skb_dst(skb)) { |
474 | printk(KERN_DEBUG "arp_find is called with dst==NULL\n"); | 474 | printk(KERN_DEBUG "arp_find is called with dst==NULL\n"); |
475 | kfree_skb(skb); | 475 | kfree_skb(skb); |
476 | return 1; | 476 | return 1; |
477 | } | 477 | } |
478 | 478 | ||
479 | paddr = skb_rtable(skb)->rt_gateway; | 479 | paddr = skb_rtable(skb)->rt_gateway; |
480 | 480 | ||
481 | if (arp_set_predefined(inet_addr_type(dev_net(dev), paddr), haddr, paddr, dev)) | 481 | if (arp_set_predefined(inet_addr_type(dev_net(dev), paddr), haddr, paddr, dev)) |
482 | return 0; | 482 | return 0; |
483 | 483 | ||
484 | n = __neigh_lookup(&arp_tbl, &paddr, dev, 1); | 484 | n = __neigh_lookup(&arp_tbl, &paddr, dev, 1); |
485 | 485 | ||
486 | if (n) { | 486 | if (n) { |
487 | n->used = jiffies; | 487 | n->used = jiffies; |
488 | if (n->nud_state&NUD_VALID || neigh_event_send(n, skb) == 0) { | 488 | if (n->nud_state&NUD_VALID || neigh_event_send(n, skb) == 0) { |
489 | read_lock_bh(&n->lock); | 489 | read_lock_bh(&n->lock); |
490 | memcpy(haddr, n->ha, dev->addr_len); | 490 | memcpy(haddr, n->ha, dev->addr_len); |
491 | read_unlock_bh(&n->lock); | 491 | read_unlock_bh(&n->lock); |
492 | neigh_release(n); | 492 | neigh_release(n); |
493 | return 0; | 493 | return 0; |
494 | } | 494 | } |
495 | neigh_release(n); | 495 | neigh_release(n); |
496 | } else | 496 | } else |
497 | kfree_skb(skb); | 497 | kfree_skb(skb); |
498 | return 1; | 498 | return 1; |
499 | } | 499 | } |
500 | 500 | ||
501 | /* END OF OBSOLETE FUNCTIONS */ | 501 | /* END OF OBSOLETE FUNCTIONS */ |
502 | 502 | ||
503 | int arp_bind_neighbour(struct dst_entry *dst) | 503 | int arp_bind_neighbour(struct dst_entry *dst) |
504 | { | 504 | { |
505 | struct net_device *dev = dst->dev; | 505 | struct net_device *dev = dst->dev; |
506 | struct neighbour *n = dst->neighbour; | 506 | struct neighbour *n = dst->neighbour; |
507 | 507 | ||
508 | if (dev == NULL) | 508 | if (dev == NULL) |
509 | return -EINVAL; | 509 | return -EINVAL; |
510 | if (n == NULL) { | 510 | if (n == NULL) { |
511 | __be32 nexthop = ((struct rtable *)dst)->rt_gateway; | 511 | __be32 nexthop = ((struct rtable *)dst)->rt_gateway; |
512 | if (dev->flags&(IFF_LOOPBACK|IFF_POINTOPOINT)) | 512 | if (dev->flags&(IFF_LOOPBACK|IFF_POINTOPOINT)) |
513 | nexthop = 0; | 513 | nexthop = 0; |
514 | n = __neigh_lookup_errno( | 514 | n = __neigh_lookup_errno( |
515 | #if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE) | 515 | #if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE) |
516 | dev->type == ARPHRD_ATM ? clip_tbl_hook : | 516 | dev->type == ARPHRD_ATM ? clip_tbl_hook : |
517 | #endif | 517 | #endif |
518 | &arp_tbl, &nexthop, dev); | 518 | &arp_tbl, &nexthop, dev); |
519 | if (IS_ERR(n)) | 519 | if (IS_ERR(n)) |
520 | return PTR_ERR(n); | 520 | return PTR_ERR(n); |
521 | dst->neighbour = n; | 521 | dst->neighbour = n; |
522 | } | 522 | } |
523 | return 0; | 523 | return 0; |
524 | } | 524 | } |
525 | 525 | ||
526 | /* | 526 | /* |
527 | * Check if we can use proxy ARP for this path | 527 | * Check if we can use proxy ARP for this path |
528 | */ | 528 | */ |
529 | static inline int arp_fwd_proxy(struct in_device *in_dev, | 529 | static inline int arp_fwd_proxy(struct in_device *in_dev, |
530 | struct net_device *dev, struct rtable *rt) | 530 | struct net_device *dev, struct rtable *rt) |
531 | { | 531 | { |
532 | struct in_device *out_dev; | 532 | struct in_device *out_dev; |
533 | int imi, omi = -1; | 533 | int imi, omi = -1; |
534 | 534 | ||
535 | if (rt->u.dst.dev == dev) | 535 | if (rt->u.dst.dev == dev) |
536 | return 0; | 536 | return 0; |
537 | 537 | ||
538 | if (!IN_DEV_PROXY_ARP(in_dev)) | 538 | if (!IN_DEV_PROXY_ARP(in_dev)) |
539 | return 0; | 539 | return 0; |
540 | 540 | ||
541 | if ((imi = IN_DEV_MEDIUM_ID(in_dev)) == 0) | 541 | if ((imi = IN_DEV_MEDIUM_ID(in_dev)) == 0) |
542 | return 1; | 542 | return 1; |
543 | if (imi == -1) | 543 | if (imi == -1) |
544 | return 0; | 544 | return 0; |
545 | 545 | ||
546 | /* place to check for proxy_arp for routes */ | 546 | /* place to check for proxy_arp for routes */ |
547 | 547 | ||
548 | if ((out_dev = in_dev_get(rt->u.dst.dev)) != NULL) { | 548 | if ((out_dev = in_dev_get(rt->u.dst.dev)) != NULL) { |
549 | omi = IN_DEV_MEDIUM_ID(out_dev); | 549 | omi = IN_DEV_MEDIUM_ID(out_dev); |
550 | in_dev_put(out_dev); | 550 | in_dev_put(out_dev); |
551 | } | 551 | } |
552 | return (omi != imi && omi != -1); | 552 | return (omi != imi && omi != -1); |
553 | } | 553 | } |
554 | 554 | ||
555 | /* | 555 | /* |
556 | * Check for RFC3069 proxy arp private VLAN (allow to send back to same dev) | 556 | * Check for RFC3069 proxy arp private VLAN (allow to send back to same dev) |
557 | * | 557 | * |
558 | * RFC3069 supports proxy arp replies back to the same interface. This | 558 | * RFC3069 supports proxy arp replies back to the same interface. This |
559 | * is done to support (ethernet) switch features, like RFC 3069, where | 559 | * is done to support (ethernet) switch features, like RFC 3069, where |
560 | * the individual ports are not allowed to communicate with each | 560 | * the individual ports are not allowed to communicate with each |
561 | * other, BUT they are allowed to talk to the upstream router. As | 561 | * other, BUT they are allowed to talk to the upstream router. As |
562 | * described in RFC 3069, it is possible to allow these hosts to | 562 | * described in RFC 3069, it is possible to allow these hosts to |
563 | * communicate through the upstream router, by proxy_arp'ing. | 563 | * communicate through the upstream router, by proxy_arp'ing. |
564 | * | 564 | * |
565 | * RFC 3069: "VLAN Aggregation for Efficient IP Address Allocation" | 565 | * RFC 3069: "VLAN Aggregation for Efficient IP Address Allocation" |
566 | * | 566 | * |
567 | * This technology is known by different names: | 567 | * This technology is known by different names: |
568 | * In RFC 3069 it is called VLAN Aggregation. | 568 | * In RFC 3069 it is called VLAN Aggregation. |
569 | * Cisco and Allied Telesyn call it Private VLAN. | 569 | * Cisco and Allied Telesyn call it Private VLAN. |
570 | * Hewlett-Packard call it Source-Port filtering or port-isolation. | 570 | * Hewlett-Packard call it Source-Port filtering or port-isolation. |
571 | * Ericsson call it MAC-Forced Forwarding (RFC Draft). | 571 | * Ericsson call it MAC-Forced Forwarding (RFC Draft). |
572 | * | 572 | * |
573 | */ | 573 | */ |
574 | static inline int arp_fwd_pvlan(struct in_device *in_dev, | 574 | static inline int arp_fwd_pvlan(struct in_device *in_dev, |
575 | struct net_device *dev, struct rtable *rt, | 575 | struct net_device *dev, struct rtable *rt, |
576 | __be32 sip, __be32 tip) | 576 | __be32 sip, __be32 tip) |
577 | { | 577 | { |
578 | /* Private VLAN is only concerned about the same ethernet segment */ | 578 | /* Private VLAN is only concerned about the same ethernet segment */ |
579 | if (rt->u.dst.dev != dev) | 579 | if (rt->u.dst.dev != dev) |
580 | return 0; | 580 | return 0; |
581 | 581 | ||
582 | /* Don't reply on self probes (often done by windowz boxes)*/ | 582 | /* Don't reply on self probes (often done by windowz boxes)*/ |
583 | if (sip == tip) | 583 | if (sip == tip) |
584 | return 0; | 584 | return 0; |
585 | 585 | ||
586 | if (IN_DEV_PROXY_ARP_PVLAN(in_dev)) | 586 | if (IN_DEV_PROXY_ARP_PVLAN(in_dev)) |
587 | return 1; | 587 | return 1; |
588 | else | 588 | else |
589 | return 0; | 589 | return 0; |
590 | } | 590 | } |
591 | 591 | ||
592 | /* | 592 | /* |
593 | * Interface to link layer: send routine and receive handler. | 593 | * Interface to link layer: send routine and receive handler. |
594 | */ | 594 | */ |
595 | 595 | ||
596 | /* | 596 | /* |
597 | * Create an arp packet. If (dest_hw == NULL), we create a broadcast | 597 | * Create an arp packet. If (dest_hw == NULL), we create a broadcast |
598 | * message. | 598 | * message. |
599 | */ | 599 | */ |
600 | struct sk_buff *arp_create(int type, int ptype, __be32 dest_ip, | 600 | struct sk_buff *arp_create(int type, int ptype, __be32 dest_ip, |
601 | struct net_device *dev, __be32 src_ip, | 601 | struct net_device *dev, __be32 src_ip, |
602 | const unsigned char *dest_hw, | 602 | const unsigned char *dest_hw, |
603 | const unsigned char *src_hw, | 603 | const unsigned char *src_hw, |
604 | const unsigned char *target_hw) | 604 | const unsigned char *target_hw) |
605 | { | 605 | { |
606 | struct sk_buff *skb; | 606 | struct sk_buff *skb; |
607 | struct arphdr *arp; | 607 | struct arphdr *arp; |
608 | unsigned char *arp_ptr; | 608 | unsigned char *arp_ptr; |
609 | 609 | ||
610 | /* | 610 | /* |
611 | * Allocate a buffer | 611 | * Allocate a buffer |
612 | */ | 612 | */ |
613 | 613 | ||
614 | skb = alloc_skb(arp_hdr_len(dev) + LL_ALLOCATED_SPACE(dev), GFP_ATOMIC); | 614 | skb = alloc_skb(arp_hdr_len(dev) + LL_ALLOCATED_SPACE(dev), GFP_ATOMIC); |
615 | if (skb == NULL) | 615 | if (skb == NULL) |
616 | return NULL; | 616 | return NULL; |
617 | 617 | ||
618 | skb_reserve(skb, LL_RESERVED_SPACE(dev)); | 618 | skb_reserve(skb, LL_RESERVED_SPACE(dev)); |
619 | skb_reset_network_header(skb); | 619 | skb_reset_network_header(skb); |
620 | arp = (struct arphdr *) skb_put(skb, arp_hdr_len(dev)); | 620 | arp = (struct arphdr *) skb_put(skb, arp_hdr_len(dev)); |
621 | skb->dev = dev; | 621 | skb->dev = dev; |
622 | skb->protocol = htons(ETH_P_ARP); | 622 | skb->protocol = htons(ETH_P_ARP); |
623 | if (src_hw == NULL) | 623 | if (src_hw == NULL) |
624 | src_hw = dev->dev_addr; | 624 | src_hw = dev->dev_addr; |
625 | if (dest_hw == NULL) | 625 | if (dest_hw == NULL) |
626 | dest_hw = dev->broadcast; | 626 | dest_hw = dev->broadcast; |
627 | 627 | ||
628 | /* | 628 | /* |
629 | * Fill the device header for the ARP frame | 629 | * Fill the device header for the ARP frame |
630 | */ | 630 | */ |
631 | if (dev_hard_header(skb, dev, ptype, dest_hw, src_hw, skb->len) < 0) | 631 | if (dev_hard_header(skb, dev, ptype, dest_hw, src_hw, skb->len) < 0) |
632 | goto out; | 632 | goto out; |
633 | 633 | ||
634 | /* | 634 | /* |
635 | * Fill out the arp protocol part. | 635 | * Fill out the arp protocol part. |
636 | * | 636 | * |
637 | * The arp hardware type should match the device type, except for FDDI, | 637 | * The arp hardware type should match the device type, except for FDDI, |
638 | * which (according to RFC 1390) should always equal 1 (Ethernet). | 638 | * which (according to RFC 1390) should always equal 1 (Ethernet). |
639 | */ | 639 | */ |
640 | /* | 640 | /* |
641 | * Exceptions everywhere. AX.25 uses the AX.25 PID value not the | 641 | * Exceptions everywhere. AX.25 uses the AX.25 PID value not the |
642 | * DIX code for the protocol. Make these device structure fields. | 642 | * DIX code for the protocol. Make these device structure fields. |
643 | */ | 643 | */ |
644 | switch (dev->type) { | 644 | switch (dev->type) { |
645 | default: | 645 | default: |
646 | arp->ar_hrd = htons(dev->type); | 646 | arp->ar_hrd = htons(dev->type); |
647 | arp->ar_pro = htons(ETH_P_IP); | 647 | arp->ar_pro = htons(ETH_P_IP); |
648 | break; | 648 | break; |
649 | 649 | ||
650 | #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) | 650 | #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) |
651 | case ARPHRD_AX25: | 651 | case ARPHRD_AX25: |
652 | arp->ar_hrd = htons(ARPHRD_AX25); | 652 | arp->ar_hrd = htons(ARPHRD_AX25); |
653 | arp->ar_pro = htons(AX25_P_IP); | 653 | arp->ar_pro = htons(AX25_P_IP); |
654 | break; | 654 | break; |
655 | 655 | ||
656 | #if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE) | 656 | #if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE) |
657 | case ARPHRD_NETROM: | 657 | case ARPHRD_NETROM: |
658 | arp->ar_hrd = htons(ARPHRD_NETROM); | 658 | arp->ar_hrd = htons(ARPHRD_NETROM); |
659 | arp->ar_pro = htons(AX25_P_IP); | 659 | arp->ar_pro = htons(AX25_P_IP); |
660 | break; | 660 | break; |
661 | #endif | 661 | #endif |
662 | #endif | 662 | #endif |
663 | 663 | ||
664 | #if defined(CONFIG_FDDI) || defined(CONFIG_FDDI_MODULE) | 664 | #if defined(CONFIG_FDDI) || defined(CONFIG_FDDI_MODULE) |
665 | case ARPHRD_FDDI: | 665 | case ARPHRD_FDDI: |
666 | arp->ar_hrd = htons(ARPHRD_ETHER); | 666 | arp->ar_hrd = htons(ARPHRD_ETHER); |
667 | arp->ar_pro = htons(ETH_P_IP); | 667 | arp->ar_pro = htons(ETH_P_IP); |
668 | break; | 668 | break; |
669 | #endif | 669 | #endif |
670 | #if defined(CONFIG_TR) || defined(CONFIG_TR_MODULE) | 670 | #if defined(CONFIG_TR) || defined(CONFIG_TR_MODULE) |
671 | case ARPHRD_IEEE802_TR: | 671 | case ARPHRD_IEEE802_TR: |
672 | arp->ar_hrd = htons(ARPHRD_IEEE802); | 672 | arp->ar_hrd = htons(ARPHRD_IEEE802); |
673 | arp->ar_pro = htons(ETH_P_IP); | 673 | arp->ar_pro = htons(ETH_P_IP); |
674 | break; | 674 | break; |
675 | #endif | 675 | #endif |
676 | } | 676 | } |
677 | 677 | ||
678 | arp->ar_hln = dev->addr_len; | 678 | arp->ar_hln = dev->addr_len; |
679 | arp->ar_pln = 4; | 679 | arp->ar_pln = 4; |
680 | arp->ar_op = htons(type); | 680 | arp->ar_op = htons(type); |
681 | 681 | ||
682 | arp_ptr=(unsigned char *)(arp+1); | 682 | arp_ptr=(unsigned char *)(arp+1); |
683 | 683 | ||
684 | memcpy(arp_ptr, src_hw, dev->addr_len); | 684 | memcpy(arp_ptr, src_hw, dev->addr_len); |
685 | arp_ptr += dev->addr_len; | 685 | arp_ptr += dev->addr_len; |
686 | memcpy(arp_ptr, &src_ip, 4); | 686 | memcpy(arp_ptr, &src_ip, 4); |
687 | arp_ptr += 4; | 687 | arp_ptr += 4; |
688 | if (target_hw != NULL) | 688 | if (target_hw != NULL) |
689 | memcpy(arp_ptr, target_hw, dev->addr_len); | 689 | memcpy(arp_ptr, target_hw, dev->addr_len); |
690 | else | 690 | else |
691 | memset(arp_ptr, 0, dev->addr_len); | 691 | memset(arp_ptr, 0, dev->addr_len); |
692 | arp_ptr += dev->addr_len; | 692 | arp_ptr += dev->addr_len; |
693 | memcpy(arp_ptr, &dest_ip, 4); | 693 | memcpy(arp_ptr, &dest_ip, 4); |
694 | 694 | ||
695 | return skb; | 695 | return skb; |
696 | 696 | ||
697 | out: | 697 | out: |
698 | kfree_skb(skb); | 698 | kfree_skb(skb); |
699 | return NULL; | 699 | return NULL; |
700 | } | 700 | } |
701 | 701 | ||
702 | /* | 702 | /* |
703 | * Send an arp packet. | 703 | * Send an arp packet. |
704 | */ | 704 | */ |
705 | void arp_xmit(struct sk_buff *skb) | 705 | void arp_xmit(struct sk_buff *skb) |
706 | { | 706 | { |
707 | /* Send it off, maybe filter it using firewalling first. */ | 707 | /* Send it off, maybe filter it using firewalling first. */ |
708 | NF_HOOK(NFPROTO_ARP, NF_ARP_OUT, skb, NULL, skb->dev, dev_queue_xmit); | 708 | NF_HOOK(NFPROTO_ARP, NF_ARP_OUT, skb, NULL, skb->dev, dev_queue_xmit); |
709 | } | 709 | } |
710 | 710 | ||
711 | /* | 711 | /* |
712 | * Create and send an arp packet. | 712 | * Create and send an arp packet. |
713 | */ | 713 | */ |
714 | void arp_send(int type, int ptype, __be32 dest_ip, | 714 | void arp_send(int type, int ptype, __be32 dest_ip, |
715 | struct net_device *dev, __be32 src_ip, | 715 | struct net_device *dev, __be32 src_ip, |
716 | const unsigned char *dest_hw, const unsigned char *src_hw, | 716 | const unsigned char *dest_hw, const unsigned char *src_hw, |
717 | const unsigned char *target_hw) | 717 | const unsigned char *target_hw) |
718 | { | 718 | { |
719 | struct sk_buff *skb; | 719 | struct sk_buff *skb; |
720 | 720 | ||
721 | /* | 721 | /* |
722 | * No arp on this interface. | 722 | * No arp on this interface. |
723 | */ | 723 | */ |
724 | 724 | ||
725 | if (dev->flags&IFF_NOARP) | 725 | if (dev->flags&IFF_NOARP) |
726 | return; | 726 | return; |
727 | 727 | ||
728 | skb = arp_create(type, ptype, dest_ip, dev, src_ip, | 728 | skb = arp_create(type, ptype, dest_ip, dev, src_ip, |
729 | dest_hw, src_hw, target_hw); | 729 | dest_hw, src_hw, target_hw); |
730 | if (skb == NULL) { | 730 | if (skb == NULL) { |
731 | return; | 731 | return; |
732 | } | 732 | } |
733 | 733 | ||
734 | arp_xmit(skb); | 734 | arp_xmit(skb); |
735 | } | 735 | } |
736 | 736 | ||
737 | /* | 737 | /* |
738 | * Process an arp request. | 738 | * Process an arp request. |
739 | */ | 739 | */ |
740 | 740 | ||
741 | static int arp_process(struct sk_buff *skb) | 741 | static int arp_process(struct sk_buff *skb) |
742 | { | 742 | { |
743 | struct net_device *dev = skb->dev; | 743 | struct net_device *dev = skb->dev; |
744 | struct in_device *in_dev = in_dev_get(dev); | 744 | struct in_device *in_dev = in_dev_get(dev); |
745 | struct arphdr *arp; | 745 | struct arphdr *arp; |
746 | unsigned char *arp_ptr; | 746 | unsigned char *arp_ptr; |
747 | struct rtable *rt; | 747 | struct rtable *rt; |
748 | unsigned char *sha; | 748 | unsigned char *sha; |
749 | __be32 sip, tip; | 749 | __be32 sip, tip; |
750 | u16 dev_type = dev->type; | 750 | u16 dev_type = dev->type; |
751 | int addr_type; | 751 | int addr_type; |
752 | struct neighbour *n; | 752 | struct neighbour *n; |
753 | struct net *net = dev_net(dev); | 753 | struct net *net = dev_net(dev); |
754 | 754 | ||
755 | /* arp_rcv below verifies the ARP header and verifies the device | 755 | /* arp_rcv below verifies the ARP header and verifies the device |
756 | * is ARP'able. | 756 | * is ARP'able. |
757 | */ | 757 | */ |
758 | 758 | ||
759 | if (in_dev == NULL) | 759 | if (in_dev == NULL) |
760 | goto out; | 760 | goto out; |
761 | 761 | ||
762 | arp = arp_hdr(skb); | 762 | arp = arp_hdr(skb); |
763 | 763 | ||
764 | switch (dev_type) { | 764 | switch (dev_type) { |
765 | default: | 765 | default: |
766 | if (arp->ar_pro != htons(ETH_P_IP) || | 766 | if (arp->ar_pro != htons(ETH_P_IP) || |
767 | htons(dev_type) != arp->ar_hrd) | 767 | htons(dev_type) != arp->ar_hrd) |
768 | goto out; | 768 | goto out; |
769 | break; | 769 | break; |
770 | case ARPHRD_ETHER: | 770 | case ARPHRD_ETHER: |
771 | case ARPHRD_IEEE802_TR: | 771 | case ARPHRD_IEEE802_TR: |
772 | case ARPHRD_FDDI: | 772 | case ARPHRD_FDDI: |
773 | case ARPHRD_IEEE802: | 773 | case ARPHRD_IEEE802: |
774 | /* | 774 | /* |
775 | * ETHERNET, Token Ring and Fibre Channel (which are IEEE 802 | 775 | * ETHERNET, Token Ring and Fibre Channel (which are IEEE 802 |
776 | * devices, according to RFC 2625) devices will accept ARP | 776 | * devices, according to RFC 2625) devices will accept ARP |
777 | * hardware types of either 1 (Ethernet) or 6 (IEEE 802.2). | 777 | * hardware types of either 1 (Ethernet) or 6 (IEEE 802.2). |
778 | * This is the case also of FDDI, where the RFC 1390 says that | 778 | * This is the case also of FDDI, where the RFC 1390 says that |
779 | * FDDI devices should accept ARP hardware of (1) Ethernet, | 779 | * FDDI devices should accept ARP hardware of (1) Ethernet, |
780 | * however, to be more robust, we'll accept both 1 (Ethernet) | 780 | * however, to be more robust, we'll accept both 1 (Ethernet) |
781 | * or 6 (IEEE 802.2) | 781 | * or 6 (IEEE 802.2) |
782 | */ | 782 | */ |
783 | if ((arp->ar_hrd != htons(ARPHRD_ETHER) && | 783 | if ((arp->ar_hrd != htons(ARPHRD_ETHER) && |
784 | arp->ar_hrd != htons(ARPHRD_IEEE802)) || | 784 | arp->ar_hrd != htons(ARPHRD_IEEE802)) || |
785 | arp->ar_pro != htons(ETH_P_IP)) | 785 | arp->ar_pro != htons(ETH_P_IP)) |
786 | goto out; | 786 | goto out; |
787 | break; | 787 | break; |
788 | case ARPHRD_AX25: | 788 | case ARPHRD_AX25: |
789 | if (arp->ar_pro != htons(AX25_P_IP) || | 789 | if (arp->ar_pro != htons(AX25_P_IP) || |
790 | arp->ar_hrd != htons(ARPHRD_AX25)) | 790 | arp->ar_hrd != htons(ARPHRD_AX25)) |
791 | goto out; | 791 | goto out; |
792 | break; | 792 | break; |
793 | case ARPHRD_NETROM: | 793 | case ARPHRD_NETROM: |
794 | if (arp->ar_pro != htons(AX25_P_IP) || | 794 | if (arp->ar_pro != htons(AX25_P_IP) || |
795 | arp->ar_hrd != htons(ARPHRD_NETROM)) | 795 | arp->ar_hrd != htons(ARPHRD_NETROM)) |
796 | goto out; | 796 | goto out; |
797 | break; | 797 | break; |
798 | } | 798 | } |
799 | 799 | ||
800 | /* Understand only these message types */ | 800 | /* Understand only these message types */ |
801 | 801 | ||
802 | if (arp->ar_op != htons(ARPOP_REPLY) && | 802 | if (arp->ar_op != htons(ARPOP_REPLY) && |
803 | arp->ar_op != htons(ARPOP_REQUEST)) | 803 | arp->ar_op != htons(ARPOP_REQUEST)) |
804 | goto out; | 804 | goto out; |
805 | 805 | ||
806 | /* | 806 | /* |
807 | * Extract fields | 807 | * Extract fields |
808 | */ | 808 | */ |
809 | arp_ptr= (unsigned char *)(arp+1); | 809 | arp_ptr= (unsigned char *)(arp+1); |
810 | sha = arp_ptr; | 810 | sha = arp_ptr; |
811 | arp_ptr += dev->addr_len; | 811 | arp_ptr += dev->addr_len; |
812 | memcpy(&sip, arp_ptr, 4); | 812 | memcpy(&sip, arp_ptr, 4); |
813 | arp_ptr += 4; | 813 | arp_ptr += 4; |
814 | arp_ptr += dev->addr_len; | 814 | arp_ptr += dev->addr_len; |
815 | memcpy(&tip, arp_ptr, 4); | 815 | memcpy(&tip, arp_ptr, 4); |
816 | /* | 816 | /* |
817 | * Check for bad requests for 127.x.x.x and requests for multicast | 817 | * Check for bad requests for 127.x.x.x and requests for multicast |
818 | * addresses. If this is one such, delete it. | 818 | * addresses. If this is one such, delete it. |
819 | */ | 819 | */ |
820 | if (ipv4_is_loopback(tip) || ipv4_is_multicast(tip)) | 820 | if (ipv4_is_loopback(tip) || ipv4_is_multicast(tip)) |
821 | goto out; | 821 | goto out; |
822 | 822 | ||
823 | /* | 823 | /* |
824 | * Special case: We must set Frame Relay source Q.922 address | 824 | * Special case: We must set Frame Relay source Q.922 address |
825 | */ | 825 | */ |
826 | if (dev_type == ARPHRD_DLCI) | 826 | if (dev_type == ARPHRD_DLCI) |
827 | sha = dev->broadcast; | 827 | sha = dev->broadcast; |
828 | 828 | ||
829 | /* | 829 | /* |
830 | * Process entry. The idea here is we want to send a reply if it is a | 830 | * Process entry. The idea here is we want to send a reply if it is a |
831 | * request for us or if it is a request for someone else that we hold | 831 | * request for us or if it is a request for someone else that we hold |
832 | * a proxy for. We want to add an entry to our cache if it is a reply | 832 | * a proxy for. We want to add an entry to our cache if it is a reply |
833 | * to us or if it is a request for our address. | 833 | * to us or if it is a request for our address. |
834 | * (The assumption for this last is that if someone is requesting our | 834 | * (The assumption for this last is that if someone is requesting our |
835 | * address, they are probably intending to talk to us, so it saves time | 835 | * address, they are probably intending to talk to us, so it saves time |
836 | * if we cache their address. Their address is also probably not in | 836 | * if we cache their address. Their address is also probably not in |
837 | * our cache, since ours is not in their cache.) | 837 | * our cache, since ours is not in their cache.) |
838 | * | 838 | * |
839 | * Putting this another way, we only care about replies if they are to | 839 | * Putting this another way, we only care about replies if they are to |
840 | * us, in which case we add them to the cache. For requests, we care | 840 | * us, in which case we add them to the cache. For requests, we care |
841 | * about those for us and those for our proxies. We reply to both, | 841 | * about those for us and those for our proxies. We reply to both, |
842 | * and in the case of requests for us we add the requester to the arp | 842 | * and in the case of requests for us we add the requester to the arp |
843 | * cache. | 843 | * cache. |
844 | */ | 844 | */ |
845 | 845 | ||
846 | /* Special case: IPv4 duplicate address detection packet (RFC2131) */ | 846 | /* Special case: IPv4 duplicate address detection packet (RFC2131) */ |
847 | if (sip == 0) { | 847 | if (sip == 0) { |
848 | if (arp->ar_op == htons(ARPOP_REQUEST) && | 848 | if (arp->ar_op == htons(ARPOP_REQUEST) && |
849 | inet_addr_type(net, tip) == RTN_LOCAL && | 849 | inet_addr_type(net, tip) == RTN_LOCAL && |
850 | !arp_ignore(in_dev, sip, tip)) | 850 | !arp_ignore(in_dev, sip, tip)) |
851 | arp_send(ARPOP_REPLY, ETH_P_ARP, sip, dev, tip, sha, | 851 | arp_send(ARPOP_REPLY, ETH_P_ARP, sip, dev, tip, sha, |
852 | dev->dev_addr, sha); | 852 | dev->dev_addr, sha); |
853 | goto out; | 853 | goto out; |
854 | } | 854 | } |
855 | 855 | ||
856 | if (arp->ar_op == htons(ARPOP_REQUEST) && | 856 | if (arp->ar_op == htons(ARPOP_REQUEST) && |
857 | ip_route_input(skb, tip, sip, 0, dev) == 0) { | 857 | ip_route_input_noref(skb, tip, sip, 0, dev) == 0) { |
858 | 858 | ||
859 | rt = skb_rtable(skb); | 859 | rt = skb_rtable(skb); |
860 | addr_type = rt->rt_type; | 860 | addr_type = rt->rt_type; |
861 | 861 | ||
862 | if (addr_type == RTN_LOCAL) { | 862 | if (addr_type == RTN_LOCAL) { |
863 | int dont_send = 0; | 863 | int dont_send = 0; |
864 | 864 | ||
865 | if (!dont_send) | 865 | if (!dont_send) |
866 | dont_send |= arp_ignore(in_dev,sip,tip); | 866 | dont_send |= arp_ignore(in_dev,sip,tip); |
867 | if (!dont_send && IN_DEV_ARPFILTER(in_dev)) | 867 | if (!dont_send && IN_DEV_ARPFILTER(in_dev)) |
868 | dont_send |= arp_filter(sip,tip,dev); | 868 | dont_send |= arp_filter(sip,tip,dev); |
869 | if (!dont_send) { | 869 | if (!dont_send) { |
870 | n = neigh_event_ns(&arp_tbl, sha, &sip, dev); | 870 | n = neigh_event_ns(&arp_tbl, sha, &sip, dev); |
871 | if (n) { | 871 | if (n) { |
872 | arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,sha,dev->dev_addr,sha); | 872 | arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,sha,dev->dev_addr,sha); |
873 | neigh_release(n); | 873 | neigh_release(n); |
874 | } | 874 | } |
875 | } | 875 | } |
876 | goto out; | 876 | goto out; |
877 | } else if (IN_DEV_FORWARD(in_dev)) { | 877 | } else if (IN_DEV_FORWARD(in_dev)) { |
878 | if (addr_type == RTN_UNICAST && | 878 | if (addr_type == RTN_UNICAST && |
879 | (arp_fwd_proxy(in_dev, dev, rt) || | 879 | (arp_fwd_proxy(in_dev, dev, rt) || |
880 | arp_fwd_pvlan(in_dev, dev, rt, sip, tip) || | 880 | arp_fwd_pvlan(in_dev, dev, rt, sip, tip) || |
881 | pneigh_lookup(&arp_tbl, net, &tip, dev, 0))) | 881 | pneigh_lookup(&arp_tbl, net, &tip, dev, 0))) |
882 | { | 882 | { |
883 | n = neigh_event_ns(&arp_tbl, sha, &sip, dev); | 883 | n = neigh_event_ns(&arp_tbl, sha, &sip, dev); |
884 | if (n) | 884 | if (n) |
885 | neigh_release(n); | 885 | neigh_release(n); |
886 | 886 | ||
887 | if (NEIGH_CB(skb)->flags & LOCALLY_ENQUEUED || | 887 | if (NEIGH_CB(skb)->flags & LOCALLY_ENQUEUED || |
888 | skb->pkt_type == PACKET_HOST || | 888 | skb->pkt_type == PACKET_HOST || |
889 | in_dev->arp_parms->proxy_delay == 0) { | 889 | in_dev->arp_parms->proxy_delay == 0) { |
890 | arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,sha,dev->dev_addr,sha); | 890 | arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,sha,dev->dev_addr,sha); |
891 | } else { | 891 | } else { |
892 | pneigh_enqueue(&arp_tbl, in_dev->arp_parms, skb); | 892 | pneigh_enqueue(&arp_tbl, in_dev->arp_parms, skb); |
893 | in_dev_put(in_dev); | 893 | in_dev_put(in_dev); |
894 | return 0; | 894 | return 0; |
895 | } | 895 | } |
896 | goto out; | 896 | goto out; |
897 | } | 897 | } |
898 | } | 898 | } |
899 | } | 899 | } |
900 | 900 | ||
901 | /* Update our ARP tables */ | 901 | /* Update our ARP tables */ |
902 | 902 | ||
903 | n = __neigh_lookup(&arp_tbl, &sip, dev, 0); | 903 | n = __neigh_lookup(&arp_tbl, &sip, dev, 0); |
904 | 904 | ||
905 | if (IPV4_DEVCONF_ALL(dev_net(dev), ARP_ACCEPT)) { | 905 | if (IPV4_DEVCONF_ALL(dev_net(dev), ARP_ACCEPT)) { |
906 | /* Unsolicited ARP is not accepted by default. | 906 | /* Unsolicited ARP is not accepted by default. |
907 | It is possible, that this option should be enabled for some | 907 | It is possible, that this option should be enabled for some |
908 | devices (strip is candidate) | 908 | devices (strip is candidate) |
909 | */ | 909 | */ |
910 | if (n == NULL && | 910 | if (n == NULL && |
911 | (arp->ar_op == htons(ARPOP_REPLY) || | 911 | (arp->ar_op == htons(ARPOP_REPLY) || |
912 | (arp->ar_op == htons(ARPOP_REQUEST) && tip == sip)) && | 912 | (arp->ar_op == htons(ARPOP_REQUEST) && tip == sip)) && |
913 | inet_addr_type(net, sip) == RTN_UNICAST) | 913 | inet_addr_type(net, sip) == RTN_UNICAST) |
914 | n = __neigh_lookup(&arp_tbl, &sip, dev, 1); | 914 | n = __neigh_lookup(&arp_tbl, &sip, dev, 1); |
915 | } | 915 | } |
916 | 916 | ||
917 | if (n) { | 917 | if (n) { |
918 | int state = NUD_REACHABLE; | 918 | int state = NUD_REACHABLE; |
919 | int override; | 919 | int override; |
920 | 920 | ||
921 | /* If several different ARP replies follows back-to-back, | 921 | /* If several different ARP replies follows back-to-back, |
922 | use the FIRST one. It is possible, if several proxy | 922 | use the FIRST one. It is possible, if several proxy |
923 | agents are active. Taking the first reply prevents | 923 | agents are active. Taking the first reply prevents |
924 | arp trashing and chooses the fastest router. | 924 | arp trashing and chooses the fastest router. |
925 | */ | 925 | */ |
926 | override = time_after(jiffies, n->updated + n->parms->locktime); | 926 | override = time_after(jiffies, n->updated + n->parms->locktime); |
927 | 927 | ||
928 | /* Broadcast replies and request packets | 928 | /* Broadcast replies and request packets |
929 | do not assert neighbour reachability. | 929 | do not assert neighbour reachability. |
930 | */ | 930 | */ |
931 | if (arp->ar_op != htons(ARPOP_REPLY) || | 931 | if (arp->ar_op != htons(ARPOP_REPLY) || |
932 | skb->pkt_type != PACKET_HOST) | 932 | skb->pkt_type != PACKET_HOST) |
933 | state = NUD_STALE; | 933 | state = NUD_STALE; |
934 | neigh_update(n, sha, state, override ? NEIGH_UPDATE_F_OVERRIDE : 0); | 934 | neigh_update(n, sha, state, override ? NEIGH_UPDATE_F_OVERRIDE : 0); |
935 | neigh_release(n); | 935 | neigh_release(n); |
936 | } | 936 | } |
937 | 937 | ||
938 | out: | 938 | out: |
939 | if (in_dev) | 939 | if (in_dev) |
940 | in_dev_put(in_dev); | 940 | in_dev_put(in_dev); |
941 | consume_skb(skb); | 941 | consume_skb(skb); |
942 | return 0; | 942 | return 0; |
943 | } | 943 | } |
944 | 944 | ||
945 | static void parp_redo(struct sk_buff *skb) | 945 | static void parp_redo(struct sk_buff *skb) |
946 | { | 946 | { |
947 | arp_process(skb); | 947 | arp_process(skb); |
948 | } | 948 | } |
949 | 949 | ||
950 | 950 | ||
951 | /* | 951 | /* |
952 | * Receive an arp request from the device layer. | 952 | * Receive an arp request from the device layer. |
953 | */ | 953 | */ |
954 | 954 | ||
955 | static int arp_rcv(struct sk_buff *skb, struct net_device *dev, | 955 | static int arp_rcv(struct sk_buff *skb, struct net_device *dev, |
956 | struct packet_type *pt, struct net_device *orig_dev) | 956 | struct packet_type *pt, struct net_device *orig_dev) |
957 | { | 957 | { |
958 | struct arphdr *arp; | 958 | struct arphdr *arp; |
959 | 959 | ||
960 | /* ARP header, plus 2 device addresses, plus 2 IP addresses. */ | 960 | /* ARP header, plus 2 device addresses, plus 2 IP addresses. */ |
961 | if (!pskb_may_pull(skb, arp_hdr_len(dev))) | 961 | if (!pskb_may_pull(skb, arp_hdr_len(dev))) |
962 | goto freeskb; | 962 | goto freeskb; |
963 | 963 | ||
964 | arp = arp_hdr(skb); | 964 | arp = arp_hdr(skb); |
965 | if (arp->ar_hln != dev->addr_len || | 965 | if (arp->ar_hln != dev->addr_len || |
966 | dev->flags & IFF_NOARP || | 966 | dev->flags & IFF_NOARP || |
967 | skb->pkt_type == PACKET_OTHERHOST || | 967 | skb->pkt_type == PACKET_OTHERHOST || |
968 | skb->pkt_type == PACKET_LOOPBACK || | 968 | skb->pkt_type == PACKET_LOOPBACK || |
969 | arp->ar_pln != 4) | 969 | arp->ar_pln != 4) |
970 | goto freeskb; | 970 | goto freeskb; |
971 | 971 | ||
972 | if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) | 972 | if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) |
973 | goto out_of_mem; | 973 | goto out_of_mem; |
974 | 974 | ||
975 | memset(NEIGH_CB(skb), 0, sizeof(struct neighbour_cb)); | 975 | memset(NEIGH_CB(skb), 0, sizeof(struct neighbour_cb)); |
976 | 976 | ||
977 | return NF_HOOK(NFPROTO_ARP, NF_ARP_IN, skb, dev, NULL, arp_process); | 977 | return NF_HOOK(NFPROTO_ARP, NF_ARP_IN, skb, dev, NULL, arp_process); |
978 | 978 | ||
979 | freeskb: | 979 | freeskb: |
980 | kfree_skb(skb); | 980 | kfree_skb(skb); |
981 | out_of_mem: | 981 | out_of_mem: |
982 | return 0; | 982 | return 0; |
983 | } | 983 | } |
984 | 984 | ||
985 | /* | 985 | /* |
986 | * User level interface (ioctl) | 986 | * User level interface (ioctl) |
987 | */ | 987 | */ |
988 | 988 | ||
989 | /* | 989 | /* |
990 | * Set (create) an ARP cache entry. | 990 | * Set (create) an ARP cache entry. |
991 | */ | 991 | */ |
992 | 992 | ||
993 | static int arp_req_set_proxy(struct net *net, struct net_device *dev, int on) | 993 | static int arp_req_set_proxy(struct net *net, struct net_device *dev, int on) |
994 | { | 994 | { |
995 | if (dev == NULL) { | 995 | if (dev == NULL) { |
996 | IPV4_DEVCONF_ALL(net, PROXY_ARP) = on; | 996 | IPV4_DEVCONF_ALL(net, PROXY_ARP) = on; |
997 | return 0; | 997 | return 0; |
998 | } | 998 | } |
999 | if (__in_dev_get_rtnl(dev)) { | 999 | if (__in_dev_get_rtnl(dev)) { |
1000 | IN_DEV_CONF_SET(__in_dev_get_rtnl(dev), PROXY_ARP, on); | 1000 | IN_DEV_CONF_SET(__in_dev_get_rtnl(dev), PROXY_ARP, on); |
1001 | return 0; | 1001 | return 0; |
1002 | } | 1002 | } |
1003 | return -ENXIO; | 1003 | return -ENXIO; |
1004 | } | 1004 | } |
1005 | 1005 | ||
1006 | static int arp_req_set_public(struct net *net, struct arpreq *r, | 1006 | static int arp_req_set_public(struct net *net, struct arpreq *r, |
1007 | struct net_device *dev) | 1007 | struct net_device *dev) |
1008 | { | 1008 | { |
1009 | __be32 ip = ((struct sockaddr_in *)&r->arp_pa)->sin_addr.s_addr; | 1009 | __be32 ip = ((struct sockaddr_in *)&r->arp_pa)->sin_addr.s_addr; |
1010 | __be32 mask = ((struct sockaddr_in *)&r->arp_netmask)->sin_addr.s_addr; | 1010 | __be32 mask = ((struct sockaddr_in *)&r->arp_netmask)->sin_addr.s_addr; |
1011 | 1011 | ||
1012 | if (mask && mask != htonl(0xFFFFFFFF)) | 1012 | if (mask && mask != htonl(0xFFFFFFFF)) |
1013 | return -EINVAL; | 1013 | return -EINVAL; |
1014 | if (!dev && (r->arp_flags & ATF_COM)) { | 1014 | if (!dev && (r->arp_flags & ATF_COM)) { |
1015 | dev = dev_getbyhwaddr(net, r->arp_ha.sa_family, | 1015 | dev = dev_getbyhwaddr(net, r->arp_ha.sa_family, |
1016 | r->arp_ha.sa_data); | 1016 | r->arp_ha.sa_data); |
1017 | if (!dev) | 1017 | if (!dev) |
1018 | return -ENODEV; | 1018 | return -ENODEV; |
1019 | } | 1019 | } |
1020 | if (mask) { | 1020 | if (mask) { |
1021 | if (pneigh_lookup(&arp_tbl, net, &ip, dev, 1) == NULL) | 1021 | if (pneigh_lookup(&arp_tbl, net, &ip, dev, 1) == NULL) |
1022 | return -ENOBUFS; | 1022 | return -ENOBUFS; |
1023 | return 0; | 1023 | return 0; |
1024 | } | 1024 | } |
1025 | 1025 | ||
1026 | return arp_req_set_proxy(net, dev, 1); | 1026 | return arp_req_set_proxy(net, dev, 1); |
1027 | } | 1027 | } |
1028 | 1028 | ||
1029 | static int arp_req_set(struct net *net, struct arpreq *r, | 1029 | static int arp_req_set(struct net *net, struct arpreq *r, |
1030 | struct net_device * dev) | 1030 | struct net_device * dev) |
1031 | { | 1031 | { |
1032 | __be32 ip; | 1032 | __be32 ip; |
1033 | struct neighbour *neigh; | 1033 | struct neighbour *neigh; |
1034 | int err; | 1034 | int err; |
1035 | 1035 | ||
1036 | if (r->arp_flags & ATF_PUBL) | 1036 | if (r->arp_flags & ATF_PUBL) |
1037 | return arp_req_set_public(net, r, dev); | 1037 | return arp_req_set_public(net, r, dev); |
1038 | 1038 | ||
1039 | ip = ((struct sockaddr_in *)&r->arp_pa)->sin_addr.s_addr; | 1039 | ip = ((struct sockaddr_in *)&r->arp_pa)->sin_addr.s_addr; |
1040 | if (r->arp_flags & ATF_PERM) | 1040 | if (r->arp_flags & ATF_PERM) |
1041 | r->arp_flags |= ATF_COM; | 1041 | r->arp_flags |= ATF_COM; |
1042 | if (dev == NULL) { | 1042 | if (dev == NULL) { |
1043 | struct flowi fl = { .nl_u = { .ip4_u = { .daddr = ip, | 1043 | struct flowi fl = { .nl_u = { .ip4_u = { .daddr = ip, |
1044 | .tos = RTO_ONLINK } } }; | 1044 | .tos = RTO_ONLINK } } }; |
1045 | struct rtable * rt; | 1045 | struct rtable * rt; |
1046 | if ((err = ip_route_output_key(net, &rt, &fl)) != 0) | 1046 | if ((err = ip_route_output_key(net, &rt, &fl)) != 0) |
1047 | return err; | 1047 | return err; |
1048 | dev = rt->u.dst.dev; | 1048 | dev = rt->u.dst.dev; |
1049 | ip_rt_put(rt); | 1049 | ip_rt_put(rt); |
1050 | if (!dev) | 1050 | if (!dev) |
1051 | return -EINVAL; | 1051 | return -EINVAL; |
1052 | } | 1052 | } |
1053 | switch (dev->type) { | 1053 | switch (dev->type) { |
1054 | #if defined(CONFIG_FDDI) || defined(CONFIG_FDDI_MODULE) | 1054 | #if defined(CONFIG_FDDI) || defined(CONFIG_FDDI_MODULE) |
1055 | case ARPHRD_FDDI: | 1055 | case ARPHRD_FDDI: |
1056 | /* | 1056 | /* |
1057 | * According to RFC 1390, FDDI devices should accept ARP | 1057 | * According to RFC 1390, FDDI devices should accept ARP |
1058 | * hardware types of 1 (Ethernet). However, to be more | 1058 | * hardware types of 1 (Ethernet). However, to be more |
1059 | * robust, we'll accept hardware types of either 1 (Ethernet) | 1059 | * robust, we'll accept hardware types of either 1 (Ethernet) |
1060 | * or 6 (IEEE 802.2). | 1060 | * or 6 (IEEE 802.2). |
1061 | */ | 1061 | */ |
1062 | if (r->arp_ha.sa_family != ARPHRD_FDDI && | 1062 | if (r->arp_ha.sa_family != ARPHRD_FDDI && |
1063 | r->arp_ha.sa_family != ARPHRD_ETHER && | 1063 | r->arp_ha.sa_family != ARPHRD_ETHER && |
1064 | r->arp_ha.sa_family != ARPHRD_IEEE802) | 1064 | r->arp_ha.sa_family != ARPHRD_IEEE802) |
1065 | return -EINVAL; | 1065 | return -EINVAL; |
1066 | break; | 1066 | break; |
1067 | #endif | 1067 | #endif |
1068 | default: | 1068 | default: |
1069 | if (r->arp_ha.sa_family != dev->type) | 1069 | if (r->arp_ha.sa_family != dev->type) |
1070 | return -EINVAL; | 1070 | return -EINVAL; |
1071 | break; | 1071 | break; |
1072 | } | 1072 | } |
1073 | 1073 | ||
1074 | neigh = __neigh_lookup_errno(&arp_tbl, &ip, dev); | 1074 | neigh = __neigh_lookup_errno(&arp_tbl, &ip, dev); |
1075 | err = PTR_ERR(neigh); | 1075 | err = PTR_ERR(neigh); |
1076 | if (!IS_ERR(neigh)) { | 1076 | if (!IS_ERR(neigh)) { |
1077 | unsigned state = NUD_STALE; | 1077 | unsigned state = NUD_STALE; |
1078 | if (r->arp_flags & ATF_PERM) | 1078 | if (r->arp_flags & ATF_PERM) |
1079 | state = NUD_PERMANENT; | 1079 | state = NUD_PERMANENT; |
1080 | err = neigh_update(neigh, (r->arp_flags&ATF_COM) ? | 1080 | err = neigh_update(neigh, (r->arp_flags&ATF_COM) ? |
1081 | r->arp_ha.sa_data : NULL, state, | 1081 | r->arp_ha.sa_data : NULL, state, |
1082 | NEIGH_UPDATE_F_OVERRIDE| | 1082 | NEIGH_UPDATE_F_OVERRIDE| |
1083 | NEIGH_UPDATE_F_ADMIN); | 1083 | NEIGH_UPDATE_F_ADMIN); |
1084 | neigh_release(neigh); | 1084 | neigh_release(neigh); |
1085 | } | 1085 | } |
1086 | return err; | 1086 | return err; |
1087 | } | 1087 | } |
1088 | 1088 | ||
1089 | static unsigned arp_state_to_flags(struct neighbour *neigh) | 1089 | static unsigned arp_state_to_flags(struct neighbour *neigh) |
1090 | { | 1090 | { |
1091 | unsigned flags = 0; | 1091 | unsigned flags = 0; |
1092 | if (neigh->nud_state&NUD_PERMANENT) | 1092 | if (neigh->nud_state&NUD_PERMANENT) |
1093 | flags = ATF_PERM|ATF_COM; | 1093 | flags = ATF_PERM|ATF_COM; |
1094 | else if (neigh->nud_state&NUD_VALID) | 1094 | else if (neigh->nud_state&NUD_VALID) |
1095 | flags = ATF_COM; | 1095 | flags = ATF_COM; |
1096 | return flags; | 1096 | return flags; |
1097 | } | 1097 | } |
1098 | 1098 | ||
1099 | /* | 1099 | /* |
1100 | * Get an ARP cache entry. | 1100 | * Get an ARP cache entry. |
1101 | */ | 1101 | */ |
1102 | 1102 | ||
1103 | static int arp_req_get(struct arpreq *r, struct net_device *dev) | 1103 | static int arp_req_get(struct arpreq *r, struct net_device *dev) |
1104 | { | 1104 | { |
1105 | __be32 ip = ((struct sockaddr_in *) &r->arp_pa)->sin_addr.s_addr; | 1105 | __be32 ip = ((struct sockaddr_in *) &r->arp_pa)->sin_addr.s_addr; |
1106 | struct neighbour *neigh; | 1106 | struct neighbour *neigh; |
1107 | int err = -ENXIO; | 1107 | int err = -ENXIO; |
1108 | 1108 | ||
1109 | neigh = neigh_lookup(&arp_tbl, &ip, dev); | 1109 | neigh = neigh_lookup(&arp_tbl, &ip, dev); |
1110 | if (neigh) { | 1110 | if (neigh) { |
1111 | read_lock_bh(&neigh->lock); | 1111 | read_lock_bh(&neigh->lock); |
1112 | memcpy(r->arp_ha.sa_data, neigh->ha, dev->addr_len); | 1112 | memcpy(r->arp_ha.sa_data, neigh->ha, dev->addr_len); |
1113 | r->arp_flags = arp_state_to_flags(neigh); | 1113 | r->arp_flags = arp_state_to_flags(neigh); |
1114 | read_unlock_bh(&neigh->lock); | 1114 | read_unlock_bh(&neigh->lock); |
1115 | r->arp_ha.sa_family = dev->type; | 1115 | r->arp_ha.sa_family = dev->type; |
1116 | strlcpy(r->arp_dev, dev->name, sizeof(r->arp_dev)); | 1116 | strlcpy(r->arp_dev, dev->name, sizeof(r->arp_dev)); |
1117 | neigh_release(neigh); | 1117 | neigh_release(neigh); |
1118 | err = 0; | 1118 | err = 0; |
1119 | } | 1119 | } |
1120 | return err; | 1120 | return err; |
1121 | } | 1121 | } |
1122 | 1122 | ||
1123 | static int arp_req_delete_public(struct net *net, struct arpreq *r, | 1123 | static int arp_req_delete_public(struct net *net, struct arpreq *r, |
1124 | struct net_device *dev) | 1124 | struct net_device *dev) |
1125 | { | 1125 | { |
1126 | __be32 ip = ((struct sockaddr_in *) &r->arp_pa)->sin_addr.s_addr; | 1126 | __be32 ip = ((struct sockaddr_in *) &r->arp_pa)->sin_addr.s_addr; |
1127 | __be32 mask = ((struct sockaddr_in *)&r->arp_netmask)->sin_addr.s_addr; | 1127 | __be32 mask = ((struct sockaddr_in *)&r->arp_netmask)->sin_addr.s_addr; |
1128 | 1128 | ||
1129 | if (mask == htonl(0xFFFFFFFF)) | 1129 | if (mask == htonl(0xFFFFFFFF)) |
1130 | return pneigh_delete(&arp_tbl, net, &ip, dev); | 1130 | return pneigh_delete(&arp_tbl, net, &ip, dev); |
1131 | 1131 | ||
1132 | if (mask) | 1132 | if (mask) |
1133 | return -EINVAL; | 1133 | return -EINVAL; |
1134 | 1134 | ||
1135 | return arp_req_set_proxy(net, dev, 0); | 1135 | return arp_req_set_proxy(net, dev, 0); |
1136 | } | 1136 | } |
1137 | 1137 | ||
1138 | static int arp_req_delete(struct net *net, struct arpreq *r, | 1138 | static int arp_req_delete(struct net *net, struct arpreq *r, |
1139 | struct net_device * dev) | 1139 | struct net_device * dev) |
1140 | { | 1140 | { |
1141 | int err; | 1141 | int err; |
1142 | __be32 ip; | 1142 | __be32 ip; |
1143 | struct neighbour *neigh; | 1143 | struct neighbour *neigh; |
1144 | 1144 | ||
1145 | if (r->arp_flags & ATF_PUBL) | 1145 | if (r->arp_flags & ATF_PUBL) |
1146 | return arp_req_delete_public(net, r, dev); | 1146 | return arp_req_delete_public(net, r, dev); |
1147 | 1147 | ||
1148 | ip = ((struct sockaddr_in *)&r->arp_pa)->sin_addr.s_addr; | 1148 | ip = ((struct sockaddr_in *)&r->arp_pa)->sin_addr.s_addr; |
1149 | if (dev == NULL) { | 1149 | if (dev == NULL) { |
1150 | struct flowi fl = { .nl_u = { .ip4_u = { .daddr = ip, | 1150 | struct flowi fl = { .nl_u = { .ip4_u = { .daddr = ip, |
1151 | .tos = RTO_ONLINK } } }; | 1151 | .tos = RTO_ONLINK } } }; |
1152 | struct rtable * rt; | 1152 | struct rtable * rt; |
1153 | if ((err = ip_route_output_key(net, &rt, &fl)) != 0) | 1153 | if ((err = ip_route_output_key(net, &rt, &fl)) != 0) |
1154 | return err; | 1154 | return err; |
1155 | dev = rt->u.dst.dev; | 1155 | dev = rt->u.dst.dev; |
1156 | ip_rt_put(rt); | 1156 | ip_rt_put(rt); |
1157 | if (!dev) | 1157 | if (!dev) |
1158 | return -EINVAL; | 1158 | return -EINVAL; |
1159 | } | 1159 | } |
1160 | err = -ENXIO; | 1160 | err = -ENXIO; |
1161 | neigh = neigh_lookup(&arp_tbl, &ip, dev); | 1161 | neigh = neigh_lookup(&arp_tbl, &ip, dev); |
1162 | if (neigh) { | 1162 | if (neigh) { |
1163 | if (neigh->nud_state&~NUD_NOARP) | 1163 | if (neigh->nud_state&~NUD_NOARP) |
1164 | err = neigh_update(neigh, NULL, NUD_FAILED, | 1164 | err = neigh_update(neigh, NULL, NUD_FAILED, |
1165 | NEIGH_UPDATE_F_OVERRIDE| | 1165 | NEIGH_UPDATE_F_OVERRIDE| |
1166 | NEIGH_UPDATE_F_ADMIN); | 1166 | NEIGH_UPDATE_F_ADMIN); |
1167 | neigh_release(neigh); | 1167 | neigh_release(neigh); |
1168 | } | 1168 | } |
1169 | return err; | 1169 | return err; |
1170 | } | 1170 | } |
1171 | 1171 | ||
1172 | /* | 1172 | /* |
1173 | * Handle an ARP layer I/O control request. | 1173 | * Handle an ARP layer I/O control request. |
1174 | */ | 1174 | */ |
1175 | 1175 | ||
1176 | int arp_ioctl(struct net *net, unsigned int cmd, void __user *arg) | 1176 | int arp_ioctl(struct net *net, unsigned int cmd, void __user *arg) |
1177 | { | 1177 | { |
1178 | int err; | 1178 | int err; |
1179 | struct arpreq r; | 1179 | struct arpreq r; |
1180 | struct net_device *dev = NULL; | 1180 | struct net_device *dev = NULL; |
1181 | 1181 | ||
1182 | switch (cmd) { | 1182 | switch (cmd) { |
1183 | case SIOCDARP: | 1183 | case SIOCDARP: |
1184 | case SIOCSARP: | 1184 | case SIOCSARP: |
1185 | if (!capable(CAP_NET_ADMIN)) | 1185 | if (!capable(CAP_NET_ADMIN)) |
1186 | return -EPERM; | 1186 | return -EPERM; |
1187 | case SIOCGARP: | 1187 | case SIOCGARP: |
1188 | err = copy_from_user(&r, arg, sizeof(struct arpreq)); | 1188 | err = copy_from_user(&r, arg, sizeof(struct arpreq)); |
1189 | if (err) | 1189 | if (err) |
1190 | return -EFAULT; | 1190 | return -EFAULT; |
1191 | break; | 1191 | break; |
1192 | default: | 1192 | default: |
1193 | return -EINVAL; | 1193 | return -EINVAL; |
1194 | } | 1194 | } |
1195 | 1195 | ||
1196 | if (r.arp_pa.sa_family != AF_INET) | 1196 | if (r.arp_pa.sa_family != AF_INET) |
1197 | return -EPFNOSUPPORT; | 1197 | return -EPFNOSUPPORT; |
1198 | 1198 | ||
1199 | if (!(r.arp_flags & ATF_PUBL) && | 1199 | if (!(r.arp_flags & ATF_PUBL) && |
1200 | (r.arp_flags & (ATF_NETMASK|ATF_DONTPUB))) | 1200 | (r.arp_flags & (ATF_NETMASK|ATF_DONTPUB))) |
1201 | return -EINVAL; | 1201 | return -EINVAL; |
1202 | if (!(r.arp_flags & ATF_NETMASK)) | 1202 | if (!(r.arp_flags & ATF_NETMASK)) |
1203 | ((struct sockaddr_in *)&r.arp_netmask)->sin_addr.s_addr = | 1203 | ((struct sockaddr_in *)&r.arp_netmask)->sin_addr.s_addr = |
1204 | htonl(0xFFFFFFFFUL); | 1204 | htonl(0xFFFFFFFFUL); |
1205 | rtnl_lock(); | 1205 | rtnl_lock(); |
1206 | if (r.arp_dev[0]) { | 1206 | if (r.arp_dev[0]) { |
1207 | err = -ENODEV; | 1207 | err = -ENODEV; |
1208 | if ((dev = __dev_get_by_name(net, r.arp_dev)) == NULL) | 1208 | if ((dev = __dev_get_by_name(net, r.arp_dev)) == NULL) |
1209 | goto out; | 1209 | goto out; |
1210 | 1210 | ||
1211 | /* Mmmm... It is wrong... ARPHRD_NETROM==0 */ | 1211 | /* Mmmm... It is wrong... ARPHRD_NETROM==0 */ |
1212 | if (!r.arp_ha.sa_family) | 1212 | if (!r.arp_ha.sa_family) |
1213 | r.arp_ha.sa_family = dev->type; | 1213 | r.arp_ha.sa_family = dev->type; |
1214 | err = -EINVAL; | 1214 | err = -EINVAL; |
1215 | if ((r.arp_flags & ATF_COM) && r.arp_ha.sa_family != dev->type) | 1215 | if ((r.arp_flags & ATF_COM) && r.arp_ha.sa_family != dev->type) |
1216 | goto out; | 1216 | goto out; |
1217 | } else if (cmd == SIOCGARP) { | 1217 | } else if (cmd == SIOCGARP) { |
1218 | err = -ENODEV; | 1218 | err = -ENODEV; |
1219 | goto out; | 1219 | goto out; |
1220 | } | 1220 | } |
1221 | 1221 | ||
1222 | switch (cmd) { | 1222 | switch (cmd) { |
1223 | case SIOCDARP: | 1223 | case SIOCDARP: |
1224 | err = arp_req_delete(net, &r, dev); | 1224 | err = arp_req_delete(net, &r, dev); |
1225 | break; | 1225 | break; |
1226 | case SIOCSARP: | 1226 | case SIOCSARP: |
1227 | err = arp_req_set(net, &r, dev); | 1227 | err = arp_req_set(net, &r, dev); |
1228 | break; | 1228 | break; |
1229 | case SIOCGARP: | 1229 | case SIOCGARP: |
1230 | err = arp_req_get(&r, dev); | 1230 | err = arp_req_get(&r, dev); |
1231 | if (!err && copy_to_user(arg, &r, sizeof(r))) | 1231 | if (!err && copy_to_user(arg, &r, sizeof(r))) |
1232 | err = -EFAULT; | 1232 | err = -EFAULT; |
1233 | break; | 1233 | break; |
1234 | } | 1234 | } |
1235 | out: | 1235 | out: |
1236 | rtnl_unlock(); | 1236 | rtnl_unlock(); |
1237 | return err; | 1237 | return err; |
1238 | } | 1238 | } |
1239 | 1239 | ||
1240 | static int arp_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) | 1240 | static int arp_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) |
1241 | { | 1241 | { |
1242 | struct net_device *dev = ptr; | 1242 | struct net_device *dev = ptr; |
1243 | 1243 | ||
1244 | switch (event) { | 1244 | switch (event) { |
1245 | case NETDEV_CHANGEADDR: | 1245 | case NETDEV_CHANGEADDR: |
1246 | neigh_changeaddr(&arp_tbl, dev); | 1246 | neigh_changeaddr(&arp_tbl, dev); |
1247 | rt_cache_flush(dev_net(dev), 0); | 1247 | rt_cache_flush(dev_net(dev), 0); |
1248 | break; | 1248 | break; |
1249 | default: | 1249 | default: |
1250 | break; | 1250 | break; |
1251 | } | 1251 | } |
1252 | 1252 | ||
1253 | return NOTIFY_DONE; | 1253 | return NOTIFY_DONE; |
1254 | } | 1254 | } |
1255 | 1255 | ||
1256 | static struct notifier_block arp_netdev_notifier = { | 1256 | static struct notifier_block arp_netdev_notifier = { |
1257 | .notifier_call = arp_netdev_event, | 1257 | .notifier_call = arp_netdev_event, |
1258 | }; | 1258 | }; |
1259 | 1259 | ||
1260 | /* Note, that it is not on notifier chain. | 1260 | /* Note, that it is not on notifier chain. |
1261 | It is necessary, that this routine was called after route cache will be | 1261 | It is necessary, that this routine was called after route cache will be |
1262 | flushed. | 1262 | flushed. |
1263 | */ | 1263 | */ |
1264 | void arp_ifdown(struct net_device *dev) | 1264 | void arp_ifdown(struct net_device *dev) |
1265 | { | 1265 | { |
1266 | neigh_ifdown(&arp_tbl, dev); | 1266 | neigh_ifdown(&arp_tbl, dev); |
1267 | } | 1267 | } |
1268 | 1268 | ||
1269 | 1269 | ||
1270 | /* | 1270 | /* |
1271 | * Called once on startup. | 1271 | * Called once on startup. |
1272 | */ | 1272 | */ |
1273 | 1273 | ||
1274 | static struct packet_type arp_packet_type __read_mostly = { | 1274 | static struct packet_type arp_packet_type __read_mostly = { |
1275 | .type = cpu_to_be16(ETH_P_ARP), | 1275 | .type = cpu_to_be16(ETH_P_ARP), |
1276 | .func = arp_rcv, | 1276 | .func = arp_rcv, |
1277 | }; | 1277 | }; |
1278 | 1278 | ||
1279 | static int arp_proc_init(void); | 1279 | static int arp_proc_init(void); |
1280 | 1280 | ||
1281 | void __init arp_init(void) | 1281 | void __init arp_init(void) |
1282 | { | 1282 | { |
1283 | neigh_table_init(&arp_tbl); | 1283 | neigh_table_init(&arp_tbl); |
1284 | 1284 | ||
1285 | dev_add_pack(&arp_packet_type); | 1285 | dev_add_pack(&arp_packet_type); |
1286 | arp_proc_init(); | 1286 | arp_proc_init(); |
1287 | #ifdef CONFIG_SYSCTL | 1287 | #ifdef CONFIG_SYSCTL |
1288 | neigh_sysctl_register(NULL, &arp_tbl.parms, "ipv4", NULL); | 1288 | neigh_sysctl_register(NULL, &arp_tbl.parms, "ipv4", NULL); |
1289 | #endif | 1289 | #endif |
1290 | register_netdevice_notifier(&arp_netdev_notifier); | 1290 | register_netdevice_notifier(&arp_netdev_notifier); |
1291 | } | 1291 | } |
1292 | 1292 | ||
1293 | #ifdef CONFIG_PROC_FS | 1293 | #ifdef CONFIG_PROC_FS |
1294 | #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) | 1294 | #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) |
1295 | 1295 | ||
1296 | /* ------------------------------------------------------------------------ */ | 1296 | /* ------------------------------------------------------------------------ */ |
1297 | /* | 1297 | /* |
1298 | * ax25 -> ASCII conversion | 1298 | * ax25 -> ASCII conversion |
1299 | */ | 1299 | */ |
1300 | static char *ax2asc2(ax25_address *a, char *buf) | 1300 | static char *ax2asc2(ax25_address *a, char *buf) |
1301 | { | 1301 | { |
1302 | char c, *s; | 1302 | char c, *s; |
1303 | int n; | 1303 | int n; |
1304 | 1304 | ||
1305 | for (n = 0, s = buf; n < 6; n++) { | 1305 | for (n = 0, s = buf; n < 6; n++) { |
1306 | c = (a->ax25_call[n] >> 1) & 0x7F; | 1306 | c = (a->ax25_call[n] >> 1) & 0x7F; |
1307 | 1307 | ||
1308 | if (c != ' ') *s++ = c; | 1308 | if (c != ' ') *s++ = c; |
1309 | } | 1309 | } |
1310 | 1310 | ||
1311 | *s++ = '-'; | 1311 | *s++ = '-'; |
1312 | 1312 | ||
1313 | if ((n = ((a->ax25_call[6] >> 1) & 0x0F)) > 9) { | 1313 | if ((n = ((a->ax25_call[6] >> 1) & 0x0F)) > 9) { |
1314 | *s++ = '1'; | 1314 | *s++ = '1'; |
1315 | n -= 10; | 1315 | n -= 10; |
1316 | } | 1316 | } |
1317 | 1317 | ||
1318 | *s++ = n + '0'; | 1318 | *s++ = n + '0'; |
1319 | *s++ = '\0'; | 1319 | *s++ = '\0'; |
1320 | 1320 | ||
1321 | if (*buf == '\0' || *buf == '-') | 1321 | if (*buf == '\0' || *buf == '-') |
1322 | return "*"; | 1322 | return "*"; |
1323 | 1323 | ||
1324 | return buf; | 1324 | return buf; |
1325 | 1325 | ||
1326 | } | 1326 | } |
1327 | #endif /* CONFIG_AX25 */ | 1327 | #endif /* CONFIG_AX25 */ |
1328 | 1328 | ||
1329 | #define HBUFFERLEN 30 | 1329 | #define HBUFFERLEN 30 |
1330 | 1330 | ||
1331 | static void arp_format_neigh_entry(struct seq_file *seq, | 1331 | static void arp_format_neigh_entry(struct seq_file *seq, |
1332 | struct neighbour *n) | 1332 | struct neighbour *n) |
1333 | { | 1333 | { |
1334 | char hbuffer[HBUFFERLEN]; | 1334 | char hbuffer[HBUFFERLEN]; |
1335 | int k, j; | 1335 | int k, j; |
1336 | char tbuf[16]; | 1336 | char tbuf[16]; |
1337 | struct net_device *dev = n->dev; | 1337 | struct net_device *dev = n->dev; |
1338 | int hatype = dev->type; | 1338 | int hatype = dev->type; |
1339 | 1339 | ||
1340 | read_lock(&n->lock); | 1340 | read_lock(&n->lock); |
1341 | /* Convert hardware address to XX:XX:XX:XX ... form. */ | 1341 | /* Convert hardware address to XX:XX:XX:XX ... form. */ |
1342 | #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) | 1342 | #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) |
1343 | if (hatype == ARPHRD_AX25 || hatype == ARPHRD_NETROM) | 1343 | if (hatype == ARPHRD_AX25 || hatype == ARPHRD_NETROM) |
1344 | ax2asc2((ax25_address *)n->ha, hbuffer); | 1344 | ax2asc2((ax25_address *)n->ha, hbuffer); |
1345 | else { | 1345 | else { |
1346 | #endif | 1346 | #endif |
1347 | for (k = 0, j = 0; k < HBUFFERLEN - 3 && j < dev->addr_len; j++) { | 1347 | for (k = 0, j = 0; k < HBUFFERLEN - 3 && j < dev->addr_len; j++) { |
1348 | hbuffer[k++] = hex_asc_hi(n->ha[j]); | 1348 | hbuffer[k++] = hex_asc_hi(n->ha[j]); |
1349 | hbuffer[k++] = hex_asc_lo(n->ha[j]); | 1349 | hbuffer[k++] = hex_asc_lo(n->ha[j]); |
1350 | hbuffer[k++] = ':'; | 1350 | hbuffer[k++] = ':'; |
1351 | } | 1351 | } |
1352 | if (k != 0) | 1352 | if (k != 0) |
1353 | --k; | 1353 | --k; |
1354 | hbuffer[k] = 0; | 1354 | hbuffer[k] = 0; |
1355 | #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) | 1355 | #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) |
1356 | } | 1356 | } |
1357 | #endif | 1357 | #endif |
1358 | sprintf(tbuf, "%pI4", n->primary_key); | 1358 | sprintf(tbuf, "%pI4", n->primary_key); |
1359 | seq_printf(seq, "%-16s 0x%-10x0x%-10x%s * %s\n", | 1359 | seq_printf(seq, "%-16s 0x%-10x0x%-10x%s * %s\n", |
1360 | tbuf, hatype, arp_state_to_flags(n), hbuffer, dev->name); | 1360 | tbuf, hatype, arp_state_to_flags(n), hbuffer, dev->name); |
1361 | read_unlock(&n->lock); | 1361 | read_unlock(&n->lock); |
1362 | } | 1362 | } |
1363 | 1363 | ||
1364 | static void arp_format_pneigh_entry(struct seq_file *seq, | 1364 | static void arp_format_pneigh_entry(struct seq_file *seq, |
1365 | struct pneigh_entry *n) | 1365 | struct pneigh_entry *n) |
1366 | { | 1366 | { |
1367 | struct net_device *dev = n->dev; | 1367 | struct net_device *dev = n->dev; |
1368 | int hatype = dev ? dev->type : 0; | 1368 | int hatype = dev ? dev->type : 0; |
1369 | char tbuf[16]; | 1369 | char tbuf[16]; |
1370 | 1370 | ||
1371 | sprintf(tbuf, "%pI4", n->key); | 1371 | sprintf(tbuf, "%pI4", n->key); |
1372 | seq_printf(seq, "%-16s 0x%-10x0x%-10x%s * %s\n", | 1372 | seq_printf(seq, "%-16s 0x%-10x0x%-10x%s * %s\n", |
1373 | tbuf, hatype, ATF_PUBL | ATF_PERM, "00:00:00:00:00:00", | 1373 | tbuf, hatype, ATF_PUBL | ATF_PERM, "00:00:00:00:00:00", |
1374 | dev ? dev->name : "*"); | 1374 | dev ? dev->name : "*"); |
1375 | } | 1375 | } |
1376 | 1376 | ||
1377 | static int arp_seq_show(struct seq_file *seq, void *v) | 1377 | static int arp_seq_show(struct seq_file *seq, void *v) |
1378 | { | 1378 | { |
1379 | if (v == SEQ_START_TOKEN) { | 1379 | if (v == SEQ_START_TOKEN) { |
1380 | seq_puts(seq, "IP address HW type Flags " | 1380 | seq_puts(seq, "IP address HW type Flags " |
1381 | "HW address Mask Device\n"); | 1381 | "HW address Mask Device\n"); |
1382 | } else { | 1382 | } else { |
1383 | struct neigh_seq_state *state = seq->private; | 1383 | struct neigh_seq_state *state = seq->private; |
1384 | 1384 | ||
1385 | if (state->flags & NEIGH_SEQ_IS_PNEIGH) | 1385 | if (state->flags & NEIGH_SEQ_IS_PNEIGH) |
1386 | arp_format_pneigh_entry(seq, v); | 1386 | arp_format_pneigh_entry(seq, v); |
1387 | else | 1387 | else |
1388 | arp_format_neigh_entry(seq, v); | 1388 | arp_format_neigh_entry(seq, v); |
1389 | } | 1389 | } |
1390 | 1390 | ||
1391 | return 0; | 1391 | return 0; |
1392 | } | 1392 | } |
1393 | 1393 | ||
1394 | static void *arp_seq_start(struct seq_file *seq, loff_t *pos) | 1394 | static void *arp_seq_start(struct seq_file *seq, loff_t *pos) |
1395 | { | 1395 | { |
1396 | /* Don't want to confuse "arp -a" w/ magic entries, | 1396 | /* Don't want to confuse "arp -a" w/ magic entries, |
1397 | * so we tell the generic iterator to skip NUD_NOARP. | 1397 | * so we tell the generic iterator to skip NUD_NOARP. |
1398 | */ | 1398 | */ |
1399 | return neigh_seq_start(seq, pos, &arp_tbl, NEIGH_SEQ_SKIP_NOARP); | 1399 | return neigh_seq_start(seq, pos, &arp_tbl, NEIGH_SEQ_SKIP_NOARP); |
1400 | } | 1400 | } |
1401 | 1401 | ||
1402 | /* ------------------------------------------------------------------------ */ | 1402 | /* ------------------------------------------------------------------------ */ |
1403 | 1403 | ||
1404 | static const struct seq_operations arp_seq_ops = { | 1404 | static const struct seq_operations arp_seq_ops = { |
1405 | .start = arp_seq_start, | 1405 | .start = arp_seq_start, |
1406 | .next = neigh_seq_next, | 1406 | .next = neigh_seq_next, |
1407 | .stop = neigh_seq_stop, | 1407 | .stop = neigh_seq_stop, |
1408 | .show = arp_seq_show, | 1408 | .show = arp_seq_show, |
1409 | }; | 1409 | }; |
1410 | 1410 | ||
1411 | static int arp_seq_open(struct inode *inode, struct file *file) | 1411 | static int arp_seq_open(struct inode *inode, struct file *file) |
1412 | { | 1412 | { |
1413 | return seq_open_net(inode, file, &arp_seq_ops, | 1413 | return seq_open_net(inode, file, &arp_seq_ops, |
1414 | sizeof(struct neigh_seq_state)); | 1414 | sizeof(struct neigh_seq_state)); |
1415 | } | 1415 | } |
1416 | 1416 | ||
1417 | static const struct file_operations arp_seq_fops = { | 1417 | static const struct file_operations arp_seq_fops = { |
1418 | .owner = THIS_MODULE, | 1418 | .owner = THIS_MODULE, |
1419 | .open = arp_seq_open, | 1419 | .open = arp_seq_open, |
1420 | .read = seq_read, | 1420 | .read = seq_read, |
1421 | .llseek = seq_lseek, | 1421 | .llseek = seq_lseek, |
1422 | .release = seq_release_net, | 1422 | .release = seq_release_net, |
1423 | }; | 1423 | }; |
1424 | 1424 | ||
1425 | 1425 | ||
1426 | static int __net_init arp_net_init(struct net *net) | 1426 | static int __net_init arp_net_init(struct net *net) |
1427 | { | 1427 | { |
1428 | if (!proc_net_fops_create(net, "arp", S_IRUGO, &arp_seq_fops)) | 1428 | if (!proc_net_fops_create(net, "arp", S_IRUGO, &arp_seq_fops)) |
1429 | return -ENOMEM; | 1429 | return -ENOMEM; |
1430 | return 0; | 1430 | return 0; |
1431 | } | 1431 | } |
1432 | 1432 | ||
1433 | static void __net_exit arp_net_exit(struct net *net) | 1433 | static void __net_exit arp_net_exit(struct net *net) |
1434 | { | 1434 | { |
1435 | proc_net_remove(net, "arp"); | 1435 | proc_net_remove(net, "arp"); |
1436 | } | 1436 | } |
1437 | 1437 | ||
1438 | static struct pernet_operations arp_net_ops = { | 1438 | static struct pernet_operations arp_net_ops = { |
1439 | .init = arp_net_init, | 1439 | .init = arp_net_init, |
1440 | .exit = arp_net_exit, | 1440 | .exit = arp_net_exit, |
1441 | }; | 1441 | }; |
1442 | 1442 | ||
1443 | static int __init arp_proc_init(void) | 1443 | static int __init arp_proc_init(void) |
1444 | { | 1444 | { |
1445 | return register_pernet_subsys(&arp_net_ops); | 1445 | return register_pernet_subsys(&arp_net_ops); |
1446 | } | 1446 | } |
1447 | 1447 | ||
1448 | #else /* CONFIG_PROC_FS */ | 1448 | #else /* CONFIG_PROC_FS */ |
1449 | 1449 | ||
1450 | static int __init arp_proc_init(void) | 1450 | static int __init arp_proc_init(void) |
1451 | { | 1451 | { |
1452 | return 0; | 1452 | return 0; |
1453 | } | 1453 | } |
1454 | 1454 | ||
1455 | #endif /* CONFIG_PROC_FS */ | 1455 | #endif /* CONFIG_PROC_FS */ |
1456 | 1456 | ||
1457 | EXPORT_SYMBOL(arp_broken_ops); | 1457 | EXPORT_SYMBOL(arp_broken_ops); |
1458 | EXPORT_SYMBOL(arp_find); | 1458 | EXPORT_SYMBOL(arp_find); |
1459 | EXPORT_SYMBOL(arp_create); | 1459 | EXPORT_SYMBOL(arp_create); |
1460 | EXPORT_SYMBOL(arp_xmit); | 1460 | EXPORT_SYMBOL(arp_xmit); |
1461 | EXPORT_SYMBOL(arp_send); | 1461 | EXPORT_SYMBOL(arp_send); |
1462 | EXPORT_SYMBOL(arp_tbl); | 1462 | EXPORT_SYMBOL(arp_tbl); |
1463 | 1463 | ||
1464 | #if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE) | 1464 | #if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE) |
1465 | EXPORT_SYMBOL(clip_tbl_hook); | 1465 | EXPORT_SYMBOL(clip_tbl_hook); |
1466 | #endif | 1466 | #endif |
1467 | 1467 |
net/ipv4/ip_input.c
1 | /* | 1 | /* |
2 | * INET An implementation of the TCP/IP protocol suite for the LINUX | 2 | * INET An implementation of the TCP/IP protocol suite for the LINUX |
3 | * operating system. INET is implemented using the BSD Socket | 3 | * operating system. INET is implemented using the BSD Socket |
4 | * interface as the means of communication with the user level. | 4 | * interface as the means of communication with the user level. |
5 | * | 5 | * |
6 | * The Internet Protocol (IP) module. | 6 | * The Internet Protocol (IP) module. |
7 | * | 7 | * |
8 | * Authors: Ross Biro | 8 | * Authors: Ross Biro |
9 | * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> | 9 | * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> |
10 | * Donald Becker, <becker@super.org> | 10 | * Donald Becker, <becker@super.org> |
11 | * Alan Cox, <alan@lxorguk.ukuu.org.uk> | 11 | * Alan Cox, <alan@lxorguk.ukuu.org.uk> |
12 | * Richard Underwood | 12 | * Richard Underwood |
13 | * Stefan Becker, <stefanb@yello.ping.de> | 13 | * Stefan Becker, <stefanb@yello.ping.de> |
14 | * Jorge Cwik, <jorge@laser.satlink.net> | 14 | * Jorge Cwik, <jorge@laser.satlink.net> |
15 | * Arnt Gulbrandsen, <agulbra@nvg.unit.no> | 15 | * Arnt Gulbrandsen, <agulbra@nvg.unit.no> |
16 | * | 16 | * |
17 | * | 17 | * |
18 | * Fixes: | 18 | * Fixes: |
19 | * Alan Cox : Commented a couple of minor bits of surplus code | 19 | * Alan Cox : Commented a couple of minor bits of surplus code |
20 | * Alan Cox : Undefining IP_FORWARD doesn't include the code | 20 | * Alan Cox : Undefining IP_FORWARD doesn't include the code |
21 | * (just stops a compiler warning). | 21 | * (just stops a compiler warning). |
22 | * Alan Cox : Frames with >=MAX_ROUTE record routes, strict routes or loose routes | 22 | * Alan Cox : Frames with >=MAX_ROUTE record routes, strict routes or loose routes |
23 | * are junked rather than corrupting things. | 23 | * are junked rather than corrupting things. |
24 | * Alan Cox : Frames to bad broadcast subnets are dumped | 24 | * Alan Cox : Frames to bad broadcast subnets are dumped |
25 | * We used to process them non broadcast and | 25 | * We used to process them non broadcast and |
26 | * boy could that cause havoc. | 26 | * boy could that cause havoc. |
27 | * Alan Cox : ip_forward sets the free flag on the | 27 | * Alan Cox : ip_forward sets the free flag on the |
28 | * new frame it queues. Still crap because | 28 | * new frame it queues. Still crap because |
29 | * it copies the frame but at least it | 29 | * it copies the frame but at least it |
30 | * doesn't eat memory too. | 30 | * doesn't eat memory too. |
31 | * Alan Cox : Generic queue code and memory fixes. | 31 | * Alan Cox : Generic queue code and memory fixes. |
32 | * Fred Van Kempen : IP fragment support (borrowed from NET2E) | 32 | * Fred Van Kempen : IP fragment support (borrowed from NET2E) |
33 | * Gerhard Koerting: Forward fragmented frames correctly. | 33 | * Gerhard Koerting: Forward fragmented frames correctly. |
34 | * Gerhard Koerting: Fixes to my fix of the above 8-). | 34 | * Gerhard Koerting: Fixes to my fix of the above 8-). |
35 | * Gerhard Koerting: IP interface addressing fix. | 35 | * Gerhard Koerting: IP interface addressing fix. |
36 | * Linus Torvalds : More robustness checks | 36 | * Linus Torvalds : More robustness checks |
37 | * Alan Cox : Even more checks: Still not as robust as it ought to be | 37 | * Alan Cox : Even more checks: Still not as robust as it ought to be |
38 | * Alan Cox : Save IP header pointer for later | 38 | * Alan Cox : Save IP header pointer for later |
39 | * Alan Cox : ip option setting | 39 | * Alan Cox : ip option setting |
40 | * Alan Cox : Use ip_tos/ip_ttl settings | 40 | * Alan Cox : Use ip_tos/ip_ttl settings |
41 | * Alan Cox : Fragmentation bogosity removed | 41 | * Alan Cox : Fragmentation bogosity removed |
42 | * (Thanks to Mark.Bush@prg.ox.ac.uk) | 42 | * (Thanks to Mark.Bush@prg.ox.ac.uk) |
43 | * Dmitry Gorodchanin : Send of a raw packet crash fix. | 43 | * Dmitry Gorodchanin : Send of a raw packet crash fix. |
44 | * Alan Cox : Silly ip bug when an overlength | 44 | * Alan Cox : Silly ip bug when an overlength |
45 | * fragment turns up. Now frees the | 45 | * fragment turns up. Now frees the |
46 | * queue. | 46 | * queue. |
47 | * Linus Torvalds/ : Memory leakage on fragmentation | 47 | * Linus Torvalds/ : Memory leakage on fragmentation |
48 | * Alan Cox : handling. | 48 | * Alan Cox : handling. |
49 | * Gerhard Koerting: Forwarding uses IP priority hints | 49 | * Gerhard Koerting: Forwarding uses IP priority hints |
50 | * Teemu Rantanen : Fragment problems. | 50 | * Teemu Rantanen : Fragment problems. |
51 | * Alan Cox : General cleanup, comments and reformat | 51 | * Alan Cox : General cleanup, comments and reformat |
52 | * Alan Cox : SNMP statistics | 52 | * Alan Cox : SNMP statistics |
53 | * Alan Cox : BSD address rule semantics. Also see | 53 | * Alan Cox : BSD address rule semantics. Also see |
54 | * UDP as there is a nasty checksum issue | 54 | * UDP as there is a nasty checksum issue |
55 | * if you do things the wrong way. | 55 | * if you do things the wrong way. |
56 | * Alan Cox : Always defrag, moved IP_FORWARD to the config.in file | 56 | * Alan Cox : Always defrag, moved IP_FORWARD to the config.in file |
57 | * Alan Cox : IP options adjust sk->priority. | 57 | * Alan Cox : IP options adjust sk->priority. |
58 | * Pedro Roque : Fix mtu/length error in ip_forward. | 58 | * Pedro Roque : Fix mtu/length error in ip_forward. |
59 | * Alan Cox : Avoid ip_chk_addr when possible. | 59 | * Alan Cox : Avoid ip_chk_addr when possible. |
60 | * Richard Underwood : IP multicasting. | 60 | * Richard Underwood : IP multicasting. |
61 | * Alan Cox : Cleaned up multicast handlers. | 61 | * Alan Cox : Cleaned up multicast handlers. |
62 | * Alan Cox : RAW sockets demultiplex in the BSD style. | 62 | * Alan Cox : RAW sockets demultiplex in the BSD style. |
63 | * Gunther Mayer : Fix the SNMP reporting typo | 63 | * Gunther Mayer : Fix the SNMP reporting typo |
64 | * Alan Cox : Always in group 224.0.0.1 | 64 | * Alan Cox : Always in group 224.0.0.1 |
65 | * Pauline Middelink : Fast ip_checksum update when forwarding | 65 | * Pauline Middelink : Fast ip_checksum update when forwarding |
66 | * Masquerading support. | 66 | * Masquerading support. |
67 | * Alan Cox : Multicast loopback error for 224.0.0.1 | 67 | * Alan Cox : Multicast loopback error for 224.0.0.1 |
68 | * Alan Cox : IP_MULTICAST_LOOP option. | 68 | * Alan Cox : IP_MULTICAST_LOOP option. |
69 | * Alan Cox : Use notifiers. | 69 | * Alan Cox : Use notifiers. |
70 | * Bjorn Ekwall : Removed ip_csum (from slhc.c too) | 70 | * Bjorn Ekwall : Removed ip_csum (from slhc.c too) |
71 | * Bjorn Ekwall : Moved ip_fast_csum to ip.h (inline!) | 71 | * Bjorn Ekwall : Moved ip_fast_csum to ip.h (inline!) |
72 | * Stefan Becker : Send out ICMP HOST REDIRECT | 72 | * Stefan Becker : Send out ICMP HOST REDIRECT |
73 | * Arnt Gulbrandsen : ip_build_xmit | 73 | * Arnt Gulbrandsen : ip_build_xmit |
74 | * Alan Cox : Per socket routing cache | 74 | * Alan Cox : Per socket routing cache |
75 | * Alan Cox : Fixed routing cache, added header cache. | 75 | * Alan Cox : Fixed routing cache, added header cache. |
76 | * Alan Cox : Loopback didn't work right in original ip_build_xmit - fixed it. | 76 | * Alan Cox : Loopback didn't work right in original ip_build_xmit - fixed it. |
77 | * Alan Cox : Only send ICMP_REDIRECT if src/dest are the same net. | 77 | * Alan Cox : Only send ICMP_REDIRECT if src/dest are the same net. |
78 | * Alan Cox : Incoming IP option handling. | 78 | * Alan Cox : Incoming IP option handling. |
79 | * Alan Cox : Set saddr on raw output frames as per BSD. | 79 | * Alan Cox : Set saddr on raw output frames as per BSD. |
80 | * Alan Cox : Stopped broadcast source route explosions. | 80 | * Alan Cox : Stopped broadcast source route explosions. |
81 | * Alan Cox : Can disable source routing | 81 | * Alan Cox : Can disable source routing |
82 | * Takeshi Sone : Masquerading didn't work. | 82 | * Takeshi Sone : Masquerading didn't work. |
83 | * Dave Bonn,Alan Cox : Faster IP forwarding whenever possible. | 83 | * Dave Bonn,Alan Cox : Faster IP forwarding whenever possible. |
84 | * Alan Cox : Memory leaks, tramples, misc debugging. | 84 | * Alan Cox : Memory leaks, tramples, misc debugging. |
85 | * Alan Cox : Fixed multicast (by popular demand 8)) | 85 | * Alan Cox : Fixed multicast (by popular demand 8)) |
86 | * Alan Cox : Fixed forwarding (by even more popular demand 8)) | 86 | * Alan Cox : Fixed forwarding (by even more popular demand 8)) |
87 | * Alan Cox : Fixed SNMP statistics [I think] | 87 | * Alan Cox : Fixed SNMP statistics [I think] |
88 | * Gerhard Koerting : IP fragmentation forwarding fix | 88 | * Gerhard Koerting : IP fragmentation forwarding fix |
89 | * Alan Cox : Device lock against page fault. | 89 | * Alan Cox : Device lock against page fault. |
90 | * Alan Cox : IP_HDRINCL facility. | 90 | * Alan Cox : IP_HDRINCL facility. |
91 | * Werner Almesberger : Zero fragment bug | 91 | * Werner Almesberger : Zero fragment bug |
92 | * Alan Cox : RAW IP frame length bug | 92 | * Alan Cox : RAW IP frame length bug |
93 | * Alan Cox : Outgoing firewall on build_xmit | 93 | * Alan Cox : Outgoing firewall on build_xmit |
94 | * A.N.Kuznetsov : IP_OPTIONS support throughout the kernel | 94 | * A.N.Kuznetsov : IP_OPTIONS support throughout the kernel |
95 | * Alan Cox : Multicast routing hooks | 95 | * Alan Cox : Multicast routing hooks |
96 | * Jos Vos : Do accounting *before* call_in_firewall | 96 | * Jos Vos : Do accounting *before* call_in_firewall |
97 | * Willy Konynenberg : Transparent proxying support | 97 | * Willy Konynenberg : Transparent proxying support |
98 | * | 98 | * |
99 | * | 99 | * |
100 | * | 100 | * |
101 | * To Fix: | 101 | * To Fix: |
102 | * IP fragmentation wants rewriting cleanly. The RFC815 algorithm is much more efficient | 102 | * IP fragmentation wants rewriting cleanly. The RFC815 algorithm is much more efficient |
103 | * and could be made very efficient with the addition of some virtual memory hacks to permit | 103 | * and could be made very efficient with the addition of some virtual memory hacks to permit |
104 | * the allocation of a buffer that can then be 'grown' by twiddling page tables. | 104 | * the allocation of a buffer that can then be 'grown' by twiddling page tables. |
105 | * Output fragmentation wants updating along with the buffer management to use a single | 105 | * Output fragmentation wants updating along with the buffer management to use a single |
106 | * interleaved copy algorithm so that fragmenting has a one copy overhead. Actual packet | 106 | * interleaved copy algorithm so that fragmenting has a one copy overhead. Actual packet |
107 | * output should probably do its own fragmentation at the UDP/RAW layer. TCP shouldn't cause | 107 | * output should probably do its own fragmentation at the UDP/RAW layer. TCP shouldn't cause |
108 | * fragmentation anyway. | 108 | * fragmentation anyway. |
109 | * | 109 | * |
110 | * This program is free software; you can redistribute it and/or | 110 | * This program is free software; you can redistribute it and/or |
111 | * modify it under the terms of the GNU General Public License | 111 | * modify it under the terms of the GNU General Public License |
112 | * as published by the Free Software Foundation; either version | 112 | * as published by the Free Software Foundation; either version |
113 | * 2 of the License, or (at your option) any later version. | 113 | * 2 of the License, or (at your option) any later version. |
114 | */ | 114 | */ |
115 | 115 | ||
116 | #include <asm/system.h> | 116 | #include <asm/system.h> |
117 | #include <linux/module.h> | 117 | #include <linux/module.h> |
118 | #include <linux/types.h> | 118 | #include <linux/types.h> |
119 | #include <linux/kernel.h> | 119 | #include <linux/kernel.h> |
120 | #include <linux/string.h> | 120 | #include <linux/string.h> |
121 | #include <linux/errno.h> | 121 | #include <linux/errno.h> |
122 | #include <linux/slab.h> | 122 | #include <linux/slab.h> |
123 | 123 | ||
124 | #include <linux/net.h> | 124 | #include <linux/net.h> |
125 | #include <linux/socket.h> | 125 | #include <linux/socket.h> |
126 | #include <linux/sockios.h> | 126 | #include <linux/sockios.h> |
127 | #include <linux/in.h> | 127 | #include <linux/in.h> |
128 | #include <linux/inet.h> | 128 | #include <linux/inet.h> |
129 | #include <linux/inetdevice.h> | 129 | #include <linux/inetdevice.h> |
130 | #include <linux/netdevice.h> | 130 | #include <linux/netdevice.h> |
131 | #include <linux/etherdevice.h> | 131 | #include <linux/etherdevice.h> |
132 | 132 | ||
133 | #include <net/snmp.h> | 133 | #include <net/snmp.h> |
134 | #include <net/ip.h> | 134 | #include <net/ip.h> |
135 | #include <net/protocol.h> | 135 | #include <net/protocol.h> |
136 | #include <net/route.h> | 136 | #include <net/route.h> |
137 | #include <linux/skbuff.h> | 137 | #include <linux/skbuff.h> |
138 | #include <net/sock.h> | 138 | #include <net/sock.h> |
139 | #include <net/arp.h> | 139 | #include <net/arp.h> |
140 | #include <net/icmp.h> | 140 | #include <net/icmp.h> |
141 | #include <net/raw.h> | 141 | #include <net/raw.h> |
142 | #include <net/checksum.h> | 142 | #include <net/checksum.h> |
143 | #include <linux/netfilter_ipv4.h> | 143 | #include <linux/netfilter_ipv4.h> |
144 | #include <net/xfrm.h> | 144 | #include <net/xfrm.h> |
145 | #include <linux/mroute.h> | 145 | #include <linux/mroute.h> |
146 | #include <linux/netlink.h> | 146 | #include <linux/netlink.h> |
147 | 147 | ||
148 | /* | 148 | /* |
149 | * Process Router Attention IP option | 149 | * Process Router Attention IP option |
150 | */ | 150 | */ |
151 | int ip_call_ra_chain(struct sk_buff *skb) | 151 | int ip_call_ra_chain(struct sk_buff *skb) |
152 | { | 152 | { |
153 | struct ip_ra_chain *ra; | 153 | struct ip_ra_chain *ra; |
154 | u8 protocol = ip_hdr(skb)->protocol; | 154 | u8 protocol = ip_hdr(skb)->protocol; |
155 | struct sock *last = NULL; | 155 | struct sock *last = NULL; |
156 | struct net_device *dev = skb->dev; | 156 | struct net_device *dev = skb->dev; |
157 | 157 | ||
158 | read_lock(&ip_ra_lock); | 158 | read_lock(&ip_ra_lock); |
159 | for (ra = ip_ra_chain; ra; ra = ra->next) { | 159 | for (ra = ip_ra_chain; ra; ra = ra->next) { |
160 | struct sock *sk = ra->sk; | 160 | struct sock *sk = ra->sk; |
161 | 161 | ||
162 | /* If socket is bound to an interface, only report | 162 | /* If socket is bound to an interface, only report |
163 | * the packet if it came from that interface. | 163 | * the packet if it came from that interface. |
164 | */ | 164 | */ |
165 | if (sk && inet_sk(sk)->inet_num == protocol && | 165 | if (sk && inet_sk(sk)->inet_num == protocol && |
166 | (!sk->sk_bound_dev_if || | 166 | (!sk->sk_bound_dev_if || |
167 | sk->sk_bound_dev_if == dev->ifindex) && | 167 | sk->sk_bound_dev_if == dev->ifindex) && |
168 | net_eq(sock_net(sk), dev_net(dev))) { | 168 | net_eq(sock_net(sk), dev_net(dev))) { |
169 | if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) { | 169 | if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) { |
170 | if (ip_defrag(skb, IP_DEFRAG_CALL_RA_CHAIN)) { | 170 | if (ip_defrag(skb, IP_DEFRAG_CALL_RA_CHAIN)) { |
171 | read_unlock(&ip_ra_lock); | 171 | read_unlock(&ip_ra_lock); |
172 | return 1; | 172 | return 1; |
173 | } | 173 | } |
174 | } | 174 | } |
175 | if (last) { | 175 | if (last) { |
176 | struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); | 176 | struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); |
177 | if (skb2) | 177 | if (skb2) |
178 | raw_rcv(last, skb2); | 178 | raw_rcv(last, skb2); |
179 | } | 179 | } |
180 | last = sk; | 180 | last = sk; |
181 | } | 181 | } |
182 | } | 182 | } |
183 | 183 | ||
184 | if (last) { | 184 | if (last) { |
185 | raw_rcv(last, skb); | 185 | raw_rcv(last, skb); |
186 | read_unlock(&ip_ra_lock); | 186 | read_unlock(&ip_ra_lock); |
187 | return 1; | 187 | return 1; |
188 | } | 188 | } |
189 | read_unlock(&ip_ra_lock); | 189 | read_unlock(&ip_ra_lock); |
190 | return 0; | 190 | return 0; |
191 | } | 191 | } |
192 | 192 | ||
193 | static int ip_local_deliver_finish(struct sk_buff *skb) | 193 | static int ip_local_deliver_finish(struct sk_buff *skb) |
194 | { | 194 | { |
195 | struct net *net = dev_net(skb->dev); | 195 | struct net *net = dev_net(skb->dev); |
196 | 196 | ||
197 | __skb_pull(skb, ip_hdrlen(skb)); | 197 | __skb_pull(skb, ip_hdrlen(skb)); |
198 | 198 | ||
199 | /* Point into the IP datagram, just past the header. */ | 199 | /* Point into the IP datagram, just past the header. */ |
200 | skb_reset_transport_header(skb); | 200 | skb_reset_transport_header(skb); |
201 | 201 | ||
202 | rcu_read_lock(); | 202 | rcu_read_lock(); |
203 | { | 203 | { |
204 | int protocol = ip_hdr(skb)->protocol; | 204 | int protocol = ip_hdr(skb)->protocol; |
205 | int hash, raw; | 205 | int hash, raw; |
206 | const struct net_protocol *ipprot; | 206 | const struct net_protocol *ipprot; |
207 | 207 | ||
208 | resubmit: | 208 | resubmit: |
209 | raw = raw_local_deliver(skb, protocol); | 209 | raw = raw_local_deliver(skb, protocol); |
210 | 210 | ||
211 | hash = protocol & (MAX_INET_PROTOS - 1); | 211 | hash = protocol & (MAX_INET_PROTOS - 1); |
212 | ipprot = rcu_dereference(inet_protos[hash]); | 212 | ipprot = rcu_dereference(inet_protos[hash]); |
213 | if (ipprot != NULL) { | 213 | if (ipprot != NULL) { |
214 | int ret; | 214 | int ret; |
215 | 215 | ||
216 | if (!net_eq(net, &init_net) && !ipprot->netns_ok) { | 216 | if (!net_eq(net, &init_net) && !ipprot->netns_ok) { |
217 | if (net_ratelimit()) | 217 | if (net_ratelimit()) |
218 | printk("%s: proto %d isn't netns-ready\n", | 218 | printk("%s: proto %d isn't netns-ready\n", |
219 | __func__, protocol); | 219 | __func__, protocol); |
220 | kfree_skb(skb); | 220 | kfree_skb(skb); |
221 | goto out; | 221 | goto out; |
222 | } | 222 | } |
223 | 223 | ||
224 | if (!ipprot->no_policy) { | 224 | if (!ipprot->no_policy) { |
225 | if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) { | 225 | if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) { |
226 | kfree_skb(skb); | 226 | kfree_skb(skb); |
227 | goto out; | 227 | goto out; |
228 | } | 228 | } |
229 | nf_reset(skb); | 229 | nf_reset(skb); |
230 | } | 230 | } |
231 | ret = ipprot->handler(skb); | 231 | ret = ipprot->handler(skb); |
232 | if (ret < 0) { | 232 | if (ret < 0) { |
233 | protocol = -ret; | 233 | protocol = -ret; |
234 | goto resubmit; | 234 | goto resubmit; |
235 | } | 235 | } |
236 | IP_INC_STATS_BH(net, IPSTATS_MIB_INDELIVERS); | 236 | IP_INC_STATS_BH(net, IPSTATS_MIB_INDELIVERS); |
237 | } else { | 237 | } else { |
238 | if (!raw) { | 238 | if (!raw) { |
239 | if (xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) { | 239 | if (xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) { |
240 | IP_INC_STATS_BH(net, IPSTATS_MIB_INUNKNOWNPROTOS); | 240 | IP_INC_STATS_BH(net, IPSTATS_MIB_INUNKNOWNPROTOS); |
241 | icmp_send(skb, ICMP_DEST_UNREACH, | 241 | icmp_send(skb, ICMP_DEST_UNREACH, |
242 | ICMP_PROT_UNREACH, 0); | 242 | ICMP_PROT_UNREACH, 0); |
243 | } | 243 | } |
244 | } else | 244 | } else |
245 | IP_INC_STATS_BH(net, IPSTATS_MIB_INDELIVERS); | 245 | IP_INC_STATS_BH(net, IPSTATS_MIB_INDELIVERS); |
246 | kfree_skb(skb); | 246 | kfree_skb(skb); |
247 | } | 247 | } |
248 | } | 248 | } |
249 | out: | 249 | out: |
250 | rcu_read_unlock(); | 250 | rcu_read_unlock(); |
251 | 251 | ||
252 | return 0; | 252 | return 0; |
253 | } | 253 | } |
254 | 254 | ||
255 | /* | 255 | /* |
256 | * Deliver IP Packets to the higher protocol layers. | 256 | * Deliver IP Packets to the higher protocol layers. |
257 | */ | 257 | */ |
258 | int ip_local_deliver(struct sk_buff *skb) | 258 | int ip_local_deliver(struct sk_buff *skb) |
259 | { | 259 | { |
260 | /* | 260 | /* |
261 | * Reassemble IP fragments. | 261 | * Reassemble IP fragments. |
262 | */ | 262 | */ |
263 | 263 | ||
264 | if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) { | 264 | if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) { |
265 | if (ip_defrag(skb, IP_DEFRAG_LOCAL_DELIVER)) | 265 | if (ip_defrag(skb, IP_DEFRAG_LOCAL_DELIVER)) |
266 | return 0; | 266 | return 0; |
267 | } | 267 | } |
268 | 268 | ||
269 | return NF_HOOK(NFPROTO_IPV4, NF_INET_LOCAL_IN, skb, skb->dev, NULL, | 269 | return NF_HOOK(NFPROTO_IPV4, NF_INET_LOCAL_IN, skb, skb->dev, NULL, |
270 | ip_local_deliver_finish); | 270 | ip_local_deliver_finish); |
271 | } | 271 | } |
272 | 272 | ||
273 | static inline int ip_rcv_options(struct sk_buff *skb) | 273 | static inline int ip_rcv_options(struct sk_buff *skb) |
274 | { | 274 | { |
275 | struct ip_options *opt; | 275 | struct ip_options *opt; |
276 | struct iphdr *iph; | 276 | struct iphdr *iph; |
277 | struct net_device *dev = skb->dev; | 277 | struct net_device *dev = skb->dev; |
278 | 278 | ||
279 | /* It looks as overkill, because not all | 279 | /* It looks as overkill, because not all |
280 | IP options require packet mangling. | 280 | IP options require packet mangling. |
281 | But it is the easiest for now, especially taking | 281 | But it is the easiest for now, especially taking |
282 | into account that combination of IP options | 282 | into account that combination of IP options |
283 | and running sniffer is extremely rare condition. | 283 | and running sniffer is extremely rare condition. |
284 | --ANK (980813) | 284 | --ANK (980813) |
285 | */ | 285 | */ |
286 | if (skb_cow(skb, skb_headroom(skb))) { | 286 | if (skb_cow(skb, skb_headroom(skb))) { |
287 | IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INDISCARDS); | 287 | IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INDISCARDS); |
288 | goto drop; | 288 | goto drop; |
289 | } | 289 | } |
290 | 290 | ||
291 | iph = ip_hdr(skb); | 291 | iph = ip_hdr(skb); |
292 | opt = &(IPCB(skb)->opt); | 292 | opt = &(IPCB(skb)->opt); |
293 | opt->optlen = iph->ihl*4 - sizeof(struct iphdr); | 293 | opt->optlen = iph->ihl*4 - sizeof(struct iphdr); |
294 | 294 | ||
295 | if (ip_options_compile(dev_net(dev), opt, skb)) { | 295 | if (ip_options_compile(dev_net(dev), opt, skb)) { |
296 | IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INHDRERRORS); | 296 | IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INHDRERRORS); |
297 | goto drop; | 297 | goto drop; |
298 | } | 298 | } |
299 | 299 | ||
300 | if (unlikely(opt->srr)) { | 300 | if (unlikely(opt->srr)) { |
301 | struct in_device *in_dev = in_dev_get(dev); | 301 | struct in_device *in_dev = in_dev_get(dev); |
302 | if (in_dev) { | 302 | if (in_dev) { |
303 | if (!IN_DEV_SOURCE_ROUTE(in_dev)) { | 303 | if (!IN_DEV_SOURCE_ROUTE(in_dev)) { |
304 | if (IN_DEV_LOG_MARTIANS(in_dev) && | 304 | if (IN_DEV_LOG_MARTIANS(in_dev) && |
305 | net_ratelimit()) | 305 | net_ratelimit()) |
306 | printk(KERN_INFO "source route option %pI4 -> %pI4\n", | 306 | printk(KERN_INFO "source route option %pI4 -> %pI4\n", |
307 | &iph->saddr, &iph->daddr); | 307 | &iph->saddr, &iph->daddr); |
308 | in_dev_put(in_dev); | 308 | in_dev_put(in_dev); |
309 | goto drop; | 309 | goto drop; |
310 | } | 310 | } |
311 | 311 | ||
312 | in_dev_put(in_dev); | 312 | in_dev_put(in_dev); |
313 | } | 313 | } |
314 | 314 | ||
315 | if (ip_options_rcv_srr(skb)) | 315 | if (ip_options_rcv_srr(skb)) |
316 | goto drop; | 316 | goto drop; |
317 | } | 317 | } |
318 | 318 | ||
319 | return 0; | 319 | return 0; |
320 | drop: | 320 | drop: |
321 | return -1; | 321 | return -1; |
322 | } | 322 | } |
323 | 323 | ||
324 | static int ip_rcv_finish(struct sk_buff *skb) | 324 | static int ip_rcv_finish(struct sk_buff *skb) |
325 | { | 325 | { |
326 | const struct iphdr *iph = ip_hdr(skb); | 326 | const struct iphdr *iph = ip_hdr(skb); |
327 | struct rtable *rt; | 327 | struct rtable *rt; |
328 | 328 | ||
329 | /* | 329 | /* |
330 | * Initialise the virtual path cache for the packet. It describes | 330 | * Initialise the virtual path cache for the packet. It describes |
331 | * how the packet travels inside Linux networking. | 331 | * how the packet travels inside Linux networking. |
332 | */ | 332 | */ |
333 | if (skb_dst(skb) == NULL) { | 333 | if (skb_dst(skb) == NULL) { |
334 | int err = ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, | 334 | int err = ip_route_input_noref(skb, iph->daddr, iph->saddr, |
335 | skb->dev); | 335 | iph->tos, skb->dev); |
336 | if (unlikely(err)) { | 336 | if (unlikely(err)) { |
337 | if (err == -EHOSTUNREACH) | 337 | if (err == -EHOSTUNREACH) |
338 | IP_INC_STATS_BH(dev_net(skb->dev), | 338 | IP_INC_STATS_BH(dev_net(skb->dev), |
339 | IPSTATS_MIB_INADDRERRORS); | 339 | IPSTATS_MIB_INADDRERRORS); |
340 | else if (err == -ENETUNREACH) | 340 | else if (err == -ENETUNREACH) |
341 | IP_INC_STATS_BH(dev_net(skb->dev), | 341 | IP_INC_STATS_BH(dev_net(skb->dev), |
342 | IPSTATS_MIB_INNOROUTES); | 342 | IPSTATS_MIB_INNOROUTES); |
343 | goto drop; | 343 | goto drop; |
344 | } | 344 | } |
345 | } | 345 | } |
346 | 346 | ||
347 | #ifdef CONFIG_NET_CLS_ROUTE | 347 | #ifdef CONFIG_NET_CLS_ROUTE |
348 | if (unlikely(skb_dst(skb)->tclassid)) { | 348 | if (unlikely(skb_dst(skb)->tclassid)) { |
349 | struct ip_rt_acct *st = per_cpu_ptr(ip_rt_acct, smp_processor_id()); | 349 | struct ip_rt_acct *st = per_cpu_ptr(ip_rt_acct, smp_processor_id()); |
350 | u32 idx = skb_dst(skb)->tclassid; | 350 | u32 idx = skb_dst(skb)->tclassid; |
351 | st[idx&0xFF].o_packets++; | 351 | st[idx&0xFF].o_packets++; |
352 | st[idx&0xFF].o_bytes += skb->len; | 352 | st[idx&0xFF].o_bytes += skb->len; |
353 | st[(idx>>16)&0xFF].i_packets++; | 353 | st[(idx>>16)&0xFF].i_packets++; |
354 | st[(idx>>16)&0xFF].i_bytes += skb->len; | 354 | st[(idx>>16)&0xFF].i_bytes += skb->len; |
355 | } | 355 | } |
356 | #endif | 356 | #endif |
357 | 357 | ||
358 | if (iph->ihl > 5 && ip_rcv_options(skb)) | 358 | if (iph->ihl > 5 && ip_rcv_options(skb)) |
359 | goto drop; | 359 | goto drop; |
360 | 360 | ||
361 | rt = skb_rtable(skb); | 361 | rt = skb_rtable(skb); |
362 | if (rt->rt_type == RTN_MULTICAST) { | 362 | if (rt->rt_type == RTN_MULTICAST) { |
363 | IP_UPD_PO_STATS_BH(dev_net(rt->u.dst.dev), IPSTATS_MIB_INMCAST, | 363 | IP_UPD_PO_STATS_BH(dev_net(rt->u.dst.dev), IPSTATS_MIB_INMCAST, |
364 | skb->len); | 364 | skb->len); |
365 | } else if (rt->rt_type == RTN_BROADCAST) | 365 | } else if (rt->rt_type == RTN_BROADCAST) |
366 | IP_UPD_PO_STATS_BH(dev_net(rt->u.dst.dev), IPSTATS_MIB_INBCAST, | 366 | IP_UPD_PO_STATS_BH(dev_net(rt->u.dst.dev), IPSTATS_MIB_INBCAST, |
367 | skb->len); | 367 | skb->len); |
368 | 368 | ||
369 | return dst_input(skb); | 369 | return dst_input(skb); |
370 | 370 | ||
371 | drop: | 371 | drop: |
372 | kfree_skb(skb); | 372 | kfree_skb(skb); |
373 | return NET_RX_DROP; | 373 | return NET_RX_DROP; |
374 | } | 374 | } |
375 | 375 | ||
376 | /* | 376 | /* |
377 | * Main IP Receive routine. | 377 | * Main IP Receive routine. |
378 | */ | 378 | */ |
379 | int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev) | 379 | int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev) |
380 | { | 380 | { |
381 | struct iphdr *iph; | 381 | struct iphdr *iph; |
382 | u32 len; | 382 | u32 len; |
383 | 383 | ||
384 | /* When the interface is in promisc. mode, drop all the crap | 384 | /* When the interface is in promisc. mode, drop all the crap |
385 | * that it receives, do not try to analyse it. | 385 | * that it receives, do not try to analyse it. |
386 | */ | 386 | */ |
387 | if (skb->pkt_type == PACKET_OTHERHOST) | 387 | if (skb->pkt_type == PACKET_OTHERHOST) |
388 | goto drop; | 388 | goto drop; |
389 | 389 | ||
390 | 390 | ||
391 | IP_UPD_PO_STATS_BH(dev_net(dev), IPSTATS_MIB_IN, skb->len); | 391 | IP_UPD_PO_STATS_BH(dev_net(dev), IPSTATS_MIB_IN, skb->len); |
392 | 392 | ||
393 | if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) { | 393 | if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) { |
394 | IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INDISCARDS); | 394 | IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INDISCARDS); |
395 | goto out; | 395 | goto out; |
396 | } | 396 | } |
397 | 397 | ||
398 | if (!pskb_may_pull(skb, sizeof(struct iphdr))) | 398 | if (!pskb_may_pull(skb, sizeof(struct iphdr))) |
399 | goto inhdr_error; | 399 | goto inhdr_error; |
400 | 400 | ||
401 | iph = ip_hdr(skb); | 401 | iph = ip_hdr(skb); |
402 | 402 | ||
403 | /* | 403 | /* |
404 | * RFC1122: 3.2.1.2 MUST silently discard any IP frame that fails the checksum. | 404 | * RFC1122: 3.2.1.2 MUST silently discard any IP frame that fails the checksum. |
405 | * | 405 | * |
406 | * Is the datagram acceptable? | 406 | * Is the datagram acceptable? |
407 | * | 407 | * |
408 | * 1. Length at least the size of an ip header | 408 | * 1. Length at least the size of an ip header |
409 | * 2. Version of 4 | 409 | * 2. Version of 4 |
410 | * 3. Checksums correctly. [Speed optimisation for later, skip loopback checksums] | 410 | * 3. Checksums correctly. [Speed optimisation for later, skip loopback checksums] |
411 | * 4. Doesn't have a bogus length | 411 | * 4. Doesn't have a bogus length |
412 | */ | 412 | */ |
413 | 413 | ||
414 | if (iph->ihl < 5 || iph->version != 4) | 414 | if (iph->ihl < 5 || iph->version != 4) |
415 | goto inhdr_error; | 415 | goto inhdr_error; |
416 | 416 | ||
417 | if (!pskb_may_pull(skb, iph->ihl*4)) | 417 | if (!pskb_may_pull(skb, iph->ihl*4)) |
418 | goto inhdr_error; | 418 | goto inhdr_error; |
419 | 419 | ||
420 | iph = ip_hdr(skb); | 420 | iph = ip_hdr(skb); |
421 | 421 | ||
422 | if (unlikely(ip_fast_csum((u8 *)iph, iph->ihl))) | 422 | if (unlikely(ip_fast_csum((u8 *)iph, iph->ihl))) |
423 | goto inhdr_error; | 423 | goto inhdr_error; |
424 | 424 | ||
425 | len = ntohs(iph->tot_len); | 425 | len = ntohs(iph->tot_len); |
426 | if (skb->len < len) { | 426 | if (skb->len < len) { |
427 | IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INTRUNCATEDPKTS); | 427 | IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INTRUNCATEDPKTS); |
428 | goto drop; | 428 | goto drop; |
429 | } else if (len < (iph->ihl*4)) | 429 | } else if (len < (iph->ihl*4)) |
430 | goto inhdr_error; | 430 | goto inhdr_error; |
431 | 431 | ||
432 | /* Our transport medium may have padded the buffer out. Now we know it | 432 | /* Our transport medium may have padded the buffer out. Now we know it |
433 | * is IP we can trim to the true length of the frame. | 433 | * is IP we can trim to the true length of the frame. |
434 | * Note this now means skb->len holds ntohs(iph->tot_len). | 434 | * Note this now means skb->len holds ntohs(iph->tot_len). |
435 | */ | 435 | */ |
436 | if (pskb_trim_rcsum(skb, len)) { | 436 | if (pskb_trim_rcsum(skb, len)) { |
437 | IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INDISCARDS); | 437 | IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INDISCARDS); |
438 | goto drop; | 438 | goto drop; |
439 | } | 439 | } |
440 | 440 | ||
441 | /* Remove any debris in the socket control block */ | 441 | /* Remove any debris in the socket control block */ |
442 | memset(IPCB(skb), 0, sizeof(struct inet_skb_parm)); | 442 | memset(IPCB(skb), 0, sizeof(struct inet_skb_parm)); |
443 | 443 | ||
444 | /* Must drop socket now because of tproxy. */ | 444 | /* Must drop socket now because of tproxy. */ |
445 | skb_orphan(skb); | 445 | skb_orphan(skb); |
446 | 446 | ||
447 | return NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING, skb, dev, NULL, | 447 | return NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING, skb, dev, NULL, |
448 | ip_rcv_finish); | 448 | ip_rcv_finish); |
449 | 449 | ||
450 | inhdr_error: | 450 | inhdr_error: |
451 | IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INHDRERRORS); | 451 | IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INHDRERRORS); |
452 | drop: | 452 | drop: |
453 | kfree_skb(skb); | 453 | kfree_skb(skb); |
454 | out: | 454 | out: |
455 | return NET_RX_DROP; | 455 | return NET_RX_DROP; |
456 | } | 456 | } |
457 | 457 |
net/ipv4/xfrm4_input.c
1 | /* | 1 | /* |
2 | * xfrm4_input.c | 2 | * xfrm4_input.c |
3 | * | 3 | * |
4 | * Changes: | 4 | * Changes: |
5 | * YOSHIFUJI Hideaki @USAGI | 5 | * YOSHIFUJI Hideaki @USAGI |
6 | * Split up af-specific portion | 6 | * Split up af-specific portion |
7 | * Derek Atkins <derek@ihtfp.com> | 7 | * Derek Atkins <derek@ihtfp.com> |
8 | * Add Encapsulation support | 8 | * Add Encapsulation support |
9 | * | 9 | * |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/string.h> | 14 | #include <linux/string.h> |
15 | #include <linux/netfilter.h> | 15 | #include <linux/netfilter.h> |
16 | #include <linux/netfilter_ipv4.h> | 16 | #include <linux/netfilter_ipv4.h> |
17 | #include <net/ip.h> | 17 | #include <net/ip.h> |
18 | #include <net/xfrm.h> | 18 | #include <net/xfrm.h> |
19 | 19 | ||
20 | int xfrm4_extract_input(struct xfrm_state *x, struct sk_buff *skb) | 20 | int xfrm4_extract_input(struct xfrm_state *x, struct sk_buff *skb) |
21 | { | 21 | { |
22 | return xfrm4_extract_header(skb); | 22 | return xfrm4_extract_header(skb); |
23 | } | 23 | } |
24 | 24 | ||
25 | static inline int xfrm4_rcv_encap_finish(struct sk_buff *skb) | 25 | static inline int xfrm4_rcv_encap_finish(struct sk_buff *skb) |
26 | { | 26 | { |
27 | if (skb_dst(skb) == NULL) { | 27 | if (skb_dst(skb) == NULL) { |
28 | const struct iphdr *iph = ip_hdr(skb); | 28 | const struct iphdr *iph = ip_hdr(skb); |
29 | 29 | ||
30 | if (ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, | 30 | if (ip_route_input_noref(skb, iph->daddr, iph->saddr, |
31 | skb->dev)) | 31 | iph->tos, skb->dev)) |
32 | goto drop; | 32 | goto drop; |
33 | } | 33 | } |
34 | return dst_input(skb); | 34 | return dst_input(skb); |
35 | drop: | 35 | drop: |
36 | kfree_skb(skb); | 36 | kfree_skb(skb); |
37 | return NET_RX_DROP; | 37 | return NET_RX_DROP; |
38 | } | 38 | } |
39 | 39 | ||
40 | int xfrm4_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi, | 40 | int xfrm4_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi, |
41 | int encap_type) | 41 | int encap_type) |
42 | { | 42 | { |
43 | XFRM_SPI_SKB_CB(skb)->family = AF_INET; | 43 | XFRM_SPI_SKB_CB(skb)->family = AF_INET; |
44 | XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct iphdr, daddr); | 44 | XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct iphdr, daddr); |
45 | return xfrm_input(skb, nexthdr, spi, encap_type); | 45 | return xfrm_input(skb, nexthdr, spi, encap_type); |
46 | } | 46 | } |
47 | EXPORT_SYMBOL(xfrm4_rcv_encap); | 47 | EXPORT_SYMBOL(xfrm4_rcv_encap); |
48 | 48 | ||
49 | int xfrm4_transport_finish(struct sk_buff *skb, int async) | 49 | int xfrm4_transport_finish(struct sk_buff *skb, int async) |
50 | { | 50 | { |
51 | struct iphdr *iph = ip_hdr(skb); | 51 | struct iphdr *iph = ip_hdr(skb); |
52 | 52 | ||
53 | iph->protocol = XFRM_MODE_SKB_CB(skb)->protocol; | 53 | iph->protocol = XFRM_MODE_SKB_CB(skb)->protocol; |
54 | 54 | ||
55 | #ifndef CONFIG_NETFILTER | 55 | #ifndef CONFIG_NETFILTER |
56 | if (!async) | 56 | if (!async) |
57 | return -iph->protocol; | 57 | return -iph->protocol; |
58 | #endif | 58 | #endif |
59 | 59 | ||
60 | __skb_push(skb, skb->data - skb_network_header(skb)); | 60 | __skb_push(skb, skb->data - skb_network_header(skb)); |
61 | iph->tot_len = htons(skb->len); | 61 | iph->tot_len = htons(skb->len); |
62 | ip_send_check(iph); | 62 | ip_send_check(iph); |
63 | 63 | ||
64 | NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING, skb, skb->dev, NULL, | 64 | NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING, skb, skb->dev, NULL, |
65 | xfrm4_rcv_encap_finish); | 65 | xfrm4_rcv_encap_finish); |
66 | return 0; | 66 | return 0; |
67 | } | 67 | } |
68 | 68 | ||
69 | /* If it's a keepalive packet, then just eat it. | 69 | /* If it's a keepalive packet, then just eat it. |
70 | * If it's an encapsulated packet, then pass it to the | 70 | * If it's an encapsulated packet, then pass it to the |
71 | * IPsec xfrm input. | 71 | * IPsec xfrm input. |
72 | * Returns 0 if skb passed to xfrm or was dropped. | 72 | * Returns 0 if skb passed to xfrm or was dropped. |
73 | * Returns >0 if skb should be passed to UDP. | 73 | * Returns >0 if skb should be passed to UDP. |
74 | * Returns <0 if skb should be resubmitted (-ret is protocol) | 74 | * Returns <0 if skb should be resubmitted (-ret is protocol) |
75 | */ | 75 | */ |
76 | int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb) | 76 | int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb) |
77 | { | 77 | { |
78 | struct udp_sock *up = udp_sk(sk); | 78 | struct udp_sock *up = udp_sk(sk); |
79 | struct udphdr *uh; | 79 | struct udphdr *uh; |
80 | struct iphdr *iph; | 80 | struct iphdr *iph; |
81 | int iphlen, len; | 81 | int iphlen, len; |
82 | 82 | ||
83 | __u8 *udpdata; | 83 | __u8 *udpdata; |
84 | __be32 *udpdata32; | 84 | __be32 *udpdata32; |
85 | __u16 encap_type = up->encap_type; | 85 | __u16 encap_type = up->encap_type; |
86 | 86 | ||
87 | /* if this is not encapsulated socket, then just return now */ | 87 | /* if this is not encapsulated socket, then just return now */ |
88 | if (!encap_type) | 88 | if (!encap_type) |
89 | return 1; | 89 | return 1; |
90 | 90 | ||
91 | /* If this is a paged skb, make sure we pull up | 91 | /* If this is a paged skb, make sure we pull up |
92 | * whatever data we need to look at. */ | 92 | * whatever data we need to look at. */ |
93 | len = skb->len - sizeof(struct udphdr); | 93 | len = skb->len - sizeof(struct udphdr); |
94 | if (!pskb_may_pull(skb, sizeof(struct udphdr) + min(len, 8))) | 94 | if (!pskb_may_pull(skb, sizeof(struct udphdr) + min(len, 8))) |
95 | return 1; | 95 | return 1; |
96 | 96 | ||
97 | /* Now we can get the pointers */ | 97 | /* Now we can get the pointers */ |
98 | uh = udp_hdr(skb); | 98 | uh = udp_hdr(skb); |
99 | udpdata = (__u8 *)uh + sizeof(struct udphdr); | 99 | udpdata = (__u8 *)uh + sizeof(struct udphdr); |
100 | udpdata32 = (__be32 *)udpdata; | 100 | udpdata32 = (__be32 *)udpdata; |
101 | 101 | ||
102 | switch (encap_type) { | 102 | switch (encap_type) { |
103 | default: | 103 | default: |
104 | case UDP_ENCAP_ESPINUDP: | 104 | case UDP_ENCAP_ESPINUDP: |
105 | /* Check if this is a keepalive packet. If so, eat it. */ | 105 | /* Check if this is a keepalive packet. If so, eat it. */ |
106 | if (len == 1 && udpdata[0] == 0xff) { | 106 | if (len == 1 && udpdata[0] == 0xff) { |
107 | goto drop; | 107 | goto drop; |
108 | } else if (len > sizeof(struct ip_esp_hdr) && udpdata32[0] != 0) { | 108 | } else if (len > sizeof(struct ip_esp_hdr) && udpdata32[0] != 0) { |
109 | /* ESP Packet without Non-ESP header */ | 109 | /* ESP Packet without Non-ESP header */ |
110 | len = sizeof(struct udphdr); | 110 | len = sizeof(struct udphdr); |
111 | } else | 111 | } else |
112 | /* Must be an IKE packet.. pass it through */ | 112 | /* Must be an IKE packet.. pass it through */ |
113 | return 1; | 113 | return 1; |
114 | break; | 114 | break; |
115 | case UDP_ENCAP_ESPINUDP_NON_IKE: | 115 | case UDP_ENCAP_ESPINUDP_NON_IKE: |
116 | /* Check if this is a keepalive packet. If so, eat it. */ | 116 | /* Check if this is a keepalive packet. If so, eat it. */ |
117 | if (len == 1 && udpdata[0] == 0xff) { | 117 | if (len == 1 && udpdata[0] == 0xff) { |
118 | goto drop; | 118 | goto drop; |
119 | } else if (len > 2 * sizeof(u32) + sizeof(struct ip_esp_hdr) && | 119 | } else if (len > 2 * sizeof(u32) + sizeof(struct ip_esp_hdr) && |
120 | udpdata32[0] == 0 && udpdata32[1] == 0) { | 120 | udpdata32[0] == 0 && udpdata32[1] == 0) { |
121 | 121 | ||
122 | /* ESP Packet with Non-IKE marker */ | 122 | /* ESP Packet with Non-IKE marker */ |
123 | len = sizeof(struct udphdr) + 2 * sizeof(u32); | 123 | len = sizeof(struct udphdr) + 2 * sizeof(u32); |
124 | } else | 124 | } else |
125 | /* Must be an IKE packet.. pass it through */ | 125 | /* Must be an IKE packet.. pass it through */ |
126 | return 1; | 126 | return 1; |
127 | break; | 127 | break; |
128 | } | 128 | } |
129 | 129 | ||
130 | /* At this point we are sure that this is an ESPinUDP packet, | 130 | /* At this point we are sure that this is an ESPinUDP packet, |
131 | * so we need to remove 'len' bytes from the packet (the UDP | 131 | * so we need to remove 'len' bytes from the packet (the UDP |
132 | * header and optional ESP marker bytes) and then modify the | 132 | * header and optional ESP marker bytes) and then modify the |
133 | * protocol to ESP, and then call into the transform receiver. | 133 | * protocol to ESP, and then call into the transform receiver. |
134 | */ | 134 | */ |
135 | if (skb_cloned(skb) && pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) | 135 | if (skb_cloned(skb) && pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) |
136 | goto drop; | 136 | goto drop; |
137 | 137 | ||
138 | /* Now we can update and verify the packet length... */ | 138 | /* Now we can update and verify the packet length... */ |
139 | iph = ip_hdr(skb); | 139 | iph = ip_hdr(skb); |
140 | iphlen = iph->ihl << 2; | 140 | iphlen = iph->ihl << 2; |
141 | iph->tot_len = htons(ntohs(iph->tot_len) - len); | 141 | iph->tot_len = htons(ntohs(iph->tot_len) - len); |
142 | if (skb->len < iphlen + len) { | 142 | if (skb->len < iphlen + len) { |
143 | /* packet is too small!?! */ | 143 | /* packet is too small!?! */ |
144 | goto drop; | 144 | goto drop; |
145 | } | 145 | } |
146 | 146 | ||
147 | /* pull the data buffer up to the ESP header and set the | 147 | /* pull the data buffer up to the ESP header and set the |
148 | * transport header to point to ESP. Keep UDP on the stack | 148 | * transport header to point to ESP. Keep UDP on the stack |
149 | * for later. | 149 | * for later. |
150 | */ | 150 | */ |
151 | __skb_pull(skb, len); | 151 | __skb_pull(skb, len); |
152 | skb_reset_transport_header(skb); | 152 | skb_reset_transport_header(skb); |
153 | 153 | ||
154 | /* process ESP */ | 154 | /* process ESP */ |
155 | return xfrm4_rcv_encap(skb, IPPROTO_ESP, 0, encap_type); | 155 | return xfrm4_rcv_encap(skb, IPPROTO_ESP, 0, encap_type); |
156 | 156 | ||
157 | drop: | 157 | drop: |
158 | kfree_skb(skb); | 158 | kfree_skb(skb); |
159 | return 0; | 159 | return 0; |
160 | } | 160 | } |
161 | 161 | ||
162 | int xfrm4_rcv(struct sk_buff *skb) | 162 | int xfrm4_rcv(struct sk_buff *skb) |
163 | { | 163 | { |
164 | return xfrm4_rcv_spi(skb, ip_hdr(skb)->protocol, 0); | 164 | return xfrm4_rcv_spi(skb, ip_hdr(skb)->protocol, 0); |
165 | } | 165 | } |
166 | 166 | ||
167 | EXPORT_SYMBOL(xfrm4_rcv); | 167 | EXPORT_SYMBOL(xfrm4_rcv); |
168 | 168 |