aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/ip6_output.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/ip6_output.c')
-rw-r--r--net/ipv6/ip6_output.c81
1 files changed, 31 insertions, 50 deletions
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 5552d13ae92f..155eccfa7760 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -56,8 +56,6 @@
56#include <net/checksum.h> 56#include <net/checksum.h>
57#include <linux/mroute6.h> 57#include <linux/mroute6.h>
58 58
59int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *));
60
61int __ip6_local_out(struct sk_buff *skb) 59int __ip6_local_out(struct sk_buff *skb)
62{ 60{
63 int len; 61 int len;
@@ -88,7 +86,8 @@ static int ip6_finish_output2(struct sk_buff *skb)
88 struct dst_entry *dst = skb_dst(skb); 86 struct dst_entry *dst = skb_dst(skb);
89 struct net_device *dev = dst->dev; 87 struct net_device *dev = dst->dev;
90 struct neighbour *neigh; 88 struct neighbour *neigh;
91 struct rt6_info *rt; 89 struct in6_addr *nexthop;
90 int ret;
92 91
93 skb->protocol = htons(ETH_P_IPV6); 92 skb->protocol = htons(ETH_P_IPV6);
94 skb->dev = dev; 93 skb->dev = dev;
@@ -121,12 +120,26 @@ static int ip6_finish_output2(struct sk_buff *skb)
121 120
122 IP6_UPD_PO_STATS(dev_net(dev), idev, IPSTATS_MIB_OUTMCAST, 121 IP6_UPD_PO_STATS(dev_net(dev), idev, IPSTATS_MIB_OUTMCAST,
123 skb->len); 122 skb->len);
123
124 if (IPV6_ADDR_MC_SCOPE(&ipv6_hdr(skb)->daddr) <=
125 IPV6_ADDR_SCOPE_NODELOCAL &&
126 !(dev->flags & IFF_LOOPBACK)) {
127 kfree_skb(skb);
128 return 0;
129 }
124 } 130 }
125 131
126 rt = (struct rt6_info *) dst; 132 rcu_read_lock_bh();
127 neigh = rt->n; 133 nexthop = rt6_nexthop((struct rt6_info *)dst, &ipv6_hdr(skb)->daddr);
128 if (neigh) 134 neigh = __ipv6_neigh_lookup_noref(dst->dev, nexthop);
129 return dst_neigh_output(dst, neigh, skb); 135 if (unlikely(!neigh))
136 neigh = __neigh_create(&nd_tbl, nexthop, dst->dev, false);
137 if (!IS_ERR(neigh)) {
138 ret = dst_neigh_output(dst, neigh, skb);
139 rcu_read_unlock_bh();
140 return ret;
141 }
142 rcu_read_unlock_bh();
130 143
131 IP6_INC_STATS_BH(dev_net(dst->dev), 144 IP6_INC_STATS_BH(dev_net(dst->dev),
132 ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES); 145 ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES);
@@ -216,7 +229,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6,
216 if (hlimit < 0) 229 if (hlimit < 0)
217 hlimit = ip6_dst_hoplimit(dst); 230 hlimit = ip6_dst_hoplimit(dst);
218 231
219 *(__be32 *)hdr = htonl(0x60000000 | (tclass << 20)) | fl6->flowlabel; 232 ip6_flow_hdr(hdr, tclass, fl6->flowlabel);
220 233
221 hdr->payload_len = htons(seg_len); 234 hdr->payload_len = htons(seg_len);
222 hdr->nexthdr = proto; 235 hdr->nexthdr = proto;
@@ -236,9 +249,8 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6,
236 dst->dev, dst_output); 249 dst->dev, dst_output);
237 } 250 }
238 251
239 net_dbg_ratelimited("IPv6: sending pkt_too_big to self\n");
240 skb->dev = dst->dev; 252 skb->dev = dst->dev;
241 icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); 253 ipv6_local_error(sk, EMSGSIZE, fl6, mtu);
242 IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_FRAGFAILS); 254 IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_FRAGFAILS);
243 kfree_skb(skb); 255 kfree_skb(skb);
244 return -EMSGSIZE; 256 return -EMSGSIZE;
@@ -246,39 +258,6 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6,
246 258
247EXPORT_SYMBOL(ip6_xmit); 259EXPORT_SYMBOL(ip6_xmit);
248 260
249/*
250 * To avoid extra problems ND packets are send through this
251 * routine. It's code duplication but I really want to avoid
252 * extra checks since ipv6_build_header is used by TCP (which
253 * is for us performance critical)
254 */
255
256int ip6_nd_hdr(struct sock *sk, struct sk_buff *skb, struct net_device *dev,
257 const struct in6_addr *saddr, const struct in6_addr *daddr,
258 int proto, int len)
259{
260 struct ipv6_pinfo *np = inet6_sk(sk);
261 struct ipv6hdr *hdr;
262
263 skb->protocol = htons(ETH_P_IPV6);
264 skb->dev = dev;
265
266 skb_reset_network_header(skb);
267 skb_put(skb, sizeof(struct ipv6hdr));
268 hdr = ipv6_hdr(skb);
269
270 *(__be32*)hdr = htonl(0x60000000);
271
272 hdr->payload_len = htons(len);
273 hdr->nexthdr = proto;
274 hdr->hop_limit = np->hop_limit;
275
276 hdr->saddr = *saddr;
277 hdr->daddr = *daddr;
278
279 return 0;
280}
281
282static int ip6_call_ra_chain(struct sk_buff *skb, int sel) 261static int ip6_call_ra_chain(struct sk_buff *skb, int sel)
283{ 262{
284 struct ip6_ra_chain *ra; 263 struct ip6_ra_chain *ra;
@@ -913,8 +892,12 @@ static int ip6_dst_lookup_tail(struct sock *sk,
913 * dst entry of the nexthop router 892 * dst entry of the nexthop router
914 */ 893 */
915 rt = (struct rt6_info *) *dst; 894 rt = (struct rt6_info *) *dst;
916 n = rt->n; 895 rcu_read_lock_bh();
917 if (n && !(n->nud_state & NUD_VALID)) { 896 n = __ipv6_neigh_lookup_noref(rt->dst.dev, rt6_nexthop(rt, &fl6->daddr));
897 err = n && !(n->nud_state & NUD_VALID) ? -EINVAL : 0;
898 rcu_read_unlock_bh();
899
900 if (err) {
918 struct inet6_ifaddr *ifp; 901 struct inet6_ifaddr *ifp;
919 struct flowi6 fl_gw6; 902 struct flowi6 fl_gw6;
920 int redirect; 903 int redirect;
@@ -1213,10 +1196,10 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
1213 if (dst_allfrag(rt->dst.path)) 1196 if (dst_allfrag(rt->dst.path))
1214 cork->flags |= IPCORK_ALLFRAG; 1197 cork->flags |= IPCORK_ALLFRAG;
1215 cork->length = 0; 1198 cork->length = 0;
1216 exthdrlen = (opt ? opt->opt_flen : 0) - rt->rt6i_nfheader_len; 1199 exthdrlen = (opt ? opt->opt_flen : 0);
1217 length += exthdrlen; 1200 length += exthdrlen;
1218 transhdrlen += exthdrlen; 1201 transhdrlen += exthdrlen;
1219 dst_exthdrlen = rt->dst.header_len; 1202 dst_exthdrlen = rt->dst.header_len - rt->rt6i_nfheader_len;
1220 } else { 1203 } else {
1221 rt = (struct rt6_info *)cork->dst; 1204 rt = (struct rt6_info *)cork->dst;
1222 fl6 = &inet->cork.fl.u.ip6; 1205 fl6 = &inet->cork.fl.u.ip6;
@@ -1548,9 +1531,7 @@ int ip6_push_pending_frames(struct sock *sk)
1548 skb_reset_network_header(skb); 1531 skb_reset_network_header(skb);
1549 hdr = ipv6_hdr(skb); 1532 hdr = ipv6_hdr(skb);
1550 1533
1551 *(__be32*)hdr = fl6->flowlabel | 1534 ip6_flow_hdr(hdr, np->cork.tclass, fl6->flowlabel);
1552 htonl(0x60000000 | ((int)np->cork.tclass << 20));
1553
1554 hdr->hop_limit = np->cork.hop_limit; 1535 hdr->hop_limit = np->cork.hop_limit;
1555 hdr->nexthdr = proto; 1536 hdr->nexthdr = proto;
1556 hdr->saddr = fl6->saddr; 1537 hdr->saddr = fl6->saddr;