ip6_output.c (c5e77f5216abdd1d98e6d14d9a3eb4e88d80011a) | ip6_output.c (63159f29be1df7f93563a8a0f78c5e65fc844ed6) |
---|---|
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 --- 163 unchanged lines hidden (view full) --- 172 MAX_HEADER is not enough. 173 */ 174 head_room = opt->opt_nflen + opt->opt_flen; 175 seg_len += head_room; 176 head_room += sizeof(struct ipv6hdr) + LL_RESERVED_SPACE(dst->dev); 177 178 if (skb_headroom(skb) < head_room) { 179 struct sk_buff *skb2 = skb_realloc_headroom(skb, head_room); | 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 --- 163 unchanged lines hidden (view full) --- 172 MAX_HEADER is not enough. 173 */ 174 head_room = opt->opt_nflen + opt->opt_flen; 175 seg_len += head_room; 176 head_room += sizeof(struct ipv6hdr) + LL_RESERVED_SPACE(dst->dev); 177 178 if (skb_headroom(skb) < head_room) { 179 struct sk_buff *skb2 = skb_realloc_headroom(skb, head_room); |
180 if (skb2 == NULL) { | 180 if (!skb2) { |
181 IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), 182 IPSTATS_MIB_OUTDISCARDS); 183 kfree_skb(skb); 184 return -ENOBUFS; 185 } 186 consume_skb(skb); 187 skb = skb2; 188 skb_set_owner_w(skb, sk); --- 434 unchanged lines hidden (view full) --- 623 } 624 625 __skb_pull(skb, hlen); 626 fh = (struct frag_hdr *)__skb_push(skb, sizeof(struct frag_hdr)); 627 __skb_push(skb, hlen); 628 skb_reset_network_header(skb); 629 memcpy(skb_network_header(skb), tmp_hdr, hlen); 630 | 181 IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), 182 IPSTATS_MIB_OUTDISCARDS); 183 kfree_skb(skb); 184 return -ENOBUFS; 185 } 186 consume_skb(skb); 187 skb = skb2; 188 skb_set_owner_w(skb, sk); --- 434 unchanged lines hidden (view full) --- 623 } 624 625 __skb_pull(skb, hlen); 626 fh = (struct frag_hdr *)__skb_push(skb, sizeof(struct frag_hdr)); 627 __skb_push(skb, hlen); 628 skb_reset_network_header(skb); 629 memcpy(skb_network_header(skb), tmp_hdr, hlen); 630 |
631 ipv6_select_ident(fh, rt); | 631 ipv6_select_ident(net, fh, rt); |
632 fh->nexthdr = nexthdr; 633 fh->reserved = 0; 634 fh->frag_off = htons(IP6_MF); 635 frag_id = fh->identification; 636 637 first_len = skb_pagelen(skb); 638 skb->data_len = first_len - skb_headlen(skb); 639 skb->len = first_len; --- 130 unchanged lines hidden (view full) --- 770 skb_copy_from_linear_data(skb, skb_network_header(frag), hlen); 771 772 /* 773 * Build fragment header. 774 */ 775 fh->nexthdr = nexthdr; 776 fh->reserved = 0; 777 if (!frag_id) { | 632 fh->nexthdr = nexthdr; 633 fh->reserved = 0; 634 fh->frag_off = htons(IP6_MF); 635 frag_id = fh->identification; 636 637 first_len = skb_pagelen(skb); 638 skb->data_len = first_len - skb_headlen(skb); 639 skb->len = first_len; --- 130 unchanged lines hidden (view full) --- 770 skb_copy_from_linear_data(skb, skb_network_header(frag), hlen); 771 772 /* 773 * Build fragment header. 774 */ 775 fh->nexthdr = nexthdr; 776 fh->reserved = 0; 777 if (!frag_id) { |
778 ipv6_select_ident(fh, rt); | 778 ipv6_select_ident(net, fh, rt); |
779 frag_id = fh->identification; 780 } else 781 fh->identification = frag_id; 782 783 /* 784 * Copy a block of the IP datagram. 785 */ 786 BUG_ON(skb_copy_bits(skb, ptr, skb_transport_header(frag), --- 31 unchanged lines hidden (view full) --- 818 return err; 819} 820 821static inline int ip6_rt_check(const struct rt6key *rt_key, 822 const struct in6_addr *fl_addr, 823 const struct in6_addr *addr_cache) 824{ 825 return (rt_key->plen != 128 || !ipv6_addr_equal(fl_addr, &rt_key->addr)) && | 779 frag_id = fh->identification; 780 } else 781 fh->identification = frag_id; 782 783 /* 784 * Copy a block of the IP datagram. 785 */ 786 BUG_ON(skb_copy_bits(skb, ptr, skb_transport_header(frag), --- 31 unchanged lines hidden (view full) --- 818 return err; 819} 820 821static inline int ip6_rt_check(const struct rt6key *rt_key, 822 const struct in6_addr *fl_addr, 823 const struct in6_addr *addr_cache) 824{ 825 return (rt_key->plen != 128 || !ipv6_addr_equal(fl_addr, &rt_key->addr)) && |
826 (addr_cache == NULL || !ipv6_addr_equal(fl_addr, addr_cache)); | 826 (!addr_cache || !ipv6_addr_equal(fl_addr, addr_cache)); |
827} 828 829static struct dst_entry *ip6_sk_dst_check(struct sock *sk, 830 struct dst_entry *dst, 831 const struct flowi6 *fl6) 832{ 833 struct ipv6_pinfo *np = inet6_sk(sk); 834 struct rt6_info *rt; --- 42 unchanged lines hidden (view full) --- 877{ 878 struct net *net = sock_net(sk); 879#ifdef CONFIG_IPV6_OPTIMISTIC_DAD 880 struct neighbour *n; 881 struct rt6_info *rt; 882#endif 883 int err; 884 | 827} 828 829static struct dst_entry *ip6_sk_dst_check(struct sock *sk, 830 struct dst_entry *dst, 831 const struct flowi6 *fl6) 832{ 833 struct ipv6_pinfo *np = inet6_sk(sk); 834 struct rt6_info *rt; --- 42 unchanged lines hidden (view full) --- 877{ 878 struct net *net = sock_net(sk); 879#ifdef CONFIG_IPV6_OPTIMISTIC_DAD 880 struct neighbour *n; 881 struct rt6_info *rt; 882#endif 883 int err; 884 |
885 if (*dst == NULL) | 885 if (!*dst) |
886 *dst = ip6_route_output(net, sk, fl6); 887 888 err = (*dst)->error; 889 if (err) 890 goto out_err_release; 891 892 if (ipv6_addr_any(&fl6->saddr)) { 893 struct rt6_info *rt = (struct rt6_info *) *dst; --- 146 unchanged lines hidden (view full) --- 1040 struct frag_hdr fhdr; 1041 int err; 1042 1043 /* There is support for UDP large send offload by network 1044 * device, so create one single skb packet containing complete 1045 * udp datagram 1046 */ 1047 skb = skb_peek_tail(queue); | 886 *dst = ip6_route_output(net, sk, fl6); 887 888 err = (*dst)->error; 889 if (err) 890 goto out_err_release; 891 892 if (ipv6_addr_any(&fl6->saddr)) { 893 struct rt6_info *rt = (struct rt6_info *) *dst; --- 146 unchanged lines hidden (view full) --- 1040 struct frag_hdr fhdr; 1041 int err; 1042 1043 /* There is support for UDP large send offload by network 1044 * device, so create one single skb packet containing complete 1045 * udp datagram 1046 */ 1047 skb = skb_peek_tail(queue); |
1048 if (skb == NULL) { | 1048 if (!skb) { |
1049 skb = sock_alloc_send_skb(sk, 1050 hh_len + fragheaderlen + transhdrlen + 20, 1051 (flags & MSG_DONTWAIT), &err); | 1049 skb = sock_alloc_send_skb(sk, 1050 hh_len + fragheaderlen + transhdrlen + 20, 1051 (flags & MSG_DONTWAIT), &err); |
1052 if (skb == NULL) | 1052 if (!skb) |
1053 return err; 1054 1055 /* reserve space for Hardware header */ 1056 skb_reserve(skb, hh_len); 1057 1058 /* create space for UDP/IP header */ 1059 skb_put(skb, fragheaderlen + transhdrlen); 1060 --- 13 unchanged lines hidden (view full) --- 1074 1075 skb->ip_summed = CHECKSUM_PARTIAL; 1076 /* Specify the length of each IPv6 datagram fragment. 1077 * It has to be a multiple of 8. 1078 */ 1079 skb_shinfo(skb)->gso_size = (mtu - fragheaderlen - 1080 sizeof(struct frag_hdr)) & ~7; 1081 skb_shinfo(skb)->gso_type = SKB_GSO_UDP; | 1053 return err; 1054 1055 /* reserve space for Hardware header */ 1056 skb_reserve(skb, hh_len); 1057 1058 /* create space for UDP/IP header */ 1059 skb_put(skb, fragheaderlen + transhdrlen); 1060 --- 13 unchanged lines hidden (view full) --- 1074 1075 skb->ip_summed = CHECKSUM_PARTIAL; 1076 /* Specify the length of each IPv6 datagram fragment. 1077 * It has to be a multiple of 8. 1078 */ 1079 skb_shinfo(skb)->gso_size = (mtu - fragheaderlen - 1080 sizeof(struct frag_hdr)) & ~7; 1081 skb_shinfo(skb)->gso_type = SKB_GSO_UDP; |
1082 ipv6_select_ident(&fhdr, rt); | 1082 ipv6_select_ident(sock_net(sk), &fhdr, rt); |
1083 skb_shinfo(skb)->ip6_frag_id = fhdr.identification; 1084 1085append: 1086 return skb_append_datato_frags(sk, skb, getfrag, from, 1087 (length - transhdrlen)); 1088} 1089 1090static inline struct ipv6_opt_hdr *ip6_opt_dup(struct ipv6_opt_hdr *src, --- 11 unchanged lines hidden (view full) --- 1102static void ip6_append_data_mtu(unsigned int *mtu, 1103 int *maxfraglen, 1104 unsigned int fragheaderlen, 1105 struct sk_buff *skb, 1106 struct rt6_info *rt, 1107 unsigned int orig_mtu) 1108{ 1109 if (!(rt->dst.flags & DST_XFRM_TUNNEL)) { | 1083 skb_shinfo(skb)->ip6_frag_id = fhdr.identification; 1084 1085append: 1086 return skb_append_datato_frags(sk, skb, getfrag, from, 1087 (length - transhdrlen)); 1088} 1089 1090static inline struct ipv6_opt_hdr *ip6_opt_dup(struct ipv6_opt_hdr *src, --- 11 unchanged lines hidden (view full) --- 1102static void ip6_append_data_mtu(unsigned int *mtu, 1103 int *maxfraglen, 1104 unsigned int fragheaderlen, 1105 struct sk_buff *skb, 1106 struct rt6_info *rt, 1107 unsigned int orig_mtu) 1108{ 1109 if (!(rt->dst.flags & DST_XFRM_TUNNEL)) { |
1110 if (skb == NULL) { | 1110 if (!skb) { |
1111 /* first fragment, reserve header_len */ 1112 *mtu = orig_mtu - rt->dst.header_len; 1113 1114 } else { 1115 /* 1116 * this fragment is not first, the headers 1117 * space is regarded as data space. 1118 */ --- 15 unchanged lines hidden (view full) --- 1134 /* 1135 * setup for corking 1136 */ 1137 if (opt) { 1138 if (WARN_ON(v6_cork->opt)) 1139 return -EINVAL; 1140 1141 v6_cork->opt = kzalloc(opt->tot_len, sk->sk_allocation); | 1111 /* first fragment, reserve header_len */ 1112 *mtu = orig_mtu - rt->dst.header_len; 1113 1114 } else { 1115 /* 1116 * this fragment is not first, the headers 1117 * space is regarded as data space. 1118 */ --- 15 unchanged lines hidden (view full) --- 1134 /* 1135 * setup for corking 1136 */ 1137 if (opt) { 1138 if (WARN_ON(v6_cork->opt)) 1139 return -EINVAL; 1140 1141 v6_cork->opt = kzalloc(opt->tot_len, sk->sk_allocation); |
1142 if (unlikely(v6_cork->opt == NULL)) | 1142 if (unlikely(!v6_cork->opt)) |
1143 return -ENOBUFS; 1144 1145 v6_cork->opt->tot_len = opt->tot_len; 1146 v6_cork->opt->opt_flen = opt->opt_flen; 1147 v6_cork->opt->opt_nflen = opt->opt_nflen; 1148 1149 v6_cork->opt->dst0opt = ip6_opt_dup(opt->dst0opt, 1150 sk->sk_allocation); --- 175 unchanged lines hidden (view full) --- 1326 unsigned int alloclen; 1327alloc_new_skb: 1328 /* There's no room in the current skb */ 1329 if (skb) 1330 fraggap = skb->len - maxfraglen; 1331 else 1332 fraggap = 0; 1333 /* update mtu and maxfraglen if necessary */ | 1143 return -ENOBUFS; 1144 1145 v6_cork->opt->tot_len = opt->tot_len; 1146 v6_cork->opt->opt_flen = opt->opt_flen; 1147 v6_cork->opt->opt_nflen = opt->opt_nflen; 1148 1149 v6_cork->opt->dst0opt = ip6_opt_dup(opt->dst0opt, 1150 sk->sk_allocation); --- 175 unchanged lines hidden (view full) --- 1326 unsigned int alloclen; 1327alloc_new_skb: 1328 /* There's no room in the current skb */ 1329 if (skb) 1330 fraggap = skb->len - maxfraglen; 1331 else 1332 fraggap = 0; 1333 /* update mtu and maxfraglen if necessary */ |
1334 if (skb == NULL || skb_prev == NULL) | 1334 if (!skb || !skb_prev) |
1335 ip6_append_data_mtu(&mtu, &maxfraglen, 1336 fragheaderlen, skb, rt, 1337 orig_mtu); 1338 1339 skb_prev = skb; 1340 1341 /* 1342 * If remaining data exceeds the mtu, --- 35 unchanged lines hidden (view full) --- 1378 (flags & MSG_DONTWAIT), &err); 1379 } else { 1380 skb = NULL; 1381 if (atomic_read(&sk->sk_wmem_alloc) <= 1382 2 * sk->sk_sndbuf) 1383 skb = sock_wmalloc(sk, 1384 alloclen + hh_len, 1, 1385 sk->sk_allocation); | 1335 ip6_append_data_mtu(&mtu, &maxfraglen, 1336 fragheaderlen, skb, rt, 1337 orig_mtu); 1338 1339 skb_prev = skb; 1340 1341 /* 1342 * If remaining data exceeds the mtu, --- 35 unchanged lines hidden (view full) --- 1378 (flags & MSG_DONTWAIT), &err); 1379 } else { 1380 skb = NULL; 1381 if (atomic_read(&sk->sk_wmem_alloc) <= 1382 2 * sk->sk_sndbuf) 1383 skb = sock_wmalloc(sk, 1384 alloclen + hh_len, 1, 1385 sk->sk_allocation); |
1386 if (unlikely(skb == NULL)) | 1386 if (unlikely(!skb)) |
1387 err = -ENOBUFS; 1388 } | 1387 err = -ENOBUFS; 1388 } |
1389 if (skb == NULL) | 1389 if (!skb) |
1390 goto error; 1391 /* 1392 * Fill in the control structures 1393 */ 1394 skb->protocol = htons(ETH_P_IPV6); 1395 skb->ip_summed = csummode; 1396 skb->csum = 0; 1397 /* reserve for fragmentation and ipsec header */ --- 175 unchanged lines hidden (view full) --- 1573 struct net *net = sock_net(sk); 1574 struct ipv6hdr *hdr; 1575 struct ipv6_txoptions *opt = v6_cork->opt; 1576 struct rt6_info *rt = (struct rt6_info *)cork->base.dst; 1577 struct flowi6 *fl6 = &cork->fl.u.ip6; 1578 unsigned char proto = fl6->flowi6_proto; 1579 1580 skb = __skb_dequeue(queue); | 1390 goto error; 1391 /* 1392 * Fill in the control structures 1393 */ 1394 skb->protocol = htons(ETH_P_IPV6); 1395 skb->ip_summed = csummode; 1396 skb->csum = 0; 1397 /* reserve for fragmentation and ipsec header */ --- 175 unchanged lines hidden (view full) --- 1573 struct net *net = sock_net(sk); 1574 struct ipv6hdr *hdr; 1575 struct ipv6_txoptions *opt = v6_cork->opt; 1576 struct rt6_info *rt = (struct rt6_info *)cork->base.dst; 1577 struct flowi6 *fl6 = &cork->fl.u.ip6; 1578 unsigned char proto = fl6->flowi6_proto; 1579 1580 skb = __skb_dequeue(queue); |
1581 if (skb == NULL) | 1581 if (!skb) |
1582 goto out; 1583 tail_skb = &(skb_shinfo(skb)->frag_list); 1584 1585 /* move skb->data to ip header from ext header */ 1586 if (skb->data < skb_network_header(skb)) 1587 __skb_pull(skb, skb_network_offset(skb)); 1588 while ((tmp_skb = __skb_dequeue(queue)) != NULL) { 1589 __skb_pull(tmp_skb, skb_network_header_len(skb)); --- 144 unchanged lines hidden --- | 1582 goto out; 1583 tail_skb = &(skb_shinfo(skb)->frag_list); 1584 1585 /* move skb->data to ip header from ext header */ 1586 if (skb->data < skb_network_header(skb)) 1587 __skb_pull(skb, skb_network_offset(skb)); 1588 while ((tmp_skb = __skb_dequeue(queue)) != NULL) { 1589 __skb_pull(tmp_skb, skb_network_header_len(skb)); --- 144 unchanged lines hidden --- |