aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/ip6_vti.c
diff options
context:
space:
mode:
authorSteffen Klassert <steffen.klassert@secunet.com>2014-03-14 02:28:08 -0400
committerSteffen Klassert <steffen.klassert@secunet.com>2014-03-14 02:28:08 -0400
commitfa9ad96d4905c3e2013bcce18c104108275c4c08 (patch)
treeb78fbf428db9ae9e175c23e35f37d752b05f77ea /net/ipv6/ip6_vti.c
parent7cf9fdb5c771c61771e4e39efe18e2dbc8c8bfa4 (diff)
vti6: Update the ipv6 side to use its own receive hook.
With this patch, vti6 uses the IPsec protocol multiplexer to register its own receive side hooks for ESP, AH and IPCOMP. Vti6 now does the following on receive side: 1. Do an input policy check for the IPsec packet we received. This is required because this packet could be already prosecces by IPsec, so an inbuond policy check is needed. 2. Mark the packet with the i_key. The policy and the state must match this key now. Policy and state belong to the vti namespace and policy enforcement is done at the further layers. 3. Call the generic xfrm layer to do decryption and decapsulation. 4. Wait for a callback from the xfrm layer to properly clean the skb to not leak informations on namespace transitions and update the device statistics. On transmit side: 1. Mark the packet with the o_key. The policy and the state must match this key now. 2. Do a xfrm_lookup on the original packet with the mark applied. 3. Check if we got an IPsec route. 4. Clean the skb to not leak informations on namespace transitions. 5. Attach the dst_enty we got from the xfrm_lookup to the skb. 6. Call dst_output to do the IPsec processing. 7. Do the device statistics. Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
Diffstat (limited to 'net/ipv6/ip6_vti.c')
-rw-r--r--net/ipv6/ip6_vti.c176
1 files changed, 149 insertions, 27 deletions
diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c
index cc4a758d84c7..226854a3c392 100644
--- a/net/ipv6/ip6_vti.c
+++ b/net/ipv6/ip6_vti.c
@@ -287,11 +287,8 @@ static int vti6_rcv(struct sk_buff *skb)
287 const struct ipv6hdr *ipv6h = ipv6_hdr(skb); 287 const struct ipv6hdr *ipv6h = ipv6_hdr(skb);
288 288
289 rcu_read_lock(); 289 rcu_read_lock();
290
291 if ((t = vti6_tnl_lookup(dev_net(skb->dev), &ipv6h->saddr, 290 if ((t = vti6_tnl_lookup(dev_net(skb->dev), &ipv6h->saddr,
292 &ipv6h->daddr)) != NULL) { 291 &ipv6h->daddr)) != NULL) {
293 struct pcpu_sw_netstats *tstats;
294
295 if (t->parms.proto != IPPROTO_IPV6 && t->parms.proto != 0) { 292 if (t->parms.proto != IPPROTO_IPV6 && t->parms.proto != 0) {
296 rcu_read_unlock(); 293 rcu_read_unlock();
297 goto discard; 294 goto discard;
@@ -308,27 +305,58 @@ static int vti6_rcv(struct sk_buff *skb)
308 goto discard; 305 goto discard;
309 } 306 }
310 307
311 tstats = this_cpu_ptr(t->dev->tstats); 308 XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = t;
312 u64_stats_update_begin(&tstats->syncp); 309 skb->mark = be32_to_cpu(t->parms.i_key);
313 tstats->rx_packets++;
314 tstats->rx_bytes += skb->len;
315 u64_stats_update_end(&tstats->syncp);
316
317 skb->mark = 0;
318 secpath_reset(skb);
319 skb->dev = t->dev;
320 310
321 rcu_read_unlock(); 311 rcu_read_unlock();
322 return 0; 312
313 return xfrm6_rcv(skb);
323 } 314 }
324 rcu_read_unlock(); 315 rcu_read_unlock();
325 return 1; 316 return -EINVAL;
326
327discard: 317discard:
328 kfree_skb(skb); 318 kfree_skb(skb);
329 return 0; 319 return 0;
330} 320}
331 321
322static int vti6_rcv_cb(struct sk_buff *skb, int err)
323{
324 unsigned short family;
325 struct net_device *dev;
326 struct pcpu_sw_netstats *tstats;
327 struct xfrm_state *x;
328 struct ip6_tnl *t = XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6;
329
330 if (!t)
331 return 1;
332
333 dev = t->dev;
334
335 if (err) {
336 dev->stats.rx_errors++;
337 dev->stats.rx_dropped++;
338
339 return 0;
340 }
341
342 x = xfrm_input_state(skb);
343 family = x->inner_mode->afinfo->family;
344
345 if (!xfrm_policy_check(NULL, XFRM_POLICY_IN, skb, family))
346 return -EPERM;
347
348 skb_scrub_packet(skb, !net_eq(t->net, dev_net(skb->dev)));
349 skb->dev = dev;
350
351 tstats = this_cpu_ptr(dev->tstats);
352 u64_stats_update_begin(&tstats->syncp);
353 tstats->rx_packets++;
354 tstats->rx_bytes += skb->len;
355 u64_stats_update_end(&tstats->syncp);
356
357 return 0;
358}
359
332/** 360/**
333 * vti6_addr_conflict - compare packet addresses to tunnel's own 361 * vti6_addr_conflict - compare packet addresses to tunnel's own
334 * @t: the outgoing tunnel device 362 * @t: the outgoing tunnel device
@@ -394,7 +422,6 @@ static int vti6_xmit(struct sk_buff *skb, struct net_device *dev)
394 goto tx_err_dst_release; 422 goto tx_err_dst_release;
395 } 423 }
396 424
397
398 memset(IP6CB(skb), 0, sizeof(*IP6CB(skb))); 425 memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
399 skb_scrub_packet(skb, !net_eq(t->net, dev_net(dev))); 426 skb_scrub_packet(skb, !net_eq(t->net, dev_net(dev)));
400 skb_dst_set(skb, dst); 427 skb_dst_set(skb, dst);
@@ -438,9 +465,60 @@ tx_err:
438 return NETDEV_TX_OK; 465 return NETDEV_TX_OK;
439} 466}
440 467
468static int vti6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
469 u8 type, u8 code, int offset, __be32 info)
470{
471 __be32 spi;
472 struct xfrm_state *x;
473 struct ip6_tnl *t;
474 struct ip_esp_hdr *esph;
475 struct ip_auth_hdr *ah;
476 struct ip_comp_hdr *ipch;
477 struct net *net = dev_net(skb->dev);
478 const struct ipv6hdr *iph = (const struct ipv6hdr *)skb->data;
479 int protocol = iph->nexthdr;
480
481 t = vti6_tnl_lookup(dev_net(skb->dev), &iph->daddr, &iph->saddr);
482 if (!t)
483 return -1;
484
485 switch (protocol) {
486 case IPPROTO_ESP:
487 esph = (struct ip_esp_hdr *)(skb->data + offset);
488 spi = esph->spi;
489 break;
490 case IPPROTO_AH:
491 ah = (struct ip_auth_hdr *)(skb->data + offset);
492 spi = ah->spi;
493 break;
494 case IPPROTO_COMP:
495 ipch = (struct ip_comp_hdr *)(skb->data + offset);
496 spi = htonl(ntohs(ipch->cpi));
497 break;
498 default:
499 return 0;
500 }
501
502 if (type != ICMPV6_PKT_TOOBIG &&
503 type != NDISC_REDIRECT)
504 return 0;
505
506 x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr,
507 spi, protocol, AF_INET6);
508 if (!x)
509 return 0;
510
511 if (type == NDISC_REDIRECT)
512 ip6_redirect(skb, net, skb->dev->ifindex, 0);
513 else
514 ip6_update_pmtu(skb, net, info, 0, 0);
515 xfrm_state_put(x);
516
517 return 0;
518}
519
441static void vti6_link_config(struct ip6_tnl *t) 520static void vti6_link_config(struct ip6_tnl *t)
442{ 521{
443 struct dst_entry *dst;
444 struct net_device *dev = t->dev; 522 struct net_device *dev = t->dev;
445 struct __ip6_tnl_parm *p = &t->parms; 523 struct __ip6_tnl_parm *p = &t->parms;
446 524
@@ -871,11 +949,6 @@ static struct rtnl_link_ops vti6_link_ops __read_mostly = {
871 .fill_info = vti6_fill_info, 949 .fill_info = vti6_fill_info,
872}; 950};
873 951
874static struct xfrm_tunnel_notifier vti6_handler __read_mostly = {
875 .handler = vti6_rcv,
876 .priority = 1,
877};
878
879static void __net_exit vti6_destroy_tunnels(struct vti6_net *ip6n) 952static void __net_exit vti6_destroy_tunnels(struct vti6_net *ip6n)
880{ 953{
881 int h; 954 int h;
@@ -947,6 +1020,27 @@ static struct pernet_operations vti6_net_ops = {
947 .size = sizeof(struct vti6_net), 1020 .size = sizeof(struct vti6_net),
948}; 1021};
949 1022
1023static struct xfrm6_protocol vti_esp6_protocol __read_mostly = {
1024 .handler = vti6_rcv,
1025 .cb_handler = vti6_rcv_cb,
1026 .err_handler = vti6_err,
1027 .priority = 100,
1028};
1029
1030static struct xfrm6_protocol vti_ah6_protocol __read_mostly = {
1031 .handler = vti6_rcv,
1032 .cb_handler = vti6_rcv_cb,
1033 .err_handler = vti6_err,
1034 .priority = 100,
1035};
1036
1037static struct xfrm6_protocol vti_ipcomp6_protocol __read_mostly = {
1038 .handler = vti6_rcv,
1039 .cb_handler = vti6_rcv_cb,
1040 .err_handler = vti6_err,
1041 .priority = 100,
1042};
1043
950/** 1044/**
951 * vti6_tunnel_init - register protocol and reserve needed resources 1045 * vti6_tunnel_init - register protocol and reserve needed resources
952 * 1046 *
@@ -960,11 +1054,33 @@ static int __init vti6_tunnel_init(void)
960 if (err < 0) 1054 if (err < 0)
961 goto out_pernet; 1055 goto out_pernet;
962 1056
963 err = xfrm6_mode_tunnel_input_register(&vti6_handler); 1057 err = xfrm6_protocol_register(&vti_esp6_protocol, IPPROTO_ESP);
964 if (err < 0) { 1058 if (err < 0) {
965 pr_err("%s: can't register vti6\n", __func__); 1059 unregister_pernet_device(&vti6_net_ops);
1060 pr_err("%s: can't register vti6 protocol\n", __func__);
1061
966 goto out; 1062 goto out;
967 } 1063 }
1064
1065 err = xfrm6_protocol_register(&vti_ah6_protocol, IPPROTO_AH);
1066 if (err < 0) {
1067 xfrm6_protocol_deregister(&vti_esp6_protocol, IPPROTO_ESP);
1068 unregister_pernet_device(&vti6_net_ops);
1069 pr_err("%s: can't register vti6 protocol\n", __func__);
1070
1071 goto out;
1072 }
1073
1074 err = xfrm6_protocol_register(&vti_ipcomp6_protocol, IPPROTO_COMP);
1075 if (err < 0) {
1076 xfrm6_protocol_deregister(&vti_ah6_protocol, IPPROTO_AH);
1077 xfrm6_protocol_deregister(&vti_esp6_protocol, IPPROTO_ESP);
1078 unregister_pernet_device(&vti6_net_ops);
1079 pr_err("%s: can't register vti6 protocol\n", __func__);
1080
1081 goto out;
1082 }
1083
968 err = rtnl_link_register(&vti6_link_ops); 1084 err = rtnl_link_register(&vti6_link_ops);
969 if (err < 0) 1085 if (err < 0)
970 goto rtnl_link_failed; 1086 goto rtnl_link_failed;
@@ -972,7 +1088,9 @@ static int __init vti6_tunnel_init(void)
972 return 0; 1088 return 0;
973 1089
974rtnl_link_failed: 1090rtnl_link_failed:
975 xfrm6_mode_tunnel_input_deregister(&vti6_handler); 1091 xfrm6_protocol_deregister(&vti_ipcomp6_protocol, IPPROTO_COMP);
1092 xfrm6_protocol_deregister(&vti_ah6_protocol, IPPROTO_AH);
1093 xfrm6_protocol_deregister(&vti_esp6_protocol, IPPROTO_ESP);
976out: 1094out:
977 unregister_pernet_device(&vti6_net_ops); 1095 unregister_pernet_device(&vti6_net_ops);
978out_pernet: 1096out_pernet:
@@ -985,8 +1103,12 @@ out_pernet:
985static void __exit vti6_tunnel_cleanup(void) 1103static void __exit vti6_tunnel_cleanup(void)
986{ 1104{
987 rtnl_link_unregister(&vti6_link_ops); 1105 rtnl_link_unregister(&vti6_link_ops);
988 if (xfrm6_mode_tunnel_input_deregister(&vti6_handler)) 1106 if (xfrm6_protocol_deregister(&vti_ipcomp6_protocol, IPPROTO_COMP))
989 pr_info("%s: can't deregister vti6\n", __func__); 1107 pr_info("%s: can't deregister protocol\n", __func__);
1108 if (xfrm6_protocol_deregister(&vti_ah6_protocol, IPPROTO_AH))
1109 pr_info("%s: can't deregister protocol\n", __func__);
1110 if (xfrm6_protocol_deregister(&vti_esp6_protocol, IPPROTO_ESP))
1111 pr_info("%s: can't deregister protocol\n", __func__);
990 1112
991 unregister_pernet_device(&vti6_net_ops); 1113 unregister_pernet_device(&vti6_net_ops);
992} 1114}