Commit 8cdfab8a43bb4b3da686ea503a702cb6f9f6a803
Committed by
David S. Miller
1 parent
b05e106698
Exists in
master
and in
7 other branches
[IPV4]: reset IPCB flags when neccessary
Reset IPSKB_XFRM_TUNNEL_SIZE flags in ipip and ip_gre hard_start_xmit function before the packet reenters IP. This is neccessary so the encapsulated packets are checked not to be oversized in xfrm4_output.c again. Reset all flags in sit when a packet changes its address family. Also remove some obsolete IPSKB flags. Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Showing 4 changed files with 7 additions and 5 deletions Inline Diff
include/net/ip.h
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 | * Definitions for the IP module. | 6 | * Definitions for the IP module. |
7 | * | 7 | * |
8 | * Version: @(#)ip.h 1.0.2 05/07/93 | 8 | * Version: @(#)ip.h 1.0.2 05/07/93 |
9 | * | 9 | * |
10 | * Authors: Ross Biro | 10 | * Authors: Ross Biro |
11 | * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> | 11 | * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> |
12 | * Alan Cox, <gw4pts@gw4pts.ampr.org> | 12 | * Alan Cox, <gw4pts@gw4pts.ampr.org> |
13 | * | 13 | * |
14 | * Changes: | 14 | * Changes: |
15 | * Mike McLagan : Routing by source | 15 | * Mike McLagan : Routing by source |
16 | * | 16 | * |
17 | * This program is free software; you can redistribute it and/or | 17 | * This program is free software; you can redistribute it and/or |
18 | * modify it under the terms of the GNU General Public License | 18 | * modify it under the terms of the GNU General Public License |
19 | * as published by the Free Software Foundation; either version | 19 | * as published by the Free Software Foundation; either version |
20 | * 2 of the License, or (at your option) any later version. | 20 | * 2 of the License, or (at your option) any later version. |
21 | */ | 21 | */ |
22 | #ifndef _IP_H | 22 | #ifndef _IP_H |
23 | #define _IP_H | 23 | #define _IP_H |
24 | 24 | ||
25 | #include <linux/config.h> | 25 | #include <linux/config.h> |
26 | #include <linux/types.h> | 26 | #include <linux/types.h> |
27 | #include <linux/ip.h> | 27 | #include <linux/ip.h> |
28 | #include <linux/in.h> | 28 | #include <linux/in.h> |
29 | 29 | ||
30 | #include <net/inet_sock.h> | 30 | #include <net/inet_sock.h> |
31 | #include <net/snmp.h> | 31 | #include <net/snmp.h> |
32 | 32 | ||
33 | struct sock; | 33 | struct sock; |
34 | 34 | ||
35 | struct inet_skb_parm | 35 | struct inet_skb_parm |
36 | { | 36 | { |
37 | struct ip_options opt; /* Compiled IP options */ | 37 | struct ip_options opt; /* Compiled IP options */ |
38 | unsigned char flags; | 38 | unsigned char flags; |
39 | 39 | ||
40 | #define IPSKB_MASQUERADED 1 | 40 | #define IPSKB_FORWARDED 1 |
41 | #define IPSKB_TRANSLATED 2 | 41 | #define IPSKB_XFRM_TUNNEL_SIZE 2 |
42 | #define IPSKB_FORWARDED 4 | 42 | #define IPSKB_FRAG_COMPLETE 4 |
43 | #define IPSKB_XFRM_TUNNEL_SIZE 8 | ||
44 | #define IPSKB_FRAG_COMPLETE 16 | ||
45 | }; | 43 | }; |
46 | 44 | ||
47 | struct ipcm_cookie | 45 | struct ipcm_cookie |
48 | { | 46 | { |
49 | u32 addr; | 47 | u32 addr; |
50 | int oif; | 48 | int oif; |
51 | struct ip_options *opt; | 49 | struct ip_options *opt; |
52 | }; | 50 | }; |
53 | 51 | ||
54 | #define IPCB(skb) ((struct inet_skb_parm*)((skb)->cb)) | 52 | #define IPCB(skb) ((struct inet_skb_parm*)((skb)->cb)) |
55 | 53 | ||
56 | struct ip_ra_chain | 54 | struct ip_ra_chain |
57 | { | 55 | { |
58 | struct ip_ra_chain *next; | 56 | struct ip_ra_chain *next; |
59 | struct sock *sk; | 57 | struct sock *sk; |
60 | void (*destructor)(struct sock *); | 58 | void (*destructor)(struct sock *); |
61 | }; | 59 | }; |
62 | 60 | ||
63 | extern struct ip_ra_chain *ip_ra_chain; | 61 | extern struct ip_ra_chain *ip_ra_chain; |
64 | extern rwlock_t ip_ra_lock; | 62 | extern rwlock_t ip_ra_lock; |
65 | 63 | ||
66 | /* IP flags. */ | 64 | /* IP flags. */ |
67 | #define IP_CE 0x8000 /* Flag: "Congestion" */ | 65 | #define IP_CE 0x8000 /* Flag: "Congestion" */ |
68 | #define IP_DF 0x4000 /* Flag: "Don't Fragment" */ | 66 | #define IP_DF 0x4000 /* Flag: "Don't Fragment" */ |
69 | #define IP_MF 0x2000 /* Flag: "More Fragments" */ | 67 | #define IP_MF 0x2000 /* Flag: "More Fragments" */ |
70 | #define IP_OFFSET 0x1FFF /* "Fragment Offset" part */ | 68 | #define IP_OFFSET 0x1FFF /* "Fragment Offset" part */ |
71 | 69 | ||
72 | #define IP_FRAG_TIME (30 * HZ) /* fragment lifetime */ | 70 | #define IP_FRAG_TIME (30 * HZ) /* fragment lifetime */ |
73 | 71 | ||
74 | struct msghdr; | 72 | struct msghdr; |
75 | struct net_device; | 73 | struct net_device; |
76 | struct packet_type; | 74 | struct packet_type; |
77 | struct rtable; | 75 | struct rtable; |
78 | struct sk_buff; | 76 | struct sk_buff; |
79 | struct sockaddr; | 77 | struct sockaddr; |
80 | 78 | ||
81 | extern void ip_mc_dropsocket(struct sock *); | 79 | extern void ip_mc_dropsocket(struct sock *); |
82 | extern void ip_mc_dropdevice(struct net_device *dev); | 80 | extern void ip_mc_dropdevice(struct net_device *dev); |
83 | extern int igmp_mc_proc_init(void); | 81 | extern int igmp_mc_proc_init(void); |
84 | 82 | ||
85 | /* | 83 | /* |
86 | * Functions provided by ip.c | 84 | * Functions provided by ip.c |
87 | */ | 85 | */ |
88 | 86 | ||
89 | extern int ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk, | 87 | extern int ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk, |
90 | u32 saddr, u32 daddr, | 88 | u32 saddr, u32 daddr, |
91 | struct ip_options *opt); | 89 | struct ip_options *opt); |
92 | extern int ip_rcv(struct sk_buff *skb, struct net_device *dev, | 90 | extern int ip_rcv(struct sk_buff *skb, struct net_device *dev, |
93 | struct packet_type *pt, struct net_device *orig_dev); | 91 | struct packet_type *pt, struct net_device *orig_dev); |
94 | extern int ip_local_deliver(struct sk_buff *skb); | 92 | extern int ip_local_deliver(struct sk_buff *skb); |
95 | extern int ip_mr_input(struct sk_buff *skb); | 93 | extern int ip_mr_input(struct sk_buff *skb); |
96 | extern int ip_output(struct sk_buff *skb); | 94 | extern int ip_output(struct sk_buff *skb); |
97 | extern int ip_mc_output(struct sk_buff *skb); | 95 | extern int ip_mc_output(struct sk_buff *skb); |
98 | extern int ip_fragment(struct sk_buff *skb, int (*out)(struct sk_buff*)); | 96 | extern int ip_fragment(struct sk_buff *skb, int (*out)(struct sk_buff*)); |
99 | extern int ip_do_nat(struct sk_buff *skb); | 97 | extern int ip_do_nat(struct sk_buff *skb); |
100 | extern void ip_send_check(struct iphdr *ip); | 98 | extern void ip_send_check(struct iphdr *ip); |
101 | extern int ip_queue_xmit(struct sk_buff *skb, int ipfragok); | 99 | extern int ip_queue_xmit(struct sk_buff *skb, int ipfragok); |
102 | extern void ip_init(void); | 100 | extern void ip_init(void); |
103 | extern int ip_append_data(struct sock *sk, | 101 | extern int ip_append_data(struct sock *sk, |
104 | int getfrag(void *from, char *to, int offset, int len, | 102 | int getfrag(void *from, char *to, int offset, int len, |
105 | int odd, struct sk_buff *skb), | 103 | int odd, struct sk_buff *skb), |
106 | void *from, int len, int protolen, | 104 | void *from, int len, int protolen, |
107 | struct ipcm_cookie *ipc, | 105 | struct ipcm_cookie *ipc, |
108 | struct rtable *rt, | 106 | struct rtable *rt, |
109 | unsigned int flags); | 107 | unsigned int flags); |
110 | extern int ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb); | 108 | extern int ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb); |
111 | extern ssize_t ip_append_page(struct sock *sk, struct page *page, | 109 | extern ssize_t ip_append_page(struct sock *sk, struct page *page, |
112 | int offset, size_t size, int flags); | 110 | int offset, size_t size, int flags); |
113 | extern int ip_push_pending_frames(struct sock *sk); | 111 | extern int ip_push_pending_frames(struct sock *sk); |
114 | extern void ip_flush_pending_frames(struct sock *sk); | 112 | extern void ip_flush_pending_frames(struct sock *sk); |
115 | 113 | ||
116 | /* datagram.c */ | 114 | /* datagram.c */ |
117 | extern int ip4_datagram_connect(struct sock *sk, | 115 | extern int ip4_datagram_connect(struct sock *sk, |
118 | struct sockaddr *uaddr, int addr_len); | 116 | struct sockaddr *uaddr, int addr_len); |
119 | 117 | ||
120 | /* | 118 | /* |
121 | * Map a multicast IP onto multicast MAC for type Token Ring. | 119 | * Map a multicast IP onto multicast MAC for type Token Ring. |
122 | * This conforms to RFC1469 Option 2 Multicasting i.e. | 120 | * This conforms to RFC1469 Option 2 Multicasting i.e. |
123 | * using a functional address to transmit / receive | 121 | * using a functional address to transmit / receive |
124 | * multicast packets. | 122 | * multicast packets. |
125 | */ | 123 | */ |
126 | 124 | ||
127 | static inline void ip_tr_mc_map(u32 addr, char *buf) | 125 | static inline void ip_tr_mc_map(u32 addr, char *buf) |
128 | { | 126 | { |
129 | buf[0]=0xC0; | 127 | buf[0]=0xC0; |
130 | buf[1]=0x00; | 128 | buf[1]=0x00; |
131 | buf[2]=0x00; | 129 | buf[2]=0x00; |
132 | buf[3]=0x04; | 130 | buf[3]=0x04; |
133 | buf[4]=0x00; | 131 | buf[4]=0x00; |
134 | buf[5]=0x00; | 132 | buf[5]=0x00; |
135 | } | 133 | } |
136 | 134 | ||
137 | struct ip_reply_arg { | 135 | struct ip_reply_arg { |
138 | struct kvec iov[1]; | 136 | struct kvec iov[1]; |
139 | u32 csum; | 137 | u32 csum; |
140 | int csumoffset; /* u16 offset of csum in iov[0].iov_base */ | 138 | int csumoffset; /* u16 offset of csum in iov[0].iov_base */ |
141 | /* -1 if not needed */ | 139 | /* -1 if not needed */ |
142 | }; | 140 | }; |
143 | 141 | ||
144 | void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *arg, | 142 | void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *arg, |
145 | unsigned int len); | 143 | unsigned int len); |
146 | 144 | ||
147 | struct ipv4_config | 145 | struct ipv4_config |
148 | { | 146 | { |
149 | int log_martians; | 147 | int log_martians; |
150 | int autoconfig; | 148 | int autoconfig; |
151 | int no_pmtu_disc; | 149 | int no_pmtu_disc; |
152 | }; | 150 | }; |
153 | 151 | ||
154 | extern struct ipv4_config ipv4_config; | 152 | extern struct ipv4_config ipv4_config; |
155 | DECLARE_SNMP_STAT(struct ipstats_mib, ip_statistics); | 153 | DECLARE_SNMP_STAT(struct ipstats_mib, ip_statistics); |
156 | #define IP_INC_STATS(field) SNMP_INC_STATS(ip_statistics, field) | 154 | #define IP_INC_STATS(field) SNMP_INC_STATS(ip_statistics, field) |
157 | #define IP_INC_STATS_BH(field) SNMP_INC_STATS_BH(ip_statistics, field) | 155 | #define IP_INC_STATS_BH(field) SNMP_INC_STATS_BH(ip_statistics, field) |
158 | #define IP_INC_STATS_USER(field) SNMP_INC_STATS_USER(ip_statistics, field) | 156 | #define IP_INC_STATS_USER(field) SNMP_INC_STATS_USER(ip_statistics, field) |
159 | DECLARE_SNMP_STAT(struct linux_mib, net_statistics); | 157 | DECLARE_SNMP_STAT(struct linux_mib, net_statistics); |
160 | #define NET_INC_STATS(field) SNMP_INC_STATS(net_statistics, field) | 158 | #define NET_INC_STATS(field) SNMP_INC_STATS(net_statistics, field) |
161 | #define NET_INC_STATS_BH(field) SNMP_INC_STATS_BH(net_statistics, field) | 159 | #define NET_INC_STATS_BH(field) SNMP_INC_STATS_BH(net_statistics, field) |
162 | #define NET_INC_STATS_USER(field) SNMP_INC_STATS_USER(net_statistics, field) | 160 | #define NET_INC_STATS_USER(field) SNMP_INC_STATS_USER(net_statistics, field) |
163 | #define NET_ADD_STATS_BH(field, adnd) SNMP_ADD_STATS_BH(net_statistics, field, adnd) | 161 | #define NET_ADD_STATS_BH(field, adnd) SNMP_ADD_STATS_BH(net_statistics, field, adnd) |
164 | #define NET_ADD_STATS_USER(field, adnd) SNMP_ADD_STATS_USER(net_statistics, field, adnd) | 162 | #define NET_ADD_STATS_USER(field, adnd) SNMP_ADD_STATS_USER(net_statistics, field, adnd) |
165 | 163 | ||
166 | extern int sysctl_local_port_range[2]; | 164 | extern int sysctl_local_port_range[2]; |
167 | extern int sysctl_ip_default_ttl; | 165 | extern int sysctl_ip_default_ttl; |
168 | extern int sysctl_ip_nonlocal_bind; | 166 | extern int sysctl_ip_nonlocal_bind; |
169 | 167 | ||
170 | /* From ip_fragment.c */ | 168 | /* From ip_fragment.c */ |
171 | extern int sysctl_ipfrag_high_thresh; | 169 | extern int sysctl_ipfrag_high_thresh; |
172 | extern int sysctl_ipfrag_low_thresh; | 170 | extern int sysctl_ipfrag_low_thresh; |
173 | extern int sysctl_ipfrag_time; | 171 | extern int sysctl_ipfrag_time; |
174 | extern int sysctl_ipfrag_secret_interval; | 172 | extern int sysctl_ipfrag_secret_interval; |
175 | extern int sysctl_ipfrag_max_dist; | 173 | extern int sysctl_ipfrag_max_dist; |
176 | 174 | ||
177 | /* From inetpeer.c */ | 175 | /* From inetpeer.c */ |
178 | extern int inet_peer_threshold; | 176 | extern int inet_peer_threshold; |
179 | extern int inet_peer_minttl; | 177 | extern int inet_peer_minttl; |
180 | extern int inet_peer_maxttl; | 178 | extern int inet_peer_maxttl; |
181 | extern int inet_peer_gc_mintime; | 179 | extern int inet_peer_gc_mintime; |
182 | extern int inet_peer_gc_maxtime; | 180 | extern int inet_peer_gc_maxtime; |
183 | 181 | ||
184 | /* From ip_output.c */ | 182 | /* From ip_output.c */ |
185 | extern int sysctl_ip_dynaddr; | 183 | extern int sysctl_ip_dynaddr; |
186 | 184 | ||
187 | extern void ipfrag_init(void); | 185 | extern void ipfrag_init(void); |
188 | 186 | ||
189 | #ifdef CONFIG_INET | 187 | #ifdef CONFIG_INET |
190 | #include <net/dst.h> | 188 | #include <net/dst.h> |
191 | 189 | ||
192 | /* The function in 2.2 was invalid, producing wrong result for | 190 | /* The function in 2.2 was invalid, producing wrong result for |
193 | * check=0xFEFF. It was noticed by Arthur Skawina _year_ ago. --ANK(000625) */ | 191 | * check=0xFEFF. It was noticed by Arthur Skawina _year_ ago. --ANK(000625) */ |
194 | static inline | 192 | static inline |
195 | int ip_decrease_ttl(struct iphdr *iph) | 193 | int ip_decrease_ttl(struct iphdr *iph) |
196 | { | 194 | { |
197 | u32 check = iph->check; | 195 | u32 check = iph->check; |
198 | check += htons(0x0100); | 196 | check += htons(0x0100); |
199 | iph->check = check + (check>=0xFFFF); | 197 | iph->check = check + (check>=0xFFFF); |
200 | return --iph->ttl; | 198 | return --iph->ttl; |
201 | } | 199 | } |
202 | 200 | ||
203 | static inline | 201 | static inline |
204 | int ip_dont_fragment(struct sock *sk, struct dst_entry *dst) | 202 | int ip_dont_fragment(struct sock *sk, struct dst_entry *dst) |
205 | { | 203 | { |
206 | return (inet_sk(sk)->pmtudisc == IP_PMTUDISC_DO || | 204 | return (inet_sk(sk)->pmtudisc == IP_PMTUDISC_DO || |
207 | (inet_sk(sk)->pmtudisc == IP_PMTUDISC_WANT && | 205 | (inet_sk(sk)->pmtudisc == IP_PMTUDISC_WANT && |
208 | !(dst_metric(dst, RTAX_LOCK)&(1<<RTAX_MTU)))); | 206 | !(dst_metric(dst, RTAX_LOCK)&(1<<RTAX_MTU)))); |
209 | } | 207 | } |
210 | 208 | ||
211 | extern void __ip_select_ident(struct iphdr *iph, struct dst_entry *dst, int more); | 209 | extern void __ip_select_ident(struct iphdr *iph, struct dst_entry *dst, int more); |
212 | 210 | ||
213 | static inline void ip_select_ident(struct iphdr *iph, struct dst_entry *dst, struct sock *sk) | 211 | static inline void ip_select_ident(struct iphdr *iph, struct dst_entry *dst, struct sock *sk) |
214 | { | 212 | { |
215 | if (iph->frag_off & htons(IP_DF)) { | 213 | if (iph->frag_off & htons(IP_DF)) { |
216 | /* This is only to work around buggy Windows95/2000 | 214 | /* This is only to work around buggy Windows95/2000 |
217 | * VJ compression implementations. If the ID field | 215 | * VJ compression implementations. If the ID field |
218 | * does not change, they drop every other packet in | 216 | * does not change, they drop every other packet in |
219 | * a TCP stream using header compression. | 217 | * a TCP stream using header compression. |
220 | */ | 218 | */ |
221 | iph->id = (sk && inet_sk(sk)->daddr) ? | 219 | iph->id = (sk && inet_sk(sk)->daddr) ? |
222 | htons(inet_sk(sk)->id++) : 0; | 220 | htons(inet_sk(sk)->id++) : 0; |
223 | } else | 221 | } else |
224 | __ip_select_ident(iph, dst, 0); | 222 | __ip_select_ident(iph, dst, 0); |
225 | } | 223 | } |
226 | 224 | ||
227 | static inline void ip_select_ident_more(struct iphdr *iph, struct dst_entry *dst, struct sock *sk, int more) | 225 | static inline void ip_select_ident_more(struct iphdr *iph, struct dst_entry *dst, struct sock *sk, int more) |
228 | { | 226 | { |
229 | if (iph->frag_off & htons(IP_DF)) { | 227 | if (iph->frag_off & htons(IP_DF)) { |
230 | if (sk && inet_sk(sk)->daddr) { | 228 | if (sk && inet_sk(sk)->daddr) { |
231 | iph->id = htons(inet_sk(sk)->id); | 229 | iph->id = htons(inet_sk(sk)->id); |
232 | inet_sk(sk)->id += 1 + more; | 230 | inet_sk(sk)->id += 1 + more; |
233 | } else | 231 | } else |
234 | iph->id = 0; | 232 | iph->id = 0; |
235 | } else | 233 | } else |
236 | __ip_select_ident(iph, dst, more); | 234 | __ip_select_ident(iph, dst, more); |
237 | } | 235 | } |
238 | 236 | ||
239 | /* | 237 | /* |
240 | * Map a multicast IP onto multicast MAC for type ethernet. | 238 | * Map a multicast IP onto multicast MAC for type ethernet. |
241 | */ | 239 | */ |
242 | 240 | ||
243 | static inline void ip_eth_mc_map(u32 addr, char *buf) | 241 | static inline void ip_eth_mc_map(u32 addr, char *buf) |
244 | { | 242 | { |
245 | addr=ntohl(addr); | 243 | addr=ntohl(addr); |
246 | buf[0]=0x01; | 244 | buf[0]=0x01; |
247 | buf[1]=0x00; | 245 | buf[1]=0x00; |
248 | buf[2]=0x5e; | 246 | buf[2]=0x5e; |
249 | buf[5]=addr&0xFF; | 247 | buf[5]=addr&0xFF; |
250 | addr>>=8; | 248 | addr>>=8; |
251 | buf[4]=addr&0xFF; | 249 | buf[4]=addr&0xFF; |
252 | addr>>=8; | 250 | addr>>=8; |
253 | buf[3]=addr&0x7F; | 251 | buf[3]=addr&0x7F; |
254 | } | 252 | } |
255 | 253 | ||
256 | /* | 254 | /* |
257 | * Map a multicast IP onto multicast MAC for type IP-over-InfiniBand. | 255 | * Map a multicast IP onto multicast MAC for type IP-over-InfiniBand. |
258 | * Leave P_Key as 0 to be filled in by driver. | 256 | * Leave P_Key as 0 to be filled in by driver. |
259 | */ | 257 | */ |
260 | 258 | ||
261 | static inline void ip_ib_mc_map(u32 addr, char *buf) | 259 | static inline void ip_ib_mc_map(u32 addr, char *buf) |
262 | { | 260 | { |
263 | buf[0] = 0; /* Reserved */ | 261 | buf[0] = 0; /* Reserved */ |
264 | buf[1] = 0xff; /* Multicast QPN */ | 262 | buf[1] = 0xff; /* Multicast QPN */ |
265 | buf[2] = 0xff; | 263 | buf[2] = 0xff; |
266 | buf[3] = 0xff; | 264 | buf[3] = 0xff; |
267 | addr = ntohl(addr); | 265 | addr = ntohl(addr); |
268 | buf[4] = 0xff; | 266 | buf[4] = 0xff; |
269 | buf[5] = 0x12; /* link local scope */ | 267 | buf[5] = 0x12; /* link local scope */ |
270 | buf[6] = 0x40; /* IPv4 signature */ | 268 | buf[6] = 0x40; /* IPv4 signature */ |
271 | buf[7] = 0x1b; | 269 | buf[7] = 0x1b; |
272 | buf[8] = 0; /* P_Key */ | 270 | buf[8] = 0; /* P_Key */ |
273 | buf[9] = 0; | 271 | buf[9] = 0; |
274 | buf[10] = 0; | 272 | buf[10] = 0; |
275 | buf[11] = 0; | 273 | buf[11] = 0; |
276 | buf[12] = 0; | 274 | buf[12] = 0; |
277 | buf[13] = 0; | 275 | buf[13] = 0; |
278 | buf[14] = 0; | 276 | buf[14] = 0; |
279 | buf[15] = 0; | 277 | buf[15] = 0; |
280 | buf[19] = addr & 0xff; | 278 | buf[19] = addr & 0xff; |
281 | addr >>= 8; | 279 | addr >>= 8; |
282 | buf[18] = addr & 0xff; | 280 | buf[18] = addr & 0xff; |
283 | addr >>= 8; | 281 | addr >>= 8; |
284 | buf[17] = addr & 0xff; | 282 | buf[17] = addr & 0xff; |
285 | addr >>= 8; | 283 | addr >>= 8; |
286 | buf[16] = addr & 0x0f; | 284 | buf[16] = addr & 0x0f; |
287 | } | 285 | } |
288 | 286 | ||
289 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 287 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
290 | #include <linux/ipv6.h> | 288 | #include <linux/ipv6.h> |
291 | #endif | 289 | #endif |
292 | 290 | ||
293 | static __inline__ void inet_reset_saddr(struct sock *sk) | 291 | static __inline__ void inet_reset_saddr(struct sock *sk) |
294 | { | 292 | { |
295 | inet_sk(sk)->rcv_saddr = inet_sk(sk)->saddr = 0; | 293 | inet_sk(sk)->rcv_saddr = inet_sk(sk)->saddr = 0; |
296 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 294 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
297 | if (sk->sk_family == PF_INET6) { | 295 | if (sk->sk_family == PF_INET6) { |
298 | struct ipv6_pinfo *np = inet6_sk(sk); | 296 | struct ipv6_pinfo *np = inet6_sk(sk); |
299 | 297 | ||
300 | memset(&np->saddr, 0, sizeof(np->saddr)); | 298 | memset(&np->saddr, 0, sizeof(np->saddr)); |
301 | memset(&np->rcv_saddr, 0, sizeof(np->rcv_saddr)); | 299 | memset(&np->rcv_saddr, 0, sizeof(np->rcv_saddr)); |
302 | } | 300 | } |
303 | #endif | 301 | #endif |
304 | } | 302 | } |
305 | 303 | ||
306 | #endif | 304 | #endif |
307 | 305 | ||
308 | extern int ip_call_ra_chain(struct sk_buff *skb); | 306 | extern int ip_call_ra_chain(struct sk_buff *skb); |
309 | 307 | ||
310 | /* | 308 | /* |
311 | * Functions provided by ip_fragment.o | 309 | * Functions provided by ip_fragment.o |
312 | */ | 310 | */ |
313 | 311 | ||
314 | enum ip_defrag_users | 312 | enum ip_defrag_users |
315 | { | 313 | { |
316 | IP_DEFRAG_LOCAL_DELIVER, | 314 | IP_DEFRAG_LOCAL_DELIVER, |
317 | IP_DEFRAG_CALL_RA_CHAIN, | 315 | IP_DEFRAG_CALL_RA_CHAIN, |
318 | IP_DEFRAG_CONNTRACK_IN, | 316 | IP_DEFRAG_CONNTRACK_IN, |
319 | IP_DEFRAG_CONNTRACK_OUT, | 317 | IP_DEFRAG_CONNTRACK_OUT, |
320 | IP_DEFRAG_VS_IN, | 318 | IP_DEFRAG_VS_IN, |
321 | IP_DEFRAG_VS_OUT, | 319 | IP_DEFRAG_VS_OUT, |
322 | IP_DEFRAG_VS_FWD | 320 | IP_DEFRAG_VS_FWD |
323 | }; | 321 | }; |
324 | 322 | ||
325 | struct sk_buff *ip_defrag(struct sk_buff *skb, u32 user); | 323 | struct sk_buff *ip_defrag(struct sk_buff *skb, u32 user); |
326 | extern int ip_frag_nqueues; | 324 | extern int ip_frag_nqueues; |
327 | extern atomic_t ip_frag_mem; | 325 | extern atomic_t ip_frag_mem; |
328 | 326 | ||
329 | /* | 327 | /* |
330 | * Functions provided by ip_forward.c | 328 | * Functions provided by ip_forward.c |
331 | */ | 329 | */ |
332 | 330 | ||
333 | extern int ip_forward(struct sk_buff *skb); | 331 | extern int ip_forward(struct sk_buff *skb); |
334 | extern int ip_net_unreachable(struct sk_buff *skb); | 332 | extern int ip_net_unreachable(struct sk_buff *skb); |
335 | 333 | ||
336 | /* | 334 | /* |
337 | * Functions provided by ip_options.c | 335 | * Functions provided by ip_options.c |
338 | */ | 336 | */ |
339 | 337 | ||
340 | extern void ip_options_build(struct sk_buff *skb, struct ip_options *opt, u32 daddr, struct rtable *rt, int is_frag); | 338 | extern void ip_options_build(struct sk_buff *skb, struct ip_options *opt, u32 daddr, struct rtable *rt, int is_frag); |
341 | extern int ip_options_echo(struct ip_options *dopt, struct sk_buff *skb); | 339 | extern int ip_options_echo(struct ip_options *dopt, struct sk_buff *skb); |
342 | extern void ip_options_fragment(struct sk_buff *skb); | 340 | extern void ip_options_fragment(struct sk_buff *skb); |
343 | extern int ip_options_compile(struct ip_options *opt, struct sk_buff *skb); | 341 | extern int ip_options_compile(struct ip_options *opt, struct sk_buff *skb); |
344 | extern int ip_options_get(struct ip_options **optp, | 342 | extern int ip_options_get(struct ip_options **optp, |
345 | unsigned char *data, int optlen); | 343 | unsigned char *data, int optlen); |
346 | extern int ip_options_get_from_user(struct ip_options **optp, | 344 | extern int ip_options_get_from_user(struct ip_options **optp, |
347 | unsigned char __user *data, int optlen); | 345 | unsigned char __user *data, int optlen); |
348 | extern void ip_options_undo(struct ip_options * opt); | 346 | extern void ip_options_undo(struct ip_options * opt); |
349 | extern void ip_forward_options(struct sk_buff *skb); | 347 | extern void ip_forward_options(struct sk_buff *skb); |
350 | extern int ip_options_rcv_srr(struct sk_buff *skb); | 348 | extern int ip_options_rcv_srr(struct sk_buff *skb); |
351 | 349 | ||
352 | /* | 350 | /* |
353 | * Functions provided by ip_sockglue.c | 351 | * Functions provided by ip_sockglue.c |
354 | */ | 352 | */ |
355 | 353 | ||
356 | extern void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb); | 354 | extern void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb); |
357 | extern int ip_cmsg_send(struct msghdr *msg, struct ipcm_cookie *ipc); | 355 | extern int ip_cmsg_send(struct msghdr *msg, struct ipcm_cookie *ipc); |
358 | extern int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval, int optlen); | 356 | extern int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval, int optlen); |
359 | extern int ip_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen); | 357 | extern int ip_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen); |
360 | extern int ip_ra_control(struct sock *sk, unsigned char on, void (*destructor)(struct sock *)); | 358 | extern int ip_ra_control(struct sock *sk, unsigned char on, void (*destructor)(struct sock *)); |
361 | 359 | ||
362 | extern int ip_recv_error(struct sock *sk, struct msghdr *msg, int len); | 360 | extern int ip_recv_error(struct sock *sk, struct msghdr *msg, int len); |
363 | extern void ip_icmp_error(struct sock *sk, struct sk_buff *skb, int err, | 361 | extern void ip_icmp_error(struct sock *sk, struct sk_buff *skb, int err, |
364 | u16 port, u32 info, u8 *payload); | 362 | u16 port, u32 info, u8 *payload); |
365 | extern void ip_local_error(struct sock *sk, int err, u32 daddr, u16 dport, | 363 | extern void ip_local_error(struct sock *sk, int err, u32 daddr, u16 dport, |
366 | u32 info); | 364 | u32 info); |
367 | 365 | ||
368 | /* sysctl helpers - any sysctl which holds a value that ends up being | 366 | /* sysctl helpers - any sysctl which holds a value that ends up being |
369 | * fed into the routing cache should use these handlers. | 367 | * fed into the routing cache should use these handlers. |
370 | */ | 368 | */ |
371 | int ipv4_doint_and_flush(ctl_table *ctl, int write, | 369 | int ipv4_doint_and_flush(ctl_table *ctl, int write, |
372 | struct file* filp, void __user *buffer, | 370 | struct file* filp, void __user *buffer, |
373 | size_t *lenp, loff_t *ppos); | 371 | size_t *lenp, loff_t *ppos); |
374 | int ipv4_doint_and_flush_strategy(ctl_table *table, int __user *name, int nlen, | 372 | int ipv4_doint_and_flush_strategy(ctl_table *table, int __user *name, int nlen, |
375 | void __user *oldval, size_t __user *oldlenp, | 373 | void __user *oldval, size_t __user *oldlenp, |
376 | void __user *newval, size_t newlen, | 374 | void __user *newval, size_t newlen, |
377 | void **context); | 375 | void **context); |
378 | #ifdef CONFIG_PROC_FS | 376 | #ifdef CONFIG_PROC_FS |
379 | extern int ip_misc_proc_init(void); | 377 | extern int ip_misc_proc_init(void); |
380 | #endif | 378 | #endif |
381 | 379 | ||
382 | extern struct ctl_table ipv4_table[]; | 380 | extern struct ctl_table ipv4_table[]; |
383 | 381 | ||
384 | #endif /* _IP_H */ | 382 | #endif /* _IP_H */ |
385 | 383 |
net/ipv4/ip_gre.c
1 | /* | 1 | /* |
2 | * Linux NET3: GRE over IP protocol decoder. | 2 | * Linux NET3: GRE over IP protocol decoder. |
3 | * | 3 | * |
4 | * Authors: Alexey Kuznetsov (kuznet@ms2.inr.ac.ru) | 4 | * Authors: Alexey Kuznetsov (kuznet@ms2.inr.ac.ru) |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
7 | * modify it under the terms of the GNU General Public License | 7 | * modify it under the terms of the GNU General Public License |
8 | * as published by the Free Software Foundation; either version | 8 | * as published by the Free Software Foundation; either version |
9 | * 2 of the License, or (at your option) any later version. | 9 | * 2 of the License, or (at your option) any later version. |
10 | * | 10 | * |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/config.h> | 13 | #include <linux/config.h> |
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/types.h> | 15 | #include <linux/types.h> |
16 | #include <linux/sched.h> | 16 | #include <linux/sched.h> |
17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
18 | #include <asm/uaccess.h> | 18 | #include <asm/uaccess.h> |
19 | #include <linux/skbuff.h> | 19 | #include <linux/skbuff.h> |
20 | #include <linux/netdevice.h> | 20 | #include <linux/netdevice.h> |
21 | #include <linux/in.h> | 21 | #include <linux/in.h> |
22 | #include <linux/tcp.h> | 22 | #include <linux/tcp.h> |
23 | #include <linux/udp.h> | 23 | #include <linux/udp.h> |
24 | #include <linux/if_arp.h> | 24 | #include <linux/if_arp.h> |
25 | #include <linux/mroute.h> | 25 | #include <linux/mroute.h> |
26 | #include <linux/init.h> | 26 | #include <linux/init.h> |
27 | #include <linux/in6.h> | 27 | #include <linux/in6.h> |
28 | #include <linux/inetdevice.h> | 28 | #include <linux/inetdevice.h> |
29 | #include <linux/igmp.h> | 29 | #include <linux/igmp.h> |
30 | #include <linux/netfilter_ipv4.h> | 30 | #include <linux/netfilter_ipv4.h> |
31 | #include <linux/if_ether.h> | 31 | #include <linux/if_ether.h> |
32 | 32 | ||
33 | #include <net/sock.h> | 33 | #include <net/sock.h> |
34 | #include <net/ip.h> | 34 | #include <net/ip.h> |
35 | #include <net/icmp.h> | 35 | #include <net/icmp.h> |
36 | #include <net/protocol.h> | 36 | #include <net/protocol.h> |
37 | #include <net/ipip.h> | 37 | #include <net/ipip.h> |
38 | #include <net/arp.h> | 38 | #include <net/arp.h> |
39 | #include <net/checksum.h> | 39 | #include <net/checksum.h> |
40 | #include <net/dsfield.h> | 40 | #include <net/dsfield.h> |
41 | #include <net/inet_ecn.h> | 41 | #include <net/inet_ecn.h> |
42 | #include <net/xfrm.h> | 42 | #include <net/xfrm.h> |
43 | 43 | ||
44 | #ifdef CONFIG_IPV6 | 44 | #ifdef CONFIG_IPV6 |
45 | #include <net/ipv6.h> | 45 | #include <net/ipv6.h> |
46 | #include <net/ip6_fib.h> | 46 | #include <net/ip6_fib.h> |
47 | #include <net/ip6_route.h> | 47 | #include <net/ip6_route.h> |
48 | #endif | 48 | #endif |
49 | 49 | ||
50 | /* | 50 | /* |
51 | Problems & solutions | 51 | Problems & solutions |
52 | -------------------- | 52 | -------------------- |
53 | 53 | ||
54 | 1. The most important issue is detecting local dead loops. | 54 | 1. The most important issue is detecting local dead loops. |
55 | They would cause complete host lockup in transmit, which | 55 | They would cause complete host lockup in transmit, which |
56 | would be "resolved" by stack overflow or, if queueing is enabled, | 56 | would be "resolved" by stack overflow or, if queueing is enabled, |
57 | with infinite looping in net_bh. | 57 | with infinite looping in net_bh. |
58 | 58 | ||
59 | We cannot track such dead loops during route installation, | 59 | We cannot track such dead loops during route installation, |
60 | it is infeasible task. The most general solutions would be | 60 | it is infeasible task. The most general solutions would be |
61 | to keep skb->encapsulation counter (sort of local ttl), | 61 | to keep skb->encapsulation counter (sort of local ttl), |
62 | and silently drop packet when it expires. It is the best | 62 | and silently drop packet when it expires. It is the best |
63 | solution, but it supposes maintaing new variable in ALL | 63 | solution, but it supposes maintaing new variable in ALL |
64 | skb, even if no tunneling is used. | 64 | skb, even if no tunneling is used. |
65 | 65 | ||
66 | Current solution: t->recursion lock breaks dead loops. It looks | 66 | Current solution: t->recursion lock breaks dead loops. It looks |
67 | like dev->tbusy flag, but I preferred new variable, because | 67 | like dev->tbusy flag, but I preferred new variable, because |
68 | the semantics is different. One day, when hard_start_xmit | 68 | the semantics is different. One day, when hard_start_xmit |
69 | will be multithreaded we will have to use skb->encapsulation. | 69 | will be multithreaded we will have to use skb->encapsulation. |
70 | 70 | ||
71 | 71 | ||
72 | 72 | ||
73 | 2. Networking dead loops would not kill routers, but would really | 73 | 2. Networking dead loops would not kill routers, but would really |
74 | kill network. IP hop limit plays role of "t->recursion" in this case, | 74 | kill network. IP hop limit plays role of "t->recursion" in this case, |
75 | if we copy it from packet being encapsulated to upper header. | 75 | if we copy it from packet being encapsulated to upper header. |
76 | It is very good solution, but it introduces two problems: | 76 | It is very good solution, but it introduces two problems: |
77 | 77 | ||
78 | - Routing protocols, using packets with ttl=1 (OSPF, RIP2), | 78 | - Routing protocols, using packets with ttl=1 (OSPF, RIP2), |
79 | do not work over tunnels. | 79 | do not work over tunnels. |
80 | - traceroute does not work. I planned to relay ICMP from tunnel, | 80 | - traceroute does not work. I planned to relay ICMP from tunnel, |
81 | so that this problem would be solved and traceroute output | 81 | so that this problem would be solved and traceroute output |
82 | would even more informative. This idea appeared to be wrong: | 82 | would even more informative. This idea appeared to be wrong: |
83 | only Linux complies to rfc1812 now (yes, guys, Linux is the only | 83 | only Linux complies to rfc1812 now (yes, guys, Linux is the only |
84 | true router now :-)), all routers (at least, in neighbourhood of mine) | 84 | true router now :-)), all routers (at least, in neighbourhood of mine) |
85 | return only 8 bytes of payload. It is the end. | 85 | return only 8 bytes of payload. It is the end. |
86 | 86 | ||
87 | Hence, if we want that OSPF worked or traceroute said something reasonable, | 87 | Hence, if we want that OSPF worked or traceroute said something reasonable, |
88 | we should search for another solution. | 88 | we should search for another solution. |
89 | 89 | ||
90 | One of them is to parse packet trying to detect inner encapsulation | 90 | One of them is to parse packet trying to detect inner encapsulation |
91 | made by our node. It is difficult or even impossible, especially, | 91 | made by our node. It is difficult or even impossible, especially, |
92 | taking into account fragmentation. TO be short, tt is not solution at all. | 92 | taking into account fragmentation. TO be short, tt is not solution at all. |
93 | 93 | ||
94 | Current solution: The solution was UNEXPECTEDLY SIMPLE. | 94 | Current solution: The solution was UNEXPECTEDLY SIMPLE. |
95 | We force DF flag on tunnels with preconfigured hop limit, | 95 | We force DF flag on tunnels with preconfigured hop limit, |
96 | that is ALL. :-) Well, it does not remove the problem completely, | 96 | that is ALL. :-) Well, it does not remove the problem completely, |
97 | but exponential growth of network traffic is changed to linear | 97 | but exponential growth of network traffic is changed to linear |
98 | (branches, that exceed pmtu are pruned) and tunnel mtu | 98 | (branches, that exceed pmtu are pruned) and tunnel mtu |
99 | fastly degrades to value <68, where looping stops. | 99 | fastly degrades to value <68, where looping stops. |
100 | Yes, it is not good if there exists a router in the loop, | 100 | Yes, it is not good if there exists a router in the loop, |
101 | which does not force DF, even when encapsulating packets have DF set. | 101 | which does not force DF, even when encapsulating packets have DF set. |
102 | But it is not our problem! Nobody could accuse us, we made | 102 | But it is not our problem! Nobody could accuse us, we made |
103 | all that we could make. Even if it is your gated who injected | 103 | all that we could make. Even if it is your gated who injected |
104 | fatal route to network, even if it were you who configured | 104 | fatal route to network, even if it were you who configured |
105 | fatal static route: you are innocent. :-) | 105 | fatal static route: you are innocent. :-) |
106 | 106 | ||
107 | 107 | ||
108 | 108 | ||
109 | 3. Really, ipv4/ipip.c, ipv4/ip_gre.c and ipv6/sit.c contain | 109 | 3. Really, ipv4/ipip.c, ipv4/ip_gre.c and ipv6/sit.c contain |
110 | practically identical code. It would be good to glue them | 110 | practically identical code. It would be good to glue them |
111 | together, but it is not very evident, how to make them modular. | 111 | together, but it is not very evident, how to make them modular. |
112 | sit is integral part of IPv6, ipip and gre are naturally modular. | 112 | sit is integral part of IPv6, ipip and gre are naturally modular. |
113 | We could extract common parts (hash table, ioctl etc) | 113 | We could extract common parts (hash table, ioctl etc) |
114 | to a separate module (ip_tunnel.c). | 114 | to a separate module (ip_tunnel.c). |
115 | 115 | ||
116 | Alexey Kuznetsov. | 116 | Alexey Kuznetsov. |
117 | */ | 117 | */ |
118 | 118 | ||
119 | static int ipgre_tunnel_init(struct net_device *dev); | 119 | static int ipgre_tunnel_init(struct net_device *dev); |
120 | static void ipgre_tunnel_setup(struct net_device *dev); | 120 | static void ipgre_tunnel_setup(struct net_device *dev); |
121 | 121 | ||
122 | /* Fallback tunnel: no source, no destination, no key, no options */ | 122 | /* Fallback tunnel: no source, no destination, no key, no options */ |
123 | 123 | ||
124 | static int ipgre_fb_tunnel_init(struct net_device *dev); | 124 | static int ipgre_fb_tunnel_init(struct net_device *dev); |
125 | 125 | ||
126 | static struct net_device *ipgre_fb_tunnel_dev; | 126 | static struct net_device *ipgre_fb_tunnel_dev; |
127 | 127 | ||
128 | /* Tunnel hash table */ | 128 | /* Tunnel hash table */ |
129 | 129 | ||
130 | /* | 130 | /* |
131 | 4 hash tables: | 131 | 4 hash tables: |
132 | 132 | ||
133 | 3: (remote,local) | 133 | 3: (remote,local) |
134 | 2: (remote,*) | 134 | 2: (remote,*) |
135 | 1: (*,local) | 135 | 1: (*,local) |
136 | 0: (*,*) | 136 | 0: (*,*) |
137 | 137 | ||
138 | We require exact key match i.e. if a key is present in packet | 138 | We require exact key match i.e. if a key is present in packet |
139 | it will match only tunnel with the same key; if it is not present, | 139 | it will match only tunnel with the same key; if it is not present, |
140 | it will match only keyless tunnel. | 140 | it will match only keyless tunnel. |
141 | 141 | ||
142 | All keysless packets, if not matched configured keyless tunnels | 142 | All keysless packets, if not matched configured keyless tunnels |
143 | will match fallback tunnel. | 143 | will match fallback tunnel. |
144 | */ | 144 | */ |
145 | 145 | ||
146 | #define HASH_SIZE 16 | 146 | #define HASH_SIZE 16 |
147 | #define HASH(addr) ((addr^(addr>>4))&0xF) | 147 | #define HASH(addr) ((addr^(addr>>4))&0xF) |
148 | 148 | ||
149 | static struct ip_tunnel *tunnels[4][HASH_SIZE]; | 149 | static struct ip_tunnel *tunnels[4][HASH_SIZE]; |
150 | 150 | ||
151 | #define tunnels_r_l (tunnels[3]) | 151 | #define tunnels_r_l (tunnels[3]) |
152 | #define tunnels_r (tunnels[2]) | 152 | #define tunnels_r (tunnels[2]) |
153 | #define tunnels_l (tunnels[1]) | 153 | #define tunnels_l (tunnels[1]) |
154 | #define tunnels_wc (tunnels[0]) | 154 | #define tunnels_wc (tunnels[0]) |
155 | 155 | ||
156 | static DEFINE_RWLOCK(ipgre_lock); | 156 | static DEFINE_RWLOCK(ipgre_lock); |
157 | 157 | ||
158 | /* Given src, dst and key, find appropriate for input tunnel. */ | 158 | /* Given src, dst and key, find appropriate for input tunnel. */ |
159 | 159 | ||
160 | static struct ip_tunnel * ipgre_tunnel_lookup(u32 remote, u32 local, u32 key) | 160 | static struct ip_tunnel * ipgre_tunnel_lookup(u32 remote, u32 local, u32 key) |
161 | { | 161 | { |
162 | unsigned h0 = HASH(remote); | 162 | unsigned h0 = HASH(remote); |
163 | unsigned h1 = HASH(key); | 163 | unsigned h1 = HASH(key); |
164 | struct ip_tunnel *t; | 164 | struct ip_tunnel *t; |
165 | 165 | ||
166 | for (t = tunnels_r_l[h0^h1]; t; t = t->next) { | 166 | for (t = tunnels_r_l[h0^h1]; t; t = t->next) { |
167 | if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr) { | 167 | if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr) { |
168 | if (t->parms.i_key == key && (t->dev->flags&IFF_UP)) | 168 | if (t->parms.i_key == key && (t->dev->flags&IFF_UP)) |
169 | return t; | 169 | return t; |
170 | } | 170 | } |
171 | } | 171 | } |
172 | for (t = tunnels_r[h0^h1]; t; t = t->next) { | 172 | for (t = tunnels_r[h0^h1]; t; t = t->next) { |
173 | if (remote == t->parms.iph.daddr) { | 173 | if (remote == t->parms.iph.daddr) { |
174 | if (t->parms.i_key == key && (t->dev->flags&IFF_UP)) | 174 | if (t->parms.i_key == key && (t->dev->flags&IFF_UP)) |
175 | return t; | 175 | return t; |
176 | } | 176 | } |
177 | } | 177 | } |
178 | for (t = tunnels_l[h1]; t; t = t->next) { | 178 | for (t = tunnels_l[h1]; t; t = t->next) { |
179 | if (local == t->parms.iph.saddr || | 179 | if (local == t->parms.iph.saddr || |
180 | (local == t->parms.iph.daddr && MULTICAST(local))) { | 180 | (local == t->parms.iph.daddr && MULTICAST(local))) { |
181 | if (t->parms.i_key == key && (t->dev->flags&IFF_UP)) | 181 | if (t->parms.i_key == key && (t->dev->flags&IFF_UP)) |
182 | return t; | 182 | return t; |
183 | } | 183 | } |
184 | } | 184 | } |
185 | for (t = tunnels_wc[h1]; t; t = t->next) { | 185 | for (t = tunnels_wc[h1]; t; t = t->next) { |
186 | if (t->parms.i_key == key && (t->dev->flags&IFF_UP)) | 186 | if (t->parms.i_key == key && (t->dev->flags&IFF_UP)) |
187 | return t; | 187 | return t; |
188 | } | 188 | } |
189 | 189 | ||
190 | if (ipgre_fb_tunnel_dev->flags&IFF_UP) | 190 | if (ipgre_fb_tunnel_dev->flags&IFF_UP) |
191 | return ipgre_fb_tunnel_dev->priv; | 191 | return ipgre_fb_tunnel_dev->priv; |
192 | return NULL; | 192 | return NULL; |
193 | } | 193 | } |
194 | 194 | ||
195 | static struct ip_tunnel **ipgre_bucket(struct ip_tunnel *t) | 195 | static struct ip_tunnel **ipgre_bucket(struct ip_tunnel *t) |
196 | { | 196 | { |
197 | u32 remote = t->parms.iph.daddr; | 197 | u32 remote = t->parms.iph.daddr; |
198 | u32 local = t->parms.iph.saddr; | 198 | u32 local = t->parms.iph.saddr; |
199 | u32 key = t->parms.i_key; | 199 | u32 key = t->parms.i_key; |
200 | unsigned h = HASH(key); | 200 | unsigned h = HASH(key); |
201 | int prio = 0; | 201 | int prio = 0; |
202 | 202 | ||
203 | if (local) | 203 | if (local) |
204 | prio |= 1; | 204 | prio |= 1; |
205 | if (remote && !MULTICAST(remote)) { | 205 | if (remote && !MULTICAST(remote)) { |
206 | prio |= 2; | 206 | prio |= 2; |
207 | h ^= HASH(remote); | 207 | h ^= HASH(remote); |
208 | } | 208 | } |
209 | 209 | ||
210 | return &tunnels[prio][h]; | 210 | return &tunnels[prio][h]; |
211 | } | 211 | } |
212 | 212 | ||
213 | static void ipgre_tunnel_link(struct ip_tunnel *t) | 213 | static void ipgre_tunnel_link(struct ip_tunnel *t) |
214 | { | 214 | { |
215 | struct ip_tunnel **tp = ipgre_bucket(t); | 215 | struct ip_tunnel **tp = ipgre_bucket(t); |
216 | 216 | ||
217 | t->next = *tp; | 217 | t->next = *tp; |
218 | write_lock_bh(&ipgre_lock); | 218 | write_lock_bh(&ipgre_lock); |
219 | *tp = t; | 219 | *tp = t; |
220 | write_unlock_bh(&ipgre_lock); | 220 | write_unlock_bh(&ipgre_lock); |
221 | } | 221 | } |
222 | 222 | ||
223 | static void ipgre_tunnel_unlink(struct ip_tunnel *t) | 223 | static void ipgre_tunnel_unlink(struct ip_tunnel *t) |
224 | { | 224 | { |
225 | struct ip_tunnel **tp; | 225 | struct ip_tunnel **tp; |
226 | 226 | ||
227 | for (tp = ipgre_bucket(t); *tp; tp = &(*tp)->next) { | 227 | for (tp = ipgre_bucket(t); *tp; tp = &(*tp)->next) { |
228 | if (t == *tp) { | 228 | if (t == *tp) { |
229 | write_lock_bh(&ipgre_lock); | 229 | write_lock_bh(&ipgre_lock); |
230 | *tp = t->next; | 230 | *tp = t->next; |
231 | write_unlock_bh(&ipgre_lock); | 231 | write_unlock_bh(&ipgre_lock); |
232 | break; | 232 | break; |
233 | } | 233 | } |
234 | } | 234 | } |
235 | } | 235 | } |
236 | 236 | ||
237 | static struct ip_tunnel * ipgre_tunnel_locate(struct ip_tunnel_parm *parms, int create) | 237 | static struct ip_tunnel * ipgre_tunnel_locate(struct ip_tunnel_parm *parms, int create) |
238 | { | 238 | { |
239 | u32 remote = parms->iph.daddr; | 239 | u32 remote = parms->iph.daddr; |
240 | u32 local = parms->iph.saddr; | 240 | u32 local = parms->iph.saddr; |
241 | u32 key = parms->i_key; | 241 | u32 key = parms->i_key; |
242 | struct ip_tunnel *t, **tp, *nt; | 242 | struct ip_tunnel *t, **tp, *nt; |
243 | struct net_device *dev; | 243 | struct net_device *dev; |
244 | unsigned h = HASH(key); | 244 | unsigned h = HASH(key); |
245 | int prio = 0; | 245 | int prio = 0; |
246 | char name[IFNAMSIZ]; | 246 | char name[IFNAMSIZ]; |
247 | 247 | ||
248 | if (local) | 248 | if (local) |
249 | prio |= 1; | 249 | prio |= 1; |
250 | if (remote && !MULTICAST(remote)) { | 250 | if (remote && !MULTICAST(remote)) { |
251 | prio |= 2; | 251 | prio |= 2; |
252 | h ^= HASH(remote); | 252 | h ^= HASH(remote); |
253 | } | 253 | } |
254 | for (tp = &tunnels[prio][h]; (t = *tp) != NULL; tp = &t->next) { | 254 | for (tp = &tunnels[prio][h]; (t = *tp) != NULL; tp = &t->next) { |
255 | if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr) { | 255 | if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr) { |
256 | if (key == t->parms.i_key) | 256 | if (key == t->parms.i_key) |
257 | return t; | 257 | return t; |
258 | } | 258 | } |
259 | } | 259 | } |
260 | if (!create) | 260 | if (!create) |
261 | return NULL; | 261 | return NULL; |
262 | 262 | ||
263 | if (parms->name[0]) | 263 | if (parms->name[0]) |
264 | strlcpy(name, parms->name, IFNAMSIZ); | 264 | strlcpy(name, parms->name, IFNAMSIZ); |
265 | else { | 265 | else { |
266 | int i; | 266 | int i; |
267 | for (i=1; i<100; i++) { | 267 | for (i=1; i<100; i++) { |
268 | sprintf(name, "gre%d", i); | 268 | sprintf(name, "gre%d", i); |
269 | if (__dev_get_by_name(name) == NULL) | 269 | if (__dev_get_by_name(name) == NULL) |
270 | break; | 270 | break; |
271 | } | 271 | } |
272 | if (i==100) | 272 | if (i==100) |
273 | goto failed; | 273 | goto failed; |
274 | } | 274 | } |
275 | 275 | ||
276 | dev = alloc_netdev(sizeof(*t), name, ipgre_tunnel_setup); | 276 | dev = alloc_netdev(sizeof(*t), name, ipgre_tunnel_setup); |
277 | if (!dev) | 277 | if (!dev) |
278 | return NULL; | 278 | return NULL; |
279 | 279 | ||
280 | dev->init = ipgre_tunnel_init; | 280 | dev->init = ipgre_tunnel_init; |
281 | nt = dev->priv; | 281 | nt = dev->priv; |
282 | nt->parms = *parms; | 282 | nt->parms = *parms; |
283 | 283 | ||
284 | if (register_netdevice(dev) < 0) { | 284 | if (register_netdevice(dev) < 0) { |
285 | free_netdev(dev); | 285 | free_netdev(dev); |
286 | goto failed; | 286 | goto failed; |
287 | } | 287 | } |
288 | 288 | ||
289 | nt = dev->priv; | 289 | nt = dev->priv; |
290 | nt->parms = *parms; | 290 | nt->parms = *parms; |
291 | 291 | ||
292 | dev_hold(dev); | 292 | dev_hold(dev); |
293 | ipgre_tunnel_link(nt); | 293 | ipgre_tunnel_link(nt); |
294 | return nt; | 294 | return nt; |
295 | 295 | ||
296 | failed: | 296 | failed: |
297 | return NULL; | 297 | return NULL; |
298 | } | 298 | } |
299 | 299 | ||
300 | static void ipgre_tunnel_uninit(struct net_device *dev) | 300 | static void ipgre_tunnel_uninit(struct net_device *dev) |
301 | { | 301 | { |
302 | ipgre_tunnel_unlink((struct ip_tunnel*)dev->priv); | 302 | ipgre_tunnel_unlink((struct ip_tunnel*)dev->priv); |
303 | dev_put(dev); | 303 | dev_put(dev); |
304 | } | 304 | } |
305 | 305 | ||
306 | 306 | ||
307 | static void ipgre_err(struct sk_buff *skb, u32 info) | 307 | static void ipgre_err(struct sk_buff *skb, u32 info) |
308 | { | 308 | { |
309 | #ifndef I_WISH_WORLD_WERE_PERFECT | 309 | #ifndef I_WISH_WORLD_WERE_PERFECT |
310 | 310 | ||
311 | /* It is not :-( All the routers (except for Linux) return only | 311 | /* It is not :-( All the routers (except for Linux) return only |
312 | 8 bytes of packet payload. It means, that precise relaying of | 312 | 8 bytes of packet payload. It means, that precise relaying of |
313 | ICMP in the real Internet is absolutely infeasible. | 313 | ICMP in the real Internet is absolutely infeasible. |
314 | 314 | ||
315 | Moreover, Cisco "wise men" put GRE key to the third word | 315 | Moreover, Cisco "wise men" put GRE key to the third word |
316 | in GRE header. It makes impossible maintaining even soft state for keyed | 316 | in GRE header. It makes impossible maintaining even soft state for keyed |
317 | GRE tunnels with enabled checksum. Tell them "thank you". | 317 | GRE tunnels with enabled checksum. Tell them "thank you". |
318 | 318 | ||
319 | Well, I wonder, rfc1812 was written by Cisco employee, | 319 | Well, I wonder, rfc1812 was written by Cisco employee, |
320 | what the hell these idiots break standrads established | 320 | what the hell these idiots break standrads established |
321 | by themself??? | 321 | by themself??? |
322 | */ | 322 | */ |
323 | 323 | ||
324 | struct iphdr *iph = (struct iphdr*)skb->data; | 324 | struct iphdr *iph = (struct iphdr*)skb->data; |
325 | u16 *p = (u16*)(skb->data+(iph->ihl<<2)); | 325 | u16 *p = (u16*)(skb->data+(iph->ihl<<2)); |
326 | int grehlen = (iph->ihl<<2) + 4; | 326 | int grehlen = (iph->ihl<<2) + 4; |
327 | int type = skb->h.icmph->type; | 327 | int type = skb->h.icmph->type; |
328 | int code = skb->h.icmph->code; | 328 | int code = skb->h.icmph->code; |
329 | struct ip_tunnel *t; | 329 | struct ip_tunnel *t; |
330 | u16 flags; | 330 | u16 flags; |
331 | 331 | ||
332 | flags = p[0]; | 332 | flags = p[0]; |
333 | if (flags&(GRE_CSUM|GRE_KEY|GRE_SEQ|GRE_ROUTING|GRE_VERSION)) { | 333 | if (flags&(GRE_CSUM|GRE_KEY|GRE_SEQ|GRE_ROUTING|GRE_VERSION)) { |
334 | if (flags&(GRE_VERSION|GRE_ROUTING)) | 334 | if (flags&(GRE_VERSION|GRE_ROUTING)) |
335 | return; | 335 | return; |
336 | if (flags&GRE_KEY) { | 336 | if (flags&GRE_KEY) { |
337 | grehlen += 4; | 337 | grehlen += 4; |
338 | if (flags&GRE_CSUM) | 338 | if (flags&GRE_CSUM) |
339 | grehlen += 4; | 339 | grehlen += 4; |
340 | } | 340 | } |
341 | } | 341 | } |
342 | 342 | ||
343 | /* If only 8 bytes returned, keyed message will be dropped here */ | 343 | /* If only 8 bytes returned, keyed message will be dropped here */ |
344 | if (skb_headlen(skb) < grehlen) | 344 | if (skb_headlen(skb) < grehlen) |
345 | return; | 345 | return; |
346 | 346 | ||
347 | switch (type) { | 347 | switch (type) { |
348 | default: | 348 | default: |
349 | case ICMP_PARAMETERPROB: | 349 | case ICMP_PARAMETERPROB: |
350 | return; | 350 | return; |
351 | 351 | ||
352 | case ICMP_DEST_UNREACH: | 352 | case ICMP_DEST_UNREACH: |
353 | switch (code) { | 353 | switch (code) { |
354 | case ICMP_SR_FAILED: | 354 | case ICMP_SR_FAILED: |
355 | case ICMP_PORT_UNREACH: | 355 | case ICMP_PORT_UNREACH: |
356 | /* Impossible event. */ | 356 | /* Impossible event. */ |
357 | return; | 357 | return; |
358 | case ICMP_FRAG_NEEDED: | 358 | case ICMP_FRAG_NEEDED: |
359 | /* Soft state for pmtu is maintained by IP core. */ | 359 | /* Soft state for pmtu is maintained by IP core. */ |
360 | return; | 360 | return; |
361 | default: | 361 | default: |
362 | /* All others are translated to HOST_UNREACH. | 362 | /* All others are translated to HOST_UNREACH. |
363 | rfc2003 contains "deep thoughts" about NET_UNREACH, | 363 | rfc2003 contains "deep thoughts" about NET_UNREACH, |
364 | I believe they are just ether pollution. --ANK | 364 | I believe they are just ether pollution. --ANK |
365 | */ | 365 | */ |
366 | break; | 366 | break; |
367 | } | 367 | } |
368 | break; | 368 | break; |
369 | case ICMP_TIME_EXCEEDED: | 369 | case ICMP_TIME_EXCEEDED: |
370 | if (code != ICMP_EXC_TTL) | 370 | if (code != ICMP_EXC_TTL) |
371 | return; | 371 | return; |
372 | break; | 372 | break; |
373 | } | 373 | } |
374 | 374 | ||
375 | read_lock(&ipgre_lock); | 375 | read_lock(&ipgre_lock); |
376 | t = ipgre_tunnel_lookup(iph->daddr, iph->saddr, (flags&GRE_KEY) ? *(((u32*)p) + (grehlen>>2) - 1) : 0); | 376 | t = ipgre_tunnel_lookup(iph->daddr, iph->saddr, (flags&GRE_KEY) ? *(((u32*)p) + (grehlen>>2) - 1) : 0); |
377 | if (t == NULL || t->parms.iph.daddr == 0 || MULTICAST(t->parms.iph.daddr)) | 377 | if (t == NULL || t->parms.iph.daddr == 0 || MULTICAST(t->parms.iph.daddr)) |
378 | goto out; | 378 | goto out; |
379 | 379 | ||
380 | if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED) | 380 | if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED) |
381 | goto out; | 381 | goto out; |
382 | 382 | ||
383 | if (jiffies - t->err_time < IPTUNNEL_ERR_TIMEO) | 383 | if (jiffies - t->err_time < IPTUNNEL_ERR_TIMEO) |
384 | t->err_count++; | 384 | t->err_count++; |
385 | else | 385 | else |
386 | t->err_count = 1; | 386 | t->err_count = 1; |
387 | t->err_time = jiffies; | 387 | t->err_time = jiffies; |
388 | out: | 388 | out: |
389 | read_unlock(&ipgre_lock); | 389 | read_unlock(&ipgre_lock); |
390 | return; | 390 | return; |
391 | #else | 391 | #else |
392 | struct iphdr *iph = (struct iphdr*)dp; | 392 | struct iphdr *iph = (struct iphdr*)dp; |
393 | struct iphdr *eiph; | 393 | struct iphdr *eiph; |
394 | u16 *p = (u16*)(dp+(iph->ihl<<2)); | 394 | u16 *p = (u16*)(dp+(iph->ihl<<2)); |
395 | int type = skb->h.icmph->type; | 395 | int type = skb->h.icmph->type; |
396 | int code = skb->h.icmph->code; | 396 | int code = skb->h.icmph->code; |
397 | int rel_type = 0; | 397 | int rel_type = 0; |
398 | int rel_code = 0; | 398 | int rel_code = 0; |
399 | int rel_info = 0; | 399 | int rel_info = 0; |
400 | u16 flags; | 400 | u16 flags; |
401 | int grehlen = (iph->ihl<<2) + 4; | 401 | int grehlen = (iph->ihl<<2) + 4; |
402 | struct sk_buff *skb2; | 402 | struct sk_buff *skb2; |
403 | struct flowi fl; | 403 | struct flowi fl; |
404 | struct rtable *rt; | 404 | struct rtable *rt; |
405 | 405 | ||
406 | if (p[1] != htons(ETH_P_IP)) | 406 | if (p[1] != htons(ETH_P_IP)) |
407 | return; | 407 | return; |
408 | 408 | ||
409 | flags = p[0]; | 409 | flags = p[0]; |
410 | if (flags&(GRE_CSUM|GRE_KEY|GRE_SEQ|GRE_ROUTING|GRE_VERSION)) { | 410 | if (flags&(GRE_CSUM|GRE_KEY|GRE_SEQ|GRE_ROUTING|GRE_VERSION)) { |
411 | if (flags&(GRE_VERSION|GRE_ROUTING)) | 411 | if (flags&(GRE_VERSION|GRE_ROUTING)) |
412 | return; | 412 | return; |
413 | if (flags&GRE_CSUM) | 413 | if (flags&GRE_CSUM) |
414 | grehlen += 4; | 414 | grehlen += 4; |
415 | if (flags&GRE_KEY) | 415 | if (flags&GRE_KEY) |
416 | grehlen += 4; | 416 | grehlen += 4; |
417 | if (flags&GRE_SEQ) | 417 | if (flags&GRE_SEQ) |
418 | grehlen += 4; | 418 | grehlen += 4; |
419 | } | 419 | } |
420 | if (len < grehlen + sizeof(struct iphdr)) | 420 | if (len < grehlen + sizeof(struct iphdr)) |
421 | return; | 421 | return; |
422 | eiph = (struct iphdr*)(dp + grehlen); | 422 | eiph = (struct iphdr*)(dp + grehlen); |
423 | 423 | ||
424 | switch (type) { | 424 | switch (type) { |
425 | default: | 425 | default: |
426 | return; | 426 | return; |
427 | case ICMP_PARAMETERPROB: | 427 | case ICMP_PARAMETERPROB: |
428 | if (skb->h.icmph->un.gateway < (iph->ihl<<2)) | 428 | if (skb->h.icmph->un.gateway < (iph->ihl<<2)) |
429 | return; | 429 | return; |
430 | 430 | ||
431 | /* So... This guy found something strange INSIDE encapsulated | 431 | /* So... This guy found something strange INSIDE encapsulated |
432 | packet. Well, he is fool, but what can we do ? | 432 | packet. Well, he is fool, but what can we do ? |
433 | */ | 433 | */ |
434 | rel_type = ICMP_PARAMETERPROB; | 434 | rel_type = ICMP_PARAMETERPROB; |
435 | rel_info = skb->h.icmph->un.gateway - grehlen; | 435 | rel_info = skb->h.icmph->un.gateway - grehlen; |
436 | break; | 436 | break; |
437 | 437 | ||
438 | case ICMP_DEST_UNREACH: | 438 | case ICMP_DEST_UNREACH: |
439 | switch (code) { | 439 | switch (code) { |
440 | case ICMP_SR_FAILED: | 440 | case ICMP_SR_FAILED: |
441 | case ICMP_PORT_UNREACH: | 441 | case ICMP_PORT_UNREACH: |
442 | /* Impossible event. */ | 442 | /* Impossible event. */ |
443 | return; | 443 | return; |
444 | case ICMP_FRAG_NEEDED: | 444 | case ICMP_FRAG_NEEDED: |
445 | /* And it is the only really necessary thing :-) */ | 445 | /* And it is the only really necessary thing :-) */ |
446 | rel_info = ntohs(skb->h.icmph->un.frag.mtu); | 446 | rel_info = ntohs(skb->h.icmph->un.frag.mtu); |
447 | if (rel_info < grehlen+68) | 447 | if (rel_info < grehlen+68) |
448 | return; | 448 | return; |
449 | rel_info -= grehlen; | 449 | rel_info -= grehlen; |
450 | /* BSD 4.2 MORE DOES NOT EXIST IN NATURE. */ | 450 | /* BSD 4.2 MORE DOES NOT EXIST IN NATURE. */ |
451 | if (rel_info > ntohs(eiph->tot_len)) | 451 | if (rel_info > ntohs(eiph->tot_len)) |
452 | return; | 452 | return; |
453 | break; | 453 | break; |
454 | default: | 454 | default: |
455 | /* All others are translated to HOST_UNREACH. | 455 | /* All others are translated to HOST_UNREACH. |
456 | rfc2003 contains "deep thoughts" about NET_UNREACH, | 456 | rfc2003 contains "deep thoughts" about NET_UNREACH, |
457 | I believe, it is just ether pollution. --ANK | 457 | I believe, it is just ether pollution. --ANK |
458 | */ | 458 | */ |
459 | rel_type = ICMP_DEST_UNREACH; | 459 | rel_type = ICMP_DEST_UNREACH; |
460 | rel_code = ICMP_HOST_UNREACH; | 460 | rel_code = ICMP_HOST_UNREACH; |
461 | break; | 461 | break; |
462 | } | 462 | } |
463 | break; | 463 | break; |
464 | case ICMP_TIME_EXCEEDED: | 464 | case ICMP_TIME_EXCEEDED: |
465 | if (code != ICMP_EXC_TTL) | 465 | if (code != ICMP_EXC_TTL) |
466 | return; | 466 | return; |
467 | break; | 467 | break; |
468 | } | 468 | } |
469 | 469 | ||
470 | /* Prepare fake skb to feed it to icmp_send */ | 470 | /* Prepare fake skb to feed it to icmp_send */ |
471 | skb2 = skb_clone(skb, GFP_ATOMIC); | 471 | skb2 = skb_clone(skb, GFP_ATOMIC); |
472 | if (skb2 == NULL) | 472 | if (skb2 == NULL) |
473 | return; | 473 | return; |
474 | dst_release(skb2->dst); | 474 | dst_release(skb2->dst); |
475 | skb2->dst = NULL; | 475 | skb2->dst = NULL; |
476 | skb_pull(skb2, skb->data - (u8*)eiph); | 476 | skb_pull(skb2, skb->data - (u8*)eiph); |
477 | skb2->nh.raw = skb2->data; | 477 | skb2->nh.raw = skb2->data; |
478 | 478 | ||
479 | /* Try to guess incoming interface */ | 479 | /* Try to guess incoming interface */ |
480 | memset(&fl, 0, sizeof(fl)); | 480 | memset(&fl, 0, sizeof(fl)); |
481 | fl.fl4_dst = eiph->saddr; | 481 | fl.fl4_dst = eiph->saddr; |
482 | fl.fl4_tos = RT_TOS(eiph->tos); | 482 | fl.fl4_tos = RT_TOS(eiph->tos); |
483 | fl.proto = IPPROTO_GRE; | 483 | fl.proto = IPPROTO_GRE; |
484 | if (ip_route_output_key(&rt, &fl)) { | 484 | if (ip_route_output_key(&rt, &fl)) { |
485 | kfree_skb(skb2); | 485 | kfree_skb(skb2); |
486 | return; | 486 | return; |
487 | } | 487 | } |
488 | skb2->dev = rt->u.dst.dev; | 488 | skb2->dev = rt->u.dst.dev; |
489 | 489 | ||
490 | /* route "incoming" packet */ | 490 | /* route "incoming" packet */ |
491 | if (rt->rt_flags&RTCF_LOCAL) { | 491 | if (rt->rt_flags&RTCF_LOCAL) { |
492 | ip_rt_put(rt); | 492 | ip_rt_put(rt); |
493 | rt = NULL; | 493 | rt = NULL; |
494 | fl.fl4_dst = eiph->daddr; | 494 | fl.fl4_dst = eiph->daddr; |
495 | fl.fl4_src = eiph->saddr; | 495 | fl.fl4_src = eiph->saddr; |
496 | fl.fl4_tos = eiph->tos; | 496 | fl.fl4_tos = eiph->tos; |
497 | if (ip_route_output_key(&rt, &fl) || | 497 | if (ip_route_output_key(&rt, &fl) || |
498 | rt->u.dst.dev->type != ARPHRD_IPGRE) { | 498 | rt->u.dst.dev->type != ARPHRD_IPGRE) { |
499 | ip_rt_put(rt); | 499 | ip_rt_put(rt); |
500 | kfree_skb(skb2); | 500 | kfree_skb(skb2); |
501 | return; | 501 | return; |
502 | } | 502 | } |
503 | } else { | 503 | } else { |
504 | ip_rt_put(rt); | 504 | ip_rt_put(rt); |
505 | if (ip_route_input(skb2, eiph->daddr, eiph->saddr, eiph->tos, skb2->dev) || | 505 | if (ip_route_input(skb2, eiph->daddr, eiph->saddr, eiph->tos, skb2->dev) || |
506 | skb2->dst->dev->type != ARPHRD_IPGRE) { | 506 | skb2->dst->dev->type != ARPHRD_IPGRE) { |
507 | kfree_skb(skb2); | 507 | kfree_skb(skb2); |
508 | return; | 508 | return; |
509 | } | 509 | } |
510 | } | 510 | } |
511 | 511 | ||
512 | /* change mtu on this route */ | 512 | /* change mtu on this route */ |
513 | if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) { | 513 | if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) { |
514 | if (rel_info > dst_mtu(skb2->dst)) { | 514 | if (rel_info > dst_mtu(skb2->dst)) { |
515 | kfree_skb(skb2); | 515 | kfree_skb(skb2); |
516 | return; | 516 | return; |
517 | } | 517 | } |
518 | skb2->dst->ops->update_pmtu(skb2->dst, rel_info); | 518 | skb2->dst->ops->update_pmtu(skb2->dst, rel_info); |
519 | rel_info = htonl(rel_info); | 519 | rel_info = htonl(rel_info); |
520 | } else if (type == ICMP_TIME_EXCEEDED) { | 520 | } else if (type == ICMP_TIME_EXCEEDED) { |
521 | struct ip_tunnel *t = (struct ip_tunnel*)skb2->dev->priv; | 521 | struct ip_tunnel *t = (struct ip_tunnel*)skb2->dev->priv; |
522 | if (t->parms.iph.ttl) { | 522 | if (t->parms.iph.ttl) { |
523 | rel_type = ICMP_DEST_UNREACH; | 523 | rel_type = ICMP_DEST_UNREACH; |
524 | rel_code = ICMP_HOST_UNREACH; | 524 | rel_code = ICMP_HOST_UNREACH; |
525 | } | 525 | } |
526 | } | 526 | } |
527 | 527 | ||
528 | icmp_send(skb2, rel_type, rel_code, rel_info); | 528 | icmp_send(skb2, rel_type, rel_code, rel_info); |
529 | kfree_skb(skb2); | 529 | kfree_skb(skb2); |
530 | #endif | 530 | #endif |
531 | } | 531 | } |
532 | 532 | ||
533 | static inline void ipgre_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb) | 533 | static inline void ipgre_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb) |
534 | { | 534 | { |
535 | if (INET_ECN_is_ce(iph->tos)) { | 535 | if (INET_ECN_is_ce(iph->tos)) { |
536 | if (skb->protocol == htons(ETH_P_IP)) { | 536 | if (skb->protocol == htons(ETH_P_IP)) { |
537 | IP_ECN_set_ce(skb->nh.iph); | 537 | IP_ECN_set_ce(skb->nh.iph); |
538 | } else if (skb->protocol == htons(ETH_P_IPV6)) { | 538 | } else if (skb->protocol == htons(ETH_P_IPV6)) { |
539 | IP6_ECN_set_ce(skb->nh.ipv6h); | 539 | IP6_ECN_set_ce(skb->nh.ipv6h); |
540 | } | 540 | } |
541 | } | 541 | } |
542 | } | 542 | } |
543 | 543 | ||
544 | static inline u8 | 544 | static inline u8 |
545 | ipgre_ecn_encapsulate(u8 tos, struct iphdr *old_iph, struct sk_buff *skb) | 545 | ipgre_ecn_encapsulate(u8 tos, struct iphdr *old_iph, struct sk_buff *skb) |
546 | { | 546 | { |
547 | u8 inner = 0; | 547 | u8 inner = 0; |
548 | if (skb->protocol == htons(ETH_P_IP)) | 548 | if (skb->protocol == htons(ETH_P_IP)) |
549 | inner = old_iph->tos; | 549 | inner = old_iph->tos; |
550 | else if (skb->protocol == htons(ETH_P_IPV6)) | 550 | else if (skb->protocol == htons(ETH_P_IPV6)) |
551 | inner = ipv6_get_dsfield((struct ipv6hdr *)old_iph); | 551 | inner = ipv6_get_dsfield((struct ipv6hdr *)old_iph); |
552 | return INET_ECN_encapsulate(tos, inner); | 552 | return INET_ECN_encapsulate(tos, inner); |
553 | } | 553 | } |
554 | 554 | ||
555 | static int ipgre_rcv(struct sk_buff *skb) | 555 | static int ipgre_rcv(struct sk_buff *skb) |
556 | { | 556 | { |
557 | struct iphdr *iph; | 557 | struct iphdr *iph; |
558 | u8 *h; | 558 | u8 *h; |
559 | u16 flags; | 559 | u16 flags; |
560 | u16 csum = 0; | 560 | u16 csum = 0; |
561 | u32 key = 0; | 561 | u32 key = 0; |
562 | u32 seqno = 0; | 562 | u32 seqno = 0; |
563 | struct ip_tunnel *tunnel; | 563 | struct ip_tunnel *tunnel; |
564 | int offset = 4; | 564 | int offset = 4; |
565 | 565 | ||
566 | if (!pskb_may_pull(skb, 16)) | 566 | if (!pskb_may_pull(skb, 16)) |
567 | goto drop_nolock; | 567 | goto drop_nolock; |
568 | 568 | ||
569 | iph = skb->nh.iph; | 569 | iph = skb->nh.iph; |
570 | h = skb->data; | 570 | h = skb->data; |
571 | flags = *(u16*)h; | 571 | flags = *(u16*)h; |
572 | 572 | ||
573 | if (flags&(GRE_CSUM|GRE_KEY|GRE_ROUTING|GRE_SEQ|GRE_VERSION)) { | 573 | if (flags&(GRE_CSUM|GRE_KEY|GRE_ROUTING|GRE_SEQ|GRE_VERSION)) { |
574 | /* - Version must be 0. | 574 | /* - Version must be 0. |
575 | - We do not support routing headers. | 575 | - We do not support routing headers. |
576 | */ | 576 | */ |
577 | if (flags&(GRE_VERSION|GRE_ROUTING)) | 577 | if (flags&(GRE_VERSION|GRE_ROUTING)) |
578 | goto drop_nolock; | 578 | goto drop_nolock; |
579 | 579 | ||
580 | if (flags&GRE_CSUM) { | 580 | if (flags&GRE_CSUM) { |
581 | switch (skb->ip_summed) { | 581 | switch (skb->ip_summed) { |
582 | case CHECKSUM_HW: | 582 | case CHECKSUM_HW: |
583 | csum = (u16)csum_fold(skb->csum); | 583 | csum = (u16)csum_fold(skb->csum); |
584 | if (!csum) | 584 | if (!csum) |
585 | break; | 585 | break; |
586 | /* fall through */ | 586 | /* fall through */ |
587 | case CHECKSUM_NONE: | 587 | case CHECKSUM_NONE: |
588 | skb->csum = 0; | 588 | skb->csum = 0; |
589 | csum = __skb_checksum_complete(skb); | 589 | csum = __skb_checksum_complete(skb); |
590 | skb->ip_summed = CHECKSUM_HW; | 590 | skb->ip_summed = CHECKSUM_HW; |
591 | } | 591 | } |
592 | offset += 4; | 592 | offset += 4; |
593 | } | 593 | } |
594 | if (flags&GRE_KEY) { | 594 | if (flags&GRE_KEY) { |
595 | key = *(u32*)(h + offset); | 595 | key = *(u32*)(h + offset); |
596 | offset += 4; | 596 | offset += 4; |
597 | } | 597 | } |
598 | if (flags&GRE_SEQ) { | 598 | if (flags&GRE_SEQ) { |
599 | seqno = ntohl(*(u32*)(h + offset)); | 599 | seqno = ntohl(*(u32*)(h + offset)); |
600 | offset += 4; | 600 | offset += 4; |
601 | } | 601 | } |
602 | } | 602 | } |
603 | 603 | ||
604 | read_lock(&ipgre_lock); | 604 | read_lock(&ipgre_lock); |
605 | if ((tunnel = ipgre_tunnel_lookup(iph->saddr, iph->daddr, key)) != NULL) { | 605 | if ((tunnel = ipgre_tunnel_lookup(iph->saddr, iph->daddr, key)) != NULL) { |
606 | secpath_reset(skb); | 606 | secpath_reset(skb); |
607 | 607 | ||
608 | skb->protocol = *(u16*)(h + 2); | 608 | skb->protocol = *(u16*)(h + 2); |
609 | /* WCCP version 1 and 2 protocol decoding. | 609 | /* WCCP version 1 and 2 protocol decoding. |
610 | * - Change protocol to IP | 610 | * - Change protocol to IP |
611 | * - When dealing with WCCPv2, Skip extra 4 bytes in GRE header | 611 | * - When dealing with WCCPv2, Skip extra 4 bytes in GRE header |
612 | */ | 612 | */ |
613 | if (flags == 0 && | 613 | if (flags == 0 && |
614 | skb->protocol == __constant_htons(ETH_P_WCCP)) { | 614 | skb->protocol == __constant_htons(ETH_P_WCCP)) { |
615 | skb->protocol = __constant_htons(ETH_P_IP); | 615 | skb->protocol = __constant_htons(ETH_P_IP); |
616 | if ((*(h + offset) & 0xF0) != 0x40) | 616 | if ((*(h + offset) & 0xF0) != 0x40) |
617 | offset += 4; | 617 | offset += 4; |
618 | } | 618 | } |
619 | 619 | ||
620 | skb->mac.raw = skb->nh.raw; | 620 | skb->mac.raw = skb->nh.raw; |
621 | skb->nh.raw = __pskb_pull(skb, offset); | 621 | skb->nh.raw = __pskb_pull(skb, offset); |
622 | skb_postpull_rcsum(skb, skb->h.raw, offset); | 622 | skb_postpull_rcsum(skb, skb->h.raw, offset); |
623 | memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options)); | 623 | memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options)); |
624 | skb->pkt_type = PACKET_HOST; | 624 | skb->pkt_type = PACKET_HOST; |
625 | #ifdef CONFIG_NET_IPGRE_BROADCAST | 625 | #ifdef CONFIG_NET_IPGRE_BROADCAST |
626 | if (MULTICAST(iph->daddr)) { | 626 | if (MULTICAST(iph->daddr)) { |
627 | /* Looped back packet, drop it! */ | 627 | /* Looped back packet, drop it! */ |
628 | if (((struct rtable*)skb->dst)->fl.iif == 0) | 628 | if (((struct rtable*)skb->dst)->fl.iif == 0) |
629 | goto drop; | 629 | goto drop; |
630 | tunnel->stat.multicast++; | 630 | tunnel->stat.multicast++; |
631 | skb->pkt_type = PACKET_BROADCAST; | 631 | skb->pkt_type = PACKET_BROADCAST; |
632 | } | 632 | } |
633 | #endif | 633 | #endif |
634 | 634 | ||
635 | if (((flags&GRE_CSUM) && csum) || | 635 | if (((flags&GRE_CSUM) && csum) || |
636 | (!(flags&GRE_CSUM) && tunnel->parms.i_flags&GRE_CSUM)) { | 636 | (!(flags&GRE_CSUM) && tunnel->parms.i_flags&GRE_CSUM)) { |
637 | tunnel->stat.rx_crc_errors++; | 637 | tunnel->stat.rx_crc_errors++; |
638 | tunnel->stat.rx_errors++; | 638 | tunnel->stat.rx_errors++; |
639 | goto drop; | 639 | goto drop; |
640 | } | 640 | } |
641 | if (tunnel->parms.i_flags&GRE_SEQ) { | 641 | if (tunnel->parms.i_flags&GRE_SEQ) { |
642 | if (!(flags&GRE_SEQ) || | 642 | if (!(flags&GRE_SEQ) || |
643 | (tunnel->i_seqno && (s32)(seqno - tunnel->i_seqno) < 0)) { | 643 | (tunnel->i_seqno && (s32)(seqno - tunnel->i_seqno) < 0)) { |
644 | tunnel->stat.rx_fifo_errors++; | 644 | tunnel->stat.rx_fifo_errors++; |
645 | tunnel->stat.rx_errors++; | 645 | tunnel->stat.rx_errors++; |
646 | goto drop; | 646 | goto drop; |
647 | } | 647 | } |
648 | tunnel->i_seqno = seqno + 1; | 648 | tunnel->i_seqno = seqno + 1; |
649 | } | 649 | } |
650 | tunnel->stat.rx_packets++; | 650 | tunnel->stat.rx_packets++; |
651 | tunnel->stat.rx_bytes += skb->len; | 651 | tunnel->stat.rx_bytes += skb->len; |
652 | skb->dev = tunnel->dev; | 652 | skb->dev = tunnel->dev; |
653 | dst_release(skb->dst); | 653 | dst_release(skb->dst); |
654 | skb->dst = NULL; | 654 | skb->dst = NULL; |
655 | nf_reset(skb); | 655 | nf_reset(skb); |
656 | ipgre_ecn_decapsulate(iph, skb); | 656 | ipgre_ecn_decapsulate(iph, skb); |
657 | netif_rx(skb); | 657 | netif_rx(skb); |
658 | read_unlock(&ipgre_lock); | 658 | read_unlock(&ipgre_lock); |
659 | return(0); | 659 | return(0); |
660 | } | 660 | } |
661 | icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, 0); | 661 | icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, 0); |
662 | 662 | ||
663 | drop: | 663 | drop: |
664 | read_unlock(&ipgre_lock); | 664 | read_unlock(&ipgre_lock); |
665 | drop_nolock: | 665 | drop_nolock: |
666 | kfree_skb(skb); | 666 | kfree_skb(skb); |
667 | return(0); | 667 | return(0); |
668 | } | 668 | } |
669 | 669 | ||
670 | static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | 670 | static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) |
671 | { | 671 | { |
672 | struct ip_tunnel *tunnel = (struct ip_tunnel*)dev->priv; | 672 | struct ip_tunnel *tunnel = (struct ip_tunnel*)dev->priv; |
673 | struct net_device_stats *stats = &tunnel->stat; | 673 | struct net_device_stats *stats = &tunnel->stat; |
674 | struct iphdr *old_iph = skb->nh.iph; | 674 | struct iphdr *old_iph = skb->nh.iph; |
675 | struct iphdr *tiph; | 675 | struct iphdr *tiph; |
676 | u8 tos; | 676 | u8 tos; |
677 | u16 df; | 677 | u16 df; |
678 | struct rtable *rt; /* Route to the other host */ | 678 | struct rtable *rt; /* Route to the other host */ |
679 | struct net_device *tdev; /* Device to other host */ | 679 | struct net_device *tdev; /* Device to other host */ |
680 | struct iphdr *iph; /* Our new IP header */ | 680 | struct iphdr *iph; /* Our new IP header */ |
681 | int max_headroom; /* The extra header space needed */ | 681 | int max_headroom; /* The extra header space needed */ |
682 | int gre_hlen; | 682 | int gre_hlen; |
683 | u32 dst; | 683 | u32 dst; |
684 | int mtu; | 684 | int mtu; |
685 | 685 | ||
686 | if (tunnel->recursion++) { | 686 | if (tunnel->recursion++) { |
687 | tunnel->stat.collisions++; | 687 | tunnel->stat.collisions++; |
688 | goto tx_error; | 688 | goto tx_error; |
689 | } | 689 | } |
690 | 690 | ||
691 | if (dev->hard_header) { | 691 | if (dev->hard_header) { |
692 | gre_hlen = 0; | 692 | gre_hlen = 0; |
693 | tiph = (struct iphdr*)skb->data; | 693 | tiph = (struct iphdr*)skb->data; |
694 | } else { | 694 | } else { |
695 | gre_hlen = tunnel->hlen; | 695 | gre_hlen = tunnel->hlen; |
696 | tiph = &tunnel->parms.iph; | 696 | tiph = &tunnel->parms.iph; |
697 | } | 697 | } |
698 | 698 | ||
699 | if ((dst = tiph->daddr) == 0) { | 699 | if ((dst = tiph->daddr) == 0) { |
700 | /* NBMA tunnel */ | 700 | /* NBMA tunnel */ |
701 | 701 | ||
702 | if (skb->dst == NULL) { | 702 | if (skb->dst == NULL) { |
703 | tunnel->stat.tx_fifo_errors++; | 703 | tunnel->stat.tx_fifo_errors++; |
704 | goto tx_error; | 704 | goto tx_error; |
705 | } | 705 | } |
706 | 706 | ||
707 | if (skb->protocol == htons(ETH_P_IP)) { | 707 | if (skb->protocol == htons(ETH_P_IP)) { |
708 | rt = (struct rtable*)skb->dst; | 708 | rt = (struct rtable*)skb->dst; |
709 | if ((dst = rt->rt_gateway) == 0) | 709 | if ((dst = rt->rt_gateway) == 0) |
710 | goto tx_error_icmp; | 710 | goto tx_error_icmp; |
711 | } | 711 | } |
712 | #ifdef CONFIG_IPV6 | 712 | #ifdef CONFIG_IPV6 |
713 | else if (skb->protocol == htons(ETH_P_IPV6)) { | 713 | else if (skb->protocol == htons(ETH_P_IPV6)) { |
714 | struct in6_addr *addr6; | 714 | struct in6_addr *addr6; |
715 | int addr_type; | 715 | int addr_type; |
716 | struct neighbour *neigh = skb->dst->neighbour; | 716 | struct neighbour *neigh = skb->dst->neighbour; |
717 | 717 | ||
718 | if (neigh == NULL) | 718 | if (neigh == NULL) |
719 | goto tx_error; | 719 | goto tx_error; |
720 | 720 | ||
721 | addr6 = (struct in6_addr*)&neigh->primary_key; | 721 | addr6 = (struct in6_addr*)&neigh->primary_key; |
722 | addr_type = ipv6_addr_type(addr6); | 722 | addr_type = ipv6_addr_type(addr6); |
723 | 723 | ||
724 | if (addr_type == IPV6_ADDR_ANY) { | 724 | if (addr_type == IPV6_ADDR_ANY) { |
725 | addr6 = &skb->nh.ipv6h->daddr; | 725 | addr6 = &skb->nh.ipv6h->daddr; |
726 | addr_type = ipv6_addr_type(addr6); | 726 | addr_type = ipv6_addr_type(addr6); |
727 | } | 727 | } |
728 | 728 | ||
729 | if ((addr_type & IPV6_ADDR_COMPATv4) == 0) | 729 | if ((addr_type & IPV6_ADDR_COMPATv4) == 0) |
730 | goto tx_error_icmp; | 730 | goto tx_error_icmp; |
731 | 731 | ||
732 | dst = addr6->s6_addr32[3]; | 732 | dst = addr6->s6_addr32[3]; |
733 | } | 733 | } |
734 | #endif | 734 | #endif |
735 | else | 735 | else |
736 | goto tx_error; | 736 | goto tx_error; |
737 | } | 737 | } |
738 | 738 | ||
739 | tos = tiph->tos; | 739 | tos = tiph->tos; |
740 | if (tos&1) { | 740 | if (tos&1) { |
741 | if (skb->protocol == htons(ETH_P_IP)) | 741 | if (skb->protocol == htons(ETH_P_IP)) |
742 | tos = old_iph->tos; | 742 | tos = old_iph->tos; |
743 | tos &= ~1; | 743 | tos &= ~1; |
744 | } | 744 | } |
745 | 745 | ||
746 | { | 746 | { |
747 | struct flowi fl = { .oif = tunnel->parms.link, | 747 | struct flowi fl = { .oif = tunnel->parms.link, |
748 | .nl_u = { .ip4_u = | 748 | .nl_u = { .ip4_u = |
749 | { .daddr = dst, | 749 | { .daddr = dst, |
750 | .saddr = tiph->saddr, | 750 | .saddr = tiph->saddr, |
751 | .tos = RT_TOS(tos) } }, | 751 | .tos = RT_TOS(tos) } }, |
752 | .proto = IPPROTO_GRE }; | 752 | .proto = IPPROTO_GRE }; |
753 | if (ip_route_output_key(&rt, &fl)) { | 753 | if (ip_route_output_key(&rt, &fl)) { |
754 | tunnel->stat.tx_carrier_errors++; | 754 | tunnel->stat.tx_carrier_errors++; |
755 | goto tx_error; | 755 | goto tx_error; |
756 | } | 756 | } |
757 | } | 757 | } |
758 | tdev = rt->u.dst.dev; | 758 | tdev = rt->u.dst.dev; |
759 | 759 | ||
760 | if (tdev == dev) { | 760 | if (tdev == dev) { |
761 | ip_rt_put(rt); | 761 | ip_rt_put(rt); |
762 | tunnel->stat.collisions++; | 762 | tunnel->stat.collisions++; |
763 | goto tx_error; | 763 | goto tx_error; |
764 | } | 764 | } |
765 | 765 | ||
766 | df = tiph->frag_off; | 766 | df = tiph->frag_off; |
767 | if (df) | 767 | if (df) |
768 | mtu = dst_mtu(&rt->u.dst) - tunnel->hlen; | 768 | mtu = dst_mtu(&rt->u.dst) - tunnel->hlen; |
769 | else | 769 | else |
770 | mtu = skb->dst ? dst_mtu(skb->dst) : dev->mtu; | 770 | mtu = skb->dst ? dst_mtu(skb->dst) : dev->mtu; |
771 | 771 | ||
772 | if (skb->dst) | 772 | if (skb->dst) |
773 | skb->dst->ops->update_pmtu(skb->dst, mtu); | 773 | skb->dst->ops->update_pmtu(skb->dst, mtu); |
774 | 774 | ||
775 | if (skb->protocol == htons(ETH_P_IP)) { | 775 | if (skb->protocol == htons(ETH_P_IP)) { |
776 | df |= (old_iph->frag_off&htons(IP_DF)); | 776 | df |= (old_iph->frag_off&htons(IP_DF)); |
777 | 777 | ||
778 | if ((old_iph->frag_off&htons(IP_DF)) && | 778 | if ((old_iph->frag_off&htons(IP_DF)) && |
779 | mtu < ntohs(old_iph->tot_len)) { | 779 | mtu < ntohs(old_iph->tot_len)) { |
780 | icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu)); | 780 | icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu)); |
781 | ip_rt_put(rt); | 781 | ip_rt_put(rt); |
782 | goto tx_error; | 782 | goto tx_error; |
783 | } | 783 | } |
784 | } | 784 | } |
785 | #ifdef CONFIG_IPV6 | 785 | #ifdef CONFIG_IPV6 |
786 | else if (skb->protocol == htons(ETH_P_IPV6)) { | 786 | else if (skb->protocol == htons(ETH_P_IPV6)) { |
787 | struct rt6_info *rt6 = (struct rt6_info*)skb->dst; | 787 | struct rt6_info *rt6 = (struct rt6_info*)skb->dst; |
788 | 788 | ||
789 | if (rt6 && mtu < dst_mtu(skb->dst) && mtu >= IPV6_MIN_MTU) { | 789 | if (rt6 && mtu < dst_mtu(skb->dst) && mtu >= IPV6_MIN_MTU) { |
790 | if ((tunnel->parms.iph.daddr && !MULTICAST(tunnel->parms.iph.daddr)) || | 790 | if ((tunnel->parms.iph.daddr && !MULTICAST(tunnel->parms.iph.daddr)) || |
791 | rt6->rt6i_dst.plen == 128) { | 791 | rt6->rt6i_dst.plen == 128) { |
792 | rt6->rt6i_flags |= RTF_MODIFIED; | 792 | rt6->rt6i_flags |= RTF_MODIFIED; |
793 | skb->dst->metrics[RTAX_MTU-1] = mtu; | 793 | skb->dst->metrics[RTAX_MTU-1] = mtu; |
794 | } | 794 | } |
795 | } | 795 | } |
796 | 796 | ||
797 | if (mtu >= IPV6_MIN_MTU && mtu < skb->len - tunnel->hlen + gre_hlen) { | 797 | if (mtu >= IPV6_MIN_MTU && mtu < skb->len - tunnel->hlen + gre_hlen) { |
798 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, dev); | 798 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, dev); |
799 | ip_rt_put(rt); | 799 | ip_rt_put(rt); |
800 | goto tx_error; | 800 | goto tx_error; |
801 | } | 801 | } |
802 | } | 802 | } |
803 | #endif | 803 | #endif |
804 | 804 | ||
805 | if (tunnel->err_count > 0) { | 805 | if (tunnel->err_count > 0) { |
806 | if (jiffies - tunnel->err_time < IPTUNNEL_ERR_TIMEO) { | 806 | if (jiffies - tunnel->err_time < IPTUNNEL_ERR_TIMEO) { |
807 | tunnel->err_count--; | 807 | tunnel->err_count--; |
808 | 808 | ||
809 | dst_link_failure(skb); | 809 | dst_link_failure(skb); |
810 | } else | 810 | } else |
811 | tunnel->err_count = 0; | 811 | tunnel->err_count = 0; |
812 | } | 812 | } |
813 | 813 | ||
814 | max_headroom = LL_RESERVED_SPACE(tdev) + gre_hlen; | 814 | max_headroom = LL_RESERVED_SPACE(tdev) + gre_hlen; |
815 | 815 | ||
816 | if (skb_headroom(skb) < max_headroom || skb_cloned(skb) || skb_shared(skb)) { | 816 | if (skb_headroom(skb) < max_headroom || skb_cloned(skb) || skb_shared(skb)) { |
817 | struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom); | 817 | struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom); |
818 | if (!new_skb) { | 818 | if (!new_skb) { |
819 | ip_rt_put(rt); | 819 | ip_rt_put(rt); |
820 | stats->tx_dropped++; | 820 | stats->tx_dropped++; |
821 | dev_kfree_skb(skb); | 821 | dev_kfree_skb(skb); |
822 | tunnel->recursion--; | 822 | tunnel->recursion--; |
823 | return 0; | 823 | return 0; |
824 | } | 824 | } |
825 | if (skb->sk) | 825 | if (skb->sk) |
826 | skb_set_owner_w(new_skb, skb->sk); | 826 | skb_set_owner_w(new_skb, skb->sk); |
827 | dev_kfree_skb(skb); | 827 | dev_kfree_skb(skb); |
828 | skb = new_skb; | 828 | skb = new_skb; |
829 | old_iph = skb->nh.iph; | 829 | old_iph = skb->nh.iph; |
830 | } | 830 | } |
831 | 831 | ||
832 | skb->h.raw = skb->nh.raw; | 832 | skb->h.raw = skb->nh.raw; |
833 | skb->nh.raw = skb_push(skb, gre_hlen); | 833 | skb->nh.raw = skb_push(skb, gre_hlen); |
834 | memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); | 834 | memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); |
835 | IPCB(skb)->flags &= ~IPSKB_XFRM_TUNNEL_SIZE; | ||
835 | dst_release(skb->dst); | 836 | dst_release(skb->dst); |
836 | skb->dst = &rt->u.dst; | 837 | skb->dst = &rt->u.dst; |
837 | 838 | ||
838 | /* | 839 | /* |
839 | * Push down and install the IPIP header. | 840 | * Push down and install the IPIP header. |
840 | */ | 841 | */ |
841 | 842 | ||
842 | iph = skb->nh.iph; | 843 | iph = skb->nh.iph; |
843 | iph->version = 4; | 844 | iph->version = 4; |
844 | iph->ihl = sizeof(struct iphdr) >> 2; | 845 | iph->ihl = sizeof(struct iphdr) >> 2; |
845 | iph->frag_off = df; | 846 | iph->frag_off = df; |
846 | iph->protocol = IPPROTO_GRE; | 847 | iph->protocol = IPPROTO_GRE; |
847 | iph->tos = ipgre_ecn_encapsulate(tos, old_iph, skb); | 848 | iph->tos = ipgre_ecn_encapsulate(tos, old_iph, skb); |
848 | iph->daddr = rt->rt_dst; | 849 | iph->daddr = rt->rt_dst; |
849 | iph->saddr = rt->rt_src; | 850 | iph->saddr = rt->rt_src; |
850 | 851 | ||
851 | if ((iph->ttl = tiph->ttl) == 0) { | 852 | if ((iph->ttl = tiph->ttl) == 0) { |
852 | if (skb->protocol == htons(ETH_P_IP)) | 853 | if (skb->protocol == htons(ETH_P_IP)) |
853 | iph->ttl = old_iph->ttl; | 854 | iph->ttl = old_iph->ttl; |
854 | #ifdef CONFIG_IPV6 | 855 | #ifdef CONFIG_IPV6 |
855 | else if (skb->protocol == htons(ETH_P_IPV6)) | 856 | else if (skb->protocol == htons(ETH_P_IPV6)) |
856 | iph->ttl = ((struct ipv6hdr*)old_iph)->hop_limit; | 857 | iph->ttl = ((struct ipv6hdr*)old_iph)->hop_limit; |
857 | #endif | 858 | #endif |
858 | else | 859 | else |
859 | iph->ttl = dst_metric(&rt->u.dst, RTAX_HOPLIMIT); | 860 | iph->ttl = dst_metric(&rt->u.dst, RTAX_HOPLIMIT); |
860 | } | 861 | } |
861 | 862 | ||
862 | ((u16*)(iph+1))[0] = tunnel->parms.o_flags; | 863 | ((u16*)(iph+1))[0] = tunnel->parms.o_flags; |
863 | ((u16*)(iph+1))[1] = skb->protocol; | 864 | ((u16*)(iph+1))[1] = skb->protocol; |
864 | 865 | ||
865 | if (tunnel->parms.o_flags&(GRE_KEY|GRE_CSUM|GRE_SEQ)) { | 866 | if (tunnel->parms.o_flags&(GRE_KEY|GRE_CSUM|GRE_SEQ)) { |
866 | u32 *ptr = (u32*)(((u8*)iph) + tunnel->hlen - 4); | 867 | u32 *ptr = (u32*)(((u8*)iph) + tunnel->hlen - 4); |
867 | 868 | ||
868 | if (tunnel->parms.o_flags&GRE_SEQ) { | 869 | if (tunnel->parms.o_flags&GRE_SEQ) { |
869 | ++tunnel->o_seqno; | 870 | ++tunnel->o_seqno; |
870 | *ptr = htonl(tunnel->o_seqno); | 871 | *ptr = htonl(tunnel->o_seqno); |
871 | ptr--; | 872 | ptr--; |
872 | } | 873 | } |
873 | if (tunnel->parms.o_flags&GRE_KEY) { | 874 | if (tunnel->parms.o_flags&GRE_KEY) { |
874 | *ptr = tunnel->parms.o_key; | 875 | *ptr = tunnel->parms.o_key; |
875 | ptr--; | 876 | ptr--; |
876 | } | 877 | } |
877 | if (tunnel->parms.o_flags&GRE_CSUM) { | 878 | if (tunnel->parms.o_flags&GRE_CSUM) { |
878 | *ptr = 0; | 879 | *ptr = 0; |
879 | *(__u16*)ptr = ip_compute_csum((void*)(iph+1), skb->len - sizeof(struct iphdr)); | 880 | *(__u16*)ptr = ip_compute_csum((void*)(iph+1), skb->len - sizeof(struct iphdr)); |
880 | } | 881 | } |
881 | } | 882 | } |
882 | 883 | ||
883 | nf_reset(skb); | 884 | nf_reset(skb); |
884 | 885 | ||
885 | IPTUNNEL_XMIT(); | 886 | IPTUNNEL_XMIT(); |
886 | tunnel->recursion--; | 887 | tunnel->recursion--; |
887 | return 0; | 888 | return 0; |
888 | 889 | ||
889 | tx_error_icmp: | 890 | tx_error_icmp: |
890 | dst_link_failure(skb); | 891 | dst_link_failure(skb); |
891 | 892 | ||
892 | tx_error: | 893 | tx_error: |
893 | stats->tx_errors++; | 894 | stats->tx_errors++; |
894 | dev_kfree_skb(skb); | 895 | dev_kfree_skb(skb); |
895 | tunnel->recursion--; | 896 | tunnel->recursion--; |
896 | return 0; | 897 | return 0; |
897 | } | 898 | } |
898 | 899 | ||
899 | static int | 900 | static int |
900 | ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | 901 | ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) |
901 | { | 902 | { |
902 | int err = 0; | 903 | int err = 0; |
903 | struct ip_tunnel_parm p; | 904 | struct ip_tunnel_parm p; |
904 | struct ip_tunnel *t; | 905 | struct ip_tunnel *t; |
905 | 906 | ||
906 | switch (cmd) { | 907 | switch (cmd) { |
907 | case SIOCGETTUNNEL: | 908 | case SIOCGETTUNNEL: |
908 | t = NULL; | 909 | t = NULL; |
909 | if (dev == ipgre_fb_tunnel_dev) { | 910 | if (dev == ipgre_fb_tunnel_dev) { |
910 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) { | 911 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) { |
911 | err = -EFAULT; | 912 | err = -EFAULT; |
912 | break; | 913 | break; |
913 | } | 914 | } |
914 | t = ipgre_tunnel_locate(&p, 0); | 915 | t = ipgre_tunnel_locate(&p, 0); |
915 | } | 916 | } |
916 | if (t == NULL) | 917 | if (t == NULL) |
917 | t = (struct ip_tunnel*)dev->priv; | 918 | t = (struct ip_tunnel*)dev->priv; |
918 | memcpy(&p, &t->parms, sizeof(p)); | 919 | memcpy(&p, &t->parms, sizeof(p)); |
919 | if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p))) | 920 | if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p))) |
920 | err = -EFAULT; | 921 | err = -EFAULT; |
921 | break; | 922 | break; |
922 | 923 | ||
923 | case SIOCADDTUNNEL: | 924 | case SIOCADDTUNNEL: |
924 | case SIOCCHGTUNNEL: | 925 | case SIOCCHGTUNNEL: |
925 | err = -EPERM; | 926 | err = -EPERM; |
926 | if (!capable(CAP_NET_ADMIN)) | 927 | if (!capable(CAP_NET_ADMIN)) |
927 | goto done; | 928 | goto done; |
928 | 929 | ||
929 | err = -EFAULT; | 930 | err = -EFAULT; |
930 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) | 931 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) |
931 | goto done; | 932 | goto done; |
932 | 933 | ||
933 | err = -EINVAL; | 934 | err = -EINVAL; |
934 | if (p.iph.version != 4 || p.iph.protocol != IPPROTO_GRE || | 935 | if (p.iph.version != 4 || p.iph.protocol != IPPROTO_GRE || |
935 | p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF)) || | 936 | p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF)) || |
936 | ((p.i_flags|p.o_flags)&(GRE_VERSION|GRE_ROUTING))) | 937 | ((p.i_flags|p.o_flags)&(GRE_VERSION|GRE_ROUTING))) |
937 | goto done; | 938 | goto done; |
938 | if (p.iph.ttl) | 939 | if (p.iph.ttl) |
939 | p.iph.frag_off |= htons(IP_DF); | 940 | p.iph.frag_off |= htons(IP_DF); |
940 | 941 | ||
941 | if (!(p.i_flags&GRE_KEY)) | 942 | if (!(p.i_flags&GRE_KEY)) |
942 | p.i_key = 0; | 943 | p.i_key = 0; |
943 | if (!(p.o_flags&GRE_KEY)) | 944 | if (!(p.o_flags&GRE_KEY)) |
944 | p.o_key = 0; | 945 | p.o_key = 0; |
945 | 946 | ||
946 | t = ipgre_tunnel_locate(&p, cmd == SIOCADDTUNNEL); | 947 | t = ipgre_tunnel_locate(&p, cmd == SIOCADDTUNNEL); |
947 | 948 | ||
948 | if (dev != ipgre_fb_tunnel_dev && cmd == SIOCCHGTUNNEL) { | 949 | if (dev != ipgre_fb_tunnel_dev && cmd == SIOCCHGTUNNEL) { |
949 | if (t != NULL) { | 950 | if (t != NULL) { |
950 | if (t->dev != dev) { | 951 | if (t->dev != dev) { |
951 | err = -EEXIST; | 952 | err = -EEXIST; |
952 | break; | 953 | break; |
953 | } | 954 | } |
954 | } else { | 955 | } else { |
955 | unsigned nflags=0; | 956 | unsigned nflags=0; |
956 | 957 | ||
957 | t = (struct ip_tunnel*)dev->priv; | 958 | t = (struct ip_tunnel*)dev->priv; |
958 | 959 | ||
959 | if (MULTICAST(p.iph.daddr)) | 960 | if (MULTICAST(p.iph.daddr)) |
960 | nflags = IFF_BROADCAST; | 961 | nflags = IFF_BROADCAST; |
961 | else if (p.iph.daddr) | 962 | else if (p.iph.daddr) |
962 | nflags = IFF_POINTOPOINT; | 963 | nflags = IFF_POINTOPOINT; |
963 | 964 | ||
964 | if ((dev->flags^nflags)&(IFF_POINTOPOINT|IFF_BROADCAST)) { | 965 | if ((dev->flags^nflags)&(IFF_POINTOPOINT|IFF_BROADCAST)) { |
965 | err = -EINVAL; | 966 | err = -EINVAL; |
966 | break; | 967 | break; |
967 | } | 968 | } |
968 | ipgre_tunnel_unlink(t); | 969 | ipgre_tunnel_unlink(t); |
969 | t->parms.iph.saddr = p.iph.saddr; | 970 | t->parms.iph.saddr = p.iph.saddr; |
970 | t->parms.iph.daddr = p.iph.daddr; | 971 | t->parms.iph.daddr = p.iph.daddr; |
971 | t->parms.i_key = p.i_key; | 972 | t->parms.i_key = p.i_key; |
972 | t->parms.o_key = p.o_key; | 973 | t->parms.o_key = p.o_key; |
973 | memcpy(dev->dev_addr, &p.iph.saddr, 4); | 974 | memcpy(dev->dev_addr, &p.iph.saddr, 4); |
974 | memcpy(dev->broadcast, &p.iph.daddr, 4); | 975 | memcpy(dev->broadcast, &p.iph.daddr, 4); |
975 | ipgre_tunnel_link(t); | 976 | ipgre_tunnel_link(t); |
976 | netdev_state_change(dev); | 977 | netdev_state_change(dev); |
977 | } | 978 | } |
978 | } | 979 | } |
979 | 980 | ||
980 | if (t) { | 981 | if (t) { |
981 | err = 0; | 982 | err = 0; |
982 | if (cmd == SIOCCHGTUNNEL) { | 983 | if (cmd == SIOCCHGTUNNEL) { |
983 | t->parms.iph.ttl = p.iph.ttl; | 984 | t->parms.iph.ttl = p.iph.ttl; |
984 | t->parms.iph.tos = p.iph.tos; | 985 | t->parms.iph.tos = p.iph.tos; |
985 | t->parms.iph.frag_off = p.iph.frag_off; | 986 | t->parms.iph.frag_off = p.iph.frag_off; |
986 | } | 987 | } |
987 | if (copy_to_user(ifr->ifr_ifru.ifru_data, &t->parms, sizeof(p))) | 988 | if (copy_to_user(ifr->ifr_ifru.ifru_data, &t->parms, sizeof(p))) |
988 | err = -EFAULT; | 989 | err = -EFAULT; |
989 | } else | 990 | } else |
990 | err = (cmd == SIOCADDTUNNEL ? -ENOBUFS : -ENOENT); | 991 | err = (cmd == SIOCADDTUNNEL ? -ENOBUFS : -ENOENT); |
991 | break; | 992 | break; |
992 | 993 | ||
993 | case SIOCDELTUNNEL: | 994 | case SIOCDELTUNNEL: |
994 | err = -EPERM; | 995 | err = -EPERM; |
995 | if (!capable(CAP_NET_ADMIN)) | 996 | if (!capable(CAP_NET_ADMIN)) |
996 | goto done; | 997 | goto done; |
997 | 998 | ||
998 | if (dev == ipgre_fb_tunnel_dev) { | 999 | if (dev == ipgre_fb_tunnel_dev) { |
999 | err = -EFAULT; | 1000 | err = -EFAULT; |
1000 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) | 1001 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) |
1001 | goto done; | 1002 | goto done; |
1002 | err = -ENOENT; | 1003 | err = -ENOENT; |
1003 | if ((t = ipgre_tunnel_locate(&p, 0)) == NULL) | 1004 | if ((t = ipgre_tunnel_locate(&p, 0)) == NULL) |
1004 | goto done; | 1005 | goto done; |
1005 | err = -EPERM; | 1006 | err = -EPERM; |
1006 | if (t == ipgre_fb_tunnel_dev->priv) | 1007 | if (t == ipgre_fb_tunnel_dev->priv) |
1007 | goto done; | 1008 | goto done; |
1008 | dev = t->dev; | 1009 | dev = t->dev; |
1009 | } | 1010 | } |
1010 | err = unregister_netdevice(dev); | 1011 | err = unregister_netdevice(dev); |
1011 | break; | 1012 | break; |
1012 | 1013 | ||
1013 | default: | 1014 | default: |
1014 | err = -EINVAL; | 1015 | err = -EINVAL; |
1015 | } | 1016 | } |
1016 | 1017 | ||
1017 | done: | 1018 | done: |
1018 | return err; | 1019 | return err; |
1019 | } | 1020 | } |
1020 | 1021 | ||
1021 | static struct net_device_stats *ipgre_tunnel_get_stats(struct net_device *dev) | 1022 | static struct net_device_stats *ipgre_tunnel_get_stats(struct net_device *dev) |
1022 | { | 1023 | { |
1023 | return &(((struct ip_tunnel*)dev->priv)->stat); | 1024 | return &(((struct ip_tunnel*)dev->priv)->stat); |
1024 | } | 1025 | } |
1025 | 1026 | ||
1026 | static int ipgre_tunnel_change_mtu(struct net_device *dev, int new_mtu) | 1027 | static int ipgre_tunnel_change_mtu(struct net_device *dev, int new_mtu) |
1027 | { | 1028 | { |
1028 | struct ip_tunnel *tunnel = (struct ip_tunnel*)dev->priv; | 1029 | struct ip_tunnel *tunnel = (struct ip_tunnel*)dev->priv; |
1029 | if (new_mtu < 68 || new_mtu > 0xFFF8 - tunnel->hlen) | 1030 | if (new_mtu < 68 || new_mtu > 0xFFF8 - tunnel->hlen) |
1030 | return -EINVAL; | 1031 | return -EINVAL; |
1031 | dev->mtu = new_mtu; | 1032 | dev->mtu = new_mtu; |
1032 | return 0; | 1033 | return 0; |
1033 | } | 1034 | } |
1034 | 1035 | ||
1035 | #ifdef CONFIG_NET_IPGRE_BROADCAST | 1036 | #ifdef CONFIG_NET_IPGRE_BROADCAST |
1036 | /* Nice toy. Unfortunately, useless in real life :-) | 1037 | /* Nice toy. Unfortunately, useless in real life :-) |
1037 | It allows to construct virtual multiprotocol broadcast "LAN" | 1038 | It allows to construct virtual multiprotocol broadcast "LAN" |
1038 | over the Internet, provided multicast routing is tuned. | 1039 | over the Internet, provided multicast routing is tuned. |
1039 | 1040 | ||
1040 | 1041 | ||
1041 | I have no idea was this bicycle invented before me, | 1042 | I have no idea was this bicycle invented before me, |
1042 | so that I had to set ARPHRD_IPGRE to a random value. | 1043 | so that I had to set ARPHRD_IPGRE to a random value. |
1043 | I have an impression, that Cisco could make something similar, | 1044 | I have an impression, that Cisco could make something similar, |
1044 | but this feature is apparently missing in IOS<=11.2(8). | 1045 | but this feature is apparently missing in IOS<=11.2(8). |
1045 | 1046 | ||
1046 | I set up 10.66.66/24 and fec0:6666:6666::0/96 as virtual networks | 1047 | I set up 10.66.66/24 and fec0:6666:6666::0/96 as virtual networks |
1047 | with broadcast 224.66.66.66. If you have access to mbone, play with me :-) | 1048 | with broadcast 224.66.66.66. If you have access to mbone, play with me :-) |
1048 | 1049 | ||
1049 | ping -t 255 224.66.66.66 | 1050 | ping -t 255 224.66.66.66 |
1050 | 1051 | ||
1051 | If nobody answers, mbone does not work. | 1052 | If nobody answers, mbone does not work. |
1052 | 1053 | ||
1053 | ip tunnel add Universe mode gre remote 224.66.66.66 local <Your_real_addr> ttl 255 | 1054 | ip tunnel add Universe mode gre remote 224.66.66.66 local <Your_real_addr> ttl 255 |
1054 | ip addr add 10.66.66.<somewhat>/24 dev Universe | 1055 | ip addr add 10.66.66.<somewhat>/24 dev Universe |
1055 | ifconfig Universe up | 1056 | ifconfig Universe up |
1056 | ifconfig Universe add fe80::<Your_real_addr>/10 | 1057 | ifconfig Universe add fe80::<Your_real_addr>/10 |
1057 | ifconfig Universe add fec0:6666:6666::<Your_real_addr>/96 | 1058 | ifconfig Universe add fec0:6666:6666::<Your_real_addr>/96 |
1058 | ftp 10.66.66.66 | 1059 | ftp 10.66.66.66 |
1059 | ... | 1060 | ... |
1060 | ftp fec0:6666:6666::193.233.7.65 | 1061 | ftp fec0:6666:6666::193.233.7.65 |
1061 | ... | 1062 | ... |
1062 | 1063 | ||
1063 | */ | 1064 | */ |
1064 | 1065 | ||
1065 | static int ipgre_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, | 1066 | static int ipgre_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, |
1066 | void *daddr, void *saddr, unsigned len) | 1067 | void *daddr, void *saddr, unsigned len) |
1067 | { | 1068 | { |
1068 | struct ip_tunnel *t = (struct ip_tunnel*)dev->priv; | 1069 | struct ip_tunnel *t = (struct ip_tunnel*)dev->priv; |
1069 | struct iphdr *iph = (struct iphdr *)skb_push(skb, t->hlen); | 1070 | struct iphdr *iph = (struct iphdr *)skb_push(skb, t->hlen); |
1070 | u16 *p = (u16*)(iph+1); | 1071 | u16 *p = (u16*)(iph+1); |
1071 | 1072 | ||
1072 | memcpy(iph, &t->parms.iph, sizeof(struct iphdr)); | 1073 | memcpy(iph, &t->parms.iph, sizeof(struct iphdr)); |
1073 | p[0] = t->parms.o_flags; | 1074 | p[0] = t->parms.o_flags; |
1074 | p[1] = htons(type); | 1075 | p[1] = htons(type); |
1075 | 1076 | ||
1076 | /* | 1077 | /* |
1077 | * Set the source hardware address. | 1078 | * Set the source hardware address. |
1078 | */ | 1079 | */ |
1079 | 1080 | ||
1080 | if (saddr) | 1081 | if (saddr) |
1081 | memcpy(&iph->saddr, saddr, 4); | 1082 | memcpy(&iph->saddr, saddr, 4); |
1082 | 1083 | ||
1083 | if (daddr) { | 1084 | if (daddr) { |
1084 | memcpy(&iph->daddr, daddr, 4); | 1085 | memcpy(&iph->daddr, daddr, 4); |
1085 | return t->hlen; | 1086 | return t->hlen; |
1086 | } | 1087 | } |
1087 | if (iph->daddr && !MULTICAST(iph->daddr)) | 1088 | if (iph->daddr && !MULTICAST(iph->daddr)) |
1088 | return t->hlen; | 1089 | return t->hlen; |
1089 | 1090 | ||
1090 | return -t->hlen; | 1091 | return -t->hlen; |
1091 | } | 1092 | } |
1092 | 1093 | ||
1093 | static int ipgre_open(struct net_device *dev) | 1094 | static int ipgre_open(struct net_device *dev) |
1094 | { | 1095 | { |
1095 | struct ip_tunnel *t = (struct ip_tunnel*)dev->priv; | 1096 | struct ip_tunnel *t = (struct ip_tunnel*)dev->priv; |
1096 | 1097 | ||
1097 | if (MULTICAST(t->parms.iph.daddr)) { | 1098 | if (MULTICAST(t->parms.iph.daddr)) { |
1098 | struct flowi fl = { .oif = t->parms.link, | 1099 | struct flowi fl = { .oif = t->parms.link, |
1099 | .nl_u = { .ip4_u = | 1100 | .nl_u = { .ip4_u = |
1100 | { .daddr = t->parms.iph.daddr, | 1101 | { .daddr = t->parms.iph.daddr, |
1101 | .saddr = t->parms.iph.saddr, | 1102 | .saddr = t->parms.iph.saddr, |
1102 | .tos = RT_TOS(t->parms.iph.tos) } }, | 1103 | .tos = RT_TOS(t->parms.iph.tos) } }, |
1103 | .proto = IPPROTO_GRE }; | 1104 | .proto = IPPROTO_GRE }; |
1104 | struct rtable *rt; | 1105 | struct rtable *rt; |
1105 | if (ip_route_output_key(&rt, &fl)) | 1106 | if (ip_route_output_key(&rt, &fl)) |
1106 | return -EADDRNOTAVAIL; | 1107 | return -EADDRNOTAVAIL; |
1107 | dev = rt->u.dst.dev; | 1108 | dev = rt->u.dst.dev; |
1108 | ip_rt_put(rt); | 1109 | ip_rt_put(rt); |
1109 | if (__in_dev_get_rtnl(dev) == NULL) | 1110 | if (__in_dev_get_rtnl(dev) == NULL) |
1110 | return -EADDRNOTAVAIL; | 1111 | return -EADDRNOTAVAIL; |
1111 | t->mlink = dev->ifindex; | 1112 | t->mlink = dev->ifindex; |
1112 | ip_mc_inc_group(__in_dev_get_rtnl(dev), t->parms.iph.daddr); | 1113 | ip_mc_inc_group(__in_dev_get_rtnl(dev), t->parms.iph.daddr); |
1113 | } | 1114 | } |
1114 | return 0; | 1115 | return 0; |
1115 | } | 1116 | } |
1116 | 1117 | ||
1117 | static int ipgre_close(struct net_device *dev) | 1118 | static int ipgre_close(struct net_device *dev) |
1118 | { | 1119 | { |
1119 | struct ip_tunnel *t = (struct ip_tunnel*)dev->priv; | 1120 | struct ip_tunnel *t = (struct ip_tunnel*)dev->priv; |
1120 | if (MULTICAST(t->parms.iph.daddr) && t->mlink) { | 1121 | if (MULTICAST(t->parms.iph.daddr) && t->mlink) { |
1121 | struct in_device *in_dev = inetdev_by_index(t->mlink); | 1122 | struct in_device *in_dev = inetdev_by_index(t->mlink); |
1122 | if (in_dev) { | 1123 | if (in_dev) { |
1123 | ip_mc_dec_group(in_dev, t->parms.iph.daddr); | 1124 | ip_mc_dec_group(in_dev, t->parms.iph.daddr); |
1124 | in_dev_put(in_dev); | 1125 | in_dev_put(in_dev); |
1125 | } | 1126 | } |
1126 | } | 1127 | } |
1127 | return 0; | 1128 | return 0; |
1128 | } | 1129 | } |
1129 | 1130 | ||
1130 | #endif | 1131 | #endif |
1131 | 1132 | ||
1132 | static void ipgre_tunnel_setup(struct net_device *dev) | 1133 | static void ipgre_tunnel_setup(struct net_device *dev) |
1133 | { | 1134 | { |
1134 | SET_MODULE_OWNER(dev); | 1135 | SET_MODULE_OWNER(dev); |
1135 | dev->uninit = ipgre_tunnel_uninit; | 1136 | dev->uninit = ipgre_tunnel_uninit; |
1136 | dev->destructor = free_netdev; | 1137 | dev->destructor = free_netdev; |
1137 | dev->hard_start_xmit = ipgre_tunnel_xmit; | 1138 | dev->hard_start_xmit = ipgre_tunnel_xmit; |
1138 | dev->get_stats = ipgre_tunnel_get_stats; | 1139 | dev->get_stats = ipgre_tunnel_get_stats; |
1139 | dev->do_ioctl = ipgre_tunnel_ioctl; | 1140 | dev->do_ioctl = ipgre_tunnel_ioctl; |
1140 | dev->change_mtu = ipgre_tunnel_change_mtu; | 1141 | dev->change_mtu = ipgre_tunnel_change_mtu; |
1141 | 1142 | ||
1142 | dev->type = ARPHRD_IPGRE; | 1143 | dev->type = ARPHRD_IPGRE; |
1143 | dev->hard_header_len = LL_MAX_HEADER + sizeof(struct iphdr) + 4; | 1144 | dev->hard_header_len = LL_MAX_HEADER + sizeof(struct iphdr) + 4; |
1144 | dev->mtu = ETH_DATA_LEN - sizeof(struct iphdr) - 4; | 1145 | dev->mtu = ETH_DATA_LEN - sizeof(struct iphdr) - 4; |
1145 | dev->flags = IFF_NOARP; | 1146 | dev->flags = IFF_NOARP; |
1146 | dev->iflink = 0; | 1147 | dev->iflink = 0; |
1147 | dev->addr_len = 4; | 1148 | dev->addr_len = 4; |
1148 | } | 1149 | } |
1149 | 1150 | ||
1150 | static int ipgre_tunnel_init(struct net_device *dev) | 1151 | static int ipgre_tunnel_init(struct net_device *dev) |
1151 | { | 1152 | { |
1152 | struct net_device *tdev = NULL; | 1153 | struct net_device *tdev = NULL; |
1153 | struct ip_tunnel *tunnel; | 1154 | struct ip_tunnel *tunnel; |
1154 | struct iphdr *iph; | 1155 | struct iphdr *iph; |
1155 | int hlen = LL_MAX_HEADER; | 1156 | int hlen = LL_MAX_HEADER; |
1156 | int mtu = ETH_DATA_LEN; | 1157 | int mtu = ETH_DATA_LEN; |
1157 | int addend = sizeof(struct iphdr) + 4; | 1158 | int addend = sizeof(struct iphdr) + 4; |
1158 | 1159 | ||
1159 | tunnel = (struct ip_tunnel*)dev->priv; | 1160 | tunnel = (struct ip_tunnel*)dev->priv; |
1160 | iph = &tunnel->parms.iph; | 1161 | iph = &tunnel->parms.iph; |
1161 | 1162 | ||
1162 | tunnel->dev = dev; | 1163 | tunnel->dev = dev; |
1163 | strcpy(tunnel->parms.name, dev->name); | 1164 | strcpy(tunnel->parms.name, dev->name); |
1164 | 1165 | ||
1165 | memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4); | 1166 | memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4); |
1166 | memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4); | 1167 | memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4); |
1167 | 1168 | ||
1168 | /* Guess output device to choose reasonable mtu and hard_header_len */ | 1169 | /* Guess output device to choose reasonable mtu and hard_header_len */ |
1169 | 1170 | ||
1170 | if (iph->daddr) { | 1171 | if (iph->daddr) { |
1171 | struct flowi fl = { .oif = tunnel->parms.link, | 1172 | struct flowi fl = { .oif = tunnel->parms.link, |
1172 | .nl_u = { .ip4_u = | 1173 | .nl_u = { .ip4_u = |
1173 | { .daddr = iph->daddr, | 1174 | { .daddr = iph->daddr, |
1174 | .saddr = iph->saddr, | 1175 | .saddr = iph->saddr, |
1175 | .tos = RT_TOS(iph->tos) } }, | 1176 | .tos = RT_TOS(iph->tos) } }, |
1176 | .proto = IPPROTO_GRE }; | 1177 | .proto = IPPROTO_GRE }; |
1177 | struct rtable *rt; | 1178 | struct rtable *rt; |
1178 | if (!ip_route_output_key(&rt, &fl)) { | 1179 | if (!ip_route_output_key(&rt, &fl)) { |
1179 | tdev = rt->u.dst.dev; | 1180 | tdev = rt->u.dst.dev; |
1180 | ip_rt_put(rt); | 1181 | ip_rt_put(rt); |
1181 | } | 1182 | } |
1182 | 1183 | ||
1183 | dev->flags |= IFF_POINTOPOINT; | 1184 | dev->flags |= IFF_POINTOPOINT; |
1184 | 1185 | ||
1185 | #ifdef CONFIG_NET_IPGRE_BROADCAST | 1186 | #ifdef CONFIG_NET_IPGRE_BROADCAST |
1186 | if (MULTICAST(iph->daddr)) { | 1187 | if (MULTICAST(iph->daddr)) { |
1187 | if (!iph->saddr) | 1188 | if (!iph->saddr) |
1188 | return -EINVAL; | 1189 | return -EINVAL; |
1189 | dev->flags = IFF_BROADCAST; | 1190 | dev->flags = IFF_BROADCAST; |
1190 | dev->hard_header = ipgre_header; | 1191 | dev->hard_header = ipgre_header; |
1191 | dev->open = ipgre_open; | 1192 | dev->open = ipgre_open; |
1192 | dev->stop = ipgre_close; | 1193 | dev->stop = ipgre_close; |
1193 | } | 1194 | } |
1194 | #endif | 1195 | #endif |
1195 | } | 1196 | } |
1196 | 1197 | ||
1197 | if (!tdev && tunnel->parms.link) | 1198 | if (!tdev && tunnel->parms.link) |
1198 | tdev = __dev_get_by_index(tunnel->parms.link); | 1199 | tdev = __dev_get_by_index(tunnel->parms.link); |
1199 | 1200 | ||
1200 | if (tdev) { | 1201 | if (tdev) { |
1201 | hlen = tdev->hard_header_len; | 1202 | hlen = tdev->hard_header_len; |
1202 | mtu = tdev->mtu; | 1203 | mtu = tdev->mtu; |
1203 | } | 1204 | } |
1204 | dev->iflink = tunnel->parms.link; | 1205 | dev->iflink = tunnel->parms.link; |
1205 | 1206 | ||
1206 | /* Precalculate GRE options length */ | 1207 | /* Precalculate GRE options length */ |
1207 | if (tunnel->parms.o_flags&(GRE_CSUM|GRE_KEY|GRE_SEQ)) { | 1208 | if (tunnel->parms.o_flags&(GRE_CSUM|GRE_KEY|GRE_SEQ)) { |
1208 | if (tunnel->parms.o_flags&GRE_CSUM) | 1209 | if (tunnel->parms.o_flags&GRE_CSUM) |
1209 | addend += 4; | 1210 | addend += 4; |
1210 | if (tunnel->parms.o_flags&GRE_KEY) | 1211 | if (tunnel->parms.o_flags&GRE_KEY) |
1211 | addend += 4; | 1212 | addend += 4; |
1212 | if (tunnel->parms.o_flags&GRE_SEQ) | 1213 | if (tunnel->parms.o_flags&GRE_SEQ) |
1213 | addend += 4; | 1214 | addend += 4; |
1214 | } | 1215 | } |
1215 | dev->hard_header_len = hlen + addend; | 1216 | dev->hard_header_len = hlen + addend; |
1216 | dev->mtu = mtu - addend; | 1217 | dev->mtu = mtu - addend; |
1217 | tunnel->hlen = addend; | 1218 | tunnel->hlen = addend; |
1218 | return 0; | 1219 | return 0; |
1219 | } | 1220 | } |
1220 | 1221 | ||
1221 | static int __init ipgre_fb_tunnel_init(struct net_device *dev) | 1222 | static int __init ipgre_fb_tunnel_init(struct net_device *dev) |
1222 | { | 1223 | { |
1223 | struct ip_tunnel *tunnel = (struct ip_tunnel*)dev->priv; | 1224 | struct ip_tunnel *tunnel = (struct ip_tunnel*)dev->priv; |
1224 | struct iphdr *iph = &tunnel->parms.iph; | 1225 | struct iphdr *iph = &tunnel->parms.iph; |
1225 | 1226 | ||
1226 | tunnel->dev = dev; | 1227 | tunnel->dev = dev; |
1227 | strcpy(tunnel->parms.name, dev->name); | 1228 | strcpy(tunnel->parms.name, dev->name); |
1228 | 1229 | ||
1229 | iph->version = 4; | 1230 | iph->version = 4; |
1230 | iph->protocol = IPPROTO_GRE; | 1231 | iph->protocol = IPPROTO_GRE; |
1231 | iph->ihl = 5; | 1232 | iph->ihl = 5; |
1232 | tunnel->hlen = sizeof(struct iphdr) + 4; | 1233 | tunnel->hlen = sizeof(struct iphdr) + 4; |
1233 | 1234 | ||
1234 | dev_hold(dev); | 1235 | dev_hold(dev); |
1235 | tunnels_wc[0] = tunnel; | 1236 | tunnels_wc[0] = tunnel; |
1236 | return 0; | 1237 | return 0; |
1237 | } | 1238 | } |
1238 | 1239 | ||
1239 | 1240 | ||
1240 | static struct net_protocol ipgre_protocol = { | 1241 | static struct net_protocol ipgre_protocol = { |
1241 | .handler = ipgre_rcv, | 1242 | .handler = ipgre_rcv, |
1242 | .err_handler = ipgre_err, | 1243 | .err_handler = ipgre_err, |
1243 | }; | 1244 | }; |
1244 | 1245 | ||
1245 | 1246 | ||
1246 | /* | 1247 | /* |
1247 | * And now the modules code and kernel interface. | 1248 | * And now the modules code and kernel interface. |
1248 | */ | 1249 | */ |
1249 | 1250 | ||
1250 | static int __init ipgre_init(void) | 1251 | static int __init ipgre_init(void) |
1251 | { | 1252 | { |
1252 | int err; | 1253 | int err; |
1253 | 1254 | ||
1254 | printk(KERN_INFO "GRE over IPv4 tunneling driver\n"); | 1255 | printk(KERN_INFO "GRE over IPv4 tunneling driver\n"); |
1255 | 1256 | ||
1256 | if (inet_add_protocol(&ipgre_protocol, IPPROTO_GRE) < 0) { | 1257 | if (inet_add_protocol(&ipgre_protocol, IPPROTO_GRE) < 0) { |
1257 | printk(KERN_INFO "ipgre init: can't add protocol\n"); | 1258 | printk(KERN_INFO "ipgre init: can't add protocol\n"); |
1258 | return -EAGAIN; | 1259 | return -EAGAIN; |
1259 | } | 1260 | } |
1260 | 1261 | ||
1261 | ipgre_fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), "gre0", | 1262 | ipgre_fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), "gre0", |
1262 | ipgre_tunnel_setup); | 1263 | ipgre_tunnel_setup); |
1263 | if (!ipgre_fb_tunnel_dev) { | 1264 | if (!ipgre_fb_tunnel_dev) { |
1264 | err = -ENOMEM; | 1265 | err = -ENOMEM; |
1265 | goto err1; | 1266 | goto err1; |
1266 | } | 1267 | } |
1267 | 1268 | ||
1268 | ipgre_fb_tunnel_dev->init = ipgre_fb_tunnel_init; | 1269 | ipgre_fb_tunnel_dev->init = ipgre_fb_tunnel_init; |
1269 | 1270 | ||
1270 | if ((err = register_netdev(ipgre_fb_tunnel_dev))) | 1271 | if ((err = register_netdev(ipgre_fb_tunnel_dev))) |
1271 | goto err2; | 1272 | goto err2; |
1272 | out: | 1273 | out: |
1273 | return err; | 1274 | return err; |
1274 | err2: | 1275 | err2: |
1275 | free_netdev(ipgre_fb_tunnel_dev); | 1276 | free_netdev(ipgre_fb_tunnel_dev); |
1276 | err1: | 1277 | err1: |
1277 | inet_del_protocol(&ipgre_protocol, IPPROTO_GRE); | 1278 | inet_del_protocol(&ipgre_protocol, IPPROTO_GRE); |
1278 | goto out; | 1279 | goto out; |
1279 | } | 1280 | } |
1280 | 1281 | ||
1281 | static void __exit ipgre_destroy_tunnels(void) | 1282 | static void __exit ipgre_destroy_tunnels(void) |
1282 | { | 1283 | { |
1283 | int prio; | 1284 | int prio; |
1284 | 1285 | ||
1285 | for (prio = 0; prio < 4; prio++) { | 1286 | for (prio = 0; prio < 4; prio++) { |
1286 | int h; | 1287 | int h; |
1287 | for (h = 0; h < HASH_SIZE; h++) { | 1288 | for (h = 0; h < HASH_SIZE; h++) { |
1288 | struct ip_tunnel *t; | 1289 | struct ip_tunnel *t; |
1289 | while ((t = tunnels[prio][h]) != NULL) | 1290 | while ((t = tunnels[prio][h]) != NULL) |
1290 | unregister_netdevice(t->dev); | 1291 | unregister_netdevice(t->dev); |
1291 | } | 1292 | } |
1292 | } | 1293 | } |
1293 | } | 1294 | } |
1294 | 1295 | ||
1295 | static void __exit ipgre_fini(void) | 1296 | static void __exit ipgre_fini(void) |
1296 | { | 1297 | { |
1297 | if (inet_del_protocol(&ipgre_protocol, IPPROTO_GRE) < 0) | 1298 | if (inet_del_protocol(&ipgre_protocol, IPPROTO_GRE) < 0) |
1298 | printk(KERN_INFO "ipgre close: can't remove protocol\n"); | 1299 | printk(KERN_INFO "ipgre close: can't remove protocol\n"); |
1299 | 1300 | ||
1300 | rtnl_lock(); | 1301 | rtnl_lock(); |
1301 | ipgre_destroy_tunnels(); | 1302 | ipgre_destroy_tunnels(); |
1302 | rtnl_unlock(); | 1303 | rtnl_unlock(); |
1303 | } | 1304 | } |
1304 | 1305 | ||
1305 | module_init(ipgre_init); | 1306 | module_init(ipgre_init); |
1306 | module_exit(ipgre_fini); | 1307 | module_exit(ipgre_fini); |
1307 | MODULE_LICENSE("GPL"); | 1308 | MODULE_LICENSE("GPL"); |
1308 | 1309 |
net/ipv4/ipip.c
1 | /* | 1 | /* |
2 | * Linux NET3: IP/IP protocol decoder. | 2 | * Linux NET3: IP/IP protocol decoder. |
3 | * | 3 | * |
4 | * Version: $Id: ipip.c,v 1.50 2001/10/02 02:22:36 davem Exp $ | 4 | * Version: $Id: ipip.c,v 1.50 2001/10/02 02:22:36 davem Exp $ |
5 | * | 5 | * |
6 | * Authors: | 6 | * Authors: |
7 | * Sam Lantinga (slouken@cs.ucdavis.edu) 02/01/95 | 7 | * Sam Lantinga (slouken@cs.ucdavis.edu) 02/01/95 |
8 | * | 8 | * |
9 | * Fixes: | 9 | * Fixes: |
10 | * Alan Cox : Merged and made usable non modular (its so tiny its silly as | 10 | * Alan Cox : Merged and made usable non modular (its so tiny its silly as |
11 | * a module taking up 2 pages). | 11 | * a module taking up 2 pages). |
12 | * Alan Cox : Fixed bug with 1.3.18 and IPIP not working (now needs to set skb->h.iph) | 12 | * Alan Cox : Fixed bug with 1.3.18 and IPIP not working (now needs to set skb->h.iph) |
13 | * to keep ip_forward happy. | 13 | * to keep ip_forward happy. |
14 | * Alan Cox : More fixes for 1.3.21, and firewall fix. Maybe this will work soon 8). | 14 | * Alan Cox : More fixes for 1.3.21, and firewall fix. Maybe this will work soon 8). |
15 | * Kai Schulte : Fixed #defines for IP_FIREWALL->FIREWALL | 15 | * Kai Schulte : Fixed #defines for IP_FIREWALL->FIREWALL |
16 | * David Woodhouse : Perform some basic ICMP handling. | 16 | * David Woodhouse : Perform some basic ICMP handling. |
17 | * IPIP Routing without decapsulation. | 17 | * IPIP Routing without decapsulation. |
18 | * Carlos Picoto : GRE over IP support | 18 | * Carlos Picoto : GRE over IP support |
19 | * Alexey Kuznetsov: Reworked. Really, now it is truncated version of ipv4/ip_gre.c. | 19 | * Alexey Kuznetsov: Reworked. Really, now it is truncated version of ipv4/ip_gre.c. |
20 | * I do not want to merge them together. | 20 | * I do not want to merge them together. |
21 | * | 21 | * |
22 | * This program is free software; you can redistribute it and/or | 22 | * This program is free software; you can redistribute it and/or |
23 | * modify it under the terms of the GNU General Public License | 23 | * modify it under the terms of the GNU General Public License |
24 | * as published by the Free Software Foundation; either version | 24 | * as published by the Free Software Foundation; either version |
25 | * 2 of the License, or (at your option) any later version. | 25 | * 2 of the License, or (at your option) any later version. |
26 | * | 26 | * |
27 | */ | 27 | */ |
28 | 28 | ||
29 | /* tunnel.c: an IP tunnel driver | 29 | /* tunnel.c: an IP tunnel driver |
30 | 30 | ||
31 | The purpose of this driver is to provide an IP tunnel through | 31 | The purpose of this driver is to provide an IP tunnel through |
32 | which you can tunnel network traffic transparently across subnets. | 32 | which you can tunnel network traffic transparently across subnets. |
33 | 33 | ||
34 | This was written by looking at Nick Holloway's dummy driver | 34 | This was written by looking at Nick Holloway's dummy driver |
35 | Thanks for the great code! | 35 | Thanks for the great code! |
36 | 36 | ||
37 | -Sam Lantinga (slouken@cs.ucdavis.edu) 02/01/95 | 37 | -Sam Lantinga (slouken@cs.ucdavis.edu) 02/01/95 |
38 | 38 | ||
39 | Minor tweaks: | 39 | Minor tweaks: |
40 | Cleaned up the code a little and added some pre-1.3.0 tweaks. | 40 | Cleaned up the code a little and added some pre-1.3.0 tweaks. |
41 | dev->hard_header/hard_header_len changed to use no headers. | 41 | dev->hard_header/hard_header_len changed to use no headers. |
42 | Comments/bracketing tweaked. | 42 | Comments/bracketing tweaked. |
43 | Made the tunnels use dev->name not tunnel: when error reporting. | 43 | Made the tunnels use dev->name not tunnel: when error reporting. |
44 | Added tx_dropped stat | 44 | Added tx_dropped stat |
45 | 45 | ||
46 | -Alan Cox (Alan.Cox@linux.org) 21 March 95 | 46 | -Alan Cox (Alan.Cox@linux.org) 21 March 95 |
47 | 47 | ||
48 | Reworked: | 48 | Reworked: |
49 | Changed to tunnel to destination gateway in addition to the | 49 | Changed to tunnel to destination gateway in addition to the |
50 | tunnel's pointopoint address | 50 | tunnel's pointopoint address |
51 | Almost completely rewritten | 51 | Almost completely rewritten |
52 | Note: There is currently no firewall or ICMP handling done. | 52 | Note: There is currently no firewall or ICMP handling done. |
53 | 53 | ||
54 | -Sam Lantinga (slouken@cs.ucdavis.edu) 02/13/96 | 54 | -Sam Lantinga (slouken@cs.ucdavis.edu) 02/13/96 |
55 | 55 | ||
56 | */ | 56 | */ |
57 | 57 | ||
58 | /* Things I wish I had known when writing the tunnel driver: | 58 | /* Things I wish I had known when writing the tunnel driver: |
59 | 59 | ||
60 | When the tunnel_xmit() function is called, the skb contains the | 60 | When the tunnel_xmit() function is called, the skb contains the |
61 | packet to be sent (plus a great deal of extra info), and dev | 61 | packet to be sent (plus a great deal of extra info), and dev |
62 | contains the tunnel device that _we_ are. | 62 | contains the tunnel device that _we_ are. |
63 | 63 | ||
64 | When we are passed a packet, we are expected to fill in the | 64 | When we are passed a packet, we are expected to fill in the |
65 | source address with our source IP address. | 65 | source address with our source IP address. |
66 | 66 | ||
67 | What is the proper way to allocate, copy and free a buffer? | 67 | What is the proper way to allocate, copy and free a buffer? |
68 | After you allocate it, it is a "0 length" chunk of memory | 68 | After you allocate it, it is a "0 length" chunk of memory |
69 | starting at zero. If you want to add headers to the buffer | 69 | starting at zero. If you want to add headers to the buffer |
70 | later, you'll have to call "skb_reserve(skb, amount)" with | 70 | later, you'll have to call "skb_reserve(skb, amount)" with |
71 | the amount of memory you want reserved. Then, you call | 71 | the amount of memory you want reserved. Then, you call |
72 | "skb_put(skb, amount)" with the amount of space you want in | 72 | "skb_put(skb, amount)" with the amount of space you want in |
73 | the buffer. skb_put() returns a pointer to the top (#0) of | 73 | the buffer. skb_put() returns a pointer to the top (#0) of |
74 | that buffer. skb->len is set to the amount of space you have | 74 | that buffer. skb->len is set to the amount of space you have |
75 | "allocated" with skb_put(). You can then write up to skb->len | 75 | "allocated" with skb_put(). You can then write up to skb->len |
76 | bytes to that buffer. If you need more, you can call skb_put() | 76 | bytes to that buffer. If you need more, you can call skb_put() |
77 | again with the additional amount of space you need. You can | 77 | again with the additional amount of space you need. You can |
78 | find out how much more space you can allocate by calling | 78 | find out how much more space you can allocate by calling |
79 | "skb_tailroom(skb)". | 79 | "skb_tailroom(skb)". |
80 | Now, to add header space, call "skb_push(skb, header_len)". | 80 | Now, to add header space, call "skb_push(skb, header_len)". |
81 | This creates space at the beginning of the buffer and returns | 81 | This creates space at the beginning of the buffer and returns |
82 | a pointer to this new space. If later you need to strip a | 82 | a pointer to this new space. If later you need to strip a |
83 | header from a buffer, call "skb_pull(skb, header_len)". | 83 | header from a buffer, call "skb_pull(skb, header_len)". |
84 | skb_headroom() will return how much space is left at the top | 84 | skb_headroom() will return how much space is left at the top |
85 | of the buffer (before the main data). Remember, this headroom | 85 | of the buffer (before the main data). Remember, this headroom |
86 | space must be reserved before the skb_put() function is called. | 86 | space must be reserved before the skb_put() function is called. |
87 | */ | 87 | */ |
88 | 88 | ||
89 | /* | 89 | /* |
90 | This version of net/ipv4/ipip.c is cloned of net/ipv4/ip_gre.c | 90 | This version of net/ipv4/ipip.c is cloned of net/ipv4/ip_gre.c |
91 | 91 | ||
92 | For comments look at net/ipv4/ip_gre.c --ANK | 92 | For comments look at net/ipv4/ip_gre.c --ANK |
93 | */ | 93 | */ |
94 | 94 | ||
95 | 95 | ||
96 | #include <linux/config.h> | 96 | #include <linux/config.h> |
97 | #include <linux/module.h> | 97 | #include <linux/module.h> |
98 | #include <linux/types.h> | 98 | #include <linux/types.h> |
99 | #include <linux/sched.h> | 99 | #include <linux/sched.h> |
100 | #include <linux/kernel.h> | 100 | #include <linux/kernel.h> |
101 | #include <asm/uaccess.h> | 101 | #include <asm/uaccess.h> |
102 | #include <linux/skbuff.h> | 102 | #include <linux/skbuff.h> |
103 | #include <linux/netdevice.h> | 103 | #include <linux/netdevice.h> |
104 | #include <linux/in.h> | 104 | #include <linux/in.h> |
105 | #include <linux/tcp.h> | 105 | #include <linux/tcp.h> |
106 | #include <linux/udp.h> | 106 | #include <linux/udp.h> |
107 | #include <linux/if_arp.h> | 107 | #include <linux/if_arp.h> |
108 | #include <linux/mroute.h> | 108 | #include <linux/mroute.h> |
109 | #include <linux/init.h> | 109 | #include <linux/init.h> |
110 | #include <linux/netfilter_ipv4.h> | 110 | #include <linux/netfilter_ipv4.h> |
111 | #include <linux/if_ether.h> | 111 | #include <linux/if_ether.h> |
112 | 112 | ||
113 | #include <net/sock.h> | 113 | #include <net/sock.h> |
114 | #include <net/ip.h> | 114 | #include <net/ip.h> |
115 | #include <net/icmp.h> | 115 | #include <net/icmp.h> |
116 | #include <net/protocol.h> | 116 | #include <net/protocol.h> |
117 | #include <net/ipip.h> | 117 | #include <net/ipip.h> |
118 | #include <net/inet_ecn.h> | 118 | #include <net/inet_ecn.h> |
119 | #include <net/xfrm.h> | 119 | #include <net/xfrm.h> |
120 | 120 | ||
121 | #define HASH_SIZE 16 | 121 | #define HASH_SIZE 16 |
122 | #define HASH(addr) ((addr^(addr>>4))&0xF) | 122 | #define HASH(addr) ((addr^(addr>>4))&0xF) |
123 | 123 | ||
124 | static int ipip_fb_tunnel_init(struct net_device *dev); | 124 | static int ipip_fb_tunnel_init(struct net_device *dev); |
125 | static int ipip_tunnel_init(struct net_device *dev); | 125 | static int ipip_tunnel_init(struct net_device *dev); |
126 | static void ipip_tunnel_setup(struct net_device *dev); | 126 | static void ipip_tunnel_setup(struct net_device *dev); |
127 | 127 | ||
128 | static struct net_device *ipip_fb_tunnel_dev; | 128 | static struct net_device *ipip_fb_tunnel_dev; |
129 | 129 | ||
130 | static struct ip_tunnel *tunnels_r_l[HASH_SIZE]; | 130 | static struct ip_tunnel *tunnels_r_l[HASH_SIZE]; |
131 | static struct ip_tunnel *tunnels_r[HASH_SIZE]; | 131 | static struct ip_tunnel *tunnels_r[HASH_SIZE]; |
132 | static struct ip_tunnel *tunnels_l[HASH_SIZE]; | 132 | static struct ip_tunnel *tunnels_l[HASH_SIZE]; |
133 | static struct ip_tunnel *tunnels_wc[1]; | 133 | static struct ip_tunnel *tunnels_wc[1]; |
134 | static struct ip_tunnel **tunnels[4] = { tunnels_wc, tunnels_l, tunnels_r, tunnels_r_l }; | 134 | static struct ip_tunnel **tunnels[4] = { tunnels_wc, tunnels_l, tunnels_r, tunnels_r_l }; |
135 | 135 | ||
136 | static DEFINE_RWLOCK(ipip_lock); | 136 | static DEFINE_RWLOCK(ipip_lock); |
137 | 137 | ||
138 | static struct ip_tunnel * ipip_tunnel_lookup(u32 remote, u32 local) | 138 | static struct ip_tunnel * ipip_tunnel_lookup(u32 remote, u32 local) |
139 | { | 139 | { |
140 | unsigned h0 = HASH(remote); | 140 | unsigned h0 = HASH(remote); |
141 | unsigned h1 = HASH(local); | 141 | unsigned h1 = HASH(local); |
142 | struct ip_tunnel *t; | 142 | struct ip_tunnel *t; |
143 | 143 | ||
144 | for (t = tunnels_r_l[h0^h1]; t; t = t->next) { | 144 | for (t = tunnels_r_l[h0^h1]; t; t = t->next) { |
145 | if (local == t->parms.iph.saddr && | 145 | if (local == t->parms.iph.saddr && |
146 | remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP)) | 146 | remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP)) |
147 | return t; | 147 | return t; |
148 | } | 148 | } |
149 | for (t = tunnels_r[h0]; t; t = t->next) { | 149 | for (t = tunnels_r[h0]; t; t = t->next) { |
150 | if (remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP)) | 150 | if (remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP)) |
151 | return t; | 151 | return t; |
152 | } | 152 | } |
153 | for (t = tunnels_l[h1]; t; t = t->next) { | 153 | for (t = tunnels_l[h1]; t; t = t->next) { |
154 | if (local == t->parms.iph.saddr && (t->dev->flags&IFF_UP)) | 154 | if (local == t->parms.iph.saddr && (t->dev->flags&IFF_UP)) |
155 | return t; | 155 | return t; |
156 | } | 156 | } |
157 | if ((t = tunnels_wc[0]) != NULL && (t->dev->flags&IFF_UP)) | 157 | if ((t = tunnels_wc[0]) != NULL && (t->dev->flags&IFF_UP)) |
158 | return t; | 158 | return t; |
159 | return NULL; | 159 | return NULL; |
160 | } | 160 | } |
161 | 161 | ||
162 | static struct ip_tunnel **ipip_bucket(struct ip_tunnel *t) | 162 | static struct ip_tunnel **ipip_bucket(struct ip_tunnel *t) |
163 | { | 163 | { |
164 | u32 remote = t->parms.iph.daddr; | 164 | u32 remote = t->parms.iph.daddr; |
165 | u32 local = t->parms.iph.saddr; | 165 | u32 local = t->parms.iph.saddr; |
166 | unsigned h = 0; | 166 | unsigned h = 0; |
167 | int prio = 0; | 167 | int prio = 0; |
168 | 168 | ||
169 | if (remote) { | 169 | if (remote) { |
170 | prio |= 2; | 170 | prio |= 2; |
171 | h ^= HASH(remote); | 171 | h ^= HASH(remote); |
172 | } | 172 | } |
173 | if (local) { | 173 | if (local) { |
174 | prio |= 1; | 174 | prio |= 1; |
175 | h ^= HASH(local); | 175 | h ^= HASH(local); |
176 | } | 176 | } |
177 | return &tunnels[prio][h]; | 177 | return &tunnels[prio][h]; |
178 | } | 178 | } |
179 | 179 | ||
180 | 180 | ||
181 | static void ipip_tunnel_unlink(struct ip_tunnel *t) | 181 | static void ipip_tunnel_unlink(struct ip_tunnel *t) |
182 | { | 182 | { |
183 | struct ip_tunnel **tp; | 183 | struct ip_tunnel **tp; |
184 | 184 | ||
185 | for (tp = ipip_bucket(t); *tp; tp = &(*tp)->next) { | 185 | for (tp = ipip_bucket(t); *tp; tp = &(*tp)->next) { |
186 | if (t == *tp) { | 186 | if (t == *tp) { |
187 | write_lock_bh(&ipip_lock); | 187 | write_lock_bh(&ipip_lock); |
188 | *tp = t->next; | 188 | *tp = t->next; |
189 | write_unlock_bh(&ipip_lock); | 189 | write_unlock_bh(&ipip_lock); |
190 | break; | 190 | break; |
191 | } | 191 | } |
192 | } | 192 | } |
193 | } | 193 | } |
194 | 194 | ||
195 | static void ipip_tunnel_link(struct ip_tunnel *t) | 195 | static void ipip_tunnel_link(struct ip_tunnel *t) |
196 | { | 196 | { |
197 | struct ip_tunnel **tp = ipip_bucket(t); | 197 | struct ip_tunnel **tp = ipip_bucket(t); |
198 | 198 | ||
199 | t->next = *tp; | 199 | t->next = *tp; |
200 | write_lock_bh(&ipip_lock); | 200 | write_lock_bh(&ipip_lock); |
201 | *tp = t; | 201 | *tp = t; |
202 | write_unlock_bh(&ipip_lock); | 202 | write_unlock_bh(&ipip_lock); |
203 | } | 203 | } |
204 | 204 | ||
205 | static struct ip_tunnel * ipip_tunnel_locate(struct ip_tunnel_parm *parms, int create) | 205 | static struct ip_tunnel * ipip_tunnel_locate(struct ip_tunnel_parm *parms, int create) |
206 | { | 206 | { |
207 | u32 remote = parms->iph.daddr; | 207 | u32 remote = parms->iph.daddr; |
208 | u32 local = parms->iph.saddr; | 208 | u32 local = parms->iph.saddr; |
209 | struct ip_tunnel *t, **tp, *nt; | 209 | struct ip_tunnel *t, **tp, *nt; |
210 | struct net_device *dev; | 210 | struct net_device *dev; |
211 | unsigned h = 0; | 211 | unsigned h = 0; |
212 | int prio = 0; | 212 | int prio = 0; |
213 | char name[IFNAMSIZ]; | 213 | char name[IFNAMSIZ]; |
214 | 214 | ||
215 | if (remote) { | 215 | if (remote) { |
216 | prio |= 2; | 216 | prio |= 2; |
217 | h ^= HASH(remote); | 217 | h ^= HASH(remote); |
218 | } | 218 | } |
219 | if (local) { | 219 | if (local) { |
220 | prio |= 1; | 220 | prio |= 1; |
221 | h ^= HASH(local); | 221 | h ^= HASH(local); |
222 | } | 222 | } |
223 | for (tp = &tunnels[prio][h]; (t = *tp) != NULL; tp = &t->next) { | 223 | for (tp = &tunnels[prio][h]; (t = *tp) != NULL; tp = &t->next) { |
224 | if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr) | 224 | if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr) |
225 | return t; | 225 | return t; |
226 | } | 226 | } |
227 | if (!create) | 227 | if (!create) |
228 | return NULL; | 228 | return NULL; |
229 | 229 | ||
230 | if (parms->name[0]) | 230 | if (parms->name[0]) |
231 | strlcpy(name, parms->name, IFNAMSIZ); | 231 | strlcpy(name, parms->name, IFNAMSIZ); |
232 | else { | 232 | else { |
233 | int i; | 233 | int i; |
234 | for (i=1; i<100; i++) { | 234 | for (i=1; i<100; i++) { |
235 | sprintf(name, "tunl%d", i); | 235 | sprintf(name, "tunl%d", i); |
236 | if (__dev_get_by_name(name) == NULL) | 236 | if (__dev_get_by_name(name) == NULL) |
237 | break; | 237 | break; |
238 | } | 238 | } |
239 | if (i==100) | 239 | if (i==100) |
240 | goto failed; | 240 | goto failed; |
241 | } | 241 | } |
242 | 242 | ||
243 | dev = alloc_netdev(sizeof(*t), name, ipip_tunnel_setup); | 243 | dev = alloc_netdev(sizeof(*t), name, ipip_tunnel_setup); |
244 | if (dev == NULL) | 244 | if (dev == NULL) |
245 | return NULL; | 245 | return NULL; |
246 | 246 | ||
247 | nt = dev->priv; | 247 | nt = dev->priv; |
248 | SET_MODULE_OWNER(dev); | 248 | SET_MODULE_OWNER(dev); |
249 | dev->init = ipip_tunnel_init; | 249 | dev->init = ipip_tunnel_init; |
250 | nt->parms = *parms; | 250 | nt->parms = *parms; |
251 | 251 | ||
252 | if (register_netdevice(dev) < 0) { | 252 | if (register_netdevice(dev) < 0) { |
253 | free_netdev(dev); | 253 | free_netdev(dev); |
254 | goto failed; | 254 | goto failed; |
255 | } | 255 | } |
256 | 256 | ||
257 | dev_hold(dev); | 257 | dev_hold(dev); |
258 | ipip_tunnel_link(nt); | 258 | ipip_tunnel_link(nt); |
259 | return nt; | 259 | return nt; |
260 | 260 | ||
261 | failed: | 261 | failed: |
262 | return NULL; | 262 | return NULL; |
263 | } | 263 | } |
264 | 264 | ||
265 | static void ipip_tunnel_uninit(struct net_device *dev) | 265 | static void ipip_tunnel_uninit(struct net_device *dev) |
266 | { | 266 | { |
267 | if (dev == ipip_fb_tunnel_dev) { | 267 | if (dev == ipip_fb_tunnel_dev) { |
268 | write_lock_bh(&ipip_lock); | 268 | write_lock_bh(&ipip_lock); |
269 | tunnels_wc[0] = NULL; | 269 | tunnels_wc[0] = NULL; |
270 | write_unlock_bh(&ipip_lock); | 270 | write_unlock_bh(&ipip_lock); |
271 | } else | 271 | } else |
272 | ipip_tunnel_unlink((struct ip_tunnel*)dev->priv); | 272 | ipip_tunnel_unlink((struct ip_tunnel*)dev->priv); |
273 | dev_put(dev); | 273 | dev_put(dev); |
274 | } | 274 | } |
275 | 275 | ||
276 | static void ipip_err(struct sk_buff *skb, u32 info) | 276 | static void ipip_err(struct sk_buff *skb, u32 info) |
277 | { | 277 | { |
278 | #ifndef I_WISH_WORLD_WERE_PERFECT | 278 | #ifndef I_WISH_WORLD_WERE_PERFECT |
279 | 279 | ||
280 | /* It is not :-( All the routers (except for Linux) return only | 280 | /* It is not :-( All the routers (except for Linux) return only |
281 | 8 bytes of packet payload. It means, that precise relaying of | 281 | 8 bytes of packet payload. It means, that precise relaying of |
282 | ICMP in the real Internet is absolutely infeasible. | 282 | ICMP in the real Internet is absolutely infeasible. |
283 | */ | 283 | */ |
284 | struct iphdr *iph = (struct iphdr*)skb->data; | 284 | struct iphdr *iph = (struct iphdr*)skb->data; |
285 | int type = skb->h.icmph->type; | 285 | int type = skb->h.icmph->type; |
286 | int code = skb->h.icmph->code; | 286 | int code = skb->h.icmph->code; |
287 | struct ip_tunnel *t; | 287 | struct ip_tunnel *t; |
288 | 288 | ||
289 | switch (type) { | 289 | switch (type) { |
290 | default: | 290 | default: |
291 | case ICMP_PARAMETERPROB: | 291 | case ICMP_PARAMETERPROB: |
292 | return; | 292 | return; |
293 | 293 | ||
294 | case ICMP_DEST_UNREACH: | 294 | case ICMP_DEST_UNREACH: |
295 | switch (code) { | 295 | switch (code) { |
296 | case ICMP_SR_FAILED: | 296 | case ICMP_SR_FAILED: |
297 | case ICMP_PORT_UNREACH: | 297 | case ICMP_PORT_UNREACH: |
298 | /* Impossible event. */ | 298 | /* Impossible event. */ |
299 | return; | 299 | return; |
300 | case ICMP_FRAG_NEEDED: | 300 | case ICMP_FRAG_NEEDED: |
301 | /* Soft state for pmtu is maintained by IP core. */ | 301 | /* Soft state for pmtu is maintained by IP core. */ |
302 | return; | 302 | return; |
303 | default: | 303 | default: |
304 | /* All others are translated to HOST_UNREACH. | 304 | /* All others are translated to HOST_UNREACH. |
305 | rfc2003 contains "deep thoughts" about NET_UNREACH, | 305 | rfc2003 contains "deep thoughts" about NET_UNREACH, |
306 | I believe they are just ether pollution. --ANK | 306 | I believe they are just ether pollution. --ANK |
307 | */ | 307 | */ |
308 | break; | 308 | break; |
309 | } | 309 | } |
310 | break; | 310 | break; |
311 | case ICMP_TIME_EXCEEDED: | 311 | case ICMP_TIME_EXCEEDED: |
312 | if (code != ICMP_EXC_TTL) | 312 | if (code != ICMP_EXC_TTL) |
313 | return; | 313 | return; |
314 | break; | 314 | break; |
315 | } | 315 | } |
316 | 316 | ||
317 | read_lock(&ipip_lock); | 317 | read_lock(&ipip_lock); |
318 | t = ipip_tunnel_lookup(iph->daddr, iph->saddr); | 318 | t = ipip_tunnel_lookup(iph->daddr, iph->saddr); |
319 | if (t == NULL || t->parms.iph.daddr == 0) | 319 | if (t == NULL || t->parms.iph.daddr == 0) |
320 | goto out; | 320 | goto out; |
321 | if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED) | 321 | if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED) |
322 | goto out; | 322 | goto out; |
323 | 323 | ||
324 | if (jiffies - t->err_time < IPTUNNEL_ERR_TIMEO) | 324 | if (jiffies - t->err_time < IPTUNNEL_ERR_TIMEO) |
325 | t->err_count++; | 325 | t->err_count++; |
326 | else | 326 | else |
327 | t->err_count = 1; | 327 | t->err_count = 1; |
328 | t->err_time = jiffies; | 328 | t->err_time = jiffies; |
329 | out: | 329 | out: |
330 | read_unlock(&ipip_lock); | 330 | read_unlock(&ipip_lock); |
331 | return; | 331 | return; |
332 | #else | 332 | #else |
333 | struct iphdr *iph = (struct iphdr*)dp; | 333 | struct iphdr *iph = (struct iphdr*)dp; |
334 | int hlen = iph->ihl<<2; | 334 | int hlen = iph->ihl<<2; |
335 | struct iphdr *eiph; | 335 | struct iphdr *eiph; |
336 | int type = skb->h.icmph->type; | 336 | int type = skb->h.icmph->type; |
337 | int code = skb->h.icmph->code; | 337 | int code = skb->h.icmph->code; |
338 | int rel_type = 0; | 338 | int rel_type = 0; |
339 | int rel_code = 0; | 339 | int rel_code = 0; |
340 | int rel_info = 0; | 340 | int rel_info = 0; |
341 | struct sk_buff *skb2; | 341 | struct sk_buff *skb2; |
342 | struct flowi fl; | 342 | struct flowi fl; |
343 | struct rtable *rt; | 343 | struct rtable *rt; |
344 | 344 | ||
345 | if (len < hlen + sizeof(struct iphdr)) | 345 | if (len < hlen + sizeof(struct iphdr)) |
346 | return; | 346 | return; |
347 | eiph = (struct iphdr*)(dp + hlen); | 347 | eiph = (struct iphdr*)(dp + hlen); |
348 | 348 | ||
349 | switch (type) { | 349 | switch (type) { |
350 | default: | 350 | default: |
351 | return; | 351 | return; |
352 | case ICMP_PARAMETERPROB: | 352 | case ICMP_PARAMETERPROB: |
353 | if (skb->h.icmph->un.gateway < hlen) | 353 | if (skb->h.icmph->un.gateway < hlen) |
354 | return; | 354 | return; |
355 | 355 | ||
356 | /* So... This guy found something strange INSIDE encapsulated | 356 | /* So... This guy found something strange INSIDE encapsulated |
357 | packet. Well, he is fool, but what can we do ? | 357 | packet. Well, he is fool, but what can we do ? |
358 | */ | 358 | */ |
359 | rel_type = ICMP_PARAMETERPROB; | 359 | rel_type = ICMP_PARAMETERPROB; |
360 | rel_info = skb->h.icmph->un.gateway - hlen; | 360 | rel_info = skb->h.icmph->un.gateway - hlen; |
361 | break; | 361 | break; |
362 | 362 | ||
363 | case ICMP_DEST_UNREACH: | 363 | case ICMP_DEST_UNREACH: |
364 | switch (code) { | 364 | switch (code) { |
365 | case ICMP_SR_FAILED: | 365 | case ICMP_SR_FAILED: |
366 | case ICMP_PORT_UNREACH: | 366 | case ICMP_PORT_UNREACH: |
367 | /* Impossible event. */ | 367 | /* Impossible event. */ |
368 | return; | 368 | return; |
369 | case ICMP_FRAG_NEEDED: | 369 | case ICMP_FRAG_NEEDED: |
370 | /* And it is the only really necessary thing :-) */ | 370 | /* And it is the only really necessary thing :-) */ |
371 | rel_info = ntohs(skb->h.icmph->un.frag.mtu); | 371 | rel_info = ntohs(skb->h.icmph->un.frag.mtu); |
372 | if (rel_info < hlen+68) | 372 | if (rel_info < hlen+68) |
373 | return; | 373 | return; |
374 | rel_info -= hlen; | 374 | rel_info -= hlen; |
375 | /* BSD 4.2 MORE DOES NOT EXIST IN NATURE. */ | 375 | /* BSD 4.2 MORE DOES NOT EXIST IN NATURE. */ |
376 | if (rel_info > ntohs(eiph->tot_len)) | 376 | if (rel_info > ntohs(eiph->tot_len)) |
377 | return; | 377 | return; |
378 | break; | 378 | break; |
379 | default: | 379 | default: |
380 | /* All others are translated to HOST_UNREACH. | 380 | /* All others are translated to HOST_UNREACH. |
381 | rfc2003 contains "deep thoughts" about NET_UNREACH, | 381 | rfc2003 contains "deep thoughts" about NET_UNREACH, |
382 | I believe, it is just ether pollution. --ANK | 382 | I believe, it is just ether pollution. --ANK |
383 | */ | 383 | */ |
384 | rel_type = ICMP_DEST_UNREACH; | 384 | rel_type = ICMP_DEST_UNREACH; |
385 | rel_code = ICMP_HOST_UNREACH; | 385 | rel_code = ICMP_HOST_UNREACH; |
386 | break; | 386 | break; |
387 | } | 387 | } |
388 | break; | 388 | break; |
389 | case ICMP_TIME_EXCEEDED: | 389 | case ICMP_TIME_EXCEEDED: |
390 | if (code != ICMP_EXC_TTL) | 390 | if (code != ICMP_EXC_TTL) |
391 | return; | 391 | return; |
392 | break; | 392 | break; |
393 | } | 393 | } |
394 | 394 | ||
395 | /* Prepare fake skb to feed it to icmp_send */ | 395 | /* Prepare fake skb to feed it to icmp_send */ |
396 | skb2 = skb_clone(skb, GFP_ATOMIC); | 396 | skb2 = skb_clone(skb, GFP_ATOMIC); |
397 | if (skb2 == NULL) | 397 | if (skb2 == NULL) |
398 | return; | 398 | return; |
399 | dst_release(skb2->dst); | 399 | dst_release(skb2->dst); |
400 | skb2->dst = NULL; | 400 | skb2->dst = NULL; |
401 | skb_pull(skb2, skb->data - (u8*)eiph); | 401 | skb_pull(skb2, skb->data - (u8*)eiph); |
402 | skb2->nh.raw = skb2->data; | 402 | skb2->nh.raw = skb2->data; |
403 | 403 | ||
404 | /* Try to guess incoming interface */ | 404 | /* Try to guess incoming interface */ |
405 | memset(&fl, 0, sizeof(fl)); | 405 | memset(&fl, 0, sizeof(fl)); |
406 | fl.fl4_daddr = eiph->saddr; | 406 | fl.fl4_daddr = eiph->saddr; |
407 | fl.fl4_tos = RT_TOS(eiph->tos); | 407 | fl.fl4_tos = RT_TOS(eiph->tos); |
408 | fl.proto = IPPROTO_IPIP; | 408 | fl.proto = IPPROTO_IPIP; |
409 | if (ip_route_output_key(&rt, &key)) { | 409 | if (ip_route_output_key(&rt, &key)) { |
410 | kfree_skb(skb2); | 410 | kfree_skb(skb2); |
411 | return; | 411 | return; |
412 | } | 412 | } |
413 | skb2->dev = rt->u.dst.dev; | 413 | skb2->dev = rt->u.dst.dev; |
414 | 414 | ||
415 | /* route "incoming" packet */ | 415 | /* route "incoming" packet */ |
416 | if (rt->rt_flags&RTCF_LOCAL) { | 416 | if (rt->rt_flags&RTCF_LOCAL) { |
417 | ip_rt_put(rt); | 417 | ip_rt_put(rt); |
418 | rt = NULL; | 418 | rt = NULL; |
419 | fl.fl4_daddr = eiph->daddr; | 419 | fl.fl4_daddr = eiph->daddr; |
420 | fl.fl4_src = eiph->saddr; | 420 | fl.fl4_src = eiph->saddr; |
421 | fl.fl4_tos = eiph->tos; | 421 | fl.fl4_tos = eiph->tos; |
422 | if (ip_route_output_key(&rt, &fl) || | 422 | if (ip_route_output_key(&rt, &fl) || |
423 | rt->u.dst.dev->type != ARPHRD_TUNNEL) { | 423 | rt->u.dst.dev->type != ARPHRD_TUNNEL) { |
424 | ip_rt_put(rt); | 424 | ip_rt_put(rt); |
425 | kfree_skb(skb2); | 425 | kfree_skb(skb2); |
426 | return; | 426 | return; |
427 | } | 427 | } |
428 | } else { | 428 | } else { |
429 | ip_rt_put(rt); | 429 | ip_rt_put(rt); |
430 | if (ip_route_input(skb2, eiph->daddr, eiph->saddr, eiph->tos, skb2->dev) || | 430 | if (ip_route_input(skb2, eiph->daddr, eiph->saddr, eiph->tos, skb2->dev) || |
431 | skb2->dst->dev->type != ARPHRD_TUNNEL) { | 431 | skb2->dst->dev->type != ARPHRD_TUNNEL) { |
432 | kfree_skb(skb2); | 432 | kfree_skb(skb2); |
433 | return; | 433 | return; |
434 | } | 434 | } |
435 | } | 435 | } |
436 | 436 | ||
437 | /* change mtu on this route */ | 437 | /* change mtu on this route */ |
438 | if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) { | 438 | if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) { |
439 | if (rel_info > dst_mtu(skb2->dst)) { | 439 | if (rel_info > dst_mtu(skb2->dst)) { |
440 | kfree_skb(skb2); | 440 | kfree_skb(skb2); |
441 | return; | 441 | return; |
442 | } | 442 | } |
443 | skb2->dst->ops->update_pmtu(skb2->dst, rel_info); | 443 | skb2->dst->ops->update_pmtu(skb2->dst, rel_info); |
444 | rel_info = htonl(rel_info); | 444 | rel_info = htonl(rel_info); |
445 | } else if (type == ICMP_TIME_EXCEEDED) { | 445 | } else if (type == ICMP_TIME_EXCEEDED) { |
446 | struct ip_tunnel *t = (struct ip_tunnel*)skb2->dev->priv; | 446 | struct ip_tunnel *t = (struct ip_tunnel*)skb2->dev->priv; |
447 | if (t->parms.iph.ttl) { | 447 | if (t->parms.iph.ttl) { |
448 | rel_type = ICMP_DEST_UNREACH; | 448 | rel_type = ICMP_DEST_UNREACH; |
449 | rel_code = ICMP_HOST_UNREACH; | 449 | rel_code = ICMP_HOST_UNREACH; |
450 | } | 450 | } |
451 | } | 451 | } |
452 | 452 | ||
453 | icmp_send(skb2, rel_type, rel_code, rel_info); | 453 | icmp_send(skb2, rel_type, rel_code, rel_info); |
454 | kfree_skb(skb2); | 454 | kfree_skb(skb2); |
455 | return; | 455 | return; |
456 | #endif | 456 | #endif |
457 | } | 457 | } |
458 | 458 | ||
459 | static inline void ipip_ecn_decapsulate(struct iphdr *outer_iph, struct sk_buff *skb) | 459 | static inline void ipip_ecn_decapsulate(struct iphdr *outer_iph, struct sk_buff *skb) |
460 | { | 460 | { |
461 | struct iphdr *inner_iph = skb->nh.iph; | 461 | struct iphdr *inner_iph = skb->nh.iph; |
462 | 462 | ||
463 | if (INET_ECN_is_ce(outer_iph->tos)) | 463 | if (INET_ECN_is_ce(outer_iph->tos)) |
464 | IP_ECN_set_ce(inner_iph); | 464 | IP_ECN_set_ce(inner_iph); |
465 | } | 465 | } |
466 | 466 | ||
467 | static int ipip_rcv(struct sk_buff *skb) | 467 | static int ipip_rcv(struct sk_buff *skb) |
468 | { | 468 | { |
469 | struct iphdr *iph; | 469 | struct iphdr *iph; |
470 | struct ip_tunnel *tunnel; | 470 | struct ip_tunnel *tunnel; |
471 | 471 | ||
472 | if (!pskb_may_pull(skb, sizeof(struct iphdr))) | 472 | if (!pskb_may_pull(skb, sizeof(struct iphdr))) |
473 | goto out; | 473 | goto out; |
474 | 474 | ||
475 | iph = skb->nh.iph; | 475 | iph = skb->nh.iph; |
476 | 476 | ||
477 | read_lock(&ipip_lock); | 477 | read_lock(&ipip_lock); |
478 | if ((tunnel = ipip_tunnel_lookup(iph->saddr, iph->daddr)) != NULL) { | 478 | if ((tunnel = ipip_tunnel_lookup(iph->saddr, iph->daddr)) != NULL) { |
479 | if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) { | 479 | if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) { |
480 | read_unlock(&ipip_lock); | 480 | read_unlock(&ipip_lock); |
481 | kfree_skb(skb); | 481 | kfree_skb(skb); |
482 | return 0; | 482 | return 0; |
483 | } | 483 | } |
484 | 484 | ||
485 | secpath_reset(skb); | 485 | secpath_reset(skb); |
486 | 486 | ||
487 | skb->mac.raw = skb->nh.raw; | 487 | skb->mac.raw = skb->nh.raw; |
488 | skb->nh.raw = skb->data; | 488 | skb->nh.raw = skb->data; |
489 | memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options)); | 489 | memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options)); |
490 | skb->protocol = htons(ETH_P_IP); | 490 | skb->protocol = htons(ETH_P_IP); |
491 | skb->pkt_type = PACKET_HOST; | 491 | skb->pkt_type = PACKET_HOST; |
492 | 492 | ||
493 | tunnel->stat.rx_packets++; | 493 | tunnel->stat.rx_packets++; |
494 | tunnel->stat.rx_bytes += skb->len; | 494 | tunnel->stat.rx_bytes += skb->len; |
495 | skb->dev = tunnel->dev; | 495 | skb->dev = tunnel->dev; |
496 | dst_release(skb->dst); | 496 | dst_release(skb->dst); |
497 | skb->dst = NULL; | 497 | skb->dst = NULL; |
498 | nf_reset(skb); | 498 | nf_reset(skb); |
499 | ipip_ecn_decapsulate(iph, skb); | 499 | ipip_ecn_decapsulate(iph, skb); |
500 | netif_rx(skb); | 500 | netif_rx(skb); |
501 | read_unlock(&ipip_lock); | 501 | read_unlock(&ipip_lock); |
502 | return 0; | 502 | return 0; |
503 | } | 503 | } |
504 | read_unlock(&ipip_lock); | 504 | read_unlock(&ipip_lock); |
505 | 505 | ||
506 | out: | 506 | out: |
507 | return -1; | 507 | return -1; |
508 | } | 508 | } |
509 | 509 | ||
510 | /* | 510 | /* |
511 | * This function assumes it is being called from dev_queue_xmit() | 511 | * This function assumes it is being called from dev_queue_xmit() |
512 | * and that skb is filled properly by that function. | 512 | * and that skb is filled properly by that function. |
513 | */ | 513 | */ |
514 | 514 | ||
515 | static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | 515 | static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) |
516 | { | 516 | { |
517 | struct ip_tunnel *tunnel = (struct ip_tunnel*)dev->priv; | 517 | struct ip_tunnel *tunnel = (struct ip_tunnel*)dev->priv; |
518 | struct net_device_stats *stats = &tunnel->stat; | 518 | struct net_device_stats *stats = &tunnel->stat; |
519 | struct iphdr *tiph = &tunnel->parms.iph; | 519 | struct iphdr *tiph = &tunnel->parms.iph; |
520 | u8 tos = tunnel->parms.iph.tos; | 520 | u8 tos = tunnel->parms.iph.tos; |
521 | u16 df = tiph->frag_off; | 521 | u16 df = tiph->frag_off; |
522 | struct rtable *rt; /* Route to the other host */ | 522 | struct rtable *rt; /* Route to the other host */ |
523 | struct net_device *tdev; /* Device to other host */ | 523 | struct net_device *tdev; /* Device to other host */ |
524 | struct iphdr *old_iph = skb->nh.iph; | 524 | struct iphdr *old_iph = skb->nh.iph; |
525 | struct iphdr *iph; /* Our new IP header */ | 525 | struct iphdr *iph; /* Our new IP header */ |
526 | int max_headroom; /* The extra header space needed */ | 526 | int max_headroom; /* The extra header space needed */ |
527 | u32 dst = tiph->daddr; | 527 | u32 dst = tiph->daddr; |
528 | int mtu; | 528 | int mtu; |
529 | 529 | ||
530 | if (tunnel->recursion++) { | 530 | if (tunnel->recursion++) { |
531 | tunnel->stat.collisions++; | 531 | tunnel->stat.collisions++; |
532 | goto tx_error; | 532 | goto tx_error; |
533 | } | 533 | } |
534 | 534 | ||
535 | if (skb->protocol != htons(ETH_P_IP)) | 535 | if (skb->protocol != htons(ETH_P_IP)) |
536 | goto tx_error; | 536 | goto tx_error; |
537 | 537 | ||
538 | if (tos&1) | 538 | if (tos&1) |
539 | tos = old_iph->tos; | 539 | tos = old_iph->tos; |
540 | 540 | ||
541 | if (!dst) { | 541 | if (!dst) { |
542 | /* NBMA tunnel */ | 542 | /* NBMA tunnel */ |
543 | if ((rt = (struct rtable*)skb->dst) == NULL) { | 543 | if ((rt = (struct rtable*)skb->dst) == NULL) { |
544 | tunnel->stat.tx_fifo_errors++; | 544 | tunnel->stat.tx_fifo_errors++; |
545 | goto tx_error; | 545 | goto tx_error; |
546 | } | 546 | } |
547 | if ((dst = rt->rt_gateway) == 0) | 547 | if ((dst = rt->rt_gateway) == 0) |
548 | goto tx_error_icmp; | 548 | goto tx_error_icmp; |
549 | } | 549 | } |
550 | 550 | ||
551 | { | 551 | { |
552 | struct flowi fl = { .oif = tunnel->parms.link, | 552 | struct flowi fl = { .oif = tunnel->parms.link, |
553 | .nl_u = { .ip4_u = | 553 | .nl_u = { .ip4_u = |
554 | { .daddr = dst, | 554 | { .daddr = dst, |
555 | .saddr = tiph->saddr, | 555 | .saddr = tiph->saddr, |
556 | .tos = RT_TOS(tos) } }, | 556 | .tos = RT_TOS(tos) } }, |
557 | .proto = IPPROTO_IPIP }; | 557 | .proto = IPPROTO_IPIP }; |
558 | if (ip_route_output_key(&rt, &fl)) { | 558 | if (ip_route_output_key(&rt, &fl)) { |
559 | tunnel->stat.tx_carrier_errors++; | 559 | tunnel->stat.tx_carrier_errors++; |
560 | goto tx_error_icmp; | 560 | goto tx_error_icmp; |
561 | } | 561 | } |
562 | } | 562 | } |
563 | tdev = rt->u.dst.dev; | 563 | tdev = rt->u.dst.dev; |
564 | 564 | ||
565 | if (tdev == dev) { | 565 | if (tdev == dev) { |
566 | ip_rt_put(rt); | 566 | ip_rt_put(rt); |
567 | tunnel->stat.collisions++; | 567 | tunnel->stat.collisions++; |
568 | goto tx_error; | 568 | goto tx_error; |
569 | } | 569 | } |
570 | 570 | ||
571 | if (tiph->frag_off) | 571 | if (tiph->frag_off) |
572 | mtu = dst_mtu(&rt->u.dst) - sizeof(struct iphdr); | 572 | mtu = dst_mtu(&rt->u.dst) - sizeof(struct iphdr); |
573 | else | 573 | else |
574 | mtu = skb->dst ? dst_mtu(skb->dst) : dev->mtu; | 574 | mtu = skb->dst ? dst_mtu(skb->dst) : dev->mtu; |
575 | 575 | ||
576 | if (mtu < 68) { | 576 | if (mtu < 68) { |
577 | tunnel->stat.collisions++; | 577 | tunnel->stat.collisions++; |
578 | ip_rt_put(rt); | 578 | ip_rt_put(rt); |
579 | goto tx_error; | 579 | goto tx_error; |
580 | } | 580 | } |
581 | if (skb->dst) | 581 | if (skb->dst) |
582 | skb->dst->ops->update_pmtu(skb->dst, mtu); | 582 | skb->dst->ops->update_pmtu(skb->dst, mtu); |
583 | 583 | ||
584 | df |= (old_iph->frag_off&htons(IP_DF)); | 584 | df |= (old_iph->frag_off&htons(IP_DF)); |
585 | 585 | ||
586 | if ((old_iph->frag_off&htons(IP_DF)) && mtu < ntohs(old_iph->tot_len)) { | 586 | if ((old_iph->frag_off&htons(IP_DF)) && mtu < ntohs(old_iph->tot_len)) { |
587 | icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu)); | 587 | icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu)); |
588 | ip_rt_put(rt); | 588 | ip_rt_put(rt); |
589 | goto tx_error; | 589 | goto tx_error; |
590 | } | 590 | } |
591 | 591 | ||
592 | if (tunnel->err_count > 0) { | 592 | if (tunnel->err_count > 0) { |
593 | if (jiffies - tunnel->err_time < IPTUNNEL_ERR_TIMEO) { | 593 | if (jiffies - tunnel->err_time < IPTUNNEL_ERR_TIMEO) { |
594 | tunnel->err_count--; | 594 | tunnel->err_count--; |
595 | dst_link_failure(skb); | 595 | dst_link_failure(skb); |
596 | } else | 596 | } else |
597 | tunnel->err_count = 0; | 597 | tunnel->err_count = 0; |
598 | } | 598 | } |
599 | 599 | ||
600 | /* | 600 | /* |
601 | * Okay, now see if we can stuff it in the buffer as-is. | 601 | * Okay, now see if we can stuff it in the buffer as-is. |
602 | */ | 602 | */ |
603 | max_headroom = (LL_RESERVED_SPACE(tdev)+sizeof(struct iphdr)); | 603 | max_headroom = (LL_RESERVED_SPACE(tdev)+sizeof(struct iphdr)); |
604 | 604 | ||
605 | if (skb_headroom(skb) < max_headroom || skb_cloned(skb) || skb_shared(skb)) { | 605 | if (skb_headroom(skb) < max_headroom || skb_cloned(skb) || skb_shared(skb)) { |
606 | struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom); | 606 | struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom); |
607 | if (!new_skb) { | 607 | if (!new_skb) { |
608 | ip_rt_put(rt); | 608 | ip_rt_put(rt); |
609 | stats->tx_dropped++; | 609 | stats->tx_dropped++; |
610 | dev_kfree_skb(skb); | 610 | dev_kfree_skb(skb); |
611 | tunnel->recursion--; | 611 | tunnel->recursion--; |
612 | return 0; | 612 | return 0; |
613 | } | 613 | } |
614 | if (skb->sk) | 614 | if (skb->sk) |
615 | skb_set_owner_w(new_skb, skb->sk); | 615 | skb_set_owner_w(new_skb, skb->sk); |
616 | dev_kfree_skb(skb); | 616 | dev_kfree_skb(skb); |
617 | skb = new_skb; | 617 | skb = new_skb; |
618 | old_iph = skb->nh.iph; | 618 | old_iph = skb->nh.iph; |
619 | } | 619 | } |
620 | 620 | ||
621 | skb->h.raw = skb->nh.raw; | 621 | skb->h.raw = skb->nh.raw; |
622 | skb->nh.raw = skb_push(skb, sizeof(struct iphdr)); | 622 | skb->nh.raw = skb_push(skb, sizeof(struct iphdr)); |
623 | memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); | 623 | memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); |
624 | IPCB(skb)->flags &= ~IPSKB_XFRM_TUNNEL_SIZE; | ||
624 | dst_release(skb->dst); | 625 | dst_release(skb->dst); |
625 | skb->dst = &rt->u.dst; | 626 | skb->dst = &rt->u.dst; |
626 | 627 | ||
627 | /* | 628 | /* |
628 | * Push down and install the IPIP header. | 629 | * Push down and install the IPIP header. |
629 | */ | 630 | */ |
630 | 631 | ||
631 | iph = skb->nh.iph; | 632 | iph = skb->nh.iph; |
632 | iph->version = 4; | 633 | iph->version = 4; |
633 | iph->ihl = sizeof(struct iphdr)>>2; | 634 | iph->ihl = sizeof(struct iphdr)>>2; |
634 | iph->frag_off = df; | 635 | iph->frag_off = df; |
635 | iph->protocol = IPPROTO_IPIP; | 636 | iph->protocol = IPPROTO_IPIP; |
636 | iph->tos = INET_ECN_encapsulate(tos, old_iph->tos); | 637 | iph->tos = INET_ECN_encapsulate(tos, old_iph->tos); |
637 | iph->daddr = rt->rt_dst; | 638 | iph->daddr = rt->rt_dst; |
638 | iph->saddr = rt->rt_src; | 639 | iph->saddr = rt->rt_src; |
639 | 640 | ||
640 | if ((iph->ttl = tiph->ttl) == 0) | 641 | if ((iph->ttl = tiph->ttl) == 0) |
641 | iph->ttl = old_iph->ttl; | 642 | iph->ttl = old_iph->ttl; |
642 | 643 | ||
643 | nf_reset(skb); | 644 | nf_reset(skb); |
644 | 645 | ||
645 | IPTUNNEL_XMIT(); | 646 | IPTUNNEL_XMIT(); |
646 | tunnel->recursion--; | 647 | tunnel->recursion--; |
647 | return 0; | 648 | return 0; |
648 | 649 | ||
649 | tx_error_icmp: | 650 | tx_error_icmp: |
650 | dst_link_failure(skb); | 651 | dst_link_failure(skb); |
651 | tx_error: | 652 | tx_error: |
652 | stats->tx_errors++; | 653 | stats->tx_errors++; |
653 | dev_kfree_skb(skb); | 654 | dev_kfree_skb(skb); |
654 | tunnel->recursion--; | 655 | tunnel->recursion--; |
655 | return 0; | 656 | return 0; |
656 | } | 657 | } |
657 | 658 | ||
658 | static int | 659 | static int |
659 | ipip_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | 660 | ipip_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) |
660 | { | 661 | { |
661 | int err = 0; | 662 | int err = 0; |
662 | struct ip_tunnel_parm p; | 663 | struct ip_tunnel_parm p; |
663 | struct ip_tunnel *t; | 664 | struct ip_tunnel *t; |
664 | 665 | ||
665 | switch (cmd) { | 666 | switch (cmd) { |
666 | case SIOCGETTUNNEL: | 667 | case SIOCGETTUNNEL: |
667 | t = NULL; | 668 | t = NULL; |
668 | if (dev == ipip_fb_tunnel_dev) { | 669 | if (dev == ipip_fb_tunnel_dev) { |
669 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) { | 670 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) { |
670 | err = -EFAULT; | 671 | err = -EFAULT; |
671 | break; | 672 | break; |
672 | } | 673 | } |
673 | t = ipip_tunnel_locate(&p, 0); | 674 | t = ipip_tunnel_locate(&p, 0); |
674 | } | 675 | } |
675 | if (t == NULL) | 676 | if (t == NULL) |
676 | t = (struct ip_tunnel*)dev->priv; | 677 | t = (struct ip_tunnel*)dev->priv; |
677 | memcpy(&p, &t->parms, sizeof(p)); | 678 | memcpy(&p, &t->parms, sizeof(p)); |
678 | if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p))) | 679 | if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p))) |
679 | err = -EFAULT; | 680 | err = -EFAULT; |
680 | break; | 681 | break; |
681 | 682 | ||
682 | case SIOCADDTUNNEL: | 683 | case SIOCADDTUNNEL: |
683 | case SIOCCHGTUNNEL: | 684 | case SIOCCHGTUNNEL: |
684 | err = -EPERM; | 685 | err = -EPERM; |
685 | if (!capable(CAP_NET_ADMIN)) | 686 | if (!capable(CAP_NET_ADMIN)) |
686 | goto done; | 687 | goto done; |
687 | 688 | ||
688 | err = -EFAULT; | 689 | err = -EFAULT; |
689 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) | 690 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) |
690 | goto done; | 691 | goto done; |
691 | 692 | ||
692 | err = -EINVAL; | 693 | err = -EINVAL; |
693 | if (p.iph.version != 4 || p.iph.protocol != IPPROTO_IPIP || | 694 | if (p.iph.version != 4 || p.iph.protocol != IPPROTO_IPIP || |
694 | p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF))) | 695 | p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF))) |
695 | goto done; | 696 | goto done; |
696 | if (p.iph.ttl) | 697 | if (p.iph.ttl) |
697 | p.iph.frag_off |= htons(IP_DF); | 698 | p.iph.frag_off |= htons(IP_DF); |
698 | 699 | ||
699 | t = ipip_tunnel_locate(&p, cmd == SIOCADDTUNNEL); | 700 | t = ipip_tunnel_locate(&p, cmd == SIOCADDTUNNEL); |
700 | 701 | ||
701 | if (dev != ipip_fb_tunnel_dev && cmd == SIOCCHGTUNNEL) { | 702 | if (dev != ipip_fb_tunnel_dev && cmd == SIOCCHGTUNNEL) { |
702 | if (t != NULL) { | 703 | if (t != NULL) { |
703 | if (t->dev != dev) { | 704 | if (t->dev != dev) { |
704 | err = -EEXIST; | 705 | err = -EEXIST; |
705 | break; | 706 | break; |
706 | } | 707 | } |
707 | } else { | 708 | } else { |
708 | if (((dev->flags&IFF_POINTOPOINT) && !p.iph.daddr) || | 709 | if (((dev->flags&IFF_POINTOPOINT) && !p.iph.daddr) || |
709 | (!(dev->flags&IFF_POINTOPOINT) && p.iph.daddr)) { | 710 | (!(dev->flags&IFF_POINTOPOINT) && p.iph.daddr)) { |
710 | err = -EINVAL; | 711 | err = -EINVAL; |
711 | break; | 712 | break; |
712 | } | 713 | } |
713 | t = (struct ip_tunnel*)dev->priv; | 714 | t = (struct ip_tunnel*)dev->priv; |
714 | ipip_tunnel_unlink(t); | 715 | ipip_tunnel_unlink(t); |
715 | t->parms.iph.saddr = p.iph.saddr; | 716 | t->parms.iph.saddr = p.iph.saddr; |
716 | t->parms.iph.daddr = p.iph.daddr; | 717 | t->parms.iph.daddr = p.iph.daddr; |
717 | memcpy(dev->dev_addr, &p.iph.saddr, 4); | 718 | memcpy(dev->dev_addr, &p.iph.saddr, 4); |
718 | memcpy(dev->broadcast, &p.iph.daddr, 4); | 719 | memcpy(dev->broadcast, &p.iph.daddr, 4); |
719 | ipip_tunnel_link(t); | 720 | ipip_tunnel_link(t); |
720 | netdev_state_change(dev); | 721 | netdev_state_change(dev); |
721 | } | 722 | } |
722 | } | 723 | } |
723 | 724 | ||
724 | if (t) { | 725 | if (t) { |
725 | err = 0; | 726 | err = 0; |
726 | if (cmd == SIOCCHGTUNNEL) { | 727 | if (cmd == SIOCCHGTUNNEL) { |
727 | t->parms.iph.ttl = p.iph.ttl; | 728 | t->parms.iph.ttl = p.iph.ttl; |
728 | t->parms.iph.tos = p.iph.tos; | 729 | t->parms.iph.tos = p.iph.tos; |
729 | t->parms.iph.frag_off = p.iph.frag_off; | 730 | t->parms.iph.frag_off = p.iph.frag_off; |
730 | } | 731 | } |
731 | if (copy_to_user(ifr->ifr_ifru.ifru_data, &t->parms, sizeof(p))) | 732 | if (copy_to_user(ifr->ifr_ifru.ifru_data, &t->parms, sizeof(p))) |
732 | err = -EFAULT; | 733 | err = -EFAULT; |
733 | } else | 734 | } else |
734 | err = (cmd == SIOCADDTUNNEL ? -ENOBUFS : -ENOENT); | 735 | err = (cmd == SIOCADDTUNNEL ? -ENOBUFS : -ENOENT); |
735 | break; | 736 | break; |
736 | 737 | ||
737 | case SIOCDELTUNNEL: | 738 | case SIOCDELTUNNEL: |
738 | err = -EPERM; | 739 | err = -EPERM; |
739 | if (!capable(CAP_NET_ADMIN)) | 740 | if (!capable(CAP_NET_ADMIN)) |
740 | goto done; | 741 | goto done; |
741 | 742 | ||
742 | if (dev == ipip_fb_tunnel_dev) { | 743 | if (dev == ipip_fb_tunnel_dev) { |
743 | err = -EFAULT; | 744 | err = -EFAULT; |
744 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) | 745 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) |
745 | goto done; | 746 | goto done; |
746 | err = -ENOENT; | 747 | err = -ENOENT; |
747 | if ((t = ipip_tunnel_locate(&p, 0)) == NULL) | 748 | if ((t = ipip_tunnel_locate(&p, 0)) == NULL) |
748 | goto done; | 749 | goto done; |
749 | err = -EPERM; | 750 | err = -EPERM; |
750 | if (t->dev == ipip_fb_tunnel_dev) | 751 | if (t->dev == ipip_fb_tunnel_dev) |
751 | goto done; | 752 | goto done; |
752 | dev = t->dev; | 753 | dev = t->dev; |
753 | } | 754 | } |
754 | err = unregister_netdevice(dev); | 755 | err = unregister_netdevice(dev); |
755 | break; | 756 | break; |
756 | 757 | ||
757 | default: | 758 | default: |
758 | err = -EINVAL; | 759 | err = -EINVAL; |
759 | } | 760 | } |
760 | 761 | ||
761 | done: | 762 | done: |
762 | return err; | 763 | return err; |
763 | } | 764 | } |
764 | 765 | ||
765 | static struct net_device_stats *ipip_tunnel_get_stats(struct net_device *dev) | 766 | static struct net_device_stats *ipip_tunnel_get_stats(struct net_device *dev) |
766 | { | 767 | { |
767 | return &(((struct ip_tunnel*)dev->priv)->stat); | 768 | return &(((struct ip_tunnel*)dev->priv)->stat); |
768 | } | 769 | } |
769 | 770 | ||
770 | static int ipip_tunnel_change_mtu(struct net_device *dev, int new_mtu) | 771 | static int ipip_tunnel_change_mtu(struct net_device *dev, int new_mtu) |
771 | { | 772 | { |
772 | if (new_mtu < 68 || new_mtu > 0xFFF8 - sizeof(struct iphdr)) | 773 | if (new_mtu < 68 || new_mtu > 0xFFF8 - sizeof(struct iphdr)) |
773 | return -EINVAL; | 774 | return -EINVAL; |
774 | dev->mtu = new_mtu; | 775 | dev->mtu = new_mtu; |
775 | return 0; | 776 | return 0; |
776 | } | 777 | } |
777 | 778 | ||
778 | static void ipip_tunnel_setup(struct net_device *dev) | 779 | static void ipip_tunnel_setup(struct net_device *dev) |
779 | { | 780 | { |
780 | SET_MODULE_OWNER(dev); | 781 | SET_MODULE_OWNER(dev); |
781 | dev->uninit = ipip_tunnel_uninit; | 782 | dev->uninit = ipip_tunnel_uninit; |
782 | dev->hard_start_xmit = ipip_tunnel_xmit; | 783 | dev->hard_start_xmit = ipip_tunnel_xmit; |
783 | dev->get_stats = ipip_tunnel_get_stats; | 784 | dev->get_stats = ipip_tunnel_get_stats; |
784 | dev->do_ioctl = ipip_tunnel_ioctl; | 785 | dev->do_ioctl = ipip_tunnel_ioctl; |
785 | dev->change_mtu = ipip_tunnel_change_mtu; | 786 | dev->change_mtu = ipip_tunnel_change_mtu; |
786 | dev->destructor = free_netdev; | 787 | dev->destructor = free_netdev; |
787 | 788 | ||
788 | dev->type = ARPHRD_TUNNEL; | 789 | dev->type = ARPHRD_TUNNEL; |
789 | dev->hard_header_len = LL_MAX_HEADER + sizeof(struct iphdr); | 790 | dev->hard_header_len = LL_MAX_HEADER + sizeof(struct iphdr); |
790 | dev->mtu = ETH_DATA_LEN - sizeof(struct iphdr); | 791 | dev->mtu = ETH_DATA_LEN - sizeof(struct iphdr); |
791 | dev->flags = IFF_NOARP; | 792 | dev->flags = IFF_NOARP; |
792 | dev->iflink = 0; | 793 | dev->iflink = 0; |
793 | dev->addr_len = 4; | 794 | dev->addr_len = 4; |
794 | } | 795 | } |
795 | 796 | ||
796 | static int ipip_tunnel_init(struct net_device *dev) | 797 | static int ipip_tunnel_init(struct net_device *dev) |
797 | { | 798 | { |
798 | struct net_device *tdev = NULL; | 799 | struct net_device *tdev = NULL; |
799 | struct ip_tunnel *tunnel; | 800 | struct ip_tunnel *tunnel; |
800 | struct iphdr *iph; | 801 | struct iphdr *iph; |
801 | 802 | ||
802 | tunnel = (struct ip_tunnel*)dev->priv; | 803 | tunnel = (struct ip_tunnel*)dev->priv; |
803 | iph = &tunnel->parms.iph; | 804 | iph = &tunnel->parms.iph; |
804 | 805 | ||
805 | tunnel->dev = dev; | 806 | tunnel->dev = dev; |
806 | strcpy(tunnel->parms.name, dev->name); | 807 | strcpy(tunnel->parms.name, dev->name); |
807 | 808 | ||
808 | memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4); | 809 | memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4); |
809 | memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4); | 810 | memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4); |
810 | 811 | ||
811 | if (iph->daddr) { | 812 | if (iph->daddr) { |
812 | struct flowi fl = { .oif = tunnel->parms.link, | 813 | struct flowi fl = { .oif = tunnel->parms.link, |
813 | .nl_u = { .ip4_u = | 814 | .nl_u = { .ip4_u = |
814 | { .daddr = iph->daddr, | 815 | { .daddr = iph->daddr, |
815 | .saddr = iph->saddr, | 816 | .saddr = iph->saddr, |
816 | .tos = RT_TOS(iph->tos) } }, | 817 | .tos = RT_TOS(iph->tos) } }, |
817 | .proto = IPPROTO_IPIP }; | 818 | .proto = IPPROTO_IPIP }; |
818 | struct rtable *rt; | 819 | struct rtable *rt; |
819 | if (!ip_route_output_key(&rt, &fl)) { | 820 | if (!ip_route_output_key(&rt, &fl)) { |
820 | tdev = rt->u.dst.dev; | 821 | tdev = rt->u.dst.dev; |
821 | ip_rt_put(rt); | 822 | ip_rt_put(rt); |
822 | } | 823 | } |
823 | dev->flags |= IFF_POINTOPOINT; | 824 | dev->flags |= IFF_POINTOPOINT; |
824 | } | 825 | } |
825 | 826 | ||
826 | if (!tdev && tunnel->parms.link) | 827 | if (!tdev && tunnel->parms.link) |
827 | tdev = __dev_get_by_index(tunnel->parms.link); | 828 | tdev = __dev_get_by_index(tunnel->parms.link); |
828 | 829 | ||
829 | if (tdev) { | 830 | if (tdev) { |
830 | dev->hard_header_len = tdev->hard_header_len + sizeof(struct iphdr); | 831 | dev->hard_header_len = tdev->hard_header_len + sizeof(struct iphdr); |
831 | dev->mtu = tdev->mtu - sizeof(struct iphdr); | 832 | dev->mtu = tdev->mtu - sizeof(struct iphdr); |
832 | } | 833 | } |
833 | dev->iflink = tunnel->parms.link; | 834 | dev->iflink = tunnel->parms.link; |
834 | 835 | ||
835 | return 0; | 836 | return 0; |
836 | } | 837 | } |
837 | 838 | ||
838 | static int __init ipip_fb_tunnel_init(struct net_device *dev) | 839 | static int __init ipip_fb_tunnel_init(struct net_device *dev) |
839 | { | 840 | { |
840 | struct ip_tunnel *tunnel = dev->priv; | 841 | struct ip_tunnel *tunnel = dev->priv; |
841 | struct iphdr *iph = &tunnel->parms.iph; | 842 | struct iphdr *iph = &tunnel->parms.iph; |
842 | 843 | ||
843 | tunnel->dev = dev; | 844 | tunnel->dev = dev; |
844 | strcpy(tunnel->parms.name, dev->name); | 845 | strcpy(tunnel->parms.name, dev->name); |
845 | 846 | ||
846 | iph->version = 4; | 847 | iph->version = 4; |
847 | iph->protocol = IPPROTO_IPIP; | 848 | iph->protocol = IPPROTO_IPIP; |
848 | iph->ihl = 5; | 849 | iph->ihl = 5; |
849 | 850 | ||
850 | dev_hold(dev); | 851 | dev_hold(dev); |
851 | tunnels_wc[0] = tunnel; | 852 | tunnels_wc[0] = tunnel; |
852 | return 0; | 853 | return 0; |
853 | } | 854 | } |
854 | 855 | ||
855 | #ifdef CONFIG_INET_TUNNEL | 856 | #ifdef CONFIG_INET_TUNNEL |
856 | static struct xfrm_tunnel ipip_handler = { | 857 | static struct xfrm_tunnel ipip_handler = { |
857 | .handler = ipip_rcv, | 858 | .handler = ipip_rcv, |
858 | .err_handler = ipip_err, | 859 | .err_handler = ipip_err, |
859 | }; | 860 | }; |
860 | 861 | ||
861 | static inline int ipip_register(void) | 862 | static inline int ipip_register(void) |
862 | { | 863 | { |
863 | return xfrm4_tunnel_register(&ipip_handler); | 864 | return xfrm4_tunnel_register(&ipip_handler); |
864 | } | 865 | } |
865 | 866 | ||
866 | static inline int ipip_unregister(void) | 867 | static inline int ipip_unregister(void) |
867 | { | 868 | { |
868 | return xfrm4_tunnel_deregister(&ipip_handler); | 869 | return xfrm4_tunnel_deregister(&ipip_handler); |
869 | } | 870 | } |
870 | #else | 871 | #else |
871 | static struct net_protocol ipip_protocol = { | 872 | static struct net_protocol ipip_protocol = { |
872 | .handler = ipip_rcv, | 873 | .handler = ipip_rcv, |
873 | .err_handler = ipip_err, | 874 | .err_handler = ipip_err, |
874 | .no_policy = 1, | 875 | .no_policy = 1, |
875 | }; | 876 | }; |
876 | 877 | ||
877 | static inline int ipip_register(void) | 878 | static inline int ipip_register(void) |
878 | { | 879 | { |
879 | return inet_add_protocol(&ipip_protocol, IPPROTO_IPIP); | 880 | return inet_add_protocol(&ipip_protocol, IPPROTO_IPIP); |
880 | } | 881 | } |
881 | 882 | ||
882 | static inline int ipip_unregister(void) | 883 | static inline int ipip_unregister(void) |
883 | { | 884 | { |
884 | return inet_del_protocol(&ipip_protocol, IPPROTO_IPIP); | 885 | return inet_del_protocol(&ipip_protocol, IPPROTO_IPIP); |
885 | } | 886 | } |
886 | #endif | 887 | #endif |
887 | 888 | ||
888 | static char banner[] __initdata = | 889 | static char banner[] __initdata = |
889 | KERN_INFO "IPv4 over IPv4 tunneling driver\n"; | 890 | KERN_INFO "IPv4 over IPv4 tunneling driver\n"; |
890 | 891 | ||
891 | static int __init ipip_init(void) | 892 | static int __init ipip_init(void) |
892 | { | 893 | { |
893 | int err; | 894 | int err; |
894 | 895 | ||
895 | printk(banner); | 896 | printk(banner); |
896 | 897 | ||
897 | if (ipip_register() < 0) { | 898 | if (ipip_register() < 0) { |
898 | printk(KERN_INFO "ipip init: can't register tunnel\n"); | 899 | printk(KERN_INFO "ipip init: can't register tunnel\n"); |
899 | return -EAGAIN; | 900 | return -EAGAIN; |
900 | } | 901 | } |
901 | 902 | ||
902 | ipip_fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), | 903 | ipip_fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), |
903 | "tunl0", | 904 | "tunl0", |
904 | ipip_tunnel_setup); | 905 | ipip_tunnel_setup); |
905 | if (!ipip_fb_tunnel_dev) { | 906 | if (!ipip_fb_tunnel_dev) { |
906 | err = -ENOMEM; | 907 | err = -ENOMEM; |
907 | goto err1; | 908 | goto err1; |
908 | } | 909 | } |
909 | 910 | ||
910 | ipip_fb_tunnel_dev->init = ipip_fb_tunnel_init; | 911 | ipip_fb_tunnel_dev->init = ipip_fb_tunnel_init; |
911 | 912 | ||
912 | if ((err = register_netdev(ipip_fb_tunnel_dev))) | 913 | if ((err = register_netdev(ipip_fb_tunnel_dev))) |
913 | goto err2; | 914 | goto err2; |
914 | out: | 915 | out: |
915 | return err; | 916 | return err; |
916 | err2: | 917 | err2: |
917 | free_netdev(ipip_fb_tunnel_dev); | 918 | free_netdev(ipip_fb_tunnel_dev); |
918 | err1: | 919 | err1: |
919 | ipip_unregister(); | 920 | ipip_unregister(); |
920 | goto out; | 921 | goto out; |
921 | } | 922 | } |
922 | 923 | ||
923 | static void __exit ipip_destroy_tunnels(void) | 924 | static void __exit ipip_destroy_tunnels(void) |
924 | { | 925 | { |
925 | int prio; | 926 | int prio; |
926 | 927 | ||
927 | for (prio = 1; prio < 4; prio++) { | 928 | for (prio = 1; prio < 4; prio++) { |
928 | int h; | 929 | int h; |
929 | for (h = 0; h < HASH_SIZE; h++) { | 930 | for (h = 0; h < HASH_SIZE; h++) { |
930 | struct ip_tunnel *t; | 931 | struct ip_tunnel *t; |
931 | while ((t = tunnels[prio][h]) != NULL) | 932 | while ((t = tunnels[prio][h]) != NULL) |
932 | unregister_netdevice(t->dev); | 933 | unregister_netdevice(t->dev); |
933 | } | 934 | } |
934 | } | 935 | } |
935 | } | 936 | } |
936 | 937 | ||
937 | static void __exit ipip_fini(void) | 938 | static void __exit ipip_fini(void) |
938 | { | 939 | { |
939 | if (ipip_unregister() < 0) | 940 | if (ipip_unregister() < 0) |
940 | printk(KERN_INFO "ipip close: can't deregister tunnel\n"); | 941 | printk(KERN_INFO "ipip close: can't deregister tunnel\n"); |
941 | 942 | ||
942 | rtnl_lock(); | 943 | rtnl_lock(); |
943 | ipip_destroy_tunnels(); | 944 | ipip_destroy_tunnels(); |
944 | unregister_netdevice(ipip_fb_tunnel_dev); | 945 | unregister_netdevice(ipip_fb_tunnel_dev); |
945 | rtnl_unlock(); | 946 | rtnl_unlock(); |
946 | } | 947 | } |
947 | 948 | ||
948 | module_init(ipip_init); | 949 | module_init(ipip_init); |
949 | module_exit(ipip_fini); | 950 | module_exit(ipip_fini); |
950 | MODULE_LICENSE("GPL"); | 951 | MODULE_LICENSE("GPL"); |
951 | 952 |
net/ipv6/sit.c
1 | /* | 1 | /* |
2 | * IPv6 over IPv4 tunnel device - Simple Internet Transition (SIT) | 2 | * IPv6 over IPv4 tunnel device - Simple Internet Transition (SIT) |
3 | * Linux INET6 implementation | 3 | * Linux INET6 implementation |
4 | * | 4 | * |
5 | * Authors: | 5 | * Authors: |
6 | * Pedro Roque <roque@di.fc.ul.pt> | 6 | * Pedro Roque <roque@di.fc.ul.pt> |
7 | * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> | 7 | * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> |
8 | * | 8 | * |
9 | * $Id: sit.c,v 1.53 2001/09/25 05:09:53 davem Exp $ | 9 | * $Id: sit.c,v 1.53 2001/09/25 05:09:53 davem Exp $ |
10 | * | 10 | * |
11 | * This program is free software; you can redistribute it and/or | 11 | * This program is free software; you can redistribute it and/or |
12 | * modify it under the terms of the GNU General Public License | 12 | * modify it under the terms of the GNU General Public License |
13 | * as published by the Free Software Foundation; either version | 13 | * as published by the Free Software Foundation; either version |
14 | * 2 of the License, or (at your option) any later version. | 14 | * 2 of the License, or (at your option) any later version. |
15 | * | 15 | * |
16 | * Changes: | 16 | * Changes: |
17 | * Roger Venning <r.venning@telstra.com>: 6to4 support | 17 | * Roger Venning <r.venning@telstra.com>: 6to4 support |
18 | * Nate Thompson <nate@thebog.net>: 6to4 support | 18 | * Nate Thompson <nate@thebog.net>: 6to4 support |
19 | */ | 19 | */ |
20 | 20 | ||
21 | #include <linux/config.h> | 21 | #include <linux/config.h> |
22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
23 | #include <linux/errno.h> | 23 | #include <linux/errno.h> |
24 | #include <linux/types.h> | 24 | #include <linux/types.h> |
25 | #include <linux/socket.h> | 25 | #include <linux/socket.h> |
26 | #include <linux/sockios.h> | 26 | #include <linux/sockios.h> |
27 | #include <linux/sched.h> | 27 | #include <linux/sched.h> |
28 | #include <linux/net.h> | 28 | #include <linux/net.h> |
29 | #include <linux/in6.h> | 29 | #include <linux/in6.h> |
30 | #include <linux/netdevice.h> | 30 | #include <linux/netdevice.h> |
31 | #include <linux/if_arp.h> | 31 | #include <linux/if_arp.h> |
32 | #include <linux/icmp.h> | 32 | #include <linux/icmp.h> |
33 | #include <asm/uaccess.h> | 33 | #include <asm/uaccess.h> |
34 | #include <linux/init.h> | 34 | #include <linux/init.h> |
35 | #include <linux/netfilter_ipv4.h> | 35 | #include <linux/netfilter_ipv4.h> |
36 | #include <linux/if_ether.h> | 36 | #include <linux/if_ether.h> |
37 | 37 | ||
38 | #include <net/sock.h> | 38 | #include <net/sock.h> |
39 | #include <net/snmp.h> | 39 | #include <net/snmp.h> |
40 | 40 | ||
41 | #include <net/ipv6.h> | 41 | #include <net/ipv6.h> |
42 | #include <net/protocol.h> | 42 | #include <net/protocol.h> |
43 | #include <net/transp_v6.h> | 43 | #include <net/transp_v6.h> |
44 | #include <net/ip6_fib.h> | 44 | #include <net/ip6_fib.h> |
45 | #include <net/ip6_route.h> | 45 | #include <net/ip6_route.h> |
46 | #include <net/ndisc.h> | 46 | #include <net/ndisc.h> |
47 | #include <net/addrconf.h> | 47 | #include <net/addrconf.h> |
48 | #include <net/ip.h> | 48 | #include <net/ip.h> |
49 | #include <net/udp.h> | 49 | #include <net/udp.h> |
50 | #include <net/icmp.h> | 50 | #include <net/icmp.h> |
51 | #include <net/ipip.h> | 51 | #include <net/ipip.h> |
52 | #include <net/inet_ecn.h> | 52 | #include <net/inet_ecn.h> |
53 | #include <net/xfrm.h> | 53 | #include <net/xfrm.h> |
54 | #include <net/dsfield.h> | 54 | #include <net/dsfield.h> |
55 | 55 | ||
56 | /* | 56 | /* |
57 | This version of net/ipv6/sit.c is cloned of net/ipv4/ip_gre.c | 57 | This version of net/ipv6/sit.c is cloned of net/ipv4/ip_gre.c |
58 | 58 | ||
59 | For comments look at net/ipv4/ip_gre.c --ANK | 59 | For comments look at net/ipv4/ip_gre.c --ANK |
60 | */ | 60 | */ |
61 | 61 | ||
62 | #define HASH_SIZE 16 | 62 | #define HASH_SIZE 16 |
63 | #define HASH(addr) ((addr^(addr>>4))&0xF) | 63 | #define HASH(addr) ((addr^(addr>>4))&0xF) |
64 | 64 | ||
65 | static int ipip6_fb_tunnel_init(struct net_device *dev); | 65 | static int ipip6_fb_tunnel_init(struct net_device *dev); |
66 | static int ipip6_tunnel_init(struct net_device *dev); | 66 | static int ipip6_tunnel_init(struct net_device *dev); |
67 | static void ipip6_tunnel_setup(struct net_device *dev); | 67 | static void ipip6_tunnel_setup(struct net_device *dev); |
68 | 68 | ||
69 | static struct net_device *ipip6_fb_tunnel_dev; | 69 | static struct net_device *ipip6_fb_tunnel_dev; |
70 | 70 | ||
71 | static struct ip_tunnel *tunnels_r_l[HASH_SIZE]; | 71 | static struct ip_tunnel *tunnels_r_l[HASH_SIZE]; |
72 | static struct ip_tunnel *tunnels_r[HASH_SIZE]; | 72 | static struct ip_tunnel *tunnels_r[HASH_SIZE]; |
73 | static struct ip_tunnel *tunnels_l[HASH_SIZE]; | 73 | static struct ip_tunnel *tunnels_l[HASH_SIZE]; |
74 | static struct ip_tunnel *tunnels_wc[1]; | 74 | static struct ip_tunnel *tunnels_wc[1]; |
75 | static struct ip_tunnel **tunnels[4] = { tunnels_wc, tunnels_l, tunnels_r, tunnels_r_l }; | 75 | static struct ip_tunnel **tunnels[4] = { tunnels_wc, tunnels_l, tunnels_r, tunnels_r_l }; |
76 | 76 | ||
77 | static DEFINE_RWLOCK(ipip6_lock); | 77 | static DEFINE_RWLOCK(ipip6_lock); |
78 | 78 | ||
79 | static struct ip_tunnel * ipip6_tunnel_lookup(u32 remote, u32 local) | 79 | static struct ip_tunnel * ipip6_tunnel_lookup(u32 remote, u32 local) |
80 | { | 80 | { |
81 | unsigned h0 = HASH(remote); | 81 | unsigned h0 = HASH(remote); |
82 | unsigned h1 = HASH(local); | 82 | unsigned h1 = HASH(local); |
83 | struct ip_tunnel *t; | 83 | struct ip_tunnel *t; |
84 | 84 | ||
85 | for (t = tunnels_r_l[h0^h1]; t; t = t->next) { | 85 | for (t = tunnels_r_l[h0^h1]; t; t = t->next) { |
86 | if (local == t->parms.iph.saddr && | 86 | if (local == t->parms.iph.saddr && |
87 | remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP)) | 87 | remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP)) |
88 | return t; | 88 | return t; |
89 | } | 89 | } |
90 | for (t = tunnels_r[h0]; t; t = t->next) { | 90 | for (t = tunnels_r[h0]; t; t = t->next) { |
91 | if (remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP)) | 91 | if (remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP)) |
92 | return t; | 92 | return t; |
93 | } | 93 | } |
94 | for (t = tunnels_l[h1]; t; t = t->next) { | 94 | for (t = tunnels_l[h1]; t; t = t->next) { |
95 | if (local == t->parms.iph.saddr && (t->dev->flags&IFF_UP)) | 95 | if (local == t->parms.iph.saddr && (t->dev->flags&IFF_UP)) |
96 | return t; | 96 | return t; |
97 | } | 97 | } |
98 | if ((t = tunnels_wc[0]) != NULL && (t->dev->flags&IFF_UP)) | 98 | if ((t = tunnels_wc[0]) != NULL && (t->dev->flags&IFF_UP)) |
99 | return t; | 99 | return t; |
100 | return NULL; | 100 | return NULL; |
101 | } | 101 | } |
102 | 102 | ||
103 | static struct ip_tunnel ** ipip6_bucket(struct ip_tunnel *t) | 103 | static struct ip_tunnel ** ipip6_bucket(struct ip_tunnel *t) |
104 | { | 104 | { |
105 | u32 remote = t->parms.iph.daddr; | 105 | u32 remote = t->parms.iph.daddr; |
106 | u32 local = t->parms.iph.saddr; | 106 | u32 local = t->parms.iph.saddr; |
107 | unsigned h = 0; | 107 | unsigned h = 0; |
108 | int prio = 0; | 108 | int prio = 0; |
109 | 109 | ||
110 | if (remote) { | 110 | if (remote) { |
111 | prio |= 2; | 111 | prio |= 2; |
112 | h ^= HASH(remote); | 112 | h ^= HASH(remote); |
113 | } | 113 | } |
114 | if (local) { | 114 | if (local) { |
115 | prio |= 1; | 115 | prio |= 1; |
116 | h ^= HASH(local); | 116 | h ^= HASH(local); |
117 | } | 117 | } |
118 | return &tunnels[prio][h]; | 118 | return &tunnels[prio][h]; |
119 | } | 119 | } |
120 | 120 | ||
121 | static void ipip6_tunnel_unlink(struct ip_tunnel *t) | 121 | static void ipip6_tunnel_unlink(struct ip_tunnel *t) |
122 | { | 122 | { |
123 | struct ip_tunnel **tp; | 123 | struct ip_tunnel **tp; |
124 | 124 | ||
125 | for (tp = ipip6_bucket(t); *tp; tp = &(*tp)->next) { | 125 | for (tp = ipip6_bucket(t); *tp; tp = &(*tp)->next) { |
126 | if (t == *tp) { | 126 | if (t == *tp) { |
127 | write_lock_bh(&ipip6_lock); | 127 | write_lock_bh(&ipip6_lock); |
128 | *tp = t->next; | 128 | *tp = t->next; |
129 | write_unlock_bh(&ipip6_lock); | 129 | write_unlock_bh(&ipip6_lock); |
130 | break; | 130 | break; |
131 | } | 131 | } |
132 | } | 132 | } |
133 | } | 133 | } |
134 | 134 | ||
135 | static void ipip6_tunnel_link(struct ip_tunnel *t) | 135 | static void ipip6_tunnel_link(struct ip_tunnel *t) |
136 | { | 136 | { |
137 | struct ip_tunnel **tp = ipip6_bucket(t); | 137 | struct ip_tunnel **tp = ipip6_bucket(t); |
138 | 138 | ||
139 | t->next = *tp; | 139 | t->next = *tp; |
140 | write_lock_bh(&ipip6_lock); | 140 | write_lock_bh(&ipip6_lock); |
141 | *tp = t; | 141 | *tp = t; |
142 | write_unlock_bh(&ipip6_lock); | 142 | write_unlock_bh(&ipip6_lock); |
143 | } | 143 | } |
144 | 144 | ||
145 | static struct ip_tunnel * ipip6_tunnel_locate(struct ip_tunnel_parm *parms, int create) | 145 | static struct ip_tunnel * ipip6_tunnel_locate(struct ip_tunnel_parm *parms, int create) |
146 | { | 146 | { |
147 | u32 remote = parms->iph.daddr; | 147 | u32 remote = parms->iph.daddr; |
148 | u32 local = parms->iph.saddr; | 148 | u32 local = parms->iph.saddr; |
149 | struct ip_tunnel *t, **tp, *nt; | 149 | struct ip_tunnel *t, **tp, *nt; |
150 | struct net_device *dev; | 150 | struct net_device *dev; |
151 | unsigned h = 0; | 151 | unsigned h = 0; |
152 | int prio = 0; | 152 | int prio = 0; |
153 | char name[IFNAMSIZ]; | 153 | char name[IFNAMSIZ]; |
154 | 154 | ||
155 | if (remote) { | 155 | if (remote) { |
156 | prio |= 2; | 156 | prio |= 2; |
157 | h ^= HASH(remote); | 157 | h ^= HASH(remote); |
158 | } | 158 | } |
159 | if (local) { | 159 | if (local) { |
160 | prio |= 1; | 160 | prio |= 1; |
161 | h ^= HASH(local); | 161 | h ^= HASH(local); |
162 | } | 162 | } |
163 | for (tp = &tunnels[prio][h]; (t = *tp) != NULL; tp = &t->next) { | 163 | for (tp = &tunnels[prio][h]; (t = *tp) != NULL; tp = &t->next) { |
164 | if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr) | 164 | if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr) |
165 | return t; | 165 | return t; |
166 | } | 166 | } |
167 | if (!create) | 167 | if (!create) |
168 | goto failed; | 168 | goto failed; |
169 | 169 | ||
170 | if (parms->name[0]) | 170 | if (parms->name[0]) |
171 | strlcpy(name, parms->name, IFNAMSIZ); | 171 | strlcpy(name, parms->name, IFNAMSIZ); |
172 | else { | 172 | else { |
173 | int i; | 173 | int i; |
174 | for (i=1; i<100; i++) { | 174 | for (i=1; i<100; i++) { |
175 | sprintf(name, "sit%d", i); | 175 | sprintf(name, "sit%d", i); |
176 | if (__dev_get_by_name(name) == NULL) | 176 | if (__dev_get_by_name(name) == NULL) |
177 | break; | 177 | break; |
178 | } | 178 | } |
179 | if (i==100) | 179 | if (i==100) |
180 | goto failed; | 180 | goto failed; |
181 | } | 181 | } |
182 | 182 | ||
183 | dev = alloc_netdev(sizeof(*t), name, ipip6_tunnel_setup); | 183 | dev = alloc_netdev(sizeof(*t), name, ipip6_tunnel_setup); |
184 | if (dev == NULL) | 184 | if (dev == NULL) |
185 | return NULL; | 185 | return NULL; |
186 | 186 | ||
187 | nt = dev->priv; | 187 | nt = dev->priv; |
188 | dev->init = ipip6_tunnel_init; | 188 | dev->init = ipip6_tunnel_init; |
189 | nt->parms = *parms; | 189 | nt->parms = *parms; |
190 | 190 | ||
191 | if (register_netdevice(dev) < 0) { | 191 | if (register_netdevice(dev) < 0) { |
192 | free_netdev(dev); | 192 | free_netdev(dev); |
193 | goto failed; | 193 | goto failed; |
194 | } | 194 | } |
195 | 195 | ||
196 | dev_hold(dev); | 196 | dev_hold(dev); |
197 | 197 | ||
198 | ipip6_tunnel_link(nt); | 198 | ipip6_tunnel_link(nt); |
199 | return nt; | 199 | return nt; |
200 | 200 | ||
201 | failed: | 201 | failed: |
202 | return NULL; | 202 | return NULL; |
203 | } | 203 | } |
204 | 204 | ||
205 | static void ipip6_tunnel_uninit(struct net_device *dev) | 205 | static void ipip6_tunnel_uninit(struct net_device *dev) |
206 | { | 206 | { |
207 | if (dev == ipip6_fb_tunnel_dev) { | 207 | if (dev == ipip6_fb_tunnel_dev) { |
208 | write_lock_bh(&ipip6_lock); | 208 | write_lock_bh(&ipip6_lock); |
209 | tunnels_wc[0] = NULL; | 209 | tunnels_wc[0] = NULL; |
210 | write_unlock_bh(&ipip6_lock); | 210 | write_unlock_bh(&ipip6_lock); |
211 | dev_put(dev); | 211 | dev_put(dev); |
212 | } else { | 212 | } else { |
213 | ipip6_tunnel_unlink((struct ip_tunnel*)dev->priv); | 213 | ipip6_tunnel_unlink((struct ip_tunnel*)dev->priv); |
214 | dev_put(dev); | 214 | dev_put(dev); |
215 | } | 215 | } |
216 | } | 216 | } |
217 | 217 | ||
218 | 218 | ||
219 | static void ipip6_err(struct sk_buff *skb, u32 info) | 219 | static void ipip6_err(struct sk_buff *skb, u32 info) |
220 | { | 220 | { |
221 | #ifndef I_WISH_WORLD_WERE_PERFECT | 221 | #ifndef I_WISH_WORLD_WERE_PERFECT |
222 | 222 | ||
223 | /* It is not :-( All the routers (except for Linux) return only | 223 | /* It is not :-( All the routers (except for Linux) return only |
224 | 8 bytes of packet payload. It means, that precise relaying of | 224 | 8 bytes of packet payload. It means, that precise relaying of |
225 | ICMP in the real Internet is absolutely infeasible. | 225 | ICMP in the real Internet is absolutely infeasible. |
226 | */ | 226 | */ |
227 | struct iphdr *iph = (struct iphdr*)skb->data; | 227 | struct iphdr *iph = (struct iphdr*)skb->data; |
228 | int type = skb->h.icmph->type; | 228 | int type = skb->h.icmph->type; |
229 | int code = skb->h.icmph->code; | 229 | int code = skb->h.icmph->code; |
230 | struct ip_tunnel *t; | 230 | struct ip_tunnel *t; |
231 | 231 | ||
232 | switch (type) { | 232 | switch (type) { |
233 | default: | 233 | default: |
234 | case ICMP_PARAMETERPROB: | 234 | case ICMP_PARAMETERPROB: |
235 | return; | 235 | return; |
236 | 236 | ||
237 | case ICMP_DEST_UNREACH: | 237 | case ICMP_DEST_UNREACH: |
238 | switch (code) { | 238 | switch (code) { |
239 | case ICMP_SR_FAILED: | 239 | case ICMP_SR_FAILED: |
240 | case ICMP_PORT_UNREACH: | 240 | case ICMP_PORT_UNREACH: |
241 | /* Impossible event. */ | 241 | /* Impossible event. */ |
242 | return; | 242 | return; |
243 | case ICMP_FRAG_NEEDED: | 243 | case ICMP_FRAG_NEEDED: |
244 | /* Soft state for pmtu is maintained by IP core. */ | 244 | /* Soft state for pmtu is maintained by IP core. */ |
245 | return; | 245 | return; |
246 | default: | 246 | default: |
247 | /* All others are translated to HOST_UNREACH. | 247 | /* All others are translated to HOST_UNREACH. |
248 | rfc2003 contains "deep thoughts" about NET_UNREACH, | 248 | rfc2003 contains "deep thoughts" about NET_UNREACH, |
249 | I believe they are just ether pollution. --ANK | 249 | I believe they are just ether pollution. --ANK |
250 | */ | 250 | */ |
251 | break; | 251 | break; |
252 | } | 252 | } |
253 | break; | 253 | break; |
254 | case ICMP_TIME_EXCEEDED: | 254 | case ICMP_TIME_EXCEEDED: |
255 | if (code != ICMP_EXC_TTL) | 255 | if (code != ICMP_EXC_TTL) |
256 | return; | 256 | return; |
257 | break; | 257 | break; |
258 | } | 258 | } |
259 | 259 | ||
260 | read_lock(&ipip6_lock); | 260 | read_lock(&ipip6_lock); |
261 | t = ipip6_tunnel_lookup(iph->daddr, iph->saddr); | 261 | t = ipip6_tunnel_lookup(iph->daddr, iph->saddr); |
262 | if (t == NULL || t->parms.iph.daddr == 0) | 262 | if (t == NULL || t->parms.iph.daddr == 0) |
263 | goto out; | 263 | goto out; |
264 | if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED) | 264 | if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED) |
265 | goto out; | 265 | goto out; |
266 | 266 | ||
267 | if (jiffies - t->err_time < IPTUNNEL_ERR_TIMEO) | 267 | if (jiffies - t->err_time < IPTUNNEL_ERR_TIMEO) |
268 | t->err_count++; | 268 | t->err_count++; |
269 | else | 269 | else |
270 | t->err_count = 1; | 270 | t->err_count = 1; |
271 | t->err_time = jiffies; | 271 | t->err_time = jiffies; |
272 | out: | 272 | out: |
273 | read_unlock(&ipip6_lock); | 273 | read_unlock(&ipip6_lock); |
274 | return; | 274 | return; |
275 | #else | 275 | #else |
276 | struct iphdr *iph = (struct iphdr*)dp; | 276 | struct iphdr *iph = (struct iphdr*)dp; |
277 | int hlen = iph->ihl<<2; | 277 | int hlen = iph->ihl<<2; |
278 | struct ipv6hdr *iph6; | 278 | struct ipv6hdr *iph6; |
279 | int type = skb->h.icmph->type; | 279 | int type = skb->h.icmph->type; |
280 | int code = skb->h.icmph->code; | 280 | int code = skb->h.icmph->code; |
281 | int rel_type = 0; | 281 | int rel_type = 0; |
282 | int rel_code = 0; | 282 | int rel_code = 0; |
283 | int rel_info = 0; | 283 | int rel_info = 0; |
284 | struct sk_buff *skb2; | 284 | struct sk_buff *skb2; |
285 | struct rt6_info *rt6i; | 285 | struct rt6_info *rt6i; |
286 | 286 | ||
287 | if (len < hlen + sizeof(struct ipv6hdr)) | 287 | if (len < hlen + sizeof(struct ipv6hdr)) |
288 | return; | 288 | return; |
289 | iph6 = (struct ipv6hdr*)(dp + hlen); | 289 | iph6 = (struct ipv6hdr*)(dp + hlen); |
290 | 290 | ||
291 | switch (type) { | 291 | switch (type) { |
292 | default: | 292 | default: |
293 | return; | 293 | return; |
294 | case ICMP_PARAMETERPROB: | 294 | case ICMP_PARAMETERPROB: |
295 | if (skb->h.icmph->un.gateway < hlen) | 295 | if (skb->h.icmph->un.gateway < hlen) |
296 | return; | 296 | return; |
297 | 297 | ||
298 | /* So... This guy found something strange INSIDE encapsulated | 298 | /* So... This guy found something strange INSIDE encapsulated |
299 | packet. Well, he is fool, but what can we do ? | 299 | packet. Well, he is fool, but what can we do ? |
300 | */ | 300 | */ |
301 | rel_type = ICMPV6_PARAMPROB; | 301 | rel_type = ICMPV6_PARAMPROB; |
302 | rel_info = skb->h.icmph->un.gateway - hlen; | 302 | rel_info = skb->h.icmph->un.gateway - hlen; |
303 | break; | 303 | break; |
304 | 304 | ||
305 | case ICMP_DEST_UNREACH: | 305 | case ICMP_DEST_UNREACH: |
306 | switch (code) { | 306 | switch (code) { |
307 | case ICMP_SR_FAILED: | 307 | case ICMP_SR_FAILED: |
308 | case ICMP_PORT_UNREACH: | 308 | case ICMP_PORT_UNREACH: |
309 | /* Impossible event. */ | 309 | /* Impossible event. */ |
310 | return; | 310 | return; |
311 | case ICMP_FRAG_NEEDED: | 311 | case ICMP_FRAG_NEEDED: |
312 | /* Too complicated case ... */ | 312 | /* Too complicated case ... */ |
313 | return; | 313 | return; |
314 | default: | 314 | default: |
315 | /* All others are translated to HOST_UNREACH. | 315 | /* All others are translated to HOST_UNREACH. |
316 | rfc2003 contains "deep thoughts" about NET_UNREACH, | 316 | rfc2003 contains "deep thoughts" about NET_UNREACH, |
317 | I believe, it is just ether pollution. --ANK | 317 | I believe, it is just ether pollution. --ANK |
318 | */ | 318 | */ |
319 | rel_type = ICMPV6_DEST_UNREACH; | 319 | rel_type = ICMPV6_DEST_UNREACH; |
320 | rel_code = ICMPV6_ADDR_UNREACH; | 320 | rel_code = ICMPV6_ADDR_UNREACH; |
321 | break; | 321 | break; |
322 | } | 322 | } |
323 | break; | 323 | break; |
324 | case ICMP_TIME_EXCEEDED: | 324 | case ICMP_TIME_EXCEEDED: |
325 | if (code != ICMP_EXC_TTL) | 325 | if (code != ICMP_EXC_TTL) |
326 | return; | 326 | return; |
327 | rel_type = ICMPV6_TIME_EXCEED; | 327 | rel_type = ICMPV6_TIME_EXCEED; |
328 | rel_code = ICMPV6_EXC_HOPLIMIT; | 328 | rel_code = ICMPV6_EXC_HOPLIMIT; |
329 | break; | 329 | break; |
330 | } | 330 | } |
331 | 331 | ||
332 | /* Prepare fake skb to feed it to icmpv6_send */ | 332 | /* Prepare fake skb to feed it to icmpv6_send */ |
333 | skb2 = skb_clone(skb, GFP_ATOMIC); | 333 | skb2 = skb_clone(skb, GFP_ATOMIC); |
334 | if (skb2 == NULL) | 334 | if (skb2 == NULL) |
335 | return; | 335 | return; |
336 | dst_release(skb2->dst); | 336 | dst_release(skb2->dst); |
337 | skb2->dst = NULL; | 337 | skb2->dst = NULL; |
338 | skb_pull(skb2, skb->data - (u8*)iph6); | 338 | skb_pull(skb2, skb->data - (u8*)iph6); |
339 | skb2->nh.raw = skb2->data; | 339 | skb2->nh.raw = skb2->data; |
340 | 340 | ||
341 | /* Try to guess incoming interface */ | 341 | /* Try to guess incoming interface */ |
342 | rt6i = rt6_lookup(&iph6->saddr, NULL, NULL, 0); | 342 | rt6i = rt6_lookup(&iph6->saddr, NULL, NULL, 0); |
343 | if (rt6i && rt6i->rt6i_dev) { | 343 | if (rt6i && rt6i->rt6i_dev) { |
344 | skb2->dev = rt6i->rt6i_dev; | 344 | skb2->dev = rt6i->rt6i_dev; |
345 | 345 | ||
346 | rt6i = rt6_lookup(&iph6->daddr, &iph6->saddr, NULL, 0); | 346 | rt6i = rt6_lookup(&iph6->daddr, &iph6->saddr, NULL, 0); |
347 | 347 | ||
348 | if (rt6i && rt6i->rt6i_dev && rt6i->rt6i_dev->type == ARPHRD_SIT) { | 348 | if (rt6i && rt6i->rt6i_dev && rt6i->rt6i_dev->type == ARPHRD_SIT) { |
349 | struct ip_tunnel * t = (struct ip_tunnel*)rt6i->rt6i_dev->priv; | 349 | struct ip_tunnel * t = (struct ip_tunnel*)rt6i->rt6i_dev->priv; |
350 | if (rel_type == ICMPV6_TIME_EXCEED && t->parms.iph.ttl) { | 350 | if (rel_type == ICMPV6_TIME_EXCEED && t->parms.iph.ttl) { |
351 | rel_type = ICMPV6_DEST_UNREACH; | 351 | rel_type = ICMPV6_DEST_UNREACH; |
352 | rel_code = ICMPV6_ADDR_UNREACH; | 352 | rel_code = ICMPV6_ADDR_UNREACH; |
353 | } | 353 | } |
354 | icmpv6_send(skb2, rel_type, rel_code, rel_info, skb2->dev); | 354 | icmpv6_send(skb2, rel_type, rel_code, rel_info, skb2->dev); |
355 | } | 355 | } |
356 | } | 356 | } |
357 | kfree_skb(skb2); | 357 | kfree_skb(skb2); |
358 | return; | 358 | return; |
359 | #endif | 359 | #endif |
360 | } | 360 | } |
361 | 361 | ||
362 | static inline void ipip6_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb) | 362 | static inline void ipip6_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb) |
363 | { | 363 | { |
364 | if (INET_ECN_is_ce(iph->tos)) | 364 | if (INET_ECN_is_ce(iph->tos)) |
365 | IP6_ECN_set_ce(skb->nh.ipv6h); | 365 | IP6_ECN_set_ce(skb->nh.ipv6h); |
366 | } | 366 | } |
367 | 367 | ||
368 | static int ipip6_rcv(struct sk_buff *skb) | 368 | static int ipip6_rcv(struct sk_buff *skb) |
369 | { | 369 | { |
370 | struct iphdr *iph; | 370 | struct iphdr *iph; |
371 | struct ip_tunnel *tunnel; | 371 | struct ip_tunnel *tunnel; |
372 | 372 | ||
373 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) | 373 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) |
374 | goto out; | 374 | goto out; |
375 | 375 | ||
376 | iph = skb->nh.iph; | 376 | iph = skb->nh.iph; |
377 | 377 | ||
378 | read_lock(&ipip6_lock); | 378 | read_lock(&ipip6_lock); |
379 | if ((tunnel = ipip6_tunnel_lookup(iph->saddr, iph->daddr)) != NULL) { | 379 | if ((tunnel = ipip6_tunnel_lookup(iph->saddr, iph->daddr)) != NULL) { |
380 | secpath_reset(skb); | 380 | secpath_reset(skb); |
381 | skb->mac.raw = skb->nh.raw; | 381 | skb->mac.raw = skb->nh.raw; |
382 | skb->nh.raw = skb->data; | 382 | skb->nh.raw = skb->data; |
383 | memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options)); | 383 | memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options)); |
384 | IPCB(skb)->flags = 0; | ||
384 | skb->protocol = htons(ETH_P_IPV6); | 385 | skb->protocol = htons(ETH_P_IPV6); |
385 | skb->pkt_type = PACKET_HOST; | 386 | skb->pkt_type = PACKET_HOST; |
386 | tunnel->stat.rx_packets++; | 387 | tunnel->stat.rx_packets++; |
387 | tunnel->stat.rx_bytes += skb->len; | 388 | tunnel->stat.rx_bytes += skb->len; |
388 | skb->dev = tunnel->dev; | 389 | skb->dev = tunnel->dev; |
389 | dst_release(skb->dst); | 390 | dst_release(skb->dst); |
390 | skb->dst = NULL; | 391 | skb->dst = NULL; |
391 | nf_reset(skb); | 392 | nf_reset(skb); |
392 | ipip6_ecn_decapsulate(iph, skb); | 393 | ipip6_ecn_decapsulate(iph, skb); |
393 | netif_rx(skb); | 394 | netif_rx(skb); |
394 | read_unlock(&ipip6_lock); | 395 | read_unlock(&ipip6_lock); |
395 | return 0; | 396 | return 0; |
396 | } | 397 | } |
397 | 398 | ||
398 | icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, 0); | 399 | icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, 0); |
399 | kfree_skb(skb); | 400 | kfree_skb(skb); |
400 | read_unlock(&ipip6_lock); | 401 | read_unlock(&ipip6_lock); |
401 | out: | 402 | out: |
402 | return 0; | 403 | return 0; |
403 | } | 404 | } |
404 | 405 | ||
405 | /* Returns the embedded IPv4 address if the IPv6 address | 406 | /* Returns the embedded IPv4 address if the IPv6 address |
406 | comes from 6to4 (RFC 3056) addr space */ | 407 | comes from 6to4 (RFC 3056) addr space */ |
407 | 408 | ||
408 | static inline u32 try_6to4(struct in6_addr *v6dst) | 409 | static inline u32 try_6to4(struct in6_addr *v6dst) |
409 | { | 410 | { |
410 | u32 dst = 0; | 411 | u32 dst = 0; |
411 | 412 | ||
412 | if (v6dst->s6_addr16[0] == htons(0x2002)) { | 413 | if (v6dst->s6_addr16[0] == htons(0x2002)) { |
413 | /* 6to4 v6 addr has 16 bits prefix, 32 v4addr, 16 SLA, ... */ | 414 | /* 6to4 v6 addr has 16 bits prefix, 32 v4addr, 16 SLA, ... */ |
414 | memcpy(&dst, &v6dst->s6_addr16[1], 4); | 415 | memcpy(&dst, &v6dst->s6_addr16[1], 4); |
415 | } | 416 | } |
416 | return dst; | 417 | return dst; |
417 | } | 418 | } |
418 | 419 | ||
419 | /* | 420 | /* |
420 | * This function assumes it is being called from dev_queue_xmit() | 421 | * This function assumes it is being called from dev_queue_xmit() |
421 | * and that skb is filled properly by that function. | 422 | * and that skb is filled properly by that function. |
422 | */ | 423 | */ |
423 | 424 | ||
424 | static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | 425 | static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) |
425 | { | 426 | { |
426 | struct ip_tunnel *tunnel = (struct ip_tunnel*)dev->priv; | 427 | struct ip_tunnel *tunnel = (struct ip_tunnel*)dev->priv; |
427 | struct net_device_stats *stats = &tunnel->stat; | 428 | struct net_device_stats *stats = &tunnel->stat; |
428 | struct iphdr *tiph = &tunnel->parms.iph; | 429 | struct iphdr *tiph = &tunnel->parms.iph; |
429 | struct ipv6hdr *iph6 = skb->nh.ipv6h; | 430 | struct ipv6hdr *iph6 = skb->nh.ipv6h; |
430 | u8 tos = tunnel->parms.iph.tos; | 431 | u8 tos = tunnel->parms.iph.tos; |
431 | struct rtable *rt; /* Route to the other host */ | 432 | struct rtable *rt; /* Route to the other host */ |
432 | struct net_device *tdev; /* Device to other host */ | 433 | struct net_device *tdev; /* Device to other host */ |
433 | struct iphdr *iph; /* Our new IP header */ | 434 | struct iphdr *iph; /* Our new IP header */ |
434 | int max_headroom; /* The extra header space needed */ | 435 | int max_headroom; /* The extra header space needed */ |
435 | u32 dst = tiph->daddr; | 436 | u32 dst = tiph->daddr; |
436 | int mtu; | 437 | int mtu; |
437 | struct in6_addr *addr6; | 438 | struct in6_addr *addr6; |
438 | int addr_type; | 439 | int addr_type; |
439 | 440 | ||
440 | if (tunnel->recursion++) { | 441 | if (tunnel->recursion++) { |
441 | tunnel->stat.collisions++; | 442 | tunnel->stat.collisions++; |
442 | goto tx_error; | 443 | goto tx_error; |
443 | } | 444 | } |
444 | 445 | ||
445 | if (skb->protocol != htons(ETH_P_IPV6)) | 446 | if (skb->protocol != htons(ETH_P_IPV6)) |
446 | goto tx_error; | 447 | goto tx_error; |
447 | 448 | ||
448 | if (!dst) | 449 | if (!dst) |
449 | dst = try_6to4(&iph6->daddr); | 450 | dst = try_6to4(&iph6->daddr); |
450 | 451 | ||
451 | if (!dst) { | 452 | if (!dst) { |
452 | struct neighbour *neigh = NULL; | 453 | struct neighbour *neigh = NULL; |
453 | 454 | ||
454 | if (skb->dst) | 455 | if (skb->dst) |
455 | neigh = skb->dst->neighbour; | 456 | neigh = skb->dst->neighbour; |
456 | 457 | ||
457 | if (neigh == NULL) { | 458 | if (neigh == NULL) { |
458 | if (net_ratelimit()) | 459 | if (net_ratelimit()) |
459 | printk(KERN_DEBUG "sit: nexthop == NULL\n"); | 460 | printk(KERN_DEBUG "sit: nexthop == NULL\n"); |
460 | goto tx_error; | 461 | goto tx_error; |
461 | } | 462 | } |
462 | 463 | ||
463 | addr6 = (struct in6_addr*)&neigh->primary_key; | 464 | addr6 = (struct in6_addr*)&neigh->primary_key; |
464 | addr_type = ipv6_addr_type(addr6); | 465 | addr_type = ipv6_addr_type(addr6); |
465 | 466 | ||
466 | if (addr_type == IPV6_ADDR_ANY) { | 467 | if (addr_type == IPV6_ADDR_ANY) { |
467 | addr6 = &skb->nh.ipv6h->daddr; | 468 | addr6 = &skb->nh.ipv6h->daddr; |
468 | addr_type = ipv6_addr_type(addr6); | 469 | addr_type = ipv6_addr_type(addr6); |
469 | } | 470 | } |
470 | 471 | ||
471 | if ((addr_type & IPV6_ADDR_COMPATv4) == 0) | 472 | if ((addr_type & IPV6_ADDR_COMPATv4) == 0) |
472 | goto tx_error_icmp; | 473 | goto tx_error_icmp; |
473 | 474 | ||
474 | dst = addr6->s6_addr32[3]; | 475 | dst = addr6->s6_addr32[3]; |
475 | } | 476 | } |
476 | 477 | ||
477 | { | 478 | { |
478 | struct flowi fl = { .nl_u = { .ip4_u = | 479 | struct flowi fl = { .nl_u = { .ip4_u = |
479 | { .daddr = dst, | 480 | { .daddr = dst, |
480 | .saddr = tiph->saddr, | 481 | .saddr = tiph->saddr, |
481 | .tos = RT_TOS(tos) } }, | 482 | .tos = RT_TOS(tos) } }, |
482 | .oif = tunnel->parms.link, | 483 | .oif = tunnel->parms.link, |
483 | .proto = IPPROTO_IPV6 }; | 484 | .proto = IPPROTO_IPV6 }; |
484 | if (ip_route_output_key(&rt, &fl)) { | 485 | if (ip_route_output_key(&rt, &fl)) { |
485 | tunnel->stat.tx_carrier_errors++; | 486 | tunnel->stat.tx_carrier_errors++; |
486 | goto tx_error_icmp; | 487 | goto tx_error_icmp; |
487 | } | 488 | } |
488 | } | 489 | } |
489 | if (rt->rt_type != RTN_UNICAST) { | 490 | if (rt->rt_type != RTN_UNICAST) { |
490 | ip_rt_put(rt); | 491 | ip_rt_put(rt); |
491 | tunnel->stat.tx_carrier_errors++; | 492 | tunnel->stat.tx_carrier_errors++; |
492 | goto tx_error_icmp; | 493 | goto tx_error_icmp; |
493 | } | 494 | } |
494 | tdev = rt->u.dst.dev; | 495 | tdev = rt->u.dst.dev; |
495 | 496 | ||
496 | if (tdev == dev) { | 497 | if (tdev == dev) { |
497 | ip_rt_put(rt); | 498 | ip_rt_put(rt); |
498 | tunnel->stat.collisions++; | 499 | tunnel->stat.collisions++; |
499 | goto tx_error; | 500 | goto tx_error; |
500 | } | 501 | } |
501 | 502 | ||
502 | if (tiph->frag_off) | 503 | if (tiph->frag_off) |
503 | mtu = dst_mtu(&rt->u.dst) - sizeof(struct iphdr); | 504 | mtu = dst_mtu(&rt->u.dst) - sizeof(struct iphdr); |
504 | else | 505 | else |
505 | mtu = skb->dst ? dst_mtu(skb->dst) : dev->mtu; | 506 | mtu = skb->dst ? dst_mtu(skb->dst) : dev->mtu; |
506 | 507 | ||
507 | if (mtu < 68) { | 508 | if (mtu < 68) { |
508 | tunnel->stat.collisions++; | 509 | tunnel->stat.collisions++; |
509 | ip_rt_put(rt); | 510 | ip_rt_put(rt); |
510 | goto tx_error; | 511 | goto tx_error; |
511 | } | 512 | } |
512 | if (mtu < IPV6_MIN_MTU) | 513 | if (mtu < IPV6_MIN_MTU) |
513 | mtu = IPV6_MIN_MTU; | 514 | mtu = IPV6_MIN_MTU; |
514 | if (tunnel->parms.iph.daddr && skb->dst) | 515 | if (tunnel->parms.iph.daddr && skb->dst) |
515 | skb->dst->ops->update_pmtu(skb->dst, mtu); | 516 | skb->dst->ops->update_pmtu(skb->dst, mtu); |
516 | 517 | ||
517 | if (skb->len > mtu) { | 518 | if (skb->len > mtu) { |
518 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, dev); | 519 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, dev); |
519 | ip_rt_put(rt); | 520 | ip_rt_put(rt); |
520 | goto tx_error; | 521 | goto tx_error; |
521 | } | 522 | } |
522 | 523 | ||
523 | if (tunnel->err_count > 0) { | 524 | if (tunnel->err_count > 0) { |
524 | if (jiffies - tunnel->err_time < IPTUNNEL_ERR_TIMEO) { | 525 | if (jiffies - tunnel->err_time < IPTUNNEL_ERR_TIMEO) { |
525 | tunnel->err_count--; | 526 | tunnel->err_count--; |
526 | dst_link_failure(skb); | 527 | dst_link_failure(skb); |
527 | } else | 528 | } else |
528 | tunnel->err_count = 0; | 529 | tunnel->err_count = 0; |
529 | } | 530 | } |
530 | 531 | ||
531 | /* | 532 | /* |
532 | * Okay, now see if we can stuff it in the buffer as-is. | 533 | * Okay, now see if we can stuff it in the buffer as-is. |
533 | */ | 534 | */ |
534 | max_headroom = LL_RESERVED_SPACE(tdev)+sizeof(struct iphdr); | 535 | max_headroom = LL_RESERVED_SPACE(tdev)+sizeof(struct iphdr); |
535 | 536 | ||
536 | if (skb_headroom(skb) < max_headroom || skb_cloned(skb) || skb_shared(skb)) { | 537 | if (skb_headroom(skb) < max_headroom || skb_cloned(skb) || skb_shared(skb)) { |
537 | struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom); | 538 | struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom); |
538 | if (!new_skb) { | 539 | if (!new_skb) { |
539 | ip_rt_put(rt); | 540 | ip_rt_put(rt); |
540 | stats->tx_dropped++; | 541 | stats->tx_dropped++; |
541 | dev_kfree_skb(skb); | 542 | dev_kfree_skb(skb); |
542 | tunnel->recursion--; | 543 | tunnel->recursion--; |
543 | return 0; | 544 | return 0; |
544 | } | 545 | } |
545 | if (skb->sk) | 546 | if (skb->sk) |
546 | skb_set_owner_w(new_skb, skb->sk); | 547 | skb_set_owner_w(new_skb, skb->sk); |
547 | dev_kfree_skb(skb); | 548 | dev_kfree_skb(skb); |
548 | skb = new_skb; | 549 | skb = new_skb; |
549 | iph6 = skb->nh.ipv6h; | 550 | iph6 = skb->nh.ipv6h; |
550 | } | 551 | } |
551 | 552 | ||
552 | skb->h.raw = skb->nh.raw; | 553 | skb->h.raw = skb->nh.raw; |
553 | skb->nh.raw = skb_push(skb, sizeof(struct iphdr)); | 554 | skb->nh.raw = skb_push(skb, sizeof(struct iphdr)); |
554 | memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); | 555 | memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); |
556 | IPCB(skb)->flags = 0; | ||
555 | dst_release(skb->dst); | 557 | dst_release(skb->dst); |
556 | skb->dst = &rt->u.dst; | 558 | skb->dst = &rt->u.dst; |
557 | 559 | ||
558 | /* | 560 | /* |
559 | * Push down and install the IPIP header. | 561 | * Push down and install the IPIP header. |
560 | */ | 562 | */ |
561 | 563 | ||
562 | iph = skb->nh.iph; | 564 | iph = skb->nh.iph; |
563 | iph->version = 4; | 565 | iph->version = 4; |
564 | iph->ihl = sizeof(struct iphdr)>>2; | 566 | iph->ihl = sizeof(struct iphdr)>>2; |
565 | if (mtu > IPV6_MIN_MTU) | 567 | if (mtu > IPV6_MIN_MTU) |
566 | iph->frag_off = htons(IP_DF); | 568 | iph->frag_off = htons(IP_DF); |
567 | else | 569 | else |
568 | iph->frag_off = 0; | 570 | iph->frag_off = 0; |
569 | 571 | ||
570 | iph->protocol = IPPROTO_IPV6; | 572 | iph->protocol = IPPROTO_IPV6; |
571 | iph->tos = INET_ECN_encapsulate(tos, ipv6_get_dsfield(iph6)); | 573 | iph->tos = INET_ECN_encapsulate(tos, ipv6_get_dsfield(iph6)); |
572 | iph->daddr = rt->rt_dst; | 574 | iph->daddr = rt->rt_dst; |
573 | iph->saddr = rt->rt_src; | 575 | iph->saddr = rt->rt_src; |
574 | 576 | ||
575 | if ((iph->ttl = tiph->ttl) == 0) | 577 | if ((iph->ttl = tiph->ttl) == 0) |
576 | iph->ttl = iph6->hop_limit; | 578 | iph->ttl = iph6->hop_limit; |
577 | 579 | ||
578 | nf_reset(skb); | 580 | nf_reset(skb); |
579 | 581 | ||
580 | IPTUNNEL_XMIT(); | 582 | IPTUNNEL_XMIT(); |
581 | tunnel->recursion--; | 583 | tunnel->recursion--; |
582 | return 0; | 584 | return 0; |
583 | 585 | ||
584 | tx_error_icmp: | 586 | tx_error_icmp: |
585 | dst_link_failure(skb); | 587 | dst_link_failure(skb); |
586 | tx_error: | 588 | tx_error: |
587 | stats->tx_errors++; | 589 | stats->tx_errors++; |
588 | dev_kfree_skb(skb); | 590 | dev_kfree_skb(skb); |
589 | tunnel->recursion--; | 591 | tunnel->recursion--; |
590 | return 0; | 592 | return 0; |
591 | } | 593 | } |
592 | 594 | ||
593 | static int | 595 | static int |
594 | ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | 596 | ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) |
595 | { | 597 | { |
596 | int err = 0; | 598 | int err = 0; |
597 | struct ip_tunnel_parm p; | 599 | struct ip_tunnel_parm p; |
598 | struct ip_tunnel *t; | 600 | struct ip_tunnel *t; |
599 | 601 | ||
600 | switch (cmd) { | 602 | switch (cmd) { |
601 | case SIOCGETTUNNEL: | 603 | case SIOCGETTUNNEL: |
602 | t = NULL; | 604 | t = NULL; |
603 | if (dev == ipip6_fb_tunnel_dev) { | 605 | if (dev == ipip6_fb_tunnel_dev) { |
604 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) { | 606 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) { |
605 | err = -EFAULT; | 607 | err = -EFAULT; |
606 | break; | 608 | break; |
607 | } | 609 | } |
608 | t = ipip6_tunnel_locate(&p, 0); | 610 | t = ipip6_tunnel_locate(&p, 0); |
609 | } | 611 | } |
610 | if (t == NULL) | 612 | if (t == NULL) |
611 | t = (struct ip_tunnel*)dev->priv; | 613 | t = (struct ip_tunnel*)dev->priv; |
612 | memcpy(&p, &t->parms, sizeof(p)); | 614 | memcpy(&p, &t->parms, sizeof(p)); |
613 | if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p))) | 615 | if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p))) |
614 | err = -EFAULT; | 616 | err = -EFAULT; |
615 | break; | 617 | break; |
616 | 618 | ||
617 | case SIOCADDTUNNEL: | 619 | case SIOCADDTUNNEL: |
618 | case SIOCCHGTUNNEL: | 620 | case SIOCCHGTUNNEL: |
619 | err = -EPERM; | 621 | err = -EPERM; |
620 | if (!capable(CAP_NET_ADMIN)) | 622 | if (!capable(CAP_NET_ADMIN)) |
621 | goto done; | 623 | goto done; |
622 | 624 | ||
623 | err = -EFAULT; | 625 | err = -EFAULT; |
624 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) | 626 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) |
625 | goto done; | 627 | goto done; |
626 | 628 | ||
627 | err = -EINVAL; | 629 | err = -EINVAL; |
628 | if (p.iph.version != 4 || p.iph.protocol != IPPROTO_IPV6 || | 630 | if (p.iph.version != 4 || p.iph.protocol != IPPROTO_IPV6 || |
629 | p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF))) | 631 | p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF))) |
630 | goto done; | 632 | goto done; |
631 | if (p.iph.ttl) | 633 | if (p.iph.ttl) |
632 | p.iph.frag_off |= htons(IP_DF); | 634 | p.iph.frag_off |= htons(IP_DF); |
633 | 635 | ||
634 | t = ipip6_tunnel_locate(&p, cmd == SIOCADDTUNNEL); | 636 | t = ipip6_tunnel_locate(&p, cmd == SIOCADDTUNNEL); |
635 | 637 | ||
636 | if (dev != ipip6_fb_tunnel_dev && cmd == SIOCCHGTUNNEL) { | 638 | if (dev != ipip6_fb_tunnel_dev && cmd == SIOCCHGTUNNEL) { |
637 | if (t != NULL) { | 639 | if (t != NULL) { |
638 | if (t->dev != dev) { | 640 | if (t->dev != dev) { |
639 | err = -EEXIST; | 641 | err = -EEXIST; |
640 | break; | 642 | break; |
641 | } | 643 | } |
642 | } else { | 644 | } else { |
643 | if (((dev->flags&IFF_POINTOPOINT) && !p.iph.daddr) || | 645 | if (((dev->flags&IFF_POINTOPOINT) && !p.iph.daddr) || |
644 | (!(dev->flags&IFF_POINTOPOINT) && p.iph.daddr)) { | 646 | (!(dev->flags&IFF_POINTOPOINT) && p.iph.daddr)) { |
645 | err = -EINVAL; | 647 | err = -EINVAL; |
646 | break; | 648 | break; |
647 | } | 649 | } |
648 | t = (struct ip_tunnel*)dev->priv; | 650 | t = (struct ip_tunnel*)dev->priv; |
649 | ipip6_tunnel_unlink(t); | 651 | ipip6_tunnel_unlink(t); |
650 | t->parms.iph.saddr = p.iph.saddr; | 652 | t->parms.iph.saddr = p.iph.saddr; |
651 | t->parms.iph.daddr = p.iph.daddr; | 653 | t->parms.iph.daddr = p.iph.daddr; |
652 | memcpy(dev->dev_addr, &p.iph.saddr, 4); | 654 | memcpy(dev->dev_addr, &p.iph.saddr, 4); |
653 | memcpy(dev->broadcast, &p.iph.daddr, 4); | 655 | memcpy(dev->broadcast, &p.iph.daddr, 4); |
654 | ipip6_tunnel_link(t); | 656 | ipip6_tunnel_link(t); |
655 | netdev_state_change(dev); | 657 | netdev_state_change(dev); |
656 | } | 658 | } |
657 | } | 659 | } |
658 | 660 | ||
659 | if (t) { | 661 | if (t) { |
660 | err = 0; | 662 | err = 0; |
661 | if (cmd == SIOCCHGTUNNEL) { | 663 | if (cmd == SIOCCHGTUNNEL) { |
662 | t->parms.iph.ttl = p.iph.ttl; | 664 | t->parms.iph.ttl = p.iph.ttl; |
663 | t->parms.iph.tos = p.iph.tos; | 665 | t->parms.iph.tos = p.iph.tos; |
664 | } | 666 | } |
665 | if (copy_to_user(ifr->ifr_ifru.ifru_data, &t->parms, sizeof(p))) | 667 | if (copy_to_user(ifr->ifr_ifru.ifru_data, &t->parms, sizeof(p))) |
666 | err = -EFAULT; | 668 | err = -EFAULT; |
667 | } else | 669 | } else |
668 | err = (cmd == SIOCADDTUNNEL ? -ENOBUFS : -ENOENT); | 670 | err = (cmd == SIOCADDTUNNEL ? -ENOBUFS : -ENOENT); |
669 | break; | 671 | break; |
670 | 672 | ||
671 | case SIOCDELTUNNEL: | 673 | case SIOCDELTUNNEL: |
672 | err = -EPERM; | 674 | err = -EPERM; |
673 | if (!capable(CAP_NET_ADMIN)) | 675 | if (!capable(CAP_NET_ADMIN)) |
674 | goto done; | 676 | goto done; |
675 | 677 | ||
676 | if (dev == ipip6_fb_tunnel_dev) { | 678 | if (dev == ipip6_fb_tunnel_dev) { |
677 | err = -EFAULT; | 679 | err = -EFAULT; |
678 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) | 680 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) |
679 | goto done; | 681 | goto done; |
680 | err = -ENOENT; | 682 | err = -ENOENT; |
681 | if ((t = ipip6_tunnel_locate(&p, 0)) == NULL) | 683 | if ((t = ipip6_tunnel_locate(&p, 0)) == NULL) |
682 | goto done; | 684 | goto done; |
683 | err = -EPERM; | 685 | err = -EPERM; |
684 | if (t == ipip6_fb_tunnel_dev->priv) | 686 | if (t == ipip6_fb_tunnel_dev->priv) |
685 | goto done; | 687 | goto done; |
686 | dev = t->dev; | 688 | dev = t->dev; |
687 | } | 689 | } |
688 | err = unregister_netdevice(dev); | 690 | err = unregister_netdevice(dev); |
689 | break; | 691 | break; |
690 | 692 | ||
691 | default: | 693 | default: |
692 | err = -EINVAL; | 694 | err = -EINVAL; |
693 | } | 695 | } |
694 | 696 | ||
695 | done: | 697 | done: |
696 | return err; | 698 | return err; |
697 | } | 699 | } |
698 | 700 | ||
699 | static struct net_device_stats *ipip6_tunnel_get_stats(struct net_device *dev) | 701 | static struct net_device_stats *ipip6_tunnel_get_stats(struct net_device *dev) |
700 | { | 702 | { |
701 | return &(((struct ip_tunnel*)dev->priv)->stat); | 703 | return &(((struct ip_tunnel*)dev->priv)->stat); |
702 | } | 704 | } |
703 | 705 | ||
704 | static int ipip6_tunnel_change_mtu(struct net_device *dev, int new_mtu) | 706 | static int ipip6_tunnel_change_mtu(struct net_device *dev, int new_mtu) |
705 | { | 707 | { |
706 | if (new_mtu < IPV6_MIN_MTU || new_mtu > 0xFFF8 - sizeof(struct iphdr)) | 708 | if (new_mtu < IPV6_MIN_MTU || new_mtu > 0xFFF8 - sizeof(struct iphdr)) |
707 | return -EINVAL; | 709 | return -EINVAL; |
708 | dev->mtu = new_mtu; | 710 | dev->mtu = new_mtu; |
709 | return 0; | 711 | return 0; |
710 | } | 712 | } |
711 | 713 | ||
712 | static void ipip6_tunnel_setup(struct net_device *dev) | 714 | static void ipip6_tunnel_setup(struct net_device *dev) |
713 | { | 715 | { |
714 | SET_MODULE_OWNER(dev); | 716 | SET_MODULE_OWNER(dev); |
715 | dev->uninit = ipip6_tunnel_uninit; | 717 | dev->uninit = ipip6_tunnel_uninit; |
716 | dev->destructor = free_netdev; | 718 | dev->destructor = free_netdev; |
717 | dev->hard_start_xmit = ipip6_tunnel_xmit; | 719 | dev->hard_start_xmit = ipip6_tunnel_xmit; |
718 | dev->get_stats = ipip6_tunnel_get_stats; | 720 | dev->get_stats = ipip6_tunnel_get_stats; |
719 | dev->do_ioctl = ipip6_tunnel_ioctl; | 721 | dev->do_ioctl = ipip6_tunnel_ioctl; |
720 | dev->change_mtu = ipip6_tunnel_change_mtu; | 722 | dev->change_mtu = ipip6_tunnel_change_mtu; |
721 | 723 | ||
722 | dev->type = ARPHRD_SIT; | 724 | dev->type = ARPHRD_SIT; |
723 | dev->hard_header_len = LL_MAX_HEADER + sizeof(struct iphdr); | 725 | dev->hard_header_len = LL_MAX_HEADER + sizeof(struct iphdr); |
724 | dev->mtu = ETH_DATA_LEN - sizeof(struct iphdr); | 726 | dev->mtu = ETH_DATA_LEN - sizeof(struct iphdr); |
725 | dev->flags = IFF_NOARP; | 727 | dev->flags = IFF_NOARP; |
726 | dev->iflink = 0; | 728 | dev->iflink = 0; |
727 | dev->addr_len = 4; | 729 | dev->addr_len = 4; |
728 | } | 730 | } |
729 | 731 | ||
730 | static int ipip6_tunnel_init(struct net_device *dev) | 732 | static int ipip6_tunnel_init(struct net_device *dev) |
731 | { | 733 | { |
732 | struct net_device *tdev = NULL; | 734 | struct net_device *tdev = NULL; |
733 | struct ip_tunnel *tunnel; | 735 | struct ip_tunnel *tunnel; |
734 | struct iphdr *iph; | 736 | struct iphdr *iph; |
735 | 737 | ||
736 | tunnel = (struct ip_tunnel*)dev->priv; | 738 | tunnel = (struct ip_tunnel*)dev->priv; |
737 | iph = &tunnel->parms.iph; | 739 | iph = &tunnel->parms.iph; |
738 | 740 | ||
739 | tunnel->dev = dev; | 741 | tunnel->dev = dev; |
740 | strcpy(tunnel->parms.name, dev->name); | 742 | strcpy(tunnel->parms.name, dev->name); |
741 | 743 | ||
742 | memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4); | 744 | memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4); |
743 | memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4); | 745 | memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4); |
744 | 746 | ||
745 | if (iph->daddr) { | 747 | if (iph->daddr) { |
746 | struct flowi fl = { .nl_u = { .ip4_u = | 748 | struct flowi fl = { .nl_u = { .ip4_u = |
747 | { .daddr = iph->daddr, | 749 | { .daddr = iph->daddr, |
748 | .saddr = iph->saddr, | 750 | .saddr = iph->saddr, |
749 | .tos = RT_TOS(iph->tos) } }, | 751 | .tos = RT_TOS(iph->tos) } }, |
750 | .oif = tunnel->parms.link, | 752 | .oif = tunnel->parms.link, |
751 | .proto = IPPROTO_IPV6 }; | 753 | .proto = IPPROTO_IPV6 }; |
752 | struct rtable *rt; | 754 | struct rtable *rt; |
753 | if (!ip_route_output_key(&rt, &fl)) { | 755 | if (!ip_route_output_key(&rt, &fl)) { |
754 | tdev = rt->u.dst.dev; | 756 | tdev = rt->u.dst.dev; |
755 | ip_rt_put(rt); | 757 | ip_rt_put(rt); |
756 | } | 758 | } |
757 | dev->flags |= IFF_POINTOPOINT; | 759 | dev->flags |= IFF_POINTOPOINT; |
758 | } | 760 | } |
759 | 761 | ||
760 | if (!tdev && tunnel->parms.link) | 762 | if (!tdev && tunnel->parms.link) |
761 | tdev = __dev_get_by_index(tunnel->parms.link); | 763 | tdev = __dev_get_by_index(tunnel->parms.link); |
762 | 764 | ||
763 | if (tdev) { | 765 | if (tdev) { |
764 | dev->hard_header_len = tdev->hard_header_len + sizeof(struct iphdr); | 766 | dev->hard_header_len = tdev->hard_header_len + sizeof(struct iphdr); |
765 | dev->mtu = tdev->mtu - sizeof(struct iphdr); | 767 | dev->mtu = tdev->mtu - sizeof(struct iphdr); |
766 | if (dev->mtu < IPV6_MIN_MTU) | 768 | if (dev->mtu < IPV6_MIN_MTU) |
767 | dev->mtu = IPV6_MIN_MTU; | 769 | dev->mtu = IPV6_MIN_MTU; |
768 | } | 770 | } |
769 | dev->iflink = tunnel->parms.link; | 771 | dev->iflink = tunnel->parms.link; |
770 | 772 | ||
771 | return 0; | 773 | return 0; |
772 | } | 774 | } |
773 | 775 | ||
774 | static int __init ipip6_fb_tunnel_init(struct net_device *dev) | 776 | static int __init ipip6_fb_tunnel_init(struct net_device *dev) |
775 | { | 777 | { |
776 | struct ip_tunnel *tunnel = dev->priv; | 778 | struct ip_tunnel *tunnel = dev->priv; |
777 | struct iphdr *iph = &tunnel->parms.iph; | 779 | struct iphdr *iph = &tunnel->parms.iph; |
778 | 780 | ||
779 | tunnel->dev = dev; | 781 | tunnel->dev = dev; |
780 | strcpy(tunnel->parms.name, dev->name); | 782 | strcpy(tunnel->parms.name, dev->name); |
781 | 783 | ||
782 | iph->version = 4; | 784 | iph->version = 4; |
783 | iph->protocol = IPPROTO_IPV6; | 785 | iph->protocol = IPPROTO_IPV6; |
784 | iph->ihl = 5; | 786 | iph->ihl = 5; |
785 | iph->ttl = 64; | 787 | iph->ttl = 64; |
786 | 788 | ||
787 | dev_hold(dev); | 789 | dev_hold(dev); |
788 | tunnels_wc[0] = tunnel; | 790 | tunnels_wc[0] = tunnel; |
789 | return 0; | 791 | return 0; |
790 | } | 792 | } |
791 | 793 | ||
792 | static struct net_protocol sit_protocol = { | 794 | static struct net_protocol sit_protocol = { |
793 | .handler = ipip6_rcv, | 795 | .handler = ipip6_rcv, |
794 | .err_handler = ipip6_err, | 796 | .err_handler = ipip6_err, |
795 | }; | 797 | }; |
796 | 798 | ||
797 | static void __exit sit_destroy_tunnels(void) | 799 | static void __exit sit_destroy_tunnels(void) |
798 | { | 800 | { |
799 | int prio; | 801 | int prio; |
800 | 802 | ||
801 | for (prio = 1; prio < 4; prio++) { | 803 | for (prio = 1; prio < 4; prio++) { |
802 | int h; | 804 | int h; |
803 | for (h = 0; h < HASH_SIZE; h++) { | 805 | for (h = 0; h < HASH_SIZE; h++) { |
804 | struct ip_tunnel *t; | 806 | struct ip_tunnel *t; |
805 | while ((t = tunnels[prio][h]) != NULL) | 807 | while ((t = tunnels[prio][h]) != NULL) |
806 | unregister_netdevice(t->dev); | 808 | unregister_netdevice(t->dev); |
807 | } | 809 | } |
808 | } | 810 | } |
809 | } | 811 | } |
810 | 812 | ||
811 | void __exit sit_cleanup(void) | 813 | void __exit sit_cleanup(void) |
812 | { | 814 | { |
813 | inet_del_protocol(&sit_protocol, IPPROTO_IPV6); | 815 | inet_del_protocol(&sit_protocol, IPPROTO_IPV6); |
814 | 816 | ||
815 | rtnl_lock(); | 817 | rtnl_lock(); |
816 | sit_destroy_tunnels(); | 818 | sit_destroy_tunnels(); |
817 | unregister_netdevice(ipip6_fb_tunnel_dev); | 819 | unregister_netdevice(ipip6_fb_tunnel_dev); |
818 | rtnl_unlock(); | 820 | rtnl_unlock(); |
819 | } | 821 | } |
820 | 822 | ||
821 | int __init sit_init(void) | 823 | int __init sit_init(void) |
822 | { | 824 | { |
823 | int err; | 825 | int err; |
824 | 826 | ||
825 | printk(KERN_INFO "IPv6 over IPv4 tunneling driver\n"); | 827 | printk(KERN_INFO "IPv6 over IPv4 tunneling driver\n"); |
826 | 828 | ||
827 | if (inet_add_protocol(&sit_protocol, IPPROTO_IPV6) < 0) { | 829 | if (inet_add_protocol(&sit_protocol, IPPROTO_IPV6) < 0) { |
828 | printk(KERN_INFO "sit init: Can't add protocol\n"); | 830 | printk(KERN_INFO "sit init: Can't add protocol\n"); |
829 | return -EAGAIN; | 831 | return -EAGAIN; |
830 | } | 832 | } |
831 | 833 | ||
832 | ipip6_fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), "sit0", | 834 | ipip6_fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), "sit0", |
833 | ipip6_tunnel_setup); | 835 | ipip6_tunnel_setup); |
834 | if (!ipip6_fb_tunnel_dev) { | 836 | if (!ipip6_fb_tunnel_dev) { |
835 | err = -ENOMEM; | 837 | err = -ENOMEM; |
836 | goto err1; | 838 | goto err1; |
837 | } | 839 | } |
838 | 840 | ||
839 | ipip6_fb_tunnel_dev->init = ipip6_fb_tunnel_init; | 841 | ipip6_fb_tunnel_dev->init = ipip6_fb_tunnel_init; |
840 | 842 | ||
841 | if ((err = register_netdev(ipip6_fb_tunnel_dev))) | 843 | if ((err = register_netdev(ipip6_fb_tunnel_dev))) |
842 | goto err2; | 844 | goto err2; |
843 | 845 | ||
844 | out: | 846 | out: |
845 | return err; | 847 | return err; |
846 | err2: | 848 | err2: |
847 | free_netdev(ipip6_fb_tunnel_dev); | 849 | free_netdev(ipip6_fb_tunnel_dev); |
848 | err1: | 850 | err1: |
849 | inet_del_protocol(&sit_protocol, IPPROTO_IPV6); | 851 | inet_del_protocol(&sit_protocol, IPPROTO_IPV6); |
850 | goto out; | 852 | goto out; |
851 | } | 853 | } |
852 | 854 |