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 --- |