0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/module.h>
0011 #include <linux/mm.h>
0012 #include <linux/types.h>
0013 #include <linux/list.h>
0014 #include <linux/gfp.h>
0015 #include <net/tcp.h>
0016
0017 static DEFINE_SPINLOCK(tcp_ulp_list_lock);
0018 static LIST_HEAD(tcp_ulp_list);
0019
0020
0021 static struct tcp_ulp_ops *tcp_ulp_find(const char *name)
0022 {
0023 struct tcp_ulp_ops *e;
0024
0025 list_for_each_entry_rcu(e, &tcp_ulp_list, list,
0026 lockdep_is_held(&tcp_ulp_list_lock)) {
0027 if (strcmp(e->name, name) == 0)
0028 return e;
0029 }
0030
0031 return NULL;
0032 }
0033
0034 static const struct tcp_ulp_ops *__tcp_ulp_find_autoload(const char *name)
0035 {
0036 const struct tcp_ulp_ops *ulp = NULL;
0037
0038 rcu_read_lock();
0039 ulp = tcp_ulp_find(name);
0040
0041 #ifdef CONFIG_MODULES
0042 if (!ulp && capable(CAP_NET_ADMIN)) {
0043 rcu_read_unlock();
0044 request_module("tcp-ulp-%s", name);
0045 rcu_read_lock();
0046 ulp = tcp_ulp_find(name);
0047 }
0048 #endif
0049 if (!ulp || !try_module_get(ulp->owner))
0050 ulp = NULL;
0051
0052 rcu_read_unlock();
0053 return ulp;
0054 }
0055
0056
0057
0058
0059 int tcp_register_ulp(struct tcp_ulp_ops *ulp)
0060 {
0061 int ret = 0;
0062
0063 spin_lock(&tcp_ulp_list_lock);
0064 if (tcp_ulp_find(ulp->name))
0065 ret = -EEXIST;
0066 else
0067 list_add_tail_rcu(&ulp->list, &tcp_ulp_list);
0068 spin_unlock(&tcp_ulp_list_lock);
0069
0070 return ret;
0071 }
0072 EXPORT_SYMBOL_GPL(tcp_register_ulp);
0073
0074 void tcp_unregister_ulp(struct tcp_ulp_ops *ulp)
0075 {
0076 spin_lock(&tcp_ulp_list_lock);
0077 list_del_rcu(&ulp->list);
0078 spin_unlock(&tcp_ulp_list_lock);
0079
0080 synchronize_rcu();
0081 }
0082 EXPORT_SYMBOL_GPL(tcp_unregister_ulp);
0083
0084
0085 void tcp_get_available_ulp(char *buf, size_t maxlen)
0086 {
0087 struct tcp_ulp_ops *ulp_ops;
0088 size_t offs = 0;
0089
0090 *buf = '\0';
0091 rcu_read_lock();
0092 list_for_each_entry_rcu(ulp_ops, &tcp_ulp_list, list) {
0093 offs += snprintf(buf + offs, maxlen - offs,
0094 "%s%s",
0095 offs == 0 ? "" : " ", ulp_ops->name);
0096
0097 if (WARN_ON_ONCE(offs >= maxlen))
0098 break;
0099 }
0100 rcu_read_unlock();
0101 }
0102
0103 void tcp_update_ulp(struct sock *sk, struct proto *proto,
0104 void (*write_space)(struct sock *sk))
0105 {
0106 struct inet_connection_sock *icsk = inet_csk(sk);
0107
0108 if (icsk->icsk_ulp_ops->update)
0109 icsk->icsk_ulp_ops->update(sk, proto, write_space);
0110 }
0111
0112 void tcp_cleanup_ulp(struct sock *sk)
0113 {
0114 struct inet_connection_sock *icsk = inet_csk(sk);
0115
0116
0117
0118
0119
0120 if (!icsk->icsk_ulp_ops)
0121 return;
0122
0123 if (icsk->icsk_ulp_ops->release)
0124 icsk->icsk_ulp_ops->release(sk);
0125 module_put(icsk->icsk_ulp_ops->owner);
0126
0127 icsk->icsk_ulp_ops = NULL;
0128 }
0129
0130 static int __tcp_set_ulp(struct sock *sk, const struct tcp_ulp_ops *ulp_ops)
0131 {
0132 struct inet_connection_sock *icsk = inet_csk(sk);
0133 int err;
0134
0135 err = -EEXIST;
0136 if (icsk->icsk_ulp_ops)
0137 goto out_err;
0138
0139 err = ulp_ops->init(sk);
0140 if (err)
0141 goto out_err;
0142
0143 icsk->icsk_ulp_ops = ulp_ops;
0144 return 0;
0145 out_err:
0146 module_put(ulp_ops->owner);
0147 return err;
0148 }
0149
0150 int tcp_set_ulp(struct sock *sk, const char *name)
0151 {
0152 const struct tcp_ulp_ops *ulp_ops;
0153
0154 sock_owned_by_me(sk);
0155
0156 ulp_ops = __tcp_ulp_find_autoload(name);
0157 if (!ulp_ops)
0158 return -ENOENT;
0159
0160 return __tcp_set_ulp(sk, ulp_ops);
0161 }