ip6_output.c (80901bff812984624918d9d03f9286e3245ee9a5) | ip6_output.c (5e34af4142ffe68f01c8a9acae83300f8911e20c) |
---|---|
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 * --- 116 unchanged lines hidden (view full) --- 125 sock_confirm_neigh(skb, neigh); 126 ret = neigh_output(neigh, skb, false); 127 rcu_read_unlock_bh(); 128 return ret; 129 } 130 rcu_read_unlock_bh(); 131 132 IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTNOROUTES); | 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 * --- 116 unchanged lines hidden (view full) --- 125 sock_confirm_neigh(skb, neigh); 126 ret = neigh_output(neigh, skb, false); 127 rcu_read_unlock_bh(); 128 return ret; 129 } 130 rcu_read_unlock_bh(); 131 132 IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTNOROUTES); |
133 kfree_skb_reason(skb, SKB_DROP_REASON_NEIGH_CREATEFAIL); | 133 kfree_skb(skb); |
134 return -EINVAL; 135} 136 137static int 138ip6_finish_output_gso_slowpath_drop(struct net *net, struct sock *sk, 139 struct sk_buff *skb, unsigned int mtu) 140{ 141 struct sk_buff *segs, *nskb; --- 55 unchanged lines hidden (view full) --- 197 198 ret = BPF_CGROUP_RUN_PROG_INET_EGRESS(sk, skb); 199 switch (ret) { 200 case NET_XMIT_SUCCESS: 201 return __ip6_finish_output(net, sk, skb); 202 case NET_XMIT_CN: 203 return __ip6_finish_output(net, sk, skb) ? : ret; 204 default: | 134 return -EINVAL; 135} 136 137static int 138ip6_finish_output_gso_slowpath_drop(struct net *net, struct sock *sk, 139 struct sk_buff *skb, unsigned int mtu) 140{ 141 struct sk_buff *segs, *nskb; --- 55 unchanged lines hidden (view full) --- 197 198 ret = BPF_CGROUP_RUN_PROG_INET_EGRESS(sk, skb); 199 switch (ret) { 200 case NET_XMIT_SUCCESS: 201 return __ip6_finish_output(net, sk, skb); 202 case NET_XMIT_CN: 203 return __ip6_finish_output(net, sk, skb) ? : ret; 204 default: |
205 kfree_skb_reason(skb, SKB_DROP_REASON_BPF_CGROUP_EGRESS); | 205 kfree_skb(skb); |
206 return ret; 207 } 208} 209 210int ip6_output(struct net *net, struct sock *sk, struct sk_buff *skb) 211{ 212 struct net_device *dev = skb_dst(skb)->dev, *indev = skb->dev; 213 struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb)); 214 215 skb->protocol = htons(ETH_P_IPV6); 216 skb->dev = dev; 217 218 if (unlikely(idev->cnf.disable_ipv6)) { 219 IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS); | 206 return ret; 207 } 208} 209 210int ip6_output(struct net *net, struct sock *sk, struct sk_buff *skb) 211{ 212 struct net_device *dev = skb_dst(skb)->dev, *indev = skb->dev; 213 struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb)); 214 215 skb->protocol = htons(ETH_P_IPV6); 216 skb->dev = dev; 217 218 if (unlikely(idev->cnf.disable_ipv6)) { 219 IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS); |
220 kfree_skb_reason(skb, SKB_DROP_REASON_IPV6DISABLED); | 220 kfree_skb(skb); |
221 return 0; 222 } 223 224 return NF_HOOK_COND(NFPROTO_IPV6, NF_INET_POST_ROUTING, 225 net, sk, skb, indev, dev, 226 ip6_finish_output, 227 !(IP6CB(skb)->flags & IP6SKB_REROUTED)); 228} --- 206 unchanged lines hidden (view full) --- 435 436#ifdef CONFIG_NET_SWITCHDEV 437 if (skb->offload_l3_fwd_mark) { 438 consume_skb(skb); 439 return 0; 440 } 441#endif 442 | 221 return 0; 222 } 223 224 return NF_HOOK_COND(NFPROTO_IPV6, NF_INET_POST_ROUTING, 225 net, sk, skb, indev, dev, 226 ip6_finish_output, 227 !(IP6CB(skb)->flags & IP6SKB_REROUTED)); 228} --- 206 unchanged lines hidden (view full) --- 435 436#ifdef CONFIG_NET_SWITCHDEV 437 if (skb->offload_l3_fwd_mark) { 438 consume_skb(skb); 439 return 0; 440 } 441#endif 442 |
443 skb_clear_tstamp(skb); | 443 skb->tstamp = 0; |
444 return dst_output(net, sk, skb); 445} 446 447static bool ip6_pkt_too_big(const struct sk_buff *skb, unsigned int mtu) 448{ 449 if (skb->len <= mtu) 450 return false; 451 --- 356 unchanged lines hidden (view full) --- 808 809int ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, 810 int (*output)(struct net *, struct sock *, struct sk_buff *)) 811{ 812 struct sk_buff *frag; 813 struct rt6_info *rt = (struct rt6_info *)skb_dst(skb); 814 struct ipv6_pinfo *np = skb->sk && !dev_recursion_level() ? 815 inet6_sk(skb->sk) : NULL; | 444 return dst_output(net, sk, skb); 445} 446 447static bool ip6_pkt_too_big(const struct sk_buff *skb, unsigned int mtu) 448{ 449 if (skb->len <= mtu) 450 return false; 451 --- 356 unchanged lines hidden (view full) --- 808 809int ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, 810 int (*output)(struct net *, struct sock *, struct sk_buff *)) 811{ 812 struct sk_buff *frag; 813 struct rt6_info *rt = (struct rt6_info *)skb_dst(skb); 814 struct ipv6_pinfo *np = skb->sk && !dev_recursion_level() ? 815 inet6_sk(skb->sk) : NULL; |
816 bool mono_delivery_time = skb->mono_delivery_time; | |
817 struct ip6_frag_state state; 818 unsigned int mtu, hlen, nexthdr_offset; 819 ktime_t tstamp = skb->tstamp; 820 int hroom, err = 0; 821 __be32 frag_id; 822 u8 *prevhdr, nexthdr = 0; 823 824 err = ip6_find_1stfragopt(skb, &prevhdr); --- 74 unchanged lines hidden (view full) --- 899 goto fail; 900 901 for (;;) { 902 /* Prepare header of the next frame, 903 * before previous one went down. */ 904 if (iter.frag) 905 ip6_fraglist_prepare(skb, &iter); 906 | 816 struct ip6_frag_state state; 817 unsigned int mtu, hlen, nexthdr_offset; 818 ktime_t tstamp = skb->tstamp; 819 int hroom, err = 0; 820 __be32 frag_id; 821 u8 *prevhdr, nexthdr = 0; 822 823 err = ip6_find_1stfragopt(skb, &prevhdr); --- 74 unchanged lines hidden (view full) --- 898 goto fail; 899 900 for (;;) { 901 /* Prepare header of the next frame, 902 * before previous one went down. */ 903 if (iter.frag) 904 ip6_fraglist_prepare(skb, &iter); 905 |
907 skb_set_delivery_time(skb, tstamp, mono_delivery_time); | 906 skb->tstamp = tstamp; |
908 err = output(net, sk, skb); 909 if (!err) 910 IP6_INC_STATS(net, ip6_dst_idev(&rt->dst), 911 IPSTATS_MIB_FRAGCREATES); 912 913 if (err || !iter.frag) 914 break; 915 --- 42 unchanged lines hidden (view full) --- 958 if (IS_ERR(frag)) { 959 err = PTR_ERR(frag); 960 goto fail; 961 } 962 963 /* 964 * Put this fragment into the sending queue. 965 */ | 907 err = output(net, sk, skb); 908 if (!err) 909 IP6_INC_STATS(net, ip6_dst_idev(&rt->dst), 910 IPSTATS_MIB_FRAGCREATES); 911 912 if (err || !iter.frag) 913 break; 914 --- 42 unchanged lines hidden (view full) --- 957 if (IS_ERR(frag)) { 958 err = PTR_ERR(frag); 959 goto fail; 960 } 961 962 /* 963 * Put this fragment into the sending queue. 964 */ |
966 skb_set_delivery_time(frag, tstamp, mono_delivery_time); | 965 frag->tstamp = tstamp; |
967 err = output(net, sk, frag); 968 if (err) 969 goto fail; 970 971 IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), 972 IPSTATS_MIB_FRAGCREATES); 973 } 974 IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), --- 371 unchanged lines hidden (view full) --- 1346 } 1347 *maxfraglen = ((*mtu - fragheaderlen) & ~7) 1348 + fragheaderlen - sizeof(struct frag_hdr); 1349 } 1350} 1351 1352static int ip6_setup_cork(struct sock *sk, struct inet_cork_full *cork, 1353 struct inet6_cork *v6_cork, struct ipcm6_cookie *ipc6, | 966 err = output(net, sk, frag); 967 if (err) 968 goto fail; 969 970 IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), 971 IPSTATS_MIB_FRAGCREATES); 972 } 973 IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), --- 371 unchanged lines hidden (view full) --- 1345 } 1346 *maxfraglen = ((*mtu - fragheaderlen) & ~7) 1347 + fragheaderlen - sizeof(struct frag_hdr); 1348 } 1349} 1350 1351static int ip6_setup_cork(struct sock *sk, struct inet_cork_full *cork, 1352 struct inet6_cork *v6_cork, struct ipcm6_cookie *ipc6, |
1354 struct rt6_info *rt) | 1353 struct rt6_info *rt, struct flowi6 *fl6) |
1355{ 1356 struct ipv6_pinfo *np = inet6_sk(sk); 1357 unsigned int mtu; | 1354{ 1355 struct ipv6_pinfo *np = inet6_sk(sk); 1356 unsigned int mtu; |
1358 struct ipv6_txoptions *nopt, *opt = ipc6->opt; | 1357 struct ipv6_txoptions *opt = ipc6->opt; |
1359 | 1358 |
1360 /* callers pass dst together with a reference, set it first so 1361 * ip6_cork_release() can put it down even in case of an error. 1362 */ 1363 cork->base.dst = &rt->dst; 1364 | |
1365 /* 1366 * setup for corking 1367 */ 1368 if (opt) { 1369 if (WARN_ON(v6_cork->opt)) 1370 return -EINVAL; 1371 | 1359 /* 1360 * setup for corking 1361 */ 1362 if (opt) { 1363 if (WARN_ON(v6_cork->opt)) 1364 return -EINVAL; 1365 |
1372 nopt = v6_cork->opt = kzalloc(sizeof(*opt), sk->sk_allocation); 1373 if (unlikely(!nopt)) | 1366 v6_cork->opt = kzalloc(sizeof(*opt), sk->sk_allocation); 1367 if (unlikely(!v6_cork->opt)) |
1374 return -ENOBUFS; 1375 | 1368 return -ENOBUFS; 1369 |
1376 nopt->tot_len = sizeof(*opt); 1377 nopt->opt_flen = opt->opt_flen; 1378 nopt->opt_nflen = opt->opt_nflen; | 1370 v6_cork->opt->tot_len = sizeof(*opt); 1371 v6_cork->opt->opt_flen = opt->opt_flen; 1372 v6_cork->opt->opt_nflen = opt->opt_nflen; |
1379 | 1373 |
1380 nopt->dst0opt = ip6_opt_dup(opt->dst0opt, sk->sk_allocation); 1381 if (opt->dst0opt && !nopt->dst0opt) | 1374 v6_cork->opt->dst0opt = ip6_opt_dup(opt->dst0opt, 1375 sk->sk_allocation); 1376 if (opt->dst0opt && !v6_cork->opt->dst0opt) |
1382 return -ENOBUFS; 1383 | 1377 return -ENOBUFS; 1378 |
1384 nopt->dst1opt = ip6_opt_dup(opt->dst1opt, sk->sk_allocation); 1385 if (opt->dst1opt && !nopt->dst1opt) | 1379 v6_cork->opt->dst1opt = ip6_opt_dup(opt->dst1opt, 1380 sk->sk_allocation); 1381 if (opt->dst1opt && !v6_cork->opt->dst1opt) |
1386 return -ENOBUFS; 1387 | 1382 return -ENOBUFS; 1383 |
1388 nopt->hopopt = ip6_opt_dup(opt->hopopt, sk->sk_allocation); 1389 if (opt->hopopt && !nopt->hopopt) | 1384 v6_cork->opt->hopopt = ip6_opt_dup(opt->hopopt, 1385 sk->sk_allocation); 1386 if (opt->hopopt && !v6_cork->opt->hopopt) |
1390 return -ENOBUFS; 1391 | 1387 return -ENOBUFS; 1388 |
1392 nopt->srcrt = ip6_rthdr_dup(opt->srcrt, sk->sk_allocation); 1393 if (opt->srcrt && !nopt->srcrt) | 1389 v6_cork->opt->srcrt = ip6_rthdr_dup(opt->srcrt, 1390 sk->sk_allocation); 1391 if (opt->srcrt && !v6_cork->opt->srcrt) |
1394 return -ENOBUFS; 1395 1396 /* need source address above miyazawa*/ 1397 } | 1392 return -ENOBUFS; 1393 1394 /* need source address above miyazawa*/ 1395 } |
1396 dst_hold(&rt->dst); 1397 cork->base.dst = &rt->dst; 1398 cork->fl.u.ip6 = *fl6; |
|
1398 v6_cork->hop_limit = ipc6->hlimit; 1399 v6_cork->tclass = ipc6->tclass; 1400 if (rt->dst.flags & DST_XFRM_TUNNEL) 1401 mtu = np->pmtudisc >= IPV6_PMTUDISC_PROBE ? 1402 READ_ONCE(rt->dst.dev->mtu) : dst_mtu(&rt->dst); 1403 else 1404 mtu = np->pmtudisc >= IPV6_PMTUDISC_PROBE ? 1405 READ_ONCE(rt->dst.dev->mtu) : dst_mtu(xfrm_dst_path(&rt->dst)); --- 12 unchanged lines hidden (view full) --- 1418 cork->base.length = 0; 1419 1420 cork->base.transmit_time = ipc6->sockc.transmit_time; 1421 1422 return 0; 1423} 1424 1425static int __ip6_append_data(struct sock *sk, | 1399 v6_cork->hop_limit = ipc6->hlimit; 1400 v6_cork->tclass = ipc6->tclass; 1401 if (rt->dst.flags & DST_XFRM_TUNNEL) 1402 mtu = np->pmtudisc >= IPV6_PMTUDISC_PROBE ? 1403 READ_ONCE(rt->dst.dev->mtu) : dst_mtu(&rt->dst); 1404 else 1405 mtu = np->pmtudisc >= IPV6_PMTUDISC_PROBE ? 1406 READ_ONCE(rt->dst.dev->mtu) : dst_mtu(xfrm_dst_path(&rt->dst)); --- 12 unchanged lines hidden (view full) --- 1419 cork->base.length = 0; 1420 1421 cork->base.transmit_time = ipc6->sockc.transmit_time; 1422 1423 return 0; 1424} 1425 1426static int __ip6_append_data(struct sock *sk, |
1427 struct flowi6 *fl6, |
|
1426 struct sk_buff_head *queue, | 1428 struct sk_buff_head *queue, |
1427 struct inet_cork_full *cork_full, | 1429 struct inet_cork *cork, |
1428 struct inet6_cork *v6_cork, 1429 struct page_frag *pfrag, 1430 int getfrag(void *from, char *to, int offset, 1431 int len, int odd, struct sk_buff *skb), 1432 void *from, int length, int transhdrlen, 1433 unsigned int flags, struct ipcm6_cookie *ipc6) 1434{ 1435 struct sk_buff *skb, *skb_prev = NULL; | 1430 struct inet6_cork *v6_cork, 1431 struct page_frag *pfrag, 1432 int getfrag(void *from, char *to, int offset, 1433 int len, int odd, struct sk_buff *skb), 1434 void *from, int length, int transhdrlen, 1435 unsigned int flags, struct ipcm6_cookie *ipc6) 1436{ 1437 struct sk_buff *skb, *skb_prev = NULL; |
1436 struct inet_cork *cork = &cork_full->base; 1437 struct flowi6 *fl6 = &cork_full->fl.u.ip6; | |
1438 unsigned int maxfraglen, fragheaderlen, mtu, orig_mtu, pmtu; 1439 struct ubuf_info *uarg = NULL; 1440 int exthdrlen = 0; 1441 int dst_exthdrlen = 0; 1442 int hh_len; 1443 int copy; 1444 int err; 1445 int offset = 0; --- 25 unchanged lines hidden (view full) --- 1471 (opt ? opt->opt_nflen : 0); 1472 1473 headersize = sizeof(struct ipv6hdr) + 1474 (opt ? opt->opt_flen + opt->opt_nflen : 0) + 1475 (dst_allfrag(&rt->dst) ? 1476 sizeof(struct frag_hdr) : 0) + 1477 rt->rt6i_nfheader_len; 1478 | 1438 unsigned int maxfraglen, fragheaderlen, mtu, orig_mtu, pmtu; 1439 struct ubuf_info *uarg = NULL; 1440 int exthdrlen = 0; 1441 int dst_exthdrlen = 0; 1442 int hh_len; 1443 int copy; 1444 int err; 1445 int offset = 0; --- 25 unchanged lines hidden (view full) --- 1471 (opt ? opt->opt_nflen : 0); 1472 1473 headersize = sizeof(struct ipv6hdr) + 1474 (opt ? opt->opt_flen + opt->opt_nflen : 0) + 1475 (dst_allfrag(&rt->dst) ? 1476 sizeof(struct frag_hdr) : 0) + 1477 rt->rt6i_nfheader_len; 1478 |
1479 if (mtu < fragheaderlen || 1480 ((mtu - fragheaderlen) & ~7) + fragheaderlen < sizeof(struct frag_hdr)) | 1479 if (mtu <= fragheaderlen || 1480 ((mtu - fragheaderlen) & ~7) + fragheaderlen <= sizeof(struct frag_hdr)) |
1481 goto emsgsize; 1482 1483 maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen - 1484 sizeof(struct frag_hdr); 1485 1486 /* as per RFC 7112 section 5, the entire IPv6 Header Chain must fit 1487 * the first fragment 1488 */ 1489 if (headersize + transhdrlen > mtu) 1490 goto emsgsize; 1491 1492 if (cork->length + length > mtu - headersize && ipc6->dontfrag && 1493 (sk->sk_protocol == IPPROTO_UDP || | 1481 goto emsgsize; 1482 1483 maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen - 1484 sizeof(struct frag_hdr); 1485 1486 /* as per RFC 7112 section 5, the entire IPv6 Header Chain must fit 1487 * the first fragment 1488 */ 1489 if (headersize + transhdrlen > mtu) 1490 goto emsgsize; 1491 1492 if (cork->length + length > mtu - headersize && ipc6->dontfrag && 1493 (sk->sk_protocol == IPPROTO_UDP || |
1494 sk->sk_protocol == IPPROTO_ICMPV6 || | |
1495 sk->sk_protocol == IPPROTO_RAW)) { 1496 ipv6_local_rxpmtu(sk, fl6, mtu - headersize + 1497 sizeof(struct ipv6hdr)); 1498 goto emsgsize; 1499 } 1500 1501 if (ip6_sk_ignore_df(sk)) 1502 maxnonfragsize = sizeof(struct ipv6hdr) + IPV6_MAXPLEN; --- 284 unchanged lines hidden (view full) --- 1787 int err; 1788 1789 if (flags&MSG_PROBE) 1790 return 0; 1791 if (skb_queue_empty(&sk->sk_write_queue)) { 1792 /* 1793 * setup for corking 1794 */ | 1494 sk->sk_protocol == IPPROTO_RAW)) { 1495 ipv6_local_rxpmtu(sk, fl6, mtu - headersize + 1496 sizeof(struct ipv6hdr)); 1497 goto emsgsize; 1498 } 1499 1500 if (ip6_sk_ignore_df(sk)) 1501 maxnonfragsize = sizeof(struct ipv6hdr) + IPV6_MAXPLEN; --- 284 unchanged lines hidden (view full) --- 1786 int err; 1787 1788 if (flags&MSG_PROBE) 1789 return 0; 1790 if (skb_queue_empty(&sk->sk_write_queue)) { 1791 /* 1792 * setup for corking 1793 */ |
1795 dst_hold(&rt->dst); | |
1796 err = ip6_setup_cork(sk, &inet->cork, &np->cork, | 1794 err = ip6_setup_cork(sk, &inet->cork, &np->cork, |
1797 ipc6, rt); | 1795 ipc6, rt, fl6); |
1798 if (err) 1799 return err; 1800 | 1796 if (err) 1797 return err; 1798 |
1801 inet->cork.fl.u.ip6 = *fl6; | |
1802 exthdrlen = (ipc6->opt ? ipc6->opt->opt_flen : 0); 1803 length += exthdrlen; 1804 transhdrlen += exthdrlen; 1805 } else { | 1799 exthdrlen = (ipc6->opt ? ipc6->opt->opt_flen : 0); 1800 length += exthdrlen; 1801 transhdrlen += exthdrlen; 1802 } else { |
1803 fl6 = &inet->cork.fl.u.ip6; |
|
1806 transhdrlen = 0; 1807 } 1808 | 1804 transhdrlen = 0; 1805 } 1806 |
1809 return __ip6_append_data(sk, &sk->sk_write_queue, &inet->cork, | 1807 return __ip6_append_data(sk, fl6, &sk->sk_write_queue, &inet->cork.base, |
1810 &np->cork, sk_page_frag(sk), getfrag, 1811 from, length, transhdrlen, flags, ipc6); 1812} 1813EXPORT_SYMBOL_GPL(ip6_append_data); 1814 | 1808 &np->cork, sk_page_frag(sk), getfrag, 1809 from, length, transhdrlen, flags, ipc6); 1810} 1811EXPORT_SYMBOL_GPL(ip6_append_data); 1812 |
1815static void ip6_cork_steal_dst(struct sk_buff *skb, struct inet_cork_full *cork) 1816{ 1817 struct dst_entry *dst = cork->base.dst; 1818 1819 cork->base.dst = NULL; 1820 cork->base.flags &= ~IPCORK_ALLFRAG; 1821 skb_dst_set(skb, dst); 1822} 1823 | |
1824static void ip6_cork_release(struct inet_cork_full *cork, 1825 struct inet6_cork *v6_cork) 1826{ 1827 if (v6_cork->opt) { | 1813static void ip6_cork_release(struct inet_cork_full *cork, 1814 struct inet6_cork *v6_cork) 1815{ 1816 if (v6_cork->opt) { |
1828 struct ipv6_txoptions *opt = v6_cork->opt; 1829 1830 kfree(opt->dst0opt); 1831 kfree(opt->dst1opt); 1832 kfree(opt->hopopt); 1833 kfree(opt->srcrt); 1834 kfree(opt); | 1817 kfree(v6_cork->opt->dst0opt); 1818 kfree(v6_cork->opt->dst1opt); 1819 kfree(v6_cork->opt->hopopt); 1820 kfree(v6_cork->opt->srcrt); 1821 kfree(v6_cork->opt); |
1835 v6_cork->opt = NULL; 1836 } 1837 1838 if (cork->base.dst) { 1839 dst_release(cork->base.dst); 1840 cork->base.dst = NULL; 1841 cork->base.flags &= ~IPCORK_ALLFRAG; 1842 } | 1822 v6_cork->opt = NULL; 1823 } 1824 1825 if (cork->base.dst) { 1826 dst_release(cork->base.dst); 1827 cork->base.dst = NULL; 1828 cork->base.flags &= ~IPCORK_ALLFRAG; 1829 } |
1830 memset(&cork->fl, 0, sizeof(cork->fl)); |
|
1843} 1844 1845struct sk_buff *__ip6_make_skb(struct sock *sk, 1846 struct sk_buff_head *queue, 1847 struct inet_cork_full *cork, 1848 struct inet6_cork *v6_cork) 1849{ 1850 struct sk_buff *skb, *tmp_skb; 1851 struct sk_buff **tail_skb; | 1831} 1832 1833struct sk_buff *__ip6_make_skb(struct sock *sk, 1834 struct sk_buff_head *queue, 1835 struct inet_cork_full *cork, 1836 struct inet6_cork *v6_cork) 1837{ 1838 struct sk_buff *skb, *tmp_skb; 1839 struct sk_buff **tail_skb; |
1852 struct in6_addr *final_dst; | 1840 struct in6_addr final_dst_buf, *final_dst = &final_dst_buf; |
1853 struct ipv6_pinfo *np = inet6_sk(sk); 1854 struct net *net = sock_net(sk); 1855 struct ipv6hdr *hdr; 1856 struct ipv6_txoptions *opt = v6_cork->opt; 1857 struct rt6_info *rt = (struct rt6_info *)cork->base.dst; 1858 struct flowi6 *fl6 = &cork->fl.u.ip6; 1859 unsigned char proto = fl6->flowi6_proto; 1860 --- 13 unchanged lines hidden (view full) --- 1874 skb->data_len += tmp_skb->len; 1875 skb->truesize += tmp_skb->truesize; 1876 tmp_skb->destructor = NULL; 1877 tmp_skb->sk = NULL; 1878 } 1879 1880 /* Allow local fragmentation. */ 1881 skb->ignore_df = ip6_sk_ignore_df(sk); | 1841 struct ipv6_pinfo *np = inet6_sk(sk); 1842 struct net *net = sock_net(sk); 1843 struct ipv6hdr *hdr; 1844 struct ipv6_txoptions *opt = v6_cork->opt; 1845 struct rt6_info *rt = (struct rt6_info *)cork->base.dst; 1846 struct flowi6 *fl6 = &cork->fl.u.ip6; 1847 unsigned char proto = fl6->flowi6_proto; 1848 --- 13 unchanged lines hidden (view full) --- 1862 skb->data_len += tmp_skb->len; 1863 skb->truesize += tmp_skb->truesize; 1864 tmp_skb->destructor = NULL; 1865 tmp_skb->sk = NULL; 1866 } 1867 1868 /* Allow local fragmentation. */ 1869 skb->ignore_df = ip6_sk_ignore_df(sk); |
1882 __skb_pull(skb, skb_network_header_len(skb)); | |
1883 | 1870 |
1884 final_dst = &fl6->daddr; | 1871 *final_dst = fl6->daddr; 1872 __skb_pull(skb, skb_network_header_len(skb)); |
1885 if (opt && opt->opt_flen) 1886 ipv6_push_frag_opts(skb, opt, &proto); 1887 if (opt && opt->opt_nflen) 1888 ipv6_push_nfrag_opts(skb, opt, &proto, &final_dst, &fl6->saddr); 1889 1890 skb_push(skb, sizeof(struct ipv6hdr)); 1891 skb_reset_network_header(skb); 1892 hdr = ipv6_hdr(skb); 1893 1894 ip6_flow_hdr(hdr, v6_cork->tclass, 1895 ip6_make_flowlabel(net, skb, fl6->flowlabel, 1896 ip6_autoflowlabel(net, np), fl6)); 1897 hdr->hop_limit = v6_cork->hop_limit; 1898 hdr->nexthdr = proto; 1899 hdr->saddr = fl6->saddr; 1900 hdr->daddr = *final_dst; 1901 1902 skb->priority = sk->sk_priority; 1903 skb->mark = cork->base.mark; | 1873 if (opt && opt->opt_flen) 1874 ipv6_push_frag_opts(skb, opt, &proto); 1875 if (opt && opt->opt_nflen) 1876 ipv6_push_nfrag_opts(skb, opt, &proto, &final_dst, &fl6->saddr); 1877 1878 skb_push(skb, sizeof(struct ipv6hdr)); 1879 skb_reset_network_header(skb); 1880 hdr = ipv6_hdr(skb); 1881 1882 ip6_flow_hdr(hdr, v6_cork->tclass, 1883 ip6_make_flowlabel(net, skb, fl6->flowlabel, 1884 ip6_autoflowlabel(net, np), fl6)); 1885 hdr->hop_limit = v6_cork->hop_limit; 1886 hdr->nexthdr = proto; 1887 hdr->saddr = fl6->saddr; 1888 hdr->daddr = *final_dst; 1889 1890 skb->priority = sk->sk_priority; 1891 skb->mark = cork->base.mark; |
1892 |
|
1904 skb->tstamp = cork->base.transmit_time; 1905 | 1893 skb->tstamp = cork->base.transmit_time; 1894 |
1906 ip6_cork_steal_dst(skb, cork); | 1895 skb_dst_set(skb, dst_clone(&rt->dst)); |
1907 IP6_UPD_PO_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUT, skb->len); 1908 if (proto == IPPROTO_ICMPV6) { 1909 struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb)); 1910 1911 ICMP6MSGOUT_INC_STATS(net, idev, icmp6_hdr(skb)->icmp6_type); 1912 ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS); 1913 } 1914 --- 55 unchanged lines hidden (view full) --- 1970 &inet_sk(sk)->cork, &inet6_sk(sk)->cork); 1971} 1972EXPORT_SYMBOL_GPL(ip6_flush_pending_frames); 1973 1974struct sk_buff *ip6_make_skb(struct sock *sk, 1975 int getfrag(void *from, char *to, int offset, 1976 int len, int odd, struct sk_buff *skb), 1977 void *from, int length, int transhdrlen, | 1896 IP6_UPD_PO_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUT, skb->len); 1897 if (proto == IPPROTO_ICMPV6) { 1898 struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb)); 1899 1900 ICMP6MSGOUT_INC_STATS(net, idev, icmp6_hdr(skb)->icmp6_type); 1901 ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS); 1902 } 1903 --- 55 unchanged lines hidden (view full) --- 1959 &inet_sk(sk)->cork, &inet6_sk(sk)->cork); 1960} 1961EXPORT_SYMBOL_GPL(ip6_flush_pending_frames); 1962 1963struct sk_buff *ip6_make_skb(struct sock *sk, 1964 int getfrag(void *from, char *to, int offset, 1965 int len, int odd, struct sk_buff *skb), 1966 void *from, int length, int transhdrlen, |
1978 struct ipcm6_cookie *ipc6, struct rt6_info *rt, 1979 unsigned int flags, struct inet_cork_full *cork) | 1967 struct ipcm6_cookie *ipc6, struct flowi6 *fl6, 1968 struct rt6_info *rt, unsigned int flags, 1969 struct inet_cork_full *cork) |
1980{ 1981 struct inet6_cork v6_cork; 1982 struct sk_buff_head queue; 1983 int exthdrlen = (ipc6->opt ? ipc6->opt->opt_flen : 0); 1984 int err; 1985 | 1970{ 1971 struct inet6_cork v6_cork; 1972 struct sk_buff_head queue; 1973 int exthdrlen = (ipc6->opt ? ipc6->opt->opt_flen : 0); 1974 int err; 1975 |
1986 if (flags & MSG_PROBE) { 1987 dst_release(&rt->dst); | 1976 if (flags & MSG_PROBE) |
1988 return NULL; | 1977 return NULL; |
1989 } | |
1990 1991 __skb_queue_head_init(&queue); 1992 1993 cork->base.flags = 0; 1994 cork->base.addr = 0; 1995 cork->base.opt = NULL; | 1978 1979 __skb_queue_head_init(&queue); 1980 1981 cork->base.flags = 0; 1982 cork->base.addr = 0; 1983 cork->base.opt = NULL; |
1984 cork->base.dst = NULL; |
|
1996 v6_cork.opt = NULL; | 1985 v6_cork.opt = NULL; |
1997 err = ip6_setup_cork(sk, cork, &v6_cork, ipc6, rt); | 1986 err = ip6_setup_cork(sk, cork, &v6_cork, ipc6, rt, fl6); |
1998 if (err) { 1999 ip6_cork_release(cork, &v6_cork); 2000 return ERR_PTR(err); 2001 } 2002 if (ipc6->dontfrag < 0) 2003 ipc6->dontfrag = inet6_sk(sk)->dontfrag; 2004 | 1987 if (err) { 1988 ip6_cork_release(cork, &v6_cork); 1989 return ERR_PTR(err); 1990 } 1991 if (ipc6->dontfrag < 0) 1992 ipc6->dontfrag = inet6_sk(sk)->dontfrag; 1993 |
2005 err = __ip6_append_data(sk, &queue, cork, &v6_cork, | 1994 err = __ip6_append_data(sk, fl6, &queue, &cork->base, &v6_cork, |
2006 ¤t->task_frag, getfrag, from, 2007 length + exthdrlen, transhdrlen + exthdrlen, 2008 flags, ipc6); 2009 if (err) { 2010 __ip6_flush_pending_frames(sk, &queue, cork, &v6_cork); 2011 return ERR_PTR(err); 2012 } 2013 2014 return __ip6_make_skb(sk, &queue, cork, &v6_cork); 2015} | 1995 ¤t->task_frag, getfrag, from, 1996 length + exthdrlen, transhdrlen + exthdrlen, 1997 flags, ipc6); 1998 if (err) { 1999 __ip6_flush_pending_frames(sk, &queue, cork, &v6_cork); 2000 return ERR_PTR(err); 2001 } 2002 2003 return __ip6_make_skb(sk, &queue, cork, &v6_cork); 2004} |