1 /*
2  * Copyright (C) 2009 iptelorg GmbH
3  *
4  * Permission to use, copy, modify, and distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 /*
17  * modules/tm/rpc_uac.c
18  */
19 
20 #include "rpc_uac.h"
21 #include "../../core/rpc.h"
22 #include "../../core/socket_info.h"
23 #include "../../core/ut.h"
24 #include "../../core/parser/parse_from.h"
25 #include "../../core/str_list.h"
26 #include "../../core/timer_proc.h"
27 #include "../../core/utils/sruid.h"
28 #include "ut.h"
29 #include "dlg.h"
30 #include "uac.h"
31 #include "callid.h"
32 
33 
34 /* RPC substitution char (used in rpc_t_uac headers) */
35 #define SUBST_CHAR '!'
36 
37 #define TM_RPC_RESPONSE_LIFETIME 300
38 #define TM_RPC_RESPONSE_TIMERSTEP 10
39 
40 void tm_rpc_response_list_clean(unsigned int ticks, void *param);
41 
42 typedef struct tm_rpc_response {
43 	str ruid;
44 	int flags;
45 	int rcode;
46 	str rtext;
47 	time_t rtime;
48 	struct tm_rpc_response *next;
49 } tm_rpc_response_t;
50 
51 typedef struct tm_rpc_response_list {
52 	gen_lock_t rlock;
53 	tm_rpc_response_t *rlist;
54 } tm_rpc_response_list_t;
55 
56 static tm_rpc_response_list_t *_tm_rpc_response_list = NULL;
57 
58 static sruid_t _tm_rpc_sruid;
59 
60 /**
61  *
62  */
tm_rpc_response_list_init(void)63 int tm_rpc_response_list_init(void)
64 {
65 	if(_tm_rpc_response_list != NULL) {
66 		return 0;
67 	}
68 	if(sruid_init(&_tm_rpc_sruid, '-', "tmrp", SRUID_INC)<0) {
69 		LM_ERR("failed to init sruid\n");
70 		return -1;
71 	}
72 	if(sr_wtimer_add(tm_rpc_response_list_clean, 0,
73 				TM_RPC_RESPONSE_TIMERSTEP)<0) {
74 		LM_ERR("failed to register timer routine\n");
75 		return -1;
76 	}
77 	_tm_rpc_response_list = shm_malloc(sizeof(tm_rpc_response_list_t));
78 	if(_tm_rpc_response_list == NULL) {
79 		SHM_MEM_ERROR;
80 		return -1;
81 	}
82 
83 	memset(_tm_rpc_response_list, 0, sizeof(tm_rpc_response_list_t));
84 
85 	lock_init(&_tm_rpc_response_list->rlock);
86 
87 	return 0;
88 }
89 
90 /**
91  *
92  */
tm_rpc_response_list_destroy(void)93 int tm_rpc_response_list_destroy(void)
94 {
95 	tm_rpc_response_t *rl0 = NULL;
96 	tm_rpc_response_t *rl1 = NULL;
97 
98 	if(_tm_rpc_response_list == NULL) {
99 		return 0;
100 	}
101 
102 	rl1 = _tm_rpc_response_list->rlist;
103 
104 	while(rl1!=NULL) {
105 		rl0 = rl1;
106 		rl1 = rl1->next;
107 		shm_free(rl0);
108 	}
109 	lock_destroy(&_tm_rpc_response_list->rlock);
110 	shm_free(_tm_rpc_response_list);
111 	_tm_rpc_response_list = NULL;
112 
113 	return 0;
114 }
115 
116 /**
117  *
118  */
tm_rpc_response_list_add(str * ruid,int rcode,str * rtext)119 int tm_rpc_response_list_add(str *ruid, int rcode, str *rtext)
120 {
121 	size_t rsize = 0;
122 	tm_rpc_response_t *ri = NULL;
123 	if(_tm_rpc_response_list == NULL) {
124 		LM_ERR("rpc response list not initialized\n");
125 		return -1;
126 	}
127 
128 	rsize = sizeof(tm_rpc_response_t) + ruid->len + 2
129 				+ ((rtext!=NULL)?rtext->len:0);
130 
131 	ri = (tm_rpc_response_t*)shm_malloc(rsize);
132 	if(ri==NULL) {
133 		SHM_MEM_ERROR;
134 		return -1;
135 	}
136 	memset(ri, 0, rsize);
137 
138 	ri->ruid.s = (char*)ri + sizeof(tm_rpc_response_t);
139 	ri->ruid.len = ruid->len;
140 	memcpy(ri->ruid.s, ruid->s, ruid->len);
141 	ri->rtime = time(NULL);
142 	ri->rcode = rcode;
143 	if(rtext!=NULL) {
144 		ri->rtext.s = ri->ruid.s + ri->ruid.len + 1;
145 		ri->rtext.len = rtext->len;
146 		memcpy(ri->rtext.s, rtext->s, rtext->len);
147 	}
148 	lock_get(&_tm_rpc_response_list->rlock);
149 	ri->next = _tm_rpc_response_list->rlist;
150 	_tm_rpc_response_list->rlist = ri;
151 	lock_release(&_tm_rpc_response_list->rlock);
152 
153 	return 0;
154 }
155 
156 /**
157  *
158  */
tm_rpc_response_list_get(str * ruid)159 tm_rpc_response_t *tm_rpc_response_list_get(str *ruid)
160 {
161 	tm_rpc_response_t *ri0 = NULL;
162 	tm_rpc_response_t *ri1 = NULL;
163 
164 	if(_tm_rpc_response_list == NULL) {
165 		LM_ERR("rpc response list not initialized\n");
166 		return NULL;
167 	}
168 
169 	lock_get(&_tm_rpc_response_list->rlock);
170 	ri1 = _tm_rpc_response_list->rlist;
171 	while(ri1!=NULL) {
172 		if(ri1->ruid.len==ruid->len
173 				&& memcmp(ri1->ruid.s, ruid->s, ruid->len)==0) {
174 			if(ri0 == NULL) {
175 				_tm_rpc_response_list->rlist = ri1->next;
176 			} else {
177 				ri0->next = ri1->next;
178 			}
179 			lock_release(&_tm_rpc_response_list->rlock);
180 			return ri1;
181 		}
182 		ri0 = ri1;
183 		ri1 = ri1->next;
184 	}
185 	lock_release(&_tm_rpc_response_list->rlock);
186 	return NULL;
187 }
188 
189 /**
190  *
191  */
tm_rpc_response_list_clean(unsigned int ticks,void * param)192 void tm_rpc_response_list_clean(unsigned int ticks, void *param)
193 {
194 	tm_rpc_response_t *ri0 = NULL;
195 	tm_rpc_response_t *ri1 = NULL;
196 	time_t tnow;
197 
198 	if(_tm_rpc_response_list == NULL) {
199 		return;
200 	}
201 
202 	tnow = time(NULL);
203 	lock_get(&_tm_rpc_response_list->rlock);
204 	ri1 = _tm_rpc_response_list->rlist;
205 	while(ri1!=NULL) {
206 		if(ri1->rtime < tnow - TM_RPC_RESPONSE_LIFETIME) {
207 			LM_DBG("freeing item [%.*s]\n", ri1->ruid.len, ri1->ruid.s);
208 			if(ri0 == NULL) {
209 				_tm_rpc_response_list->rlist = ri1->next;
210 				shm_free(ri1);
211 				ri1 = _tm_rpc_response_list->rlist;
212 			} else {
213 				ri0->next = ri1->next;
214 				shm_free(ri1);
215 				ri1 = ri0->next;
216 			}
217 		} else {
218 			ri0 = ri1;
219 			ri1 = ri1->next;
220 		}
221 	}
222 	lock_release(&_tm_rpc_response_list->rlock);
223 }
224 
225 /** make sure the rpc user created the msg properly.
226  * Make sure that the FIFO user created the message
227  * correctly and fill some extra parameters in function
228  * of the message contents.
229  * @param rpc - rpc handle
230  * @param  c  - rpc context handle
231  * @param msg - faked sip msg
232  * @param method
233  * @param body
234  * @param fromtag - filled on success (1 if fromtag present, 0 if not)
235  * @param cseq_is - filled on success (1 if cseq present, 0 if not)
236  * @param cseq    - filled on success with the cseq number
237  * @callid        - filled on success with a pointer to the callid in the msg.
238  * @return -1 on error (and sends the rpc reply), 0 on success
239  */
rpc_uac_check_msg(rpc_t * rpc,void * c,struct sip_msg * msg,str * method,str * body,int * fromtag,int * cseq_is,int * cseq,str * callid)240 static int rpc_uac_check_msg(rpc_t *rpc, void* c,
241 		struct sip_msg* msg,
242 		str* method, str* body,
243 		int* fromtag, int *cseq_is, int* cseq,
244 		str* callid)
245 {
246 	struct to_body* parsed_from;
247 	struct cseq_body *parsed_cseq;
248 	int i;
249 	char ch;
250 
251 	if (body->len && !msg->content_type) {
252 		rpc->fault(c, 400, "Content-Type missing");
253 		goto err;
254 	}
255 
256 	if (body->len && msg->content_length) {
257 		rpc->fault(c, 400, "Content-Length disallowed");
258 		goto err;
259 	}
260 
261 	if (!msg->to) {
262 		rpc->fault(c, 400,  "To missing");
263 		goto err;
264 	}
265 
266 	if (!msg->from) {
267 		rpc->fault(c, 400, "From missing");
268 		goto err;
269 	}
270 
271 	/* we also need to know if there is from-tag and add it otherwise */
272 	if (parse_from_header(msg) < 0) {
273 		rpc->fault(c, 400, "Error in From");
274 		goto err;
275 	}
276 
277 	parsed_from = (struct to_body*)msg->from->parsed;
278 	*fromtag = parsed_from->tag_value.s && parsed_from->tag_value.len;
279 
280 	*cseq = 0;
281 	if (msg->cseq && (parsed_cseq = get_cseq(msg))) {
282 		*cseq_is = 1;
283 		for (i = 0; i < parsed_cseq->number.len; i++) {
284 			ch = parsed_cseq->number.s[i];
285 			if (ch >= '0' && ch <= '9' ) {
286 				*cseq = (*cseq) * 10 + ch - '0';
287 			} else {
288 				LM_DBG("Found non-numerical in CSeq: <%i>='%c'\n",
289 						(unsigned int)ch, ch);
290 				rpc->fault(c, 400,  "Non-numerical CSeq");
291 				goto err;
292 			}
293 		}
294 
295 		if (parsed_cseq->method.len != method->len ||
296 				memcmp(parsed_cseq->method.s, method->s, method->len) !=0 ) {
297 			rpc->fault(c, 400, "CSeq method mismatch");
298 			goto err;
299 		}
300 	} else {
301 		*cseq_is = 0;
302 	}
303 
304 	if (msg->callid) {
305 		callid->s = msg->callid->body.s;
306 		callid->len = msg->callid->body.len;
307 	} else {
308 		callid->s = 0;
309 		callid->len = 0;
310 	}
311 	return 0;
312 
313 err:
314 	return -1;
315 }
316 
317 
318 /** construct a "header block" from a header list.
319  *
320  * @return pkg_malloc'ed header block on success (with *l set to its length),
321  *         0 on error.
322  */
get_hfblock(str * uri,struct hdr_field * hf,int proto,struct socket_info * ssock,str * hout)323 static int get_hfblock(str *uri, struct hdr_field *hf, int proto,
324 		struct socket_info* ssock, str* hout)
325 {
326 	struct str_list sl, *last, *i, *foo;
327 	int p, frag_len, total_len;
328 	char *begin, *needle, *dst, *ret, *d;
329 	str *sock_name, *portname;
330 	struct dest_info di;
331 
332 	hout->s = NULL;
333 	hout->len = 0;
334 	ret = 0; /* pessimist: assume failure */
335 	total_len = 0;
336 	last = &sl;
337 	last->next = 0;
338 	sock_name = 0;
339 	portname = 0;
340 	if (ssock){
341 		si_get_signaling_data(ssock, &sock_name, &portname);
342 	}
343 
344 	for (; hf; hf = hf->next) {
345 		if (tm_skip_hf(hf)) continue;
346 
347 		begin = needle = hf->name.s;
348 		p = hf->len;
349 
350 		/* substitution loop */
351 		while(p) {
352 			d = q_memchr(needle, SUBST_CHAR, p);
353 			if (!d || d + 1 >= needle + p) { /* nothing to substitute */
354 				if (!append_str_list(begin, p, &last, &total_len)) goto error;
355 				break;
356 			} else {
357 				frag_len = d - begin;
358 				d++; /* d not at the second substitution char */
359 				switch(*d) {
360 					case SUBST_CHAR: /* double SUBST_CHAR: IP */
361 						/* string before substitute */
362 						if (!append_str_list(begin, frag_len, &last, &total_len))
363 							goto error;
364 						/* substitute */
365 						if (!sock_name) {
366 							if (
367 #ifdef USE_DNS_FAILOVER
368 									uri2dst(0, &di, 0, uri, proto)
369 #else
370 									uri2dst(&di, 0, uri, proto)
371 #endif /* USE_DNS_FAILOVER */
372 									== 0 ){
373 								LM_ERR("send_sock failed\n");
374 								goto error;
375 							}
376 							si_get_signaling_data(di.send_sock, &sock_name, &portname);
377 						}
378 						if (!append_str_list(sock_name->s, sock_name->len, &last,
379 									&total_len))
380 							goto error;
381 						/* inefficient - FIXME --andrei*/
382 						if (!append_str_list(":", 1, &last, &total_len)) goto error;
383 						if (!append_str_list(portname->s, portname->len, &last,
384 									&total_len)) goto error;
385 						/* keep going ... */
386 						begin = needle = d + 1;
387 						p -= frag_len + 2;
388 						continue;
389 					default:
390 						/* no valid substitution char -- keep going */
391 						p -= frag_len + 1;
392 						needle = d;
393 				}
394 			} /* possible substitute */
395 		} /* substitution loop */
396 		LM_DBG("one more hf processed\n");
397 	} /* header loop */
398 
399 	if(total_len==0) {
400 		LM_DBG("empty result for headers block\n");
401 		return 1;;
402 	}
403 
404 	/* construct a single header block now */
405 	ret = pkg_malloc(total_len);
406 	if (!ret) {
407 		PKG_MEM_ERROR;
408 		goto error;
409 	}
410 	i = sl.next;
411 	dst = ret;
412 	while(i) {
413 		foo = i;
414 		i = i->next;
415 		memcpy(dst, foo->s.s, foo->s.len);
416 		dst += foo->s.len;
417 		pkg_free(foo);
418 	}
419 	hout->len = total_len;
420 	hout->s = ret;
421 	return 0;
422 
423 error:
424 	i = sl.next;
425 	while(i) {
426 		foo = i;
427 		i = i->next;
428 		pkg_free(foo);
429 	}
430 	return -1;
431 }
432 
433 
434 #define RPC_ROUTE_PREFIX	"Route: "
435 #define RPC_ROUTE_PREFIX_LEN	(sizeof(RPC_ROUTE_PREFIX)-1)
436 #define RPC_ROUTE_SEPARATOR	", "
437 #define RPC_ROUTE_SEPARATOR_LEN	(sizeof(RPC_ROUTE_SEPARATOR)-1)
438 
439 
440 /** internal print routes into rpc reply function.
441  *  Prints the dialog routes. It's used internally by
442  *  rpx_print_uris (called from rpc_uac_callback()).
443  *  @param rpc
444  *  @param c - rpc context
445  *  @param reply - sip reply
446  */
rpc_print_routes(rpc_t * rpc,void * c,dlg_t * d)447 static void  rpc_print_routes(rpc_t* rpc, void* c,
448 		dlg_t* d)
449 {
450 	rr_t* ptr;
451 	int size;
452 	char* buf;
453 	char* p;
454 
455 	if (d->hooks.first_route == 0){
456 		rpc->add(c, "s", "");
457 		return;
458 	}
459 	size=RPC_ROUTE_PREFIX_LEN;
460 	for (ptr=d->hooks.first_route; ptr; ptr=ptr->next)
461 		size+=ptr->len+(ptr->next!=0)*RPC_ROUTE_SEPARATOR_LEN;
462 	if (d->hooks.last_route)
463 		size+=RPC_ROUTE_SEPARATOR_LEN + 1 /* '<' */ +
464 			d->hooks.last_route->len +1 /* '>' */;
465 
466 	buf=pkg_malloc(size+1);
467 	if (buf==0){
468 		PKG_MEM_ERROR;
469 		rpc->add(c, "s", "");
470 		return;
471 	}
472 	p=buf;
473 	memcpy(p, RPC_ROUTE_PREFIX, RPC_ROUTE_PREFIX_LEN);
474 	p+=RPC_ROUTE_PREFIX_LEN;
475 	for (ptr=d->hooks.first_route; ptr; ptr=ptr->next){
476 		memcpy(p, ptr->nameaddr.name.s, ptr->len);
477 		p+=ptr->len;
478 		if (ptr->next!=0){
479 			memcpy(p, RPC_ROUTE_SEPARATOR, RPC_ROUTE_SEPARATOR_LEN);
480 			p+=RPC_ROUTE_SEPARATOR_LEN;
481 		}
482 	}
483 	if (d->hooks.last_route){
484 		memcpy(p, RPC_ROUTE_SEPARATOR, RPC_ROUTE_SEPARATOR_LEN);
485 		p+=RPC_ROUTE_SEPARATOR_LEN;
486 		*p='<';
487 		p++;
488 		memcpy(p, d->hooks.last_route->s, d->hooks.last_route->len);
489 		p+=d->hooks.last_route->len;
490 		*p='>';
491 		p++;
492 	}
493 	*p=0;
494 	rpc->add(c, "s", buf);
495 	pkg_free(buf);
496 	return;
497 }
498 
499 
500 /** internal print uri into rpc reply function.
501  *  Prints the uris into rpc reply. It's used internally by
502  *  rpc_uac_callback().
503  *  @param rpc
504  *  @param c - rpc context
505  *  @param reply - sip reply
506  */
rpc_print_uris(rpc_t * rpc,void * c,struct sip_msg * reply)507 static void  rpc_print_uris(rpc_t* rpc, void* c, struct sip_msg* reply)
508 {
509 	dlg_t* dlg;
510 	dlg=shm_malloc(sizeof(dlg_t));
511 	if (dlg==0){
512 		SHM_MEM_ERROR;
513 		return;
514 	}
515 	memset(dlg, 0, sizeof(dlg_t));
516 	if (dlg_response_uac(dlg, reply, TARGET_REFRESH_UNKNOWN) < 0) {
517 		LM_ERR("failure while filling dialog structure\n");
518 		free_dlg(dlg);
519 		return;
520 	}
521 	if (dlg->state != DLG_CONFIRMED) {
522 		free_dlg(dlg);
523 		return;
524 	}
525 	if (dlg->hooks.request_uri->s){
526 		rpc->add(c, "S", dlg->hooks.request_uri);
527 	}else{
528 		rpc->add(c, "s", "");
529 	}
530 	if (dlg->hooks.next_hop->s) {
531 		rpc->add(c, "S", dlg->hooks.next_hop);
532 	} else {
533 		rpc->add(c, "s", "");
534 	}
535 	rpc_print_routes(rpc, c, dlg);
536 	free_dlg(dlg);
537 	return;
538 }
539 
540 
541 
542 /* t_uac callback */
rpc_uac_callback(struct cell * t,int type,struct tmcb_params * ps)543 static void rpc_uac_callback(struct cell* t, int type, struct tmcb_params* ps)
544 {
545 	rpc_delayed_ctx_t* dctx;
546 	str text;
547 	rpc_t* rpc;
548 	void* c;
549 	int code;
550 	str* preason;
551 
552 	dctx=(rpc_delayed_ctx_t*)*ps->param;
553 	*ps->param=0;
554 	if (dctx==0){
555 		BUG("null delayed reply ctx\n");
556 		return;
557 	}
558 	rpc=&dctx->rpc;
559 	c=dctx->reply_ctx;
560 	if (ps->rpl==FAKED_REPLY) {
561 		text.s=error_text(ps->code);
562 		text.len=strlen(text.s);
563 		code=ps->code;
564 		preason=&text;
565 		rpc->add(c, "dS", code, preason);
566 		rpc->add(c, "s", ""); /* request uri (rpc_print_uris)*/
567 		rpc->add(c, "s", ""); /* next hop (rpc_print_uris) */
568 		rpc->add(c, "s", ""); /* dialog routes (rpc_print_routes) */
569 		rpc->add(c, "s", ""); /* rest of the reply */
570 	}else{
571 		code=ps->rpl->first_line.u.reply.statuscode;
572 		preason=&ps->rpl->first_line.u.reply.reason;
573 		rpc->add(c, "dS", code, preason);
574 		rpc_print_uris(rpc, c, ps->rpl);
575 		/* print all the reply (from the first header) */
576 		rpc->add(c, "s", ps->rpl->headers->name.s);
577 	}
578 	rpc->delayed_ctx_close(dctx);
579 	ps->param=0;
580 }
581 
582 
583 /* t_uac callback */
rpc_uac_block_callback(struct cell * t,int type,struct tmcb_params * ps)584 static void rpc_uac_block_callback(struct cell* t, int type,
585 		struct tmcb_params* ps)
586 {
587 	str *ruid;
588 	str rtext;
589 
590 	ruid = (str*)(*ps->param);
591 	*ps->param=0;
592 	if (ps->rpl==FAKED_REPLY) {
593 		rtext.s = error_text(ps->code);
594 		rtext.len = strlen(rtext.s);
595 	} else {
596 		rtext = ps->rpl->first_line.u.reply.reason;
597 	}
598 	tm_rpc_response_list_add(ruid, ps->code, &rtext);
599 	shm_free(ruid);
600 }
601 
602 
603 /** rpc t_uac version-
604  * It expects the following list of strings as parameters:
605  *  method
606  *  request_uri
607  *  dst_uri (next hop) -- can be empty (either "" or ".", which is still
608  *                        supported for backwards compatibility with fifo)
609  *  send_socket (socket from which the message will be sent)
610  *  headers (message headers separated by CRLF, at least From and To
611  *           must be present)
612  *  body (optional, might be null or completely missing)
613  *
614  * If all the parameters are ok it will call t_uac() using them.
615  * Note: this version will  wait for the transaction final reply
616  * only if reply_wait is set to 1. Otherwise the rpc reply will be sent
617  * immediately and it will be success if the parameters were ok and t_uac did
618  * not report any error.
619  * Note: reply waiting (reply_wait==1) is not yet supported.
620  * @param rpc - rpc handle
621  * @param  c - rpc current context
622  * @param reply_wait - if 1 do not generate a rpc reply until final response
623  *                     for the transaction arrives, if 0 immediately send
624  *                     an rpc reply (see above).
625  */
rpc_t_uac(rpc_t * rpc,void * c,int reply_wait)626 static void rpc_t_uac(rpc_t* rpc, void* c, int reply_wait)
627 {
628 	/* rpc params */
629 	str method, ruri, nexthop, send_socket, headers, body;
630 	/* other internal vars.*/
631 	str hfb, callid;
632 	struct sip_uri p_uri, pnexthop;
633 	struct sip_msg faked_msg;
634 	struct socket_info* ssock;
635 	str saddr;
636 	int sport, sproto;
637 	int ret, sip_error, err_ret, fromtag, cseq_is, cseq;
638 	char err_buf[MAX_REASON_LEN];
639 	dlg_t dlg;
640 	uac_req_t uac_req;
641 	rpc_delayed_ctx_t* dctx;
642 	str *ruid = NULL;
643 	tm_rpc_response_t *ritem = NULL;
644 	int rcount = 0;
645 	void* th = NULL;
646 
647 	body.s=0;
648 	body.len=0;
649 	dctx=0;
650 	if (reply_wait==1 && (rpc->capabilities == 0 ||
651 				!(rpc->capabilities(c) & RPC_DELAYED_REPLY))) {
652 		rpc->fault(c, 600, "Reply wait/async mode not supported"
653 				" by this rpc transport");
654 		return;
655 	}
656 	ret=rpc->scan(c, "SSSSS*S",
657 			&method, &ruri, &nexthop, &send_socket, &headers, &body);
658 	if (ret<5 && ! (-ret == 5)){
659 		rpc->fault(c, 400, "too few parameters (%d/5)", ret?ret:-ret);
660 		return;
661 	}
662 	/* check and parse parameters */
663 	if (method.len==0){
664 		rpc->fault(c, 400, "Empty method");
665 		return;
666 	}
667 	if (parse_uri(ruri.s, ruri.len, &p_uri)<0){
668 		rpc->fault(c, 400, "Invalid request uri \"%s\"", ruri.s);
669 		return;
670 	}
671 	/* old fifo & unixsock backwards compatibility for nexthop: '.' is still
672 	   allowed */
673 	if (nexthop.len==1 && nexthop.s[0]=='.'){
674 		/* empty nextop */
675 		nexthop.len=0;
676 		nexthop.s=0;
677 	}else if (nexthop.len==0){
678 		nexthop.s=0;
679 	}else if (parse_uri(nexthop.s, nexthop.len, &pnexthop)<0){
680 		rpc->fault(c, 400, "Invalid next-hop uri \"%s\"", nexthop.s);
681 		return;
682 	}
683 	/* kamailio backwards compatibility for send_socket: '.' is still
684 	   allowed for an empty socket */
685 	ssock=0;
686 	saddr.s=0;
687 	saddr.len=0;
688 	if (send_socket.len==1 && send_socket.s[0]=='.'){
689 		/* empty send socket */
690 		send_socket.len=0;
691 	}else if (send_socket.len &&
692 			(parse_phostport(send_socket.s, &saddr.s, &saddr.len,
693 							 &sport, &sproto)!=0 ||
694 			 /* check also if it's not a MH addr. */
695 			 saddr.len==0 || saddr.s[0]=='(')
696 			){
697 		rpc->fault(c, 400, "Invalid send socket \"%s\"", send_socket.s);
698 		return;
699 	}else if (saddr.len && (ssock=grep_sock_info(&saddr, sport, sproto))==0){
700 		rpc->fault(c, 400, "No local socket for \"%s\"", send_socket.s);
701 		return;
702 	}
703 	/* check headers using the SIP parser to look in the header list */
704 	memset(&faked_msg, 0, sizeof(struct sip_msg));
705 	faked_msg.len=headers.len;
706 	faked_msg.buf=faked_msg.unparsed=headers.s;
707 	if (parse_headers(&faked_msg, HDR_EOH_F, 0)==-1){
708 		rpc->fault(c, 400, "Invalid headers");
709 		return;
710 	}
711 	/* at this moment all the parameters are parsed => more sanity checks */
712 	if (rpc_uac_check_msg(rpc, c, &faked_msg, &method, &body, &fromtag,
713 				&cseq_is, &cseq, &callid)<0)
714 		goto error;
715 	if(get_hfblock(nexthop.len? &nexthop: &ruri, faked_msg.headers,
716 			PROTO_NONE, ssock, &hfb)<0) {
717 		rpc->fault(c, 500, "Failed to build headers block");
718 		goto error;
719 	}
720 	/* proceed to transaction creation */
721 	memset(&dlg, 0, sizeof(dlg_t));
722 	/* fill call-id if call-id present or else generate a callid */
723 	if (callid.s && callid.len) dlg.id.call_id=callid;
724 	else generate_callid(&dlg.id.call_id);
725 
726 	/* We will not fill in dlg->id.rem_tag because
727 	 * if present it will be printed within To HF
728 	 */
729 
730 	/* Generate fromtag if not present */
731 	if (!fromtag) {
732 		generate_fromtag(&dlg.id.loc_tag, &dlg.id.call_id, &ruri);
733 	}
734 
735 	/* Fill in CSeq */
736 	if (cseq_is) dlg.loc_seq.value = cseq;
737 	else dlg.loc_seq.value = DEFAULT_CSEQ;
738 	dlg.loc_seq.is_set = 1;
739 
740 	dlg.loc_uri = faked_msg.from->body;
741 	dlg.rem_uri = faked_msg.to->body;
742 	dlg.rem_target = ruri;
743 	dlg.dst_uri = nexthop;
744 	dlg.send_sock=ssock;
745 
746 	memset(&uac_req, 0, sizeof(uac_req));
747 	uac_req.method=&method;
748 	if(hfb.s!=NULL && hfb.len>0) uac_req.headers=&hfb;
749 	uac_req.body=body.len?&body:0;
750 	uac_req.dialog=&dlg;
751 	if (reply_wait==1){
752 		dctx=rpc->delayed_ctx_new(c);
753 		if (dctx==0){
754 			rpc->fault(c, 500, "internal error: failed to create context");
755 			return;
756 		}
757 		uac_req.cb=rpc_uac_callback;
758 		uac_req.cbp=dctx;
759 		uac_req.cb_flags=TMCB_LOCAL_COMPLETED;
760 		/* switch to dctx, in case adding the callback fails and we
761 		   want to still send a reply */
762 		rpc=&dctx->rpc;
763 		c=dctx->reply_ctx;
764 	} else if (reply_wait==2) {
765 		sruid_next(&_tm_rpc_sruid);
766 		uac_req.cb = rpc_uac_block_callback;
767 		ruid = shm_str_dup_block(&_tm_rpc_sruid.uid);
768 		uac_req.cbp = ruid;
769 		uac_req.cb_flags = TMCB_LOCAL_COMPLETED;
770 	}
771 
772 	ret = t_uac(&uac_req);
773 
774 	if (ret <= 0) {
775 		err_ret = err2reason_phrase(ret, &sip_error, err_buf,
776 				sizeof(err_buf), "RPC/UAC") ;
777 		if (err_ret > 0 ) {
778 			rpc->fault(c, sip_error, "%s", err_buf);
779 		} else {
780 			rpc->fault(c, 500, "RPC/UAC error");
781 		}
782 		if (dctx) {
783 			rpc->delayed_ctx_close(dctx);
784 		}
785 		if(ruid) {
786 			shm_free(ruid);
787 		}
788 		goto error01;
789 	}
790 
791 	if(reply_wait==2) {
792 		while(ritem==NULL && rcount<800) {
793 			sleep_us(100000);
794 			rcount++;
795 			ritem = tm_rpc_response_list_get(&_tm_rpc_sruid.uid);
796 		}
797 		if(ritem == NULL) {
798 			rpc->fault(c, 500, "No response");
799 		} else {
800 			/* add structure node */
801 			if (rpc->add(c, "{", &th) < 0) {
802 				rpc->fault(c, 500, "Structure error");
803 			} else {
804 				if(rpc->struct_add(th, "dS",
805 						"code", 	ritem->rcode,
806 						"text", 	&ritem->rtext)<0) {
807 					rpc->fault(c, 500, "Fields error");
808 					return;
809 				}
810 			}
811 			shm_free(ritem);
812 		}
813 	}
814 
815 error01:
816 	if (hfb.s) pkg_free(hfb.s);
817 error:
818 	if (faked_msg.headers) free_hdr_field_lst(faked_msg.headers);
819 }
820 
821 
822 /** t_uac with no reply waiting.
823  * @see rpc_t_uac.
824  */
rpc_t_uac_start(rpc_t * rpc,void * c)825 void rpc_t_uac_start(rpc_t* rpc, void* c)
826 {
827 	rpc_t_uac(rpc, c, 0);
828 }
829 
830 /** t_uac with reply waiting.
831  * @see rpc_t_uac.
832  */
rpc_t_uac_wait(rpc_t * rpc,void * c)833 void rpc_t_uac_wait(rpc_t* rpc, void* c)
834 {
835 	rpc_t_uac(rpc, c, 1);
836 }
837 
838 /** t_uac with blocking for reply waiting.
839  * @see rpc_t_uac.
840  */
rpc_t_uac_wait_block(rpc_t * rpc,void * c)841 void rpc_t_uac_wait_block(rpc_t* rpc, void* c)
842 {
843 	rpc_t_uac(rpc, c, 2);
844 }
845 
846 
t_uac_check_msg(struct sip_msg * msg,str * method,str * body,str * fromtag,int * cseq_is,int * cseq,str * callid)847 static int t_uac_check_msg(struct sip_msg* msg,
848 		str* method, str* body,
849 		str *fromtag, int *cseq_is, int* cseq,
850 		str* callid)
851 {
852 	struct to_body* parsed_from;
853 	struct cseq_body *parsed_cseq;
854 	int i;
855 	char ch;
856 
857 	if (body->len && !msg->content_type) {
858 		LM_ERR("Content-Type missing\n");
859 		goto err;
860 	}
861 
862 	if (body->len && msg->content_length) {
863 		LM_ERR("Content-Length disallowed\n");
864 		goto err;
865 	}
866 
867 	if (!msg->to) {
868 		LM_ERR("To missing\n");
869 		goto err;
870 	}
871 
872 	if (!msg->from) {
873 		LM_ERR("From missing\n");
874 		goto err;
875 	}
876 
877 	/* we also need to know if there is from-tag and add it otherwise */
878 	if (parse_from_header(msg) < 0) {
879 		LM_ERR("Error in From\n");
880 		goto err;
881 	}
882 
883 	parsed_from = (struct to_body*)msg->from->parsed;
884 	if(parsed_from->tag_value.s && parsed_from->tag_value.len) {
885 		fromtag->s = parsed_from->tag_value.s;
886 		fromtag->len = parsed_from->tag_value.len;
887 	} else {
888 		fromtag->s = NULL;
889 		fromtag->len = 0;
890 	}
891 
892 	*cseq = 0;
893 	if (msg->cseq && (parsed_cseq = get_cseq(msg))) {
894 		*cseq_is = 1;
895 		for (i = 0; i < parsed_cseq->number.len; i++) {
896 			ch = parsed_cseq->number.s[i];
897 			if (ch >= '0' && ch <= '9' ) {
898 				*cseq = (*cseq) * 10 + ch - '0';
899 			} else {
900 				DBG("check_msg: Found non-numerical in CSeq: <%i>='%c'\n",
901 						(unsigned int)ch, ch);
902 				LM_ERR("Non-numerical CSeq\n");
903 				goto err;
904 			}
905 		}
906 
907 		if (parsed_cseq->method.len != method->len ||
908 				memcmp(parsed_cseq->method.s, method->s, method->len) !=0 ) {
909 			LM_ERR("CSeq method mismatch\n");
910 			goto err;
911 		}
912 	} else {
913 		*cseq_is = 0;
914 	}
915 
916 	if (msg->callid) {
917 		callid->s = msg->callid->body.s;
918 		callid->len = msg->callid->body.len;
919 	} else {
920 		callid->s = 0;
921 		callid->len = 0;
922 	}
923 	return 0;
924 
925 err:
926 	return -1;
927 }
928 
t_uac_send(str * method,str * ruri,str * nexthop,str * send_socket,str * headers,str * body)929 int t_uac_send(str *method, str *ruri, str *nexthop, str *send_socket,
930 		str *headers, str *body)
931 {
932 	str hfb, callid;
933 	struct sip_uri p_uri, pnexthop;
934 	struct sip_msg faked_msg;
935 	struct socket_info* ssock;
936 	str saddr;
937 	int sport, sproto;
938 	int ret, cseq_is, cseq;
939 	str fromtag;
940 	dlg_t dlg;
941 	uac_req_t uac_req;
942 
943 	ret = -1;
944 
945 	/* check and parse parameters */
946 	if (method->len<=0){
947 		LM_ERR("Empty method\n");
948 		return -1;
949 	}
950 	if (parse_uri(ruri->s, ruri->len, &p_uri)<0){
951 		LM_ERR("Invalid request uri \"%s\"", ruri->s);
952 		return -1;
953 	}
954 	if (nexthop->len==1 && nexthop->s[0]=='.'){
955 		/* empty nextop */
956 		nexthop->len=0;
957 		nexthop->s=0;
958 	}else if (nexthop->len==0){
959 		nexthop->s=0;
960 	}else if (parse_uri(nexthop->s, nexthop->len, &pnexthop)<0){
961 		LM_ERR("Invalid next-hop uri \"%s\"", nexthop->s);
962 		return -1;
963 	}
964 	ssock=0;
965 	saddr.s=0;
966 	saddr.len=0;
967 	if (send_socket->len==1 && send_socket->s[0]=='.'){
968 		/* empty send socket */
969 		send_socket->len=0;
970 	}else if (send_socket->len &&
971 			(parse_phostport(send_socket->s, &saddr.s, &saddr.len,
972 							 &sport, &sproto)!=0 ||
973 			 /* check also if it's not a MH addr. */
974 			 saddr.len==0 || saddr.s[0]=='(')
975 			){
976 		LM_ERR("Invalid send socket \"%s\"", send_socket->s);
977 		return -1;
978 	}else if (saddr.len && (ssock=grep_sock_info(&saddr, sport, sproto))==0){
979 		LM_ERR("No local socket for \"%s\"", send_socket->s);
980 		return -1;
981 	}
982 	/* check headers using the SIP parser to look in the header list */
983 	memset(&faked_msg, 0, sizeof(struct sip_msg));
984 	faked_msg.len=headers->len;
985 	faked_msg.buf=faked_msg.unparsed=headers->s;
986 	if (parse_headers(&faked_msg, HDR_EOH_F, 0)==-1){
987 		LM_ERR("Invalid headers\n");
988 		return -1;
989 	}
990 	/* at this moment all the parameters are parsed => more sanity checks */
991 	if (t_uac_check_msg(&faked_msg, method, body, &fromtag,
992 				&cseq_is, &cseq, &callid)<0) {
993 		LM_ERR("checking values failed\n");
994 		goto error;
995 	}
996 	if(get_hfblock(nexthop->len? nexthop: ruri, faked_msg.headers,
997 			PROTO_NONE, ssock, &hfb)<0) {
998 		LM_ERR("failed to get the block of headers\n");
999 		goto error;
1000 	}
1001 	/* proceed to transaction creation */
1002 	memset(&dlg, 0, sizeof(dlg_t));
1003 	/* fill call-id if call-id present or else generate a callid */
1004 	if (callid.s && callid.len) dlg.id.call_id=callid;
1005 	else generate_callid(&dlg.id.call_id);
1006 
1007 	/* We will not fill in dlg->id.rem_tag because
1008 	 * if present it will be printed within To HF
1009 	 */
1010 
1011 	/* Generate fromtag if not present */
1012 	if (fromtag.s && fromtag.len) {
1013 		dlg.id.loc_tag = fromtag;
1014 	} else {
1015 		generate_fromtag(&dlg.id.loc_tag, &dlg.id.call_id, ruri);
1016 	}
1017 
1018 	/* Fill in CSeq */
1019 	if (cseq_is) dlg.loc_seq.value = cseq;
1020 	else dlg.loc_seq.value = DEFAULT_CSEQ;
1021 	dlg.loc_seq.is_set = 1;
1022 
1023 	dlg.loc_uri = get_from(&faked_msg)->uri;
1024 	dlg.rem_uri = get_to(&faked_msg)->uri;
1025 	if(get_to(&faked_msg)->tag_value.len > 0) {
1026 		dlg.id.rem_tag = get_to(&faked_msg)->tag_value;
1027 	}
1028 	dlg.rem_target = *ruri;
1029 	dlg.dst_uri = *nexthop;
1030 	dlg.send_sock=ssock;
1031 
1032 	memset(&uac_req, 0, sizeof(uac_req));
1033 	uac_req.method=method;
1034 	if(hfb.s!=NULL && hfb.len>0) uac_req.headers=&hfb;
1035 	uac_req.body=body->len?body:0;
1036 	uac_req.dialog=&dlg;
1037 
1038 	ret = t_uac(&uac_req);
1039 
1040 	if (ret <= 0) {
1041 		LM_ERR("UAC error\n");
1042 		goto error01;
1043 	}
1044 error01:
1045 	if (hfb.s) pkg_free(hfb.s);
1046 error:
1047 	if (faked_msg.headers) free_hdr_field_lst(faked_msg.headers);
1048 
1049 	return ret;
1050 }
1051 
1052 /* vi: set ts=4 sw=4 tw=79:ai:cindent: */
1053