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