input.c (bb598c1b8c9bf56981927dcb8c0dc34b8ff95342) input.c (7fda702f9315e6f4a74fee155c540750788a2d66)
1/* SCTP kernel implementation
2 * Copyright (c) 1999-2000 Cisco, Inc.
3 * Copyright (c) 1999-2001 Motorola, Inc.
4 * Copyright (c) 2001-2003 International Business Machines, Corp.
5 * Copyright (c) 2001 Intel Corp.
6 * Copyright (c) 2001 Nokia, Inc.
7 * Copyright (c) 2001 La Monte H.P. Yarroll
8 *

--- 776 unchanged lines hidden (view full) ---

785hit:
786 sctp_endpoint_hold(ep);
787 read_unlock(&head->lock);
788 return ep;
789}
790
791/* rhashtable for transport */
792struct sctp_hash_cmp_arg {
1/* SCTP kernel implementation
2 * Copyright (c) 1999-2000 Cisco, Inc.
3 * Copyright (c) 1999-2001 Motorola, Inc.
4 * Copyright (c) 2001-2003 International Business Machines, Corp.
5 * Copyright (c) 2001 Intel Corp.
6 * Copyright (c) 2001 Nokia, Inc.
7 * Copyright (c) 2001 La Monte H.P. Yarroll
8 *

--- 776 unchanged lines hidden (view full) ---

785hit:
786 sctp_endpoint_hold(ep);
787 read_unlock(&head->lock);
788 return ep;
789}
790
791/* rhashtable for transport */
792struct sctp_hash_cmp_arg {
793 const struct sctp_endpoint *ep;
794 const union sctp_addr *laddr;
795 const union sctp_addr *paddr;
796 const struct net *net;
793 const union sctp_addr *paddr;
794 const struct net *net;
795 u16 lport;
797};
798
799static inline int sctp_hash_cmp(struct rhashtable_compare_arg *arg,
800 const void *ptr)
801{
802 struct sctp_transport *t = (struct sctp_transport *)ptr;
803 const struct sctp_hash_cmp_arg *x = arg->key;
796};
797
798static inline int sctp_hash_cmp(struct rhashtable_compare_arg *arg,
799 const void *ptr)
800{
801 struct sctp_transport *t = (struct sctp_transport *)ptr;
802 const struct sctp_hash_cmp_arg *x = arg->key;
804 struct sctp_association *asoc;
805 int err = 1;
806
807 if (!sctp_cmp_addr_exact(&t->ipaddr, x->paddr))
808 return err;
809 if (!sctp_transport_hold(t))
810 return err;
811
803 int err = 1;
804
805 if (!sctp_cmp_addr_exact(&t->ipaddr, x->paddr))
806 return err;
807 if (!sctp_transport_hold(t))
808 return err;
809
812 asoc = t->asoc;
813 if (!net_eq(sock_net(asoc->base.sk), x->net))
810 if (!net_eq(sock_net(t->asoc->base.sk), x->net))
814 goto out;
811 goto out;
815 if (x->ep) {
816 if (x->ep != asoc->ep)
817 goto out;
818 } else {
819 if (x->laddr->v4.sin_port != htons(asoc->base.bind_addr.port))
820 goto out;
821 if (!sctp_bind_addr_match(&asoc->base.bind_addr,
822 x->laddr, sctp_sk(asoc->base.sk)))
823 goto out;
824 }
812 if (x->lport != htons(t->asoc->base.bind_addr.port))
813 goto out;
825
826 err = 0;
827out:
828 sctp_transport_put(t);
829 return err;
830}
831
832static inline u32 sctp_hash_obj(const void *data, u32 len, u32 seed)

--- 13 unchanged lines hidden (view full) ---

846 (__force __u32)lport, net_hash_mix(net), seed);
847}
848
849static inline u32 sctp_hash_key(const void *data, u32 len, u32 seed)
850{
851 const struct sctp_hash_cmp_arg *x = data;
852 const union sctp_addr *paddr = x->paddr;
853 const struct net *net = x->net;
814
815 err = 0;
816out:
817 sctp_transport_put(t);
818 return err;
819}
820
821static inline u32 sctp_hash_obj(const void *data, u32 len, u32 seed)

