1 /* 2 * Checksum updating actions 3 * 4 * Copyright (c) 2010 Gregoire Baron <baronchon@n7mm.org> 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License as published by the Free 8 * Software Foundation; either version 2 of the License, or (at your option) 9 * any later version. 10 * 11 */ 12 13 #include <linux/types.h> 14 #include <linux/init.h> 15 #include <linux/kernel.h> 16 #include <linux/module.h> 17 #include <linux/spinlock.h> 18 19 #include <linux/netlink.h> 20 #include <net/netlink.h> 21 #include <linux/rtnetlink.h> 22 23 #include <linux/skbuff.h> 24 25 #include <net/ip.h> 26 #include <net/ipv6.h> 27 #include <net/icmp.h> 28 #include <linux/icmpv6.h> 29 #include <linux/igmp.h> 30 #include <net/tcp.h> 31 #include <net/udp.h> 32 #include <net/ip6_checksum.h> 33 #include <net/sctp/checksum.h> 34 35 #include <net/act_api.h> 36 37 #include <linux/tc_act/tc_csum.h> 38 #include <net/tc_act/tc_csum.h> 39 40 static const struct nla_policy csum_policy[TCA_CSUM_MAX + 1] = { 41 [TCA_CSUM_PARMS] = { .len = sizeof(struct tc_csum), }, 42 }; 43 44 static unsigned int csum_net_id; 45 static struct tc_action_ops act_csum_ops; 46 47 static int tcf_csum_init(struct net *net, struct nlattr *nla, 48 struct nlattr *est, struct tc_action **a, int ovr, 49 int bind) 50 { 51 struct tc_action_net *tn = net_generic(net, csum_net_id); 52 struct nlattr *tb[TCA_CSUM_MAX + 1]; 53 struct tc_csum *parm; 54 struct tcf_csum *p; 55 int ret = 0, err; 56 57 if (nla == NULL) 58 return -EINVAL; 59 60 err = nla_parse_nested(tb, TCA_CSUM_MAX, nla, csum_policy, NULL); 61 if (err < 0) 62 return err; 63 64 if (tb[TCA_CSUM_PARMS] == NULL) 65 return -EINVAL; 66 parm = nla_data(tb[TCA_CSUM_PARMS]); 67 68 if (!tcf_idr_check(tn, parm->index, a, bind)) { 69 ret = tcf_idr_create(tn, parm->index, est, a, 70 &act_csum_ops, bind, false); 71 if (ret) 72 return ret; 73 ret = ACT_P_CREATED; 74 } else { 75 if (bind)/* dont override defaults */ 76 return 0; 77 tcf_idr_release(*a, bind); 78 if (!ovr) 79 return -EEXIST; 80 } 81 82 p = to_tcf_csum(*a); 83 spin_lock_bh(&p->tcf_lock); 84 p->tcf_action = parm->action; 85 p->update_flags = parm->update_flags; 86 spin_unlock_bh(&p->tcf_lock); 87 88 if (ret == ACT_P_CREATED) 89 tcf_idr_insert(tn, *a); 90 91 return ret; 92 } 93 94 /** 95 * tcf_csum_skb_nextlayer - Get next layer pointer 96 * @skb: sk_buff to use 97 * @ihl: previous summed headers length 98 * @ipl: complete packet length 99 * @jhl: next header length 100 * 101 * Check the expected next layer availability in the specified sk_buff. 102 * Return the next layer pointer if pass, NULL otherwise. 103 */ 104 static void *tcf_csum_skb_nextlayer(struct sk_buff *skb, 105 unsigned int ihl, unsigned int ipl, 106 unsigned int jhl) 107 { 108 int ntkoff = skb_network_offset(skb); 109 int hl = ihl + jhl; 110 111 if (!pskb_may_pull(skb, ipl + ntkoff) || (ipl < hl) || 112 skb_try_make_writable(skb, hl + ntkoff)) 113 return NULL; 114 else 115 return (void *)(skb_network_header(skb) + ihl); 116 } 117 118 static int tcf_csum_ipv4_icmp(struct sk_buff *skb, unsigned int ihl, 119 unsigned int ipl) 120 { 121 struct icmphdr *icmph; 122 123 icmph = tcf_csum_skb_nextlayer(skb, ihl, ipl, sizeof(*icmph)); 124 if (icmph == NULL) 125 return 0; 126 127 icmph->checksum = 0; 128 skb->csum = csum_partial(icmph, ipl - ihl, 0); 129 icmph->checksum = csum_fold(skb->csum); 130 131 skb->ip_summed = CHECKSUM_NONE; 132 133 return 1; 134 } 135 136 static int tcf_csum_ipv4_igmp(struct sk_buff *skb, 137 unsigned int ihl, unsigned int ipl) 138 { 139 struct igmphdr *igmph; 140 141 igmph = tcf_csum_skb_nextlayer(skb, ihl, ipl, sizeof(*igmph)); 142 if (igmph == NULL) 143 return 0; 144 145 igmph->csum = 0; 146 skb->csum = csum_partial(igmph, ipl - ihl, 0); 147 igmph->csum = csum_fold(skb->csum); 148 149 skb->ip_summed = CHECKSUM_NONE; 150 151 return 1; 152 } 153 154 static int tcf_csum_ipv6_icmp(struct sk_buff *skb, unsigned int ihl, 155 unsigned int ipl) 156 { 157 struct icmp6hdr *icmp6h; 158 const struct ipv6hdr *ip6h; 159 160 icmp6h = tcf_csum_skb_nextlayer(skb, ihl, ipl, sizeof(*icmp6h)); 161 if (icmp6h == NULL) 162 return 0; 163 164 ip6h = ipv6_hdr(skb); 165 icmp6h->icmp6_cksum = 0; 166 skb->csum = csum_partial(icmp6h, ipl - ihl, 0); 167 icmp6h->icmp6_cksum = csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, 168 ipl - ihl, IPPROTO_ICMPV6, 169 skb->csum); 170 171 skb->ip_summed = CHECKSUM_NONE; 172 173 return 1; 174 } 175 176 static int tcf_csum_ipv4_tcp(struct sk_buff *skb, unsigned int ihl, 177 unsigned int ipl) 178 { 179 struct tcphdr *tcph; 180 const struct iphdr *iph; 181 182 if (skb_is_gso(skb) && skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4) 183 return 1; 184 185 tcph = tcf_csum_skb_nextlayer(skb, ihl, ipl, sizeof(*tcph)); 186 if (tcph == NULL) 187 return 0; 188 189 iph = ip_hdr(skb); 190 tcph->check = 0; 191 skb->csum = csum_partial(tcph, ipl - ihl, 0); 192 tcph->check = tcp_v4_check(ipl - ihl, 193 iph->saddr, iph->daddr, skb->csum); 194 195 skb->ip_summed = CHECKSUM_NONE; 196 197 return 1; 198 } 199 200 static int tcf_csum_ipv6_tcp(struct sk_buff *skb, unsigned int ihl, 201 unsigned int ipl) 202 { 203 struct tcphdr *tcph; 204 const struct ipv6hdr *ip6h; 205 206 if (skb_is_gso(skb) && skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) 207 return 1; 208 209 tcph = tcf_csum_skb_nextlayer(skb, ihl, ipl, sizeof(*tcph)); 210 if (tcph == NULL) 211 return 0; 212 213 ip6h = ipv6_hdr(skb); 214 tcph->check = 0; 215 skb->csum = csum_partial(tcph, ipl - ihl, 0); 216 tcph->check = csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, 217 ipl - ihl, IPPROTO_TCP, 218 skb->csum); 219 220 skb->ip_summed = CHECKSUM_NONE; 221 222 return 1; 223 } 224 225 static int tcf_csum_ipv4_udp(struct sk_buff *skb, unsigned int ihl, 226 unsigned int ipl, int udplite) 227 { 228 struct udphdr *udph; 229 const struct iphdr *iph; 230 u16 ul; 231 232 if (skb_is_gso(skb) && skb_shinfo(skb)->gso_type & SKB_GSO_UDP) 233 return 1; 234 235 /* 236 * Support both UDP and UDPLITE checksum algorithms, Don't use 237 * udph->len to get the real length without any protocol check, 238 * UDPLITE uses udph->len for another thing, 239 * Use iph->tot_len, or just ipl. 240 */ 241 242 udph = tcf_csum_skb_nextlayer(skb, ihl, ipl, sizeof(*udph)); 243 if (udph == NULL) 244 return 0; 245 246 iph = ip_hdr(skb); 247 ul = ntohs(udph->len); 248 249 if (udplite || udph->check) { 250 251 udph->check = 0; 252 253 if (udplite) { 254 if (ul == 0) 255 skb->csum = csum_partial(udph, ipl - ihl, 0); 256 else if ((ul >= sizeof(*udph)) && (ul <= ipl - ihl)) 257 skb->csum = csum_partial(udph, ul, 0); 258 else 259 goto ignore_obscure_skb; 260 } else { 261 if (ul != ipl - ihl) 262 goto ignore_obscure_skb; 263 264 skb->csum = csum_partial(udph, ul, 0); 265 } 266 267 udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, 268 ul, iph->protocol, 269 skb->csum); 270 271 if (!udph->check) 272 udph->check = CSUM_MANGLED_0; 273 } 274 275 skb->ip_summed = CHECKSUM_NONE; 276 277 ignore_obscure_skb: 278 return 1; 279 } 280 281 static int tcf_csum_ipv6_udp(struct sk_buff *skb, unsigned int ihl, 282 unsigned int ipl, int udplite) 283 { 284 struct udphdr *udph; 285 const struct ipv6hdr *ip6h; 286 u16 ul; 287 288 if (skb_is_gso(skb) && skb_shinfo(skb)->gso_type & SKB_GSO_UDP) 289 return 1; 290 291 /* 292 * Support both UDP and UDPLITE checksum algorithms, Don't use 293 * udph->len to get the real length without any protocol check, 294 * UDPLITE uses udph->len for another thing, 295 * Use ip6h->payload_len + sizeof(*ip6h) ... , or just ipl. 296 */ 297 298 udph = tcf_csum_skb_nextlayer(skb, ihl, ipl, sizeof(*udph)); 299 if (udph == NULL) 300 return 0; 301 302 ip6h = ipv6_hdr(skb); 303 ul = ntohs(udph->len); 304 305 udph->check = 0; 306 307 if (udplite) { 308 if (ul == 0) 309 skb->csum = csum_partial(udph, ipl - ihl, 0); 310 311 else if ((ul >= sizeof(*udph)) && (ul <= ipl - ihl)) 312 skb->csum = csum_partial(udph, ul, 0); 313 314 else 315 goto ignore_obscure_skb; 316 } else { 317 if (ul != ipl - ihl) 318 goto ignore_obscure_skb; 319 320 skb->csum = csum_partial(udph, ul, 0); 321 } 322 323 udph->check = csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, ul, 324 udplite ? IPPROTO_UDPLITE : IPPROTO_UDP, 325 skb->csum); 326 327 if (!udph->check) 328 udph->check = CSUM_MANGLED_0; 329 330 skb->ip_summed = CHECKSUM_NONE; 331 332 ignore_obscure_skb: 333 return 1; 334 } 335 336 static int tcf_csum_sctp(struct sk_buff *skb, unsigned int ihl, 337 unsigned int ipl) 338 { 339 struct sctphdr *sctph; 340 341 if (skb_is_gso(skb) && skb_shinfo(skb)->gso_type & SKB_GSO_SCTP) 342 return 1; 343 344 sctph = tcf_csum_skb_nextlayer(skb, ihl, ipl, sizeof(*sctph)); 345 if (!sctph) 346 return 0; 347 348 sctph->checksum = sctp_compute_cksum(skb, 349 skb_network_offset(skb) + ihl); 350 skb->ip_summed = CHECKSUM_NONE; 351 skb->csum_not_inet = 0; 352 353 return 1; 354 } 355 356 static int tcf_csum_ipv4(struct sk_buff *skb, u32 update_flags) 357 { 358 const struct iphdr *iph; 359 int ntkoff; 360 361 ntkoff = skb_network_offset(skb); 362 363 if (!pskb_may_pull(skb, sizeof(*iph) + ntkoff)) 364 goto fail; 365 366 iph = ip_hdr(skb); 367 368 switch (iph->frag_off & htons(IP_OFFSET) ? 0 : iph->protocol) { 369 case IPPROTO_ICMP: 370 if (update_flags & TCA_CSUM_UPDATE_FLAG_ICMP) 371 if (!tcf_csum_ipv4_icmp(skb, iph->ihl * 4, 372 ntohs(iph->tot_len))) 373 goto fail; 374 break; 375 case IPPROTO_IGMP: 376 if (update_flags & TCA_CSUM_UPDATE_FLAG_IGMP) 377 if (!tcf_csum_ipv4_igmp(skb, iph->ihl * 4, 378 ntohs(iph->tot_len))) 379 goto fail; 380 break; 381 case IPPROTO_TCP: 382 if (update_flags & TCA_CSUM_UPDATE_FLAG_TCP) 383 if (!tcf_csum_ipv4_tcp(skb, iph->ihl * 4, 384 ntohs(iph->tot_len))) 385 goto fail; 386 break; 387 case IPPROTO_UDP: 388 if (update_flags & TCA_CSUM_UPDATE_FLAG_UDP) 389 if (!tcf_csum_ipv4_udp(skb, iph->ihl * 4, 390 ntohs(iph->tot_len), 0)) 391 goto fail; 392 break; 393 case IPPROTO_UDPLITE: 394 if (update_flags & TCA_CSUM_UPDATE_FLAG_UDPLITE) 395 if (!tcf_csum_ipv4_udp(skb, iph->ihl * 4, 396 ntohs(iph->tot_len), 1)) 397 goto fail; 398 break; 399 case IPPROTO_SCTP: 400 if ((update_flags & TCA_CSUM_UPDATE_FLAG_SCTP) && 401 !tcf_csum_sctp(skb, iph->ihl * 4, ntohs(iph->tot_len))) 402 goto fail; 403 break; 404 } 405 406 if (update_flags & TCA_CSUM_UPDATE_FLAG_IPV4HDR) { 407 if (skb_try_make_writable(skb, sizeof(*iph) + ntkoff)) 408 goto fail; 409 410 ip_send_check(ip_hdr(skb)); 411 } 412 413 return 1; 414 415 fail: 416 return 0; 417 } 418 419 static int tcf_csum_ipv6_hopopts(struct ipv6_opt_hdr *ip6xh, unsigned int ixhl, 420 unsigned int *pl) 421 { 422 int off, len, optlen; 423 unsigned char *xh = (void *)ip6xh; 424 425 off = sizeof(*ip6xh); 426 len = ixhl - off; 427 428 while (len > 1) { 429 switch (xh[off]) { 430 case IPV6_TLV_PAD1: 431 optlen = 1; 432 break; 433 case IPV6_TLV_JUMBO: 434 optlen = xh[off + 1] + 2; 435 if (optlen != 6 || len < 6 || (off & 3) != 2) 436 /* wrong jumbo option length/alignment */ 437 return 0; 438 *pl = ntohl(*(__be32 *)(xh + off + 2)); 439 goto done; 440 default: 441 optlen = xh[off + 1] + 2; 442 if (optlen > len) 443 /* ignore obscure options */ 444 goto done; 445 break; 446 } 447 off += optlen; 448 len -= optlen; 449 } 450 451 done: 452 return 1; 453 } 454 455 static int tcf_csum_ipv6(struct sk_buff *skb, u32 update_flags) 456 { 457 struct ipv6hdr *ip6h; 458 struct ipv6_opt_hdr *ip6xh; 459 unsigned int hl, ixhl; 460 unsigned int pl; 461 int ntkoff; 462 u8 nexthdr; 463 464 ntkoff = skb_network_offset(skb); 465 466 hl = sizeof(*ip6h); 467 468 if (!pskb_may_pull(skb, hl + ntkoff)) 469 goto fail; 470 471 ip6h = ipv6_hdr(skb); 472 473 pl = ntohs(ip6h->payload_len); 474 nexthdr = ip6h->nexthdr; 475 476 do { 477 switch (nexthdr) { 478 case NEXTHDR_FRAGMENT: 479 goto ignore_skb; 480 case NEXTHDR_ROUTING: 481 case NEXTHDR_HOP: 482 case NEXTHDR_DEST: 483 if (!pskb_may_pull(skb, hl + sizeof(*ip6xh) + ntkoff)) 484 goto fail; 485 ip6xh = (void *)(skb_network_header(skb) + hl); 486 ixhl = ipv6_optlen(ip6xh); 487 if (!pskb_may_pull(skb, hl + ixhl + ntkoff)) 488 goto fail; 489 ip6xh = (void *)(skb_network_header(skb) + hl); 490 if ((nexthdr == NEXTHDR_HOP) && 491 !(tcf_csum_ipv6_hopopts(ip6xh, ixhl, &pl))) 492 goto fail; 493 nexthdr = ip6xh->nexthdr; 494 hl += ixhl; 495 break; 496 case IPPROTO_ICMPV6: 497 if (update_flags & TCA_CSUM_UPDATE_FLAG_ICMP) 498 if (!tcf_csum_ipv6_icmp(skb, 499 hl, pl + sizeof(*ip6h))) 500 goto fail; 501 goto done; 502 case IPPROTO_TCP: 503 if (update_flags & TCA_CSUM_UPDATE_FLAG_TCP) 504 if (!tcf_csum_ipv6_tcp(skb, 505 hl, pl + sizeof(*ip6h))) 506 goto fail; 507 goto done; 508 case IPPROTO_UDP: 509 if (update_flags & TCA_CSUM_UPDATE_FLAG_UDP) 510 if (!tcf_csum_ipv6_udp(skb, hl, 511 pl + sizeof(*ip6h), 0)) 512 goto fail; 513 goto done; 514 case IPPROTO_UDPLITE: 515 if (update_flags & TCA_CSUM_UPDATE_FLAG_UDPLITE) 516 if (!tcf_csum_ipv6_udp(skb, hl, 517 pl + sizeof(*ip6h), 1)) 518 goto fail; 519 goto done; 520 case IPPROTO_SCTP: 521 if ((update_flags & TCA_CSUM_UPDATE_FLAG_SCTP) && 522 !tcf_csum_sctp(skb, hl, pl + sizeof(*ip6h))) 523 goto fail; 524 goto done; 525 default: 526 goto ignore_skb; 527 } 528 } while (pskb_may_pull(skb, hl + 1 + ntkoff)); 529 530 done: 531 ignore_skb: 532 return 1; 533 534 fail: 535 return 0; 536 } 537 538 static int tcf_csum(struct sk_buff *skb, const struct tc_action *a, 539 struct tcf_result *res) 540 { 541 struct tcf_csum *p = to_tcf_csum(a); 542 int action; 543 u32 update_flags; 544 545 spin_lock(&p->tcf_lock); 546 tcf_lastuse_update(&p->tcf_tm); 547 bstats_update(&p->tcf_bstats, skb); 548 action = p->tcf_action; 549 update_flags = p->update_flags; 550 spin_unlock(&p->tcf_lock); 551 552 if (unlikely(action == TC_ACT_SHOT)) 553 goto drop; 554 555 switch (tc_skb_protocol(skb)) { 556 case cpu_to_be16(ETH_P_IP): 557 if (!tcf_csum_ipv4(skb, update_flags)) 558 goto drop; 559 break; 560 case cpu_to_be16(ETH_P_IPV6): 561 if (!tcf_csum_ipv6(skb, update_flags)) 562 goto drop; 563 break; 564 } 565 566 return action; 567 568 drop: 569 spin_lock(&p->tcf_lock); 570 p->tcf_qstats.drops++; 571 spin_unlock(&p->tcf_lock); 572 return TC_ACT_SHOT; 573 } 574 575 static int tcf_csum_dump(struct sk_buff *skb, struct tc_action *a, int bind, 576 int ref) 577 { 578 unsigned char *b = skb_tail_pointer(skb); 579 struct tcf_csum *p = to_tcf_csum(a); 580 struct tc_csum opt = { 581 .update_flags = p->update_flags, 582 .index = p->tcf_index, 583 .action = p->tcf_action, 584 .refcnt = p->tcf_refcnt - ref, 585 .bindcnt = p->tcf_bindcnt - bind, 586 }; 587 struct tcf_t t; 588 589 if (nla_put(skb, TCA_CSUM_PARMS, sizeof(opt), &opt)) 590 goto nla_put_failure; 591 592 tcf_tm_dump(&t, &p->tcf_tm); 593 if (nla_put_64bit(skb, TCA_CSUM_TM, sizeof(t), &t, TCA_CSUM_PAD)) 594 goto nla_put_failure; 595 596 return skb->len; 597 598 nla_put_failure: 599 nlmsg_trim(skb, b); 600 return -1; 601 } 602 603 static int tcf_csum_walker(struct net *net, struct sk_buff *skb, 604 struct netlink_callback *cb, int type, 605 const struct tc_action_ops *ops) 606 { 607 struct tc_action_net *tn = net_generic(net, csum_net_id); 608 609 return tcf_generic_walker(tn, skb, cb, type, ops); 610 } 611 612 static int tcf_csum_search(struct net *net, struct tc_action **a, u32 index) 613 { 614 struct tc_action_net *tn = net_generic(net, csum_net_id); 615 616 return tcf_idr_search(tn, a, index); 617 } 618 619 static struct tc_action_ops act_csum_ops = { 620 .kind = "csum", 621 .type = TCA_ACT_CSUM, 622 .owner = THIS_MODULE, 623 .act = tcf_csum, 624 .dump = tcf_csum_dump, 625 .init = tcf_csum_init, 626 .walk = tcf_csum_walker, 627 .lookup = tcf_csum_search, 628 .size = sizeof(struct tcf_csum), 629 }; 630 631 static __net_init int csum_init_net(struct net *net) 632 { 633 struct tc_action_net *tn = net_generic(net, csum_net_id); 634 635 return tc_action_net_init(tn, &act_csum_ops); 636 } 637 638 static void __net_exit csum_exit_net(struct net *net) 639 { 640 struct tc_action_net *tn = net_generic(net, csum_net_id); 641 642 tc_action_net_exit(tn); 643 } 644 645 static struct pernet_operations csum_net_ops = { 646 .init = csum_init_net, 647 .exit = csum_exit_net, 648 .id = &csum_net_id, 649 .size = sizeof(struct tc_action_net), 650 }; 651 652 MODULE_DESCRIPTION("Checksum updating actions"); 653 MODULE_LICENSE("GPL"); 654 655 static int __init csum_init_module(void) 656 { 657 return tcf_register_action(&act_csum_ops, &csum_net_ops); 658 } 659 660 static void __exit csum_cleanup_module(void) 661 { 662 tcf_unregister_action(&act_csum_ops, &csum_net_ops); 663 } 664 665 module_init(csum_init_module); 666 module_exit(csum_cleanup_module); 667