1 /*
2  * Copyright (C) 2006 iptelorg GmbH
3  *
4  * This file is part of Kamailio, a free SIP server.
5  *
6  * Kamailio is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version
10  *
11  * Kamailio is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19  */
20 
21 
22 #include "binrpc.h"
23 #include "../../core/dprint.h"
24 #include "../../core/rpc.h"
25 #include "../../core/sr_module.h"
26 #include "../../core/mem/mem.h"
27 #include "../../core/clist.h"
28 #include "io_listener.h"
29 #include "ctl.h"
30 
31 #include <stdio.h>  /* vsnprintf */
32 #include <stdlib.h> /* strtod */
33 #include <stdarg.h>
34 
35 #define DEFAULT_RPC_PRINTF_BUF_SIZE	1024
36 
37 /* if set try to automatically convert values to the requested type in
38    rpc->scan (default: not set) */
39 int autoconvert=0;
40 
41 int binrpc_max_body_size = 32; /* multiplied by 1024 in mod init */
42 int binrpc_struct_max_body_size = 8; /* multiplied by 1024 in mod init */
43 int binrpc_buffer_size = DEFAULT_RPC_PRINTF_BUF_SIZE;
44 
45 #define BINRPC_MAX_BODY	binrpc_max_body_size  /* maximum body for send */
46 #define STRUCT_MAX_BODY	binrpc_struct_max_body_size
47 #define MAX_MSG_CHUNKS	96
48 
49 #define BINRPC_GC_IBSIZE 4 /* initial gc block size (pointers no.) */
50 
51 struct rpc_struct_head{
52 	struct rpc_struct_l* next;
53 	struct rpc_struct_l* prev;
54 };
55 
56 
57 struct rpc_struct_l{
58 	struct rpc_struct_l* next;
59 	struct rpc_struct_l* prev;
60 	struct binrpc_pkt pkt;
61 	struct rpc_struct_head substructs; /* head */
62 	int offset; /* byte offset in parent's pkt */
63 };
64 
65 struct binrpc_send_ctx{
66 	struct binrpc_pkt pkt; /* body */
67 	struct rpc_struct_head structs; /* list head */
68 };
69 
70 struct binrpc_recv_ctx{
71 	struct binrpc_parse_ctx ctx;
72 	unsigned char*  s; /* current position in buffer */
73 	unsigned char* end;
74 	int record_no;
75 	int in_struct;
76 };
77 
78 
79 struct binrpc_gc_block{
80 	unsigned short p_no; /**< array size */
81 	unsigned short idx;  /**< current/last used pos. in the array */
82 	struct binrpc_gc_block* next;
83 	void* p[1]; /**< array of pointers that will be free'd */
84 };
85 
86 
87 struct binrpc_ctx{
88 	struct binrpc_recv_ctx in;
89 	struct binrpc_send_ctx out;
90 	void* send_h; /* send handle */
91 	char* method;
92 	struct binrpc_gc_block* gc; /**< garbage collection */
93 	int replied;
94 	int err_code;
95 	str err_phrase;	/**< Leading zero must be included! */
96 };
97 
98 
99 struct iovec_array{
100 	struct iovec* v;
101 	int idx;
102 	int len;
103 	void *ctx;
104 };
105 
106 /* send */
107 static void rpc_fault(struct binrpc_ctx* ctx, int code, char* fmt, ...);
108 static int rpc_send(struct binrpc_ctx* ctx);
109 static int rpc_send_v(struct iovec_array *a);
110 static int rpc_add(struct binrpc_ctx* ctx, char* fmt, ...);
111 static int rpc_scan(struct binrpc_ctx* ctx, char* fmt, ...);
112 static int rpc_rpl_printf(struct binrpc_ctx* ctx, char* fmt, ...);
113 static int rpc_struct_add(struct rpc_struct_l* s, char* fmt, ...);
114 static int rpc_array_add(struct rpc_struct_l* s, char* fmt, ...);
115 static int rpc_struct_scan(struct rpc_struct_l* s, char* fmt, ...);
116 /* struct scan */
117 static int rpc_struct_printf(struct rpc_struct_l *s, char* name,
118 								char* fmt, ...);
119 
120 
121 static rpc_t binrpc_callbacks;
122 
binrpc_callbacks_init(void)123 void binrpc_callbacks_init(void)
124 {
125 	memset(&binrpc_callbacks, 0, sizeof(binrpc_callbacks));
126 	binrpc_callbacks.fault         = (rpc_fault_f)rpc_fault;
127 	binrpc_callbacks.send          = (rpc_send_f)rpc_send;
128 	binrpc_callbacks.add           = (rpc_add_f)rpc_add;
129 	binrpc_callbacks.scan          = (rpc_scan_f)rpc_scan;
130 	binrpc_callbacks.rpl_printf    = (rpc_rpl_printf_f)rpc_rpl_printf;
131 	binrpc_callbacks.struct_add    = (rpc_struct_add_f)rpc_struct_add;
132 	binrpc_callbacks.array_add     = (rpc_struct_add_f)rpc_array_add;
133 	binrpc_callbacks.struct_scan   = (rpc_struct_scan_f)rpc_struct_scan;
134 	binrpc_callbacks.struct_printf = (rpc_struct_printf_f)rpc_struct_printf;
135 }
136 
137 /** mark a pointer for freeing when the ctx is destroyed.
138  * @return 0 on success, -1 on error
139  */
binrpc_gc_track(struct binrpc_ctx * ctx,void * p)140 inline static int binrpc_gc_track(struct binrpc_ctx* ctx, void* p)
141 {
142 	struct binrpc_gc_block* b;
143 	int n;
144 
145 	b=ctx->gc;
146 	if (b==0 || (b->idx>=b->p_no)){
147 		n=(b==0)?BINRPC_GC_IBSIZE:b->p_no*2;
148 		b=ctl_malloc(sizeof(*b)+n*sizeof(void*)-sizeof(b->p));
149 		if (b==0)
150 			return -1;
151 		b->p_no=n;
152 		b->idx=0;
153 		/* link in front */
154 		b->next=ctx->gc;
155 		ctx->gc=b;
156 	}
157 	b->p[b->idx]=p;
158 	b->idx++;
159 	return 0;
160 }
161 
162 
163 
164 /** free all the tracked pointer from ctx->gc.
165  */
binrpc_gc_collect(struct binrpc_ctx * ctx)166 inline static void binrpc_gc_collect(struct binrpc_ctx* ctx)
167 {
168 	struct binrpc_gc_block* b;
169 	struct binrpc_gc_block* next;
170 	int i;
171 
172 	for(b=ctx->gc; b; b=next){
173 		next=b->next;
174 		for (i=0; i<b->idx; i++)
175 			ctl_free(b->p[i]);
176 		ctl_free(b);
177 	}
178 	ctx->gc=0;
179 }
180 
181 
new_rpc_struct()182 static struct rpc_struct_l* new_rpc_struct()
183 {
184 	struct rpc_struct_l* rs;
185 
186 	/* alloc everything in one chunk */
187 	rs=ctl_malloc(sizeof(struct rpc_struct_l)+STRUCT_MAX_BODY);
188 	if (rs==0)
189 		goto error;
190 	memset(rs, 0, sizeof(struct rpc_struct_l));
191 	clist_init(&rs->substructs, next, prev);
192 	if (binrpc_init_pkt(&rs->pkt,
193 				(unsigned char*)rs+sizeof(struct rpc_struct_l),
194 				STRUCT_MAX_BODY)<0){
195 		ctl_free(rs);
196 		goto error;
197 	}
198 	return rs;
199 error:
200 	return 0;
201 }
202 
203 
204 
205 #if 0 /* not used yet */
206 /* doubles the size */
207 static struct rpc_struct_l* grow_rpc_struct(struct rpc_struct_l *rs)
208 {
209 
210 	struct rpc_struct_l* new_rs;
211 	int csize; /* body */
212 
213 	csize=binrpc_pkt_len(&rs->pkt);
214 	csize*=2;
215 	new_rs=ctl_realloc(rs, sizeof(struct rpc_struct_l)+csize);
216 	if (new_rs){
217 		binrpc_pkt_update_buf(&rs->pkt,
218 							(unsigned char*)new_rs+sizeof(struct rpc_struct_l),
219 							csize);
220 	}
221 	return new_rs;
222 }
223 #endif
224 
225 
226 #if 0
227 /* appends buf to an already init. binrpc_pkt */
228 inline static int append_pkt_body(struct binrpc_pkt* p, unsigned char* buf,
229 							int len)
230 {
231 
232 	if ((int)(p->end-p->crt)<len){
233 		goto error;
234 #if 0
235 		size=2*(int)(p->end-p->body);
236 		offset=binrpc_pkt_len(p);
237 		for(;(size-offset)<len; size*=2); /* find new size */
238 		new_b=ctl_realloc(p->body, size);
239 		if (new_b==0)
240 			goto error;
241 		binrpc_pkt_update_buf(p, new_b, size);
242 #endif
243 	}
244 	memcpy(p->crt, buf, len);
245 	p->crt+=len;
246 	return 0;
247 error:
248 	return -1; /* buff. overflow */
249 }
250 #endif
251 
252 
append_iovec(struct iovec_array * a,unsigned char * buf,int len)253 inline static int append_iovec(struct iovec_array* a, unsigned char* buf,
254 								int len)
255 {
256 	int ret;
257 
258 	if (a->idx >= a->len) {
259 		ret = rpc_send_v(a);
260 		if (ret < 0)
261 			return ret;
262 	}
263 	a->v[a->idx].iov_base=buf;
264 	a->v[a->idx].iov_len=len;
265 	a->idx++;
266 	return 0;
267 }
268 
269 
270 
body_get_len(struct binrpc_pkt * body,struct rpc_struct_head * sl_head)271 static int body_get_len(struct binrpc_pkt* body,
272 							struct rpc_struct_head* sl_head)
273 {
274 	struct rpc_struct_l* l;
275 	int len;
276 
277 	len=binrpc_pkt_len(body);
278 	clist_foreach(sl_head, l, next){
279 		len+=body_get_len(&l->pkt, &l->substructs);
280 	}
281 	return len;
282 }
283 
284 
285 
body_fill_iovec(struct iovec_array * v_a,struct binrpc_pkt * body,struct rpc_struct_head * sl_head)286 static int body_fill_iovec(struct iovec_array* v_a,
287 							struct binrpc_pkt* body,
288 							struct rpc_struct_head* sl_head)
289 {
290 	int offs;
291 	struct rpc_struct_l* l;
292 	int ret;
293 
294 	offs=0;
295 	clist_foreach(sl_head, l, next){
296 		if ((ret=append_iovec(v_a, body->body+offs, l->offset-offs))<0)
297 			goto error;
298 		offs=l->offset;
299 		if ((ret=body_fill_iovec(v_a, &l->pkt, &l->substructs))<0)
300 			goto error;
301 	};
302 	/* copy the rest */
303 	ret=append_iovec(v_a, body->body+offs, binrpc_pkt_len(body)-offs);
304 error:
305 	return ret;
306 }
307 
308 
309 
310 #if 0
311 /* expects an initialized new_b */
312 static int build_structs(struct binrpc_pkt *new_b, struct binrpc_pkt* body,
313 							struct rpc_struct_head* sl_head)
314 {
315 	int offs;
316 	struct rpc_struct_l* l;
317 	int ret;
318 
319 	offs=0;
320 	clist_foreach(sl_head, l, next){
321 		if ((ret=append_pkt_body(new_b, body->body+offs, l->offset-offs))<0)
322 			goto error;
323 		offs=l->offset;
324 		if ((ret=build_structs(new_b, &l->pkt, &l->substructs))<0)
325 			goto error;
326 	};
327 	/* copy the rest */
328 	ret=append_pkt_body(new_b, body->body+offs, binrpc_pkt_len(body)-offs);
329 error:
330 	return ret;
331 }
332 #endif
333 
334 
335 
free_structs(struct rpc_struct_head * sl_head)336 static void free_structs(struct rpc_struct_head* sl_head)
337 {
338 	struct rpc_struct_l* l;
339 	struct rpc_struct_l* tmp;
340 
341 	clist_foreach_safe(sl_head, l, tmp, next){
342 		free_structs(&l->substructs);
343 		memset(l, 0, sizeof(struct rpc_struct_l)); /* debugging */
344 		ctl_free(l);
345 	};
346 }
347 
348 
349 
init_binrpc_ctx(struct binrpc_ctx * ctx,unsigned char * recv_buf,int recv_buf_len,void * send_handle)350 inline static int init_binrpc_ctx(	struct binrpc_ctx* ctx,
351 									unsigned char* recv_buf,
352 									int recv_buf_len,
353 									void* send_handle
354 								)
355 {
356 	int err;
357 	unsigned char* send_buf;
358 	int send_buf_len;
359 
360 	memset(ctx, 0, sizeof(struct binrpc_ctx));
361 	clist_init(&ctx->out.structs, next, prev);
362 	ctx->send_h=send_handle;
363 	ctx->in.end=recv_buf+recv_buf_len;
364 	ctx->in.s=binrpc_parse_init(&ctx->in.ctx, recv_buf, recv_buf_len, &err);
365 	if (err<0) goto end;
366 	if ((ctx->in.ctx.tlen+(int)(ctx->in.s-recv_buf))>recv_buf_len){
367 		err=E_BINRPC_MORE_DATA;
368 		goto end;
369 	}
370 	/* fix end value */
371 	ctx->in.end=ctx->in.s+ctx->in.ctx.tlen;
372 
373 	/* alloc temporary body buffer */
374 	send_buf_len=BINRPC_MAX_BODY;
375 	send_buf=ctl_malloc(send_buf_len);
376 	if (send_buf==0){
377 		err=E_BINRPC_LAST;
378 		goto end;
379 	}
380 	/* we'll keep only the body */
381 	err=binrpc_init_pkt(&ctx->out.pkt, send_buf, send_buf_len);
382 	if(err!=0) {
383 		ctl_free(send_buf);
384 	}
385 end:
386 	return err;
387 }
388 
389 
390 
destroy_binrpc_ctx(struct binrpc_ctx * ctx)391 static inline void destroy_binrpc_ctx(struct binrpc_ctx* ctx)
392 {
393 	free_structs(&ctx->out.structs);
394 	if (ctx->out.pkt.body){
395 		ctl_free(ctx->out.pkt.body);
396 		ctx->out.pkt.body=0;
397 	}
398 	if (ctx->err_phrase.s){
399 		ctl_free(ctx->err_phrase.s);
400 		ctx->err_phrase.s=NULL;
401 	}
402 	binrpc_gc_collect(ctx);
403 }
404 
405 
406 
407 #define MAX_FAULT_LEN 256
408 #define FAULT_START_BUF (3 /* maxint*/+2/*max str header*/)
_rpc_fault(struct binrpc_ctx * ctx,int code,char * phrase,int phrase_len)409 static void _rpc_fault(struct binrpc_ctx* ctx, int code,
410 			char *phrase, int phrase_len)
411 {
412 	static unsigned char fault_start[FAULT_START_BUF];
413 	static unsigned char hdr[BINRPC_MAX_HDR_SIZE];
414 	struct iovec v[3];
415 	struct binrpc_pkt body;
416 	int b_len;
417 	int hdr_len;
418 	int err;
419 
420 	if (ctx->replied){
421 		LOG(L_ERR, "ERROR: binrpc: rpc_send: rpc method %s tried to reply"
422 					" more then once\n", ctx->method?ctx->method:"");
423 		return;
424 	}
425 	err=0;
426 	err=binrpc_init_pkt(&body, fault_start, FAULT_START_BUF);
427 	if (err<0){
428 		LOG(L_ERR, "ERROR: binrpc_init_pkt error\n");
429 		goto error;
430 	}
431 	/* adding a fault "manually" to avoid extra memcpys */
432 	err=binrpc_addint(&body, code);
433 	if (err<0){
434 		LOG(L_ERR, "ERROR: _rpc_fault: addint error\n");
435 		goto error;
436 	}
437 	err=binrpc_add_str_mark(&body, BINRPC_T_STR, phrase_len);
438 	if (err<0){
439 		LOG(L_ERR, "ERROR: _rpc_fault: add_str_mark error\n");
440 		goto error;
441 	}
442 	/*
443 	err=binrpc_addfault(&body, code, phrase, phrase_len);
444 	if (err<0){
445 		LOG(L_ERR, "ERROR: binrpc_addfault error\n");
446 		goto error;
447 	}*/
448 	b_len=binrpc_pkt_len(&body);
449 	err=hdr_len=binrpc_build_hdr(BINRPC_FAULT, b_len+phrase_len,
450 								ctx->in.ctx.cookie, hdr, BINRPC_MAX_HDR_SIZE);
451 	if (err<0){
452 		LOG(L_ERR, "ERROR: binrpc_build_hdr error\n");
453 		goto error;
454 	}
455 	v[0].iov_base=hdr;
456 	v[0].iov_len=hdr_len;
457 	v[1].iov_base=body.body;
458 	v[1].iov_len=b_len;
459 	v[2].iov_base=phrase;
460 	v[2].iov_len=phrase_len;
461 	if ((err=sock_send_v(ctx->send_h, v, 3))<0){
462 		if (err==-2){
463 			LOG(L_ERR, "ERROR: _rpc_fault: send failed: "
464 					"datagram too big\n");
465 			return;
466 		}
467 		LOG(L_ERR, "ERROR: _rpc_fault: send failed\n");
468 		return;
469 	}
470 	ctx->replied=1;
471 	return;
472 error:
473 	LOG(L_ERR, "ERROR: _rpc_fault: binrpc_* failed with: %s (%d)\n",
474 			binrpc_error(err), err);
475 }
476 
rpc_fault(struct binrpc_ctx * ctx,int code,char * fmt,...)477 static void rpc_fault(struct binrpc_ctx* ctx, int code, char* fmt, ...)
478 {
479 	char buf[MAX_FAULT_LEN];
480 	va_list ap;
481 	int len;
482 
483 	if (ctx->replied){
484 		LOG(L_ERR, "ERROR: binrpc: rpc_send: rpc method %s tried to reply"
485 					" more then once\n", ctx->method?ctx->method:"");
486 		return;
487 	}
488 	va_start(ap, fmt);
489 	len=vsnprintf(buf, MAX_FAULT_LEN, fmt, ap); /* ignore trunc. errors */
490 	if ((len<0) || (len > MAX_FAULT_LEN))
491 		len=MAX_FAULT_LEN-1;
492 	va_end(ap);
493 
494 	len++; /* vnsprintf doesn't include the terminating 0 */
495 	_rpc_fault(ctx, code, buf, len);
496 }
497 
498 /* Prepare the error reply without sending out the message */
rpc_fault_prepare(struct binrpc_ctx * ctx,int code,char * fmt,...)499 static int rpc_fault_prepare(struct binrpc_ctx* ctx, int code, char* fmt, ...)
500 {
501 	char buf[MAX_FAULT_LEN];
502 	va_list ap;
503 	int len;
504 
505 	if (ctx->replied){
506 		LOG(L_ERR, "ERROR: binrpc: rpc_send: rpc method %s tried to reply"
507 					" more then once\n", ctx->method?ctx->method:"");
508 		return -1;
509 	}
510 	va_start(ap, fmt);
511 	len=vsnprintf(buf, MAX_FAULT_LEN, fmt, ap); /* ignore trunc. errors */
512 	if ((len<0) || (len >= MAX_FAULT_LEN))
513 		len=MAX_FAULT_LEN-1;
514 	va_end(ap);
515 
516 	len++; /* vnsprintf doesn't include the terminating 0 */
517 
518 	ctx->err_code = code;
519 	if (ctx->err_phrase.s)
520 		ctl_free(ctx->err_phrase.s);
521 	ctx->err_phrase.s = (char*)ctl_malloc(sizeof(char)*len);
522 	if (!ctx->err_phrase.s) {
523 		ctx->err_code = 0;
524 		ctx->err_phrase.len = 0;
525 		LOG(L_ERR, "ERROR: rpc_fault_prepare: not enough memory\n");
526 		return -1;
527 	}
528 	memcpy(ctx->err_phrase.s, buf, len);
529 	ctx->err_phrase.len = len;
530 	return 0;
531 }
532 
533 /* Reset the saved error code */
rpc_fault_reset(struct binrpc_ctx * ctx)534 static void rpc_fault_reset(struct binrpc_ctx* ctx)
535 {
536 	ctx->err_code = 0;
537 	if (ctx->err_phrase.s) {
538 		ctl_free(ctx->err_phrase.s);
539 		ctx->err_phrase.s = NULL;
540 		ctx->err_phrase.len = 0;
541 	}
542 }
543 
544 /* wrapper around sock_send_v for staggered buffer writing */
rpc_send_v(struct iovec_array * a)545 static int rpc_send_v(struct iovec_array *a)
546 {
547 	int ret;
548 
549 	if (a->idx <= 0)
550 		return 0;
551 
552 	ret = sock_send_v(a->ctx, a->v, a->idx);
553 	if (ret < 0)
554 		return ret;
555 
556 	a->idx = 0;
557 	return 0;
558 }
559 
560 /* build the reply from the current body */
rpc_send(struct binrpc_ctx * ctx)561 static int rpc_send(struct binrpc_ctx* ctx)
562 {
563 	int b_len;
564 	int hdr_len;
565 	struct iovec v[MAX_MSG_CHUNKS];
566 	struct iovec_array a;
567 	static unsigned char hdr[BINRPC_MAX_HDR_SIZE];
568 	int err;
569 
570 	err=0;
571 	a.v=v;
572 	a.idx=1;
573 	a.len=MAX_MSG_CHUNKS;
574 	a.ctx = ctx->send_h;
575 
576 	if (ctx->replied){
577 		LOG(L_ERR, "ERROR: binrpc: rpc_send: rpc method %s tried to reply"
578 					" more then once\n", ctx->method?ctx->method:"");
579 		goto error;
580 	}
581 	b_len=body_get_len(&ctx->out.pkt, &ctx->out.structs);
582 	err=hdr_len=binrpc_build_hdr( BINRPC_REPL, b_len, ctx->in.ctx.cookie,
583 									hdr, BINRPC_MAX_HDR_SIZE);
584 	if (err<0){
585 		LOG(L_ERR, "ERROR: binrpc: rpc_fault: binrpc_* failed with:"
586 					" %s (%d)\n", binrpc_error(err), err);
587 		goto error;
588 	}
589 	v[0].iov_base=hdr;
590 	v[0].iov_len=hdr_len;
591 	/* fill the rest of the iovecs */
592 	err=body_fill_iovec(&a, &ctx->out.pkt, &ctx->out.structs);
593 	if (err<0){
594 		LOG(L_ERR, "ERROR: binrprc: rpc_send: too many message chunks\n");
595 		goto error;
596 	}
597 	if ((err = rpc_send_v(&a)) < 0){
598 		if (err==-2){
599 			LOG(L_ERR, "ERROR: binrpc: rpc_send: send failed: "
600 					"datagram too big\n");
601 			goto error;
602 		}
603 		LOG(L_ERR, "ERROR: binrprc: rpc_send: send failed\n");
604 		goto error;
605 	}
606 	ctx->replied=1;
607 	return 0;
608 error:
609 	return -1;
610 }
611 
612 
613 
614 /* params: buf, size     - buffer containing the packet
615  *         bytes_needed  - int pointer, filled with how many bytes are still
616  *                         needed (after bytes_needed new bytes received this
617  *                         function will be called again
618  *         reply,        - buffer where the reply will be written
619  *         reply_len     - intially filled with the reply buffer len,
620  *                         after the call will contain how much of that
621  *                         buffer was really used
622  * returns: number of bytes processed on success/partial success
623  *          -1 on error
624  */
process_rpc_req(unsigned char * buf,int size,int * bytes_needed,void * sh,void ** saved_state)625 int process_rpc_req(unsigned char* buf, int size, int* bytes_needed,
626 					void* sh, void** saved_state)
627 {
628 	int err;
629 	struct binrpc_val val;
630 	rpc_export_t* rpc_e;
631 	struct binrpc_ctx f_ctx;
632 	struct binrpc_parse_ctx* ctx;
633 
634 	if(ksr_shutdown_phase()) {
635 		/* during shutdown - no more RPC command handling */
636 		LM_DBG("shutdown phase - skipping rpc command\n");
637 		return -1;
638 	}
639 
640 	if (size<BINRPC_MIN_PKT_SIZE){
641 		*bytes_needed=BINRPC_MIN_PKT_SIZE-size;
642 		LM_DBG("more data needed - at least: %d bytes\n", *bytes_needed);
643 		return 0; /* more data, nothing processed */
644 	}
645 	err=init_binrpc_ctx(&f_ctx, buf, size, sh);
646 	ctx=&f_ctx.in.ctx;
647 	if (err<0){
648 		if (err==E_BINRPC_MORE_DATA){
649 			if (f_ctx.in.ctx.tlen){
650 				*bytes_needed=ctx->tlen+(int)(f_ctx.in.s-buf)-size;
651 			}else{
652 				*bytes_needed=1; /* we don't really know how much */
653 			}
654 			goto more_data;
655 		}else if( err==E_BINRPC_LAST){
656 			LOG(L_ERR, "ERROR: init_binrpc_ctx: out of memory\n");
657 			rpc_fault(&f_ctx, 500, "internal server error: out of mem.");
658 			goto error;
659 		}
660 		rpc_fault(&f_ctx, 400, "bad request: %s", binrpc_error(err));
661 		goto error;
662 	}
663 	err=E_BINRPC_BADPKT;
664 	if (ctx->type!=BINRPC_REQ){
665 		rpc_fault(&f_ctx, 400, "bad request: %s", binrpc_error(err));
666 		goto error;
667 	}
668 	/* now we have the entire packet */
669 
670 	/* get rpc method */
671 	val.type=BINRPC_T_STR;
672 	f_ctx.in.s=binrpc_read_record(ctx, f_ctx.in.s, f_ctx.in.end, &val, 0, &err);
673 	if (err<0){
674 		LOG(L_CRIT, "ERROR: bad rpc request method, binrpc error: %s (%d)\n",
675 				binrpc_error(err), err);
676 		rpc_fault(&f_ctx, 400, "bad request method: %s", binrpc_error(err) );
677 		goto error;
678 	}
679 
680 	/* find_rpc_exports needs 0 terminated strings, but all str are
681 	 * 0 term by default */
682 	rpc_e=find_rpc_export(val.u.strval.s, 0);
683 	if ((rpc_e==0) || (rpc_e->function==0)){
684 		rpc_fault(&f_ctx, 500, "command %s not found", val.u.strval.s);
685 		goto end;
686 	}
687 	f_ctx.method=val.u.strval.s;
688 	rpc_e->function(&binrpc_callbacks, &f_ctx);
689 	if (f_ctx.replied==0){
690 		if ((binrpc_pkt_len(&f_ctx.out.pkt)==0)
691 			&& f_ctx.err_code && f_ctx.err_phrase.s
692 		) {
693 			_rpc_fault(&f_ctx, f_ctx.err_code,
694 				f_ctx.err_phrase.s, f_ctx.err_phrase.len);
695 		/* to get an error reply if the rpc handlers hasn't replied
696 		 *  uncomment the following code:
697 		 * } else if (binrpc_pkt_len(&f_ctx.out.pkt)==0){
698 			rpc_fault(&f_ctx, 500, "internal server error: no reply");
699 			LOG(L_ERR, "ERROR: rpc method %s hasn't replied\n",
700 					val.u.strval.s);
701 		 */
702 		} else {
703 			rpc_send(&f_ctx);
704 		}
705 	}
706 end:
707 	*bytes_needed=0; /* full read */
708 	destroy_binrpc_ctx(&f_ctx);
709 	return (int)(f_ctx.in.end-buf);
710 error:
711 	if (f_ctx.replied==0){
712 			rpc_fault(&f_ctx, 500, "internal server error");
713 			LOG(L_ERR, "ERROR: unknown rpc error\n");
714 	}
715 	*bytes_needed=0; /* we don't need anymore crap */
716 	destroy_binrpc_ctx(&f_ctx);
717 	return -1;
718 more_data:
719 	destroy_binrpc_ctx(&f_ctx);
720 	return 0; /* nothing was processed */
721 }
722 
723 
724 
725 
rpc_type_name(int type)726 static char* rpc_type_name(int type)
727 {
728 	switch(type){
729 		case BINRPC_T_INT:
730 			return "integer";
731 		case BINRPC_T_STR:
732 			return "string";
733 		case BINRPC_T_DOUBLE:
734 			return "float";
735 		case BINRPC_T_STRUCT:
736 			return "structure";
737 		case BINRPC_T_ARRAY:
738 			return "array";
739 		case BINRPC_T_AVP:
740 			return "structure member";
741 		case BINRPC_T_BYTES:
742 			return "bytes array";
743 		case BINRPC_T_ALL:
744 			return "any";
745 	}
746 	return "<unknown/error>";
747 };
748 
749 
750 
751 /** converts a binrpc_val to int.
752   *@return int val on success, 0 and sets err on error (E_BINRPC_TYPE) */
binrpc_val_conv_int(struct binrpc_val * v,int * err)753 inline static int binrpc_val_conv_int( struct binrpc_val* v, int* err)
754 {
755 	int ret;
756 
757 	*err=0;
758 	switch(v->type){
759 		case BINRPC_T_INT:
760 			return v->u.intval;
761 		case BINRPC_T_DOUBLE:
762 			return (int) v->u.fval;
763 		case BINRPC_T_STR:
764 			if (str2sint(&v->u.strval, &ret)==0)
765 				return ret;
766 	}
767 	*err=E_BINRPC_TYPE;
768 	return 0;
769 }
770 
771 
772 
773 /** converts a binrpc_val to double.
774   *@return double val on success, 0 and sets err on error (E_BINRPC_TYPE) */
binrpc_val_conv_double(struct binrpc_val * v,int * err)775 inline static double binrpc_val_conv_double( struct binrpc_val* v, int* err)
776 {
777 	double ret;
778 	char* end;
779 
780 	*err=0;
781 	switch(v->type){
782 		case BINRPC_T_DOUBLE:
783 			return v->u.fval;
784 		case BINRPC_T_INT:
785 			return (double)v->u.intval;
786 		case BINRPC_T_STR:
787 			ret=strtod(v->u.strval.s, &end);
788 			if (end!=v->u.strval.s)
789 				return ret;
790 	}
791 	*err=E_BINRPC_TYPE;
792 	return 0;
793 }
794 
795 
796 
797 /** converts a binrpc_val to str.
798   *@return str val pointer on success, 0 and sets err on error (E_BINRPC_TYPE)*/
binrpc_val_conv_str(struct binrpc_ctx * ctx,struct binrpc_val * v,int * err)799 inline static str* binrpc_val_conv_str(struct binrpc_ctx* ctx,
800 										struct binrpc_val* v, int* err)
801 {
802 	str* ret;
803 	char* s;
804 	int len;
805 
806 	*err=0;
807 	switch(v->type){
808 		case BINRPC_T_STR:
809 			return &v->u.strval;
810 		case BINRPC_T_INT:
811 			s=int2str(v->u.intval, &len);
812 			ret=ctl_malloc(sizeof(*ret)+len+1);
813 			if (ret==0 || binrpc_gc_track(ctx, ret)!=0){
814 				if(ret!=0) ctl_free(ret);
815 				*err=E_BINRPC_OVERFLOW;
816 				return 0;
817 			}
818 			ret->s=(char*)ret+sizeof(*ret);
819 			ret->len=len;
820 			memcpy(ret->s, s, len);
821 			ret->s[len]=0;
822 			return ret;
823 		case BINRPC_T_DOUBLE:
824 			/* for now the double to string conversion is not supported*/
825 			*err=E_BINRPC_BUG;
826 			return 0;
827 	}
828 	*err=E_BINRPC_TYPE;
829 	return 0;
830 }
831 
832 
833 
834 /* rpc interface functions */
835 
836 /* returns the number of parameters read
837  * on error: - number of parameters read so far (<=0)*/
rpc_scan(struct binrpc_ctx * ctx,char * fmt,...)838 static int rpc_scan(struct binrpc_ctx* ctx, char* fmt, ...)
839 {
840 	va_list ap;
841 	struct binrpc_val v;
842 	int err;
843 	char* orig_fmt;
844 	int nofault;
845 	int modifiers;
846 	int autoconv;
847 	int i;
848 	double d;
849 	str* s;
850 
851 	/* clear the previously saved error code */
852 	rpc_fault_reset(ctx);
853 
854 	orig_fmt=fmt;
855 	nofault = 0;
856 	modifiers=0;
857 	autoconv=autoconvert;
858 	va_start(ap, fmt);
859 	for (;*fmt; fmt++){
860 		switch(*fmt){
861 			case '*': /* start of optional parameters */
862 				nofault = 1;
863 				modifiers++;
864 				continue;
865 			case '.': /* autoconv. on for the next parameter */
866 				modifiers++;
867 				autoconv=1;
868 				continue;
869 			case 'b': /* bool */
870 			case 't': /* time */
871 			case 'd': /* int */
872 			case 'u': /* uint */
873 				v.type=autoconv?BINRPC_T_ALL:BINRPC_T_INT;
874 				ctx->in.s=binrpc_read_record(&ctx->in.ctx, ctx->in.s,
875 												ctx->in.end, &v, 0, &err);
876 				if (err<0 || ((i=binrpc_val_conv_int(&v, &err))==0 && err<0))
877 						goto error_read;
878 				*(va_arg(ap, int*))=i;
879 				break;
880 			case 'f':
881 				v.type=autoconv?BINRPC_T_ALL:BINRPC_T_DOUBLE;
882 				ctx->in.s=binrpc_read_record(&ctx->in.ctx, ctx->in.s,
883 												ctx->in.end, &v, 0, &err);
884 				if (err<0 || ((d=binrpc_val_conv_double(&v, &err))==0 &&
885 						err<0))
886 					goto error_read;
887 				*(va_arg(ap, double*))=d;
888 				break;
889 			case 's': /* asciiz */
890 			case 'S': /* str */
891 				v.type=autoconv?BINRPC_T_ALL:BINRPC_T_STR;
892 				ctx->in.s=binrpc_read_record(&ctx->in.ctx, ctx->in.s,
893 												ctx->in.end, &v, 0, &err);
894 				if (err<0 || ((s=binrpc_val_conv_str(ctx, &v, &err))==0 ||
895 							err<0)){
896 					v.u.strval.s="if you get this string, you don't"
897 								"check rpc_scan return code !!! (very bad)";
898 					v.u.strval.len=strlen(v.u.strval.s);
899 					s=&v.u.strval;
900 				}
901 				if (*fmt=='s'){
902 					*(va_arg(ap, char**))=s->s; /* 0 term by proto*/
903 				}else{
904 					*(va_arg(ap, str*))=*s;
905 				}
906 				if (err<0) goto error_read;
907 				break;
908 			case '{': /* struct */
909 				v.type=BINRPC_T_STRUCT;
910 				/* FIXME: structure reading doesn't work for now */
911 #if 0
912 				ctx->in.s=binrpc_read_record(&ctx->in.ctx, ctx->in.s,
913 												ctx->in.end, &v, 0, &err);
914 				if (err<0) goto error_read;
915 				ctx->in.in_struct++;
916 				*(va_arg(ap, void**))=ctx; /* use the same context */
917 #endif
918 				goto error_not_supported;
919 				break;
920 			default:
921 				goto error_inv_param;
922 		}
923 		autoconv=autoconvert; /* reset autoconv*/
924 		ctx->in.record_no++;
925 	}
926 	va_end(ap);
927 	return (int)(fmt-orig_fmt)-modifiers;
928 error_read:
929 	/* Do not immediately send out the error message, the user might retry the scan with
930 	different parameters */
931 	if(nofault==0 || ((err!=E_BINRPC_MORE_DATA) && (err!=E_BINRPC_EOP))) {
932 		rpc_fault_prepare(ctx, 400, "error at parameter %d: expected %s type but"
933 						" %s", ctx->in.record_no, rpc_type_name(v.type),
934 						 binrpc_error(err));
935 	/*
936 	rpc_fault(ctx, 400, "invalid record %d, offset %d (expected %d type)"
937 						": %s", ctx->in.record_no, ctx->in.ctx.offset,
938 								v.type, binrpc_error(err));
939 	*/
940 	}
941 	if(nofault==1 && (err==E_BINRPC_MORE_DATA || err==E_BINRPC_EOP)) {
942 		va_end(ap);
943 		return (int)(fmt-orig_fmt)-modifiers;
944 	}
945 	goto error_ret;
946 error_not_supported:
947 	rpc_fault(ctx, 500, "internal server error, type %d not supported",
948 						v.type);
949 	LOG(L_CRIT, "BUG: binrpc: rpc_scan: formatting char \'%c\'"
950 						" not supported\n", *fmt);
951 goto error_ret;
952 error_inv_param:
953 	rpc_fault(ctx, 500, "internal server error, invalid format char \'%c\'",
954 						*fmt);
955 error_ret:
956 	va_end(ap);
957 	return -((int)(fmt-orig_fmt)-modifiers);
958 }
959 
960 
961 
962 /* returns  0 on success, -1 on error */
rpc_add(struct binrpc_ctx * ctx,char * fmt,...)963 static int rpc_add(struct binrpc_ctx* ctx, char* fmt, ...)
964 {
965 	va_list ap;
966 	int err;
967 	str st;
968 	str* sp;
969 	struct rpc_struct_l* rs;
970 	str null_value = str_init("<null string>");
971 
972 	va_start(ap, fmt);
973 	for (;*fmt; fmt++){
974 		switch(*fmt){
975 			case 'd':
976 			case 't':
977 			case 'b':
978 			case 'u':
979 				err=binrpc_addint(&ctx->out.pkt, va_arg(ap, int));
980 				if (err<0) goto error_add;
981 				break;
982 			case 's': /* asciiz */
983 				st.s=va_arg(ap, char*);
984 				if (st.s==0) {
985 					/* fix null strings */
986 					st=null_value;
987 				} else {
988 					st.len=strlen(st.s);
989 				}
990 				err=binrpc_addstr(&ctx->out.pkt, st.s, st.len);
991 				if (err<0) goto error_add;
992 				break;
993 			case 'S': /* str */
994 				sp=va_arg(ap, str*);
995 				if(sp!=NULL && sp->s!=NULL) {
996 					st=*sp;
997 				} else {
998 					st=null_value;
999 				}
1000 				err=binrpc_addstr(&ctx->out.pkt, st.s, st.len);
1001 				if (err<0) goto error_add;
1002 				break;
1003 			case '{':
1004 			case '[':
1005 				err=binrpc_start_struct(&ctx->out.pkt);
1006 				if (err<0) goto error_add;
1007 				rs=new_rpc_struct();
1008 				if (rs==0) goto error_mem;
1009 				rs->offset=binrpc_pkt_len(&ctx->out.pkt);
1010 				err=binrpc_end_struct(&ctx->out.pkt);
1011 				if (err<0) goto error_add;
1012 				clist_append(&ctx->out.structs, rs, next, prev);
1013 				*(va_arg(ap, void**))=rs;
1014 				break;
1015 			case 'f':
1016 				err=binrpc_adddouble(&ctx->out.pkt, va_arg(ap, double));
1017 				if (err<0) goto error_add;
1018 				break;
1019 			default:
1020 				rpc_fault(ctx, 500, "Internal server error: "
1021 								"invalid formatting character \'%c\'", *fmt);
1022 				LOG(L_CRIT, "BUG: binrpc: rpc_add: formatting char \'%c\'"
1023 							" not supported\n", *fmt);
1024 				goto error;
1025 		}
1026 	}
1027 	va_end(ap);
1028 	return 0;
1029 error_mem:
1030 	LOG(L_ERR, "ERROR: binrpc: rpc_add: out of memory\n");
1031 	rpc_fault(ctx, 500, "Internal server error: out of memory");
1032 	goto error;
1033 error_add:
1034 	rpc_fault(ctx, 500, "Internal server error processing \'%c\': %s (%d)",
1035 				*fmt, binrpc_error(err), err);
1036 error:
1037 	va_end(ap);
1038 	return -1;
1039 }
1040 
1041 
1042 
1043 #define RPC_PRINTF_BUF_SIZE	binrpc_buffer_size
1044 /* returns  0 on success, -1 on error */
rpc_rpl_printf(struct binrpc_ctx * ctx,char * fmt,...)1045 static int rpc_rpl_printf(struct binrpc_ctx* ctx, char* fmt, ...)
1046 {
1047 	va_list ap;
1048 	char* buf;
1049 	int len;
1050 	int err;
1051 
1052 	buf=ctl_malloc(RPC_PRINTF_BUF_SIZE);
1053 	if (buf==0) goto error;
1054 	va_start(ap, fmt);
1055 	len=vsnprintf(buf, RPC_PRINTF_BUF_SIZE, fmt, ap);
1056 	va_end(ap);
1057 	if ((len<0) || (len> RPC_PRINTF_BUF_SIZE)){
1058 		LOG(L_ERR, "ERROR: binrpc: rpc_rpl_printf: buffer size exceeded(%d)\n",
1059 				RPC_PRINTF_BUF_SIZE);
1060 		goto error;
1061 	}
1062 	if ((err=binrpc_addstr(&ctx->out.pkt, buf, len))<0){
1063 		LOG(L_ERR, "ERROR: binrpc: rpc_rpl_printf: binrpc_addstr failed:"
1064 					" %s (%d)\n", binrpc_error(err), err);
1065 		goto error;
1066 	}
1067 	ctl_free(buf);
1068 	return 0;
1069 error:
1070 	if (buf) ctl_free(buf);
1071 	return -1;
1072 }
1073 
1074 
1075 
1076 /* returns  0 on success, -1 on error */
rpc_struct_add(struct rpc_struct_l * s,char * fmt,...)1077 static int rpc_struct_add(struct rpc_struct_l* s, char* fmt, ...)
1078 {
1079 	va_list ap;
1080 	int err;
1081 	struct binrpc_val avp;
1082 	struct rpc_struct_l* rs;
1083 	str *sp;
1084 	str null_value = str_init("<null string>");
1085 
1086 	va_start(ap, fmt);
1087 	for (;*fmt; fmt++){
1088 		memset(&avp, 0, sizeof(struct binrpc_val));
1089 		avp.name.s=va_arg(ap, char*);
1090 		if (avp.name.s)
1091 			avp.name.len=strlen(avp.name.s);
1092 		switch(*fmt){
1093 			case 'd':
1094 			case 't':
1095 			case 'b':
1096 			case 'u':
1097 				avp.type=BINRPC_T_INT;
1098 				avp.u.intval=va_arg(ap, int);
1099 				break;
1100 			case 's': /* asciiz */
1101 				avp.type=BINRPC_T_STR;
1102 				avp.u.strval.s=va_arg(ap, char*);
1103 				if (avp.u.strval.s==NULL) {
1104 					/* fix null strings */
1105 					avp.u.strval=null_value;
1106 				} else {
1107 					avp.u.strval.len=strlen(avp.u.strval.s);
1108 				}
1109 				break;
1110 			case 'S': /* str */
1111 				avp.type=BINRPC_T_STR;
1112 				sp = va_arg(ap, str*);
1113 				if(sp!=NULL && sp->s!=NULL) {
1114 					avp.u.strval=*sp;
1115 				} else {
1116 					avp.u.strval=null_value;
1117 				}
1118 				break;
1119 			case '{':
1120 			case '[':
1121 				avp.type=BINRPC_T_STRUCT;
1122 				err=binrpc_addavp(&s->pkt, &avp);
1123 				if (err<0){
1124 					LM_ERR("failed to add attribute-value (%c)\n", *fmt);
1125 					goto error_add;
1126 				}
1127 				rs=new_rpc_struct();
1128 				if (rs==0){
1129 					LM_ERR("not enough memory (%c)\n", *fmt);
1130 					goto error_mem;
1131 				}
1132 				rs->offset=binrpc_pkt_len(&s->pkt);
1133 				err=binrpc_end_struct(&s->pkt);
1134 				if (err<0) {
1135 					LM_ERR("failed to end struct (%c)\n", *fmt);
1136 					goto error_add;
1137 				}
1138 				clist_append(&s->substructs, rs, next, prev);
1139 				*(va_arg(ap, void**))=rs;
1140 				goto end;
1141 			case 'f':
1142 				avp.type=BINRPC_T_DOUBLE;
1143 				avp.u.fval=va_arg(ap, double);
1144 				break;
1145 			default:
1146 				LM_ERR("formatting char \'%c\' not supported\n", *fmt);
1147 				goto error;
1148 		}
1149 		err=binrpc_addavp(&s->pkt, &avp);
1150 		if (err<0) {
1151 			LM_ERR("failed to add attribute-value (%c)\n", *fmt);
1152 			goto error;
1153 		}
1154 	}
1155 end:
1156 	va_end(ap);
1157 	return 0;
1158 error_mem:
1159 error_add:
1160 error:
1161 	va_end(ap);
1162 	return -1;
1163 }
1164 
1165 /* returns  0 on success, -1 on error */
rpc_array_add(struct rpc_struct_l * s,char * fmt,...)1166 static int rpc_array_add(struct rpc_struct_l* s, char* fmt, ...)
1167 {
1168 	va_list ap;
1169 	int err;
1170 	str st;
1171 	str *sp;
1172 	struct rpc_struct_l* rs;
1173 	str null_value = str_init("<null string>");
1174 
1175 	va_start(ap, fmt);
1176 	for (;*fmt; fmt++){
1177 		switch(*fmt){
1178 			case 'd':
1179 			case 't':
1180 			case 'b':
1181 			case 'u':
1182 				err=binrpc_addint(&s->pkt, va_arg(ap, int));
1183 				if (err<0) goto error_add;
1184 				break;
1185 			case 's': /* asciiz */
1186 				st.s=va_arg(ap, char*);
1187 				if (st.s==0) {
1188 					/* fix null strings */
1189 					st=null_value;
1190 				} else {
1191 					st.len = strlen(st.s);
1192 				}
1193 				err=binrpc_addstr(&s->pkt, st.s, st.len);
1194 				if (err<0) goto error_add;
1195 				break;
1196 			case 'S': /* str */
1197 				sp=va_arg(ap, str*);
1198 				if(sp!=NULL && sp->s!=NULL) {
1199 					st=*sp;
1200 				} else {
1201 					st=null_value;
1202 				}
1203 				err=binrpc_addstr(&s->pkt, st.s, st.len);
1204 				if (err<0) goto error_add;
1205 				break;
1206 			case '{':
1207 			case '[':
1208 				err=binrpc_start_struct(&s->pkt);
1209 				if (err<0) goto error_add;
1210 				rs=new_rpc_struct();
1211 				if (rs==0) goto error_mem;
1212 				rs->offset=binrpc_pkt_len(&s->pkt);
1213 				err=binrpc_end_struct(&s->pkt);
1214 				if (err<0) goto error_add;
1215 				clist_append(&s->substructs, rs, next, prev);
1216 				*(va_arg(ap, void**))=rs;
1217 				break;
1218 			case 'f':
1219 				err=binrpc_adddouble(&s->pkt, va_arg(ap, double));
1220 				if (err<0) goto error_add;
1221 				break;
1222 			default:
1223 				LOG(L_CRIT, "BUG: binrpc: rpc_add: formatting char \'%c\'"
1224 							" not supported\n", *fmt);
1225 				goto error;
1226 		}
1227 	}
1228 	va_end(ap);
1229 	return 0;
1230 error_mem:
1231 error_add:
1232 error:
1233 	va_end(ap);
1234 	return -1;
1235 }
1236 
1237 /* returns  0 on success, -1 on error */
rpc_struct_printf(struct rpc_struct_l * s,char * name,char * fmt,...)1238 static int rpc_struct_printf(struct rpc_struct_l *s, char* name,
1239 								char* fmt, ...)
1240 {
1241 	va_list ap;
1242 	char* buf;
1243 	int len;
1244 	int err;
1245 	struct binrpc_val avp;
1246 
1247 	buf=ctl_malloc(RPC_PRINTF_BUF_SIZE);
1248 	if (buf==0) goto error;
1249 	va_start(ap, fmt);
1250 	len=vsnprintf(buf, RPC_PRINTF_BUF_SIZE, fmt, ap);
1251 	va_end(ap);
1252 	if ((len<0) || (len> RPC_PRINTF_BUF_SIZE)){
1253 		LOG(L_ERR, "ERROR: binrpc: rpc_struct_printf:"
1254 				" buffer size exceeded(%d)\n", RPC_PRINTF_BUF_SIZE);
1255 		goto error;
1256 	}
1257 	avp.name.s=name;
1258 	avp.name.len=strlen(name);
1259 	avp.type=BINRPC_T_STR;
1260 	avp.u.strval.s=buf;
1261 	avp.u.strval.len=strlen(buf);
1262 
1263 	if ((err=binrpc_addavp(&s->pkt, &avp))<0){
1264 		LOG(L_ERR, "ERROR: binrpc: rpc_printf: binrpc_addavp failed:"
1265 					" %s (%d)\n", binrpc_error(err), err);
1266 		goto error;
1267 	}
1268 	ctl_free(buf);
1269 	return 0;
1270 error:
1271 	if (buf) ctl_free(buf);
1272 	return -1;
1273 }
1274 
1275 
1276 
rpc_struct_scan(struct rpc_struct_l * s,char * fmt,...)1277 static int rpc_struct_scan(struct rpc_struct_l* s, char* fmt, ...)
1278 {
1279 	LOG(L_CRIT, "ERROR: binrpc:rpc_struct_scan: not implemented\n");
1280 	return -1;
1281 };
1282 
1283