--- 13 unchanged lines hidden (view full) ---

835 (__force __u32)lport, net_hash_mix(net), seed);
836}
837
838static inline u32 sctp_hash_key(const void *data, u32 len, u32 seed)
839{
840 const struct sctp_hash_cmp_arg *x = data;
841 const union sctp_addr *paddr = x->paddr;
842 const struct net *net = x->net;
854 u16 lport;
843 u16 lport = x->lport;
855 u32 addr;
856
844 u32 addr;
845
857 lport = x->ep ? htons(x->ep->base.bind_addr.port) :
858 x->laddr->v4.sin_port;
859 if (paddr->sa.sa_family == AF_INET6)
860 addr = jhash(&paddr->v6.sin6_addr, 16, seed);
861 else
862 addr = paddr->v4.sin_addr.s_addr;
863
864 return jhash_3words(addr, ((__u32)paddr->v4.sin_port) << 16 |
865 (__force __u32)lport, net_hash_mix(net), seed);
866}
867
868static const struct rhashtable_params sctp_hash_params = {
869 .head_offset = offsetof(struct sctp_transport, node),
870 .hashfn = sctp_hash_key,
871 .obj_hashfn = sctp_hash_obj,
872 .obj_cmpfn = sctp_hash_cmp,
873 .automatic_shrinking = true,
874};
875
876int sctp_transport_hashtable_init(void)
877{
846 if (paddr->sa.sa_family == AF_INET6)
847 addr = jhash(&paddr->v6.sin6_addr, 16, seed);
848 else
849 addr = paddr->v4.sin_addr.s_addr;
850
851 return jhash_3words(addr, ((__u32)paddr->v4.sin_port) << 16 |
852 (__force __u32)lport, net_hash_mix(net), seed);
853}
854
855static const struct rhashtable_params sctp_hash_params = {
856 .head_offset = offsetof(struct sctp_transport, node),
857 .hashfn = sctp_hash_key,
858 .obj_hashfn = sctp_hash_obj,
859 .obj_cmpfn = sctp_hash_cmp,
860 .automatic_shrinking = true,
861};
862
863int sctp_transport_hashtable_init(void)
864{
878 return rhashtable_init(&sctp_transport_hashtable, &sctp_hash_params);
865 return rhltable_init(&sctp_transport_hashtable, &sctp_hash_params);
879}
880
881void sctp_transport_hashtable_destroy(void)
882{
866}
867
868void sctp_transport_hashtable_destroy(void)
869{
883 rhashtable_destroy(&sctp_transport_hashtable);
870 rhltable_destroy(&sctp_transport_hashtable);
884}
885
871}
872
886void sctp_hash_transport(struct sctp_transport *t)
873int sctp_hash_transport(struct sctp_transport *t)
887{
888 struct sctp_hash_cmp_arg arg;
874{
875 struct sctp_hash_cmp_arg arg;
876 int err;
889
890 if (t->asoc->temp)
877
878 if (t->asoc->temp)
891 return;
879 return 0;
892
880
893 arg.ep = t->asoc->ep;
894 arg.paddr = &t->ipaddr;
895 arg.net = sock_net(t->asoc->base.sk);
881 arg.net = sock_net(t->asoc->base.sk);
882 arg.paddr = &t->ipaddr;
883 arg.lport = htons(t->asoc->base.bind_addr.port);
896
884
897reinsert:
898 if (rhashtable_lookup_insert_key(&sctp_transport_hashtable, &arg,
899 &t->node, sctp_hash_params) == -EBUSY)
900 goto reinsert;
885 err = rhltable_insert_key(&sctp_transport_hashtable, &arg,
886 &t->node, sctp_hash_params);
887 if (err)
888 pr_err_once("insert transport fail, errno %d\n", err);
889
890 return err;
901}
902
903void sctp_unhash_transport(struct sctp_transport *t)
904{
905 if (t->asoc->temp)
906 return;
907
891}
892
893void sctp_unhash_transport(struct sctp_transport *t)
894{
895 if (t->asoc->temp)
896 return;
897
908 rhashtable_remove_fast(&sctp_transport_hashtable, &t->node,
909 sctp_hash_params);
898 rhltable_remove(&sctp_transport_hashtable, &t->node,
899 sctp_hash_params);
910}
911
900}
901
902/* return a transport with holding it */
912struct sctp_transport *sctp_addrs_lookup_transport(
913 struct net *net,
914 const union sctp_addr *laddr,
915 const union sctp_addr *paddr)
916{
903struct sctp_transport *sctp_addrs_lookup_transport(
904 struct net *net,
905 const union sctp_addr *laddr,
906 const union sctp_addr *paddr)
907{
908 struct rhlist_head *tmp, *list;
909 struct sctp_transport *t;
917 struct sctp_hash_cmp_arg arg = {
910 struct sctp_hash_cmp_arg arg = {
918 .ep = NULL,
919 .laddr = laddr,
920 .paddr = paddr,
921 .net = net,
911 .paddr = paddr,
912 .net = net,
913 .lport = laddr->v4.sin_port,
922 };
923
914 };
915
924 return rhashtable_lookup_fast(&sctp_transport_hashtable, &arg,
925 sctp_hash_params);
916 list = rhltable_lookup(&sctp_transport_hashtable, &arg,
917 sctp_hash_params);
918
919 rhl_for_each_entry_rcu(t, tmp, list, node) {
920 if (!sctp_transport_hold(t))
921 continue;
922
923 if (sctp_bind_addr_match(&t->asoc->base.bind_addr,
924 laddr, sctp_sk(t->asoc->base.sk)))
925 return t;
926 sctp_transport_put(t);
927 }
928
929 return NULL;
926}
927
930}
931
932/* return a transport without holding it, as it's only used under sock lock */
928struct sctp_transport *sctp_epaddr_lookup_transport(
929 const struct sctp_endpoint *ep,
930 const union sctp_addr *paddr)
931{
932 struct net *net = sock_net(ep->base.sk);
933struct sctp_transport *sctp_epaddr_lookup_transport(
934 const struct sctp_endpoint *ep,
935 const union sctp_addr *paddr)
936{
937 struct net *net = sock_net(ep->base.sk);
938 struct rhlist_head *tmp, *list;
939 struct sctp_transport *t;
933 struct sctp_hash_cmp_arg arg = {
940 struct sctp_hash_cmp_arg arg = {
934 .ep = ep,
935 .paddr = paddr,
936 .net = net,
941 .paddr = paddr,
942 .net = net,
943 .lport = htons(ep->base.bind_addr.port),
937 };
938
944 };
945
939 return rhashtable_lookup_fast(&sctp_transport_hashtable, &arg,
940 sctp_hash_params);
946 list = rhltable_lookup(&sctp_transport_hashtable, &arg,
947 sctp_hash_params);
948
949 rhl_for_each_entry_rcu(t, tmp, list, node)
950 if (ep == t->asoc->ep)
951 return t;
952
953 return NULL;
941}
942
943/* Look up an association. */
944static struct sctp_association *__sctp_lookup_association(
945 struct net *net,
946 const union sctp_addr *local,
947 const union sctp_addr *peer,
948 struct sctp_transport **pt)
949{
950 struct sctp_transport *t;
951 struct sctp_association *asoc = NULL;
952
953 t = sctp_addrs_lookup_transport(net, local, peer);
954}
955
956/* Look up an association. */
957static struct sctp_association *__sctp_lookup_association(
958 struct net *net,
959 const union sctp_addr *local,
960 const union sctp_addr *peer,
961 struct sctp_transport **pt)
962{
963 struct sctp_transport *t;
964 struct sctp_association *asoc = NULL;
965
966 t = sctp_addrs_lookup_transport(net, local, peer);
954 if (!t || !sctp_transport_hold(t))
967 if (!t)
955 goto out;
956
957 asoc = t->asoc;
958 *pt = t;
959
960out:
961 return asoc;
962}

--- 266 unchanged lines hidden ---
968 goto out;
969
970 asoc = t->asoc;
971 *pt = t;
972
973out:
974 return asoc;
975}

--- 266 unchanged lines hidden ---