ip6_output.c (888dc273ea4e7ca332a6f73d10dfc8f2b212c803) | ip6_output.c (b7034146756b9e91cc059b19df7fe4defd4d7de7) |
---|---|
1// SPDX-License-Identifier: GPL-2.0-or-later | |
2/* 3 * IPv6 output functions 4 * Linux INET6 implementation 5 * 6 * Authors: 7 * Pedro Roque <roque@di.fc.ul.pt> 8 * 9 * Based on linux/net/ipv4/ip_output.c 10 * | 1/* 2 * IPv6 output functions 3 * Linux INET6 implementation 4 * 5 * Authors: 6 * Pedro Roque <roque@di.fc.ul.pt> 7 * 8 * Based on linux/net/ipv4/ip_output.c 9 * |
10 * This program is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU General Public License 12 * as published by the Free Software Foundation; either version 13 * 2 of the License, or (at your option) any later version. 14 * |
|
11 * Changes: 12 * A.N.Kuznetsov : airthmetics in fragmentation. 13 * extension headers are implemented. 14 * route changes now work. 15 * ip6_forward does not confuse sniffers. 16 * etc. 17 * 18 * H. von Brand : Added missing #include <linux/string.h> --- 100 unchanged lines hidden (view full) --- 119 } 120 rcu_read_unlock_bh(); 121 122 IP6_INC_STATS(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES); 123 kfree_skb(skb); 124 return -EINVAL; 125} 126 | 15 * Changes: 16 * A.N.Kuznetsov : airthmetics in fragmentation. 17 * extension headers are implemented. 18 * route changes now work. 19 * ip6_forward does not confuse sniffers. 20 * etc. 21 * 22 * H. von Brand : Added missing #include <linux/string.h> --- 100 unchanged lines hidden (view full) --- 123 } 124 rcu_read_unlock_bh(); 125 126 IP6_INC_STATS(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES); 127 kfree_skb(skb); 128 return -EINVAL; 129} 130 |
127static int ip6_finish_output(struct net *net, struct sock *sk, struct sk_buff *skb) | 131static int __ip6_finish_output(struct net *net, struct sock *sk, struct sk_buff *skb) |
128{ | 132{ |
129 int ret; 130 131 ret = BPF_CGROUP_RUN_PROG_INET_EGRESS(sk, skb); 132 if (ret) { 133 kfree_skb(skb); 134 return ret; 135 } 136 | |
137#if defined(CONFIG_NETFILTER) && defined(CONFIG_XFRM) 138 /* Policy lookup after SNAT yielded a new policy */ 139 if (skb_dst(skb)->xfrm) { 140 IPCB(skb)->flags |= IPSKB_REROUTED; 141 return dst_output(net, sk, skb); 142 } 143#endif 144 145 if ((skb->len > ip6_skb_dst_mtu(skb) && !skb_is_gso(skb)) || 146 dst_allfrag(skb_dst(skb)) || 147 (IP6CB(skb)->frag_max_size && skb->len > IP6CB(skb)->frag_max_size)) 148 return ip6_fragment(net, sk, skb, ip6_finish_output2); 149 else 150 return ip6_finish_output2(net, sk, skb); 151} 152 | 133#if defined(CONFIG_NETFILTER) && defined(CONFIG_XFRM) 134 /* Policy lookup after SNAT yielded a new policy */ 135 if (skb_dst(skb)->xfrm) { 136 IPCB(skb)->flags |= IPSKB_REROUTED; 137 return dst_output(net, sk, skb); 138 } 139#endif 140 141 if ((skb->len > ip6_skb_dst_mtu(skb) && !skb_is_gso(skb)) || 142 dst_allfrag(skb_dst(skb)) || 143 (IP6CB(skb)->frag_max_size && skb->len > IP6CB(skb)->frag_max_size)) 144 return ip6_fragment(net, sk, skb, ip6_finish_output2); 145 else 146 return ip6_finish_output2(net, sk, skb); 147} 148 |
149static int ip6_finish_output(struct net *net, struct sock *sk, struct sk_buff *skb) 150{ 151 int ret; 152 153 ret = BPF_CGROUP_RUN_PROG_INET_EGRESS(sk, skb); 154 switch (ret) { 155 case NET_XMIT_SUCCESS: 156 return __ip6_finish_output(net, sk, skb); 157 case NET_XMIT_CN: 158 return __ip6_finish_output(net, sk, skb) ? : ret; 159 default: 160 kfree_skb(skb); 161 return ret; 162 } 163} 164 |
|
153int ip6_output(struct net *net, struct sock *sk, struct sk_buff *skb) 154{ 155 struct net_device *dev = skb_dst(skb)->dev; 156 struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb)); 157 158 skb->protocol = htons(ETH_P_IPV6); 159 skb->dev = dev; 160 --- 422 unchanged lines hidden (view full) --- 583#ifdef CONFIG_NET_SCHED 584 to->tc_index = from->tc_index; 585#endif 586 nf_copy(to, from); 587 skb_ext_copy(to, from); 588 skb_copy_secmark(to, from); 589} 590 | 165int ip6_output(struct net *net, struct sock *sk, struct sk_buff *skb) 166{ 167 struct net_device *dev = skb_dst(skb)->dev; 168 struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb)); 169 170 skb->protocol = htons(ETH_P_IPV6); 171 skb->dev = dev; 172 --- 422 unchanged lines hidden (view full) --- 595#ifdef CONFIG_NET_SCHED 596 to->tc_index = from->tc_index; 597#endif 598 nf_copy(to, from); 599 skb_ext_copy(to, from); 600 skb_copy_secmark(to, from); 601} 602 |
603int ip6_fraglist_init(struct sk_buff *skb, unsigned int hlen, u8 *prevhdr, 604 u8 nexthdr, __be32 frag_id, 605 struct ip6_fraglist_iter *iter) 606{ 607 unsigned int first_len; 608 struct frag_hdr *fh; 609 610 /* BUILD HEADER */ 611 *prevhdr = NEXTHDR_FRAGMENT; 612 iter->tmp_hdr = kmemdup(skb_network_header(skb), hlen, GFP_ATOMIC); 613 if (!iter->tmp_hdr) 614 return -ENOMEM; 615 616 iter->frag = skb_shinfo(skb)->frag_list; 617 skb_frag_list_init(skb); 618 619 iter->offset = 0; 620 iter->hlen = hlen; 621 iter->frag_id = frag_id; 622 iter->nexthdr = nexthdr; 623 624 __skb_pull(skb, hlen); 625 fh = __skb_push(skb, sizeof(struct frag_hdr)); 626 __skb_push(skb, hlen); 627 skb_reset_network_header(skb); 628 memcpy(skb_network_header(skb), iter->tmp_hdr, hlen); 629 630 fh->nexthdr = nexthdr; 631 fh->reserved = 0; 632 fh->frag_off = htons(IP6_MF); 633 fh->identification = frag_id; 634 635 first_len = skb_pagelen(skb); 636 skb->data_len = first_len - skb_headlen(skb); 637 skb->len = first_len; 638 ipv6_hdr(skb)->payload_len = htons(first_len - sizeof(struct ipv6hdr)); 639 640 return 0; 641} 642EXPORT_SYMBOL(ip6_fraglist_init); 643 644void ip6_fraglist_prepare(struct sk_buff *skb, 645 struct ip6_fraglist_iter *iter) 646{ 647 struct sk_buff *frag = iter->frag; 648 unsigned int hlen = iter->hlen; 649 struct frag_hdr *fh; 650 651 frag->ip_summed = CHECKSUM_NONE; 652 skb_reset_transport_header(frag); 653 fh = __skb_push(frag, sizeof(struct frag_hdr)); 654 __skb_push(frag, hlen); 655 skb_reset_network_header(frag); 656 memcpy(skb_network_header(frag), iter->tmp_hdr, hlen); 657 iter->offset += skb->len - hlen - sizeof(struct frag_hdr); 658 fh->nexthdr = iter->nexthdr; 659 fh->reserved = 0; 660 fh->frag_off = htons(iter->offset); 661 if (frag->next) 662 fh->frag_off |= htons(IP6_MF); 663 fh->identification = iter->frag_id; 664 ipv6_hdr(frag)->payload_len = htons(frag->len - sizeof(struct ipv6hdr)); 665 ip6_copy_metadata(frag, skb); 666} 667EXPORT_SYMBOL(ip6_fraglist_prepare); 668 669void ip6_frag_init(struct sk_buff *skb, unsigned int hlen, unsigned int mtu, 670 unsigned short needed_tailroom, int hdr_room, u8 *prevhdr, 671 u8 nexthdr, __be32 frag_id, struct ip6_frag_state *state) 672{ 673 state->prevhdr = prevhdr; 674 state->nexthdr = nexthdr; 675 state->frag_id = frag_id; 676 677 state->hlen = hlen; 678 state->mtu = mtu; 679 680 state->left = skb->len - hlen; /* Space per frame */ 681 state->ptr = hlen; /* Where to start from */ 682 683 state->hroom = hdr_room; 684 state->troom = needed_tailroom; 685 686 state->offset = 0; 687} 688EXPORT_SYMBOL(ip6_frag_init); 689 690struct sk_buff *ip6_frag_next(struct sk_buff *skb, struct ip6_frag_state *state) 691{ 692 u8 *prevhdr = state->prevhdr, *fragnexthdr_offset; 693 struct sk_buff *frag; 694 struct frag_hdr *fh; 695 unsigned int len; 696 697 len = state->left; 698 /* IF: it doesn't fit, use 'mtu' - the data space left */ 699 if (len > state->mtu) 700 len = state->mtu; 701 /* IF: we are not sending up to and including the packet end 702 then align the next start on an eight byte boundary */ 703 if (len < state->left) 704 len &= ~7; 705 706 /* Allocate buffer */ 707 frag = alloc_skb(len + state->hlen + sizeof(struct frag_hdr) + 708 state->hroom + state->troom, GFP_ATOMIC); 709 if (!frag) 710 return ERR_PTR(-ENOMEM); 711 712 /* 713 * Set up data on packet 714 */ 715 716 ip6_copy_metadata(frag, skb); 717 skb_reserve(frag, state->hroom); 718 skb_put(frag, len + state->hlen + sizeof(struct frag_hdr)); 719 skb_reset_network_header(frag); 720 fh = (struct frag_hdr *)(skb_network_header(frag) + state->hlen); 721 frag->transport_header = (frag->network_header + state->hlen + 722 sizeof(struct frag_hdr)); 723 724 /* 725 * Charge the memory for the fragment to any owner 726 * it might possess 727 */ 728 if (skb->sk) 729 skb_set_owner_w(frag, skb->sk); 730 731 /* 732 * Copy the packet header into the new buffer. 733 */ 734 skb_copy_from_linear_data(skb, skb_network_header(frag), state->hlen); 735 736 fragnexthdr_offset = skb_network_header(frag); 737 fragnexthdr_offset += prevhdr - skb_network_header(skb); 738 *fragnexthdr_offset = NEXTHDR_FRAGMENT; 739 740 /* 741 * Build fragment header. 742 */ 743 fh->nexthdr = state->nexthdr; 744 fh->reserved = 0; 745 fh->identification = state->frag_id; 746 747 /* 748 * Copy a block of the IP datagram. 749 */ 750 BUG_ON(skb_copy_bits(skb, state->ptr, skb_transport_header(frag), 751 len)); 752 state->left -= len; 753 754 fh->frag_off = htons(state->offset); 755 if (state->left > 0) 756 fh->frag_off |= htons(IP6_MF); 757 ipv6_hdr(frag)->payload_len = htons(frag->len - sizeof(struct ipv6hdr)); 758 759 state->ptr += len; 760 state->offset += len; 761 762 return frag; 763} 764EXPORT_SYMBOL(ip6_frag_next); 765 |
|
591int ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, 592 int (*output)(struct net *, struct sock *, struct sk_buff *)) 593{ 594 struct sk_buff *frag; 595 struct rt6_info *rt = (struct rt6_info *)skb_dst(skb); 596 struct ipv6_pinfo *np = skb->sk && !dev_recursion_level() ? 597 inet6_sk(skb->sk) : NULL; | 766int ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, 767 int (*output)(struct net *, struct sock *, struct sk_buff *)) 768{ 769 struct sk_buff *frag; 770 struct rt6_info *rt = (struct rt6_info *)skb_dst(skb); 771 struct ipv6_pinfo *np = skb->sk && !dev_recursion_level() ? 772 inet6_sk(skb->sk) : NULL; |
598 struct ipv6hdr *tmp_hdr; 599 struct frag_hdr *fh; 600 unsigned int mtu, hlen, left, len, nexthdr_offset; 601 int hroom, troom; | 773 struct ip6_frag_state state; 774 unsigned int mtu, hlen, nexthdr_offset; 775 int hroom, err = 0; |
602 __be32 frag_id; | 776 __be32 frag_id; |
603 int ptr, offset = 0, err = 0; | |
604 u8 *prevhdr, nexthdr = 0; 605 606 err = ip6_find_1stfragopt(skb, &prevhdr); 607 if (err < 0) 608 goto fail; 609 hlen = err; 610 nexthdr = *prevhdr; 611 nexthdr_offset = prevhdr - skb_network_header(skb); --- 30 unchanged lines hidden (view full) --- 642 if (skb->ip_summed == CHECKSUM_PARTIAL && 643 (err = skb_checksum_help(skb))) 644 goto fail; 645 646 prevhdr = skb_network_header(skb) + nexthdr_offset; 647 hroom = LL_RESERVED_SPACE(rt->dst.dev); 648 if (skb_has_frag_list(skb)) { 649 unsigned int first_len = skb_pagelen(skb); | 777 u8 *prevhdr, nexthdr = 0; 778 779 err = ip6_find_1stfragopt(skb, &prevhdr); 780 if (err < 0) 781 goto fail; 782 hlen = err; 783 nexthdr = *prevhdr; 784 nexthdr_offset = prevhdr - skb_network_header(skb); --- 30 unchanged lines hidden (view full) --- 815 if (skb->ip_summed == CHECKSUM_PARTIAL && 816 (err = skb_checksum_help(skb))) 817 goto fail; 818 819 prevhdr = skb_network_header(skb) + nexthdr_offset; 820 hroom = LL_RESERVED_SPACE(rt->dst.dev); 821 if (skb_has_frag_list(skb)) { 822 unsigned int first_len = skb_pagelen(skb); |
823 struct ip6_fraglist_iter iter; |
|
650 struct sk_buff *frag2; 651 652 if (first_len - hlen > mtu || 653 ((first_len - hlen) & 7) || 654 skb_cloned(skb) || 655 skb_headroom(skb) < (hroom + sizeof(struct frag_hdr))) 656 goto slow_path; 657 --- 11 unchanged lines hidden (view full) --- 669 BUG_ON(frag->sk); 670 if (skb->sk) { 671 frag->sk = skb->sk; 672 frag->destructor = sock_wfree; 673 } 674 skb->truesize -= frag->truesize; 675 } 676 | 824 struct sk_buff *frag2; 825 826 if (first_len - hlen > mtu || 827 ((first_len - hlen) & 7) || 828 skb_cloned(skb) || 829 skb_headroom(skb) < (hroom + sizeof(struct frag_hdr))) 830 goto slow_path; 831 --- 11 unchanged lines hidden (view full) --- 843 BUG_ON(frag->sk); 844 if (skb->sk) { 845 frag->sk = skb->sk; 846 frag->destructor = sock_wfree; 847 } 848 skb->truesize -= frag->truesize; 849 } 850 |
677 err = 0; 678 offset = 0; 679 /* BUILD HEADER */ 680 681 *prevhdr = NEXTHDR_FRAGMENT; 682 tmp_hdr = kmemdup(skb_network_header(skb), hlen, GFP_ATOMIC); 683 if (!tmp_hdr) { 684 err = -ENOMEM; | 851 err = ip6_fraglist_init(skb, hlen, prevhdr, nexthdr, frag_id, 852 &iter); 853 if (err < 0) |
685 goto fail; | 854 goto fail; |
686 } 687 frag = skb_shinfo(skb)->frag_list; 688 skb_frag_list_init(skb); | |
689 | 855 |
690 __skb_pull(skb, hlen); 691 fh = __skb_push(skb, sizeof(struct frag_hdr)); 692 __skb_push(skb, hlen); 693 skb_reset_network_header(skb); 694 memcpy(skb_network_header(skb), tmp_hdr, hlen); 695 696 fh->nexthdr = nexthdr; 697 fh->reserved = 0; 698 fh->frag_off = htons(IP6_MF); 699 fh->identification = frag_id; 700 701 first_len = skb_pagelen(skb); 702 skb->data_len = first_len - skb_headlen(skb); 703 skb->len = first_len; 704 ipv6_hdr(skb)->payload_len = htons(first_len - 705 sizeof(struct ipv6hdr)); 706 | |
707 for (;;) { 708 /* Prepare header of the next frame, 709 * before previous one went down. */ | 856 for (;;) { 857 /* Prepare header of the next frame, 858 * before previous one went down. */ |
710 if (frag) { 711 frag->ip_summed = CHECKSUM_NONE; 712 skb_reset_transport_header(frag); 713 fh = __skb_push(frag, sizeof(struct frag_hdr)); 714 __skb_push(frag, hlen); 715 skb_reset_network_header(frag); 716 memcpy(skb_network_header(frag), tmp_hdr, 717 hlen); 718 offset += skb->len - hlen - sizeof(struct frag_hdr); 719 fh->nexthdr = nexthdr; 720 fh->reserved = 0; 721 fh->frag_off = htons(offset); 722 if (frag->next) 723 fh->frag_off |= htons(IP6_MF); 724 fh->identification = frag_id; 725 ipv6_hdr(frag)->payload_len = 726 htons(frag->len - 727 sizeof(struct ipv6hdr)); 728 ip6_copy_metadata(frag, skb); 729 } | 859 if (iter.frag) 860 ip6_fraglist_prepare(skb, &iter); |
730 731 err = output(net, sk, skb); 732 if (!err) 733 IP6_INC_STATS(net, ip6_dst_idev(&rt->dst), 734 IPSTATS_MIB_FRAGCREATES); 735 | 861 862 err = output(net, sk, skb); 863 if (!err) 864 IP6_INC_STATS(net, ip6_dst_idev(&rt->dst), 865 IPSTATS_MIB_FRAGCREATES); 866 |
736 if (err || !frag) | 867 if (err || !iter.frag) |
737 break; 738 | 868 break; 869 |
739 skb = frag; 740 frag = skb->next; 741 skb_mark_not_on_list(skb); | 870 skb = ip6_fraglist_next(&iter); |
742 } 743 | 871 } 872 |
744 kfree(tmp_hdr); | 873 kfree(iter.tmp_hdr); |
745 746 if (err == 0) { 747 IP6_INC_STATS(net, ip6_dst_idev(&rt->dst), 748 IPSTATS_MIB_FRAGOKS); 749 return 0; 750 } 751 | 874 875 if (err == 0) { 876 IP6_INC_STATS(net, ip6_dst_idev(&rt->dst), 877 IPSTATS_MIB_FRAGOKS); 878 return 0; 879 } 880 |
752 kfree_skb_list(frag); | 881 kfree_skb_list(iter.frag); |
753 754 IP6_INC_STATS(net, ip6_dst_idev(&rt->dst), 755 IPSTATS_MIB_FRAGFAILS); 756 return err; 757 758slow_path_clean: 759 skb_walk_frags(skb, frag2) { 760 if (frag2 == frag) 761 break; 762 frag2->sk = NULL; 763 frag2->destructor = NULL; 764 skb->truesize += frag2->truesize; 765 } 766 } 767 768slow_path: | 882 883 IP6_INC_STATS(net, ip6_dst_idev(&rt->dst), 884 IPSTATS_MIB_FRAGFAILS); 885 return err; 886 887slow_path_clean: 888 skb_walk_frags(skb, frag2) { 889 if (frag2 == frag) 890 break; 891 frag2->sk = NULL; 892 frag2->destructor = NULL; 893 skb->truesize += frag2->truesize; 894 } 895 } 896 897slow_path: |
769 left = skb->len - hlen; /* Space per frame */ 770 ptr = hlen; /* Where to start from */ 771 | |
772 /* 773 * Fragment the datagram. 774 */ 775 | 898 /* 899 * Fragment the datagram. 900 */ 901 |
776 troom = rt->dst.dev->needed_tailroom; | 902 ip6_frag_init(skb, hlen, mtu, rt->dst.dev->needed_tailroom, 903 LL_RESERVED_SPACE(rt->dst.dev), prevhdr, nexthdr, frag_id, 904 &state); |
777 778 /* 779 * Keep copying data until we run out. 780 */ | 905 906 /* 907 * Keep copying data until we run out. 908 */ |
781 while (left > 0) { 782 u8 *fragnexthdr_offset; | |
783 | 909 |
784 len = left; 785 /* IF: it doesn't fit, use 'mtu' - the data space left */ 786 if (len > mtu) 787 len = mtu; 788 /* IF: we are not sending up to and including the packet end 789 then align the next start on an eight byte boundary */ 790 if (len < left) { 791 len &= ~7; 792 } 793 794 /* Allocate buffer */ 795 frag = alloc_skb(len + hlen + sizeof(struct frag_hdr) + 796 hroom + troom, GFP_ATOMIC); 797 if (!frag) { 798 err = -ENOMEM; | 910 while (state.left > 0) { 911 frag = ip6_frag_next(skb, &state); 912 if (IS_ERR(frag)) { 913 err = PTR_ERR(frag); |
799 goto fail; 800 } 801 802 /* | 914 goto fail; 915 } 916 917 /* |
803 * Set up data on packet 804 */ 805 806 ip6_copy_metadata(frag, skb); 807 skb_reserve(frag, hroom); 808 skb_put(frag, len + hlen + sizeof(struct frag_hdr)); 809 skb_reset_network_header(frag); 810 fh = (struct frag_hdr *)(skb_network_header(frag) + hlen); 811 frag->transport_header = (frag->network_header + hlen + 812 sizeof(struct frag_hdr)); 813 814 /* 815 * Charge the memory for the fragment to any owner 816 * it might possess 817 */ 818 if (skb->sk) 819 skb_set_owner_w(frag, skb->sk); 820 821 /* 822 * Copy the packet header into the new buffer. 823 */ 824 skb_copy_from_linear_data(skb, skb_network_header(frag), hlen); 825 826 fragnexthdr_offset = skb_network_header(frag); 827 fragnexthdr_offset += prevhdr - skb_network_header(skb); 828 *fragnexthdr_offset = NEXTHDR_FRAGMENT; 829 830 /* 831 * Build fragment header. 832 */ 833 fh->nexthdr = nexthdr; 834 fh->reserved = 0; 835 fh->identification = frag_id; 836 837 /* 838 * Copy a block of the IP datagram. 839 */ 840 BUG_ON(skb_copy_bits(skb, ptr, skb_transport_header(frag), 841 len)); 842 left -= len; 843 844 fh->frag_off = htons(offset); 845 if (left > 0) 846 fh->frag_off |= htons(IP6_MF); 847 ipv6_hdr(frag)->payload_len = htons(frag->len - 848 sizeof(struct ipv6hdr)); 849 850 ptr += len; 851 offset += len; 852 853 /* | |
854 * Put this fragment into the sending queue. 855 */ 856 err = output(net, sk, frag); 857 if (err) 858 goto fail; 859 860 IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), 861 IPSTATS_MIB_FRAGCREATES); --- 959 unchanged lines hidden --- | 918 * Put this fragment into the sending queue. 919 */ 920 err = output(net, sk, frag); 921 if (err) 922 goto fail; 923 924 IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), 925 IPSTATS_MIB_FRAGCREATES); --- 959 unchanged lines hidden --- |