aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/ip6_output.c
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2006-07-30 23:19:33 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-08-02 16:38:14 -0400
commit497c615abad7ee81994dd592194535aea2aad617 (patch)
tree86bb23e49071ea1bc867232d576b2d4ece31eb4d /net/ipv6/ip6_output.c
parent679e898a4742d4a4a47430b67fd68a789a73dcfd (diff)
[IPV6]: Audit all ip6_dst_lookup/ip6_dst_store calls
The current users of ip6_dst_lookup can be divided into two classes: 1) The caller holds no locks and is in user-context (UDP). 2) The caller does not want to lookup the dst cache at all. The second class covers everyone except UDP because most people do the cache lookup directly before calling ip6_dst_lookup. This patch adds ip6_sk_dst_lookup for the first class. Similarly ip6_dst_store users can be divded into those that need to take the socket dst lock and those that don't. This patch adds __ip6_dst_store for those (everyone except UDP/datagram) that don't need an extra lock. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/ip6_output.c')
-rw-r--r--net/ipv6/ip6_output.c120
1 files changed, 81 insertions, 39 deletions
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
726int ip6_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi *fl) 726static 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
762out:
763 return dst;
764}
765
766static 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 */
801int 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}
789EXPORT_SYMBOL_GPL(ip6_dst_lookup); 806EXPORT_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 */
821int 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}
831EXPORT_SYMBOL_GPL(ip6_sk_dst_lookup);
832
791static inline int ip6_ufo_append_data(struct sock *sk, 833static 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),