13
13
#define pr_fmt (fmt ) KBUILD_MODNAME ": " fmt
14
14
15
15
#include <linux/module.h>
16
+ #include <linux/if.h>
17
+ #include <linux/icmp.h>
16
18
#include <linux/kernel.h>
17
19
#include <linux/kmod.h>
18
20
#include <linux/skbuff.h>
24
26
#include <net/protocol.h>
25
27
#include <net/gre.h>
26
28
29
+ #include <net/icmp.h>
30
+ #include <net/route.h>
31
+ #include <net/xfrm.h>
27
32
28
33
static const struct gre_protocol __rcu * gre_proto [GREPROTO_MAX ] __read_mostly ;
34
+ static struct gre_cisco_protocol __rcu * gre_cisco_proto_list [GRE_IP_PROTO_MAX ];
29
35
30
36
int gre_add_protocol (const struct gre_protocol * proto , u8 version )
31
37
{
@@ -55,6 +61,173 @@ int gre_del_protocol(const struct gre_protocol *proto, u8 version)
55
61
}
56
62
EXPORT_SYMBOL_GPL (gre_del_protocol );
57
63
64
+ static __sum16 check_checksum (struct sk_buff * skb )
65
+ {
66
+ __sum16 csum = 0 ;
67
+
68
+ switch (skb -> ip_summed ) {
69
+ case CHECKSUM_COMPLETE :
70
+ csum = csum_fold (skb -> csum );
71
+
72
+ if (!csum )
73
+ break ;
74
+ /* Fall through. */
75
+
76
+ case CHECKSUM_NONE :
77
+ skb -> csum = 0 ;
78
+ csum = __skb_checksum_complete (skb );
79
+ skb -> ip_summed = CHECKSUM_COMPLETE ;
80
+ break ;
81
+ }
82
+
83
+ return csum ;
84
+ }
85
+
86
+ static int parse_gre_header (struct sk_buff * skb , struct tnl_ptk_info * tpi ,
87
+ bool * csum_err )
88
+ {
89
+ unsigned int ip_hlen = ip_hdrlen (skb );
90
+ const struct gre_base_hdr * greh ;
91
+ __be32 * options ;
92
+ int hdr_len ;
93
+
94
+ if (unlikely (!pskb_may_pull (skb , sizeof (struct gre_base_hdr ))))
95
+ return - EINVAL ;
96
+
97
+ greh = (struct gre_base_hdr * )(skb_network_header (skb ) + ip_hlen );
98
+ if (unlikely (greh -> flags & (GRE_VERSION | GRE_ROUTING )))
99
+ return - EINVAL ;
100
+
101
+ tpi -> flags = gre_flags_to_tnl_flags (greh -> flags );
102
+ hdr_len = ip_gre_calc_hlen (tpi -> flags );
103
+
104
+ if (!pskb_may_pull (skb , hdr_len ))
105
+ return - EINVAL ;
106
+
107
+ greh = (struct gre_base_hdr * )(skb_network_header (skb ) + ip_hlen );
108
+ tpi -> proto = greh -> protocol ;
109
+
110
+ options = (__be32 * )(greh + 1 );
111
+ if (greh -> flags & GRE_CSUM ) {
112
+ if (check_checksum (skb )) {
113
+ * csum_err = true;
114
+ return - EINVAL ;
115
+ }
116
+ options ++ ;
117
+ }
118
+
119
+ if (greh -> flags & GRE_KEY ) {
120
+ tpi -> key = * options ;
121
+ options ++ ;
122
+ } else
123
+ tpi -> key = 0 ;
124
+
125
+ if (unlikely (greh -> flags & GRE_SEQ )) {
126
+ tpi -> seq = * options ;
127
+ options ++ ;
128
+ } else
129
+ tpi -> seq = 0 ;
130
+
131
+ /* WCCP version 1 and 2 protocol decoding.
132
+ * - Change protocol to IP
133
+ * - When dealing with WCCPv2, Skip extra 4 bytes in GRE header
134
+ */
135
+ if (greh -> flags == 0 && tpi -> proto == htons (ETH_P_WCCP )) {
136
+ tpi -> proto = htons (ETH_P_IP );
137
+ if ((* (u8 * )options & 0xF0 ) != 0x40 ) {
138
+ hdr_len += 4 ;
139
+ if (!pskb_may_pull (skb , hdr_len ))
140
+ return - EINVAL ;
141
+ }
142
+ }
143
+ return 0 ;
144
+ }
145
+
146
+ static int gre_cisco_rcv (struct sk_buff * skb )
147
+ {
148
+ struct tnl_ptk_info tpi ;
149
+ int i ;
150
+ bool csum_err = false;
151
+
152
+ if (parse_gre_header (skb , & tpi , & csum_err ) < 0 )
153
+ goto drop ;
154
+
155
+ rcu_read_lock ();
156
+ for (i = 0 ; i < GRE_IP_PROTO_MAX ; i ++ ) {
157
+ struct gre_cisco_protocol * proto ;
158
+ int ret ;
159
+
160
+ proto = rcu_dereference (gre_cisco_proto_list [i ]);
161
+ if (!proto )
162
+ continue ;
163
+ ret = proto -> handler (skb , & tpi );
164
+ if (ret == PACKET_RCVD ) {
165
+ rcu_read_unlock ();
166
+ return 0 ;
167
+ }
168
+ }
169
+ rcu_read_unlock ();
170
+
171
+ icmp_send (skb , ICMP_DEST_UNREACH , ICMP_PORT_UNREACH , 0 );
172
+ drop :
173
+ kfree_skb (skb );
174
+ return 0 ;
175
+ }
176
+
177
+ static void gre_cisco_err (struct sk_buff * skb , u32 info )
178
+ {
179
+ /* All the routers (except for Linux) return only
180
+ * 8 bytes of packet payload. It means, that precise relaying of
181
+ * ICMP in the real Internet is absolutely infeasible.
182
+ *
183
+ * Moreover, Cisco "wise men" put GRE key to the third word
184
+ * in GRE header. It makes impossible maintaining even soft
185
+ * state for keyed
186
+ * GRE tunnels with enabled checksum. Tell them "thank you".
187
+ *
188
+ * Well, I wonder, rfc1812 was written by Cisco employee,
189
+ * what the hell these idiots break standards established
190
+ * by themselves???
191
+ */
192
+
193
+ const int type = icmp_hdr (skb )-> type ;
194
+ const int code = icmp_hdr (skb )-> code ;
195
+ struct tnl_ptk_info tpi ;
196
+ bool csum_err = false;
197
+ int i ;
198
+
199
+ if (parse_gre_header (skb , & tpi , & csum_err )) {
200
+ if (!csum_err ) /* ignore csum errors. */
201
+ return ;
202
+ }
203
+
204
+ if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED ) {
205
+ ipv4_update_pmtu (skb , dev_net (skb -> dev ), info ,
206
+ skb -> dev -> ifindex , 0 , IPPROTO_GRE , 0 );
207
+ return ;
208
+ }
209
+ if (type == ICMP_REDIRECT ) {
210
+ ipv4_redirect (skb , dev_net (skb -> dev ), skb -> dev -> ifindex , 0 ,
211
+ IPPROTO_GRE , 0 );
212
+ return ;
213
+ }
214
+
215
+ rcu_read_lock ();
216
+ for (i = 0 ; i < GRE_IP_PROTO_MAX ; i ++ ) {
217
+ struct gre_cisco_protocol * proto ;
218
+
219
+ proto = rcu_dereference (gre_cisco_proto_list [i ]);
220
+ if (!proto )
221
+ continue ;
222
+
223
+ if (proto -> err_handler (skb , info , & tpi ) == PACKET_RCVD )
224
+ goto out ;
225
+
226
+ }
227
+ out :
228
+ rcu_read_unlock ();
229
+ }
230
+
58
231
static int gre_rcv (struct sk_buff * skb )
59
232
{
60
233
const struct gre_protocol * proto ;
@@ -206,27 +379,68 @@ static const struct net_offload gre_offload = {
206
379
},
207
380
};
208
381
382
+ static const struct gre_protocol ipgre_protocol = {
383
+ .handler = gre_cisco_rcv ,
384
+ .err_handler = gre_cisco_err ,
385
+ };
386
+
387
+ int gre_cisco_register (struct gre_cisco_protocol * newp )
388
+ {
389
+ struct gre_cisco_protocol * * proto = (struct gre_cisco_protocol * * )
390
+ & gre_cisco_proto_list [newp -> priority ];
391
+
392
+ return (cmpxchg (proto , NULL , newp ) == NULL ) ? 0 : - EBUSY ;
393
+ }
394
+ EXPORT_SYMBOL_GPL (gre_cisco_register );
395
+
396
+ int gre_cisco_unregister (struct gre_cisco_protocol * del_proto )
397
+ {
398
+ struct gre_cisco_protocol * * proto = (struct gre_cisco_protocol * * )
399
+ & gre_cisco_proto_list [del_proto -> priority ];
400
+ int ret ;
401
+
402
+ ret = (cmpxchg (proto , del_proto , NULL ) == del_proto ) ? 0 : - EINVAL ;
403
+
404
+ if (ret )
405
+ return ret ;
406
+
407
+ synchronize_net ();
408
+ return 0 ;
409
+ }
410
+ EXPORT_SYMBOL_GPL (gre_cisco_unregister );
411
+
209
412
static int __init gre_init (void )
210
413
{
211
414
pr_info ("GRE over IPv4 demultiplexor driver\n" );
212
415
213
416
if (inet_add_protocol (& net_gre_protocol , IPPROTO_GRE ) < 0 ) {
214
417
pr_err ("can't add protocol\n" );
215
- return - EAGAIN ;
418
+ goto err ;
419
+ }
420
+
421
+ if (gre_add_protocol (& ipgre_protocol , GREPROTO_CISCO ) < 0 ) {
422
+ pr_info ("%s: can't add ipgre handler\n" , __func__ );
423
+ goto err_gre ;
216
424
}
217
425
218
426
if (inet_add_offload (& gre_offload , IPPROTO_GRE )) {
219
427
pr_err ("can't add protocol offload\n" );
220
- inet_del_protocol (& net_gre_protocol , IPPROTO_GRE );
221
- return - EAGAIN ;
428
+ goto err_gso ;
222
429
}
223
430
224
431
return 0 ;
432
+ err_gso :
433
+ gre_del_protocol (& ipgre_protocol , GREPROTO_CISCO );
434
+ err_gre :
435
+ inet_del_protocol (& net_gre_protocol , IPPROTO_GRE );
436
+ err :
437
+ return - EAGAIN ;
225
438
}
226
439
227
440
static void __exit gre_exit (void )
228
441
{
229
442
inet_del_offload (& gre_offload , IPPROTO_GRE );
443
+ gre_del_protocol (& ipgre_protocol , GREPROTO_CISCO );
230
444
inet_del_protocol (& net_gre_protocol , IPPROTO_GRE );
231
445
}
232
446
@@ -236,4 +450,3 @@ module_exit(gre_exit);
236
450
MODULE_DESCRIPTION ("GRE over IPv4 demultiplexer driver" );
237
451
MODULE_AUTHOR ("D. Kozlov (xeb@mail.ru)" );
238
452
MODULE_LICENSE ("GPL" );
239
-
0 commit comments