diff options
-rw-r--r-- | include/net/ip6_route.h | 12 | ||||
-rw-r--r-- | include/net/ipv6.h | 3 | ||||
-rw-r--r-- | net/dccp/ipv6.c | 4 | ||||
-rw-r--r-- | net/ipv6/af_inet6.c | 2 | ||||
-rw-r--r-- | net/ipv6/inet6_connection_sock.c | 2 | ||||
-rw-r--r-- | net/ipv6/ip6_output.c | 120 | ||||
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 4 | ||||
-rw-r--r-- | net/ipv6/udp.c | 2 |
8 files changed, 100 insertions, 49 deletions
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h index ab29dafb1a6a..96b0e66406ec 100644 --- a/include/net/ip6_route.h +++ b/include/net/ip6_route.h | |||
@@ -139,16 +139,22 @@ extern rwlock_t rt6_lock; | |||
139 | /* | 139 | /* |
140 | * Store a destination cache entry in a socket | 140 | * Store a destination cache entry in a socket |
141 | */ | 141 | */ |
142 | static inline void ip6_dst_store(struct sock *sk, struct dst_entry *dst, | 142 | static inline void __ip6_dst_store(struct sock *sk, struct dst_entry *dst, |
143 | struct in6_addr *daddr) | 143 | struct in6_addr *daddr) |
144 | { | 144 | { |
145 | struct ipv6_pinfo *np = inet6_sk(sk); | 145 | struct ipv6_pinfo *np = inet6_sk(sk); |
146 | struct rt6_info *rt = (struct rt6_info *) dst; | 146 | struct rt6_info *rt = (struct rt6_info *) dst; |
147 | 147 | ||
148 | write_lock(&sk->sk_dst_lock); | ||
149 | sk_setup_caps(sk, dst); | 148 | sk_setup_caps(sk, dst); |
150 | np->daddr_cache = daddr; | 149 | np->daddr_cache = daddr; |
151 | np->dst_cookie = rt->rt6i_node ? rt->rt6i_node->fn_sernum : 0; | 150 | np->dst_cookie = rt->rt6i_node ? rt->rt6i_node->fn_sernum : 0; |
151 | } | ||
152 | |||
153 | static inline void ip6_dst_store(struct sock *sk, struct dst_entry *dst, | ||
154 | struct in6_addr *daddr) | ||
155 | { | ||
156 | write_lock(&sk->sk_dst_lock); | ||
157 | __ip6_dst_store(sk, dst, daddr); | ||
152 | write_unlock(&sk->sk_dst_lock); | 158 | write_unlock(&sk->sk_dst_lock); |
153 | } | 159 | } |
154 | 160 | ||
diff --git a/include/net/ipv6.h b/include/net/ipv6.h index a8fdf7970b37..ece7e8a84ffd 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h | |||
@@ -468,6 +468,9 @@ extern void ip6_flush_pending_frames(struct sock *sk); | |||
468 | extern int ip6_dst_lookup(struct sock *sk, | 468 | extern int ip6_dst_lookup(struct sock *sk, |
469 | struct dst_entry **dst, | 469 | struct dst_entry **dst, |
470 | struct flowi *fl); | 470 | struct flowi *fl); |
471 | extern int ip6_sk_dst_lookup(struct sock *sk, | ||
472 | struct dst_entry **dst, | ||
473 | struct flowi *fl); | ||
471 | 474 | ||
472 | /* | 475 | /* |
473 | * skb processing functions | 476 | * skb processing functions |
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 9f3d4d7cd0bf..610c722ac27f 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c | |||
@@ -230,7 +230,7 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
230 | ipv6_addr_copy(&np->saddr, saddr); | 230 | ipv6_addr_copy(&np->saddr, saddr); |
231 | inet->rcv_saddr = LOOPBACK4_IPV6; | 231 | inet->rcv_saddr = LOOPBACK4_IPV6; |
232 | 232 | ||
233 | ip6_dst_store(sk, dst, NULL); | 233 | __ip6_dst_store(sk, dst, NULL); |
234 | 234 | ||
235 | icsk->icsk_ext_hdr_len = 0; | 235 | icsk->icsk_ext_hdr_len = 0; |
236 | if (np->opt != NULL) | 236 | if (np->opt != NULL) |
@@ -863,7 +863,7 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk, | |||
863 | * comment in that function for the gory details. -acme | 863 | * comment in that function for the gory details. -acme |
864 | */ | 864 | */ |
865 | 865 | ||
866 | ip6_dst_store(newsk, dst, NULL); | 866 | __ip6_dst_store(newsk, dst, NULL); |
867 | newsk->sk_route_caps = dst->dev->features & ~(NETIF_F_IP_CSUM | | 867 | newsk->sk_route_caps = dst->dev->features & ~(NETIF_F_IP_CSUM | |
868 | NETIF_F_TSO); | 868 | NETIF_F_TSO); |
869 | newdp6 = (struct dccp6_sock *)newsk; | 869 | newdp6 = (struct dccp6_sock *)newsk; |
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 5a0ba58b86cc..ac85e9c532c2 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -658,7 +658,7 @@ int inet6_sk_rebuild_header(struct sock *sk) | |||
658 | return err; | 658 | return err; |
659 | } | 659 | } |
660 | 660 | ||
661 | ip6_dst_store(sk, dst, NULL); | 661 | __ip6_dst_store(sk, dst, NULL); |
662 | } | 662 | } |
663 | 663 | ||
664 | return 0; | 664 | return 0; |
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c index 5c950cc79d80..bf491077b822 100644 --- a/net/ipv6/inet6_connection_sock.c +++ b/net/ipv6/inet6_connection_sock.c | |||
@@ -185,7 +185,7 @@ int inet6_csk_xmit(struct sk_buff *skb, int ipfragok) | |||
185 | return err; | 185 | return err; |
186 | } | 186 | } |
187 | 187 | ||
188 | ip6_dst_store(sk, dst, NULL); | 188 | __ip6_dst_store(sk, dst, NULL); |
189 | } | 189 | } |
190 | 190 | ||
191 | skb->dst = dst_clone(dst); | 191 | skb->dst = dst_clone(dst); |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 3bc74ce78800..5e74a37695f7 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -723,48 +723,51 @@ fail: | |||
723 | return err; | 723 | return err; |
724 | } | 724 | } |
725 | 725 | ||
726 | int ip6_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi *fl) | 726 | static struct dst_entry *ip6_sk_dst_check(struct sock *sk, |
727 | struct dst_entry *dst, | ||
728 | struct flowi *fl) | ||
727 | { | 729 | { |
728 | int err = 0; | 730 | struct ipv6_pinfo *np = inet6_sk(sk); |
731 | struct rt6_info *rt = (struct rt6_info *)dst; | ||
729 | 732 | ||
730 | *dst = NULL; | 733 | if (!dst) |
731 | if (sk) { | 734 | goto out; |
732 | struct ipv6_pinfo *np = inet6_sk(sk); | 735 | |
733 | 736 | /* Yes, checking route validity in not connected | |
734 | *dst = sk_dst_check(sk, np->dst_cookie); | 737 | * case is not very simple. Take into account, |
735 | if (*dst) { | 738 | * that we do not support routing by source, TOS, |
736 | struct rt6_info *rt = (struct rt6_info*)*dst; | 739 | * and MSG_DONTROUTE --ANK (980726) |
737 | 740 | * | |
738 | /* Yes, checking route validity in not connected | 741 | * 1. If route was host route, check that |
739 | * case is not very simple. Take into account, | 742 | * cached destination is current. |
740 | * that we do not support routing by source, TOS, | 743 | * If it is network route, we still may |
741 | * and MSG_DONTROUTE --ANK (980726) | 744 | * check its validity using saved pointer |
742 | * | 745 | * to the last used address: daddr_cache. |
743 | * 1. If route was host route, check that | 746 | * We do not want to save whole address now, |
744 | * cached destination is current. | 747 | * (because main consumer of this service |
745 | * If it is network route, we still may | 748 | * is tcp, which has not this problem), |
746 | * check its validity using saved pointer | 749 | * so that the last trick works only on connected |
747 | * to the last used address: daddr_cache. | 750 | * sockets. |
748 | * We do not want to save whole address now, | 751 | * 2. oif also should be the same. |
749 | * (because main consumer of this service | 752 | */ |
750 | * is tcp, which has not this problem), | 753 | if (((rt->rt6i_dst.plen != 128 || |
751 | * so that the last trick works only on connected | 754 | !ipv6_addr_equal(&fl->fl6_dst, &rt->rt6i_dst.addr)) |
752 | * sockets. | 755 | && (np->daddr_cache == NULL || |
753 | * 2. oif also should be the same. | 756 | !ipv6_addr_equal(&fl->fl6_dst, np->daddr_cache))) |
754 | */ | 757 | || (fl->oif && fl->oif != dst->dev->ifindex)) { |
755 | if (((rt->rt6i_dst.plen != 128 || | 758 | dst_release(dst); |
756 | !ipv6_addr_equal(&fl->fl6_dst, | 759 | dst = NULL; |
757 | &rt->rt6i_dst.addr)) | ||
758 | && (np->daddr_cache == NULL || | ||
759 | !ipv6_addr_equal(&fl->fl6_dst, | ||
760 | np->daddr_cache))) | ||
761 | || (fl->oif && fl->oif != (*dst)->dev->ifindex)) { | ||
762 | dst_release(*dst); | ||
763 | *dst = NULL; | ||
764 | } | ||
765 | } | ||
766 | } | 760 | } |
767 | 761 | ||
762 | out: | ||
763 | return dst; | ||
764 | } | ||
765 | |||
766 | static int ip6_dst_lookup_tail(struct sock *sk, | ||
767 | struct dst_entry **dst, struct flowi *fl) | ||
768 | { | ||
769 | int err; | ||
770 | |||
768 | if (*dst == NULL) | 771 | if (*dst == NULL) |
769 | *dst = ip6_route_output(sk, fl); | 772 | *dst = ip6_route_output(sk, fl); |
770 | 773 | ||
@@ -773,7 +776,6 @@ int ip6_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi *fl) | |||
773 | 776 | ||
774 | if (ipv6_addr_any(&fl->fl6_src)) { | 777 | if (ipv6_addr_any(&fl->fl6_src)) { |
775 | err = ipv6_get_saddr(*dst, &fl->fl6_dst, &fl->fl6_src); | 778 | err = ipv6_get_saddr(*dst, &fl->fl6_dst, &fl->fl6_src); |
776 | |||
777 | if (err) | 779 | if (err) |
778 | goto out_err_release; | 780 | goto out_err_release; |
779 | } | 781 | } |
@@ -786,8 +788,48 @@ out_err_release: | |||
786 | return err; | 788 | return err; |
787 | } | 789 | } |
788 | 790 | ||
791 | /** | ||
792 | * ip6_dst_lookup - perform route lookup on flow | ||
793 | * @sk: socket which provides route info | ||
794 | * @dst: pointer to dst_entry * for result | ||
795 | * @fl: flow to lookup | ||
796 | * | ||
797 | * This function performs a route lookup on the given flow. | ||
798 | * | ||
799 | * It returns zero on success, or a standard errno code on error. | ||
800 | */ | ||
801 | int ip6_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi *fl) | ||
802 | { | ||
803 | *dst = NULL; | ||
804 | return ip6_dst_lookup_tail(sk, dst, fl); | ||
805 | } | ||
789 | EXPORT_SYMBOL_GPL(ip6_dst_lookup); | 806 | EXPORT_SYMBOL_GPL(ip6_dst_lookup); |
790 | 807 | ||
808 | /** | ||
809 | * ip6_sk_dst_lookup - perform socket cached route lookup on flow | ||
810 | * @sk: socket which provides the dst cache and route info | ||
811 | * @dst: pointer to dst_entry * for result | ||
812 | * @fl: flow to lookup | ||
813 | * | ||
814 | * This function performs a route lookup on the given flow with the | ||
815 | * possibility of using the cached route in the socket if it is valid. | ||
816 | * It will take the socket dst lock when operating on the dst cache. | ||
817 | * As a result, this function can only be used in process context. | ||
818 | * | ||
819 | * It returns zero on success, or a standard errno code on error. | ||
820 | */ | ||
821 | int ip6_sk_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi *fl) | ||
822 | { | ||
823 | *dst = NULL; | ||
824 | if (sk) { | ||
825 | *dst = sk_dst_check(sk, inet6_sk(sk)->dst_cookie); | ||
826 | *dst = ip6_sk_dst_check(sk, *dst, fl); | ||
827 | } | ||
828 | |||
829 | return ip6_dst_lookup_tail(sk, dst, fl); | ||
830 | } | ||
831 | EXPORT_SYMBOL_GPL(ip6_sk_dst_lookup); | ||
832 | |||
791 | static inline int ip6_ufo_append_data(struct sock *sk, | 833 | static inline int ip6_ufo_append_data(struct sock *sk, |
792 | int getfrag(void *from, char *to, int offset, int len, | 834 | int getfrag(void *from, char *to, int offset, int len, |
793 | int odd, struct sk_buff *skb), | 835 | int odd, struct sk_buff *skb), |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 923989d0520d..b76fd7fba5f5 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -270,7 +270,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
270 | inet->rcv_saddr = LOOPBACK4_IPV6; | 270 | inet->rcv_saddr = LOOPBACK4_IPV6; |
271 | 271 | ||
272 | sk->sk_gso_type = SKB_GSO_TCPV6; | 272 | sk->sk_gso_type = SKB_GSO_TCPV6; |
273 | ip6_dst_store(sk, dst, NULL); | 273 | __ip6_dst_store(sk, dst, NULL); |
274 | 274 | ||
275 | icsk->icsk_ext_hdr_len = 0; | 275 | icsk->icsk_ext_hdr_len = 0; |
276 | if (np->opt) | 276 | if (np->opt) |
@@ -947,7 +947,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
947 | */ | 947 | */ |
948 | 948 | ||
949 | sk->sk_gso_type = SKB_GSO_TCPV6; | 949 | sk->sk_gso_type = SKB_GSO_TCPV6; |
950 | ip6_dst_store(newsk, dst, NULL); | 950 | __ip6_dst_store(newsk, dst, NULL); |
951 | 951 | ||
952 | newtcp6sk = (struct tcp6_sock *)newsk; | 952 | newtcp6sk = (struct tcp6_sock *)newsk; |
953 | inet_sk(newsk)->pinet6 = &newtcp6sk->inet6; | 953 | inet_sk(newsk)->pinet6 = &newtcp6sk->inet6; |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index ccc57f434cd3..3d54f246411e 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -782,7 +782,7 @@ do_udp_sendmsg: | |||
782 | connected = 0; | 782 | connected = 0; |
783 | } | 783 | } |
784 | 784 | ||
785 | err = ip6_dst_lookup(sk, &dst, fl); | 785 | err = ip6_sk_dst_lookup(sk, &dst, fl); |
786 | if (err) | 786 | if (err) |
787 | goto out; | 787 | goto out; |
788 | if (final_p) | 788 | if (final_p) |