File: | rpc/rpc-lib/src/rpcsvc.c |
Location: | line 1346, column 17 |
Description: | Access to field 'prognum' results in a dereference of a null pointer (loaded from variable 'program') |
1 | /* | |||||
2 | Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> | |||||
3 | This file is part of GlusterFS. | |||||
4 | ||||||
5 | This file is licensed to you under your choice of the GNU Lesser | |||||
6 | General Public License, version 3 or any later version (LGPLv3 or | |||||
7 | later), or the GNU General Public License, version 2 (GPLv2), in all | |||||
8 | cases as published by the Free Software Foundation. | |||||
9 | */ | |||||
10 | ||||||
11 | #ifndef _CONFIG_H | |||||
12 | #define _CONFIG_H | |||||
13 | #include "config.h" | |||||
14 | #endif | |||||
15 | ||||||
16 | #include "rpcsvc.h" | |||||
17 | #include "rpc-transport.h" | |||||
18 | #include "dict.h" | |||||
19 | #include "logging.h" | |||||
20 | #include "byte-order.h" | |||||
21 | #include "common-utils.h" | |||||
22 | #include "compat-errno.h" | |||||
23 | #include "list.h" | |||||
24 | #include "xdr-rpc.h" | |||||
25 | #include "iobuf.h" | |||||
26 | #include "globals.h" | |||||
27 | #include "xdr-common.h" | |||||
28 | #include "xdr-generic.h" | |||||
29 | #include "rpc-common-xdr.h" | |||||
30 | #include "syncop.h" | |||||
31 | ||||||
32 | #include <errno(*__errno_location ()).h> | |||||
33 | #include <pthread.h> | |||||
34 | #include <stdlib.h> | |||||
35 | #include <rpc/rpc.h> | |||||
36 | #include <rpc/pmap_clnt.h> | |||||
37 | #include <arpa/inet.h> | |||||
38 | #include <rpc/xdr.h> | |||||
39 | #include <fnmatch.h> | |||||
40 | #include <stdarg.h> | |||||
41 | #include <stdio.h> | |||||
42 | ||||||
43 | #include "xdr-rpcclnt.h" | |||||
44 | ||||||
45 | #define ACL_PROGRAM100227 100227 | |||||
46 | ||||||
47 | struct rpcsvc_program gluster_dump_prog; | |||||
48 | ||||||
49 | #define rpcsvc_alloc_request(svc, request)do { request = (rpcsvc_request_t *) mem_get ((svc)->rxpool ); memset (request, 0, sizeof (rpcsvc_request_t)); } while (0 ) \ | |||||
50 | do { \ | |||||
51 | request = (rpcsvc_request_t *) mem_get ((svc)->rxpool); \ | |||||
52 | memset (request, 0, sizeof (rpcsvc_request_t)); \ | |||||
53 | } while (0) | |||||
54 | ||||||
55 | rpcsvc_listener_t * | |||||
56 | rpcsvc_get_listener (rpcsvc_t *svc, uint16_t port, rpc_transport_t *trans); | |||||
57 | ||||||
58 | int | |||||
59 | rpcsvc_notify (rpc_transport_t *trans, void *mydata, | |||||
60 | rpc_transport_event_t event, void *data, ...); | |||||
61 | ||||||
62 | rpcsvc_notify_wrapper_t * | |||||
63 | rpcsvc_notify_wrapper_alloc (void) | |||||
64 | { | |||||
65 | rpcsvc_notify_wrapper_t *wrapper = NULL((void*)0); | |||||
66 | ||||||
67 | wrapper = GF_CALLOC (1, sizeof (*wrapper), gf_common_mt_rpcsvc_wrapper_t)__gf_calloc (1, sizeof (*wrapper), gf_common_mt_rpcsvc_wrapper_t ); | |||||
68 | if (!wrapper) { | |||||
69 | goto out; | |||||
70 | } | |||||
71 | ||||||
72 | INIT_LIST_HEAD (&wrapper->list)do { (&wrapper->list)->next = (&wrapper->list )->prev = &wrapper->list; } while (0); | |||||
73 | out: | |||||
74 | return wrapper; | |||||
75 | } | |||||
76 | ||||||
77 | ||||||
78 | void | |||||
79 | rpcsvc_listener_destroy (rpcsvc_listener_t *listener) | |||||
80 | { | |||||
81 | rpcsvc_t *svc = NULL((void*)0); | |||||
82 | ||||||
83 | if (!listener) { | |||||
84 | goto out; | |||||
85 | } | |||||
86 | ||||||
87 | svc = listener->svc; | |||||
88 | if (!svc) { | |||||
89 | goto listener_free; | |||||
90 | } | |||||
91 | ||||||
92 | pthread_mutex_lock (&svc->rpclock); | |||||
93 | { | |||||
94 | list_del_init (&listener->list); | |||||
95 | } | |||||
96 | pthread_mutex_unlock (&svc->rpclock); | |||||
97 | ||||||
98 | listener_free: | |||||
99 | GF_FREE (listener)__gf_free (listener); | |||||
100 | out: | |||||
101 | return; | |||||
102 | } | |||||
103 | ||||||
104 | rpcsvc_vector_sizer | |||||
105 | rpcsvc_get_program_vector_sizer (rpcsvc_t *svc, uint32_t prognum, | |||||
106 | uint32_t progver, uint32_t procnum) | |||||
107 | { | |||||
108 | rpcsvc_program_t *program = NULL((void*)0); | |||||
109 | char found = 0; | |||||
110 | ||||||
111 | if (!svc) | |||||
112 | return NULL((void*)0); | |||||
113 | ||||||
114 | pthread_mutex_lock (&svc->rpclock); | |||||
115 | { | |||||
116 | list_for_each_entry (program, &svc->programs, program)for (program = ((typeof(*program) *)((char *)((&svc->programs )->next)-(unsigned long)(&((typeof(*program) *)0)-> program))); &program->program != (&svc->programs ); program = ((typeof(*program) *)((char *)(program->program .next)-(unsigned long)(&((typeof(*program) *)0)->program )))) { | |||||
117 | if ((program->prognum == prognum) | |||||
118 | && (program->progver == progver)) { | |||||
119 | found = 1; | |||||
120 | break; | |||||
121 | } | |||||
122 | } | |||||
123 | } | |||||
124 | pthread_mutex_unlock (&svc->rpclock); | |||||
125 | ||||||
126 | if (found) | |||||
127 | return program->actors[procnum].vector_sizer; | |||||
128 | else | |||||
129 | return NULL((void*)0); | |||||
130 | } | |||||
131 | ||||||
132 | /* This needs to change to returning errors, since | |||||
133 | * we need to return RPC specific error messages when some | |||||
134 | * of the pointers below are NULL. | |||||
135 | */ | |||||
136 | rpcsvc_actor_t * | |||||
137 | rpcsvc_program_actor (rpcsvc_request_t *req) | |||||
138 | { | |||||
139 | rpcsvc_program_t *program = NULL((void*)0); | |||||
140 | int err = SYSTEM_ERR; | |||||
141 | rpcsvc_actor_t *actor = NULL((void*)0); | |||||
142 | rpcsvc_t *svc = NULL((void*)0); | |||||
143 | char found = 0; | |||||
144 | ||||||
145 | if (!req) | |||||
146 | goto err; | |||||
147 | ||||||
148 | svc = req->svc; | |||||
149 | pthread_mutex_lock (&svc->rpclock); | |||||
150 | { | |||||
151 | list_for_each_entry (program, &svc->programs, program)for (program = ((typeof(*program) *)((char *)((&svc->programs )->next)-(unsigned long)(&((typeof(*program) *)0)-> program))); &program->program != (&svc->programs ); program = ((typeof(*program) *)((char *)(program->program .next)-(unsigned long)(&((typeof(*program) *)0)->program )))) { | |||||
152 | if (program->prognum == req->prognum) { | |||||
153 | err = PROG_MISMATCH; | |||||
154 | } | |||||
155 | ||||||
156 | if ((program->prognum == req->prognum) | |||||
157 | && (program->progver == req->progver)) { | |||||
158 | found = 1; | |||||
159 | break; | |||||
160 | } | |||||
161 | } | |||||
162 | } | |||||
163 | pthread_mutex_unlock (&svc->rpclock); | |||||
164 | ||||||
165 | if (!found) { | |||||
166 | if (err != PROG_MISMATCH) { | |||||
167 | /* log in DEBUG when nfs clients try to see if | |||||
168 | * ACL requests are accepted by nfs server | |||||
169 | */ | |||||
170 | gf_log (GF_RPCSVC, (req->prognum == ACL_PROGRAM) ?do { do { if (0) printf ("RPC program not available (req %u %u)" , req->prognum, req->progver); } while (0); _gf_log ("rpc-service" , "rpcsvc.c", __FUNCTION__, 173, (req->prognum == 100227) ? GF_LOG_DEBUG : GF_LOG_WARNING, "RPC program not available (req %u %u)" , req->prognum, req->progver); } while (0) | |||||
171 | GF_LOG_DEBUG : GF_LOG_WARNING,do { do { if (0) printf ("RPC program not available (req %u %u)" , req->prognum, req->progver); } while (0); _gf_log ("rpc-service" , "rpcsvc.c", __FUNCTION__, 173, (req->prognum == 100227) ? GF_LOG_DEBUG : GF_LOG_WARNING, "RPC program not available (req %u %u)" , req->prognum, req->progver); } while (0) | |||||
172 | "RPC program not available (req %u %u)",do { do { if (0) printf ("RPC program not available (req %u %u)" , req->prognum, req->progver); } while (0); _gf_log ("rpc-service" , "rpcsvc.c", __FUNCTION__, 173, (req->prognum == 100227) ? GF_LOG_DEBUG : GF_LOG_WARNING, "RPC program not available (req %u %u)" , req->prognum, req->progver); } while (0) | |||||
173 | req->prognum, req->progver)do { do { if (0) printf ("RPC program not available (req %u %u)" , req->prognum, req->progver); } while (0); _gf_log ("rpc-service" , "rpcsvc.c", __FUNCTION__, 173, (req->prognum == 100227) ? GF_LOG_DEBUG : GF_LOG_WARNING, "RPC program not available (req %u %u)" , req->prognum, req->progver); } while (0); | |||||
174 | err = PROG_UNAVAIL; | |||||
175 | goto err; | |||||
176 | } | |||||
177 | ||||||
178 | gf_log (GF_RPCSVC, GF_LOG_WARNING,do { do { if (0) printf ("RPC program version not available (req %u %u)" , req->prognum, req->progver); } while (0); _gf_log ("rpc-service" , "rpcsvc.c", __FUNCTION__, 180, GF_LOG_WARNING, "RPC program version not available (req %u %u)" , req->prognum, req->progver); } while (0) | |||||
179 | "RPC program version not available (req %u %u)",do { do { if (0) printf ("RPC program version not available (req %u %u)" , req->prognum, req->progver); } while (0); _gf_log ("rpc-service" , "rpcsvc.c", __FUNCTION__, 180, GF_LOG_WARNING, "RPC program version not available (req %u %u)" , req->prognum, req->progver); } while (0) | |||||
180 | req->prognum, req->progver)do { do { if (0) printf ("RPC program version not available (req %u %u)" , req->prognum, req->progver); } while (0); _gf_log ("rpc-service" , "rpcsvc.c", __FUNCTION__, 180, GF_LOG_WARNING, "RPC program version not available (req %u %u)" , req->prognum, req->progver); } while (0); | |||||
181 | goto err; | |||||
182 | } | |||||
183 | req->prog = program; | |||||
184 | if (!program->actors) { | |||||
185 | gf_log (GF_RPCSVC, GF_LOG_WARNING,do { do { if (0) printf ("RPC Actor not found for program %s %d" , program->progname, program->prognum); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 187, GF_LOG_WARNING , "RPC Actor not found for program %s %d", program->progname , program->prognum); } while (0) | |||||
186 | "RPC Actor not found for program %s %d",do { do { if (0) printf ("RPC Actor not found for program %s %d" , program->progname, program->prognum); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 187, GF_LOG_WARNING , "RPC Actor not found for program %s %d", program->progname , program->prognum); } while (0) | |||||
187 | program->progname, program->prognum)do { do { if (0) printf ("RPC Actor not found for program %s %d" , program->progname, program->prognum); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 187, GF_LOG_WARNING , "RPC Actor not found for program %s %d", program->progname , program->prognum); } while (0); | |||||
188 | err = SYSTEM_ERR; | |||||
189 | goto err; | |||||
190 | } | |||||
191 | ||||||
192 | if ((req->procnum < 0) || (req->procnum >= program->numactors)) { | |||||
193 | gf_log (GF_RPCSVC, GF_LOG_ERROR, "RPC Program procedure not"do { do { if (0) printf ("RPC Program procedure not" " available for procedure %d in %s" , req->procnum, program->progname); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 195, GF_LOG_ERROR, "RPC Program procedure not" " available for procedure %d in %s" , req->procnum, program->progname); } while (0) | |||||
194 | " available for procedure %d in %s", req->procnum,do { do { if (0) printf ("RPC Program procedure not" " available for procedure %d in %s" , req->procnum, program->progname); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 195, GF_LOG_ERROR, "RPC Program procedure not" " available for procedure %d in %s" , req->procnum, program->progname); } while (0) | |||||
195 | program->progname)do { do { if (0) printf ("RPC Program procedure not" " available for procedure %d in %s" , req->procnum, program->progname); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 195, GF_LOG_ERROR, "RPC Program procedure not" " available for procedure %d in %s" , req->procnum, program->progname); } while (0); | |||||
196 | err = PROC_UNAVAIL; | |||||
197 | goto err; | |||||
198 | } | |||||
199 | ||||||
200 | actor = &program->actors[req->procnum]; | |||||
201 | if (!actor->actor) { | |||||
202 | gf_log (GF_RPCSVC, GF_LOG_ERROR, "RPC Program procedure not"do { do { if (0) printf ("RPC Program procedure not" " available for procedure %d in %s" , req->procnum, program->progname); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 204, GF_LOG_ERROR, "RPC Program procedure not" " available for procedure %d in %s" , req->procnum, program->progname); } while (0) | |||||
203 | " available for procedure %d in %s", req->procnum,do { do { if (0) printf ("RPC Program procedure not" " available for procedure %d in %s" , req->procnum, program->progname); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 204, GF_LOG_ERROR, "RPC Program procedure not" " available for procedure %d in %s" , req->procnum, program->progname); } while (0) | |||||
204 | program->progname)do { do { if (0) printf ("RPC Program procedure not" " available for procedure %d in %s" , req->procnum, program->progname); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 204, GF_LOG_ERROR, "RPC Program procedure not" " available for procedure %d in %s" , req->procnum, program->progname); } while (0); | |||||
205 | err = PROC_UNAVAIL; | |||||
206 | actor = NULL((void*)0); | |||||
207 | goto err; | |||||
208 | } | |||||
209 | ||||||
210 | req->synctask = program->synctask; | |||||
211 | ||||||
212 | err = SUCCESS; | |||||
213 | gf_log (GF_RPCSVC, GF_LOG_TRACE, "Actor found: %s - %s",do { do { if (0) printf ("Actor found: %s - %s", program-> progname, actor->procname); } while (0); _gf_log ("rpc-service" , "rpcsvc.c", __FUNCTION__, 214, GF_LOG_TRACE, "Actor found: %s - %s" , program->progname, actor->procname); } while (0) | |||||
214 | program->progname, actor->procname)do { do { if (0) printf ("Actor found: %s - %s", program-> progname, actor->procname); } while (0); _gf_log ("rpc-service" , "rpcsvc.c", __FUNCTION__, 214, GF_LOG_TRACE, "Actor found: %s - %s" , program->progname, actor->procname); } while (0); | |||||
215 | err: | |||||
216 | if (req) | |||||
217 | req->rpc_err = err; | |||||
218 | ||||||
219 | return actor; | |||||
220 | } | |||||
221 | ||||||
222 | ||||||
223 | /* this procedure can only pass 4 arguments to registered notifyfn. To send more | |||||
224 | * arguments call wrapper->notify directly. | |||||
225 | */ | |||||
226 | static inline void | |||||
227 | rpcsvc_program_notify (rpcsvc_listener_t *listener, rpcsvc_event_t event, | |||||
228 | void *data) | |||||
229 | { | |||||
230 | rpcsvc_notify_wrapper_t *wrapper = NULL((void*)0); | |||||
231 | ||||||
232 | if (!listener) { | |||||
233 | goto out; | |||||
234 | } | |||||
235 | ||||||
236 | list_for_each_entry (wrapper, &listener->svc->notify, list)for (wrapper = ((typeof(*wrapper) *)((char *)((&listener-> svc->notify)->next)-(unsigned long)(&((typeof(*wrapper ) *)0)->list))); &wrapper->list != (&listener-> svc->notify); wrapper = ((typeof(*wrapper) *)((char *)(wrapper ->list.next)-(unsigned long)(&((typeof(*wrapper) *)0)-> list)))) { | |||||
237 | if (wrapper->notify) { | |||||
238 | wrapper->notify (listener->svc, | |||||
239 | wrapper->data, | |||||
240 | event, data); | |||||
241 | } | |||||
242 | } | |||||
243 | ||||||
244 | out: | |||||
245 | return; | |||||
246 | } | |||||
247 | ||||||
248 | ||||||
249 | static inline int | |||||
250 | rpcsvc_accept (rpcsvc_t *svc, rpc_transport_t *listen_trans, | |||||
251 | rpc_transport_t *new_trans) | |||||
252 | { | |||||
253 | rpcsvc_listener_t *listener = NULL((void*)0); | |||||
254 | int32_t ret = -1; | |||||
255 | ||||||
256 | listener = rpcsvc_get_listener (svc, -1, listen_trans); | |||||
257 | if (listener == NULL((void*)0)) { | |||||
258 | goto out; | |||||
259 | } | |||||
260 | ||||||
261 | rpcsvc_program_notify (listener, RPCSVC_EVENT_ACCEPT, new_trans); | |||||
262 | ret = 0; | |||||
263 | out: | |||||
264 | return ret; | |||||
265 | } | |||||
266 | ||||||
267 | ||||||
268 | void | |||||
269 | rpcsvc_request_destroy (rpcsvc_request_t *req) | |||||
270 | { | |||||
271 | if (!req) { | |||||
272 | goto out; | |||||
273 | } | |||||
274 | ||||||
275 | if (req->iobref) { | |||||
276 | iobref_unref (req->iobref); | |||||
277 | } | |||||
278 | ||||||
279 | if (req->hdr_iobuf) | |||||
280 | iobuf_unref (req->hdr_iobuf); | |||||
281 | ||||||
282 | rpc_transport_unref (req->trans); | |||||
283 | ||||||
284 | mem_put (req); | |||||
285 | ||||||
286 | out: | |||||
287 | return; | |||||
288 | } | |||||
289 | ||||||
290 | ||||||
291 | rpcsvc_request_t * | |||||
292 | rpcsvc_request_init (rpcsvc_t *svc, rpc_transport_t *trans, | |||||
293 | struct rpc_msg *callmsg, | |||||
294 | struct iovec progmsg, rpc_transport_pollin_t *msg, | |||||
295 | rpcsvc_request_t *req) | |||||
296 | { | |||||
297 | int i = 0; | |||||
298 | ||||||
299 | if ((!trans) || (!callmsg)|| (!req) || (!msg)) | |||||
300 | return NULL((void*)0); | |||||
301 | ||||||
302 | /* We start a RPC request as always denied. */ | |||||
303 | req->rpc_status = MSG_DENIED; | |||||
304 | req->xid = rpc_call_xid (callmsg)((callmsg)->rm_xid); | |||||
305 | req->prognum = rpc_call_program (callmsg)((callmsg)->ru.RM_cmb.cb_prog); | |||||
306 | req->progver = rpc_call_progver (callmsg)((callmsg)->ru.RM_cmb.cb_vers); | |||||
307 | req->procnum = rpc_call_progproc (callmsg)((callmsg)->ru.RM_cmb.cb_proc); | |||||
308 | req->trans = rpc_transport_ref (trans); | |||||
309 | req->count = msg->count; | |||||
310 | req->msg[0] = progmsg; | |||||
311 | req->iobref = iobref_ref (msg->iobref); | |||||
312 | if (msg->vectored) { | |||||
313 | /* msg->vector[2] is defined in structure. prevent a | |||||
314 | out of bound access */ | |||||
315 | for (i = 1; i < min (msg->count, 2)((msg->count)<(2)?(msg->count):(2)); i++) { | |||||
316 | req->msg[i] = msg->vector[i]; | |||||
317 | } | |||||
318 | } | |||||
319 | ||||||
320 | req->svc = svc; | |||||
321 | req->trans_private = msg->private; | |||||
322 | ||||||
323 | INIT_LIST_HEAD (&req->txlist)do { (&req->txlist)->next = (&req->txlist)-> prev = &req->txlist; } while (0); | |||||
324 | req->payloadsize = 0; | |||||
325 | ||||||
326 | /* By this time, the data bytes for the auth scheme would have already | |||||
327 | * been copied into the required sections of the req structure, | |||||
328 | * we just need to fill in the meta-data about it now. | |||||
329 | */ | |||||
330 | req->cred.flavour = rpc_call_cred_flavour (callmsg)((((&(callmsg)->ru.RM_cmb.cb_cred))->oa_flavor)); | |||||
331 | req->cred.datalen = rpc_call_cred_len (callmsg)((((&(callmsg)->ru.RM_cmb.cb_cred))->oa_length)); | |||||
332 | req->verf.flavour = rpc_call_verf_flavour (callmsg)((((&(callmsg)->ru.RM_cmb.cb_verf))->oa_flavor)); | |||||
333 | req->verf.datalen = rpc_call_verf_len (callmsg)((((&(callmsg)->ru.RM_cmb.cb_verf))->oa_length)); | |||||
334 | ||||||
335 | /* AUTH */ | |||||
336 | rpcsvc_auth_request_init (req); | |||||
337 | return req; | |||||
338 | } | |||||
339 | ||||||
340 | ||||||
341 | rpcsvc_request_t * | |||||
342 | rpcsvc_request_create (rpcsvc_t *svc, rpc_transport_t *trans, | |||||
343 | rpc_transport_pollin_t *msg) | |||||
344 | { | |||||
345 | char *msgbuf = NULL((void*)0); | |||||
346 | struct rpc_msg rpcmsg; | |||||
347 | struct iovec progmsg; /* RPC Program payload */ | |||||
348 | rpcsvc_request_t *req = NULL((void*)0); | |||||
349 | size_t msglen = 0; | |||||
350 | int ret = -1; | |||||
351 | ||||||
352 | if (!svc || !trans) | |||||
353 | return NULL((void*)0); | |||||
354 | ||||||
355 | /* We need to allocate the request before actually calling | |||||
356 | * rpcsvc_request_init on the request so that we, can fill the auth | |||||
357 | * data directly into the request structure from the message iobuf. | |||||
358 | * This avoids a need to keep a temp buffer into which the auth data | |||||
359 | * would've been copied otherwise. | |||||
360 | */ | |||||
361 | rpcsvc_alloc_request (svc, req)do { req = (rpcsvc_request_t *) mem_get ((svc)->rxpool); memset (req, 0, sizeof (rpcsvc_request_t)); } while (0); | |||||
362 | if (!req) { | |||||
363 | goto err; | |||||
364 | } | |||||
365 | ||||||
366 | msgbuf = msg->vector[0].iov_base; | |||||
367 | msglen = msg->vector[0].iov_len; | |||||
368 | ||||||
369 | ret = xdr_to_rpc_call (msgbuf, msglen, &rpcmsg, &progmsg, | |||||
370 | req->cred.authdata,req->verf.authdata); | |||||
371 | ||||||
372 | if (ret == -1) { | |||||
373 | gf_log (GF_RPCSVC, GF_LOG_WARNING, "RPC call decoding failed")do { do { if (0) printf ("RPC call decoding failed"); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 373, GF_LOG_WARNING , "RPC call decoding failed"); } while (0); | |||||
374 | rpcsvc_request_seterr (req, GARBAGE_ARGS)(req)->rpc_err = GARBAGE_ARGS; | |||||
375 | req->trans = rpc_transport_ref (trans); | |||||
376 | req->svc = svc; | |||||
377 | goto err; | |||||
378 | } | |||||
379 | ||||||
380 | ret = -1; | |||||
381 | rpcsvc_request_init (svc, trans, &rpcmsg, progmsg, msg, req); | |||||
382 | ||||||
383 | gf_log (GF_RPCSVC, GF_LOG_TRACE, "received rpc-message (XID: 0x%lx, "do { do { if (0) printf ("received rpc-message (XID: 0x%lx, " "Ver: %ld, Program: %ld, ProgVers: %ld, Proc: %ld) from" " rpc-transport (%s)" , ((&rpcmsg)->rm_xid), ((&rpcmsg)->ru.RM_cmb.cb_rpcvers ), ((&rpcmsg)->ru.RM_cmb.cb_prog), ((&rpcmsg)-> ru.RM_cmb.cb_vers), ((&rpcmsg)->ru.RM_cmb.cb_proc), trans ->name); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__ , 388, GF_LOG_TRACE, "received rpc-message (XID: 0x%lx, " "Ver: %ld, Program: %ld, ProgVers: %ld, Proc: %ld) from" " rpc-transport (%s)", ((&rpcmsg)->rm_xid), ((&rpcmsg )->ru.RM_cmb.cb_rpcvers), ((&rpcmsg)->ru.RM_cmb.cb_prog ), ((&rpcmsg)->ru.RM_cmb.cb_vers), ((&rpcmsg)-> ru.RM_cmb.cb_proc), trans->name); } while (0) | |||||
384 | "Ver: %ld, Program: %ld, ProgVers: %ld, Proc: %ld) from"do { do { if (0) printf ("received rpc-message (XID: 0x%lx, " "Ver: %ld, Program: %ld, ProgVers: %ld, Proc: %ld) from" " rpc-transport (%s)" , ((&rpcmsg)->rm_xid), ((&rpcmsg)->ru.RM_cmb.cb_rpcvers ), ((&rpcmsg)->ru.RM_cmb.cb_prog), ((&rpcmsg)-> ru.RM_cmb.cb_vers), ((&rpcmsg)->ru.RM_cmb.cb_proc), trans ->name); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__ , 388, GF_LOG_TRACE, "received rpc-message (XID: 0x%lx, " "Ver: %ld, Program: %ld, ProgVers: %ld, Proc: %ld) from" " rpc-transport (%s)", ((&rpcmsg)->rm_xid), ((&rpcmsg )->ru.RM_cmb.cb_rpcvers), ((&rpcmsg)->ru.RM_cmb.cb_prog ), ((&rpcmsg)->ru.RM_cmb.cb_vers), ((&rpcmsg)-> ru.RM_cmb.cb_proc), trans->name); } while (0) | |||||
385 | " rpc-transport (%s)", rpc_call_xid (&rpcmsg),do { do { if (0) printf ("received rpc-message (XID: 0x%lx, " "Ver: %ld, Program: %ld, ProgVers: %ld, Proc: %ld) from" " rpc-transport (%s)" , ((&rpcmsg)->rm_xid), ((&rpcmsg)->ru.RM_cmb.cb_rpcvers ), ((&rpcmsg)->ru.RM_cmb.cb_prog), ((&rpcmsg)-> ru.RM_cmb.cb_vers), ((&rpcmsg)->ru.RM_cmb.cb_proc), trans ->name); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__ , 388, GF_LOG_TRACE, "received rpc-message (XID: 0x%lx, " "Ver: %ld, Program: %ld, ProgVers: %ld, Proc: %ld) from" " rpc-transport (%s)", ((&rpcmsg)->rm_xid), ((&rpcmsg )->ru.RM_cmb.cb_rpcvers), ((&rpcmsg)->ru.RM_cmb.cb_prog ), ((&rpcmsg)->ru.RM_cmb.cb_vers), ((&rpcmsg)-> ru.RM_cmb.cb_proc), trans->name); } while (0) | |||||
386 | rpc_call_rpcvers (&rpcmsg), rpc_call_program (&rpcmsg),do { do { if (0) printf ("received rpc-message (XID: 0x%lx, " "Ver: %ld, Program: %ld, ProgVers: %ld, Proc: %ld) from" " rpc-transport (%s)" , ((&rpcmsg)->rm_xid), ((&rpcmsg)->ru.RM_cmb.cb_rpcvers ), ((&rpcmsg)->ru.RM_cmb.cb_prog), ((&rpcmsg)-> ru.RM_cmb.cb_vers), ((&rpcmsg)->ru.RM_cmb.cb_proc), trans ->name); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__ , 388, GF_LOG_TRACE, "received rpc-message (XID: 0x%lx, " "Ver: %ld, Program: %ld, ProgVers: %ld, Proc: %ld) from" " rpc-transport (%s)", ((&rpcmsg)->rm_xid), ((&rpcmsg )->ru.RM_cmb.cb_rpcvers), ((&rpcmsg)->ru.RM_cmb.cb_prog ), ((&rpcmsg)->ru.RM_cmb.cb_vers), ((&rpcmsg)-> ru.RM_cmb.cb_proc), trans->name); } while (0) | |||||
387 | rpc_call_progver (&rpcmsg), rpc_call_progproc (&rpcmsg),do { do { if (0) printf ("received rpc-message (XID: 0x%lx, " "Ver: %ld, Program: %ld, ProgVers: %ld, Proc: %ld) from" " rpc-transport (%s)" , ((&rpcmsg)->rm_xid), ((&rpcmsg)->ru.RM_cmb.cb_rpcvers ), ((&rpcmsg)->ru.RM_cmb.cb_prog), ((&rpcmsg)-> ru.RM_cmb.cb_vers), ((&rpcmsg)->ru.RM_cmb.cb_proc), trans ->name); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__ , 388, GF_LOG_TRACE, "received rpc-message (XID: 0x%lx, " "Ver: %ld, Program: %ld, ProgVers: %ld, Proc: %ld) from" " rpc-transport (%s)", ((&rpcmsg)->rm_xid), ((&rpcmsg )->ru.RM_cmb.cb_rpcvers), ((&rpcmsg)->ru.RM_cmb.cb_prog ), ((&rpcmsg)->ru.RM_cmb.cb_vers), ((&rpcmsg)-> ru.RM_cmb.cb_proc), trans->name); } while (0) | |||||
388 | trans->name)do { do { if (0) printf ("received rpc-message (XID: 0x%lx, " "Ver: %ld, Program: %ld, ProgVers: %ld, Proc: %ld) from" " rpc-transport (%s)" , ((&rpcmsg)->rm_xid), ((&rpcmsg)->ru.RM_cmb.cb_rpcvers ), ((&rpcmsg)->ru.RM_cmb.cb_prog), ((&rpcmsg)-> ru.RM_cmb.cb_vers), ((&rpcmsg)->ru.RM_cmb.cb_proc), trans ->name); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__ , 388, GF_LOG_TRACE, "received rpc-message (XID: 0x%lx, " "Ver: %ld, Program: %ld, ProgVers: %ld, Proc: %ld) from" " rpc-transport (%s)", ((&rpcmsg)->rm_xid), ((&rpcmsg )->ru.RM_cmb.cb_rpcvers), ((&rpcmsg)->ru.RM_cmb.cb_prog ), ((&rpcmsg)->ru.RM_cmb.cb_vers), ((&rpcmsg)-> ru.RM_cmb.cb_proc), trans->name); } while (0); | |||||
389 | ||||||
390 | if (rpc_call_rpcvers (&rpcmsg)((&rpcmsg)->ru.RM_cmb.cb_rpcvers) != 2) { | |||||
391 | /* LOG- TODO: print rpc version, also print the peerinfo | |||||
392 | from transport */ | |||||
393 | gf_log (GF_RPCSVC, GF_LOG_ERROR, "RPC version not supported "do { do { if (0) printf ("RPC version not supported " "(XID: 0x%lx, Ver: %ld, Prog: %ld, ProgVers: %ld, " "Proc: %ld) from trans (%s)", ((&rpcmsg)->rm_xid), (( &rpcmsg)->ru.RM_cmb.cb_rpcvers), ((&rpcmsg)->ru .RM_cmb.cb_prog), ((&rpcmsg)->ru.RM_cmb.cb_vers), ((& rpcmsg)->ru.RM_cmb.cb_proc), trans->name); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 398, GF_LOG_ERROR , "RPC version not supported " "(XID: 0x%lx, Ver: %ld, Prog: %ld, ProgVers: %ld, " "Proc: %ld) from trans (%s)", ((&rpcmsg)->rm_xid), (( &rpcmsg)->ru.RM_cmb.cb_rpcvers), ((&rpcmsg)->ru .RM_cmb.cb_prog), ((&rpcmsg)->ru.RM_cmb.cb_vers), ((& rpcmsg)->ru.RM_cmb.cb_proc), trans->name); } while (0) | |||||
394 | "(XID: 0x%lx, Ver: %ld, Prog: %ld, ProgVers: %ld, "do { do { if (0) printf ("RPC version not supported " "(XID: 0x%lx, Ver: %ld, Prog: %ld, ProgVers: %ld, " "Proc: %ld) from trans (%s)", ((&rpcmsg)->rm_xid), (( &rpcmsg)->ru.RM_cmb.cb_rpcvers), ((&rpcmsg)->ru .RM_cmb.cb_prog), ((&rpcmsg)->ru.RM_cmb.cb_vers), ((& rpcmsg)->ru.RM_cmb.cb_proc), trans->name); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 398, GF_LOG_ERROR , "RPC version not supported " "(XID: 0x%lx, Ver: %ld, Prog: %ld, ProgVers: %ld, " "Proc: %ld) from trans (%s)", ((&rpcmsg)->rm_xid), (( &rpcmsg)->ru.RM_cmb.cb_rpcvers), ((&rpcmsg)->ru .RM_cmb.cb_prog), ((&rpcmsg)->ru.RM_cmb.cb_vers), ((& rpcmsg)->ru.RM_cmb.cb_proc), trans->name); } while (0) | |||||
395 | "Proc: %ld) from trans (%s)", rpc_call_xid (&rpcmsg),do { do { if (0) printf ("RPC version not supported " "(XID: 0x%lx, Ver: %ld, Prog: %ld, ProgVers: %ld, " "Proc: %ld) from trans (%s)", ((&rpcmsg)->rm_xid), (( &rpcmsg)->ru.RM_cmb.cb_rpcvers), ((&rpcmsg)->ru .RM_cmb.cb_prog), ((&rpcmsg)->ru.RM_cmb.cb_vers), ((& rpcmsg)->ru.RM_cmb.cb_proc), trans->name); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 398, GF_LOG_ERROR , "RPC version not supported " "(XID: 0x%lx, Ver: %ld, Prog: %ld, ProgVers: %ld, " "Proc: %ld) from trans (%s)", ((&rpcmsg)->rm_xid), (( &rpcmsg)->ru.RM_cmb.cb_rpcvers), ((&rpcmsg)->ru .RM_cmb.cb_prog), ((&rpcmsg)->ru.RM_cmb.cb_vers), ((& rpcmsg)->ru.RM_cmb.cb_proc), trans->name); } while (0) | |||||
396 | rpc_call_rpcvers (&rpcmsg), rpc_call_program (&rpcmsg),do { do { if (0) printf ("RPC version not supported " "(XID: 0x%lx, Ver: %ld, Prog: %ld, ProgVers: %ld, " "Proc: %ld) from trans (%s)", ((&rpcmsg)->rm_xid), (( &rpcmsg)->ru.RM_cmb.cb_rpcvers), ((&rpcmsg)->ru .RM_cmb.cb_prog), ((&rpcmsg)->ru.RM_cmb.cb_vers), ((& rpcmsg)->ru.RM_cmb.cb_proc), trans->name); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 398, GF_LOG_ERROR , "RPC version not supported " "(XID: 0x%lx, Ver: %ld, Prog: %ld, ProgVers: %ld, " "Proc: %ld) from trans (%s)", ((&rpcmsg)->rm_xid), (( &rpcmsg)->ru.RM_cmb.cb_rpcvers), ((&rpcmsg)->ru .RM_cmb.cb_prog), ((&rpcmsg)->ru.RM_cmb.cb_vers), ((& rpcmsg)->ru.RM_cmb.cb_proc), trans->name); } while (0) | |||||
397 | rpc_call_progver (&rpcmsg), rpc_call_progproc (&rpcmsg),do { do { if (0) printf ("RPC version not supported " "(XID: 0x%lx, Ver: %ld, Prog: %ld, ProgVers: %ld, " "Proc: %ld) from trans (%s)", ((&rpcmsg)->rm_xid), (( &rpcmsg)->ru.RM_cmb.cb_rpcvers), ((&rpcmsg)->ru .RM_cmb.cb_prog), ((&rpcmsg)->ru.RM_cmb.cb_vers), ((& rpcmsg)->ru.RM_cmb.cb_proc), trans->name); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 398, GF_LOG_ERROR , "RPC version not supported " "(XID: 0x%lx, Ver: %ld, Prog: %ld, ProgVers: %ld, " "Proc: %ld) from trans (%s)", ((&rpcmsg)->rm_xid), (( &rpcmsg)->ru.RM_cmb.cb_rpcvers), ((&rpcmsg)->ru .RM_cmb.cb_prog), ((&rpcmsg)->ru.RM_cmb.cb_vers), ((& rpcmsg)->ru.RM_cmb.cb_proc), trans->name); } while (0) | |||||
398 | trans->name)do { do { if (0) printf ("RPC version not supported " "(XID: 0x%lx, Ver: %ld, Prog: %ld, ProgVers: %ld, " "Proc: %ld) from trans (%s)", ((&rpcmsg)->rm_xid), (( &rpcmsg)->ru.RM_cmb.cb_rpcvers), ((&rpcmsg)->ru .RM_cmb.cb_prog), ((&rpcmsg)->ru.RM_cmb.cb_vers), ((& rpcmsg)->ru.RM_cmb.cb_proc), trans->name); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 398, GF_LOG_ERROR , "RPC version not supported " "(XID: 0x%lx, Ver: %ld, Prog: %ld, ProgVers: %ld, " "Proc: %ld) from trans (%s)", ((&rpcmsg)->rm_xid), (( &rpcmsg)->ru.RM_cmb.cb_rpcvers), ((&rpcmsg)->ru .RM_cmb.cb_prog), ((&rpcmsg)->ru.RM_cmb.cb_vers), ((& rpcmsg)->ru.RM_cmb.cb_proc), trans->name); } while (0); | |||||
399 | rpcsvc_request_seterr (req, RPC_MISMATCH)(req)->rpc_err = RPC_MISMATCH; | |||||
400 | goto err; | |||||
401 | } | |||||
402 | ||||||
403 | ret = rpcsvc_authenticate (req); | |||||
404 | if (ret == RPCSVC_AUTH_REJECT2) { | |||||
405 | /* No need to set auth_err, that is the responsibility of | |||||
406 | * the authentication handler since only that know what exact | |||||
407 | * error happened. | |||||
408 | */ | |||||
409 | rpcsvc_request_seterr (req, AUTH_ERROR)(req)->rpc_err = AUTH_ERROR; | |||||
410 | gf_log (GF_RPCSVC, GF_LOG_ERROR, "auth failed on request. "do { do { if (0) printf ("auth failed on request. " "(XID: 0x%lx, Ver: %ld, Prog: %ld, ProgVers: %ld, " "Proc: %ld) from trans (%s)", ((&rpcmsg)->rm_xid), (( &rpcmsg)->ru.RM_cmb.cb_rpcvers), ((&rpcmsg)->ru .RM_cmb.cb_prog), ((&rpcmsg)->ru.RM_cmb.cb_vers), ((& rpcmsg)->ru.RM_cmb.cb_proc), trans->name); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 415, GF_LOG_ERROR , "auth failed on request. " "(XID: 0x%lx, Ver: %ld, Prog: %ld, ProgVers: %ld, " "Proc: %ld) from trans (%s)", ((&rpcmsg)->rm_xid), (( &rpcmsg)->ru.RM_cmb.cb_rpcvers), ((&rpcmsg)->ru .RM_cmb.cb_prog), ((&rpcmsg)->ru.RM_cmb.cb_vers), ((& rpcmsg)->ru.RM_cmb.cb_proc), trans->name); } while (0) | |||||
411 | "(XID: 0x%lx, Ver: %ld, Prog: %ld, ProgVers: %ld, "do { do { if (0) printf ("auth failed on request. " "(XID: 0x%lx, Ver: %ld, Prog: %ld, ProgVers: %ld, " "Proc: %ld) from trans (%s)", ((&rpcmsg)->rm_xid), (( &rpcmsg)->ru.RM_cmb.cb_rpcvers), ((&rpcmsg)->ru .RM_cmb.cb_prog), ((&rpcmsg)->ru.RM_cmb.cb_vers), ((& rpcmsg)->ru.RM_cmb.cb_proc), trans->name); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 415, GF_LOG_ERROR , "auth failed on request. " "(XID: 0x%lx, Ver: %ld, Prog: %ld, ProgVers: %ld, " "Proc: %ld) from trans (%s)", ((&rpcmsg)->rm_xid), (( &rpcmsg)->ru.RM_cmb.cb_rpcvers), ((&rpcmsg)->ru .RM_cmb.cb_prog), ((&rpcmsg)->ru.RM_cmb.cb_vers), ((& rpcmsg)->ru.RM_cmb.cb_proc), trans->name); } while (0) | |||||
412 | "Proc: %ld) from trans (%s)", rpc_call_xid (&rpcmsg),do { do { if (0) printf ("auth failed on request. " "(XID: 0x%lx, Ver: %ld, Prog: %ld, ProgVers: %ld, " "Proc: %ld) from trans (%s)", ((&rpcmsg)->rm_xid), (( &rpcmsg)->ru.RM_cmb.cb_rpcvers), ((&rpcmsg)->ru .RM_cmb.cb_prog), ((&rpcmsg)->ru.RM_cmb.cb_vers), ((& rpcmsg)->ru.RM_cmb.cb_proc), trans->name); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 415, GF_LOG_ERROR , "auth failed on request. " "(XID: 0x%lx, Ver: %ld, Prog: %ld, ProgVers: %ld, " "Proc: %ld) from trans (%s)", ((&rpcmsg)->rm_xid), (( &rpcmsg)->ru.RM_cmb.cb_rpcvers), ((&rpcmsg)->ru .RM_cmb.cb_prog), ((&rpcmsg)->ru.RM_cmb.cb_vers), ((& rpcmsg)->ru.RM_cmb.cb_proc), trans->name); } while (0) | |||||
413 | rpc_call_rpcvers (&rpcmsg), rpc_call_program (&rpcmsg),do { do { if (0) printf ("auth failed on request. " "(XID: 0x%lx, Ver: %ld, Prog: %ld, ProgVers: %ld, " "Proc: %ld) from trans (%s)", ((&rpcmsg)->rm_xid), (( &rpcmsg)->ru.RM_cmb.cb_rpcvers), ((&rpcmsg)->ru .RM_cmb.cb_prog), ((&rpcmsg)->ru.RM_cmb.cb_vers), ((& rpcmsg)->ru.RM_cmb.cb_proc), trans->name); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 415, GF_LOG_ERROR , "auth failed on request. " "(XID: 0x%lx, Ver: %ld, Prog: %ld, ProgVers: %ld, " "Proc: %ld) from trans (%s)", ((&rpcmsg)->rm_xid), (( &rpcmsg)->ru.RM_cmb.cb_rpcvers), ((&rpcmsg)->ru .RM_cmb.cb_prog), ((&rpcmsg)->ru.RM_cmb.cb_vers), ((& rpcmsg)->ru.RM_cmb.cb_proc), trans->name); } while (0) | |||||
414 | rpc_call_progver (&rpcmsg), rpc_call_progproc (&rpcmsg),do { do { if (0) printf ("auth failed on request. " "(XID: 0x%lx, Ver: %ld, Prog: %ld, ProgVers: %ld, " "Proc: %ld) from trans (%s)", ((&rpcmsg)->rm_xid), (( &rpcmsg)->ru.RM_cmb.cb_rpcvers), ((&rpcmsg)->ru .RM_cmb.cb_prog), ((&rpcmsg)->ru.RM_cmb.cb_vers), ((& rpcmsg)->ru.RM_cmb.cb_proc), trans->name); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 415, GF_LOG_ERROR , "auth failed on request. " "(XID: 0x%lx, Ver: %ld, Prog: %ld, ProgVers: %ld, " "Proc: %ld) from trans (%s)", ((&rpcmsg)->rm_xid), (( &rpcmsg)->ru.RM_cmb.cb_rpcvers), ((&rpcmsg)->ru .RM_cmb.cb_prog), ((&rpcmsg)->ru.RM_cmb.cb_vers), ((& rpcmsg)->ru.RM_cmb.cb_proc), trans->name); } while (0) | |||||
415 | trans->name)do { do { if (0) printf ("auth failed on request. " "(XID: 0x%lx, Ver: %ld, Prog: %ld, ProgVers: %ld, " "Proc: %ld) from trans (%s)", ((&rpcmsg)->rm_xid), (( &rpcmsg)->ru.RM_cmb.cb_rpcvers), ((&rpcmsg)->ru .RM_cmb.cb_prog), ((&rpcmsg)->ru.RM_cmb.cb_vers), ((& rpcmsg)->ru.RM_cmb.cb_proc), trans->name); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 415, GF_LOG_ERROR , "auth failed on request. " "(XID: 0x%lx, Ver: %ld, Prog: %ld, ProgVers: %ld, " "Proc: %ld) from trans (%s)", ((&rpcmsg)->rm_xid), (( &rpcmsg)->ru.RM_cmb.cb_rpcvers), ((&rpcmsg)->ru .RM_cmb.cb_prog), ((&rpcmsg)->ru.RM_cmb.cb_vers), ((& rpcmsg)->ru.RM_cmb.cb_proc), trans->name); } while (0); | |||||
416 | ret = -1; | |||||
417 | goto err; | |||||
418 | } | |||||
419 | ||||||
420 | ||||||
421 | /* If the error is not RPC_MISMATCH, we consider the call as accepted | |||||
422 | * since we are not handling authentication failures for now. | |||||
423 | */ | |||||
424 | req->rpc_status = MSG_ACCEPTED; | |||||
425 | ret = 0; | |||||
426 | err: | |||||
427 | if (ret == -1) { | |||||
428 | ret = rpcsvc_error_reply (req); | |||||
429 | if (ret) | |||||
430 | gf_log ("rpcsvc", GF_LOG_WARNING,do { do { if (0) printf ("failed to queue error reply"); } while (0); _gf_log ("rpcsvc", "rpcsvc.c", __FUNCTION__, 431, GF_LOG_WARNING , "failed to queue error reply"); } while (0) | |||||
431 | "failed to queue error reply")do { do { if (0) printf ("failed to queue error reply"); } while (0); _gf_log ("rpcsvc", "rpcsvc.c", __FUNCTION__, 431, GF_LOG_WARNING , "failed to queue error reply"); } while (0); | |||||
432 | req = NULL((void*)0); | |||||
433 | } | |||||
434 | ||||||
435 | return req; | |||||
436 | } | |||||
437 | ||||||
438 | ||||||
439 | int | |||||
440 | rpcsvc_check_and_reply_error (int ret, call_frame_t *frame, void *opaque) | |||||
441 | { | |||||
442 | rpcsvc_request_t *req = NULL((void*)0); | |||||
443 | ||||||
444 | req = opaque; | |||||
445 | ||||||
446 | if (ret) | |||||
447 | gf_log ("rpcsvc", GF_LOG_ERROR,do { do { if (0) printf ("rpc actor failed to complete successfully" ); } while (0); _gf_log ("rpcsvc", "rpcsvc.c", __FUNCTION__, 448 , GF_LOG_ERROR, "rpc actor failed to complete successfully"); } while (0) | |||||
448 | "rpc actor failed to complete successfully")do { do { if (0) printf ("rpc actor failed to complete successfully" ); } while (0); _gf_log ("rpcsvc", "rpcsvc.c", __FUNCTION__, 448 , GF_LOG_ERROR, "rpc actor failed to complete successfully"); } while (0); | |||||
449 | ||||||
450 | if (ret == RPCSVC_ACTOR_ERROR(-1)) { | |||||
451 | ret = rpcsvc_error_reply (req); | |||||
452 | if (ret) | |||||
453 | gf_log ("rpcsvc", GF_LOG_WARNING,do { do { if (0) printf ("failed to queue error reply"); } while (0); _gf_log ("rpcsvc", "rpcsvc.c", __FUNCTION__, 454, GF_LOG_WARNING , "failed to queue error reply"); } while (0) | |||||
454 | "failed to queue error reply")do { do { if (0) printf ("failed to queue error reply"); } while (0); _gf_log ("rpcsvc", "rpcsvc.c", __FUNCTION__, 454, GF_LOG_WARNING , "failed to queue error reply"); } while (0); | |||||
455 | } | |||||
456 | ||||||
457 | return 0; | |||||
458 | } | |||||
459 | ||||||
460 | int | |||||
461 | rpcsvc_handle_rpc_call (rpcsvc_t *svc, rpc_transport_t *trans, | |||||
462 | rpc_transport_pollin_t *msg) | |||||
463 | { | |||||
464 | rpcsvc_actor_t *actor = NULL((void*)0); | |||||
465 | rpcsvc_actor actor_fn = NULL((void*)0); | |||||
466 | rpcsvc_request_t *req = NULL((void*)0); | |||||
467 | int ret = -1; | |||||
468 | uint16_t port = 0; | |||||
469 | gf_boolean_t is_unix = _gf_false; | |||||
470 | gf_boolean_t unprivileged = _gf_false; | |||||
471 | ||||||
472 | if (!trans || !svc) | |||||
473 | return -1; | |||||
474 | ||||||
475 | switch (trans->peerinfo.sockaddr.ss_family) { | |||||
476 | case AF_INET2: | |||||
477 | port = ((struct sockaddr_in *)&trans->peerinfo.sockaddr)->sin_port; | |||||
478 | break; | |||||
479 | ||||||
480 | case AF_INET610: | |||||
481 | port = ((struct sockaddr_in6 *)&trans->peerinfo.sockaddr)->sin6_port; | |||||
482 | break; | |||||
483 | case AF_UNIX1: | |||||
484 | is_unix = _gf_true; | |||||
485 | break; | |||||
486 | default: | |||||
487 | gf_log (GF_RPCSVC, GF_LOG_ERROR,do { do { if (0) printf ("invalid address family (%d)", trans ->peerinfo.sockaddr.ss_family); } while (0); _gf_log ("rpc-service" , "rpcsvc.c", __FUNCTION__, 489, GF_LOG_ERROR, "invalid address family (%d)" , trans->peerinfo.sockaddr.ss_family); } while (0) | |||||
488 | "invalid address family (%d)",do { do { if (0) printf ("invalid address family (%d)", trans ->peerinfo.sockaddr.ss_family); } while (0); _gf_log ("rpc-service" , "rpcsvc.c", __FUNCTION__, 489, GF_LOG_ERROR, "invalid address family (%d)" , trans->peerinfo.sockaddr.ss_family); } while (0) | |||||
489 | trans->peerinfo.sockaddr.ss_family)do { do { if (0) printf ("invalid address family (%d)", trans ->peerinfo.sockaddr.ss_family); } while (0); _gf_log ("rpc-service" , "rpcsvc.c", __FUNCTION__, 489, GF_LOG_ERROR, "invalid address family (%d)" , trans->peerinfo.sockaddr.ss_family); } while (0); | |||||
490 | return -1; | |||||
491 | } | |||||
492 | ||||||
493 | ||||||
494 | ||||||
495 | if (is_unix == _gf_false) { | |||||
496 | port = ntohs (port); | |||||
497 | ||||||
498 | gf_log ("rpcsvc", GF_LOG_TRACE, "Client port: %d", (int)port)do { do { if (0) printf ("Client port: %d", (int)port); } while (0); _gf_log ("rpcsvc", "rpcsvc.c", __FUNCTION__, 498, GF_LOG_TRACE , "Client port: %d", (int)port); } while (0); | |||||
499 | ||||||
500 | if (port > 1024) | |||||
501 | unprivileged = _gf_true; | |||||
502 | } | |||||
503 | ||||||
504 | req = rpcsvc_request_create (svc, trans, msg); | |||||
505 | if (!req) | |||||
506 | goto err; | |||||
507 | ||||||
508 | if (!rpcsvc_request_accepted (req)((req)->rpc_status == MSG_ACCEPTED)) | |||||
509 | goto err_reply; | |||||
510 | ||||||
511 | actor = rpcsvc_program_actor (req); | |||||
512 | if (!actor) | |||||
513 | goto err_reply; | |||||
514 | ||||||
515 | if (0 == svc->allow_insecure && unprivileged && !actor->unprivileged) { | |||||
516 | /* Non-privileged user, fail request */ | |||||
517 | gf_log ("glusterd", GF_LOG_ERROR,do { do { if (0) printf ("Request received from non-" "privileged port. Failing request" ); } while (0); _gf_log ("glusterd", "rpcsvc.c", __FUNCTION__ , 519, GF_LOG_ERROR, "Request received from non-" "privileged port. Failing request" ); } while (0) | |||||
518 | "Request received from non-"do { do { if (0) printf ("Request received from non-" "privileged port. Failing request" ); } while (0); _gf_log ("glusterd", "rpcsvc.c", __FUNCTION__ , 519, GF_LOG_ERROR, "Request received from non-" "privileged port. Failing request" ); } while (0) | |||||
519 | "privileged port. Failing request")do { do { if (0) printf ("Request received from non-" "privileged port. Failing request" ); } while (0); _gf_log ("glusterd", "rpcsvc.c", __FUNCTION__ , 519, GF_LOG_ERROR, "Request received from non-" "privileged port. Failing request" ); } while (0); | |||||
520 | rpcsvc_request_destroy (req); | |||||
521 | return -1; | |||||
522 | } | |||||
523 | ||||||
524 | if (req->rpc_err == SUCCESS) { | |||||
525 | /* Before going to xlator code, set the THIS properly */ | |||||
526 | THIS(*__glusterfs_this_location()) = svc->mydata; | |||||
527 | ||||||
528 | actor_fn = actor->actor; | |||||
529 | ||||||
530 | if (!actor_fn) { | |||||
531 | rpcsvc_request_seterr (req, PROC_UNAVAIL)(req)->rpc_err = PROC_UNAVAIL; | |||||
532 | /* LOG TODO: print more info about procnum, | |||||
533 | prognum etc, also print transport info */ | |||||
534 | gf_log (GF_RPCSVC, GF_LOG_ERROR,do { do { if (0) printf ("No vectored handler present"); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 535, GF_LOG_ERROR , "No vectored handler present"); } while (0) | |||||
535 | "No vectored handler present")do { do { if (0) printf ("No vectored handler present"); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 535, GF_LOG_ERROR , "No vectored handler present"); } while (0); | |||||
536 | ret = RPCSVC_ACTOR_ERROR(-1); | |||||
537 | goto err_reply; | |||||
538 | } | |||||
539 | ||||||
540 | if (req->synctask) { | |||||
541 | if (msg->hdr_iobuf) | |||||
542 | req->hdr_iobuf = iobuf_ref (msg->hdr_iobuf); | |||||
543 | ||||||
544 | ret = synctask_new (THIS(*__glusterfs_this_location())->ctx->env, | |||||
545 | (synctask_fn_t) actor_fn, | |||||
546 | rpcsvc_check_and_reply_error, NULL((void*)0), | |||||
547 | req); | |||||
548 | } else { | |||||
549 | ret = actor_fn (req); | |||||
550 | req->hdr_iobuf = NULL((void*)0); | |||||
551 | } | |||||
552 | } | |||||
553 | ||||||
554 | err_reply: | |||||
555 | ||||||
556 | ret = rpcsvc_check_and_reply_error (ret, NULL((void*)0), req); | |||||
557 | /* No need to propagate error beyond this function since the reply | |||||
558 | * has now been queued. */ | |||||
559 | ret = 0; | |||||
560 | ||||||
561 | err: | |||||
562 | return ret; | |||||
563 | } | |||||
564 | ||||||
565 | ||||||
566 | int | |||||
567 | rpcsvc_handle_disconnect (rpcsvc_t *svc, rpc_transport_t *trans) | |||||
568 | { | |||||
569 | rpcsvc_event_t event; | |||||
570 | rpcsvc_notify_wrapper_t *wrappers = NULL((void*)0), *wrapper; | |||||
571 | int32_t ret = -1, i = 0, wrapper_count = 0; | |||||
572 | rpcsvc_listener_t *listener = NULL((void*)0); | |||||
573 | ||||||
574 | event = (trans->listener == NULL((void*)0)) ? RPCSVC_EVENT_LISTENER_DEAD | |||||
575 | : RPCSVC_EVENT_DISCONNECT; | |||||
576 | ||||||
577 | pthread_mutex_lock (&svc->rpclock); | |||||
578 | { | |||||
579 | if (!svc->notify_count) | |||||
580 | goto unlock; | |||||
581 | ||||||
582 | wrappers = GF_CALLOC (svc->notify_count, sizeof (*wrapper),__gf_calloc (svc->notify_count, sizeof (*wrapper), gf_common_mt_rpcsvc_wrapper_t ) | |||||
583 | gf_common_mt_rpcsvc_wrapper_t)__gf_calloc (svc->notify_count, sizeof (*wrapper), gf_common_mt_rpcsvc_wrapper_t ); | |||||
584 | if (!wrappers) { | |||||
585 | goto unlock; | |||||
586 | } | |||||
587 | ||||||
588 | list_for_each_entry (wrapper, &svc->notify, list)for (wrapper = ((typeof(*wrapper) *)((char *)((&svc->notify )->next)-(unsigned long)(&((typeof(*wrapper) *)0)-> list))); &wrapper->list != (&svc->notify); wrapper = ((typeof(*wrapper) *)((char *)(wrapper->list.next)-(unsigned long)(&((typeof(*wrapper) *)0)->list)))) { | |||||
589 | if (wrapper->notify) { | |||||
590 | wrappers[i++] = *wrapper; | |||||
591 | } | |||||
592 | } | |||||
593 | ||||||
594 | wrapper_count = i; | |||||
595 | } | |||||
596 | unlock: | |||||
597 | pthread_mutex_unlock (&svc->rpclock); | |||||
598 | ||||||
599 | if (wrappers) { | |||||
600 | for (i = 0; i < wrapper_count; i++) { | |||||
601 | wrappers[i].notify (svc, wrappers[i].data, | |||||
602 | event, trans); | |||||
603 | } | |||||
604 | ||||||
605 | GF_FREE (wrappers)__gf_free (wrappers); | |||||
606 | } | |||||
607 | ||||||
608 | if (event == RPCSVC_EVENT_LISTENER_DEAD) { | |||||
609 | listener = rpcsvc_get_listener (svc, -1, trans->listener); | |||||
610 | rpcsvc_listener_destroy (listener); | |||||
611 | } | |||||
612 | ||||||
613 | return ret; | |||||
614 | } | |||||
615 | ||||||
616 | ||||||
617 | int | |||||
618 | rpcsvc_notify (rpc_transport_t *trans, void *mydata, | |||||
619 | rpc_transport_event_t event, void *data, ...) | |||||
620 | { | |||||
621 | int ret = -1; | |||||
622 | rpc_transport_pollin_t *msg = NULL((void*)0); | |||||
623 | rpc_transport_t *new_trans = NULL((void*)0); | |||||
624 | rpcsvc_t *svc = NULL((void*)0); | |||||
625 | rpcsvc_listener_t *listener = NULL((void*)0); | |||||
626 | ||||||
627 | svc = mydata; | |||||
628 | if (svc == NULL((void*)0)) { | |||||
629 | goto out; | |||||
630 | } | |||||
631 | ||||||
632 | switch (event) { | |||||
633 | case RPC_TRANSPORT_ACCEPT: | |||||
634 | new_trans = data; | |||||
635 | ret = rpcsvc_accept (svc, trans, new_trans); | |||||
636 | break; | |||||
637 | ||||||
638 | case RPC_TRANSPORT_DISCONNECT: | |||||
639 | ret = rpcsvc_handle_disconnect (svc, trans); | |||||
640 | break; | |||||
641 | ||||||
642 | case RPC_TRANSPORT_MSG_RECEIVED: | |||||
643 | msg = data; | |||||
644 | ret = rpcsvc_handle_rpc_call (svc, trans, msg); | |||||
645 | break; | |||||
646 | ||||||
647 | case RPC_TRANSPORT_MSG_SENT: | |||||
648 | ret = 0; | |||||
649 | break; | |||||
650 | ||||||
651 | case RPC_TRANSPORT_CONNECT: | |||||
652 | /* do nothing, no need for rpcsvc to handle this, client should | |||||
653 | * handle this event | |||||
654 | */ | |||||
655 | /* print info about transport too : LOG TODO */ | |||||
656 | gf_log ("rpcsvc", GF_LOG_CRITICAL,do { do { if (0) printf ("got CONNECT event, which should have not come" ); } while (0); _gf_log ("rpcsvc", "rpcsvc.c", __FUNCTION__, 657 , GF_LOG_CRITICAL, "got CONNECT event, which should have not come" ); } while (0) | |||||
657 | "got CONNECT event, which should have not come")do { do { if (0) printf ("got CONNECT event, which should have not come" ); } while (0); _gf_log ("rpcsvc", "rpcsvc.c", __FUNCTION__, 657 , GF_LOG_CRITICAL, "got CONNECT event, which should have not come" ); } while (0); | |||||
658 | ret = 0; | |||||
659 | break; | |||||
660 | ||||||
661 | case RPC_TRANSPORT_CLEANUP: | |||||
662 | listener = rpcsvc_get_listener (svc, -1, trans->listener); | |||||
663 | if (listener == NULL((void*)0)) { | |||||
664 | goto out; | |||||
665 | } | |||||
666 | ||||||
667 | rpcsvc_program_notify (listener, RPCSVC_EVENT_TRANSPORT_DESTROY, | |||||
668 | trans); | |||||
669 | ret = 0; | |||||
670 | break; | |||||
671 | ||||||
672 | case RPC_TRANSPORT_MAP_XID_REQUEST: | |||||
673 | /* FIXME: think about this later */ | |||||
674 | gf_log ("rpcsvc", GF_LOG_CRITICAL,do { do { if (0) printf ("got MAP_XID event, which should have not come" ); } while (0); _gf_log ("rpcsvc", "rpcsvc.c", __FUNCTION__, 675 , GF_LOG_CRITICAL, "got MAP_XID event, which should have not come" ); } while (0) | |||||
675 | "got MAP_XID event, which should have not come")do { do { if (0) printf ("got MAP_XID event, which should have not come" ); } while (0); _gf_log ("rpcsvc", "rpcsvc.c", __FUNCTION__, 675 , GF_LOG_CRITICAL, "got MAP_XID event, which should have not come" ); } while (0); | |||||
676 | ret = 0; | |||||
677 | break; | |||||
678 | } | |||||
679 | ||||||
680 | out: | |||||
681 | return ret; | |||||
682 | } | |||||
683 | ||||||
684 | ||||||
685 | /* Given the RPC reply structure and the payload handed by the RPC program, | |||||
686 | * encode the RPC record header into the buffer pointed by recordstart. | |||||
687 | */ | |||||
688 | struct iovec | |||||
689 | rpcsvc_record_build_header (char *recordstart, size_t rlen, | |||||
690 | struct rpc_msg reply, size_t payload) | |||||
691 | { | |||||
692 | struct iovec replyhdr; | |||||
693 | struct iovec txrecord = {0, 0}; | |||||
694 | size_t fraglen = 0; | |||||
695 | int ret = -1; | |||||
696 | ||||||
697 | /* After leaving aside the 4 bytes for the fragment header, lets | |||||
698 | * encode the RPC reply structure into the buffer given to us. | |||||
699 | */ | |||||
700 | ret = rpc_reply_to_xdr (&reply, recordstart, rlen, &replyhdr); | |||||
701 | if (ret == -1) { | |||||
702 | gf_log (GF_RPCSVC, GF_LOG_WARNING, "Failed to create RPC reply")do { do { if (0) printf ("Failed to create RPC reply"); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 702, GF_LOG_WARNING , "Failed to create RPC reply"); } while (0); | |||||
703 | goto err; | |||||
704 | } | |||||
705 | ||||||
706 | fraglen = payload + replyhdr.iov_len; | |||||
707 | gf_log (GF_RPCSVC, GF_LOG_TRACE, "Reply fraglen %zu, payload: %zu, "do { do { if (0) printf ("Reply fraglen %zu, payload: %zu, " "rpc hdr: %zu" , fraglen, payload, replyhdr.iov_len); } while (0); _gf_log ( "rpc-service", "rpcsvc.c", __FUNCTION__, 708, GF_LOG_TRACE, "Reply fraglen %zu, payload: %zu, " "rpc hdr: %zu", fraglen, payload, replyhdr.iov_len); } while (0) | |||||
708 | "rpc hdr: %zu", fraglen, payload, replyhdr.iov_len)do { do { if (0) printf ("Reply fraglen %zu, payload: %zu, " "rpc hdr: %zu" , fraglen, payload, replyhdr.iov_len); } while (0); _gf_log ( "rpc-service", "rpcsvc.c", __FUNCTION__, 708, GF_LOG_TRACE, "Reply fraglen %zu, payload: %zu, " "rpc hdr: %zu", fraglen, payload, replyhdr.iov_len); } while (0); | |||||
709 | ||||||
710 | txrecord.iov_base = recordstart; | |||||
711 | ||||||
712 | /* Remember, this is only the vec for the RPC header and does not | |||||
713 | * include the payload above. We needed the payload only to calculate | |||||
714 | * the size of the full fragment. This size is sent in the fragment | |||||
715 | * header. | |||||
716 | */ | |||||
717 | txrecord.iov_len = replyhdr.iov_len; | |||||
718 | err: | |||||
719 | return txrecord; | |||||
720 | } | |||||
721 | ||||||
722 | static inline int | |||||
723 | rpcsvc_get_callid (rpcsvc_t *rpc) | |||||
724 | { | |||||
725 | return GF_UNIVERSAL_ANSWER42; | |||||
726 | } | |||||
727 | ||||||
728 | int | |||||
729 | rpcsvc_fill_callback (int prognum, int progver, int procnum, int payload, | |||||
730 | uint64_t xid, struct rpc_msg *request) | |||||
731 | { | |||||
732 | int ret = -1; | |||||
733 | ||||||
734 | if (!request) { | |||||
735 | goto out; | |||||
736 | } | |||||
737 | ||||||
738 | memset (request, 0, sizeof (*request)); | |||||
739 | ||||||
740 | request->rm_xid = xid; | |||||
741 | request->rm_direction = CALL; | |||||
742 | ||||||
743 | request->rm_callru.RM_cmb.cb_rpcvers = 2; | |||||
744 | request->rm_callru.RM_cmb.cb_prog = prognum; | |||||
745 | request->rm_callru.RM_cmb.cb_vers = progver; | |||||
746 | request->rm_callru.RM_cmb.cb_proc = procnum; | |||||
747 | ||||||
748 | request->rm_callru.RM_cmb.cb_cred.oa_flavor = AUTH_NONE0; | |||||
749 | request->rm_callru.RM_cmb.cb_cred.oa_base = NULL((void*)0); | |||||
750 | request->rm_callru.RM_cmb.cb_cred.oa_length = 0; | |||||
751 | ||||||
752 | request->rm_callru.RM_cmb.cb_verf.oa_flavor = AUTH_NONE0; | |||||
753 | request->rm_callru.RM_cmb.cb_verf.oa_base = NULL((void*)0); | |||||
754 | request->rm_callru.RM_cmb.cb_verf.oa_length = 0; | |||||
755 | ||||||
756 | ret = 0; | |||||
757 | out: | |||||
758 | return ret; | |||||
759 | } | |||||
760 | ||||||
761 | ||||||
762 | struct iovec | |||||
763 | rpcsvc_callback_build_header (char *recordstart, size_t rlen, | |||||
764 | struct rpc_msg *request, size_t payload) | |||||
765 | { | |||||
766 | struct iovec requesthdr = {0, }; | |||||
767 | struct iovec txrecord = {0, 0}; | |||||
768 | int ret = -1; | |||||
769 | size_t fraglen = 0; | |||||
770 | ||||||
771 | ret = rpc_request_to_xdr (request, recordstart, rlen, &requesthdr); | |||||
772 | if (ret == -1) { | |||||
773 | gf_log ("rpcsvc", GF_LOG_WARNING,do { do { if (0) printf ("Failed to create RPC request"); } while (0); _gf_log ("rpcsvc", "rpcsvc.c", __FUNCTION__, 774, GF_LOG_WARNING , "Failed to create RPC request"); } while (0) | |||||
774 | "Failed to create RPC request")do { do { if (0) printf ("Failed to create RPC request"); } while (0); _gf_log ("rpcsvc", "rpcsvc.c", __FUNCTION__, 774, GF_LOG_WARNING , "Failed to create RPC request"); } while (0); | |||||
775 | goto out; | |||||
776 | } | |||||
777 | ||||||
778 | fraglen = payload + requesthdr.iov_len; | |||||
779 | gf_log ("rpcsvc", GF_LOG_TRACE, "Request fraglen %zu, payload: %zu, "do { do { if (0) printf ("Request fraglen %zu, payload: %zu, " "rpc hdr: %zu", fraglen, payload, requesthdr.iov_len); } while (0); _gf_log ("rpcsvc", "rpcsvc.c", __FUNCTION__, 780, GF_LOG_TRACE , "Request fraglen %zu, payload: %zu, " "rpc hdr: %zu", fraglen , payload, requesthdr.iov_len); } while (0) | |||||
780 | "rpc hdr: %zu", fraglen, payload, requesthdr.iov_len)do { do { if (0) printf ("Request fraglen %zu, payload: %zu, " "rpc hdr: %zu", fraglen, payload, requesthdr.iov_len); } while (0); _gf_log ("rpcsvc", "rpcsvc.c", __FUNCTION__, 780, GF_LOG_TRACE , "Request fraglen %zu, payload: %zu, " "rpc hdr: %zu", fraglen , payload, requesthdr.iov_len); } while (0); | |||||
781 | ||||||
782 | txrecord.iov_base = recordstart; | |||||
783 | ||||||
784 | /* Remember, this is only the vec for the RPC header and does not | |||||
785 | * include the payload above. We needed the payload only to calculate | |||||
786 | * the size of the full fragment. This size is sent in the fragment | |||||
787 | * header. | |||||
788 | */ | |||||
789 | txrecord.iov_len = requesthdr.iov_len; | |||||
790 | ||||||
791 | out: | |||||
792 | return txrecord; | |||||
793 | } | |||||
794 | ||||||
795 | struct iobuf * | |||||
796 | rpcsvc_callback_build_record (rpcsvc_t *rpc, int prognum, int progver, | |||||
797 | int procnum, size_t payload, uint64_t xid, | |||||
798 | struct iovec *recbuf) | |||||
799 | { | |||||
800 | struct rpc_msg request = {0, }; | |||||
801 | struct iobuf *request_iob = NULL((void*)0); | |||||
802 | char *record = NULL((void*)0); | |||||
803 | struct iovec recordhdr = {0, }; | |||||
804 | size_t pagesize = 0; | |||||
805 | size_t xdr_size = 0; | |||||
806 | int ret = -1; | |||||
807 | ||||||
808 | if ((!rpc) || (!recbuf)) { | |||||
809 | goto out; | |||||
810 | } | |||||
811 | ||||||
812 | /* Fill the rpc structure and XDR it into the buffer got above. */ | |||||
813 | ret = rpcsvc_fill_callback (prognum, progver, procnum, payload, xid, | |||||
814 | &request); | |||||
815 | if (ret == -1) { | |||||
816 | gf_log ("rpcsvc", GF_LOG_WARNING, "cannot build a rpc-request "do { do { if (0) printf ("cannot build a rpc-request " "xid (%" "ll" "u"")", xid); } while (0); _gf_log ("rpcsvc", "rpcsvc.c" , __FUNCTION__, 817, GF_LOG_WARNING, "cannot build a rpc-request " "xid (%""ll" "u"")", xid); } while (0) | |||||
817 | "xid (%"PRIu64")", xid)do { do { if (0) printf ("cannot build a rpc-request " "xid (%" "ll" "u"")", xid); } while (0); _gf_log ("rpcsvc", "rpcsvc.c" , __FUNCTION__, 817, GF_LOG_WARNING, "cannot build a rpc-request " "xid (%""ll" "u"")", xid); } while (0); | |||||
818 | goto out; | |||||
819 | } | |||||
820 | ||||||
821 | /* First, try to get a pointer into the buffer which the RPC | |||||
822 | * layer can use. | |||||
823 | */ | |||||
824 | xdr_size = xdr_sizeof ((xdrproc_t)xdr_callmsg, &request); | |||||
825 | ||||||
826 | request_iob = iobuf_get2 (rpc->ctx->iobuf_pool, (xdr_size + payload)); | |||||
827 | if (!request_iob) { | |||||
828 | goto out; | |||||
829 | } | |||||
830 | ||||||
831 | pagesize = iobuf_pagesize (request_iob)(request_iob->iobuf_arena->page_size); | |||||
832 | ||||||
833 | record = iobuf_ptr (request_iob)((request_iob)->ptr); /* Now we have it. */ | |||||
834 | ||||||
835 | recordhdr = rpcsvc_callback_build_header (record, pagesize, &request, | |||||
836 | payload); | |||||
837 | ||||||
838 | if (!recordhdr.iov_base) { | |||||
839 | gf_log ("rpc-clnt", GF_LOG_ERROR, "Failed to build record "do { do { if (0) printf ("Failed to build record " " header") ; } while (0); _gf_log ("rpc-clnt", "rpcsvc.c", __FUNCTION__, 840, GF_LOG_ERROR, "Failed to build record " " header"); } while (0) | |||||
840 | " header")do { do { if (0) printf ("Failed to build record " " header") ; } while (0); _gf_log ("rpc-clnt", "rpcsvc.c", __FUNCTION__, 840, GF_LOG_ERROR, "Failed to build record " " header"); } while (0); | |||||
841 | iobuf_unref (request_iob); | |||||
842 | request_iob = NULL((void*)0); | |||||
843 | recbuf->iov_base = NULL((void*)0); | |||||
844 | goto out; | |||||
845 | } | |||||
846 | ||||||
847 | recbuf->iov_base = recordhdr.iov_base; | |||||
848 | recbuf->iov_len = recordhdr.iov_len; | |||||
849 | ||||||
850 | out: | |||||
851 | return request_iob; | |||||
852 | } | |||||
853 | ||||||
854 | int | |||||
855 | rpcsvc_callback_submit (rpcsvc_t *rpc, rpc_transport_t *trans, | |||||
856 | rpcsvc_cbk_program_t *prog, int procnum, | |||||
857 | struct iovec *proghdr, int proghdrcount) | |||||
858 | { | |||||
859 | struct iobuf *request_iob = NULL((void*)0); | |||||
860 | struct iovec rpchdr = {0,}; | |||||
861 | rpc_transport_req_t req; | |||||
862 | int ret = -1; | |||||
863 | int proglen = 0; | |||||
864 | uint64_t callid = 0; | |||||
865 | ||||||
866 | if (!rpc) { | |||||
867 | goto out; | |||||
868 | } | |||||
869 | ||||||
870 | memset (&req, 0, sizeof (req)); | |||||
871 | ||||||
872 | callid = rpcsvc_get_callid (rpc); | |||||
873 | ||||||
874 | if (proghdr) { | |||||
875 | proglen += iov_length (proghdr, proghdrcount); | |||||
876 | } | |||||
877 | ||||||
878 | request_iob = rpcsvc_callback_build_record (rpc, prog->prognum, | |||||
879 | prog->progver, procnum, | |||||
880 | proglen, callid, | |||||
881 | &rpchdr); | |||||
882 | if (!request_iob) { | |||||
883 | gf_log ("rpcsvc", GF_LOG_WARNING,do { do { if (0) printf ("cannot build rpc-record"); } while ( 0); _gf_log ("rpcsvc", "rpcsvc.c", __FUNCTION__, 884, GF_LOG_WARNING , "cannot build rpc-record"); } while (0) | |||||
884 | "cannot build rpc-record")do { do { if (0) printf ("cannot build rpc-record"); } while ( 0); _gf_log ("rpcsvc", "rpcsvc.c", __FUNCTION__, 884, GF_LOG_WARNING , "cannot build rpc-record"); } while (0); | |||||
885 | goto out; | |||||
886 | } | |||||
887 | ||||||
888 | req.msg.rpchdr = &rpchdr; | |||||
889 | req.msg.rpchdrcount = 1; | |||||
890 | req.msg.proghdr = proghdr; | |||||
891 | req.msg.proghdrcount = proghdrcount; | |||||
892 | ||||||
893 | ret = rpc_transport_submit_request (trans, &req); | |||||
894 | if (ret == -1) { | |||||
895 | gf_log ("rpcsvc", GF_LOG_WARNING,do { do { if (0) printf ("transmission of rpc-request failed" ); } while (0); _gf_log ("rpcsvc", "rpcsvc.c", __FUNCTION__, 896 , GF_LOG_WARNING, "transmission of rpc-request failed"); } while (0) | |||||
896 | "transmission of rpc-request failed")do { do { if (0) printf ("transmission of rpc-request failed" ); } while (0); _gf_log ("rpcsvc", "rpcsvc.c", __FUNCTION__, 896 , GF_LOG_WARNING, "transmission of rpc-request failed"); } while (0); | |||||
897 | goto out; | |||||
898 | } | |||||
899 | ||||||
900 | ret = 0; | |||||
901 | ||||||
902 | out: | |||||
903 | iobuf_unref (request_iob); | |||||
904 | ||||||
905 | return ret; | |||||
906 | } | |||||
907 | ||||||
908 | static inline int | |||||
909 | rpcsvc_transport_submit (rpc_transport_t *trans, struct iovec *hdrvec, | |||||
910 | int hdrcount, struct iovec *proghdr, int proghdrcount, | |||||
911 | struct iovec *progpayload, int progpayloadcount, | |||||
912 | struct iobref *iobref, void *priv) | |||||
913 | { | |||||
914 | int ret = -1; | |||||
915 | rpc_transport_reply_t reply = {{0, }}; | |||||
916 | ||||||
917 | if ((!trans) || (!hdrvec) || (!hdrvec->iov_base)) { | |||||
918 | goto out; | |||||
919 | } | |||||
920 | ||||||
921 | reply.msg.rpchdr = hdrvec; | |||||
922 | reply.msg.rpchdrcount = hdrcount; | |||||
923 | reply.msg.proghdr = proghdr; | |||||
924 | reply.msg.proghdrcount = proghdrcount; | |||||
925 | reply.msg.progpayload = progpayload; | |||||
926 | reply.msg.progpayloadcount = progpayloadcount; | |||||
927 | reply.msg.iobref = iobref; | |||||
928 | reply.private = priv; | |||||
929 | ||||||
930 | ret = rpc_transport_submit_reply (trans, &reply); | |||||
931 | ||||||
932 | out: | |||||
933 | return ret; | |||||
934 | } | |||||
935 | ||||||
936 | ||||||
937 | int | |||||
938 | rpcsvc_fill_reply (rpcsvc_request_t *req, struct rpc_msg *reply) | |||||
939 | { | |||||
940 | int ret = -1; | |||||
941 | rpcsvc_program_t *prog = NULL((void*)0); | |||||
942 | if ((!req) || (!reply)) | |||||
943 | goto out; | |||||
944 | ||||||
945 | ret = 0; | |||||
946 | rpc_fill_empty_reply (reply, req->xid); | |||||
947 | if (req->rpc_status == MSG_DENIED) { | |||||
948 | rpc_fill_denied_reply (reply, req->rpc_err, req->auth_err); | |||||
949 | goto out; | |||||
950 | } | |||||
951 | ||||||
952 | prog = rpcsvc_request_program (req)((rpcsvc_program_t *)((req)->prog)); | |||||
953 | ||||||
954 | if (req->rpc_status == MSG_ACCEPTED) | |||||
955 | rpc_fill_accepted_reply (reply, req->rpc_err, | |||||
956 | (prog) ? prog->proglowvers : 0, | |||||
957 | (prog) ? prog->proghighvers: 0, | |||||
958 | req->verf.flavour, req->verf.datalen, | |||||
959 | req->verf.authdata); | |||||
960 | else | |||||
961 | gf_log (GF_RPCSVC, GF_LOG_ERROR, "Invalid rpc_status value")do { do { if (0) printf ("Invalid rpc_status value"); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 961, GF_LOG_ERROR , "Invalid rpc_status value"); } while (0); | |||||
962 | ||||||
963 | out: | |||||
964 | return ret; | |||||
965 | } | |||||
966 | ||||||
967 | ||||||
968 | /* Given a request and the reply payload, build a reply and encodes the reply | |||||
969 | * into a record header. This record header is encoded into the vector pointed | |||||
970 | * to be recbuf. | |||||
971 | * msgvec is the buffer that points to the payload of the RPC program. | |||||
972 | * This buffer can be NULL, if an RPC error reply is being constructed. | |||||
973 | * The only reason it is needed here is that in case the buffer is provided, | |||||
974 | * we should account for the length of that buffer in the RPC fragment header. | |||||
975 | */ | |||||
976 | struct iobuf * | |||||
977 | rpcsvc_record_build_record (rpcsvc_request_t *req, size_t payload, | |||||
978 | size_t hdrlen, struct iovec *recbuf) | |||||
979 | { | |||||
980 | struct rpc_msg reply; | |||||
981 | struct iobuf *replyiob = NULL((void*)0); | |||||
982 | char *record = NULL((void*)0); | |||||
983 | struct iovec recordhdr = {0, }; | |||||
984 | size_t pagesize = 0; | |||||
985 | size_t xdr_size = 0; | |||||
986 | rpcsvc_t *svc = NULL((void*)0); | |||||
987 | int ret = -1; | |||||
988 | ||||||
989 | if ((!req) || (!req->trans) || (!req->svc) || (!recbuf)) | |||||
990 | return NULL((void*)0); | |||||
991 | ||||||
992 | svc = req->svc; | |||||
993 | ||||||
994 | /* Fill the rpc structure and XDR it into the buffer got above. */ | |||||
995 | ret = rpcsvc_fill_reply (req, &reply); | |||||
996 | if (ret) | |||||
997 | goto err_exit; | |||||
998 | ||||||
999 | xdr_size = xdr_sizeof ((xdrproc_t)xdr_replymsg, &reply); | |||||
1000 | ||||||
1001 | /* Payload would include 'readv' size etc too, where as | |||||
1002 | that comes as another payload iobuf */ | |||||
1003 | replyiob = iobuf_get2 (svc->ctx->iobuf_pool, (xdr_size + hdrlen)); | |||||
1004 | if (!replyiob) { | |||||
1005 | goto err_exit; | |||||
1006 | } | |||||
1007 | ||||||
1008 | pagesize = iobuf_pagesize (replyiob)(replyiob->iobuf_arena->page_size); | |||||
1009 | ||||||
1010 | record = iobuf_ptr (replyiob)((replyiob)->ptr); /* Now we have it. */ | |||||
1011 | ||||||
1012 | recordhdr = rpcsvc_record_build_header (record, pagesize, reply, | |||||
1013 | payload); | |||||
1014 | if (!recordhdr.iov_base) { | |||||
1015 | gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to build record "do { do { if (0) printf ("Failed to build record " " header") ; } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__ , 1016, GF_LOG_ERROR, "Failed to build record " " header"); } while (0) | |||||
1016 | " header")do { do { if (0) printf ("Failed to build record " " header") ; } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__ , 1016, GF_LOG_ERROR, "Failed to build record " " header"); } while (0); | |||||
1017 | iobuf_unref (replyiob); | |||||
1018 | replyiob = NULL((void*)0); | |||||
1019 | recbuf->iov_base = NULL((void*)0); | |||||
1020 | goto err_exit; | |||||
1021 | } | |||||
1022 | ||||||
1023 | recbuf->iov_base = recordhdr.iov_base; | |||||
1024 | recbuf->iov_len = recordhdr.iov_len; | |||||
1025 | err_exit: | |||||
1026 | return replyiob; | |||||
1027 | } | |||||
1028 | ||||||
1029 | ||||||
1030 | /* | |||||
1031 | * The function to submit a program message to the RPC service. | |||||
1032 | * This message is added to the transmission queue of the | |||||
1033 | * conn. | |||||
1034 | * | |||||
1035 | * Program callers are not expected to use the msgvec->iov_base | |||||
1036 | * address for anything else. | |||||
1037 | * Nor are they expected to free it once this function returns. | |||||
1038 | * Once the transmission of the buffer is completed by the RPC service, | |||||
1039 | * the memory area as referenced through @msg will be unrefed. | |||||
1040 | * If a higher layer does not want anything to do with this iobuf | |||||
1041 | * after this function returns, it should call unref on it. For keeping | |||||
1042 | * it around till the transmission is actually complete, rpcsvc also refs it. | |||||
1043 | * * | |||||
1044 | * If this function returns an error by returning -1, the | |||||
1045 | * higher layer programs should assume that a disconnection happened | |||||
1046 | * and should know that the conn memory area as well as the req structure | |||||
1047 | * has been freed internally. | |||||
1048 | * | |||||
1049 | * For now, this function assumes that a submit is always called | |||||
1050 | * to send a new record. Later, if there is a situation where different | |||||
1051 | * buffers for the same record come from different sources, then we'll | |||||
1052 | * need to change this code to account for multiple submit calls adding | |||||
1053 | * the buffers into a single record. | |||||
1054 | */ | |||||
1055 | ||||||
1056 | int | |||||
1057 | rpcsvc_submit_generic (rpcsvc_request_t *req, struct iovec *proghdr, | |||||
1058 | int hdrcount, struct iovec *payload, int payloadcount, | |||||
1059 | struct iobref *iobref) | |||||
1060 | { | |||||
1061 | int ret = -1, i = 0; | |||||
1062 | struct iobuf *replyiob = NULL((void*)0); | |||||
1063 | struct iovec recordhdr = {0, }; | |||||
1064 | rpc_transport_t *trans = NULL((void*)0); | |||||
1065 | size_t msglen = 0; | |||||
1066 | size_t hdrlen = 0; | |||||
1067 | char new_iobref = 0; | |||||
1068 | ||||||
1069 | if ((!req) || (!req->trans)) | |||||
1070 | return -1; | |||||
1071 | ||||||
1072 | trans = req->trans; | |||||
1073 | ||||||
1074 | for (i = 0; i < hdrcount; i++) { | |||||
1075 | msglen += proghdr[i].iov_len; | |||||
1076 | } | |||||
1077 | ||||||
1078 | for (i = 0; i < payloadcount; i++) { | |||||
1079 | msglen += payload[i].iov_len; | |||||
1080 | } | |||||
1081 | ||||||
1082 | gf_log (GF_RPCSVC, GF_LOG_TRACE, "Tx message: %zu", msglen)do { do { if (0) printf ("Tx message: %zu", msglen); } while ( 0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 1082, GF_LOG_TRACE , "Tx message: %zu", msglen); } while (0); | |||||
1083 | ||||||
1084 | /* Build the buffer containing the encoded RPC reply. */ | |||||
1085 | replyiob = rpcsvc_record_build_record (req, msglen, hdrlen, &recordhdr); | |||||
1086 | if (!replyiob) { | |||||
1087 | gf_log (GF_RPCSVC, GF_LOG_ERROR,"Reply record creation failed")do { do { if (0) printf ("Reply record creation failed"); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 1087, GF_LOG_ERROR,"Reply record creation failed"); } while (0); | |||||
1088 | goto disconnect_exit; | |||||
1089 | } | |||||
1090 | ||||||
1091 | if (!iobref) { | |||||
1092 | iobref = iobref_new (); | |||||
1093 | if (!iobref) { | |||||
1094 | goto disconnect_exit; | |||||
1095 | } | |||||
1096 | ||||||
1097 | new_iobref = 1; | |||||
1098 | } | |||||
1099 | ||||||
1100 | iobref_add (iobref, replyiob); | |||||
1101 | ||||||
1102 | ret = rpcsvc_transport_submit (trans, &recordhdr, 1, proghdr, hdrcount, | |||||
1103 | payload, payloadcount, iobref, | |||||
1104 | req->trans_private); | |||||
1105 | ||||||
1106 | if (ret == -1) { | |||||
1107 | gf_log (GF_RPCSVC, GF_LOG_ERROR, "failed to submit message "do { do { if (0) printf ("failed to submit message " "(XID: 0x%ux, Program: %s, ProgVers: %d, Proc: %d) to " "rpc-transport (%s)", req->xid, req->prog ? req->prog ->progname : "(not matched)", req->prog ? req->prog-> progver : 0, req->procnum, trans->name); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 1112, GF_LOG_ERROR , "failed to submit message " "(XID: 0x%ux, Program: %s, ProgVers: %d, Proc: %d) to " "rpc-transport (%s)", req->xid, req->prog ? req->prog ->progname : "(not matched)", req->prog ? req->prog-> progver : 0, req->procnum, trans->name); } while (0) | |||||
1108 | "(XID: 0x%ux, Program: %s, ProgVers: %d, Proc: %d) to "do { do { if (0) printf ("failed to submit message " "(XID: 0x%ux, Program: %s, ProgVers: %d, Proc: %d) to " "rpc-transport (%s)", req->xid, req->prog ? req->prog ->progname : "(not matched)", req->prog ? req->prog-> progver : 0, req->procnum, trans->name); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 1112, GF_LOG_ERROR , "failed to submit message " "(XID: 0x%ux, Program: %s, ProgVers: %d, Proc: %d) to " "rpc-transport (%s)", req->xid, req->prog ? req->prog ->progname : "(not matched)", req->prog ? req->prog-> progver : 0, req->procnum, trans->name); } while (0) | |||||
1109 | "rpc-transport (%s)", req->xid,do { do { if (0) printf ("failed to submit message " "(XID: 0x%ux, Program: %s, ProgVers: %d, Proc: %d) to " "rpc-transport (%s)", req->xid, req->prog ? req->prog ->progname : "(not matched)", req->prog ? req->prog-> progver : 0, req->procnum, trans->name); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 1112, GF_LOG_ERROR , "failed to submit message " "(XID: 0x%ux, Program: %s, ProgVers: %d, Proc: %d) to " "rpc-transport (%s)", req->xid, req->prog ? req->prog ->progname : "(not matched)", req->prog ? req->prog-> progver : 0, req->procnum, trans->name); } while (0) | |||||
1110 | req->prog ? req->prog->progname : "(not matched)",do { do { if (0) printf ("failed to submit message " "(XID: 0x%ux, Program: %s, ProgVers: %d, Proc: %d) to " "rpc-transport (%s)", req->xid, req->prog ? req->prog ->progname : "(not matched)", req->prog ? req->prog-> progver : 0, req->procnum, trans->name); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 1112, GF_LOG_ERROR , "failed to submit message " "(XID: 0x%ux, Program: %s, ProgVers: %d, Proc: %d) to " "rpc-transport (%s)", req->xid, req->prog ? req->prog ->progname : "(not matched)", req->prog ? req->prog-> progver : 0, req->procnum, trans->name); } while (0) | |||||
1111 | req->prog ? req->prog->progver : 0,do { do { if (0) printf ("failed to submit message " "(XID: 0x%ux, Program: %s, ProgVers: %d, Proc: %d) to " "rpc-transport (%s)", req->xid, req->prog ? req->prog ->progname : "(not matched)", req->prog ? req->prog-> progver : 0, req->procnum, trans->name); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 1112, GF_LOG_ERROR , "failed to submit message " "(XID: 0x%ux, Program: %s, ProgVers: %d, Proc: %d) to " "rpc-transport (%s)", req->xid, req->prog ? req->prog ->progname : "(not matched)", req->prog ? req->prog-> progver : 0, req->procnum, trans->name); } while (0) | |||||
1112 | req->procnum, trans->name)do { do { if (0) printf ("failed to submit message " "(XID: 0x%ux, Program: %s, ProgVers: %d, Proc: %d) to " "rpc-transport (%s)", req->xid, req->prog ? req->prog ->progname : "(not matched)", req->prog ? req->prog-> progver : 0, req->procnum, trans->name); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 1112, GF_LOG_ERROR , "failed to submit message " "(XID: 0x%ux, Program: %s, ProgVers: %d, Proc: %d) to " "rpc-transport (%s)", req->xid, req->prog ? req->prog ->progname : "(not matched)", req->prog ? req->prog-> progver : 0, req->procnum, trans->name); } while (0); | |||||
1113 | } else { | |||||
1114 | gf_log (GF_RPCSVC, GF_LOG_TRACE,do { do { if (0) printf ("submitted reply for rpc-message (XID: 0x%ux, " "Program: %s, ProgVers: %d, Proc: %d) to rpc-transport " "(%s)" , req->xid, req->prog ? req->prog->progname: "-", req->prog ? req->prog->progver : 0, req->procnum , trans->name); } while (0); _gf_log ("rpc-service", "rpcsvc.c" , __FUNCTION__, 1119, GF_LOG_TRACE, "submitted reply for rpc-message (XID: 0x%ux, " "Program: %s, ProgVers: %d, Proc: %d) to rpc-transport " "(%s)" , req->xid, req->prog ? req->prog->progname: "-", req->prog ? req->prog->progver : 0, req->procnum , trans->name); } while (0) | |||||
1115 | "submitted reply for rpc-message (XID: 0x%ux, "do { do { if (0) printf ("submitted reply for rpc-message (XID: 0x%ux, " "Program: %s, ProgVers: %d, Proc: %d) to rpc-transport " "(%s)" , req->xid, req->prog ? req->prog->progname: "-", req->prog ? req->prog->progver : 0, req->procnum , trans->name); } while (0); _gf_log ("rpc-service", "rpcsvc.c" , __FUNCTION__, 1119, GF_LOG_TRACE, "submitted reply for rpc-message (XID: 0x%ux, " "Program: %s, ProgVers: %d, Proc: %d) to rpc-transport " "(%s)" , req->xid, req->prog ? req->prog->progname: "-", req->prog ? req->prog->progver : 0, req->procnum , trans->name); } while (0) | |||||
1116 | "Program: %s, ProgVers: %d, Proc: %d) to rpc-transport "do { do { if (0) printf ("submitted reply for rpc-message (XID: 0x%ux, " "Program: %s, ProgVers: %d, Proc: %d) to rpc-transport " "(%s)" , req->xid, req->prog ? req->prog->progname: "-", req->prog ? req->prog->progver : 0, req->procnum , trans->name); } while (0); _gf_log ("rpc-service", "rpcsvc.c" , __FUNCTION__, 1119, GF_LOG_TRACE, "submitted reply for rpc-message (XID: 0x%ux, " "Program: %s, ProgVers: %d, Proc: %d) to rpc-transport " "(%s)" , req->xid, req->prog ? req->prog->progname: "-", req->prog ? req->prog->progver : 0, req->procnum , trans->name); } while (0) | |||||
1117 | "(%s)", req->xid, req->prog ? req->prog->progname: "-",do { do { if (0) printf ("submitted reply for rpc-message (XID: 0x%ux, " "Program: %s, ProgVers: %d, Proc: %d) to rpc-transport " "(%s)" , req->xid, req->prog ? req->prog->progname: "-", req->prog ? req->prog->progver : 0, req->procnum , trans->name); } while (0); _gf_log ("rpc-service", "rpcsvc.c" , __FUNCTION__, 1119, GF_LOG_TRACE, "submitted reply for rpc-message (XID: 0x%ux, " "Program: %s, ProgVers: %d, Proc: %d) to rpc-transport " "(%s)" , req->xid, req->prog ? req->prog->progname: "-", req->prog ? req->prog->progver : 0, req->procnum , trans->name); } while (0) | |||||
1118 | req->prog ? req->prog->progver : 0,do { do { if (0) printf ("submitted reply for rpc-message (XID: 0x%ux, " "Program: %s, ProgVers: %d, Proc: %d) to rpc-transport " "(%s)" , req->xid, req->prog ? req->prog->progname: "-", req->prog ? req->prog->progver : 0, req->procnum , trans->name); } while (0); _gf_log ("rpc-service", "rpcsvc.c" , __FUNCTION__, 1119, GF_LOG_TRACE, "submitted reply for rpc-message (XID: 0x%ux, " "Program: %s, ProgVers: %d, Proc: %d) to rpc-transport " "(%s)" , req->xid, req->prog ? req->prog->progname: "-", req->prog ? req->prog->progver : 0, req->procnum , trans->name); } while (0) | |||||
1119 | req->procnum, trans->name)do { do { if (0) printf ("submitted reply for rpc-message (XID: 0x%ux, " "Program: %s, ProgVers: %d, Proc: %d) to rpc-transport " "(%s)" , req->xid, req->prog ? req->prog->progname: "-", req->prog ? req->prog->progver : 0, req->procnum , trans->name); } while (0); _gf_log ("rpc-service", "rpcsvc.c" , __FUNCTION__, 1119, GF_LOG_TRACE, "submitted reply for rpc-message (XID: 0x%ux, " "Program: %s, ProgVers: %d, Proc: %d) to rpc-transport " "(%s)" , req->xid, req->prog ? req->prog->progname: "-", req->prog ? req->prog->progver : 0, req->procnum , trans->name); } while (0); | |||||
1120 | } | |||||
1121 | ||||||
1122 | disconnect_exit: | |||||
1123 | if (replyiob) { | |||||
1124 | iobuf_unref (replyiob); | |||||
1125 | } | |||||
1126 | ||||||
1127 | if (new_iobref) { | |||||
1128 | iobref_unref (iobref); | |||||
1129 | } | |||||
1130 | ||||||
1131 | rpcsvc_request_destroy (req); | |||||
1132 | ||||||
1133 | return ret; | |||||
1134 | } | |||||
1135 | ||||||
1136 | ||||||
1137 | int | |||||
1138 | rpcsvc_error_reply (rpcsvc_request_t *req) | |||||
1139 | { | |||||
1140 | struct iovec dummyvec = {0, }; | |||||
1141 | ||||||
1142 | if (!req) | |||||
1143 | return -1; | |||||
1144 | ||||||
1145 | gf_log_callingfn ("", GF_LOG_DEBUG, "sending a RPC error reply")do { do { if (0) printf ("sending a RPC error reply"); } while (0); _gf_log_callingfn ("", "rpcsvc.c", __FUNCTION__, 1145, GF_LOG_DEBUG , "sending a RPC error reply"); } while (0); | |||||
1146 | ||||||
1147 | /* At this point the req should already have been filled with the | |||||
1148 | * appropriate RPC error numbers. | |||||
1149 | */ | |||||
1150 | return rpcsvc_submit_generic (req, &dummyvec, 0, NULL((void*)0), 0, NULL((void*)0)); | |||||
1151 | } | |||||
1152 | ||||||
1153 | ||||||
1154 | /* Register the program with the local portmapper service. */ | |||||
1155 | inline int | |||||
1156 | rpcsvc_program_register_portmap (rpcsvc_program_t *newprog, uint32_t port) | |||||
1157 | { | |||||
1158 | int ret = 0; | |||||
1159 | ||||||
1160 | if (!newprog) { | |||||
1161 | goto out; | |||||
1162 | } | |||||
1163 | ||||||
1164 | if (!(pmap_set (newprog->prognum, newprog->progver, IPPROTO_TCPIPPROTO_TCP, | |||||
1165 | port))) { | |||||
1166 | gf_log (GF_RPCSVC, GF_LOG_ERROR, "Could not register with"do { do { if (0) printf ("Could not register with" " portmap" ); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__ , 1167, GF_LOG_ERROR, "Could not register with" " portmap"); } while (0) | |||||
1167 | " portmap")do { do { if (0) printf ("Could not register with" " portmap" ); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__ , 1167, GF_LOG_ERROR, "Could not register with" " portmap"); } while (0); | |||||
1168 | goto out; | |||||
1169 | } | |||||
1170 | ||||||
1171 | ret = 0; | |||||
1172 | out: | |||||
1173 | return ret; | |||||
1174 | } | |||||
1175 | ||||||
1176 | ||||||
1177 | static inline int | |||||
1178 | rpcsvc_program_unregister_portmap (rpcsvc_program_t *prog) | |||||
1179 | { | |||||
1180 | int ret = 0; | |||||
1181 | ||||||
1182 | if (!prog) | |||||
1183 | goto out; | |||||
1184 | ||||||
1185 | if (!(pmap_unset(prog->prognum, prog->progver))) { | |||||
1186 | gf_log (GF_RPCSVC, GF_LOG_ERROR, "Could not unregister with"do { do { if (0) printf ("Could not unregister with" " portmap" ); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__ , 1187, GF_LOG_ERROR, "Could not unregister with" " portmap") ; } while (0) | |||||
1187 | " portmap")do { do { if (0) printf ("Could not unregister with" " portmap" ); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__ , 1187, GF_LOG_ERROR, "Could not unregister with" " portmap") ; } while (0); | |||||
1188 | goto out; | |||||
1189 | } | |||||
1190 | ||||||
1191 | ret = 0; | |||||
1192 | out: | |||||
1193 | return ret; | |||||
1194 | } | |||||
1195 | ||||||
1196 | int | |||||
1197 | rpcsvc_register_portmap_enabled (rpcsvc_t *svc) | |||||
1198 | { | |||||
1199 | return svc->register_portmap; | |||||
1200 | } | |||||
1201 | ||||||
1202 | int32_t | |||||
1203 | rpcsvc_get_listener_port (rpcsvc_listener_t *listener) | |||||
1204 | { | |||||
1205 | int32_t listener_port = -1; | |||||
1206 | ||||||
1207 | if ((listener == NULL((void*)0)) || (listener->trans == NULL((void*)0))) { | |||||
1208 | goto out; | |||||
1209 | } | |||||
1210 | ||||||
1211 | switch (listener->trans->myinfo.sockaddr.ss_family) { | |||||
1212 | case AF_INET2: | |||||
1213 | listener_port = ((struct sockaddr_in *)&listener->trans->myinfo.sockaddr)->sin_port; | |||||
1214 | break; | |||||
1215 | ||||||
1216 | case AF_INET610: | |||||
1217 | listener_port = ((struct sockaddr_in6 *)&listener->trans->myinfo.sockaddr)->sin6_port; | |||||
1218 | break; | |||||
1219 | ||||||
1220 | default: | |||||
1221 | gf_log (GF_RPCSVC, GF_LOG_DEBUG,do { do { if (0) printf ("invalid address family (%d)", listener ->trans->myinfo.sockaddr.ss_family); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 1223, GF_LOG_DEBUG , "invalid address family (%d)", listener->trans->myinfo .sockaddr.ss_family); } while (0) | |||||
1222 | "invalid address family (%d)",do { do { if (0) printf ("invalid address family (%d)", listener ->trans->myinfo.sockaddr.ss_family); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 1223, GF_LOG_DEBUG , "invalid address family (%d)", listener->trans->myinfo .sockaddr.ss_family); } while (0) | |||||
1223 | listener->trans->myinfo.sockaddr.ss_family)do { do { if (0) printf ("invalid address family (%d)", listener ->trans->myinfo.sockaddr.ss_family); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 1223, GF_LOG_DEBUG , "invalid address family (%d)", listener->trans->myinfo .sockaddr.ss_family); } while (0); | |||||
1224 | goto out; | |||||
1225 | } | |||||
1226 | ||||||
1227 | listener_port = ntohs (listener_port); | |||||
1228 | ||||||
1229 | out: | |||||
1230 | return listener_port; | |||||
1231 | } | |||||
1232 | ||||||
1233 | ||||||
1234 | rpcsvc_listener_t * | |||||
1235 | rpcsvc_get_listener (rpcsvc_t *svc, uint16_t port, rpc_transport_t *trans) | |||||
1236 | { | |||||
1237 | rpcsvc_listener_t *listener = NULL((void*)0); | |||||
1238 | char found = 0; | |||||
1239 | uint32_t listener_port = 0; | |||||
1240 | ||||||
1241 | if (!svc) { | |||||
1242 | goto out; | |||||
1243 | } | |||||
1244 | ||||||
1245 | pthread_mutex_lock (&svc->rpclock); | |||||
1246 | { | |||||
1247 | list_for_each_entry (listener, &svc->listeners, list)for (listener = ((typeof(*listener) *)((char *)((&svc-> listeners)->next)-(unsigned long)(&((typeof(*listener) *)0)->list))); &listener->list != (&svc->listeners ); listener = ((typeof(*listener) *)((char *)(listener->list .next)-(unsigned long)(&((typeof(*listener) *)0)->list )))) { | |||||
1248 | if (trans != NULL((void*)0)) { | |||||
1249 | if (listener->trans == trans) { | |||||
1250 | found = 1; | |||||
1251 | break; | |||||
1252 | } | |||||
1253 | ||||||
1254 | continue; | |||||
1255 | } | |||||
1256 | ||||||
1257 | listener_port = rpcsvc_get_listener_port (listener); | |||||
1258 | if (listener_port == -1) { | |||||
1259 | gf_log (GF_RPCSVC, GF_LOG_ERROR,do { do { if (0) printf ("invalid port for listener %s", listener ->trans->name); } while (0); _gf_log ("rpc-service", "rpcsvc.c" , __FUNCTION__, 1261, GF_LOG_ERROR, "invalid port for listener %s" , listener->trans->name); } while (0) | |||||
1260 | "invalid port for listener %s",do { do { if (0) printf ("invalid port for listener %s", listener ->trans->name); } while (0); _gf_log ("rpc-service", "rpcsvc.c" , __FUNCTION__, 1261, GF_LOG_ERROR, "invalid port for listener %s" , listener->trans->name); } while (0) | |||||
1261 | listener->trans->name)do { do { if (0) printf ("invalid port for listener %s", listener ->trans->name); } while (0); _gf_log ("rpc-service", "rpcsvc.c" , __FUNCTION__, 1261, GF_LOG_ERROR, "invalid port for listener %s" , listener->trans->name); } while (0); | |||||
1262 | continue; | |||||
1263 | } | |||||
1264 | ||||||
1265 | if (listener_port == port) { | |||||
1266 | found = 1; | |||||
1267 | break; | |||||
1268 | } | |||||
1269 | } | |||||
1270 | } | |||||
1271 | pthread_mutex_unlock (&svc->rpclock); | |||||
1272 | ||||||
1273 | if (!found) { | |||||
1274 | listener = NULL((void*)0); | |||||
1275 | } | |||||
1276 | ||||||
1277 | out: | |||||
1278 | return listener; | |||||
1279 | } | |||||
1280 | ||||||
1281 | ||||||
1282 | /* The only difference between the generic submit and this one is that the | |||||
1283 | * generic submit is also used for submitting RPC error replies in where there | |||||
1284 | * are no payloads so the msgvec and msgbuf can be NULL. | |||||
1285 | * Since RPC programs should be using this function along with their payloads | |||||
1286 | * we must perform NULL checks before calling the generic submit. | |||||
1287 | */ | |||||
1288 | int | |||||
1289 | rpcsvc_submit_message (rpcsvc_request_t *req, struct iovec *proghdr, | |||||
1290 | int hdrcount, struct iovec *payload, int payloadcount, | |||||
1291 | struct iobref *iobref) | |||||
1292 | { | |||||
1293 | if ((!req) || (!req->trans) || (!proghdr) || (!proghdr->iov_base)) | |||||
1294 | return -1; | |||||
1295 | ||||||
1296 | return rpcsvc_submit_generic (req, proghdr, hdrcount, payload, | |||||
1297 | payloadcount, iobref); | |||||
1298 | } | |||||
1299 | ||||||
1300 | ||||||
1301 | int | |||||
1302 | rpcsvc_program_unregister (rpcsvc_t *svc, rpcsvc_program_t *program) | |||||
1303 | { | |||||
1304 | int ret = -1; | |||||
1305 | rpcsvc_program_t *prog = NULL((void*)0); | |||||
1306 | if (!svc || !program) { | |||||
| ||||||
1307 | goto out; | |||||
1308 | } | |||||
1309 | ||||||
1310 | ret = rpcsvc_program_unregister_portmap (program); | |||||
1311 | if (ret == -1) { | |||||
1312 | gf_log (GF_RPCSVC, GF_LOG_ERROR, "portmap unregistration of"do { do { if (0) printf ("portmap unregistration of" " program failed" ); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__ , 1313, GF_LOG_ERROR, "portmap unregistration of" " program failed" ); } while (0) | |||||
1313 | " program failed")do { do { if (0) printf ("portmap unregistration of" " program failed" ); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__ , 1313, GF_LOG_ERROR, "portmap unregistration of" " program failed" ); } while (0); | |||||
1314 | goto out; | |||||
1315 | } | |||||
1316 | ||||||
1317 | pthread_mutex_lock (&svc->rpclock); | |||||
1318 | { | |||||
1319 | list_for_each_entry (prog, &svc->programs, program)for (prog = ((typeof(*prog) *)((char *)((&svc->programs )->next)-(unsigned long)(&((typeof(*prog) *)0)->program ))); &prog->program != (&svc->programs); prog = ((typeof(*prog) *)((char *)(prog->program.next)-(unsigned long)(&((typeof(*prog) *)0)->program)))) { | |||||
1320 | if ((prog->prognum == program->prognum) | |||||
1321 | && (prog->progver == program->progver)) { | |||||
1322 | break; | |||||
1323 | } | |||||
1324 | } | |||||
1325 | } | |||||
1326 | pthread_mutex_unlock (&svc->rpclock); | |||||
1327 | ||||||
1328 | if (prog == NULL((void*)0)) { | |||||
1329 | ret = -1; | |||||
1330 | goto out; | |||||
1331 | } | |||||
1332 | ||||||
1333 | gf_log (GF_RPCSVC, GF_LOG_DEBUG, "Program unregistered: %s, Num: %d,"do { do { if (0) printf ("Program unregistered: %s, Num: %d," " Ver: %d, Port: %d", prog->progname, prog->prognum, prog ->progver, prog->progport); } while (0); _gf_log ("rpc-service" , "rpcsvc.c", __FUNCTION__, 1335, GF_LOG_DEBUG, "Program unregistered: %s, Num: %d," " Ver: %d, Port: %d", prog->progname, prog->prognum, prog ->progver, prog->progport); } while (0) | |||||
1334 | " Ver: %d, Port: %d", prog->progname, prog->prognum,do { do { if (0) printf ("Program unregistered: %s, Num: %d," " Ver: %d, Port: %d", prog->progname, prog->prognum, prog ->progver, prog->progport); } while (0); _gf_log ("rpc-service" , "rpcsvc.c", __FUNCTION__, 1335, GF_LOG_DEBUG, "Program unregistered: %s, Num: %d," " Ver: %d, Port: %d", prog->progname, prog->prognum, prog ->progver, prog->progport); } while (0) | |||||
1335 | prog->progver, prog->progport)do { do { if (0) printf ("Program unregistered: %s, Num: %d," " Ver: %d, Port: %d", prog->progname, prog->prognum, prog ->progver, prog->progport); } while (0); _gf_log ("rpc-service" , "rpcsvc.c", __FUNCTION__, 1335, GF_LOG_DEBUG, "Program unregistered: %s, Num: %d," " Ver: %d, Port: %d", prog->progname, prog->prognum, prog ->progver, prog->progport); } while (0); | |||||
1336 | ||||||
1337 | pthread_mutex_lock (&svc->rpclock); | |||||
1338 | { | |||||
1339 | list_del_init (&prog->program); | |||||
1340 | } | |||||
1341 | pthread_mutex_unlock (&svc->rpclock); | |||||
1342 | ||||||
1343 | ret = 0; | |||||
1344 | out: | |||||
1345 | if (ret == -1) { | |||||
1346 | gf_log (GF_RPCSVC, GF_LOG_ERROR, "Program unregistration failed"do { do { if (0) printf ("Program unregistration failed" ": %s, Num: %d, Ver: %d, Port: %d" , program->progname, program->prognum, program->progver , program->progport); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 1348, GF_LOG_ERROR, "Program unregistration failed" ": %s, Num: %d, Ver: %d, Port: %d", program->progname, program ->prognum, program->progver, program->progport); } while (0) | |||||
| ||||||
1347 | ": %s, Num: %d, Ver: %d, Port: %d", program->progname,do { do { if (0) printf ("Program unregistration failed" ": %s, Num: %d, Ver: %d, Port: %d" , program->progname, program->prognum, program->progver , program->progport); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 1348, GF_LOG_ERROR, "Program unregistration failed" ": %s, Num: %d, Ver: %d, Port: %d", program->progname, program ->prognum, program->progver, program->progport); } while (0) | |||||
1348 | program->prognum, program->progver, program->progport)do { do { if (0) printf ("Program unregistration failed" ": %s, Num: %d, Ver: %d, Port: %d" , program->progname, program->prognum, program->progver , program->progport); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 1348, GF_LOG_ERROR, "Program unregistration failed" ": %s, Num: %d, Ver: %d, Port: %d", program->progname, program ->prognum, program->progver, program->progport); } while (0); | |||||
1349 | } | |||||
1350 | ||||||
1351 | return ret; | |||||
1352 | } | |||||
1353 | ||||||
1354 | ||||||
1355 | inline int | |||||
1356 | rpcsvc_transport_peername (rpc_transport_t *trans, char *hostname, int hostlen) | |||||
1357 | { | |||||
1358 | if (!trans) { | |||||
1359 | return -1; | |||||
1360 | } | |||||
1361 | ||||||
1362 | return rpc_transport_get_peername (trans, hostname, hostlen); | |||||
1363 | } | |||||
1364 | ||||||
1365 | ||||||
1366 | inline int | |||||
1367 | rpcsvc_transport_peeraddr (rpc_transport_t *trans, char *addrstr, int addrlen, | |||||
1368 | struct sockaddr_storage *sa, socklen_t sasize) | |||||
1369 | { | |||||
1370 | if (!trans) { | |||||
1371 | return -1; | |||||
1372 | } | |||||
1373 | ||||||
1374 | return rpc_transport_get_peeraddr(trans, addrstr, addrlen, sa, | |||||
1375 | sasize); | |||||
1376 | } | |||||
1377 | ||||||
1378 | ||||||
1379 | rpc_transport_t * | |||||
1380 | rpcsvc_transport_create (rpcsvc_t *svc, dict_t *options, char *name) | |||||
1381 | { | |||||
1382 | int ret = -1; | |||||
1383 | rpc_transport_t *trans = NULL((void*)0); | |||||
1384 | ||||||
1385 | trans = rpc_transport_load (svc->ctx, options, name); | |||||
1386 | if (!trans) { | |||||
1387 | gf_log (GF_RPCSVC, GF_LOG_WARNING, "cannot create listener, "do { do { if (0) printf ("cannot create listener, " "initing the transport failed" ); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__ , 1388, GF_LOG_WARNING, "cannot create listener, " "initing the transport failed" ); } while (0) | |||||
1388 | "initing the transport failed")do { do { if (0) printf ("cannot create listener, " "initing the transport failed" ); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__ , 1388, GF_LOG_WARNING, "cannot create listener, " "initing the transport failed" ); } while (0); | |||||
1389 | goto out; | |||||
1390 | } | |||||
1391 | ||||||
1392 | ret = rpc_transport_listen (trans); | |||||
1393 | if (ret == -1) { | |||||
1394 | gf_log (GF_RPCSVC, GF_LOG_WARNING,do { do { if (0) printf ("listening on transport failed"); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 1395, GF_LOG_WARNING, "listening on transport failed"); } while (0 ) | |||||
1395 | "listening on transport failed")do { do { if (0) printf ("listening on transport failed"); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 1395, GF_LOG_WARNING, "listening on transport failed"); } while (0 ); | |||||
1396 | goto out; | |||||
1397 | } | |||||
1398 | ||||||
1399 | ret = rpc_transport_register_notify (trans, rpcsvc_notify, svc); | |||||
1400 | if (ret == -1) { | |||||
1401 | gf_log (GF_RPCSVC, GF_LOG_WARNING, "registering notify failed")do { do { if (0) printf ("registering notify failed"); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 1401, GF_LOG_WARNING, "registering notify failed"); } while (0); | |||||
1402 | goto out; | |||||
1403 | } | |||||
1404 | ||||||
1405 | ret = 0; | |||||
1406 | out: | |||||
1407 | if ((ret == -1) && (trans)) { | |||||
1408 | rpc_transport_disconnect (trans); | |||||
1409 | trans = NULL((void*)0); | |||||
1410 | } | |||||
1411 | ||||||
1412 | return trans; | |||||
1413 | } | |||||
1414 | ||||||
1415 | rpcsvc_listener_t * | |||||
1416 | rpcsvc_listener_alloc (rpcsvc_t *svc, rpc_transport_t *trans) | |||||
1417 | { | |||||
1418 | rpcsvc_listener_t *listener = NULL((void*)0); | |||||
1419 | ||||||
1420 | listener = GF_CALLOC (1, sizeof (*listener),__gf_calloc (1, sizeof (*listener), gf_common_mt_rpcsvc_listener_t ) | |||||
1421 | gf_common_mt_rpcsvc_listener_t)__gf_calloc (1, sizeof (*listener), gf_common_mt_rpcsvc_listener_t ); | |||||
1422 | if (!listener) { | |||||
1423 | goto out; | |||||
1424 | } | |||||
1425 | ||||||
1426 | listener->trans = trans; | |||||
1427 | listener->svc = svc; | |||||
1428 | ||||||
1429 | INIT_LIST_HEAD (&listener->list)do { (&listener->list)->next = (&listener->list )->prev = &listener->list; } while (0); | |||||
1430 | ||||||
1431 | pthread_mutex_lock (&svc->rpclock); | |||||
1432 | { | |||||
1433 | list_add_tail (&listener->list, &svc->listeners); | |||||
1434 | } | |||||
1435 | pthread_mutex_unlock (&svc->rpclock); | |||||
1436 | out: | |||||
1437 | return listener; | |||||
1438 | } | |||||
1439 | ||||||
1440 | ||||||
1441 | int32_t | |||||
1442 | rpcsvc_create_listener (rpcsvc_t *svc, dict_t *options, char *name) | |||||
1443 | { | |||||
1444 | rpc_transport_t *trans = NULL((void*)0); | |||||
1445 | rpcsvc_listener_t *listener = NULL((void*)0); | |||||
1446 | int32_t ret = -1; | |||||
1447 | ||||||
1448 | if (!svc || !options) { | |||||
1449 | goto out; | |||||
1450 | } | |||||
1451 | ||||||
1452 | trans = rpcsvc_transport_create (svc, options, name); | |||||
1453 | if (!trans) { | |||||
1454 | /* LOG TODO */ | |||||
1455 | goto out; | |||||
1456 | } | |||||
1457 | ||||||
1458 | listener = rpcsvc_listener_alloc (svc, trans); | |||||
1459 | if (listener == NULL((void*)0)) { | |||||
1460 | goto out; | |||||
1461 | } | |||||
1462 | ||||||
1463 | ret = 0; | |||||
1464 | out: | |||||
1465 | if (!listener && trans) { | |||||
1466 | rpc_transport_disconnect (trans); | |||||
1467 | } | |||||
1468 | ||||||
1469 | return ret; | |||||
1470 | } | |||||
1471 | ||||||
1472 | ||||||
1473 | int32_t | |||||
1474 | rpcsvc_create_listeners (rpcsvc_t *svc, dict_t *options, char *name) | |||||
1475 | { | |||||
1476 | int32_t ret = -1, count = 0; | |||||
1477 | data_t *data = NULL((void*)0); | |||||
1478 | char *str = NULL((void*)0), *ptr = NULL((void*)0), *transport_name = NULL((void*)0); | |||||
1479 | char *transport_type = NULL((void*)0), *saveptr = NULL((void*)0), *tmp = NULL((void*)0); | |||||
1480 | ||||||
1481 | if ((svc == NULL((void*)0)) || (options == NULL((void*)0)) || (name == NULL((void*)0))) { | |||||
1482 | goto out; | |||||
1483 | } | |||||
1484 | ||||||
1485 | data = dict_get (options, "transport-type"); | |||||
1486 | if (data == NULL((void*)0)) { | |||||
1487 | gf_log (GF_RPCSVC, GF_LOG_ERROR,do { do { if (0) printf ("option transport-type not set"); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 1488, GF_LOG_ERROR, "option transport-type not set"); } while (0) | |||||
1488 | "option transport-type not set")do { do { if (0) printf ("option transport-type not set"); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 1488, GF_LOG_ERROR, "option transport-type not set"); } while (0); | |||||
1489 | goto out; | |||||
1490 | } | |||||
1491 | ||||||
1492 | transport_type = data_to_str (data); | |||||
1493 | if (transport_type == NULL((void*)0)) { | |||||
1494 | gf_log (GF_RPCSVC, GF_LOG_ERROR,do { do { if (0) printf ("option transport-type not set"); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 1495, GF_LOG_ERROR, "option transport-type not set"); } while (0) | |||||
1495 | "option transport-type not set")do { do { if (0) printf ("option transport-type not set"); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 1495, GF_LOG_ERROR, "option transport-type not set"); } while (0); | |||||
1496 | goto out; | |||||
1497 | } | |||||
1498 | ||||||
1499 | /* duplicate transport_type, since following dict_set will free it */ | |||||
1500 | transport_type = gf_strdup (transport_type); | |||||
1501 | if (transport_type == NULL((void*)0)) { | |||||
1502 | goto out; | |||||
1503 | } | |||||
1504 | ||||||
1505 | str = gf_strdup (transport_type); | |||||
1506 | if (str == NULL((void*)0)) { | |||||
1507 | goto out; | |||||
1508 | } | |||||
1509 | ||||||
1510 | ptr = strtok_r (str, ",", &saveptr); | |||||
1511 | ||||||
1512 | while (ptr != NULL((void*)0)) { | |||||
1513 | tmp = gf_strdup (ptr); | |||||
1514 | if (tmp == NULL((void*)0)) { | |||||
1515 | goto out; | |||||
1516 | } | |||||
1517 | ||||||
1518 | ret = gf_asprintf (&transport_name, "%s.%s", tmp, name); | |||||
1519 | if (ret == -1) { | |||||
1520 | goto out; | |||||
1521 | } | |||||
1522 | ||||||
1523 | ret = dict_set_dynstr (options, "transport-type", tmp); | |||||
1524 | if (ret == -1) { | |||||
1525 | goto out; | |||||
1526 | } | |||||
1527 | ||||||
1528 | tmp = NULL((void*)0); | |||||
1529 | ptr = strtok_r (NULL((void*)0), ",", &saveptr); | |||||
1530 | ||||||
1531 | ret = rpcsvc_create_listener (svc, options, transport_name); | |||||
1532 | if (ret != 0) { | |||||
1533 | goto out; | |||||
1534 | } | |||||
1535 | ||||||
1536 | GF_FREE (transport_name)__gf_free (transport_name); | |||||
1537 | transport_name = NULL((void*)0); | |||||
1538 | count++; | |||||
1539 | } | |||||
1540 | ||||||
1541 | ret = dict_set_dynstr (options, "transport-type", transport_type); | |||||
1542 | if (ret == -1) { | |||||
1543 | goto out; | |||||
1544 | } | |||||
1545 | ||||||
1546 | transport_type = NULL((void*)0); | |||||
1547 | ||||||
1548 | out: | |||||
1549 | GF_FREE (str)__gf_free (str); | |||||
1550 | ||||||
1551 | GF_FREE (transport_type)__gf_free (transport_type); | |||||
1552 | ||||||
1553 | GF_FREE (tmp)__gf_free (tmp); | |||||
1554 | ||||||
1555 | GF_FREE (transport_name)__gf_free (transport_name); | |||||
1556 | ||||||
1557 | return count; | |||||
1558 | } | |||||
1559 | ||||||
1560 | ||||||
1561 | int | |||||
1562 | rpcsvc_unregister_notify (rpcsvc_t *svc, rpcsvc_notify_t notify, void *mydata) | |||||
1563 | { | |||||
1564 | rpcsvc_notify_wrapper_t *wrapper = NULL((void*)0), *tmp = NULL((void*)0); | |||||
1565 | int ret = 0; | |||||
1566 | ||||||
1567 | if (!svc || !notify) { | |||||
1568 | goto out; | |||||
1569 | } | |||||
1570 | ||||||
1571 | pthread_mutex_lock (&svc->rpclock); | |||||
1572 | { | |||||
1573 | list_for_each_entry_safe (wrapper, tmp, &svc->notify, list)for (wrapper = ((typeof(*wrapper) *)((char *)((&svc->notify )->next)-(unsigned long)(&((typeof(*wrapper) *)0)-> list))), tmp = ((typeof(*wrapper) *)((char *)(wrapper->list .next)-(unsigned long)(&((typeof(*wrapper) *)0)->list) )); &wrapper->list != (&svc->notify); wrapper = tmp, tmp = ((typeof(*tmp) *)((char *)(tmp->list.next)-(unsigned long)(&((typeof(*tmp) *)0)->list)))) { | |||||
1574 | if ((wrapper->notify == notify) | |||||
1575 | && (mydata == wrapper->data)) { | |||||
1576 | list_del_init (&wrapper->list); | |||||
1577 | GF_FREE (wrapper)__gf_free (wrapper); | |||||
1578 | ret++; | |||||
1579 | } | |||||
1580 | } | |||||
1581 | } | |||||
1582 | pthread_mutex_unlock (&svc->rpclock); | |||||
1583 | ||||||
1584 | out: | |||||
1585 | return ret; | |||||
1586 | } | |||||
1587 | ||||||
1588 | int | |||||
1589 | rpcsvc_register_notify (rpcsvc_t *svc, rpcsvc_notify_t notify, void *mydata) | |||||
1590 | { | |||||
1591 | rpcsvc_notify_wrapper_t *wrapper = NULL((void*)0); | |||||
1592 | int ret = -1; | |||||
1593 | ||||||
1594 | wrapper = rpcsvc_notify_wrapper_alloc (); | |||||
1595 | if (!wrapper) { | |||||
1596 | goto out; | |||||
1597 | } | |||||
1598 | svc->mydata = mydata; /* this_xlator */ | |||||
1599 | wrapper->data = mydata; | |||||
1600 | wrapper->notify = notify; | |||||
1601 | ||||||
1602 | pthread_mutex_lock (&svc->rpclock); | |||||
1603 | { | |||||
1604 | list_add_tail (&wrapper->list, &svc->notify); | |||||
1605 | svc->notify_count++; | |||||
1606 | } | |||||
1607 | pthread_mutex_unlock (&svc->rpclock); | |||||
1608 | ||||||
1609 | ret = 0; | |||||
1610 | out: | |||||
1611 | return ret; | |||||
1612 | } | |||||
1613 | ||||||
1614 | ||||||
1615 | inline int | |||||
1616 | rpcsvc_program_register (rpcsvc_t *svc, rpcsvc_program_t *program) | |||||
1617 | { | |||||
1618 | int ret = -1; | |||||
1619 | rpcsvc_program_t *newprog = NULL((void*)0); | |||||
1620 | char already_registered = 0; | |||||
1621 | ||||||
1622 | if (!svc) { | |||||
1623 | goto out; | |||||
1624 | } | |||||
1625 | ||||||
1626 | if (program->actors == NULL((void*)0)) { | |||||
1627 | goto out; | |||||
1628 | } | |||||
1629 | ||||||
1630 | pthread_mutex_lock (&svc->rpclock); | |||||
1631 | { | |||||
1632 | list_for_each_entry (newprog, &svc->programs, program)for (newprog = ((typeof(*newprog) *)((char *)((&svc->programs )->next)-(unsigned long)(&((typeof(*newprog) *)0)-> program))); &newprog->program != (&svc->programs ); newprog = ((typeof(*newprog) *)((char *)(newprog->program .next)-(unsigned long)(&((typeof(*newprog) *)0)->program )))) { | |||||
1633 | if ((newprog->prognum == program->prognum) | |||||
1634 | && (newprog->progver == program->progver)) { | |||||
1635 | already_registered = 1; | |||||
1636 | break; | |||||
1637 | } | |||||
1638 | } | |||||
1639 | } | |||||
1640 | pthread_mutex_unlock (&svc->rpclock); | |||||
1641 | ||||||
1642 | if (already_registered) { | |||||
1643 | ret = 0; | |||||
1644 | goto out; | |||||
1645 | } | |||||
1646 | ||||||
1647 | newprog = GF_CALLOC (1, sizeof(*newprog),gf_common_mt_rpcsvc_program_t)__gf_calloc (1, sizeof(*newprog), gf_common_mt_rpcsvc_program_t ); | |||||
1648 | if (newprog == NULL((void*)0)) { | |||||
1649 | goto out; | |||||
1650 | } | |||||
1651 | ||||||
1652 | memcpy (newprog, program, sizeof (*program)); | |||||
1653 | ||||||
1654 | INIT_LIST_HEAD (&newprog->program)do { (&newprog->program)->next = (&newprog-> program)->prev = &newprog->program; } while (0); | |||||
1655 | ||||||
1656 | pthread_mutex_lock (&svc->rpclock); | |||||
1657 | { | |||||
1658 | list_add_tail (&newprog->program, &svc->programs); | |||||
1659 | } | |||||
1660 | pthread_mutex_unlock (&svc->rpclock); | |||||
1661 | ||||||
1662 | ret = 0; | |||||
1663 | gf_log (GF_RPCSVC, GF_LOG_DEBUG, "New program registered: %s, Num: %d,"do { do { if (0) printf ("New program registered: %s, Num: %d," " Ver: %d, Port: %d", newprog->progname, newprog->prognum , newprog->progver, newprog->progport); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 1665, GF_LOG_DEBUG , "New program registered: %s, Num: %d," " Ver: %d, Port: %d" , newprog->progname, newprog->prognum, newprog->progver , newprog->progport); } while (0) | |||||
1664 | " Ver: %d, Port: %d", newprog->progname, newprog->prognum,do { do { if (0) printf ("New program registered: %s, Num: %d," " Ver: %d, Port: %d", newprog->progname, newprog->prognum , newprog->progver, newprog->progport); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 1665, GF_LOG_DEBUG , "New program registered: %s, Num: %d," " Ver: %d, Port: %d" , newprog->progname, newprog->prognum, newprog->progver , newprog->progport); } while (0) | |||||
1665 | newprog->progver, newprog->progport)do { do { if (0) printf ("New program registered: %s, Num: %d," " Ver: %d, Port: %d", newprog->progname, newprog->prognum , newprog->progver, newprog->progport); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 1665, GF_LOG_DEBUG , "New program registered: %s, Num: %d," " Ver: %d, Port: %d" , newprog->progname, newprog->prognum, newprog->progver , newprog->progport); } while (0); | |||||
1666 | ||||||
1667 | out: | |||||
1668 | if (ret == -1) { | |||||
1669 | gf_log (GF_RPCSVC, GF_LOG_ERROR, "Program registration failed:"do { do { if (0) printf ("Program registration failed:" " %s, Num: %d, Ver: %d, Port: %d" , program->progname, program->prognum, program->progver , program->progport); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 1671, GF_LOG_ERROR, "Program registration failed:" " %s, Num: %d, Ver: %d, Port: %d", program->progname, program ->prognum, program->progver, program->progport); } while (0) | |||||
1670 | " %s, Num: %d, Ver: %d, Port: %d", program->progname,do { do { if (0) printf ("Program registration failed:" " %s, Num: %d, Ver: %d, Port: %d" , program->progname, program->prognum, program->progver , program->progport); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 1671, GF_LOG_ERROR, "Program registration failed:" " %s, Num: %d, Ver: %d, Port: %d", program->progname, program ->prognum, program->progver, program->progport); } while (0) | |||||
1671 | program->prognum, program->progver, program->progport)do { do { if (0) printf ("Program registration failed:" " %s, Num: %d, Ver: %d, Port: %d" , program->progname, program->prognum, program->progver , program->progport); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 1671, GF_LOG_ERROR, "Program registration failed:" " %s, Num: %d, Ver: %d, Port: %d", program->progname, program ->prognum, program->progver, program->progport); } while (0); | |||||
1672 | } | |||||
1673 | ||||||
1674 | return ret; | |||||
1675 | } | |||||
1676 | ||||||
1677 | static void | |||||
1678 | free_prog_details (gf_dump_rsp *rsp) | |||||
1679 | { | |||||
1680 | gf_prog_detail *prev = NULL((void*)0); | |||||
1681 | gf_prog_detail *trav = NULL((void*)0); | |||||
1682 | ||||||
1683 | trav = rsp->prog; | |||||
1684 | while (trav) { | |||||
1685 | prev = trav; | |||||
1686 | trav = trav->next; | |||||
1687 | GF_FREE (prev)__gf_free (prev); | |||||
1688 | } | |||||
1689 | } | |||||
1690 | ||||||
1691 | static int | |||||
1692 | build_prog_details (rpcsvc_request_t *req, gf_dump_rsp *rsp) | |||||
1693 | { | |||||
1694 | int ret = -1; | |||||
1695 | rpcsvc_program_t *program = NULL((void*)0); | |||||
1696 | gf_prog_detail *prog = NULL((void*)0); | |||||
1697 | gf_prog_detail *prev = NULL((void*)0); | |||||
1698 | ||||||
1699 | if (!req || !req->trans || !req->svc) | |||||
1700 | goto out; | |||||
1701 | ||||||
1702 | list_for_each_entry (program, &req->svc->programs, program)for (program = ((typeof(*program) *)((char *)((&req->svc ->programs)->next)-(unsigned long)(&((typeof(*program ) *)0)->program))); &program->program != (&req-> svc->programs); program = ((typeof(*program) *)((char *)(program ->program.next)-(unsigned long)(&((typeof(*program) *) 0)->program)))) { | |||||
1703 | prog = GF_CALLOC (1, sizeof (*prog), 0)__gf_calloc (1, sizeof (*prog), 0); | |||||
1704 | if (!prog) | |||||
1705 | goto out; | |||||
1706 | prog->progname = program->progname; | |||||
1707 | prog->prognum = program->prognum; | |||||
1708 | prog->progver = program->progver; | |||||
1709 | if (!rsp->prog) | |||||
1710 | rsp->prog = prog; | |||||
1711 | if (prev) | |||||
1712 | prev->next = prog; | |||||
1713 | prev = prog; | |||||
1714 | } | |||||
1715 | if (prev) | |||||
1716 | ret = 0; | |||||
1717 | out: | |||||
1718 | return ret; | |||||
1719 | } | |||||
1720 | ||||||
1721 | static int | |||||
1722 | rpcsvc_dump (rpcsvc_request_t *req) | |||||
1723 | { | |||||
1724 | char rsp_buf[8 * 1024] = {0,}; | |||||
1725 | gf_dump_rsp rsp = {0,}; | |||||
1726 | struct iovec iov = {0,}; | |||||
1727 | int op_errno = EINVAL22; | |||||
1728 | int ret = -1; | |||||
1729 | uint32_t dump_rsp_len = 0; | |||||
1730 | ||||||
1731 | if (!req) | |||||
1732 | goto sendrsp; | |||||
1733 | ||||||
1734 | ret = build_prog_details (req, &rsp); | |||||
1735 | if (ret < 0) { | |||||
1736 | op_errno = -ret; | |||||
1737 | goto sendrsp; | |||||
1738 | } | |||||
1739 | ||||||
1740 | op_errno = 0; | |||||
1741 | ||||||
1742 | sendrsp: | |||||
1743 | rsp.op_errno = gf_errno_to_error (op_errno); | |||||
1744 | rsp.op_ret = ret; | |||||
1745 | ||||||
1746 | dump_rsp_len = xdr_sizeof ((xdrproc_t) xdr_gf_dump_rsp, | |||||
1747 | &rsp); | |||||
1748 | ||||||
1749 | iov.iov_base = rsp_buf; | |||||
1750 | iov.iov_len = dump_rsp_len; | |||||
1751 | ||||||
1752 | ret = xdr_serialize_generic (iov, &rsp, (xdrproc_t)xdr_gf_dump_rsp); | |||||
1753 | if (ret < 0) { | |||||
1754 | ret = RPCSVC_ACTOR_ERROR(-1); | |||||
1755 | } else { | |||||
1756 | rpcsvc_submit_generic (req, &iov, 1, NULL((void*)0), 0, NULL((void*)0)); | |||||
1757 | ret = 0; | |||||
1758 | } | |||||
1759 | ||||||
1760 | free_prog_details (&rsp); | |||||
1761 | ||||||
1762 | return ret; | |||||
1763 | } | |||||
1764 | ||||||
1765 | int | |||||
1766 | rpcsvc_init_options (rpcsvc_t *svc, dict_t *options) | |||||
1767 | { | |||||
1768 | char *optstr = NULL((void*)0); | |||||
1769 | int ret = -1; | |||||
1770 | ||||||
1771 | if ((!svc) || (!options)) | |||||
1772 | return -1; | |||||
1773 | ||||||
1774 | svc->memfactor = RPCSVC_DEFAULT_MEMFACTOR8; | |||||
1775 | ||||||
1776 | svc->register_portmap = _gf_true; | |||||
1777 | if (dict_get (options, "rpc.register-with-portmap")) { | |||||
1778 | ret = dict_get_str (options, "rpc.register-with-portmap", | |||||
1779 | &optstr); | |||||
1780 | if (ret < 0) { | |||||
1781 | gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to parse "do { do { if (0) printf ("Failed to parse " "dict"); } while ( 0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 1782, GF_LOG_ERROR , "Failed to parse " "dict"); } while (0) | |||||
1782 | "dict")do { do { if (0) printf ("Failed to parse " "dict"); } while ( 0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 1782, GF_LOG_ERROR , "Failed to parse " "dict"); } while (0); | |||||
1783 | goto out; | |||||
1784 | } | |||||
1785 | ||||||
1786 | ret = gf_string2boolean (optstr, &svc->register_portmap); | |||||
1787 | if (ret < 0) { | |||||
1788 | gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to parse bool "do { do { if (0) printf ("Failed to parse bool " "string"); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 1789, GF_LOG_ERROR, "Failed to parse bool " "string"); } while (0) | |||||
1789 | "string")do { do { if (0) printf ("Failed to parse bool " "string"); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 1789, GF_LOG_ERROR, "Failed to parse bool " "string"); } while (0); | |||||
1790 | goto out; | |||||
1791 | } | |||||
1792 | } | |||||
1793 | ||||||
1794 | if (!svc->register_portmap) | |||||
1795 | gf_log (GF_RPCSVC, GF_LOG_DEBUG, "Portmap registration "do { do { if (0) printf ("Portmap registration " "disabled"); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__ , 1796, GF_LOG_DEBUG, "Portmap registration " "disabled"); } while (0) | |||||
1796 | "disabled")do { do { if (0) printf ("Portmap registration " "disabled"); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__ , 1796, GF_LOG_DEBUG, "Portmap registration " "disabled"); } while (0); | |||||
1797 | ||||||
1798 | ret = 0; | |||||
1799 | out: | |||||
1800 | return ret; | |||||
1801 | } | |||||
1802 | ||||||
1803 | int | |||||
1804 | rpcsvc_transport_unix_options_build (dict_t **options, char *filepath) | |||||
1805 | { | |||||
1806 | dict_t *dict = NULL((void*)0); | |||||
1807 | char *fpath = NULL((void*)0); | |||||
1808 | int ret = -1; | |||||
1809 | ||||||
1810 | GF_ASSERT (filepath)do { if (!(filepath)) { do { do { if (0) printf ("Assertion failed: " "filepath"); } while (0); _gf_log_callingfn ("", "rpcsvc.c", __FUNCTION__, 1810, GF_LOG_ERROR, "Assertion failed: " "filepath" ); } while (0); } } while (0); | |||||
1811 | GF_ASSERT (options)do { if (!(options)) { do { do { if (0) printf ("Assertion failed: " "options"); } while (0); _gf_log_callingfn ("", "rpcsvc.c", __FUNCTION__ , 1811, GF_LOG_ERROR, "Assertion failed: " "options"); } while (0); } } while (0); | |||||
1812 | ||||||
1813 | dict = dict_new (); | |||||
1814 | if (!dict) | |||||
1815 | goto out; | |||||
1816 | ||||||
1817 | fpath = gf_strdup (filepath); | |||||
1818 | if (!fpath) { | |||||
1819 | ret = -1; | |||||
1820 | goto out; | |||||
1821 | } | |||||
1822 | ||||||
1823 | ret = dict_set_dynstr (dict, "transport.socket.listen-path", fpath); | |||||
1824 | if (ret) | |||||
1825 | goto out; | |||||
1826 | ||||||
1827 | ret = dict_set_str (dict, "transport.address-family", "unix"); | |||||
1828 | if (ret) | |||||
1829 | goto out; | |||||
1830 | ||||||
1831 | ret = dict_set_str (dict, "transport.socket.nodelay", "off"); | |||||
1832 | if (ret) | |||||
1833 | goto out; | |||||
1834 | ||||||
1835 | ret = dict_set_str (dict, "transport-type", "socket"); | |||||
1836 | if (ret) | |||||
1837 | goto out; | |||||
1838 | ||||||
1839 | *options = dict; | |||||
1840 | out: | |||||
1841 | if (ret) { | |||||
1842 | GF_FREE (fpath)__gf_free (fpath); | |||||
1843 | if (dict) | |||||
1844 | dict_unref (dict); | |||||
1845 | } | |||||
1846 | return ret; | |||||
1847 | } | |||||
1848 | ||||||
1849 | /* The global RPC service initializer. | |||||
1850 | */ | |||||
1851 | rpcsvc_t * | |||||
1852 | rpcsvc_init (xlator_t *xl, glusterfs_ctx_t *ctx, dict_t *options, | |||||
1853 | uint32_t poolcount) | |||||
1854 | { | |||||
1855 | rpcsvc_t *svc = NULL((void*)0); | |||||
1856 | int ret = -1; | |||||
1857 | ||||||
1858 | if ((!ctx) || (!options)) | |||||
1859 | return NULL((void*)0); | |||||
1860 | ||||||
1861 | svc = GF_CALLOC (1, sizeof (*svc), gf_common_mt_rpcsvc_t)__gf_calloc (1, sizeof (*svc), gf_common_mt_rpcsvc_t); | |||||
1862 | if (!svc) | |||||
1863 | return NULL((void*)0); | |||||
1864 | ||||||
1865 | pthread_mutex_init (&svc->rpclock, NULL((void*)0)); | |||||
1866 | INIT_LIST_HEAD (&svc->authschemes)do { (&svc->authschemes)->next = (&svc->authschemes )->prev = &svc->authschemes; } while (0); | |||||
1867 | INIT_LIST_HEAD (&svc->notify)do { (&svc->notify)->next = (&svc->notify)-> prev = &svc->notify; } while (0); | |||||
1868 | INIT_LIST_HEAD (&svc->listeners)do { (&svc->listeners)->next = (&svc->listeners )->prev = &svc->listeners; } while (0); | |||||
1869 | INIT_LIST_HEAD (&svc->programs)do { (&svc->programs)->next = (&svc->programs )->prev = &svc->programs; } while (0); | |||||
1870 | ||||||
1871 | ret = rpcsvc_init_options (svc, options); | |||||
1872 | if (ret == -1) { | |||||
1873 | gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to init options")do { do { if (0) printf ("Failed to init options"); } while ( 0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 1873, GF_LOG_ERROR , "Failed to init options"); } while (0); | |||||
1874 | goto free_svc; | |||||
1875 | } | |||||
1876 | ||||||
1877 | if (!poolcount) | |||||
1878 | poolcount = RPCSVC_POOLCOUNT_MULT64 * svc->memfactor; | |||||
1879 | ||||||
1880 | gf_log (GF_RPCSVC, GF_LOG_TRACE, "rx pool: %d", poolcount)do { do { if (0) printf ("rx pool: %d", poolcount); } while ( 0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 1880, GF_LOG_TRACE , "rx pool: %d", poolcount); } while (0); | |||||
1881 | svc->rxpool = mem_pool_new (rpcsvc_request_t, poolcount)mem_pool_new_fn (sizeof(rpcsvc_request_t), poolcount, "rpcsvc_request_t" ); | |||||
1882 | /* TODO: leak */ | |||||
1883 | if (!svc->rxpool) { | |||||
1884 | gf_log (GF_RPCSVC, GF_LOG_ERROR, "mem pool allocation failed")do { do { if (0) printf ("mem pool allocation failed"); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 1884, GF_LOG_ERROR, "mem pool allocation failed"); } while (0); | |||||
1885 | goto free_svc; | |||||
1886 | } | |||||
1887 | ||||||
1888 | ret = rpcsvc_auth_init (svc, options); | |||||
1889 | if (ret == -1) { | |||||
1890 | gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to init "do { do { if (0) printf ("Failed to init " "authentication"); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__ , 1891, GF_LOG_ERROR, "Failed to init " "authentication"); } while (0) | |||||
1891 | "authentication")do { do { if (0) printf ("Failed to init " "authentication"); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__ , 1891, GF_LOG_ERROR, "Failed to init " "authentication"); } while (0); | |||||
1892 | goto free_svc; | |||||
1893 | } | |||||
1894 | ||||||
1895 | ret = -1; | |||||
1896 | svc->options = options; | |||||
1897 | svc->ctx = ctx; | |||||
1898 | svc->mydata = xl; | |||||
1899 | gf_log (GF_RPCSVC, GF_LOG_DEBUG, "RPC service inited.")do { do { if (0) printf ("RPC service inited."); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 1899, GF_LOG_DEBUG , "RPC service inited."); } while (0); | |||||
1900 | ||||||
1901 | gluster_dump_prog.options = options; | |||||
1902 | ||||||
1903 | ret = rpcsvc_program_register (svc, &gluster_dump_prog); | |||||
1904 | if (ret) { | |||||
1905 | gf_log (GF_RPCSVC, GF_LOG_ERROR,do { do { if (0) printf ("failed to register DUMP program"); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 1906, GF_LOG_ERROR, "failed to register DUMP program"); } while (0) | |||||
1906 | "failed to register DUMP program")do { do { if (0) printf ("failed to register DUMP program"); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 1906, GF_LOG_ERROR, "failed to register DUMP program"); } while (0); | |||||
1907 | goto free_svc; | |||||
1908 | } | |||||
1909 | ret = 0; | |||||
1910 | free_svc: | |||||
1911 | if (ret == -1) { | |||||
1912 | GF_FREE (svc)__gf_free (svc); | |||||
1913 | svc = NULL((void*)0); | |||||
1914 | } | |||||
1915 | ||||||
1916 | return svc; | |||||
1917 | } | |||||
1918 | ||||||
1919 | ||||||
1920 | int | |||||
1921 | rpcsvc_transport_peer_check_search (dict_t *options, char *pattern, | |||||
1922 | char *ip, char *hostname) | |||||
1923 | { | |||||
1924 | int ret = -1; | |||||
1925 | char *addrtok = NULL((void*)0); | |||||
1926 | char *addrstr = NULL((void*)0); | |||||
1927 | char *dup_addrstr = NULL((void*)0); | |||||
1928 | char *svptr = NULL((void*)0); | |||||
1929 | ||||||
1930 | if ((!options) || (!ip)) | |||||
1931 | return -1; | |||||
1932 | ||||||
1933 | ret = dict_get_str (options, pattern, &addrstr); | |||||
1934 | if (ret < 0) { | |||||
1935 | ret = -1; | |||||
1936 | goto err; | |||||
1937 | } | |||||
1938 | ||||||
1939 | if (!addrstr) { | |||||
1940 | ret = -1; | |||||
1941 | goto err; | |||||
1942 | } | |||||
1943 | ||||||
1944 | dup_addrstr = gf_strdup (addrstr); | |||||
1945 | addrtok = strtok_r (dup_addrstr, ",", &svptr); | |||||
1946 | while (addrtok) { | |||||
1947 | ||||||
1948 | /* CASEFOLD not present on Solaris */ | |||||
1949 | #ifdef FNM_CASEFOLD(1 << 4) | |||||
1950 | ret = fnmatch (addrtok, ip, FNM_CASEFOLD(1 << 4)); | |||||
1951 | #else | |||||
1952 | ret = fnmatch (addrtok, ip, 0); | |||||
1953 | #endif | |||||
1954 | if (ret == 0) | |||||
1955 | goto err; | |||||
1956 | ||||||
1957 | /* compare hostnames if applicable */ | |||||
1958 | if (hostname) { | |||||
1959 | #ifdef FNM_CASEFOLD(1 << 4) | |||||
1960 | ret = fnmatch (addrtok, hostname, FNM_CASEFOLD(1 << 4)); | |||||
1961 | #else | |||||
1962 | ret = fnmatch (addrtok, hostname, 0); | |||||
1963 | #endif | |||||
1964 | if (ret == 0) | |||||
1965 | goto err; | |||||
1966 | } | |||||
1967 | ||||||
1968 | addrtok = strtok_r (NULL((void*)0), ",", &svptr); | |||||
1969 | } | |||||
1970 | ||||||
1971 | ret = -1; | |||||
1972 | err: | |||||
1973 | GF_FREE (dup_addrstr)__gf_free (dup_addrstr); | |||||
1974 | ||||||
1975 | return ret; | |||||
1976 | } | |||||
1977 | ||||||
1978 | ||||||
1979 | int | |||||
1980 | rpcsvc_transport_peer_check_allow (dict_t *options, char *volname, | |||||
1981 | char *ip, char *hostname) | |||||
1982 | { | |||||
1983 | int ret = RPCSVC_AUTH_DONTCARE3; | |||||
1984 | char *srchstr = NULL((void*)0); | |||||
1985 | ||||||
1986 | if ((!options) || (!ip) || (!volname)) | |||||
1987 | return ret; | |||||
1988 | ||||||
1989 | ret = gf_asprintf (&srchstr, "rpc-auth.addr.%s.allow", volname); | |||||
1990 | if (ret == -1) { | |||||
1991 | gf_log (GF_RPCSVC, GF_LOG_ERROR, "asprintf failed")do { do { if (0) printf ("asprintf failed"); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 1991, GF_LOG_ERROR , "asprintf failed"); } while (0); | |||||
1992 | ret = RPCSVC_AUTH_DONTCARE3; | |||||
1993 | goto out; | |||||
1994 | } | |||||
1995 | ||||||
1996 | ret = rpcsvc_transport_peer_check_search (options, srchstr, | |||||
1997 | ip, hostname); | |||||
1998 | GF_FREE (srchstr)__gf_free (srchstr); | |||||
1999 | ||||||
2000 | if (ret == 0) | |||||
2001 | ret = RPCSVC_AUTH_ACCEPT1; | |||||
2002 | else | |||||
2003 | ret = RPCSVC_AUTH_REJECT2; | |||||
2004 | out: | |||||
2005 | return ret; | |||||
2006 | } | |||||
2007 | ||||||
2008 | int | |||||
2009 | rpcsvc_transport_peer_check_reject (dict_t *options, char *volname, | |||||
2010 | char *ip, char *hostname) | |||||
2011 | { | |||||
2012 | int ret = RPCSVC_AUTH_DONTCARE3; | |||||
2013 | char *srchstr = NULL((void*)0); | |||||
2014 | ||||||
2015 | if ((!options) || (!ip) || (!volname)) | |||||
2016 | return ret; | |||||
2017 | ||||||
2018 | ret = gf_asprintf (&srchstr, "rpc-auth.addr.%s.reject", | |||||
2019 | volname); | |||||
2020 | if (ret == -1) { | |||||
2021 | gf_log (GF_RPCSVC, GF_LOG_ERROR, "asprintf failed")do { do { if (0) printf ("asprintf failed"); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 2021, GF_LOG_ERROR , "asprintf failed"); } while (0); | |||||
2022 | ret = RPCSVC_AUTH_REJECT2; | |||||
2023 | goto out; | |||||
2024 | } | |||||
2025 | ||||||
2026 | ret = rpcsvc_transport_peer_check_search (options, srchstr, | |||||
2027 | ip, hostname); | |||||
2028 | GF_FREE (srchstr)__gf_free (srchstr); | |||||
2029 | ||||||
2030 | if (ret == 0) | |||||
2031 | ret = RPCSVC_AUTH_REJECT2; | |||||
2032 | else | |||||
2033 | ret = RPCSVC_AUTH_DONTCARE3; | |||||
2034 | out: | |||||
2035 | return ret; | |||||
2036 | } | |||||
2037 | ||||||
2038 | ||||||
2039 | /* Combines rpc auth's allow and reject options. | |||||
2040 | * Order of checks is important. | |||||
2041 | * First, REJECT if either rejects. | |||||
2042 | * If neither rejects, ACCEPT if either accepts. | |||||
2043 | * If neither accepts, DONTCARE | |||||
2044 | */ | |||||
2045 | int | |||||
2046 | rpcsvc_combine_allow_reject_volume_check (int allow, int reject) | |||||
2047 | { | |||||
2048 | if (allow == RPCSVC_AUTH_REJECT2 || | |||||
2049 | reject == RPCSVC_AUTH_REJECT2) | |||||
2050 | return RPCSVC_AUTH_REJECT2; | |||||
2051 | ||||||
2052 | if (allow == RPCSVC_AUTH_ACCEPT1 || | |||||
2053 | reject == RPCSVC_AUTH_ACCEPT1) | |||||
2054 | return RPCSVC_AUTH_ACCEPT1; | |||||
2055 | ||||||
2056 | return RPCSVC_AUTH_DONTCARE3; | |||||
2057 | } | |||||
2058 | ||||||
2059 | int | |||||
2060 | rpcsvc_auth_check (dict_t *options, char *volname, | |||||
2061 | rpc_transport_t *trans) | |||||
2062 | { | |||||
2063 | int ret = RPCSVC_AUTH_REJECT2; | |||||
2064 | int accept = RPCSVC_AUTH_REJECT2; | |||||
2065 | int reject = RPCSVC_AUTH_REJECT2; | |||||
2066 | char *hostname = NULL((void*)0); | |||||
2067 | char *ip = NULL((void*)0); | |||||
2068 | char client_ip[RPCSVC_PEER_STRLEN1024] = {0}; | |||||
2069 | ||||||
2070 | if (!options || !volname || !trans) | |||||
2071 | return ret; | |||||
2072 | ||||||
2073 | ret = rpcsvc_transport_peername (trans, client_ip, RPCSVC_PEER_STRLEN1024); | |||||
2074 | if (ret != 0) { | |||||
2075 | gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to get remote addr: "do { do { if (0) printf ("Failed to get remote addr: " "%s", gai_strerror (ret)); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__ , 2076, GF_LOG_ERROR, "Failed to get remote addr: " "%s", gai_strerror (ret)); } while (0) | |||||
2076 | "%s", gai_strerror (ret))do { do { if (0) printf ("Failed to get remote addr: " "%s", gai_strerror (ret)); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__ , 2076, GF_LOG_ERROR, "Failed to get remote addr: " "%s", gai_strerror (ret)); } while (0); | |||||
2077 | return RPCSVC_AUTH_REJECT2; | |||||
2078 | } | |||||
2079 | ||||||
2080 | get_host_name (client_ip, &ip); | |||||
2081 | ||||||
2082 | /* addr-namelookup disabled by default */ | |||||
2083 | ret = dict_get_str_boolean (options, "rpc-auth.addr.namelookup", 0); | |||||
2084 | if (ret == _gf_true) | |||||
2085 | gf_get_hostname_from_ip (ip, &hostname); | |||||
2086 | ||||||
2087 | accept = rpcsvc_transport_peer_check_allow (options, volname, | |||||
2088 | ip, hostname); | |||||
2089 | ||||||
2090 | reject = rpcsvc_transport_peer_check_reject (options, volname, | |||||
2091 | ip, hostname); | |||||
2092 | ||||||
2093 | return rpcsvc_combine_allow_reject_volume_check (accept, reject); | |||||
2094 | } | |||||
2095 | ||||||
2096 | int | |||||
2097 | rpcsvc_transport_privport_check (rpcsvc_t *svc, char *volname, | |||||
2098 | rpc_transport_t *trans) | |||||
2099 | { | |||||
2100 | union gf_sock_union sock_union; | |||||
2101 | int ret = RPCSVC_AUTH_REJECT2; | |||||
2102 | socklen_t sinsize = sizeof (&sock_union.sin); | |||||
2103 | char *srchstr = NULL((void*)0); | |||||
2104 | char *valstr = NULL((void*)0); | |||||
2105 | uint16_t port = 0; | |||||
2106 | gf_boolean_t insecure = _gf_false; | |||||
2107 | ||||||
2108 | memset (&sock_union, 0, sizeof (sock_union)); | |||||
2109 | ||||||
2110 | if ((!svc) || (!volname) || (!trans)) | |||||
2111 | return ret; | |||||
2112 | ||||||
2113 | ret = rpcsvc_transport_peeraddr (trans, NULL((void*)0), 0, &sock_union.storage, | |||||
2114 | sinsize); | |||||
2115 | if (ret != 0) { | |||||
2116 | gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to get peer addr: %s",do { do { if (0) printf ("Failed to get peer addr: %s", gai_strerror (ret)); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__ , 2117, GF_LOG_ERROR, "Failed to get peer addr: %s", gai_strerror (ret)); } while (0) | |||||
2117 | gai_strerror (ret))do { do { if (0) printf ("Failed to get peer addr: %s", gai_strerror (ret)); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__ , 2117, GF_LOG_ERROR, "Failed to get peer addr: %s", gai_strerror (ret)); } while (0); | |||||
2118 | ret = RPCSVC_AUTH_REJECT2; | |||||
2119 | goto err; | |||||
2120 | } | |||||
2121 | ||||||
2122 | port = ntohs (sock_union.sin.sin_port); | |||||
2123 | gf_log (GF_RPCSVC, GF_LOG_TRACE, "Client port: %d", (int)port)do { do { if (0) printf ("Client port: %d", (int)port); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 2123, GF_LOG_TRACE, "Client port: %d", (int)port); } while (0); | |||||
2124 | /* If the port is already a privileged one, dont bother with checking | |||||
2125 | * options. | |||||
2126 | */ | |||||
2127 | if (port <= 1024) { | |||||
2128 | ret = RPCSVC_AUTH_ACCEPT1; | |||||
2129 | goto err; | |||||
2130 | } | |||||
2131 | ||||||
2132 | /* Disabled by default */ | |||||
2133 | ret = gf_asprintf (&srchstr, "rpc-auth.ports.%s.insecure", volname); | |||||
2134 | if (ret == -1) { | |||||
2135 | gf_log (GF_RPCSVC, GF_LOG_ERROR, "asprintf failed")do { do { if (0) printf ("asprintf failed"); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 2135, GF_LOG_ERROR , "asprintf failed"); } while (0); | |||||
2136 | ret = RPCSVC_AUTH_REJECT2; | |||||
2137 | goto err; | |||||
2138 | } | |||||
2139 | ||||||
2140 | ret = dict_get_str (svc->options, srchstr, &valstr); | |||||
2141 | if (ret) { | |||||
2142 | gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to"do { do { if (0) printf ("Failed to" " read rpc-auth.ports.insecure value" ); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__ , 2143, GF_LOG_ERROR, "Failed to" " read rpc-auth.ports.insecure value" ); } while (0) | |||||
2143 | " read rpc-auth.ports.insecure value")do { do { if (0) printf ("Failed to" " read rpc-auth.ports.insecure value" ); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__ , 2143, GF_LOG_ERROR, "Failed to" " read rpc-auth.ports.insecure value" ); } while (0); | |||||
2144 | goto err; | |||||
2145 | } | |||||
2146 | ||||||
2147 | ret = gf_string2boolean (valstr, &insecure); | |||||
2148 | if (ret) { | |||||
2149 | gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to"do { do { if (0) printf ("Failed to" " convert rpc-auth.ports.insecure value" ); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__ , 2150, GF_LOG_ERROR, "Failed to" " convert rpc-auth.ports.insecure value" ); } while (0) | |||||
2150 | " convert rpc-auth.ports.insecure value")do { do { if (0) printf ("Failed to" " convert rpc-auth.ports.insecure value" ); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__ , 2150, GF_LOG_ERROR, "Failed to" " convert rpc-auth.ports.insecure value" ); } while (0); | |||||
2151 | goto err; | |||||
2152 | } | |||||
2153 | ||||||
2154 | ret = insecure ? RPCSVC_AUTH_ACCEPT1 : RPCSVC_AUTH_REJECT2; | |||||
2155 | ||||||
2156 | if (ret == RPCSVC_AUTH_ACCEPT1) | |||||
2157 | gf_log (GF_RPCSVC, GF_LOG_DEBUG, "Unprivileged port allowed")do { do { if (0) printf ("Unprivileged port allowed"); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 2157, GF_LOG_DEBUG, "Unprivileged port allowed"); } while (0); | |||||
2158 | else | |||||
2159 | gf_log (GF_RPCSVC, GF_LOG_DEBUG, "Unprivileged port not"do { do { if (0) printf ("Unprivileged port not" " allowed"); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__ , 2160, GF_LOG_DEBUG, "Unprivileged port not" " allowed"); } while (0) | |||||
2160 | " allowed")do { do { if (0) printf ("Unprivileged port not" " allowed"); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__ , 2160, GF_LOG_DEBUG, "Unprivileged port not" " allowed"); } while (0); | |||||
2161 | ||||||
2162 | err: | |||||
2163 | if (srchstr) | |||||
2164 | GF_FREE (srchstr)__gf_free (srchstr); | |||||
2165 | ||||||
2166 | return ret; | |||||
2167 | } | |||||
2168 | ||||||
2169 | ||||||
2170 | char * | |||||
2171 | rpcsvc_volume_allowed (dict_t *options, char *volname) | |||||
2172 | { | |||||
2173 | char globalrule[] = "rpc-auth.addr.allow"; | |||||
2174 | char *srchstr = NULL((void*)0); | |||||
2175 | char *addrstr = NULL((void*)0); | |||||
2176 | int ret = -1; | |||||
2177 | ||||||
2178 | if ((!options) || (!volname)) | |||||
2179 | return NULL((void*)0); | |||||
2180 | ||||||
2181 | ret = gf_asprintf (&srchstr, "rpc-auth.addr.%s.allow", volname); | |||||
2182 | if (ret == -1) { | |||||
2183 | gf_log (GF_RPCSVC, GF_LOG_ERROR, "asprintf failed")do { do { if (0) printf ("asprintf failed"); } while (0); _gf_log ("rpc-service", "rpcsvc.c", __FUNCTION__, 2183, GF_LOG_ERROR , "asprintf failed"); } while (0); | |||||
2184 | goto out; | |||||
2185 | } | |||||
2186 | ||||||
2187 | if (!dict_get (options, srchstr)) | |||||
2188 | ret = dict_get_str (options, globalrule, &addrstr); | |||||
2189 | else | |||||
2190 | ret = dict_get_str (options, srchstr, &addrstr); | |||||
2191 | ||||||
2192 | out: | |||||
2193 | GF_FREE (srchstr)__gf_free (srchstr); | |||||
2194 | ||||||
2195 | return addrstr; | |||||
2196 | } | |||||
2197 | ||||||
2198 | ||||||
2199 | rpcsvc_actor_t gluster_dump_actors[] = { | |||||
2200 | [GF_DUMP_NULL] = {"NULL", GF_DUMP_NULL, NULL((void*)0), NULL((void*)0), 0}, | |||||
2201 | [GF_DUMP_DUMP] = {"DUMP", GF_DUMP_DUMP, rpcsvc_dump, NULL((void*)0), 0}, | |||||
2202 | [GF_DUMP_MAXVALUE] = {"MAXVALUE", GF_DUMP_MAXVALUE, NULL((void*)0), NULL((void*)0), 0}, | |||||
2203 | }; | |||||
2204 | ||||||
2205 | ||||||
2206 | struct rpcsvc_program gluster_dump_prog = { | |||||
2207 | .progname = "GF-DUMP", | |||||
2208 | .prognum = GLUSTER_DUMP_PROGRAM123451501, | |||||
2209 | .progver = GLUSTER_DUMP_VERSION1, | |||||
2210 | .actors = gluster_dump_actors, | |||||
2211 | .numactors = 2, | |||||
2212 | }; |