diff options
Diffstat (limited to 'net/ipv6/ip6_output.c')
-rw-r--r-- | net/ipv6/ip6_output.c | 158 |
1 files changed, 108 insertions, 50 deletions
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 5f8d242be3f3..46cf7bea6769 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -174,15 +174,15 @@ int ip6_output(struct sk_buff *skb) | |||
174 | * xmit an sk_buff (used by TCP, SCTP and DCCP) | 174 | * xmit an sk_buff (used by TCP, SCTP and DCCP) |
175 | */ | 175 | */ |
176 | 176 | ||
177 | int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, | 177 | int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6, |
178 | struct ipv6_txoptions *opt) | 178 | struct ipv6_txoptions *opt) |
179 | { | 179 | { |
180 | struct net *net = sock_net(sk); | 180 | struct net *net = sock_net(sk); |
181 | struct ipv6_pinfo *np = inet6_sk(sk); | 181 | struct ipv6_pinfo *np = inet6_sk(sk); |
182 | struct in6_addr *first_hop = &fl->fl6_dst; | 182 | struct in6_addr *first_hop = &fl6->daddr; |
183 | struct dst_entry *dst = skb_dst(skb); | 183 | struct dst_entry *dst = skb_dst(skb); |
184 | struct ipv6hdr *hdr; | 184 | struct ipv6hdr *hdr; |
185 | u8 proto = fl->proto; | 185 | u8 proto = fl6->flowi6_proto; |
186 | int seg_len = skb->len; | 186 | int seg_len = skb->len; |
187 | int hlimit = -1; | 187 | int hlimit = -1; |
188 | int tclass = 0; | 188 | int tclass = 0; |
@@ -230,13 +230,13 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, | |||
230 | if (hlimit < 0) | 230 | if (hlimit < 0) |
231 | hlimit = ip6_dst_hoplimit(dst); | 231 | hlimit = ip6_dst_hoplimit(dst); |
232 | 232 | ||
233 | *(__be32 *)hdr = htonl(0x60000000 | (tclass << 20)) | fl->fl6_flowlabel; | 233 | *(__be32 *)hdr = htonl(0x60000000 | (tclass << 20)) | fl6->flowlabel; |
234 | 234 | ||
235 | hdr->payload_len = htons(seg_len); | 235 | hdr->payload_len = htons(seg_len); |
236 | hdr->nexthdr = proto; | 236 | hdr->nexthdr = proto; |
237 | hdr->hop_limit = hlimit; | 237 | hdr->hop_limit = hlimit; |
238 | 238 | ||
239 | ipv6_addr_copy(&hdr->saddr, &fl->fl6_src); | 239 | ipv6_addr_copy(&hdr->saddr, &fl6->saddr); |
240 | ipv6_addr_copy(&hdr->daddr, first_hop); | 240 | ipv6_addr_copy(&hdr->daddr, first_hop); |
241 | 241 | ||
242 | skb->priority = sk->sk_priority; | 242 | skb->priority = sk->sk_priority; |
@@ -274,13 +274,10 @@ int ip6_nd_hdr(struct sock *sk, struct sk_buff *skb, struct net_device *dev, | |||
274 | { | 274 | { |
275 | struct ipv6_pinfo *np = inet6_sk(sk); | 275 | struct ipv6_pinfo *np = inet6_sk(sk); |
276 | struct ipv6hdr *hdr; | 276 | struct ipv6hdr *hdr; |
277 | int totlen; | ||
278 | 277 | ||
279 | skb->protocol = htons(ETH_P_IPV6); | 278 | skb->protocol = htons(ETH_P_IPV6); |
280 | skb->dev = dev; | 279 | skb->dev = dev; |
281 | 280 | ||
282 | totlen = len + sizeof(struct ipv6hdr); | ||
283 | |||
284 | skb_reset_network_header(skb); | 281 | skb_reset_network_header(skb); |
285 | skb_put(skb, sizeof(struct ipv6hdr)); | 282 | skb_put(skb, sizeof(struct ipv6hdr)); |
286 | hdr = ipv6_hdr(skb); | 283 | hdr = ipv6_hdr(skb); |
@@ -479,10 +476,13 @@ int ip6_forward(struct sk_buff *skb) | |||
479 | else | 476 | else |
480 | target = &hdr->daddr; | 477 | target = &hdr->daddr; |
481 | 478 | ||
479 | if (!rt->rt6i_peer) | ||
480 | rt6_bind_peer(rt, 1); | ||
481 | |||
482 | /* Limit redirects both by destination (here) | 482 | /* Limit redirects both by destination (here) |
483 | and by source (inside ndisc_send_redirect) | 483 | and by source (inside ndisc_send_redirect) |
484 | */ | 484 | */ |
485 | if (xrlim_allow(dst, 1*HZ)) | 485 | if (inet_peer_xrlim_allow(rt->rt6i_peer, 1*HZ)) |
486 | ndisc_send_redirect(skb, n, target); | 486 | ndisc_send_redirect(skb, n, target); |
487 | } else { | 487 | } else { |
488 | int addrtype = ipv6_addr_type(&hdr->saddr); | 488 | int addrtype = ipv6_addr_type(&hdr->saddr); |
@@ -779,7 +779,7 @@ slow_path: | |||
779 | /* IF: it doesn't fit, use 'mtu' - the data space left */ | 779 | /* IF: it doesn't fit, use 'mtu' - the data space left */ |
780 | if (len > mtu) | 780 | if (len > mtu) |
781 | len = mtu; | 781 | len = mtu; |
782 | /* IF: we are not sending upto and including the packet end | 782 | /* IF: we are not sending up to and including the packet end |
783 | then align the next start on an eight byte boundary */ | 783 | then align the next start on an eight byte boundary */ |
784 | if (len < left) { | 784 | if (len < left) { |
785 | len &= ~7; | 785 | len &= ~7; |
@@ -879,7 +879,7 @@ static inline int ip6_rt_check(struct rt6key *rt_key, | |||
879 | 879 | ||
880 | static struct dst_entry *ip6_sk_dst_check(struct sock *sk, | 880 | static struct dst_entry *ip6_sk_dst_check(struct sock *sk, |
881 | struct dst_entry *dst, | 881 | struct dst_entry *dst, |
882 | struct flowi *fl) | 882 | struct flowi6 *fl6) |
883 | { | 883 | { |
884 | struct ipv6_pinfo *np = inet6_sk(sk); | 884 | struct ipv6_pinfo *np = inet6_sk(sk); |
885 | struct rt6_info *rt = (struct rt6_info *)dst; | 885 | struct rt6_info *rt = (struct rt6_info *)dst; |
@@ -904,11 +904,11 @@ static struct dst_entry *ip6_sk_dst_check(struct sock *sk, | |||
904 | * sockets. | 904 | * sockets. |
905 | * 2. oif also should be the same. | 905 | * 2. oif also should be the same. |
906 | */ | 906 | */ |
907 | if (ip6_rt_check(&rt->rt6i_dst, &fl->fl6_dst, np->daddr_cache) || | 907 | if (ip6_rt_check(&rt->rt6i_dst, &fl6->daddr, np->daddr_cache) || |
908 | #ifdef CONFIG_IPV6_SUBTREES | 908 | #ifdef CONFIG_IPV6_SUBTREES |
909 | ip6_rt_check(&rt->rt6i_src, &fl->fl6_src, np->saddr_cache) || | 909 | ip6_rt_check(&rt->rt6i_src, &fl6->saddr, np->saddr_cache) || |
910 | #endif | 910 | #endif |
911 | (fl->oif && fl->oif != dst->dev->ifindex)) { | 911 | (fl6->flowi6_oif && fl6->flowi6_oif != dst->dev->ifindex)) { |
912 | dst_release(dst); | 912 | dst_release(dst); |
913 | dst = NULL; | 913 | dst = NULL; |
914 | } | 914 | } |
@@ -918,22 +918,22 @@ out: | |||
918 | } | 918 | } |
919 | 919 | ||
920 | static int ip6_dst_lookup_tail(struct sock *sk, | 920 | static int ip6_dst_lookup_tail(struct sock *sk, |
921 | struct dst_entry **dst, struct flowi *fl) | 921 | struct dst_entry **dst, struct flowi6 *fl6) |
922 | { | 922 | { |
923 | int err; | 923 | int err; |
924 | struct net *net = sock_net(sk); | 924 | struct net *net = sock_net(sk); |
925 | 925 | ||
926 | if (*dst == NULL) | 926 | if (*dst == NULL) |
927 | *dst = ip6_route_output(net, sk, fl); | 927 | *dst = ip6_route_output(net, sk, fl6); |
928 | 928 | ||
929 | if ((err = (*dst)->error)) | 929 | if ((err = (*dst)->error)) |
930 | goto out_err_release; | 930 | goto out_err_release; |
931 | 931 | ||
932 | if (ipv6_addr_any(&fl->fl6_src)) { | 932 | if (ipv6_addr_any(&fl6->saddr)) { |
933 | err = ipv6_dev_get_saddr(net, ip6_dst_idev(*dst)->dev, | 933 | err = ipv6_dev_get_saddr(net, ip6_dst_idev(*dst)->dev, |
934 | &fl->fl6_dst, | 934 | &fl6->daddr, |
935 | sk ? inet6_sk(sk)->srcprefs : 0, | 935 | sk ? inet6_sk(sk)->srcprefs : 0, |
936 | &fl->fl6_src); | 936 | &fl6->saddr); |
937 | if (err) | 937 | if (err) |
938 | goto out_err_release; | 938 | goto out_err_release; |
939 | } | 939 | } |
@@ -949,10 +949,10 @@ static int ip6_dst_lookup_tail(struct sock *sk, | |||
949 | */ | 949 | */ |
950 | if ((*dst)->neighbour && !((*dst)->neighbour->nud_state & NUD_VALID)) { | 950 | if ((*dst)->neighbour && !((*dst)->neighbour->nud_state & NUD_VALID)) { |
951 | struct inet6_ifaddr *ifp; | 951 | struct inet6_ifaddr *ifp; |
952 | struct flowi fl_gw; | 952 | struct flowi6 fl_gw6; |
953 | int redirect; | 953 | int redirect; |
954 | 954 | ||
955 | ifp = ipv6_get_ifaddr(net, &fl->fl6_src, | 955 | ifp = ipv6_get_ifaddr(net, &fl6->saddr, |
956 | (*dst)->dev, 1); | 956 | (*dst)->dev, 1); |
957 | 957 | ||
958 | redirect = (ifp && ifp->flags & IFA_F_OPTIMISTIC); | 958 | redirect = (ifp && ifp->flags & IFA_F_OPTIMISTIC); |
@@ -965,9 +965,9 @@ static int ip6_dst_lookup_tail(struct sock *sk, | |||
965 | * default router instead | 965 | * default router instead |
966 | */ | 966 | */ |
967 | dst_release(*dst); | 967 | dst_release(*dst); |
968 | memcpy(&fl_gw, fl, sizeof(struct flowi)); | 968 | memcpy(&fl_gw6, fl6, sizeof(struct flowi6)); |
969 | memset(&fl_gw.fl6_dst, 0, sizeof(struct in6_addr)); | 969 | memset(&fl_gw6.daddr, 0, sizeof(struct in6_addr)); |
970 | *dst = ip6_route_output(net, sk, &fl_gw); | 970 | *dst = ip6_route_output(net, sk, &fl_gw6); |
971 | if ((err = (*dst)->error)) | 971 | if ((err = (*dst)->error)) |
972 | goto out_err_release; | 972 | goto out_err_release; |
973 | } | 973 | } |
@@ -988,43 +988,85 @@ out_err_release: | |||
988 | * ip6_dst_lookup - perform route lookup on flow | 988 | * ip6_dst_lookup - perform route lookup on flow |
989 | * @sk: socket which provides route info | 989 | * @sk: socket which provides route info |
990 | * @dst: pointer to dst_entry * for result | 990 | * @dst: pointer to dst_entry * for result |
991 | * @fl: flow to lookup | 991 | * @fl6: flow to lookup |
992 | * | 992 | * |
993 | * This function performs a route lookup on the given flow. | 993 | * This function performs a route lookup on the given flow. |
994 | * | 994 | * |
995 | * It returns zero on success, or a standard errno code on error. | 995 | * It returns zero on success, or a standard errno code on error. |
996 | */ | 996 | */ |
997 | int ip6_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi *fl) | 997 | int ip6_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi6 *fl6) |
998 | { | 998 | { |
999 | *dst = NULL; | 999 | *dst = NULL; |
1000 | return ip6_dst_lookup_tail(sk, dst, fl); | 1000 | return ip6_dst_lookup_tail(sk, dst, fl6); |
1001 | } | 1001 | } |
1002 | EXPORT_SYMBOL_GPL(ip6_dst_lookup); | 1002 | EXPORT_SYMBOL_GPL(ip6_dst_lookup); |
1003 | 1003 | ||
1004 | /** | 1004 | /** |
1005 | * ip6_sk_dst_lookup - perform socket cached route lookup on flow | 1005 | * ip6_dst_lookup_flow - perform route lookup on flow with ipsec |
1006 | * @sk: socket which provides route info | ||
1007 | * @fl6: flow to lookup | ||
1008 | * @final_dst: final destination address for ipsec lookup | ||
1009 | * @can_sleep: we are in a sleepable context | ||
1010 | * | ||
1011 | * This function performs a route lookup on the given flow. | ||
1012 | * | ||
1013 | * It returns a valid dst pointer on success, or a pointer encoded | ||
1014 | * error code. | ||
1015 | */ | ||
1016 | struct dst_entry *ip6_dst_lookup_flow(struct sock *sk, struct flowi6 *fl6, | ||
1017 | const struct in6_addr *final_dst, | ||
1018 | bool can_sleep) | ||
1019 | { | ||
1020 | struct dst_entry *dst = NULL; | ||
1021 | int err; | ||
1022 | |||
1023 | err = ip6_dst_lookup_tail(sk, &dst, fl6); | ||
1024 | if (err) | ||
1025 | return ERR_PTR(err); | ||
1026 | if (final_dst) | ||
1027 | ipv6_addr_copy(&fl6->daddr, final_dst); | ||
1028 | if (can_sleep) | ||
1029 | fl6->flowi6_flags |= FLOWI_FLAG_CAN_SLEEP; | ||
1030 | |||
1031 | return xfrm_lookup(sock_net(sk), dst, flowi6_to_flowi(fl6), sk, 0); | ||
1032 | } | ||
1033 | EXPORT_SYMBOL_GPL(ip6_dst_lookup_flow); | ||
1034 | |||
1035 | /** | ||
1036 | * ip6_sk_dst_lookup_flow - perform socket cached route lookup on flow | ||
1006 | * @sk: socket which provides the dst cache and route info | 1037 | * @sk: socket which provides the dst cache and route info |
1007 | * @dst: pointer to dst_entry * for result | 1038 | * @fl6: flow to lookup |
1008 | * @fl: flow to lookup | 1039 | * @final_dst: final destination address for ipsec lookup |
1040 | * @can_sleep: we are in a sleepable context | ||
1009 | * | 1041 | * |
1010 | * This function performs a route lookup on the given flow with the | 1042 | * This function performs a route lookup on the given flow with the |
1011 | * possibility of using the cached route in the socket if it is valid. | 1043 | * possibility of using the cached route in the socket if it is valid. |
1012 | * It will take the socket dst lock when operating on the dst cache. | 1044 | * It will take the socket dst lock when operating on the dst cache. |
1013 | * As a result, this function can only be used in process context. | 1045 | * As a result, this function can only be used in process context. |
1014 | * | 1046 | * |
1015 | * It returns zero on success, or a standard errno code on error. | 1047 | * It returns a valid dst pointer on success, or a pointer encoded |
1048 | * error code. | ||
1016 | */ | 1049 | */ |
1017 | int ip6_sk_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi *fl) | 1050 | struct dst_entry *ip6_sk_dst_lookup_flow(struct sock *sk, struct flowi6 *fl6, |
1051 | const struct in6_addr *final_dst, | ||
1052 | bool can_sleep) | ||
1018 | { | 1053 | { |
1019 | *dst = NULL; | 1054 | struct dst_entry *dst = sk_dst_check(sk, inet6_sk(sk)->dst_cookie); |
1020 | if (sk) { | 1055 | int err; |
1021 | *dst = sk_dst_check(sk, inet6_sk(sk)->dst_cookie); | 1056 | |
1022 | *dst = ip6_sk_dst_check(sk, *dst, fl); | 1057 | dst = ip6_sk_dst_check(sk, dst, fl6); |
1023 | } | 1058 | |
1059 | err = ip6_dst_lookup_tail(sk, &dst, fl6); | ||
1060 | if (err) | ||
1061 | return ERR_PTR(err); | ||
1062 | if (final_dst) | ||
1063 | ipv6_addr_copy(&fl6->daddr, final_dst); | ||
1064 | if (can_sleep) | ||
1065 | fl6->flowi6_flags |= FLOWI_FLAG_CAN_SLEEP; | ||
1024 | 1066 | ||
1025 | return ip6_dst_lookup_tail(sk, dst, fl); | 1067 | return xfrm_lookup(sock_net(sk), dst, flowi6_to_flowi(fl6), sk, 0); |
1026 | } | 1068 | } |
1027 | EXPORT_SYMBOL_GPL(ip6_sk_dst_lookup); | 1069 | EXPORT_SYMBOL_GPL(ip6_sk_dst_lookup_flow); |
1028 | 1070 | ||
1029 | static inline int ip6_ufo_append_data(struct sock *sk, | 1071 | static inline int ip6_ufo_append_data(struct sock *sk, |
1030 | int getfrag(void *from, char *to, int offset, int len, | 1072 | int getfrag(void *from, char *to, int offset, int len, |
@@ -1061,7 +1103,6 @@ static inline int ip6_ufo_append_data(struct sock *sk, | |||
1061 | 1103 | ||
1062 | skb->ip_summed = CHECKSUM_PARTIAL; | 1104 | skb->ip_summed = CHECKSUM_PARTIAL; |
1063 | skb->csum = 0; | 1105 | skb->csum = 0; |
1064 | sk->sk_sndmsg_off = 0; | ||
1065 | } | 1106 | } |
1066 | 1107 | ||
1067 | err = skb_append_datato_frags(sk,skb, getfrag, from, | 1108 | err = skb_append_datato_frags(sk,skb, getfrag, from, |
@@ -1104,7 +1145,7 @@ static inline struct ipv6_rt_hdr *ip6_rthdr_dup(struct ipv6_rt_hdr *src, | |||
1104 | int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | 1145 | int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, |
1105 | int offset, int len, int odd, struct sk_buff *skb), | 1146 | int offset, int len, int odd, struct sk_buff *skb), |
1106 | void *from, int length, int transhdrlen, | 1147 | void *from, int length, int transhdrlen, |
1107 | int hlimit, int tclass, struct ipv6_txoptions *opt, struct flowi *fl, | 1148 | int hlimit, int tclass, struct ipv6_txoptions *opt, struct flowi6 *fl6, |
1108 | struct rt6_info *rt, unsigned int flags, int dontfrag) | 1149 | struct rt6_info *rt, unsigned int flags, int dontfrag) |
1109 | { | 1150 | { |
1110 | struct inet_sock *inet = inet_sk(sk); | 1151 | struct inet_sock *inet = inet_sk(sk); |
@@ -1118,6 +1159,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1118 | int err; | 1159 | int err; |
1119 | int offset = 0; | 1160 | int offset = 0; |
1120 | int csummode = CHECKSUM_NONE; | 1161 | int csummode = CHECKSUM_NONE; |
1162 | __u8 tx_flags = 0; | ||
1121 | 1163 | ||
1122 | if (flags&MSG_PROBE) | 1164 | if (flags&MSG_PROBE) |
1123 | return 0; | 1165 | return 0; |
@@ -1161,7 +1203,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1161 | } | 1203 | } |
1162 | dst_hold(&rt->dst); | 1204 | dst_hold(&rt->dst); |
1163 | inet->cork.dst = &rt->dst; | 1205 | inet->cork.dst = &rt->dst; |
1164 | inet->cork.fl = *fl; | 1206 | inet->cork.fl.u.ip6 = *fl6; |
1165 | np->cork.hop_limit = hlimit; | 1207 | np->cork.hop_limit = hlimit; |
1166 | np->cork.tclass = tclass; | 1208 | np->cork.tclass = tclass; |
1167 | mtu = np->pmtudisc == IPV6_PMTUDISC_PROBE ? | 1209 | mtu = np->pmtudisc == IPV6_PMTUDISC_PROBE ? |
@@ -1182,7 +1224,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1182 | transhdrlen += exthdrlen; | 1224 | transhdrlen += exthdrlen; |
1183 | } else { | 1225 | } else { |
1184 | rt = (struct rt6_info *)inet->cork.dst; | 1226 | rt = (struct rt6_info *)inet->cork.dst; |
1185 | fl = &inet->cork.fl; | 1227 | fl6 = &inet->cork.fl.u.ip6; |
1186 | opt = np->cork.opt; | 1228 | opt = np->cork.opt; |
1187 | transhdrlen = 0; | 1229 | transhdrlen = 0; |
1188 | exthdrlen = 0; | 1230 | exthdrlen = 0; |
@@ -1197,11 +1239,18 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1197 | 1239 | ||
1198 | if (mtu <= sizeof(struct ipv6hdr) + IPV6_MAXPLEN) { | 1240 | if (mtu <= sizeof(struct ipv6hdr) + IPV6_MAXPLEN) { |
1199 | if (inet->cork.length + length > sizeof(struct ipv6hdr) + IPV6_MAXPLEN - fragheaderlen) { | 1241 | if (inet->cork.length + length > sizeof(struct ipv6hdr) + IPV6_MAXPLEN - fragheaderlen) { |
1200 | ipv6_local_error(sk, EMSGSIZE, fl, mtu-exthdrlen); | 1242 | ipv6_local_error(sk, EMSGSIZE, fl6, mtu-exthdrlen); |
1201 | return -EMSGSIZE; | 1243 | return -EMSGSIZE; |
1202 | } | 1244 | } |
1203 | } | 1245 | } |
1204 | 1246 | ||
1247 | /* For UDP, check if TX timestamp is enabled */ | ||
1248 | if (sk->sk_type == SOCK_DGRAM) { | ||
1249 | err = sock_tx_timestamp(sk, &tx_flags); | ||
1250 | if (err) | ||
1251 | goto error; | ||
1252 | } | ||
1253 | |||
1205 | /* | 1254 | /* |
1206 | * Let's try using as much space as possible. | 1255 | * Let's try using as much space as possible. |
1207 | * Use MTU if total length of the message fits into the MTU. | 1256 | * Use MTU if total length of the message fits into the MTU. |
@@ -1222,7 +1271,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1222 | if (length > mtu) { | 1271 | if (length > mtu) { |
1223 | int proto = sk->sk_protocol; | 1272 | int proto = sk->sk_protocol; |
1224 | if (dontfrag && (proto == IPPROTO_UDP || proto == IPPROTO_RAW)){ | 1273 | if (dontfrag && (proto == IPPROTO_UDP || proto == IPPROTO_RAW)){ |
1225 | ipv6_local_rxpmtu(sk, fl, mtu-exthdrlen); | 1274 | ipv6_local_rxpmtu(sk, fl6, mtu-exthdrlen); |
1226 | return -EMSGSIZE; | 1275 | return -EMSGSIZE; |
1227 | } | 1276 | } |
1228 | 1277 | ||
@@ -1306,6 +1355,12 @@ alloc_new_skb: | |||
1306 | sk->sk_allocation); | 1355 | sk->sk_allocation); |
1307 | if (unlikely(skb == NULL)) | 1356 | if (unlikely(skb == NULL)) |
1308 | err = -ENOBUFS; | 1357 | err = -ENOBUFS; |
1358 | else { | ||
1359 | /* Only the initial fragment | ||
1360 | * is time stamped. | ||
1361 | */ | ||
1362 | tx_flags = 0; | ||
1363 | } | ||
1309 | } | 1364 | } |
1310 | if (skb == NULL) | 1365 | if (skb == NULL) |
1311 | goto error; | 1366 | goto error; |
@@ -1317,6 +1372,9 @@ alloc_new_skb: | |||
1317 | /* reserve for fragmentation */ | 1372 | /* reserve for fragmentation */ |
1318 | skb_reserve(skb, hh_len+sizeof(struct frag_hdr)); | 1373 | skb_reserve(skb, hh_len+sizeof(struct frag_hdr)); |
1319 | 1374 | ||
1375 | if (sk->sk_type == SOCK_DGRAM) | ||
1376 | skb_shinfo(skb)->tx_flags = tx_flags; | ||
1377 | |||
1320 | /* | 1378 | /* |
1321 | * Find where to start putting bytes | 1379 | * Find where to start putting bytes |
1322 | */ | 1380 | */ |
@@ -1458,8 +1516,8 @@ int ip6_push_pending_frames(struct sock *sk) | |||
1458 | struct ipv6hdr *hdr; | 1516 | struct ipv6hdr *hdr; |
1459 | struct ipv6_txoptions *opt = np->cork.opt; | 1517 | struct ipv6_txoptions *opt = np->cork.opt; |
1460 | struct rt6_info *rt = (struct rt6_info *)inet->cork.dst; | 1518 | struct rt6_info *rt = (struct rt6_info *)inet->cork.dst; |
1461 | struct flowi *fl = &inet->cork.fl; | 1519 | struct flowi6 *fl6 = &inet->cork.fl.u.ip6; |
1462 | unsigned char proto = fl->proto; | 1520 | unsigned char proto = fl6->flowi6_proto; |
1463 | int err = 0; | 1521 | int err = 0; |
1464 | 1522 | ||
1465 | if ((skb = __skb_dequeue(&sk->sk_write_queue)) == NULL) | 1523 | if ((skb = __skb_dequeue(&sk->sk_write_queue)) == NULL) |
@@ -1484,7 +1542,7 @@ int ip6_push_pending_frames(struct sock *sk) | |||
1484 | if (np->pmtudisc < IPV6_PMTUDISC_DO) | 1542 | if (np->pmtudisc < IPV6_PMTUDISC_DO) |
1485 | skb->local_df = 1; | 1543 | skb->local_df = 1; |
1486 | 1544 | ||
1487 | ipv6_addr_copy(final_dst, &fl->fl6_dst); | 1545 | ipv6_addr_copy(final_dst, &fl6->daddr); |
1488 | __skb_pull(skb, skb_network_header_len(skb)); | 1546 | __skb_pull(skb, skb_network_header_len(skb)); |
1489 | if (opt && opt->opt_flen) | 1547 | if (opt && opt->opt_flen) |
1490 | ipv6_push_frag_opts(skb, opt, &proto); | 1548 | ipv6_push_frag_opts(skb, opt, &proto); |
@@ -1495,12 +1553,12 @@ int ip6_push_pending_frames(struct sock *sk) | |||
1495 | skb_reset_network_header(skb); | 1553 | skb_reset_network_header(skb); |
1496 | hdr = ipv6_hdr(skb); | 1554 | hdr = ipv6_hdr(skb); |
1497 | 1555 | ||
1498 | *(__be32*)hdr = fl->fl6_flowlabel | | 1556 | *(__be32*)hdr = fl6->flowlabel | |
1499 | htonl(0x60000000 | ((int)np->cork.tclass << 20)); | 1557 | htonl(0x60000000 | ((int)np->cork.tclass << 20)); |
1500 | 1558 | ||
1501 | hdr->hop_limit = np->cork.hop_limit; | 1559 | hdr->hop_limit = np->cork.hop_limit; |
1502 | hdr->nexthdr = proto; | 1560 | hdr->nexthdr = proto; |
1503 | ipv6_addr_copy(&hdr->saddr, &fl->fl6_src); | 1561 | ipv6_addr_copy(&hdr->saddr, &fl6->saddr); |
1504 | ipv6_addr_copy(&hdr->daddr, final_dst); | 1562 | ipv6_addr_copy(&hdr->daddr, final_dst); |
1505 | 1563 | ||
1506 | skb->priority = sk->sk_priority; | 1564 | skb->priority = sk->sk_priority; |