1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | /* |
3 | * linux/include/linux/sunrpc/svc_xprt.h |
4 | * |
5 | * RPC server transport I/O |
6 | */ |
7 | |
8 | #ifndef SUNRPC_SVC_XPRT_H |
9 | #define SUNRPC_SVC_XPRT_H |
10 | |
11 | #include <linux/sunrpc/svc.h> |
12 | |
13 | struct module; |
14 | |
15 | struct svc_xprt_ops { |
16 | struct svc_xprt *(*xpo_create)(struct svc_serv *, |
17 | struct net *net, |
18 | struct sockaddr *, int, |
19 | int); |
20 | struct svc_xprt *(*xpo_accept)(struct svc_xprt *); |
21 | int (*xpo_has_wspace)(struct svc_xprt *); |
22 | int (*xpo_recvfrom)(struct svc_rqst *); |
23 | int (*xpo_sendto)(struct svc_rqst *); |
24 | int (*xpo_result_payload)(struct svc_rqst *, unsigned int, |
25 | unsigned int); |
26 | void (*xpo_release_ctxt)(struct svc_xprt *xprt, void *ctxt); |
27 | void (*xpo_detach)(struct svc_xprt *); |
28 | void (*xpo_free)(struct svc_xprt *); |
29 | void (*xpo_kill_temp_xprt)(struct svc_xprt *); |
30 | void (*xpo_handshake)(struct svc_xprt *xprt); |
31 | }; |
32 | |
33 | struct svc_xprt_class { |
34 | const char *xcl_name; |
35 | struct module *xcl_owner; |
36 | const struct svc_xprt_ops *xcl_ops; |
37 | struct list_head xcl_list; |
38 | u32 xcl_max_payload; |
39 | int xcl_ident; |
40 | }; |
41 | |
42 | /* |
43 | * This is embedded in an object that wants a callback before deleting |
44 | * an xprt; intended for use by NFSv4.1, which needs to know when a |
45 | * client's tcp connection (and hence possibly a backchannel) goes away. |
46 | */ |
47 | struct svc_xpt_user { |
48 | struct list_head list; |
49 | void (*callback)(struct svc_xpt_user *); |
50 | }; |
51 | |
52 | struct svc_xprt { |
53 | struct svc_xprt_class *xpt_class; |
54 | const struct svc_xprt_ops *xpt_ops; |
55 | struct kref xpt_ref; |
56 | struct list_head xpt_list; |
57 | struct lwq_node xpt_ready; |
58 | unsigned long xpt_flags; |
59 | |
60 | struct svc_serv *xpt_server; /* service for transport */ |
61 | atomic_t xpt_reserved; /* space on outq that is rsvd */ |
62 | atomic_t xpt_nr_rqsts; /* Number of requests */ |
63 | struct mutex xpt_mutex; /* to serialize sending data */ |
64 | spinlock_t xpt_lock; /* protects sk_deferred |
65 | * and xpt_auth_cache */ |
66 | void *xpt_auth_cache;/* auth cache */ |
67 | struct list_head xpt_deferred; /* deferred requests that need |
68 | * to be revisted */ |
69 | struct sockaddr_storage xpt_local; /* local address */ |
70 | size_t xpt_locallen; /* length of address */ |
71 | struct sockaddr_storage xpt_remote; /* remote peer's address */ |
72 | size_t xpt_remotelen; /* length of address */ |
73 | char xpt_remotebuf[INET6_ADDRSTRLEN + 10]; |
74 | struct list_head xpt_users; /* callbacks on free */ |
75 | |
76 | struct net *xpt_net; |
77 | netns_tracker ns_tracker; |
78 | const struct cred *xpt_cred; |
79 | struct rpc_xprt *xpt_bc_xprt; /* NFSv4.1 backchannel */ |
80 | struct rpc_xprt_switch *xpt_bc_xps; /* NFSv4.1 backchannel */ |
81 | }; |
82 | |
83 | /* flag bits for xpt_flags */ |
84 | enum { |
85 | XPT_BUSY, /* enqueued/receiving */ |
86 | XPT_CONN, /* conn pending */ |
87 | XPT_CLOSE, /* dead or dying */ |
88 | XPT_DATA, /* data pending */ |
89 | XPT_TEMP, /* connected transport */ |
90 | XPT_DEAD, /* transport closed */ |
91 | XPT_CHNGBUF, /* need to change snd/rcv buf sizes */ |
92 | XPT_DEFERRED, /* deferred request pending */ |
93 | XPT_OLD, /* used for xprt aging mark+sweep */ |
94 | XPT_LISTENER, /* listening endpoint */ |
95 | XPT_CACHE_AUTH, /* cache auth info */ |
96 | XPT_LOCAL, /* connection from loopback interface */ |
97 | XPT_KILL_TEMP, /* call xpo_kill_temp_xprt before closing */ |
98 | XPT_CONG_CTRL, /* has congestion control */ |
99 | XPT_HANDSHAKE, /* xprt requests a handshake */ |
100 | XPT_TLS_SESSION, /* transport-layer security established */ |
101 | XPT_PEER_AUTH, /* peer has been authenticated */ |
102 | }; |
103 | |
104 | static inline void unregister_xpt_user(struct svc_xprt *xpt, struct svc_xpt_user *u) |
105 | { |
106 | spin_lock(lock: &xpt->xpt_lock); |
107 | list_del_init(entry: &u->list); |
108 | spin_unlock(lock: &xpt->xpt_lock); |
109 | } |
110 | |
111 | static inline int register_xpt_user(struct svc_xprt *xpt, struct svc_xpt_user *u) |
112 | { |
113 | spin_lock(lock: &xpt->xpt_lock); |
114 | if (test_bit(XPT_CLOSE, &xpt->xpt_flags)) { |
115 | /* |
116 | * The connection is about to be deleted soon (or, |
117 | * worse, may already be deleted--in which case we've |
118 | * already notified the xpt_users). |
119 | */ |
120 | spin_unlock(lock: &xpt->xpt_lock); |
121 | return -ENOTCONN; |
122 | } |
123 | list_add(new: &u->list, head: &xpt->xpt_users); |
124 | spin_unlock(lock: &xpt->xpt_lock); |
125 | return 0; |
126 | } |
127 | |
128 | static inline bool svc_xprt_is_dead(const struct svc_xprt *xprt) |
129 | { |
130 | return (test_bit(XPT_DEAD, &xprt->xpt_flags) != 0) || |
131 | (test_bit(XPT_CLOSE, &xprt->xpt_flags) != 0); |
132 | } |
133 | |
134 | int svc_reg_xprt_class(struct svc_xprt_class *); |
135 | void svc_unreg_xprt_class(struct svc_xprt_class *); |
136 | void svc_xprt_init(struct net *, struct svc_xprt_class *, struct svc_xprt *, |
137 | struct svc_serv *); |
138 | int svc_xprt_create(struct svc_serv *serv, const char *xprt_name, |
139 | struct net *net, const int family, |
140 | const unsigned short port, int flags, |
141 | const struct cred *cred); |
142 | void svc_xprt_destroy_all(struct svc_serv *serv, struct net *net); |
143 | void svc_xprt_received(struct svc_xprt *xprt); |
144 | void svc_xprt_enqueue(struct svc_xprt *xprt); |
145 | void svc_xprt_put(struct svc_xprt *xprt); |
146 | void svc_xprt_copy_addrs(struct svc_rqst *rqstp, struct svc_xprt *xprt); |
147 | void svc_xprt_close(struct svc_xprt *xprt); |
148 | int svc_port_is_privileged(struct sockaddr *sin); |
149 | int svc_print_xprts(char *buf, int maxlen); |
150 | struct svc_xprt *svc_find_xprt(struct svc_serv *serv, const char *xcl_name, |
151 | struct net *net, const sa_family_t af, |
152 | const unsigned short port); |
153 | int svc_xprt_names(struct svc_serv *serv, char *buf, const int buflen); |
154 | void svc_add_new_perm_xprt(struct svc_serv *serv, struct svc_xprt *xprt); |
155 | void svc_age_temp_xprts_now(struct svc_serv *, struct sockaddr *); |
156 | void svc_xprt_deferred_close(struct svc_xprt *xprt); |
157 | |
158 | static inline void svc_xprt_get(struct svc_xprt *xprt) |
159 | { |
160 | kref_get(kref: &xprt->xpt_ref); |
161 | } |
162 | static inline void svc_xprt_set_local(struct svc_xprt *xprt, |
163 | const struct sockaddr *sa, |
164 | const size_t salen) |
165 | { |
166 | memcpy(&xprt->xpt_local, sa, salen); |
167 | xprt->xpt_locallen = salen; |
168 | } |
169 | static inline void svc_xprt_set_remote(struct svc_xprt *xprt, |
170 | const struct sockaddr *sa, |
171 | const size_t salen) |
172 | { |
173 | memcpy(&xprt->xpt_remote, sa, salen); |
174 | xprt->xpt_remotelen = salen; |
175 | snprintf(buf: xprt->xpt_remotebuf, size: sizeof(xprt->xpt_remotebuf) - 1, |
176 | fmt: "%pISpc" , sa); |
177 | } |
178 | |
179 | static inline unsigned short svc_addr_port(const struct sockaddr *sa) |
180 | { |
181 | const struct sockaddr_in *sin = (const struct sockaddr_in *)sa; |
182 | const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa; |
183 | |
184 | switch (sa->sa_family) { |
185 | case AF_INET: |
186 | return ntohs(sin->sin_port); |
187 | case AF_INET6: |
188 | return ntohs(sin6->sin6_port); |
189 | } |
190 | |
191 | return 0; |
192 | } |
193 | |
194 | static inline size_t svc_addr_len(const struct sockaddr *sa) |
195 | { |
196 | switch (sa->sa_family) { |
197 | case AF_INET: |
198 | return sizeof(struct sockaddr_in); |
199 | case AF_INET6: |
200 | return sizeof(struct sockaddr_in6); |
201 | } |
202 | BUG(); |
203 | } |
204 | |
205 | static inline unsigned short svc_xprt_local_port(const struct svc_xprt *xprt) |
206 | { |
207 | return svc_addr_port(sa: (const struct sockaddr *)&xprt->xpt_local); |
208 | } |
209 | |
210 | static inline unsigned short svc_xprt_remote_port(const struct svc_xprt *xprt) |
211 | { |
212 | return svc_addr_port(sa: (const struct sockaddr *)&xprt->xpt_remote); |
213 | } |
214 | |
215 | static inline char *__svc_print_addr(const struct sockaddr *addr, |
216 | char *buf, const size_t len) |
217 | { |
218 | const struct sockaddr_in *sin = (const struct sockaddr_in *)addr; |
219 | const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)addr; |
220 | |
221 | switch (addr->sa_family) { |
222 | case AF_INET: |
223 | snprintf(buf, size: len, fmt: "%pI4, port=%u" , &sin->sin_addr, |
224 | ntohs(sin->sin_port)); |
225 | break; |
226 | |
227 | case AF_INET6: |
228 | snprintf(buf, size: len, fmt: "%pI6, port=%u" , |
229 | &sin6->sin6_addr, |
230 | ntohs(sin6->sin6_port)); |
231 | break; |
232 | |
233 | default: |
234 | snprintf(buf, size: len, fmt: "unknown address type: %d" , addr->sa_family); |
235 | break; |
236 | } |
237 | |
238 | return buf; |
239 | } |
240 | #endif /* SUNRPC_SVC_XPRT_H */ |
241 | |