diff options
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/addrconf.c | 9 | ||||
-rw-r--r-- | net/ipv6/ip6_output.c | 7 | ||||
-rw-r--r-- | net/ipv6/xfrm6_output.c | 39 |
3 files changed, 50 insertions, 5 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index c2c26fa0943d..4da664538f52 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -862,6 +862,8 @@ static int inline ipv6_saddr_label(const struct in6_addr *addr, int type) | |||
862 | * 2002::/16 2 | 862 | * 2002::/16 2 |
863 | * ::/96 3 | 863 | * ::/96 3 |
864 | * ::ffff:0:0/96 4 | 864 | * ::ffff:0:0/96 4 |
865 | * fc00::/7 5 | ||
866 | * 2001::/32 6 | ||
865 | */ | 867 | */ |
866 | if (type & IPV6_ADDR_LOOPBACK) | 868 | if (type & IPV6_ADDR_LOOPBACK) |
867 | return 0; | 869 | return 0; |
@@ -869,8 +871,12 @@ static int inline ipv6_saddr_label(const struct in6_addr *addr, int type) | |||
869 | return 3; | 871 | return 3; |
870 | else if (type & IPV6_ADDR_MAPPED) | 872 | else if (type & IPV6_ADDR_MAPPED) |
871 | return 4; | 873 | return 4; |
874 | else if (addr->s6_addr32[0] == htonl(0x20010000)) | ||
875 | return 6; | ||
872 | else if (addr->s6_addr16[0] == htons(0x2002)) | 876 | else if (addr->s6_addr16[0] == htons(0x2002)) |
873 | return 2; | 877 | return 2; |
878 | else if ((addr->s6_addr[0] & 0xfe) == 0xfc) | ||
879 | return 5; | ||
874 | return 1; | 880 | return 1; |
875 | } | 881 | } |
876 | 882 | ||
@@ -1069,6 +1075,9 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev, | |||
1069 | if (hiscore.attrs & IPV6_SADDR_SCORE_PRIVACY) | 1075 | if (hiscore.attrs & IPV6_SADDR_SCORE_PRIVACY) |
1070 | continue; | 1076 | continue; |
1071 | } | 1077 | } |
1078 | #else | ||
1079 | if (hiscore.rule < 7) | ||
1080 | hiscore.rule++; | ||
1072 | #endif | 1081 | #endif |
1073 | /* Rule 8: Use longest matching prefix */ | 1082 | /* Rule 8: Use longest matching prefix */ |
1074 | if (hiscore.rule < 8) { | 1083 | if (hiscore.rule < 8) { |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index d29620f4910e..abb94de33768 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -148,7 +148,7 @@ static int ip6_output2(struct sk_buff *skb) | |||
148 | 148 | ||
149 | int ip6_output(struct sk_buff *skb) | 149 | int ip6_output(struct sk_buff *skb) |
150 | { | 150 | { |
151 | if ((skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->ufo_size) || | 151 | if ((skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->gso_size) || |
152 | dst_allfrag(skb->dst)) | 152 | dst_allfrag(skb->dst)) |
153 | return ip6_fragment(skb, ip6_output2); | 153 | return ip6_fragment(skb, ip6_output2); |
154 | else | 154 | else |
@@ -833,8 +833,9 @@ static inline int ip6_ufo_append_data(struct sock *sk, | |||
833 | struct frag_hdr fhdr; | 833 | struct frag_hdr fhdr; |
834 | 834 | ||
835 | /* specify the length of each IP datagram fragment*/ | 835 | /* specify the length of each IP datagram fragment*/ |
836 | skb_shinfo(skb)->ufo_size = (mtu - fragheaderlen) - | 836 | skb_shinfo(skb)->gso_size = mtu - fragheaderlen - |
837 | sizeof(struct frag_hdr); | 837 | sizeof(struct frag_hdr); |
838 | skb_shinfo(skb)->gso_type = SKB_GSO_UDPV4; | ||
838 | ipv6_select_ident(skb, &fhdr); | 839 | ipv6_select_ident(skb, &fhdr); |
839 | skb_shinfo(skb)->ip6_frag_id = fhdr.identification; | 840 | skb_shinfo(skb)->ip6_frag_id = fhdr.identification; |
840 | __skb_queue_tail(&sk->sk_write_queue, skb); | 841 | __skb_queue_tail(&sk->sk_write_queue, skb); |
diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c index 16e84254a252..48fccb1eca08 100644 --- a/net/ipv6/xfrm6_output.c +++ b/net/ipv6/xfrm6_output.c | |||
@@ -94,7 +94,7 @@ error_nolock: | |||
94 | goto out_exit; | 94 | goto out_exit; |
95 | } | 95 | } |
96 | 96 | ||
97 | static int xfrm6_output_finish(struct sk_buff *skb) | 97 | static int xfrm6_output_finish2(struct sk_buff *skb) |
98 | { | 98 | { |
99 | int err; | 99 | int err; |
100 | 100 | ||
@@ -110,7 +110,7 @@ static int xfrm6_output_finish(struct sk_buff *skb) | |||
110 | return dst_output(skb); | 110 | return dst_output(skb); |
111 | 111 | ||
112 | err = nf_hook(PF_INET6, NF_IP6_POST_ROUTING, &skb, NULL, | 112 | err = nf_hook(PF_INET6, NF_IP6_POST_ROUTING, &skb, NULL, |
113 | skb->dst->dev, xfrm6_output_finish); | 113 | skb->dst->dev, xfrm6_output_finish2); |
114 | if (unlikely(err != 1)) | 114 | if (unlikely(err != 1)) |
115 | break; | 115 | break; |
116 | } | 116 | } |
@@ -118,6 +118,41 @@ static int xfrm6_output_finish(struct sk_buff *skb) | |||
118 | return err; | 118 | return err; |
119 | } | 119 | } |
120 | 120 | ||
121 | static int xfrm6_output_finish(struct sk_buff *skb) | ||
122 | { | ||
123 | struct sk_buff *segs; | ||
124 | |||
125 | if (!skb_shinfo(skb)->gso_size) | ||
126 | return xfrm6_output_finish2(skb); | ||
127 | |||
128 | skb->protocol = htons(ETH_P_IP); | ||
129 | segs = skb_gso_segment(skb, 0); | ||
130 | kfree_skb(skb); | ||
131 | if (unlikely(IS_ERR(segs))) | ||
132 | return PTR_ERR(segs); | ||
133 | |||
134 | do { | ||
135 | struct sk_buff *nskb = segs->next; | ||
136 | int err; | ||
137 | |||
138 | segs->next = NULL; | ||
139 | err = xfrm6_output_finish2(segs); | ||
140 | |||
141 | if (unlikely(err)) { | ||
142 | while ((segs = nskb)) { | ||
143 | nskb = segs->next; | ||
144 | segs->next = NULL; | ||
145 | kfree_skb(segs); | ||
146 | } | ||
147 | return err; | ||
148 | } | ||
149 | |||
150 | segs = nskb; | ||
151 | } while (segs); | ||
152 | |||
153 | return 0; | ||
154 | } | ||
155 | |||
121 | int xfrm6_output(struct sk_buff *skb) | 156 | int xfrm6_output(struct sk_buff *skb) |
122 | { | 157 | { |
123 | return NF_HOOK(PF_INET6, NF_IP6_POST_ROUTING, skb, NULL, skb->dst->dev, | 158 | return NF_HOOK(PF_INET6, NF_IP6_POST_ROUTING, skb, NULL, skb->dst->dev, |