diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-21 00:04:44 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-21 00:04:44 -0400 |
commit | f8965467f366fd18f01feafb5db10512d7b4422c (patch) | |
tree | 3706a9cd779859271ca61b85c63a1bc3f82d626e /net/ipv6/ip6_output.c | |
parent | a26272e5200765691e67d6780e52b32498fdb659 (diff) | |
parent | 2ec8c6bb5d8f3a62a79f463525054bae1e3d4487 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6: (1674 commits)
qlcnic: adding co maintainer
ixgbe: add support for active DA cables
ixgbe: dcb, do not tag tc_prio_control frames
ixgbe: fix ixgbe_tx_is_paused logic
ixgbe: always enable vlan strip/insert when DCB is enabled
ixgbe: remove some redundant code in setting FCoE FIP filter
ixgbe: fix wrong offset to fc_frame_header in ixgbe_fcoe_ddp
ixgbe: fix header len when unsplit packet overflows to data buffer
ipv6: Never schedule DAD timer on dead address
ipv6: Use POSTDAD state
ipv6: Use state_lock to protect ifa state
ipv6: Replace inet6_ifaddr->dead with state
cxgb4: notify upper drivers if the device is already up when they load
cxgb4: keep interrupts available when the ports are brought down
cxgb4: fix initial addition of MAC address
cnic: Return SPQ credit to bnx2x after ring setup and shutdown.
cnic: Convert cnic_local_flags to atomic ops.
can: Fix SJA1000 command register writes on SMP systems
bridge: fix build for CONFIG_SYSFS disabled
ARCNET: Limit com20020 PCI ID matches for SOHARD cards
...
Fix up various conflicts with pcmcia tree drivers/net/
{pcmcia/3c589_cs.c, wireless/orinoco/orinoco_cs.c and
wireless/orinoco/spectrum_cs.c} and feature removal
(Documentation/feature-removal-schedule.txt).
Also fix a non-content conflict due to pm_qos_requirement getting
renamed in the PM tree (now pm_qos_request) in net/mac80211/scan.c
Diffstat (limited to 'net/ipv6/ip6_output.c')
-rw-r--r-- | net/ipv6/ip6_output.c | 103 |
1 files changed, 52 insertions, 51 deletions
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 75d5ef830097..cd963f64e27c 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -67,8 +67,8 @@ int __ip6_local_out(struct sk_buff *skb) | |||
67 | len = 0; | 67 | len = 0; |
68 | ipv6_hdr(skb)->payload_len = htons(len); | 68 | ipv6_hdr(skb)->payload_len = htons(len); |
69 | 69 | ||
70 | return nf_hook(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, skb_dst(skb)->dev, | 70 | return nf_hook(NFPROTO_IPV6, NF_INET_LOCAL_OUT, skb, NULL, |
71 | dst_output); | 71 | skb_dst(skb)->dev, dst_output); |
72 | } | 72 | } |
73 | 73 | ||
74 | int ip6_local_out(struct sk_buff *skb) | 74 | int ip6_local_out(struct sk_buff *skb) |
@@ -83,22 +83,6 @@ int ip6_local_out(struct sk_buff *skb) | |||
83 | } | 83 | } |
84 | EXPORT_SYMBOL_GPL(ip6_local_out); | 84 | EXPORT_SYMBOL_GPL(ip6_local_out); |
85 | 85 | ||
86 | static int ip6_output_finish(struct sk_buff *skb) | ||
87 | { | ||
88 | struct dst_entry *dst = skb_dst(skb); | ||
89 | |||
90 | if (dst->hh) | ||
91 | return neigh_hh_output(dst->hh, skb); | ||
92 | else if (dst->neighbour) | ||
93 | return dst->neighbour->output(skb); | ||
94 | |||
95 | IP6_INC_STATS_BH(dev_net(dst->dev), | ||
96 | ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES); | ||
97 | kfree_skb(skb); | ||
98 | return -EINVAL; | ||
99 | |||
100 | } | ||
101 | |||
102 | /* dev_loopback_xmit for use with netfilter. */ | 86 | /* dev_loopback_xmit for use with netfilter. */ |
103 | static int ip6_dev_loopback_xmit(struct sk_buff *newskb) | 87 | static int ip6_dev_loopback_xmit(struct sk_buff *newskb) |
104 | { | 88 | { |
@@ -112,8 +96,7 @@ static int ip6_dev_loopback_xmit(struct sk_buff *newskb) | |||
112 | return 0; | 96 | return 0; |
113 | } | 97 | } |
114 | 98 | ||
115 | 99 | static int ip6_finish_output2(struct sk_buff *skb) | |
116 | static int ip6_output2(struct sk_buff *skb) | ||
117 | { | 100 | { |
118 | struct dst_entry *dst = skb_dst(skb); | 101 | struct dst_entry *dst = skb_dst(skb); |
119 | struct net_device *dev = dst->dev; | 102 | struct net_device *dev = dst->dev; |
@@ -125,7 +108,7 @@ static int ip6_output2(struct sk_buff *skb) | |||
125 | struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb)); | 108 | struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb)); |
126 | 109 | ||
127 | if (!(dev->flags & IFF_LOOPBACK) && sk_mc_loop(skb->sk) && | 110 | if (!(dev->flags & IFF_LOOPBACK) && sk_mc_loop(skb->sk) && |
128 | ((mroute6_socket(dev_net(dev)) && | 111 | ((mroute6_socket(dev_net(dev), skb) && |
129 | !(IP6CB(skb)->flags & IP6SKB_FORWARDED)) || | 112 | !(IP6CB(skb)->flags & IP6SKB_FORWARDED)) || |
130 | ipv6_chk_mcast_addr(dev, &ipv6_hdr(skb)->daddr, | 113 | ipv6_chk_mcast_addr(dev, &ipv6_hdr(skb)->daddr, |
131 | &ipv6_hdr(skb)->saddr))) { | 114 | &ipv6_hdr(skb)->saddr))) { |
@@ -135,8 +118,8 @@ static int ip6_output2(struct sk_buff *skb) | |||
135 | is not supported in any case. | 118 | is not supported in any case. |
136 | */ | 119 | */ |
137 | if (newskb) | 120 | if (newskb) |
138 | NF_HOOK(PF_INET6, NF_INET_POST_ROUTING, newskb, | 121 | NF_HOOK(NFPROTO_IPV6, NF_INET_POST_ROUTING, |
139 | NULL, newskb->dev, | 122 | newskb, NULL, newskb->dev, |
140 | ip6_dev_loopback_xmit); | 123 | ip6_dev_loopback_xmit); |
141 | 124 | ||
142 | if (ipv6_hdr(skb)->hop_limit == 0) { | 125 | if (ipv6_hdr(skb)->hop_limit == 0) { |
@@ -151,8 +134,15 @@ static int ip6_output2(struct sk_buff *skb) | |||
151 | skb->len); | 134 | skb->len); |
152 | } | 135 | } |
153 | 136 | ||
154 | return NF_HOOK(PF_INET6, NF_INET_POST_ROUTING, skb, NULL, skb->dev, | 137 | if (dst->hh) |
155 | ip6_output_finish); | 138 | return neigh_hh_output(dst->hh, skb); |
139 | else if (dst->neighbour) | ||
140 | return dst->neighbour->output(skb); | ||
141 | |||
142 | IP6_INC_STATS_BH(dev_net(dst->dev), | ||
143 | ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES); | ||
144 | kfree_skb(skb); | ||
145 | return -EINVAL; | ||
156 | } | 146 | } |
157 | 147 | ||
158 | static inline int ip6_skb_dst_mtu(struct sk_buff *skb) | 148 | static inline int ip6_skb_dst_mtu(struct sk_buff *skb) |
@@ -163,29 +153,37 @@ static inline int ip6_skb_dst_mtu(struct sk_buff *skb) | |||
163 | skb_dst(skb)->dev->mtu : dst_mtu(skb_dst(skb)); | 153 | skb_dst(skb)->dev->mtu : dst_mtu(skb_dst(skb)); |
164 | } | 154 | } |
165 | 155 | ||
156 | static int ip6_finish_output(struct sk_buff *skb) | ||
157 | { | ||
158 | if ((skb->len > ip6_skb_dst_mtu(skb) && !skb_is_gso(skb)) || | ||
159 | dst_allfrag(skb_dst(skb))) | ||
160 | return ip6_fragment(skb, ip6_finish_output2); | ||
161 | else | ||
162 | return ip6_finish_output2(skb); | ||
163 | } | ||
164 | |||
166 | int ip6_output(struct sk_buff *skb) | 165 | int ip6_output(struct sk_buff *skb) |
167 | { | 166 | { |
167 | struct net_device *dev = skb_dst(skb)->dev; | ||
168 | struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb)); | 168 | struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb)); |
169 | if (unlikely(idev->cnf.disable_ipv6)) { | 169 | if (unlikely(idev->cnf.disable_ipv6)) { |
170 | IP6_INC_STATS(dev_net(skb_dst(skb)->dev), idev, | 170 | IP6_INC_STATS(dev_net(dev), idev, |
171 | IPSTATS_MIB_OUTDISCARDS); | 171 | IPSTATS_MIB_OUTDISCARDS); |
172 | kfree_skb(skb); | 172 | kfree_skb(skb); |
173 | return 0; | 173 | return 0; |
174 | } | 174 | } |
175 | 175 | ||
176 | if ((skb->len > ip6_skb_dst_mtu(skb) && !skb_is_gso(skb)) || | 176 | return NF_HOOK_COND(NFPROTO_IPV6, NF_INET_POST_ROUTING, skb, NULL, dev, |
177 | dst_allfrag(skb_dst(skb))) | 177 | ip6_finish_output, |
178 | return ip6_fragment(skb, ip6_output2); | 178 | !(IP6CB(skb)->flags & IP6SKB_REROUTED)); |
179 | else | ||
180 | return ip6_output2(skb); | ||
181 | } | 179 | } |
182 | 180 | ||
183 | /* | 181 | /* |
184 | * xmit an sk_buff (used by TCP) | 182 | * xmit an sk_buff (used by TCP, SCTP and DCCP) |
185 | */ | 183 | */ |
186 | 184 | ||
187 | int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, | 185 | int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, |
188 | struct ipv6_txoptions *opt, int ipfragok) | 186 | struct ipv6_txoptions *opt) |
189 | { | 187 | { |
190 | struct net *net = sock_net(sk); | 188 | struct net *net = sock_net(sk); |
191 | struct ipv6_pinfo *np = inet6_sk(sk); | 189 | struct ipv6_pinfo *np = inet6_sk(sk); |
@@ -218,8 +216,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, | |||
218 | } | 216 | } |
219 | kfree_skb(skb); | 217 | kfree_skb(skb); |
220 | skb = skb2; | 218 | skb = skb2; |
221 | if (sk) | 219 | skb_set_owner_w(skb, sk); |
222 | skb_set_owner_w(skb, sk); | ||
223 | } | 220 | } |
224 | if (opt->opt_flen) | 221 | if (opt->opt_flen) |
225 | ipv6_push_frag_opts(skb, opt, &proto); | 222 | ipv6_push_frag_opts(skb, opt, &proto); |
@@ -231,10 +228,6 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, | |||
231 | skb_reset_network_header(skb); | 228 | skb_reset_network_header(skb); |
232 | hdr = ipv6_hdr(skb); | 229 | hdr = ipv6_hdr(skb); |
233 | 230 | ||
234 | /* Allow local fragmentation. */ | ||
235 | if (ipfragok) | ||
236 | skb->local_df = 1; | ||
237 | |||
238 | /* | 231 | /* |
239 | * Fill in the IPv6 header | 232 | * Fill in the IPv6 header |
240 | */ | 233 | */ |
@@ -261,8 +254,8 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, | |||
261 | if ((skb->len <= mtu) || skb->local_df || skb_is_gso(skb)) { | 254 | if ((skb->len <= mtu) || skb->local_df || skb_is_gso(skb)) { |
262 | IP6_UPD_PO_STATS(net, ip6_dst_idev(skb_dst(skb)), | 255 | IP6_UPD_PO_STATS(net, ip6_dst_idev(skb_dst(skb)), |
263 | IPSTATS_MIB_OUT, skb->len); | 256 | IPSTATS_MIB_OUT, skb->len); |
264 | return NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, dst->dev, | 257 | return NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, skb, NULL, |
265 | dst_output); | 258 | dst->dev, dst_output); |
266 | } | 259 | } |
267 | 260 | ||
268 | if (net_ratelimit()) | 261 | if (net_ratelimit()) |
@@ -538,7 +531,7 @@ int ip6_forward(struct sk_buff *skb) | |||
538 | hdr->hop_limit--; | 531 | hdr->hop_limit--; |
539 | 532 | ||
540 | IP6_INC_STATS_BH(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTFORWDATAGRAMS); | 533 | IP6_INC_STATS_BH(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTFORWDATAGRAMS); |
541 | return NF_HOOK(PF_INET6, NF_INET_FORWARD, skb, skb->dev, dst->dev, | 534 | return NF_HOOK(NFPROTO_IPV6, NF_INET_FORWARD, skb, skb->dev, dst->dev, |
542 | ip6_forward_finish); | 535 | ip6_forward_finish); |
543 | 536 | ||
544 | error: | 537 | error: |
@@ -1109,7 +1102,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1109 | int offset, int len, int odd, struct sk_buff *skb), | 1102 | int offset, int len, int odd, struct sk_buff *skb), |
1110 | void *from, int length, int transhdrlen, | 1103 | void *from, int length, int transhdrlen, |
1111 | int hlimit, int tclass, struct ipv6_txoptions *opt, struct flowi *fl, | 1104 | int hlimit, int tclass, struct ipv6_txoptions *opt, struct flowi *fl, |
1112 | struct rt6_info *rt, unsigned int flags) | 1105 | struct rt6_info *rt, unsigned int flags, int dontfrag) |
1113 | { | 1106 | { |
1114 | struct inet_sock *inet = inet_sk(sk); | 1107 | struct inet_sock *inet = inet_sk(sk); |
1115 | struct ipv6_pinfo *np = inet6_sk(sk); | 1108 | struct ipv6_pinfo *np = inet6_sk(sk); |
@@ -1223,15 +1216,23 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1223 | */ | 1216 | */ |
1224 | 1217 | ||
1225 | inet->cork.length += length; | 1218 | inet->cork.length += length; |
1226 | if (((length > mtu) && (sk->sk_protocol == IPPROTO_UDP)) && | 1219 | if (length > mtu) { |
1227 | (rt->u.dst.dev->features & NETIF_F_UFO)) { | 1220 | int proto = sk->sk_protocol; |
1221 | if (dontfrag && (proto == IPPROTO_UDP || proto == IPPROTO_RAW)){ | ||
1222 | ipv6_local_rxpmtu(sk, fl, mtu-exthdrlen); | ||
1223 | return -EMSGSIZE; | ||
1224 | } | ||
1228 | 1225 | ||
1229 | err = ip6_ufo_append_data(sk, getfrag, from, length, hh_len, | 1226 | if (proto == IPPROTO_UDP && |
1230 | fragheaderlen, transhdrlen, mtu, | 1227 | (rt->u.dst.dev->features & NETIF_F_UFO)) { |
1231 | flags); | 1228 | |
1232 | if (err) | 1229 | err = ip6_ufo_append_data(sk, getfrag, from, length, |
1233 | goto error; | 1230 | hh_len, fragheaderlen, |
1234 | return 0; | 1231 | transhdrlen, mtu, flags); |
1232 | if (err) | ||
1233 | goto error; | ||
1234 | return 0; | ||
1235 | } | ||
1235 | } | 1236 | } |
1236 | 1237 | ||
1237 | if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL) | 1238 | if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL) |