1 /**
2  *
3  * Copyright (C) 2003-2008 Sippy Software, Inc., http://www.sippysoft.com
4  *
5  * This file is part of Kamailio, a free SIP server.
6  *
7  * Kamailio is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version
11  *
12  * Kamailio is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21 
22 #include <sys/types.h>
23 #include <sys/socket.h>
24 #include <sys/time.h>
25 #include <netinet/in.h>
26 #include <netinet/in_systm.h>
27 #ifndef __USE_BSD
28 #define  __USE_BSD
29 #endif
30 #include <netinet/ip.h>
31 #ifndef __FAVOR_BSD
32 #define __FAVOR_BSD
33 #endif
34 #include <netinet/udp.h>
35 #include <arpa/inet.h>
36 #include <sys/uio.h>
37 #include <sys/un.h>
38 #include <ctype.h>
39 #include <errno.h>
40 #include <netdb.h>
41 #include <poll.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <unistd.h>
46 
47 #include "../../core/flags.h"
48 #include "../../core/sr_module.h"
49 #include "../../core/dprint.h"
50 #include "../../core/data_lump.h"
51 #include "../../core/data_lump_rpl.h"
52 #include "../../core/error.h"
53 #include "../../core/forward.h"
54 #include "../../core/mem/mem.h"
55 #include "../../core/parser/parse_from.h"
56 #include "../../core/parser/parse_to.h"
57 #include "../../core/parser/parse_uri.h"
58 #include "../../core/parser/parser_f.h"
59 #include "../../core/parser/sdp/sdp.h"
60 #include "../../core/resolve.h"
61 #include "../../core/timer.h"
62 #include "../../core/trim.h"
63 #include "../../core/ut.h"
64 #include "../../core/pt.h"
65 #include "../../core/timer_proc.h"
66 #include "../../core/rpc.h"
67 #include "../../core/rpc_lookup.h"
68 #include "../../core/pvar.h"
69 #include "../../core/lvalue.h"
70 #include "../../core/msg_translator.h"
71 #include "../../core/usr_avp.h"
72 #include "../../core/socket_info.h"
73 #include "../../core/mod_fix.h"
74 #include "../../core/dset.h"
75 #include "../../core/route.h"
76 #include "../../core/kemi.h"
77 #include "../../modules/tm/tm_load.h"
78 #include "rtpproxy.h"
79 #include "rtpproxy_funcs.h"
80 #include "rtpproxy_stream.h"
81 
82 MODULE_VERSION
83 
84 #if !defined(AF_LOCAL)
85 #define	AF_LOCAL AF_UNIX
86 #endif
87 #if !defined(PF_LOCAL)
88 #define	PF_LOCAL PF_UNIX
89 #endif
90 
91 /* NAT UAC test constants */
92 #define	NAT_UAC_TEST_C_1918	0x01
93 #define	NAT_UAC_TEST_RCVD	0x02
94 #define	NAT_UAC_TEST_V_1918	0x04
95 #define	NAT_UAC_TEST_S_1918	0x08
96 #define	NAT_UAC_TEST_RPORT	0x10
97 
98 
99 #define DEFAULT_RTPP_SET_ID		0
100 static str DEFAULT_RTPP_SET_ID_STR = str_init("0");
101 
102 #define RPC_DEFAULT_NATPING_STATE	1
103 
104 #define RPC_MIN_RECHECK_TICKS		0
105 #define RPC_MAX_RECHECK_TICKS		(unsigned int)-1
106 
107 
108 /* Supported version of the RTP proxy command protocol */
109 #define	SUP_CPROTOVER	20040107
110 /* Required additional version of the RTP proxy command protocol */
111 #define	REQ_CPROTOVER	"20050322"
112 /* Additional version necessary for re-packetization support */
113 #define	REP_CPROTOVER	"20071116"
114 #define	PTL_CPROTOVER	"20081102"
115 
116 #define	CPORT		"22222"
117 static int rp_extract_mediaip(str *, str *, int *, char *);
118 static int alter_mediaip(struct sip_msg *, str *, str *, int, str *, int, int);
119 static int alter_mediaport(struct sip_msg *, str *, str *, str *, int);
120 static int alter_rtcp(struct sip_msg *msg, str *body, str *oldport, str *newport);
121 static char *gencookie();
122 static int rtpp_test(struct rtpp_node*, int, int);
123 static int unforce_rtp_proxy1_f(struct sip_msg *, char *, char *);
124 static int unforce_rtp_proxy(struct sip_msg *, char *);
125 static int force_rtp_proxy(struct sip_msg *, char *, char *, int, int);
126 static int start_recording_f(struct sip_msg *, char *, char *);
127 static int rtpproxy_answer1_f(struct sip_msg *, char *, char *);
128 static int rtpproxy_answer2_f(struct sip_msg *, char *, char *);
129 static int rtpproxy_offer1_f(struct sip_msg *, char *, char *);
130 static int rtpproxy_offer2_f(struct sip_msg *, char *, char *);
131 static int rtpproxy_manage0(struct sip_msg *msg, char *flags, char *ip);
132 static int rtpproxy_manage1(struct sip_msg *msg, char *flags, char *ip);
133 static int rtpproxy_manage2(struct sip_msg *msg, char *flags, char *ip);
134 
135 static int add_rtpproxy_socks(struct rtpp_set * rtpp_list, char * rtpproxy);
136 static int fixup_set_id(void ** param, int param_no);
137 static int set_rtp_proxy_set_f(struct sip_msg * msg, char * str1, char * str2);
138 static struct rtpp_set * select_rtpp_set(int id_set);
139 
140 static int rtpproxy_set_store(modparam_t type, void * val);
141 static int rtpproxy_add_rtpproxy_set( char * rtp_proxies);
142 
143 static int mod_init(void);
144 static int child_init(int);
145 static void mod_destroy(void);
146 
147 /* Pseudo-Variables */
148 static int pv_get_rtpstat_f(struct sip_msg *, pv_param_t *, pv_value_t *);
149 
150 static int rtpproxy_disable_tout = 60;
151 static int rtpproxy_retr = 5;
152 static int rtpproxy_tout = 1;
153 static pid_t mypid;
154 static unsigned int myseqn = 0;
155 static str nortpproxy_str = str_init("a=nortpproxy:yes");
156 static str extra_id_pv_param = {NULL, 0};
157 
158 static char ** rtpp_strings=0;
159 static int rtpp_sets=0; /*used in rtpproxy_set_store()*/
160 static int rtpp_set_count = 0;
161 static unsigned int current_msg_id = (unsigned int)-1;
162 /* RTP proxy balancing list */
163 struct rtpp_set_head * rtpp_set_list =0;
164 struct rtpp_set * selected_rtpp_set =0;
165 struct rtpp_set * default_rtpp_set=0;
166 static char *ice_candidate_priority_avp_param = NULL;
167 static int ice_candidate_priority_avp_type;
168 static int_str ice_candidate_priority_avp;
169 static str rtp_inst_pv_param = {NULL, 0};
170 static pv_spec_t *rtp_inst_pvar = NULL;
171 
172 /* array with the sockets used by rtpproxy (per process)*/
173 static unsigned int rtpp_no = 0;
174 static int *rtpp_socks = 0;
175 
176 
177 typedef struct rtpp_set_link {
178 	struct rtpp_set *rset;
179 	pv_spec_t *rpv;
180 } rtpp_set_link_t;
181 
182 /* tm */
183 static struct tm_binds tmb;
184 
185 /*0-> disabled, 1 ->enabled*/
186 unsigned int *natping_state=0;
187 
188 static str timeout_socket_str = {0, 0};
189 static pv_elem_t *extra_id_pv = NULL;
190 
191 static cmd_export_t cmds[] = {
192 	{"set_rtp_proxy_set",  (cmd_function)set_rtp_proxy_set_f,    1,
193 		fixup_set_id, 0,
194 		ANY_ROUTE},
195 	{"unforce_rtp_proxy",  (cmd_function)unforce_rtp_proxy1_f,   0,
196 		0, 0,
197 		ANY_ROUTE},
198 	{"rtpproxy_destroy",   (cmd_function)unforce_rtp_proxy1_f,   0,
199 		0, 0,
200 		ANY_ROUTE},
201 	{"unforce_rtp_proxy",  (cmd_function)unforce_rtp_proxy1_f,   1,
202 		fixup_spve_null, 0,
203 		ANY_ROUTE},
204 	{"rtpproxy_destroy",   (cmd_function)unforce_rtp_proxy1_f,   1,
205 		fixup_spve_null, 0,
206 		ANY_ROUTE},
207 	{"start_recording",    (cmd_function)start_recording_f,      0,
208 		0, 0,
209 		ANY_ROUTE },
210 	{"rtpproxy_offer",	(cmd_function)rtpproxy_offer1_f,     0,
211 		0, 0,
212 		ANY_ROUTE},
213 	{"rtpproxy_offer",	(cmd_function)rtpproxy_offer1_f,     1,
214 		fixup_spve_null, 0,
215 		ANY_ROUTE},
216 	{"rtpproxy_offer",	(cmd_function)rtpproxy_offer2_f,     2,
217 		fixup_spve_spve, 0,
218 		ANY_ROUTE},
219 	{"rtpproxy_answer",	(cmd_function)rtpproxy_answer1_f,    0,
220 		0, 0,
221 		ANY_ROUTE},
222 	{"rtpproxy_answer",	(cmd_function)rtpproxy_answer1_f,    1,
223 		fixup_spve_null, 0,
224 		ANY_ROUTE},
225 	{"rtpproxy_answer",	(cmd_function)rtpproxy_answer2_f,    2,
226 		fixup_spve_spve, 0,
227 		ANY_ROUTE},
228 	{"rtpproxy_stream2uac",(cmd_function)rtpproxy_stream2uac2_f, 2,
229 		fixup_var_str_int, 0,
230 		ANY_ROUTE },
231 	{"rtpproxy_stream2uas",(cmd_function)rtpproxy_stream2uas2_f, 2,
232 		fixup_var_str_int, 0,
233 		ANY_ROUTE },
234 	{"rtpproxy_stop_stream2uac",(cmd_function)rtpproxy_stop_stream2uac2_f,0,
235 		NULL, 0,
236 		ANY_ROUTE },
237 	{"rtpproxy_stop_stream2uas",(cmd_function)rtpproxy_stop_stream2uas2_f,0,
238 		NULL, 0,
239 		ANY_ROUTE },
240 	{"rtpproxy_manage",	(cmd_function)rtpproxy_manage0,     0,
241 		0, 0,
242 		ANY_ROUTE},
243 	{"rtpproxy_manage",	(cmd_function)rtpproxy_manage1,     1,
244 		fixup_spve_null, fixup_free_spve_null,
245 		ANY_ROUTE},
246 	{"rtpproxy_manage",	(cmd_function)rtpproxy_manage2,     2,
247 		fixup_spve_spve, fixup_free_spve_spve,
248 		ANY_ROUTE},
249 	{0, 0, 0, 0, 0, 0}
250 };
251 
252 static pv_export_t mod_pvs[] = {
253 	{{"rtpstat", (sizeof("rtpstat")-1)}, /* RTP-Statistics */
254 		PVT_OTHER, pv_get_rtpstat_f, 0, 0, 0, 0, 0},
255 	{{0, 0}, 0, 0, 0, 0, 0, 0, 0}
256 };
257 
258 static param_export_t params[] = {
259 	{"nortpproxy_str",        PARAM_STR, &nortpproxy_str      },
260 	{"rtpproxy_sock",         PARAM_STRING|USE_FUNC_PARAM,
261 		(void*)rtpproxy_set_store          },
262 	{"rtpproxy_disable_tout", INT_PARAM, &rtpproxy_disable_tout },
263 	{"rtpproxy_retr",         INT_PARAM, &rtpproxy_retr         },
264 	{"rtpproxy_tout",         INT_PARAM, &rtpproxy_tout         },
265 	{"timeout_socket",    	  PARAM_STR, &timeout_socket_str  },
266 	{"ice_candidate_priority_avp", PARAM_STRING,
267 		&ice_candidate_priority_avp_param},
268 	{"extra_id_pv",           PARAM_STR, &extra_id_pv_param },
269 	{"db_url",                PARAM_STR, &rtpp_db_url },
270 	{"table_name",            PARAM_STR, &rtpp_table_name },
271 	{"rtp_inst_pvar",         PARAM_STR, &rtp_inst_pv_param },
272 	{0, 0, 0}
273 };
274 
275 struct module_exports exports = {
276 	"rtpproxy",      /* module name */
277 	DEFAULT_DLFLAGS, /* dlopen flags */
278 	cmds,            /* cmd exports */
279 	params,          /* param exports */
280 	0,               /* RPC method exports */
281 	mod_pvs,         /* exported pseudo-variables */
282 	0,               /* reply processing */
283 	mod_init,        /* module init function */
284 	child_init,      /* per-child init function */
285 	mod_destroy,     /* destroy function */
286 };
287 
288 
rtpproxy_set_store(modparam_t type,void * val)289 static int rtpproxy_set_store(modparam_t type, void * val){
290 
291 	char * p;
292 	int len;
293 
294 	p = (char* )val;
295 
296 	if(p==0 || *p=='\0'){
297 		return 0;
298 	}
299 
300 	if(rtpp_sets==0){
301 		rtpp_strings = (char**)pkg_malloc(sizeof(char*));
302 		if(!rtpp_strings){
303 			LM_ERR("no pkg memory left\n");
304 			return -1;
305 		}
306 	} else {/*realloc to make room for the current set*/
307 		rtpp_strings = (char**)pkg_reallocxf(rtpp_strings,
308 				(rtpp_sets+1)* sizeof(char*));
309 		if(!rtpp_strings){
310 			LM_ERR("no pkg memory left\n");
311 			return -1;
312 		}
313 	}
314 
315 	/*allocate for the current set of urls*/
316 	len = strlen(p);
317 	rtpp_strings[rtpp_sets] = (char*)pkg_malloc((len+1)*sizeof(char));
318 
319 	if(!rtpp_strings[rtpp_sets]){
320 		LM_ERR("no pkg memory left\n");
321 		return -1;
322 	}
323 
324 	memcpy(rtpp_strings[rtpp_sets], p, len);
325 	rtpp_strings[rtpp_sets][len] = '\0';
326 	rtpp_sets++;
327 
328 	return 0;
329 }
330 
get_rtpp_set(str * const set_name)331 struct rtpp_set *get_rtpp_set(str *const set_name)
332 {
333 	unsigned int this_set_id;
334 	struct rtpp_set *rtpp_list;
335 	if (rtpp_set_list == NULL)
336 	{
337 		LM_ERR("rtpp set list not configured\n");
338 		return NULL;
339 	}
340 	/* Only integer set_names are valid at the moment */
341 	if ((set_name->s == NULL) || (set_name->len == 0))
342 	{
343 		LM_ERR("Invalid set name '%.*s'\n", set_name->len, set_name->s);
344 		return NULL;
345 	}
346 	if (str2int(set_name, &this_set_id) < 0)
347 	{
348 		LM_ERR("Invalid set name '%.*s' - must be integer\n", set_name->len, set_name->s);
349 		return NULL;
350 	}
351 
352 	rtpp_list = select_rtpp_set(this_set_id);
353 
354 	if(rtpp_list==NULL){	/*if a new id_set : add a new set of rtpp*/
355 		rtpp_list = shm_malloc(sizeof(struct rtpp_set));
356 		if(!rtpp_list){
357 			LM_ERR("no shm memory left\n");
358 			return NULL;
359 		}
360 		memset(rtpp_list, 0, sizeof(struct rtpp_set));
361 		rtpp_list->id_set = this_set_id;
362 		if (rtpp_set_list->rset_first == NULL)
363 		{
364 			rtpp_set_list->rset_first = rtpp_list;
365 		} else {
366 			rtpp_set_list->rset_last->rset_next = rtpp_list;
367 		}
368 		rtpp_set_list->rset_last = rtpp_list;
369 		rtpp_set_count++;
370 
371 		if (this_set_id == DEFAULT_RTPP_SET_ID)
372 		{
373 			default_rtpp_set = rtpp_list;
374 		}
375 	}
376 	return rtpp_list;
377 }
378 
insert_rtpp_node(struct rtpp_set * const rtpp_list,const str * const url,const int weight,const int disabled)379 int insert_rtpp_node(struct rtpp_set *const rtpp_list, const str *const url, const int weight, const int disabled)
380 {
381 	struct rtpp_node *pnode;
382 
383 	if ((pnode = shm_malloc(sizeof(struct rtpp_node) + url->len + 1)) == NULL)
384 	{
385 		LM_ERR("out of shm memory\n");
386 		return -1;
387 	}
388 	memset(pnode, 0, sizeof(struct rtpp_node) + url->len + 1);
389 	pnode->idx = rtpp_no++;
390 	pnode->rn_weight = weight;
391 	pnode->rn_umode = 0;
392 	pnode->rn_disabled = disabled;
393 	/* Permanently disable if marked as disabled */
394 	pnode->rn_recheck_ticks = disabled ? RPC_MAX_RECHECK_TICKS : 0;
395 	pnode->rn_url.s = (char*)(pnode + 1);
396 	memcpy(pnode->rn_url.s, url->s, url->len);
397 	pnode->rn_url.len = url->len;
398 
399 	LM_DBG("url is '%.*s'\n", pnode->rn_url.len, pnode->rn_url.s);
400 
401 	/* Find protocol and store address */
402 	pnode->rn_address = pnode->rn_url.s;
403 	if (strncasecmp(pnode->rn_address, "udp:", 4) == 0) {
404 		pnode->rn_umode = 1;
405 		pnode->rn_address += 4;
406 	} else if (strncasecmp(pnode->rn_address, "udp6:", 5) == 0) {
407 		pnode->rn_umode = 6;
408 		pnode->rn_address += 5;
409 	} else if (strncasecmp(pnode->rn_address, "unix:", 5) == 0) {
410 		pnode->rn_umode = 0;
411 		pnode->rn_address += 5;
412 	}
413 
414 	if (rtpp_list->rn_first == NULL)
415 	{
416 		rtpp_list->rn_first = pnode;
417 	} else {
418 		rtpp_list->rn_last->rn_next = pnode;
419 	}
420 	rtpp_list->rn_last = pnode;
421 	rtpp_list->rtpp_node_count++;
422 
423 	return 0;
424 }
425 
add_rtpproxy_socks(struct rtpp_set * rtpp_list,char * rtpproxy)426 static int add_rtpproxy_socks(struct rtpp_set * rtpp_list,
427 		char * rtpproxy){
428 	/* Make rtp proxies list. */
429 	char *p, *p1, *p2, *plim;
430 	int weight;
431 	str url;
432 
433 	p = rtpproxy;
434 	plim = p + strlen(p);
435 
436 	for(;;) {
437 		weight = 1;
438 		while (*p && isspace((int)*p))
439 			++p;
440 		if (p >= plim)
441 			break;
442 		p1 = p;
443 		while (*p && !isspace((int)*p))
444 			++p;
445 		if (p <= p1)
446 			break; /* may happen??? */
447 		/* Have weight specified? If yes, scan it */
448 		p2 = memchr(p1, '=', p - p1);
449 		if (p2 != NULL) {
450 			weight = strtoul(p2 + 1, NULL, 10);
451 		} else {
452 			p2 = p;
453 		}
454 
455 		url.s = p1;
456 		url.len = (p2-p1);
457 		insert_rtpp_node(rtpp_list, &url, weight, 0);
458 	}
459 	return 0;
460 }
461 
462 
463 /*	0-succes
464  *  -1 - erorr
465  * */
rtpproxy_add_rtpproxy_set(char * rtp_proxies)466 static int rtpproxy_add_rtpproxy_set( char * rtp_proxies)
467 {
468 	char *p,*p2;
469 	struct rtpp_set * rtpp_list;
470 	str id_set;
471 
472 	/* empty definition? */
473 	p= rtp_proxies;
474 	if(!p || *p=='\0'){
475 		return 0;
476 	}
477 
478 	for(;*p && isspace(*p);p++);
479 	if(*p=='\0'){
480 		return 0;
481 	}
482 
483 	rtp_proxies = strstr(p, "==");
484 	if(rtp_proxies){
485 		if(*(rtp_proxies +2)=='\0'){
486 			LM_ERR("script error -invalid rtp proxy list!\n");
487 			return -1;
488 		}
489 
490 		*rtp_proxies = '\0';
491 		p2 = rtp_proxies-1;
492 		for(;isspace(*p2); *p2 = '\0',p2--);
493 		id_set.s = p;	id_set.len = p2 - p+1;
494 
495 		if(id_set.len <= 0){
496 			LM_ERR("script error -invalid set_id value!\n");
497 			return -1;
498 		}
499 
500 		rtp_proxies+=2;
501 	}else{
502 		rtp_proxies = p;
503 		id_set = DEFAULT_RTPP_SET_ID_STR;
504 	}
505 
506 	for(;*rtp_proxies && isspace(*rtp_proxies);rtp_proxies++);
507 
508 	if(!(*rtp_proxies)){
509 		LM_ERR("script error -empty rtp_proxy list\n");
510 		return -1;;
511 	}
512 
513 	rtpp_list = get_rtpp_set(&id_set);
514 	if (rtpp_list == NULL)
515 	{
516 		LM_ERR("Failed to get or create rtpp_list for '%.*s'\n", id_set.len, id_set.s);
517 		return -1;
518 	}
519 
520 	if(add_rtpproxy_socks(rtpp_list, rtp_proxies)!= 0){
521 		return -1;
522 	}
523 
524 	return 0;
525 }
526 
527 
fixup_set_id(void ** param,int param_no)528 static int fixup_set_id(void ** param, int param_no)
529 {
530 	int int_val, err;
531 	struct rtpp_set* rtpp_list;
532 	rtpp_set_link_t *rtpl = NULL;
533 	str s;
534 
535 	rtpl = (rtpp_set_link_t*)pkg_malloc(sizeof(rtpp_set_link_t));
536 	if(rtpl==NULL) {
537 		LM_ERR("no more pkg memory\n");
538 		return -1;
539 	}
540 	memset(rtpl, 0, sizeof(rtpp_set_link_t));
541 	s.s = (char*)*param;
542 	s.len = strlen(s.s);
543 
544 	if(s.s[0] == PV_MARKER) {
545 		int_val = pv_locate_name(&s);
546 		if(int_val<0 || int_val!=s.len) {
547 			LM_ERR("invalid parameter %s\n", s.s);
548 			pkg_free(rtpl);
549 			return -1;
550 		}
551 		rtpl->rpv = pv_cache_get(&s);
552 		if(rtpl->rpv == NULL) {
553 			LM_ERR("invalid pv parameter %s\n", s.s);
554 			pkg_free(rtpl);
555 			return -1;
556 		}
557 	} else {
558 		int_val = str2s(*param, strlen(*param), &err);
559 		if (err == 0) {
560 			pkg_free(*param);
561 			if((rtpp_list = select_rtpp_set(int_val)) ==0){
562 				LM_ERR("rtpp_proxy set %i not configured\n", int_val);
563 				pkg_free(rtpl);
564 				return E_CFG;
565 			}
566 			rtpl->rset = rtpp_list;
567 		} else {
568 			LM_ERR("bad number <%s>\n",	(char *)(*param));
569 			pkg_free(rtpl);
570 			return E_CFG;
571 		}
572 	}
573 	*param = (void*)rtpl;
574 	return 0;
575 }
576 
rtpproxy_rpc_enable(rpc_t * rpc,void * ctx)577 static void  rtpproxy_rpc_enable(rpc_t* rpc, void* ctx)
578 {
579 	str rtpp_url;
580 	int enable;
581 	struct rtpp_set *rtpp_list;
582 	struct rtpp_node *crt_rtpp;
583 	int found;
584 
585 	found = 0;
586 	enable = 0;
587 
588 	if(rtpp_set_list ==NULL)
589 		goto end;
590 
591 	if (rpc->scan(ctx, "Sd", &rtpp_url, &enable) < 2) {
592 		rpc->fault(ctx, 500, "Not enough parameters");
593 		return;
594 	}
595 
596 	for(rtpp_list = rtpp_set_list->rset_first; rtpp_list != NULL;
597 			rtpp_list = rtpp_list->rset_next) {
598 
599 		for(crt_rtpp = rtpp_list->rn_first; crt_rtpp != NULL;
600 				crt_rtpp = crt_rtpp->rn_next) {
601 			/*found a matching rtpp*/
602 			if(crt_rtpp->rn_url.len == rtpp_url.len) {
603 
604 				if(strncmp(crt_rtpp->rn_url.s, rtpp_url.s, rtpp_url.len) == 0) {
605 					/*set the enabled/disabled status*/
606 					found = 1;
607 					crt_rtpp->rn_recheck_ticks =
608 						enable? RPC_MIN_RECHECK_TICKS : RPC_MAX_RECHECK_TICKS;
609 					crt_rtpp->rn_disabled = enable?0:1;
610 				}
611 			}
612 		}
613 	}
614 
615 end:
616 	if(!found) {
617 		rpc->fault(ctx, 404, "RTPProxy not found");
618 		return;
619 	}
620 }
621 
622 
rtpproxy_rpc_list(rpc_t * rpc,void * ctx)623 static void  rtpproxy_rpc_list(rpc_t* rpc, void* ctx)
624 {
625 	struct rtpp_set *rtpp_list;
626 	struct rtpp_node *crt_rtpp;
627 	void *vh;
628 
629 	if(rtpp_set_list ==NULL)
630 		return;
631 
632 	for(rtpp_list = rtpp_set_list->rset_first; rtpp_list != NULL;
633 			rtpp_list = rtpp_list->rset_next) {
634 
635 		for(crt_rtpp = rtpp_list->rn_first; crt_rtpp != NULL;
636 				crt_rtpp = crt_rtpp->rn_next) {
637 
638 			if (rpc->add(ctx, "{", &vh) < 0) {
639 				rpc->fault(ctx, 500, "Server error");
640 				return;
641 			}
642 			rpc->struct_add(vh, "dSdddd",
643 				"setid", rtpp_list->id_set,
644 				"url", &crt_rtpp->rn_url,
645 				"index", crt_rtpp->idx,
646 				"disabled", crt_rtpp->rn_disabled,
647 				"weight", crt_rtpp->rn_weight,
648 				"recheck", crt_rtpp->rn_recheck_ticks);
649 		}
650 	}
651 }
652 
653 static const char* rtpproxy_rpc_enable_doc[2] = {
654 	"Set state (enable/disable) for a rtp proxy.",
655 	0
656 };
657 
658 static const char* rtpproxy_rpc_list_doc[2] = {
659 	"List rtp proxies.",
660 	0
661 };
662 
663 rpc_export_t rtpproxy_rpc[] = {
664 	{"rtpproxy.list", rtpproxy_rpc_list, rtpproxy_rpc_list_doc, RET_ARRAY},
665 	{"rtpproxy.enable", rtpproxy_rpc_enable, rtpproxy_rpc_enable_doc, 0},
666 	{0, 0, 0, 0}
667 };
668 
rtpproxy_rpc_init(void)669 static int rtpproxy_rpc_init(void)
670 {
671 	if (rpc_register_array(rtpproxy_rpc)!=0)
672 	{
673 		LM_ERR("failed to register RPC commands\n");
674 		return -1;
675 	}
676 	return 0;
677 }
678 
679 	static int
mod_init(void)680 mod_init(void)
681 {
682 	int i;
683 	pv_spec_t avp_spec;
684 	str s;
685 	unsigned short avp_flags;
686 
687 	if(rtpproxy_rpc_init()<0)
688 	{
689 		LM_ERR("failed to register RPC commands\n");
690 		return -1;
691 	}
692 
693 	/* Configure the head of the rtpp_set_list */
694 	rtpp_set_list = shm_malloc(sizeof(struct rtpp_set_head));
695 	if (rtpp_set_list == NULL)
696 	{
697 		LM_ERR("no shm memory for rtpp_set_list\n");
698 		return -1;
699 	}
700 	memset(rtpp_set_list, 0, sizeof(struct rtpp_set_head));
701 
702 	if (nortpproxy_str.s==NULL || nortpproxy_str.len<=0) {
703 		nortpproxy_str.len = 0;
704 	} else {
705 		while (nortpproxy_str.len > 0
706 				&& (nortpproxy_str.s[nortpproxy_str.len - 1] == '\r' ||
707 					nortpproxy_str.s[nortpproxy_str.len - 1] == '\n'))
708 			nortpproxy_str.len--;
709 	}
710 
711 	if (rtpp_db_url.s != NULL)
712 	{
713 		init_rtpproxy_db();
714 		if (rtpp_sets > 0)
715 		{
716 			LM_WARN("rtpproxy db url configured - ignoring modparam sets\n");
717 		}
718 	}
719 	/* storing the list of rtp proxy sets in shared memory*/
720 	for(i=0;i<rtpp_sets;i++){
721 		LM_DBG("Adding RTP-Proxy set %d/%d: %s\n", i, rtpp_sets, rtpp_strings[i]);
722 		if ((rtpp_db_url.s == NULL) &&
723 				(rtpproxy_add_rtpproxy_set(rtpp_strings[i]) != 0)) {
724 			for(;i<rtpp_sets;i++)
725 				if(rtpp_strings[i])
726 					pkg_free(rtpp_strings[i]);
727 			pkg_free(rtpp_strings);
728 			LM_ERR("Failed to add RTP-Proxy from Config!\n");
729 			return -1;
730 		}
731 		if(rtpp_strings[i])
732 			pkg_free(rtpp_strings[i]);
733 	}
734 
735 	if (ice_candidate_priority_avp_param) {
736 		s.s = ice_candidate_priority_avp_param; s.len = strlen(s.s);
737 		if (pv_parse_spec(&s, &avp_spec) == 0 || avp_spec.type != PVT_AVP) {
738 			LM_ERR("malformed or non AVP definition <%s>\n",
739 					ice_candidate_priority_avp_param);
740 			return -1;
741 		}
742 		if (pv_get_avp_name(0, &(avp_spec.pvp), &ice_candidate_priority_avp,
743 					&avp_flags) != 0) {
744 			LM_ERR("invalid AVP definition <%s>\n",
745 					ice_candidate_priority_avp_param);
746 			return -1;
747 		}
748 		ice_candidate_priority_avp_type = avp_flags;
749 	}
750 
751 	if (rtp_inst_pv_param.s) {
752 		rtp_inst_pvar = pv_cache_get(&rtp_inst_pv_param);
753 		if ((rtp_inst_pvar == NULL) ||
754 				((rtp_inst_pvar->type != PVT_AVP) &&
755 					(rtp_inst_pvar->type != PVT_XAVP) &&
756 					(rtp_inst_pvar->type != PVT_SCRIPTVAR))) {
757 			LM_ERR("Invalid pvar name <%.*s>\n", rtp_inst_pv_param.len,
758 					rtp_inst_pv_param.s);
759 			return -1;
760 		}
761 	}
762 
763 	if (extra_id_pv_param.s && *extra_id_pv_param.s) {
764 		if(pv_parse_format(&extra_id_pv_param, &extra_id_pv) < 0) {
765 			LM_ERR("malformed PV string: %s\n", extra_id_pv_param.s);
766 			return -1;
767 		}
768 	} else {
769 		extra_id_pv = NULL;
770 	}
771 
772 	if (rtpp_strings)
773 		pkg_free(rtpp_strings);
774 
775 	if (load_tm_api( &tmb ) < 0)
776 	{
777 		LM_DBG("could not load the TM-functions - answer-offer model"
778 				" auto-detection is disabled\n");
779 		memset(&tmb, 0, sizeof(struct tm_binds));
780 	}
781 
782 	return 0;
783 }
784 
785 
786 	static int
child_init(int rank)787 child_init(int rank)
788 {
789 	int n;
790 	char *cp;
791 	struct addrinfo hints, *res;
792 	struct rtpp_set  *rtpp_list;
793 	struct rtpp_node *pnode;
794 
795 	if(rtpp_set_list==NULL )
796 		return 0;
797 
798 	/* do not init sockets for PROC_INIT and main process when fork=yes */
799 	if(rank==PROC_INIT || (rank==PROC_MAIN && dont_fork==0)) {
800 		return 0;
801 	}
802 
803 	/* Iterate known RTP proxies - create sockets */
804 	mypid = getpid();
805 
806 	rtpp_socks = (int*)pkg_malloc( sizeof(int)*rtpp_no );
807 	if (rtpp_socks==NULL) {
808 		LM_ERR("no more pkg memory\n");
809 		return -1;
810 	}
811 	memset(rtpp_socks, -1, sizeof(int)*rtpp_no);
812 
813 	for(rtpp_list = rtpp_set_list->rset_first; rtpp_list != 0;
814 			rtpp_list = rtpp_list->rset_next){
815 
816 		for (pnode=rtpp_list->rn_first; pnode!=0; pnode = pnode->rn_next){
817 			char *hostname;
818 
819 			if (pnode->rn_umode == 0) {
820 				rtpp_socks[pnode->idx] = -1;
821 				goto rptest;
822 			}
823 
824 			/*
825 			 * This is UDP or UDP6. Detect host and port; lookup host;
826 			 * do connect() in order to specify peer address
827 			 */
828 			hostname = (char*)pkg_malloc(sizeof(char) * (strlen(pnode->rn_address) + 1));
829 			if (hostname==NULL) {
830 				LM_ERR("no more pkg memory\n");
831 				return -1;
832 			}
833 			strcpy(hostname, pnode->rn_address);
834 
835 			cp = strrchr(hostname, ':');
836 			if (cp != NULL) {
837 				*cp = '\0';
838 				cp++;
839 			}
840 			if (cp == NULL || *cp == '\0')
841 				cp = CPORT;
842 
843 			memset(&hints, 0, sizeof(hints));
844 			hints.ai_flags = 0;
845 			hints.ai_family = (pnode->rn_umode == 6) ? AF_INET6 : AF_INET;
846 			hints.ai_socktype = SOCK_DGRAM;
847 			if ((n = getaddrinfo(hostname, cp, &hints, &res)) != 0) {
848 				LM_ERR("%s\n", gai_strerror(n));
849 				pkg_free(hostname);
850 				return -1;
851 			}
852 			pkg_free(hostname);
853 
854 			rtpp_socks[pnode->idx] = socket((pnode->rn_umode == 6)
855 					? AF_INET6 : AF_INET, SOCK_DGRAM, 0);
856 			if ( rtpp_socks[pnode->idx] == -1) {
857 				LM_ERR("can't create socket\n");
858 				freeaddrinfo(res);
859 				return -1;
860 			}
861 
862 			if (connect( rtpp_socks[pnode->idx], res->ai_addr, res->ai_addrlen) == -1) {
863 				LM_ERR("can't connect to a RTP proxy\n");
864 				close( rtpp_socks[pnode->idx] );
865 				rtpp_socks[pnode->idx] = -1;
866 				freeaddrinfo(res);
867 				return -1;
868 			}
869 			freeaddrinfo(res);
870 rptest:
871 			pnode->rn_disabled = rtpp_test(pnode, pnode->rn_disabled, 1);
872 		}
873 	}
874 
875 	return 0;
876 }
877 
878 
mod_destroy(void)879 static void mod_destroy(void)
880 {
881 	struct rtpp_set * crt_list, * last_list;
882 	struct rtpp_node * crt_rtpp, *last_rtpp;
883 
884 	/*free the shared memory*/
885 	if (natping_state)
886 		shm_free(natping_state);
887 
888 	if(rtpp_set_list == NULL)
889 		return;
890 
891 	for(crt_list = rtpp_set_list->rset_first; crt_list != NULL; ){
892 
893 		for(crt_rtpp = crt_list->rn_first; crt_rtpp != NULL;  ){
894 
895 			last_rtpp = crt_rtpp;
896 			crt_rtpp = last_rtpp->rn_next;
897 			shm_free(last_rtpp);
898 		}
899 
900 		last_list = crt_list;
901 		crt_list = last_list->rset_next;
902 		shm_free(last_list);
903 	}
904 
905 	shm_free(rtpp_set_list);
906 }
907 
908 
909 
910 	static int
isnulladdr(str * sx,int pf)911 isnulladdr(str *sx, int pf)
912 {
913 	char *cp;
914 
915 	if (pf == AF_INET6) {
916 		for(cp = sx->s; cp < sx->s + sx->len; cp++)
917 			if (*cp != '0' && *cp != ':')
918 				return 0;
919 		return 1;
920 	}
921 	return (sx->len == 7 && memcmp("0.0.0.0", sx->s, 7) == 0);
922 }
923 
924 #define	ADD_ADIRECTION	0x01
925 #define	FIX_MEDIP	0x02
926 #define	ADD_ANORTPPROXY	0x04
927 #define	FIX_ORGIP	0x08
928 
929 #define	ADIRECTION	"a=direction:active"
930 #define	ADIRECTION_LEN	(sizeof(ADIRECTION) - 1)
931 
932 #define	AOLDMEDIP	"a=oldmediaip:"
933 #define	AOLDMEDIP_LEN	(sizeof(AOLDMEDIP) - 1)
934 
935 #define	AOLDMEDIP6	"a=oldmediaip6:"
936 #define	AOLDMEDIP6_LEN	(sizeof(AOLDMEDIP6) - 1)
937 
938 #define	AOLDMEDPRT	"a=oldmediaport:"
939 #define	AOLDMEDPRT_LEN	(sizeof(AOLDMEDPRT) - 1)
940 
941 
942 	static inline int
replace_sdp_ip(struct sip_msg * msg,str * org_body,char * line,str * ip)943 replace_sdp_ip(struct sip_msg* msg, str *org_body, char *line, str *ip)
944 {
945 	str body1, oldip, newip;
946 	str body = *org_body;
947 	unsigned hasreplaced = 0;
948 	int pf, pf1 = 0;
949 	str body2;
950 	char *bodylimit = body.s + body.len;
951 
952 	/* Iterate all lines and replace ips in them. */
953 	if (!ip) {
954 		newip.s = ip_addr2a(&msg->rcv.src_ip);
955 		newip.len = strlen(newip.s);
956 	} else {
957 		newip = *ip;
958 	}
959 	body1 = body;
960 	for(;;) {
961 		if (rp_extract_mediaip(&body1, &oldip, &pf,line) == -1)
962 			break;
963 		if (pf != AF_INET) {
964 			LM_ERR("not an IPv4 address in '%s' SDP\n",line);
965 			return -1;
966 		}
967 		if (!pf1)
968 			pf1 = pf;
969 		else if (pf != pf1) {
970 			LM_ERR("mismatching address families in '%s' SDP\n",line);
971 			return -1;
972 		}
973 		body2.s = oldip.s + oldip.len;
974 		body2.len = bodylimit - body2.s;
975 		if (alter_mediaip(msg, &body1, &oldip, pf, &newip, pf,1) == -1) {
976 			LM_ERR("can't alter '%s' IP\n",line);
977 			return -1;
978 		}
979 		hasreplaced = 1;
980 		body1 = body2;
981 	}
982 	if (!hasreplaced) {
983 		LM_ERR("can't extract '%s' IP from the SDP\n",line);
984 		return -1;
985 	}
986 
987 	return 0;
988 }
989 
990 	static int
rp_extract_mediaip(str * body,str * mediaip,int * pf,char * line)991 rp_extract_mediaip(str *body, str *mediaip, int *pf, char *line)
992 {
993 	char *cp, *cp1;
994 	int len, nextisip;
995 
996 	cp1 = NULL;
997 	for (cp = body->s; (len = body->s + body->len - cp) > 0;) {
998 		cp1 = ser_memmem(cp, line, len, 2);
999 		if (cp1 == NULL || cp1[-1] == '\n' || cp1[-1] == '\r')
1000 			break;
1001 		cp = cp1 + 2;
1002 	}
1003 	if (cp1 == NULL)
1004 		return -1;
1005 
1006 	mediaip->s = cp1 + 2;
1007 	mediaip->len = eat_line(mediaip->s, body->s + body->len - mediaip->s)
1008 						- mediaip->s;
1009 	trim_len(mediaip->len, mediaip->s, *mediaip);
1010 
1011 	nextisip = 0;
1012 	for (cp = mediaip->s; cp < mediaip->s + mediaip->len;) {
1013 		len = eat_token_end(cp, mediaip->s + mediaip->len) - cp;
1014 		if (nextisip == 1) {
1015 			mediaip->s = cp;
1016 			mediaip->len = len;
1017 			nextisip++;
1018 			break;
1019 		}
1020 		if (len == 3 && memcmp(cp, "IP", 2) == 0) {
1021 			switch (cp[2]) {
1022 				case '4':
1023 					nextisip = 1;
1024 					*pf = AF_INET;
1025 					break;
1026 
1027 				case '6':
1028 					nextisip = 1;
1029 					*pf = AF_INET6;
1030 					break;
1031 
1032 				default:
1033 					break;
1034 			}
1035 		}
1036 		cp = eat_space_end(cp + len, mediaip->s + mediaip->len);
1037 	}
1038 	if (nextisip != 2 || mediaip->len == 0) {
1039 		LM_ERR("no `IP[4|6]' in `%s' field\n",line);
1040 		return -1;
1041 	}
1042 	return 1;
1043 }
1044 
1045 	static int
alter_mediaip(struct sip_msg * msg,str * body,str * oldip,int oldpf,str * newip,int newpf,int preserve)1046 alter_mediaip(struct sip_msg *msg, str *body, str *oldip, int oldpf,
1047 		str *newip, int newpf, int preserve)
1048 {
1049 	char *buf;
1050 	int offset;
1051 	struct lump* anchor;
1052 	str omip, nip, oip;
1053 
1054 	/* check that updating mediaip is really necessary */
1055 	if (oldpf == newpf && isnulladdr(oldip, oldpf))
1056 		return 0;
1057 	if (newip->len == oldip->len &&
1058 			memcmp(newip->s, oldip->s, newip->len) == 0)
1059 		return 0;
1060 
1061 	if (preserve != 0) {
1062 		anchor = anchor_lump(msg, body->s + body->len - msg->buf, 0, 0);
1063 		if (anchor == NULL) {
1064 			LM_ERR("anchor_lump failed\n");
1065 			return -1;
1066 		}
1067 		if (oldpf == AF_INET6) {
1068 			omip.s = AOLDMEDIP6;
1069 			omip.len = AOLDMEDIP6_LEN;
1070 		} else {
1071 			omip.s = AOLDMEDIP;
1072 			omip.len = AOLDMEDIP_LEN;
1073 		}
1074 		buf = pkg_malloc(omip.len + oldip->len + CRLF_LEN);
1075 		if (buf == NULL) {
1076 			LM_ERR("out of pkg memory\n");
1077 			return -1;
1078 		}
1079 		memcpy(buf, CRLF, CRLF_LEN);
1080 		memcpy(buf + CRLF_LEN, omip.s, omip.len);
1081 		memcpy(buf + CRLF_LEN + omip.len, oldip->s, oldip->len);
1082 		if (insert_new_lump_after(anchor, buf,
1083 					omip.len + oldip->len + CRLF_LEN, 0) == NULL) {
1084 			LM_ERR("insert_new_lump_after failed\n");
1085 			pkg_free(buf);
1086 			return -1;
1087 		}
1088 	}
1089 
1090 	if (oldpf == newpf) {
1091 		nip.len = newip->len;
1092 		nip.s = pkg_malloc(nip.len);
1093 		if (nip.s == NULL) {
1094 			LM_ERR("out of pkg memory\n");
1095 			return -1;
1096 		}
1097 		memcpy(nip.s, newip->s, newip->len);
1098 	} else {
1099 		nip.len = newip->len + 2;
1100 		nip.s = pkg_malloc(nip.len);
1101 		if (nip.s == NULL) {
1102 			LM_ERR("out of pkg memory\n");
1103 			return -1;
1104 		}
1105 		memcpy(nip.s + 2, newip->s, newip->len);
1106 		nip.s[0] = (newpf == AF_INET6) ? '6' : '4';
1107 		nip.s[1] = ' ';
1108 	}
1109 
1110 	oip = *oldip;
1111 	if (oldpf != newpf) {
1112 		do {
1113 			oip.s--;
1114 			oip.len++;
1115 		} while (*oip.s != '6' && *oip.s != '4');
1116 	}
1117 	offset = oip.s - msg->buf;
1118 	anchor = del_lump(msg, offset, oip.len, 0);
1119 	if (anchor == NULL) {
1120 		LM_ERR("del_lump failed\n");
1121 		pkg_free(nip.s);
1122 		return -1;
1123 	}
1124 
1125 	if (insert_new_lump_after(anchor, nip.s, nip.len, 0) == 0) {
1126 		LM_ERR("insert_new_lump_after failed\n");
1127 		pkg_free(nip.s);
1128 		return -1;
1129 	}
1130 	return 0;
1131 }
1132 
1133 	static int
alter_mediaport(struct sip_msg * msg,str * body,str * oldport,str * newport,int preserve)1134 alter_mediaport(struct sip_msg *msg, str *body, str *oldport, str *newport,
1135 		int preserve)
1136 {
1137 	char *buf;
1138 	int offset;
1139 	struct lump* anchor;
1140 
1141 	/* check that updating mediaport is really necessary */
1142 	if (newport->len == oldport->len &&
1143 			memcmp(newport->s, oldport->s, newport->len) == 0)
1144 		return 0;
1145 
1146 	/*
1147 	 * Since rewriting the same info twice will mess SDP up,
1148 	 * apply simple anti foot shooting measure - put flag on
1149 	 * messages that have been altered and check it when
1150 	 * another request comes.
1151 	 */
1152 #if 0
1153 	/* disabled: - it propagates to the reply and we don't want this
1154 	 *  -- andrei */
1155 	if (msg->msg_flags & FL_SDP_PORT_AFS) {
1156 		LM_ERR("you can't rewrite the same SDP twice, check your config!\n");
1157 		return -1;
1158 	}
1159 #endif
1160 
1161 	if (preserve != 0) {
1162 		anchor = anchor_lump(msg, body->s + body->len - msg->buf, 0, 0);
1163 		if (anchor == NULL) {
1164 			LM_ERR("anchor_lump failed\n");
1165 			return -1;
1166 		}
1167 		buf = pkg_malloc(AOLDMEDPRT_LEN + oldport->len + CRLF_LEN);
1168 		if (buf == NULL) {
1169 			LM_ERR("out of pkg memory\n");
1170 			return -1;
1171 		}
1172 		memcpy(buf, CRLF, CRLF_LEN);
1173 		memcpy(buf + CRLF_LEN, AOLDMEDPRT, AOLDMEDPRT_LEN);
1174 		memcpy(buf + CRLF_LEN + AOLDMEDPRT_LEN, oldport->s, oldport->len);
1175 		if (insert_new_lump_after(anchor, buf,
1176 					AOLDMEDPRT_LEN + oldport->len + CRLF_LEN, 0) == NULL) {
1177 			LM_ERR("insert_new_lump_after failed\n");
1178 			pkg_free(buf);
1179 			return -1;
1180 		}
1181 	}
1182 
1183 	buf = pkg_malloc(newport->len);
1184 	if (buf == NULL) {
1185 		LM_ERR("out of pkg memory\n");
1186 		return -1;
1187 	}
1188 	offset = oldport->s - msg->buf;
1189 	anchor = del_lump(msg, offset, oldport->len, 0);
1190 	if (anchor == NULL) {
1191 		LM_ERR("del_lump failed\n");
1192 		pkg_free(buf);
1193 		return -1;
1194 	}
1195 	memcpy(buf, newport->s, newport->len);
1196 	if (insert_new_lump_after(anchor, buf, newport->len, 0) == 0) {
1197 		LM_ERR("insert_new_lump_after failed\n");
1198 		pkg_free(buf);
1199 		return -1;
1200 	}
1201 
1202 #if 0
1203 	msg->msg_flags |= FL_SDP_PORT_AFS;
1204 #endif
1205 	return 0;
1206 }
1207 
1208 /**
1209  *
1210  */
1211 	static int
alter_rtcp(struct sip_msg * msg,str * body,str * oldport,str * newport)1212 alter_rtcp(struct sip_msg *msg, str *body, str *oldport, str *newport)
1213 {
1214 	char *buf;
1215 	int offset;
1216 	struct lump* anchor;
1217 
1218 	/* check that updating rtcpport is really necessary */
1219 	if (newport->len == oldport->len &&
1220 			memcmp(newport->s, oldport->s, newport->len) == 0)
1221 		return 0;
1222 
1223 	buf = pkg_malloc(newport->len);
1224 	if (buf == NULL) {
1225 		LM_ERR("alter_rtcp: out of memory\n");
1226 		return -1;
1227 	}
1228 	offset = oldport->s - msg->buf;
1229 	anchor = del_lump(msg, offset, oldport->len, 0);
1230 	if (anchor == NULL) {
1231 		LM_ERR("alter_rtcp: del_lump failed\n");
1232 		pkg_free(buf);
1233 		return -1;
1234 	}
1235 	memcpy(buf, newport->s, newport->len);
1236 	if (insert_new_lump_after(anchor, buf, newport->len, 0) == 0) {
1237 		LM_ERR("alter_rtcp: insert_new_lump_after failed\n");
1238 		pkg_free(buf);
1239 		return -1;
1240 	}
1241 
1242 	return 0;
1243 }
1244 
1245 
1246 	static char *
append_filtered_ip(char * at,str * ip)1247 append_filtered_ip(char *at, str *ip)
1248 {
1249 	int i;
1250 	for (i = 0; i < ip->len; i++) {
1251 		if (isdigit(ip->s[i])) {
1252 			append_chr(at, ip->s[i]);
1253 		}
1254 	}
1255 	return at;
1256 }
1257 
1258 
1259 	static int
insert_candidates(struct sip_msg * msg,char * where,str * ip,unsigned int port,int priority)1260 insert_candidates(struct sip_msg *msg, char *where, str *ip, unsigned int port,
1261 		int priority)
1262 {
1263 	char *buf, *at;
1264 	struct lump* anchor;
1265 	str rtp_port;
1266 	str rtcp_port;
1267 
1268 	rtcp_port.s = int2str(port+1, &rtcp_port.len); /* beware static buffer */
1269 	buf = pkg_malloc(24 + 78 + 14 + 24 + 2*ip->len + 2 + 2*rtcp_port.len + 24);
1270 	if (buf == NULL) {
1271 		LM_ERR("insert_candidates: out of memory\n");
1272 		return -1;
1273 	}
1274 
1275 	at = buf;
1276 
1277 	append_str(at, "a=candidate:", 12);
1278 	at = append_filtered_ip(at, ip);
1279 	append_str(at, " 2 UDP ", 7);
1280 	if (priority == 2) {
1281 		append_str(at, "16777214 ", 9);
1282 	} else {
1283 		append_str(at, "2197815294 ", 11);
1284 	}
1285 	append_str(at, ip->s, ip->len);
1286 	append_chr(at, ' ');
1287 	append_str(at, rtcp_port.s, rtcp_port.len);
1288 	append_str(at, " typ relay\r\n", 12);
1289 
1290 	rtp_port.s = int2str(port, &rtp_port.len); /* beware static buffer */
1291 	append_str(at, "a=candidate:", 12);
1292 	at = append_filtered_ip(at, ip);
1293 	append_str(at, " 1 UDP ", 7);
1294 	if (priority == 2) {
1295 		append_str(at, "16777215 ", 9);
1296 	} else {
1297 		append_str(at, "2197815295 ", 11);
1298 	}
1299 	append_str(at, ip->s, ip->len);
1300 	append_chr(at, ' ');
1301 	append_str(at, rtp_port.s, rtp_port.len);
1302 	append_str(at, " typ relay\r\n", 12);
1303 
1304 	LM_DBG("inserting '%.*s'\n", (int)(at - buf), buf);
1305 
1306 	anchor = anchor_lump(msg, where - msg->buf, 0, 0);
1307 	if (anchor == 0) {
1308 		LM_ERR("can't get anchor\n");
1309 		pkg_free(buf);
1310 		return -1;
1311 	}
1312 	if (insert_new_lump_before(anchor, buf, at - buf, 0) == 0) {
1313 		LM_ERR("insert_new_lump_before failed\n");
1314 		pkg_free(buf);
1315 		return -1;
1316 	}
1317 
1318 	return 0;
1319 }
1320 
1321 
gencookie(void)1322 static char * gencookie(void)
1323 {
1324 	static char cook[34];
1325 
1326 	sprintf(cook, "%d_%u ", (int)mypid, myseqn);
1327 	myseqn++;
1328 	return cook;
1329 }
1330 
1331 	static int
rtpp_checkcap(struct rtpp_node * node,char * cap,int caplen)1332 rtpp_checkcap(struct rtpp_node *node, char *cap, int caplen)
1333 {
1334 	char *cp;
1335 	struct iovec vf[4] = {{NULL, 0}, {"VF", 2}, {" ", 1}, {NULL, 0}};
1336 
1337 	vf[3].iov_base = cap;
1338 	vf[3].iov_len = caplen;
1339 
1340 	cp = send_rtpp_command(node, vf, 4);
1341 	if (cp == NULL)
1342 		return -1;
1343 	if (cp[0] == 'E' || atoi(cp) != 1)
1344 		return 0;
1345 	return 1;
1346 }
1347 
1348 	static int
rtpp_test(struct rtpp_node * node,int isdisabled,int force)1349 rtpp_test(struct rtpp_node *node, int isdisabled, int force)
1350 {
1351 	int rtpp_ver, rval;
1352 	char *cp;
1353 	struct iovec v[2] = {{NULL, 0}, {"V", 1}};
1354 
1355 	if(node->rn_recheck_ticks == RPC_MAX_RECHECK_TICKS){
1356 		LM_DBG("rtpp %s disabled for ever\n", node->rn_url.s);
1357 		return 1;
1358 	}
1359 
1360 	if (force == 0) {
1361 		if (isdisabled == 0)
1362 			return 0;
1363 		if (node->rn_recheck_ticks > get_ticks())
1364 			return 1;
1365 	}
1366 	cp = send_rtpp_command(node, v, 2);
1367 	if (cp == NULL) {
1368 		LM_WARN("can't get version of the RTP proxy\n");
1369 		goto error;
1370 	}
1371 	rtpp_ver = atoi(cp);
1372 	if (rtpp_ver != SUP_CPROTOVER) {
1373 		LM_WARN("unsupported version of RTP proxy <%s> found: %d supported,"
1374 				"%d present\n", node->rn_url.s, SUP_CPROTOVER, rtpp_ver);
1375 		goto error;
1376 	}
1377 	rval = rtpp_checkcap(node, REQ_CPROTOVER, sizeof(REQ_CPROTOVER) - 1);
1378 	if (rval == -1) {
1379 		LM_WARN("RTP proxy went down during version query\n");
1380 		goto error;
1381 	}
1382 	if (rval == 0) {
1383 		LM_WARN("of RTP proxy <%s> doesn't support required protocol version"
1384 				"%s\n", node->rn_url.s, REQ_CPROTOVER);
1385 		goto error;
1386 	}
1387 	LM_INFO("rtp proxy <%s> found, support for it %senabled\n",
1388 			node->rn_url.s, force == 0 ? "re-" : "");
1389 	/* Check for optional capabilities */
1390 	rval = rtpp_checkcap(node, REP_CPROTOVER, sizeof(REP_CPROTOVER) - 1);
1391 	if (rval != -1) {
1392 		node->rn_rep_supported = rval;
1393 	} else {
1394 		node->rn_rep_supported = 0;
1395 	}
1396 	rval = rtpp_checkcap(node, PTL_CPROTOVER, sizeof(PTL_CPROTOVER) - 1);
1397 	if (rval != -1) {
1398 		node->rn_ptl_supported = rval;
1399 	} else {
1400 		node->rn_ptl_supported = 0;
1401 	}
1402 	return 0;
1403 error:
1404 	LM_WARN("support for RTP proxy <%s> has been disabled%s\n", node->rn_url.s,
1405 			rtpproxy_disable_tout < 0 ? "" : " temporarily");
1406 	if (rtpproxy_disable_tout >= 0)
1407 		node->rn_recheck_ticks = get_ticks() + rtpproxy_disable_tout;
1408 
1409 	return 1;
1410 }
1411 
1412 	char *
send_rtpp_command(struct rtpp_node * node,struct iovec * v,int vcnt)1413 send_rtpp_command(struct rtpp_node *node, struct iovec *v, int vcnt)
1414 {
1415 	struct sockaddr_un addr;
1416 	int fd, len, i;
1417 	char *cp;
1418 	static char buf[256];
1419 	struct pollfd fds[1];
1420 
1421 	len = 0;
1422 	cp = buf;
1423 	if (node->rn_umode == 0) {
1424 		memset(&addr, 0, sizeof(addr));
1425 		addr.sun_family = AF_LOCAL;
1426 		strncpy(addr.sun_path, node->rn_address,
1427 				sizeof(addr.sun_path) - 1);
1428 #ifdef HAVE_SOCKADDR_SA_LEN
1429 		addr.sun_len = strlen(addr.sun_path);
1430 #endif
1431 
1432 		fd = socket(AF_LOCAL, SOCK_STREAM, 0);
1433 		if (fd < 0) {
1434 			LM_ERR("can't create socket\n");
1435 			goto badproxy;
1436 		}
1437 		if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1438 			close(fd);
1439 			LM_ERR("can't connect to RTP proxy\n");
1440 			goto badproxy;
1441 		}
1442 
1443 		do {
1444 			len = writev(fd, v + 1, vcnt - 1);
1445 		} while (len == -1 && errno == EINTR);
1446 		if (len <= 0) {
1447 			close(fd);
1448 			LM_ERR("can't send command to a RTP proxy\n");
1449 			goto badproxy;
1450 		}
1451 		do {
1452 			len = read(fd, buf, sizeof(buf) - 1);
1453 		} while (len == -1 && errno == EINTR);
1454 		close(fd);
1455 		if (len <= 0) {
1456 			LM_ERR("can't read reply from a RTP proxy\n");
1457 			goto badproxy;
1458 		}
1459 	} else {
1460 		fds[0].fd = rtpp_socks[node->idx];
1461 		fds[0].events = POLLIN;
1462 		fds[0].revents = 0;
1463 		/* Drain input buffer */
1464 		while ((poll(fds, 1, 0) == 1) &&
1465 				((fds[0].revents & POLLIN) != 0)) {
1466 			recv(rtpp_socks[node->idx], buf, sizeof(buf) - 1, 0);
1467 			fds[0].revents = 0;
1468 		}
1469 		v[0].iov_base = gencookie();
1470 		v[0].iov_len = strlen(v[0].iov_base);
1471 		for (i = 0; i < rtpproxy_retr; i++) {
1472 			do {
1473 				len = writev(rtpp_socks[node->idx], v, vcnt);
1474 			} while (len == -1 && (errno == EINTR || errno == ENOBUFS));
1475 			if (len <= 0) {
1476 				LM_ERR("can't send command to a RTP proxy\n");
1477 				goto badproxy;
1478 			}
1479 			while ((poll(fds, 1, rtpproxy_tout * 1000) == 1) &&
1480 					(fds[0].revents & POLLIN) != 0) {
1481 				do {
1482 					len = recv(rtpp_socks[node->idx], buf, sizeof(buf)-1, 0);
1483 				} while (len == -1 && errno == EINTR);
1484 				if (len <= 0) {
1485 					LM_ERR("can't read reply from a RTP proxy\n");
1486 					goto badproxy;
1487 				}
1488 				if (len >= (v[0].iov_len - 1) &&
1489 						memcmp(buf, v[0].iov_base, (v[0].iov_len - 1)) == 0) {
1490 					len -= (v[0].iov_len - 1);
1491 					cp += (v[0].iov_len - 1);
1492 					if (len != 0) {
1493 						len--;
1494 						cp++;
1495 					}
1496 					goto out;
1497 				}
1498 				fds[0].revents = 0;
1499 			}
1500 		}
1501 		if (i == rtpproxy_retr) {
1502 			LM_ERR("timeout waiting reply from a RTP proxy\n");
1503 			goto badproxy;
1504 		}
1505 	}
1506 
1507 out:
1508 	cp[len] = '\0';
1509 	return cp;
1510 badproxy:
1511 	LM_ERR("proxy <%s> does not respond, disable it\n", node->rn_url.s);
1512 	node->rn_disabled = 1;
1513 	node->rn_recheck_ticks = get_ticks() + rtpproxy_disable_tout;
1514 
1515 	return NULL;
1516 }
1517 
1518 /*
1519  * select the set with the id_set id
1520  */
1521 
select_rtpp_set(int id_set)1522 static struct rtpp_set * select_rtpp_set(int id_set ){
1523 
1524 	struct rtpp_set * rtpp_list;
1525 	/*is it a valid set_id?*/
1526 
1527 	if(!rtpp_set_list)
1528 	{
1529 		LM_ERR("rtpproxy set list not initialised\n");
1530 		return NULL;
1531 	}
1532 
1533 	for(rtpp_list=rtpp_set_list->rset_first; rtpp_list!=NULL &&
1534 			rtpp_list->id_set!=id_set; rtpp_list=rtpp_list->rset_next);
1535 
1536 	return rtpp_list;
1537 }
1538 /*
1539  * Main balancing routine. This does not try to keep the same proxy for
1540  * the call if some proxies were disabled or enabled; proxy death considered
1541  * too rare. Otherwise we should implement "mature" HA clustering, which is
1542  * too expensive here.
1543  */
1544 	struct rtpp_node *
select_rtpp_node(str callid,int do_test)1545 select_rtpp_node(str callid, int do_test)
1546 {
1547 	unsigned sum, sumcut, weight_sum;
1548 	struct rtpp_node* node;
1549 	int was_forced;
1550 
1551 	if(!selected_rtpp_set){
1552 		LM_ERR("script error -no valid set selected\n");
1553 		return NULL;
1554 	}
1555 	/* Most popular case: 1 proxy, nothing to calculate */
1556 	if (selected_rtpp_set->rtpp_node_count == 1) {
1557 		node = selected_rtpp_set->rn_first;
1558 		if (node->rn_disabled && node->rn_recheck_ticks <= get_ticks())
1559 			node->rn_disabled = rtpp_test(node, 1, 0);
1560 		return node->rn_disabled ? NULL : node;
1561 	}
1562 
1563 	/* XXX Use quick-and-dirty hashing algo */
1564 	for(sum = 0; callid.len > 0; callid.len--)
1565 		sum += callid.s[callid.len - 1];
1566 	sum &= 0xff;
1567 
1568 	was_forced = 0;
1569 retry:
1570 	weight_sum = 0;
1571 	for (node=selected_rtpp_set->rn_first; node!=NULL; node=node->rn_next) {
1572 
1573 		if (node->rn_disabled && node->rn_recheck_ticks <= get_ticks()){
1574 			/* Try to enable if it's time to try. */
1575 			node->rn_disabled = rtpp_test(node, 1, 0);
1576 		}
1577 		if (!node->rn_disabled)
1578 			weight_sum += node->rn_weight;
1579 	}
1580 	if (weight_sum == 0) {
1581 		/* No proxies? Force all to be redetected, if not yet */
1582 		if (was_forced)
1583 			return NULL;
1584 		was_forced = 1;
1585 		for(node=selected_rtpp_set->rn_first; node!=NULL; node=node->rn_next) {
1586 			node->rn_disabled = rtpp_test(node, 1, 1);
1587 		}
1588 		goto retry;
1589 	}
1590 	sumcut = sum % weight_sum;
1591 	/*
1592 	 * sumcut here lays from 0 to weight_sum-1.
1593 	 * Scan proxy list and decrease until appropriate proxy is found.
1594 	 */
1595 	for (node=selected_rtpp_set->rn_first; node!=NULL; node=node->rn_next) {
1596 		if (node->rn_disabled)
1597 			continue;
1598 		if (sumcut < node->rn_weight)
1599 			goto found;
1600 		sumcut -= node->rn_weight;
1601 	}
1602 	/* No node list */
1603 	return NULL;
1604 found:
1605 	if (do_test) {
1606 		node->rn_disabled = rtpp_test(node, node->rn_disabled, 0);
1607 		if (node->rn_disabled)
1608 			goto retry;
1609 	}
1610 	return node;
1611 }
1612 
1613 
1614 static int
get_extra_id(struct sip_msg * msg,str * id_str)1615 get_extra_id(struct sip_msg* msg, str *id_str) {
1616 	if(msg==NULL || extra_id_pv==NULL || id_str==NULL) {
1617 		LM_ERR("bad parameters\n");
1618 		return 0;
1619 	}
1620 	if (pv_printf_s(msg, extra_id_pv, id_str)<0) {
1621 		LM_ERR("cannot print the additional id\n");
1622 		return 0;
1623 	}
1624 
1625 	return 1;
1626 }
1627 
1628 
1629 	static int
unforce_rtp_proxy1_f(struct sip_msg * msg,char * str1,char * str2)1630 unforce_rtp_proxy1_f(struct sip_msg* msg, char* str1, char* str2)
1631 {
1632 	str flags;
1633 
1634 	if (str1) {
1635 		if(get_str_fparam(&flags, msg, (fparam_t *) str1)<0) {
1636 			LM_ERR("failed to get flags parameter\n");
1637 			return -1;
1638 		}
1639 	} else {
1640 		flags.s = NULL;
1641 	}
1642 
1643 	return unforce_rtp_proxy(msg, flags.s);
1644 }
1645 
1646 
1647 	static int
unforce_rtp_proxy(struct sip_msg * msg,char * flags)1648 unforce_rtp_proxy(struct sip_msg* msg, char* flags)
1649 {
1650 	str callid, from_tag, to_tag, viabranch;
1651 	char *cp;
1652 	int via = 0;
1653 	int to = 1;
1654 	int extra = 0;
1655 	str extra_id;
1656 	int ret;
1657 	struct rtpp_node *node;
1658 	struct iovec v[1 + 4 + 3 + 2] = {{NULL, 0}, {"D", 1}, {" ", 1}, {NULL, 0},
1659 			{NULL, 0}, {NULL, 0}, {" ", 1}, {NULL, 0}, {" ", 1}, {NULL, 0}};
1660 	/* 1 */   /* 2 */   /* 3 */    /* 4 */    /* 5 */    /* 6 */   /* 7 */    /* 8 */   /* 9 */
1661 
1662 	if(msg==NULL) {
1663 		LM_ERR("invalid sip message structure\n");
1664 		return -1;
1665 	}
1666 
1667 	for (cp = flags; cp && *cp; cp++) {
1668 		switch (*cp) {
1669 			case '1':
1670 				via = 1;
1671 				break;
1672 
1673 			case '2':
1674 				via = 2;
1675 				break;
1676 
1677 			case '3':
1678 				if(msg->first_line.type == SIP_REPLY)
1679 					via = 2;
1680 				else
1681 					via = 1;
1682 				break;
1683 
1684 			case 't':
1685 			case 'T':
1686 				to = 0;
1687 				break;
1688 			case 'b':
1689 				extra = 1;
1690 				break;
1691 			case 'a':
1692 			case 'A':
1693 			case 'i':
1694 			case 'I':
1695 			case 'e':
1696 			case 'E':
1697 			case 'l':
1698 			case 'L':
1699 			case 'f':
1700 			case 'F':
1701 			case 'r':
1702 			case 'R':
1703 			case 'c':
1704 			case 'C':
1705 			case 'o':
1706 			case 'O':
1707 			case 'x':
1708 			case 'X':
1709 			case 'w':
1710 			case 'W':
1711 			case 'z':
1712 			case 'Z':
1713 				/* ignore them - they can be sent by rtpproxy_manage() */
1714 				break;
1715 
1716 			default:
1717 				LM_ERR("unknown option `%c'\n", *cp);
1718 				return -1;
1719 		}
1720 	}
1721 
1722 	if (get_callid(msg, &callid) == -1 || callid.len == 0) {
1723 		LM_ERR("can't get Call-Id field\n");
1724 		return -1;
1725 	}
1726 	to_tag.s = 0;
1727 	to_tag.len = 0;
1728 	if ((to == 1) && get_to_tag(msg, &to_tag) == -1) {
1729 		LM_ERR("can't get To tag\n");
1730 		return -1;
1731 	}
1732 	if (get_from_tag(msg, &from_tag) == -1 || from_tag.len == 0) {
1733 		LM_ERR("can't get From tag\n");
1734 		return -1;
1735 	}
1736 	if (via) {
1737 		if (via == 1)
1738 			ret = get_via_branch(msg, 1, &viabranch);
1739 		else /* (via == 2) */
1740 			ret = get_via_branch(msg, 2, &viabranch);
1741 		if (ret == -1 || viabranch.len == 0) {
1742 			LM_ERR("can't get Via branch\n");
1743 			return -1;
1744 		}
1745 		v[4].iov_base = ";";
1746 		v[4].iov_len = 1;
1747 		STR2IOVEC(viabranch, v[5]);
1748 	} else
1749 		/* Append extra id to call-id */
1750 		if (extra && extra_id_pv && get_extra_id(msg, &extra_id)) {
1751 			v[4].iov_base = ";";
1752 			v[4].iov_len = 1;
1753 			STR2IOVEC(extra_id, v[5]);
1754 		}
1755 	STR2IOVEC(callid, v[3]);
1756 	STR2IOVEC(from_tag, v[7]);
1757 	STR2IOVEC(to_tag, v[9]);
1758 
1759 	if(msg->id != current_msg_id){
1760 		selected_rtpp_set = default_rtpp_set;
1761 	}
1762 
1763 	node = select_rtpp_node(callid, 1);
1764 	if (!node) {
1765 		LM_ERR("no available proxies\n");
1766 		return -1;
1767 	}
1768 	set_rtp_inst_pvar(msg, &node->rn_url);
1769 	send_rtpp_command(node, v, (to_tag.len > 0) ? 10 : 8);
1770 
1771 	return 1;
1772 }
1773 
1774 /* This function assumes p points to a line of requested type. */
1775 
1776 	static int
set_rtp_proxy_set_f(struct sip_msg * msg,char * str1,char * str2)1777 set_rtp_proxy_set_f(struct sip_msg * msg, char * str1, char * str2)
1778 {
1779 	rtpp_set_link_t *rtpl;
1780 	pv_value_t val;
1781 
1782 	rtpl = (rtpp_set_link_t*)str1;
1783 
1784 	current_msg_id = 0;
1785 	selected_rtpp_set = 0;
1786 
1787 	if(rtpl->rset != NULL) {
1788 		current_msg_id = msg->id;
1789 		selected_rtpp_set = rtpl->rset;
1790 	} else {
1791 		if(pv_get_spec_value(msg, rtpl->rpv, &val)<0) {
1792 			LM_ERR("cannot evaluate pv param\n");
1793 			return -1;
1794 		}
1795 		if(!(val.flags & PV_VAL_INT)) {
1796 			LM_ERR("pv param must hold an integer value\n");
1797 			return -1;
1798 		}
1799 		selected_rtpp_set = select_rtpp_set(val.ri);
1800 		if(selected_rtpp_set==NULL) {
1801 			LM_ERR("could not locate rtpproxy set %d\n", val.ri);
1802 			return -1;
1803 		}
1804 		current_msg_id = msg->id;
1805 	}
1806 	return 1;
1807 }
1808 
1809 	static int
rtpproxy_manage(struct sip_msg * msg,char * flags,char * ip)1810 rtpproxy_manage(struct sip_msg *msg, char *flags, char *ip)
1811 {
1812 	char *cp = NULL;
1813 	char newip[IP_ADDR_MAX_STR_SIZE];
1814 	int method;
1815 	int nosdp;
1816 
1817 	if(route_type==BRANCH_FAILURE_ROUTE) {
1818 		/* do nothing in branch failure event route
1819 		 * - delete done on transaction failure route */
1820 		return 1;
1821 	}
1822 
1823 	if(msg->cseq==NULL && ((parse_headers(msg, HDR_CSEQ_F, 0)==-1)
1824 				|| (msg->cseq==NULL))) {
1825 		LM_ERR("no CSEQ header\n");
1826 		return -1;
1827 	}
1828 
1829 	method = get_cseq(msg)->method_id;
1830 
1831 	if(!(method==METHOD_INVITE || method==METHOD_ACK || method==METHOD_CANCEL
1832 				|| method==METHOD_BYE || method==METHOD_UPDATE
1833 				|| method==METHOD_PRACK))
1834 		return -1;
1835 
1836 	if(method==METHOD_CANCEL || method==METHOD_BYE)
1837 		return unforce_rtp_proxy(msg, flags);
1838 
1839 	if(ip==NULL) {
1840 		cp = ip_addr2a(&msg->rcv.dst_ip);
1841 		strcpy(newip, cp);
1842 	}
1843 
1844 	if(msg->msg_flags & FL_SDP_BODY)
1845 		nosdp = 0;
1846 	else
1847 		nosdp = parse_sdp(msg);
1848 
1849 	if(msg->first_line.type == SIP_REQUEST) {
1850 		if(method==METHOD_ACK && nosdp==0)
1851 			return force_rtp_proxy(msg, flags, (cp!=NULL)?newip:ip, 0,
1852 					(ip!=NULL)?1:0);
1853 		if(method==METHOD_PRACK && nosdp==0)
1854 			return force_rtp_proxy(msg, flags, (cp!=NULL)?newip:ip, 1,
1855 					(ip!=NULL)?1:0);
1856 		if(method==METHOD_UPDATE && nosdp==0)
1857 			return force_rtp_proxy(msg, flags, (cp!=NULL)?newip:ip, 1,
1858 					(ip!=NULL)?1:0);
1859 		if(method==METHOD_INVITE && nosdp==0) {
1860 			msg->msg_flags |= FL_SDP_BODY;
1861 			if(tmb.t_gett!=NULL && tmb.t_gett()!=NULL
1862 					&& tmb.t_gett()!=T_UNDEFINED)
1863 				tmb.t_gett()->uas.request->msg_flags |= FL_SDP_BODY;
1864 			if(route_type==FAILURE_ROUTE)
1865 				return unforce_rtp_proxy(msg, flags);
1866 			return force_rtp_proxy(msg, flags, (cp!=NULL)?newip:ip, 1,
1867 					(ip!=NULL)?1:0);
1868 		}
1869 	} else if(msg->first_line.type == SIP_REPLY) {
1870 		if(msg->first_line.u.reply.statuscode>=300)
1871 			return unforce_rtp_proxy(msg, flags);
1872 		if(nosdp==0) {
1873 			if(method==METHOD_PRACK)
1874 				return force_rtp_proxy(msg, flags, (cp!=NULL)?newip:ip, 0,
1875 						(ip!=NULL)?1:0);
1876 			if(method==METHOD_UPDATE)
1877 				return force_rtp_proxy(msg, flags, (cp!=NULL)?newip:ip, 0,
1878 						(ip!=NULL)?1:0);
1879 			if(tmb.t_gett==NULL || tmb.t_gett()==NULL
1880 					|| tmb.t_gett()==T_UNDEFINED)
1881 				return force_rtp_proxy(msg, flags, (cp!=NULL)?newip:ip, 0,
1882 						(ip!=NULL)?1:0);
1883 			if(tmb.t_gett()->uas.request->msg_flags & FL_SDP_BODY)
1884 				return force_rtp_proxy(msg, flags, (cp!=NULL)?newip:ip, 0,
1885 						(ip!=NULL)?1:0);
1886 			return force_rtp_proxy(msg, flags, (cp!=NULL)?newip:ip, 1,
1887 					(ip!=NULL)?1:0);
1888 		}
1889 	}
1890 	return -1;
1891 }
1892 
1893 	static int
rtpproxy_manage0(struct sip_msg * msg,char * flags,char * ip)1894 rtpproxy_manage0(struct sip_msg *msg, char *flags, char *ip)
1895 {
1896 	return rtpproxy_manage(msg, 0, 0);
1897 }
1898 
1899 	static int
rtpproxy_manage1(struct sip_msg * msg,char * flags,char * ip)1900 rtpproxy_manage1(struct sip_msg *msg, char *flags, char *ip)
1901 {
1902 	str flag_str;
1903 	if(fixup_get_svalue(msg, (gparam_p)flags, &flag_str)<0)
1904 	{
1905 		LM_ERR("invalid flags parameter\n");
1906 		return -1;
1907 	}
1908 	return rtpproxy_manage(msg, flag_str.s, 0);
1909 }
1910 
1911 	static int
rtpproxy_manage2(struct sip_msg * msg,char * flags,char * ip)1912 rtpproxy_manage2(struct sip_msg *msg, char *flags, char *ip)
1913 {
1914 	str flag_str;
1915 	str ip_str;
1916 	if(fixup_get_svalue(msg, (gparam_p)flags, &flag_str)<0)
1917 	{
1918 		LM_ERR("invalid flags parameter\n");
1919 		return -1;
1920 	}
1921 	if(fixup_get_svalue(msg, (gparam_p)ip, &ip_str)<0)
1922 	{
1923 		LM_ERR("invalid IP parameter\n");
1924 		return -1;
1925 	}
1926 	return rtpproxy_manage(msg, flag_str.s, ip_str.s);
1927 }
1928 
1929 	static int
rtpproxy_offer1_helper_f(struct sip_msg * msg,char * flags)1930 rtpproxy_offer1_helper_f(struct sip_msg *msg, char *flags)
1931 {
1932 	char *cp;
1933 	char newip[IP_ADDR_MAX_STR_SIZE];
1934 
1935 	cp = ip_addr2a(&msg->rcv.dst_ip);
1936 	strcpy(newip, cp);
1937 
1938 	return force_rtp_proxy(msg, flags, newip, 1, 0);
1939 }
1940 
1941 	static int
rtpproxy_offer1_f(struct sip_msg * msg,char * str1,char * str2)1942 rtpproxy_offer1_f(struct sip_msg *msg, char *str1, char *str2)
1943 {
1944 	str flags;
1945 
1946 	if (str1) {
1947 		if(get_str_fparam(&flags, msg, (fparam_t *) str1)<0) {
1948 			LM_ERR("failed to get flags parameter\n");
1949 			return -1;
1950 		}
1951 	} else {
1952 		flags.s = NULL;
1953 	}
1954 
1955 	return rtpproxy_offer1_helper_f(msg, flags.s);
1956 }
1957 
1958 	static int
rtpproxy_offer2_f(struct sip_msg * msg,char * param1,char * param2)1959 rtpproxy_offer2_f(struct sip_msg *msg, char *param1, char *param2)
1960 {
1961 	str flags, new_ip;
1962 
1963 	if(get_str_fparam(&flags, msg, (fparam_t *) param1)<0) {
1964 		LM_ERR("failed to get flags parameter\n");
1965 		return -1;
1966 	}
1967 	if(get_str_fparam(&new_ip, msg, (fparam_t *) param2)<0) {
1968 		LM_ERR("failed to get new ip parameter\n");
1969 		return -1;
1970 	}
1971 	return force_rtp_proxy(msg, flags.s, new_ip.s, 1, 1);
1972 }
1973 
1974 	static int
rtpproxy_answer1_helper_f(struct sip_msg * msg,char * flags)1975 rtpproxy_answer1_helper_f(struct sip_msg *msg, char *flags)
1976 {
1977 	char *cp;
1978 	char newip[IP_ADDR_MAX_STR_SIZE];
1979 
1980 	if (msg->first_line.type == SIP_REQUEST)
1981 		if (msg->first_line.u.request.method_value != METHOD_ACK)
1982 			return -1;
1983 
1984 	cp = ip_addr2a(&msg->rcv.dst_ip);
1985 	strcpy(newip, cp);
1986 
1987 	return force_rtp_proxy(msg, flags, newip, 0, 0);
1988 }
1989 
1990 	static int
rtpproxy_answer1_f(struct sip_msg * msg,char * str1,char * str2)1991 rtpproxy_answer1_f(struct sip_msg *msg, char *str1, char *str2)
1992 {
1993 	str flags;
1994 
1995 	if (str1) {
1996 		if(get_str_fparam(&flags, msg, (fparam_t *) str1)<0) {
1997 			LM_ERR("failed to get flags parameter\n");
1998 			return -1;
1999 		}
2000 	} else {
2001 		flags.s = NULL;
2002 	}
2003 
2004 	return rtpproxy_answer1_helper_f(msg, flags.s);
2005 }
2006 
2007 	static int
rtpproxy_answer2_f(struct sip_msg * msg,char * param1,char * param2)2008 rtpproxy_answer2_f(struct sip_msg *msg, char *param1, char *param2)
2009 {
2010 
2011 	str flags, new_ip;
2012 
2013 	if (msg->first_line.type == SIP_REQUEST)
2014 		if (msg->first_line.u.request.method_value != METHOD_ACK)
2015 			return -1;
2016 
2017 	if(get_str_fparam(&flags, msg, (fparam_t *) param1)<0) {
2018 		LM_ERR("failed to get flags parameter\n");
2019 		return -1;
2020 	}
2021 	if(get_str_fparam(&new_ip, msg, (fparam_t *) param2)<0) {
2022 		LM_ERR("failed to get new ip parameter\n");
2023 		return -1;
2024 	}
2025 	return force_rtp_proxy(msg, flags.s, new_ip.s, 0, 1);
2026 }
2027 
2028 
2029 struct options {
2030 	str s;
2031 	int oidx;
2032 };
2033 
2034 	static int
append_opts(struct options * op,char ch)2035 append_opts(struct options *op, char ch)
2036 {
2037 	void *p;
2038 
2039 	if (op->s.len <= op->oidx) {
2040 		p = pkg_realloc(op->s.s, op->oidx + 32);
2041 		if (p == NULL) {
2042 			return (-1);
2043 		}
2044 		op->s.s = p;
2045 		op->s.len = op->oidx + 32;
2046 	}
2047 	op->s.s[op->oidx++] = ch;
2048 	return (0);
2049 }
2050 
2051 	static void
free_opts(struct options * op1,struct options * op2,struct options * op3)2052 free_opts(struct options *op1, struct options *op2, struct options *op3)
2053 {
2054 
2055 	if (op1->s.len > 0 && op1->s.s != NULL) {
2056 		pkg_free(op1->s.s);
2057 		op1->s.len = 0;
2058 	}
2059 	if (op2->s.len > 0 && op2->s.s != NULL) {
2060 		pkg_free(op2->s.s);
2061 		op2->s.len = 0;
2062 	}
2063 	if (op3->s.len > 0 && op3->s.s != NULL) {
2064 		pkg_free(op3->s.s);
2065 		op3->s.len = 0;
2066 	}
2067 }
2068 
2069 #define FORCE_RTP_PROXY_RET(e) \
2070 	do { \
2071 		free_opts(&opts, &rep_opts, &pt_opts); \
2072 		return (e); \
2073 	} while (0);
2074 
2075 struct new_mediaip {
2076 	str strip;
2077 	int pf;
2078 };
2079 
2080 	static int
force_rtp_proxy(struct sip_msg * msg,char * str1,char * str2,int offer,int forcedIP)2081 force_rtp_proxy(struct sip_msg* msg, char* str1, char* str2, int offer,
2082 		int forcedIP)
2083 {
2084 	str body, body1, oldport, oldip, newport;
2085 	struct new_mediaip newip;
2086 	str callid, from_tag, to_tag, tmp, payload_types;
2087 	str newrtcp = {0, 0};
2088 	str viabranch;
2089 	int create, port, len, flookup, argc, proxied, real, via, ret;
2090 	int orgip, commip;
2091 	int pf, force;
2092 	struct options opts, rep_opts, pt_opts;
2093 	char *cp, *cp1;
2094 	char  *cpend, *next;
2095 	char **ap, *argv[10];
2096 	struct lump* anchor;
2097 	struct rtpp_node *node;
2098 	struct iovec v[] = {
2099 		{NULL, 0},	/* reserved (cookie) */
2100 		{NULL, 0},	/* command & common options */
2101 		{NULL, 0},	/* per-media/per-node options 1 */
2102 		{NULL, 0},	/* per-media/per-node options 2 */
2103 		{" ", 1},	/* separator */
2104 		{NULL, 0},	/* callid */
2105 		{NULL, 0},	/* via-branch separator ";" */
2106 		{NULL, 0},	/* via-branch */
2107 		{" ", 1},	/* separator */
2108 		{NULL, 7},	/* newip */
2109 		{" ", 1},	/* separator */
2110 		{NULL, 1},	/* oldport */
2111 		{" ", 1},	/* separator */
2112 		{NULL, 0},	/* from_tag */
2113 		{";", 1},	/* separator */
2114 		{NULL, 0},	/* medianum */
2115 		{" ", 1},	/* separator */
2116 		{NULL, 0},	/* to_tag */
2117 		{";", 1},	/* separator */
2118 		{NULL, 0},	/* medianum */
2119 		{" ", 1},	/* separator */
2120 		{NULL, 0},	/* Timeout-Socket */
2121 	};
2122 	int iovec_param_count;
2123 	int autobridge_ipv4v6;
2124 	int extra;
2125 	str extra_id;
2126 
2127 	char *c1p, *c2p, *bodylimit, *o1p;
2128 	char itoabuf_buf[20];
2129 	int medianum, media_multi;
2130 	str itoabuf_str;
2131 	int c1p_altered;
2132 
2133 	int sdp_session_num, sdp_stream_num;
2134 	sdp_session_cell_t* sdp_session;
2135 	sdp_stream_cell_t* sdp_stream;
2136 
2137 	if(msg==NULL) {
2138 		LM_ERR("invalid sip message structure\n");
2139 		return -1;
2140 	}
2141 
2142 	int_str ice_candidate_priority_val;
2143 
2144 	memset(&opts, '\0', sizeof(opts));
2145 	memset(&rep_opts, '\0', sizeof(rep_opts));
2146 	memset(&pt_opts, '\0', sizeof(pt_opts));
2147 	/* Leave space for U/L prefix TBD later */
2148 	if (append_opts(&opts, '?') == -1) {
2149 		LM_ERR("out of pkg memory\n");
2150 		FORCE_RTP_PROXY_RET (-1);
2151 	}
2152 	flookup = force = real = orgip = commip = via = autobridge_ipv4v6 = extra = 0;
2153 	for (cp = str1; cp != NULL && *cp != '\0'; cp++) {
2154 		switch (*cp) {
2155 			case '1':
2156 				via = 1;
2157 				break;
2158 
2159 			case '2':
2160 				via = 2;
2161 				break;
2162 
2163 			case '3':
2164 				if(msg->first_line.type == SIP_REPLY)
2165 					via = 2;
2166 				else
2167 					via = 1;
2168 				break;
2169 
2170 			case 'a':
2171 			case 'A':
2172 				if (append_opts(&opts, 'A') == -1) {
2173 					LM_ERR("out of pkg memory\n");
2174 					FORCE_RTP_PROXY_RET (-1);
2175 				}
2176 				real = 1;
2177 				break;
2178 
2179 			case 'b':
2180 				extra = 1;
2181 				break;
2182 
2183 			case 'i':
2184 			case 'I':
2185 				if (append_opts(&opts, 'I') == -1) {
2186 					LM_ERR("out of pkg memory\n");
2187 					FORCE_RTP_PROXY_RET (-1);
2188 				}
2189 				break;
2190 
2191 			case 'e':
2192 			case 'E':
2193 				if (append_opts(&opts, 'E') == -1) {
2194 					LM_ERR("out of pkg memory\n");
2195 					FORCE_RTP_PROXY_RET (-1);
2196 				}
2197 				break;
2198 
2199 			case 'l':
2200 			case 'L':
2201 				if (offer == 0) {
2202 					FORCE_RTP_PROXY_RET (-1);
2203 				}
2204 				flookup = 1;
2205 				break;
2206 
2207 			case 'f':
2208 			case 'F':
2209 				force = 1;
2210 				break;
2211 
2212 			case 'r':
2213 			case 'R':
2214 				real = 1;
2215 				break;
2216 
2217 			case 'c':
2218 			case 'C':
2219 				commip = 1;
2220 				break;
2221 
2222 			case 'o':
2223 			case 'O':
2224 				orgip = 1;
2225 				break;
2226 
2227 			case 'x':
2228 			case 'X':
2229 				autobridge_ipv4v6 = 1;
2230 				break;
2231 
2232 			case 'w':
2233 			case 'W':
2234 				if (append_opts(&opts, 'S') == -1) {
2235 					LM_ERR("out of pkg memory\n");
2236 					FORCE_RTP_PROXY_RET (-1);
2237 				}
2238 				break;
2239 
2240 			case 'z':
2241 			case 'Z':
2242 				if (append_opts(&rep_opts, 'Z') == -1) {
2243 					LM_ERR("out of pkg memory\n");
2244 					FORCE_RTP_PROXY_RET (-1);
2245 				}
2246 				/* If there are any digits following Z copy them into the command */
2247 				for (; cp[1] != '\0' && isdigit(cp[1]); cp++) {
2248 					if (append_opts(&rep_opts, cp[1]) == -1) {
2249 						LM_ERR("out of pkg memory\n");
2250 						FORCE_RTP_PROXY_RET (-1);
2251 					}
2252 				}
2253 				break;
2254 
2255 			case 't':
2256 			case 'T':
2257 				/* Only used in rtpproxy_destroy */
2258 				break;
2259 
2260 			default:
2261 				LM_ERR("unknown option `%c'\n", *cp);
2262 				FORCE_RTP_PROXY_RET (-1);
2263 		}
2264 	}
2265 
2266 	if (offer != 0) {
2267 		create = 1;
2268 	} else {
2269 		create = 0;
2270 	}
2271 	/* extract_body will also parse all the headers in the message as
2272 	 * a side effect => don't move get_callid/get_to_tag in front of it
2273 	 * -- andrei */
2274 	if (extract_body(msg, &body) == -1) {
2275 		LM_ERR("can't extract body from the message\n");
2276 		FORCE_RTP_PROXY_RET (-1);
2277 	}
2278 	if (get_callid(msg, &callid) == -1 || callid.len == 0) {
2279 		LM_ERR("can't get Call-Id field\n");
2280 		FORCE_RTP_PROXY_RET (-1);
2281 	}
2282 	to_tag.s = 0;
2283 	if (get_to_tag(msg, &to_tag) == -1) {
2284 		LM_ERR("can't get To tag\n");
2285 		FORCE_RTP_PROXY_RET (-1);
2286 	}
2287 	if (get_from_tag(msg, &from_tag) == -1 || from_tag.len == 0) {
2288 		LM_ERR("can't get From tag\n");
2289 		FORCE_RTP_PROXY_RET (-1);
2290 	}
2291 	if (via) {
2292 		if (via == 1)
2293 			ret = get_via_branch(msg, 1, &viabranch);
2294 		else /* (via == 2) */
2295 			ret = get_via_branch(msg, 2, &viabranch);
2296 		if (ret == -1 || viabranch.len == 0) {
2297 			LM_ERR("can't get Via branch\n");
2298 			FORCE_RTP_PROXY_RET (-1);
2299 		}
2300 		v[6].iov_base = ";";
2301 		v[6].iov_len = 1;
2302 		STR2IOVEC(viabranch, v[7]);
2303 	} else
2304 		/* Append extra id to call-id */
2305 		if (extra && extra_id_pv && get_extra_id(msg, &extra_id)) {
2306 			v[6].iov_base = ";";
2307 			v[6].iov_len = 1;
2308 			STR2IOVEC(extra_id, v[7]);
2309 		}
2310 	if (flookup != 0) {
2311 		if (to_tag.len == 0) {
2312 			FORCE_RTP_PROXY_RET (-1);
2313 		}
2314 		if (msg->first_line.type == SIP_REQUEST) {
2315 			tmp = from_tag;
2316 			from_tag = to_tag;
2317 			to_tag = tmp;
2318 		}
2319 		create = 0;
2320 	} else if ((msg->first_line.type == SIP_REPLY && offer != 0)
2321 			|| (msg->first_line.type == SIP_REQUEST && offer == 0)) {
2322 		if (to_tag.len == 0) {
2323 			FORCE_RTP_PROXY_RET (-1);
2324 		}
2325 		tmp = from_tag;
2326 		from_tag = to_tag;
2327 		to_tag = tmp;
2328 	}
2329 	proxied = 0;
2330 	if (nortpproxy_str.len) {
2331 		for ( cp=body.s ; (len=body.s+body.len-cp) >= nortpproxy_str.len ; ) {
2332 			cp1 = ser_memmem(cp, nortpproxy_str.s, len, nortpproxy_str.len);
2333 			if (cp1 == NULL)
2334 				break;
2335 			if (cp1[-1] == '\n' || cp1[-1] == '\r') {
2336 				proxied = 1;
2337 				break;
2338 			}
2339 			cp = cp1 + nortpproxy_str.len;
2340 		}
2341 	}
2342 	if (proxied != 0 && force == 0) {
2343 		FORCE_RTP_PROXY_RET (-2);
2344 	}
2345 	/*
2346 	 * Parsing of SDP body.
2347 	 * It can contain a few session descriptions (each starts with
2348 	 * v-line), and each session may contain a few media descriptions
2349 	 * (each starts with m-line).
2350 	 * We have to change ports in m-lines, and also change IP addresses in
2351 	 * c-lines which can be placed either in session header (fallback for
2352 	 * all medias) or media description.
2353 	 * Ports should be allocated for any media. IPs all should be changed
2354 	 * to the same value (RTP proxy IP), so we can change all c-lines
2355 	 * unconditionally.
2356 	 */
2357 	if(0 != parse_sdp(msg)) {
2358 		LM_ERR("Unable to parse sdp\n");
2359 		FORCE_RTP_PROXY_RET (-1);
2360 	}
2361 #ifdef EXTRA_DEBUG
2362 	print_sdp((sdp_info_t*)msg->body, L_DBG);
2363 #endif
2364 
2365 	bodylimit = body.s + body.len;
2366 
2367 	if(msg->id != current_msg_id){
2368 		selected_rtpp_set = default_rtpp_set;
2369 	}
2370 
2371 	opts.s.s[0] = (create == 0) ? 'L' : 'U';
2372 	v[1].iov_base = opts.s.s;
2373 	v[1].iov_len = opts.oidx;
2374 	STR2IOVEC(callid, v[5]);
2375 	STR2IOVEC(from_tag, v[13]);
2376 	STR2IOVEC(to_tag, v[17]);
2377 
2378 	if (ice_candidate_priority_avp_param) {
2379 		if (search_first_avp(ice_candidate_priority_avp_type,
2380 					ice_candidate_priority_avp,
2381 					&ice_candidate_priority_val, 0)
2382 				== NULL) {
2383 			ice_candidate_priority_val.n = 2;
2384 		} else if ((ice_candidate_priority_val.n < 0) ||
2385 				(ice_candidate_priority_val.n > 2)) {
2386 			LM_ERR("invalid ice candidate priority value %d\n",
2387 					ice_candidate_priority_val.n);
2388 			FORCE_RTP_PROXY_RET (-1);
2389 		}
2390 	} else {
2391 		ice_candidate_priority_val.n = 0;
2392 	}
2393 
2394 	/* check if this is a single or a multi stream SDP offer/answer */
2395 	sdp_stream_num = get_sdp_stream_num(msg);
2396 	switch (sdp_stream_num) {
2397 		case 0:
2398 			LM_ERR("sdp w/o streams\n");
2399 			FORCE_RTP_PROXY_RET (-1);
2400 			break;
2401 		case 1:
2402 			media_multi = 0;
2403 			break;
2404 		default:
2405 			media_multi = 1;
2406 	}
2407 #ifdef EXTRA_DEBUG
2408 	LM_DBG("my new media_multi=%d\n", media_multi);
2409 #endif
2410 	medianum = 0;
2411 	sdp_session_num = 0;
2412 	for(;;) {
2413 		sdp_session = get_sdp_session(msg, sdp_session_num);
2414 		if(!sdp_session) break;
2415 		sdp_stream_num = 0;
2416 		c1p_altered = 0;
2417 		o1p = sdp_session->o_ip_addr.s;
2418 		for(;;) {
2419 			sdp_stream = get_sdp_stream(msg, sdp_session_num, sdp_stream_num);
2420 			if (!sdp_stream ||
2421 					(ice_candidate_priority_val.n
2422 						&& sdp_stream->remote_candidates.len)) break;
2423 
2424 			if (sdp_stream->ip_addr.s && sdp_stream->ip_addr.len>0) {
2425 				oldip = sdp_stream->ip_addr;
2426 				pf = sdp_stream->pf;
2427 			} else {
2428 				oldip = sdp_session->ip_addr;
2429 				pf = sdp_session->pf;
2430 			}
2431 			oldport = sdp_stream->port;
2432 			payload_types = sdp_stream->payloads;
2433 			medianum++;
2434 
2435 			if (real != 0) {
2436 				newip.strip = oldip;
2437 				newip.pf = pf;
2438 			} else {
2439 				newip.strip.s = ip_addr2a(&msg->rcv.src_ip);
2440 				newip.strip.len = strlen(newip.strip.s);
2441 				newip.pf = msg->rcv.src_ip.af;
2442 			}
2443 			/* XXX must compare address families in all addresses */
2444 			if (pf == AF_INET6) {
2445 				if (autobridge_ipv4v6 != 0) {
2446 					if ((append_opts(&opts, 'E') == -1)
2447 							|| (append_opts(&opts, 'I') == -1))  {
2448 						LM_ERR("out of pkg memory\n");
2449 						FORCE_RTP_PROXY_RET (-1);
2450 					}
2451 					/* Only execute once */
2452 					autobridge_ipv4v6 = 0;
2453 				}
2454 				if (append_opts(&opts, '6') == -1) {
2455 					LM_ERR("out of pkg memory\n");
2456 					FORCE_RTP_PROXY_RET (-1);
2457 				}
2458 				/* We need to update the pointers and the length here, it has changed. */
2459 				v[1].iov_base = opts.s.s;
2460 				v[1].iov_len = opts.oidx;
2461 			} else {
2462 				if (autobridge_ipv4v6 != 0) {
2463 					if ((append_opts(&opts, 'I') == -1)
2464 							|| (append_opts(&opts, 'E') == -1))  {
2465 						LM_ERR("out of pkg memory\n");
2466 						FORCE_RTP_PROXY_RET (-1);
2467 					}
2468 					/* We need to update the pointers and the length here, it has changed. */
2469 					v[1].iov_base = opts.s.s;
2470 					v[1].iov_len = opts.oidx;
2471 					/* Only execute once */
2472 					autobridge_ipv4v6 = 0;
2473 				}
2474 			}
2475 
2476 			STR2IOVEC(newip.strip, v[9]);
2477 			STR2IOVEC(oldport, v[11]);
2478 #ifdef EXTRA_DEBUG
2479 			LM_DBG("STR2IOVEC(newip[%.*s], v[9])", newip.strip.len, newip.strip.s);
2480 			LM_DBG("STR2IOVEC(oldport[%.*s], v[11])", oldport.len, oldport.s);
2481 #endif
2482 			if (1 || media_multi) /* XXX netch: can't choose now*/
2483 			{
2484 				snprintf(itoabuf_buf, sizeof itoabuf_buf, "%d", medianum);
2485 				itoabuf_str.s = itoabuf_buf;
2486 				itoabuf_str.len = strlen(itoabuf_buf);
2487 				STR2IOVEC(itoabuf_str, v[15]);
2488 				STR2IOVEC(itoabuf_str, v[19]);
2489 #ifdef EXTRA_DEBUG
2490 				LM_DBG("STR2IOVEC(itoabuf_str, v[15])\n");
2491 				LM_DBG("STR2IOVEC(itoabuf_str, v[19])\n");
2492 #endif
2493 			} else {
2494 				v[14].iov_len = v[15].iov_len = 0;
2495 				v[18].iov_len = v[19].iov_len = 0;
2496 			}
2497 			do {
2498 				node = select_rtpp_node(callid, 1);
2499 				if (!node) {
2500 					LM_ERR("no available proxies\n");
2501 					FORCE_RTP_PROXY_RET (-3);
2502 				}
2503 				set_rtp_inst_pvar(msg, &node->rn_url);
2504 				if (rep_opts.oidx > 0) {
2505 					if (node->rn_rep_supported == 0) {
2506 						LM_WARN("re-packetization is requested but is not "
2507 								"supported by the selected RTP proxy node\n");
2508 						v[2].iov_len = 0;
2509 					} else {
2510 						v[2].iov_base = rep_opts.s.s;
2511 						v[2].iov_len += rep_opts.oidx;
2512 					}
2513 				}
2514 #ifdef EXTRA_DEBUG
2515 				LM_DBG("payload_types='%.*s'\n", payload_types.len,
2516 						payload_types.s);
2517 #endif
2518 				if (sdp_stream->is_rtp && payload_types.len > 0
2519 						&& node->rn_ptl_supported != 0) {
2520 					pt_opts.oidx = 0;
2521 					if (append_opts(&pt_opts, 'c') == -1) {
2522 						LM_ERR("out of pkg memory\n");
2523 						FORCE_RTP_PROXY_RET (-1);
2524 					}
2525 					/*
2526 					 * Convert space-separated payload types list into
2527 					 * a comma-separated list.
2528 					 */
2529 					for (cp = payload_types.s;
2530 							cp < payload_types.s + payload_types.len; cp++) {
2531 						if (isdigit(*cp)) {
2532 							if (append_opts(&pt_opts, *cp) == -1) {
2533 								LM_ERR("out of pkg memory\n");
2534 								FORCE_RTP_PROXY_RET (-1);
2535 							}
2536 							continue;
2537 						}
2538 						do {
2539 							cp++;
2540 						} while (!isdigit(*cp) &&
2541 								cp < payload_types.s + payload_types.len);
2542 						/* Check EOL */
2543 						if (cp >= payload_types.s + payload_types.len)
2544 							break;
2545 						if (append_opts(&pt_opts, ',') == -1) {
2546 							LM_ERR("out of pkg memory\n");
2547 							FORCE_RTP_PROXY_RET (-1);
2548 						}
2549 						cp--;
2550 					}
2551 					v[3].iov_base = pt_opts.s.s;
2552 					v[3].iov_len = pt_opts.oidx;
2553 				} else {
2554 					v[3].iov_len = 0;
2555 				}
2556 				if (to_tag.len > 0) {
2557 					iovec_param_count = 20;
2558 					if (opts.s.s[0] == 'U' && timeout_socket_str.len > 0) {
2559 						iovec_param_count = 22;
2560 						STR2IOVEC(timeout_socket_str, v[21]);
2561 					}
2562 				} else {
2563 					iovec_param_count = 16;
2564 				}
2565 
2566 				cp = send_rtpp_command(node, v, iovec_param_count);
2567 			} while (cp == NULL);
2568 			LM_DBG("proxy reply: %s\n", cp);
2569 			/* Parse proxy reply to <argc,argv> */
2570 			argc = 0;
2571 			memset(argv, 0, sizeof(argv));
2572 			cpend=cp+strlen(cp);
2573 			next=eat_token_end(cp, cpend);
2574 			for (ap=argv; cp<cpend; cp=next+1, next=eat_token_end(cp, cpend)){
2575 				*next=0;
2576 				if (*cp != '\0') {
2577 					*ap=cp;
2578 					argc++;
2579 					if ((char*)++ap >= ((char*)argv+sizeof(argv)))
2580 						break;
2581 				}
2582 			}
2583 			if (argc < 1) {
2584 				LM_ERR("no reply from rtp proxy\n");
2585 				FORCE_RTP_PROXY_RET (-1);
2586 			}
2587 			port = atoi(argv[0]);
2588 			if (port <= 0 || port > 65535) {
2589 				if (port != 0 || flookup == 0)
2590 					LM_ERR("incorrect port %i in reply "
2591 							"from rtp proxy\n",port);
2592 				FORCE_RTP_PROXY_RET (-1);
2593 			}
2594 
2595 			/*
2596 			 * if (argc == 1) {
2597 			 *      Assume AF in reply stays the same as one in
2598 			 *      the original request.
2599 			 * }
2600 			 */
2601 			if (argc == 2) {
2602 				/*
2603 				 * For historical reasons, if rtpproxy returns
2604 				 * bare address without AF flag, this means
2605 				 * IPv4.
2606 				 */
2607 				newip.pf = AF_INET;
2608 			} else if (argc >= 3) {
2609 				/*
2610 				 * When rtpproxy returns explicit address +
2611 				 * "AF" flag, use that.
2612 				 */
2613 				newip.pf = (argv[2][0] == '6') ? AF_INET6 : AF_INET;
2614 			}
2615 
2616 			if (isnulladdr(&oldip, pf)) {
2617 				if (newip.pf == AF_INET6) {
2618 					newip.strip.s = "::";
2619 					newip.strip.len = 2;
2620 				} else {
2621 					newip.strip.s = "0.0.0.0";
2622 					newip.strip.len = 7;
2623 				}
2624 			} else {
2625 				if (forcedIP) {
2626 					newip.strip.s = str2;
2627 					newip.strip.len = strlen(newip.strip.s);
2628 #ifdef EXTRA_DEBUG
2629 					LM_DBG("forcing IP='%.*s'\n", newip.strip.len,
2630 							newip.strip.s);
2631 #endif
2632 				} else {
2633 					newip.strip.s = (argc < 2) ? str2 : argv[1];
2634 					newip.strip.len = strlen(newip.strip.s);
2635 				}
2636 			}
2637 			/* marker to double check : newport goes: str -> int -> str ?!?! */
2638 			newport.s = int2str(port, &newport.len); /* beware static buffer */
2639 			/* Alter port. */
2640 			body1.s = sdp_stream->media.s;
2641 			body1.len = bodylimit - body1.s;
2642 #ifdef EXTRA_DEBUG
2643 			LM_DBG("alter port body1='%.*s'\n", body1.len, body1.s);
2644 #endif
2645 			/* do not do it if old port was 0 (means media disable)
2646 			 * - check if actually should be better done in rtpproxy,
2647 			 *   by returning also 0
2648 			 * - or by not sending to rtpproxy the old port if 0
2649 			 */
2650 			if(oldport.len!=1 || oldport.s[0]!='0')
2651 			{
2652 				if (alter_mediaport(msg, &body1, &oldport, &newport, 0) == -1) {
2653 					FORCE_RTP_PROXY_RET (-1);
2654 				}
2655 			}
2656 
2657 			/*
2658 			 * Alter RTCP attribute if present. Inserting RTP port + 1 (as allocated
2659 			 * by RTP proxy). No IP-address is needed in the new RTCP attribute as the
2660 			 * 'c' attribute (altered below) will contain the RTP proxy IP address.
2661 			 * See RFC 3605 for definition of RTCP attribute.
2662 			 * ported from ser
2663 			 */
2664 
2665 			if (sdp_stream->rtcp_port.s && sdp_stream->rtcp_port.len) {
2666 				newrtcp.s = int2str(port+1, &newrtcp.len); /* beware static buffer */
2667 				/* Alter port. */
2668 				body1.s = sdp_stream->rtcp_port.s;
2669 				body1.len = bodylimit - body1.s;
2670 #ifdef EXTRA_DEBUG
2671 				LM_DBG("alter rtcp body1='%.*s'\n", body1.len, body1.s);
2672 #endif
2673 				if (alter_rtcp(msg, &body1, &sdp_stream->rtcp_port, &newrtcp) == -1) {
2674 					FORCE_RTP_PROXY_RET (-1);
2675 				}
2676 			}
2677 
2678 			/* Add ice relay candidates */
2679 			if (ice_candidate_priority_val.n && sdp_stream->ice_attrs_num > 0) {
2680 				body1.s = sdp_stream->ice_attr->foundation.s - 12;
2681 				body1.len = bodylimit - body1.s;
2682 				if (insert_candidates(msg, sdp_stream->ice_attr->foundation.s - 12,
2683 							&newip.strip, port, ice_candidate_priority_val.n) == -1) {
2684 					FORCE_RTP_PROXY_RET (-1);
2685 				}
2686 			}
2687 
2688 			c1p = sdp_session->ip_addr.s;
2689 			c2p = sdp_stream->ip_addr.s;
2690 			/*
2691 			 * Alter IP. Don't alter IP common for the session
2692 			 * more than once.
2693 			 */
2694 			if (c2p != NULL || !c1p_altered) {
2695 				body1.s = c2p ? c2p : c1p;
2696 				body1.len = bodylimit - body1.s;
2697 #ifdef EXTRA_DEBUG
2698 				LM_DBG("alter ip body1='%.*s'\n", body1.len, body1.s);
2699 #endif
2700 				if (alter_mediaip(msg, &body1, &oldip, pf, &newip.strip, newip.pf, 0)==-1) {
2701 					FORCE_RTP_PROXY_RET (-1);
2702 				}
2703 				if (!c2p)
2704 					c1p_altered = 1;
2705 			}
2706 			/*
2707 			 * Alter common IP if required, but don't do it more than once.
2708 			 */
2709 			if (commip && c1p && !c1p_altered) {
2710 				body1.s = c1p;
2711 				body1.len = bodylimit - body1.s;
2712 #ifdef EXTRA_DEBUG
2713 				LM_DBG("alter common ip body1='%.*s'\n", body1.len, body1.s);
2714 #endif
2715 				if (alter_mediaip(msg, &body1, &sdp_session->ip_addr,
2716 							sdp_session->pf, &newip.strip, newip.pf, 0)==-1) {
2717 					FORCE_RTP_PROXY_RET (-1);
2718 				}
2719 				c1p_altered = 1;
2720 			}
2721 			/*
2722 			 * Alter the IP in "o=", but only once per session
2723 			 */
2724 			if (o1p) {
2725 				body1.s = o1p;
2726 				body1.len = bodylimit - body1.s;
2727 #ifdef EXTRA_DEBUG
2728 				LM_DBG("alter media ip body1='%.*s'\n", body1.len, body1.s);
2729 #endif
2730 				if (alter_mediaip(msg, &body1, &sdp_session->o_ip_addr,
2731 							sdp_session->o_pf, &newip.strip, newip.pf, 0)==-1) {
2732 					FORCE_RTP_PROXY_RET (-1);
2733 				}
2734 				o1p = 0;
2735 			}
2736 			sdp_stream_num++;
2737 		}
2738 		sdp_session_num++;
2739 	}
2740 
2741 
2742 
2743 	free_opts(&opts, &rep_opts, &pt_opts);
2744 
2745 	if (proxied == 0 && nortpproxy_str.len) {
2746 		cp = pkg_malloc((nortpproxy_str.len + CRLF_LEN) * sizeof(char));
2747 		if (cp == NULL) {
2748 			LM_ERR("out of pkg memory\n");
2749 			return -1;
2750 		}
2751 		anchor = anchor_lump(msg, body.s + body.len - msg->buf, 0, 0);
2752 		if (anchor == NULL) {
2753 			LM_ERR("anchor_lump failed\n");
2754 			pkg_free(cp);
2755 			return -1;
2756 		}
2757 		memcpy(cp, CRLF, CRLF_LEN);
2758 		memcpy(cp + CRLF_LEN, nortpproxy_str.s, nortpproxy_str.len);
2759 		if (insert_new_lump_after(anchor, cp, nortpproxy_str.len + CRLF_LEN, 0) == NULL) {
2760 			LM_ERR("insert_new_lump_after failed\n");
2761 			pkg_free(cp);
2762 			return -1;
2763 		}
2764 	}
2765 
2766 	return 1;
2767 }
2768 
2769 
ki_start_recording(sip_msg_t * msg)2770 static int ki_start_recording(sip_msg_t* msg)
2771 {
2772 	int nitems;
2773 	str callid = {0, 0};
2774 	str from_tag = {0, 0};
2775 	str to_tag = {0, 0};
2776 	struct rtpp_node *node;
2777 	struct iovec v[1 + 4 + 3] = {{NULL, 0}, {"R", 1}, {" ", 1}, {NULL, 0},
2778 		{" ", 1}, {NULL, 0}, {" ", 1}, {NULL, 0}};
2779 	/* 1 */   /* 2 */   /* 3 */    /* 4 */   /* 5 */    /* 6 */   /* 1 */
2780 
2781 	if (get_callid(msg, &callid) == -1 || callid.len == 0) {
2782 		LM_ERR("can't get Call-Id field\n");
2783 		return -1;
2784 	}
2785 
2786 	if (get_to_tag(msg, &to_tag) == -1) {
2787 		LM_ERR("can't get To tag\n");
2788 		return -1;
2789 	}
2790 
2791 	if (get_from_tag(msg, &from_tag) == -1 || from_tag.len == 0) {
2792 		LM_ERR("can't get From tag\n");
2793 		return -1;
2794 	}
2795 
2796 	if(msg->id != current_msg_id){
2797 		selected_rtpp_set = default_rtpp_set;
2798 	}
2799 
2800 	STR2IOVEC(callid, v[3]);
2801 	STR2IOVEC(from_tag, v[5]);
2802 	STR2IOVEC(to_tag, v[7]);
2803 	node = select_rtpp_node(callid, 1);
2804 	if (!node) {
2805 		LM_ERR("no available proxies\n");
2806 		return -1;
2807 	}
2808 	set_rtp_inst_pvar(msg, &node->rn_url);
2809 
2810 	nitems = 8;
2811 	if (msg->first_line.type == SIP_REPLY) {
2812 		if (to_tag.len == 0)
2813 			return -1;
2814 		STR2IOVEC(to_tag, v[5]);
2815 		STR2IOVEC(from_tag, v[7]);
2816 	} else {
2817 		STR2IOVEC(from_tag, v[5]);
2818 		STR2IOVEC(to_tag, v[7]);
2819 		if (to_tag.len <= 0)
2820 			nitems = 6;
2821 	}
2822 	send_rtpp_command(node, v, nitems);
2823 
2824 	return 1;
2825 }
2826 
start_recording_f(struct sip_msg * msg,char * foo,char * bar)2827 static int start_recording_f(struct sip_msg* msg, char *foo, char *bar)
2828 {
2829 	return ki_start_recording(msg);
2830 }
2831 
2832 /*
2833  * Returns the current RTP-Statistics from the RTP-Proxy
2834  */
2835 	static int
pv_get_rtpstat_f(struct sip_msg * msg,pv_param_t * param,pv_value_t * res)2836 pv_get_rtpstat_f(struct sip_msg *msg, pv_param_t *param,
2837 		pv_value_t *res)
2838 {
2839 	str ret_val = {0, 0};
2840 	int nitems;
2841 	str callid = {0, 0};
2842 	str from_tag = {0, 0};
2843 	str to_tag = {0, 0};
2844 	struct rtpp_node *node;
2845 	struct iovec v[1 + 4 + 3 + 1] = {{NULL, 0}, {"Q", 1}, {" ", 1}, {NULL, 0},
2846 		{" ", 1}, {NULL, 0}, {";1 ", 3}, {";1", }, {NULL, 0}};
2847 
2848 	if (get_callid(msg, &callid) == -1 || callid.len == 0) {
2849 		LM_ERR("can't get Call-Id field\n");
2850 		return pv_get_null(msg, param, res);
2851 	}
2852 	if (get_to_tag(msg, &to_tag) == -1) {
2853 		LM_ERR("can't get To tag\n");
2854 		return pv_get_null(msg, param, res);
2855 	}
2856 	if (get_from_tag(msg, &from_tag) == -1 || from_tag.len == 0) {
2857 		LM_ERR("can't get From tag\n");
2858 		return pv_get_null(msg, param, res);
2859 	}
2860 	if(msg->id != current_msg_id){
2861 		selected_rtpp_set = default_rtpp_set;
2862 	}
2863 
2864 	STR2IOVEC(callid, v[3]);
2865 	STR2IOVEC(from_tag, v[5]);
2866 	STR2IOVEC(to_tag, v[7]);
2867 	node = select_rtpp_node(callid, 1);
2868 	if (!node) {
2869 		LM_ERR("no available proxies\n");
2870 		return -1;
2871 	}
2872 	set_rtp_inst_pvar(msg, &node->rn_url);
2873 	nitems = 8;
2874 	if (msg->first_line.type == SIP_REPLY) {
2875 		if (to_tag.len == 0)
2876 			return -1;
2877 		STR2IOVEC(to_tag, v[5]);
2878 		STR2IOVEC(from_tag, v[7]);
2879 	} else {
2880 		STR2IOVEC(from_tag, v[5]);
2881 		STR2IOVEC(to_tag, v[7]);
2882 		if (to_tag.len <= 0)
2883 			nitems = 6;
2884 	}
2885 	ret_val.s = send_rtpp_command(node, v, nitems);
2886 	if(ret_val.s==NULL)
2887 		return pv_get_null(msg, param, res);
2888 	ret_val.len = strlen(ret_val.s);
2889 	return pv_get_strval(msg, param, res, &ret_val);
2890 }
2891 
set_rtp_inst_pvar(struct sip_msg * msg,const str * const uri)2892 int set_rtp_inst_pvar(struct sip_msg *msg, const str * const uri) {
2893 	pv_value_t val;
2894 
2895 	if (rtp_inst_pvar == NULL)
2896 		return 0;
2897 
2898 	memset(&val, 0, sizeof(pv_value_t));
2899 	val.flags = PV_VAL_STR;
2900 	val.rs = *uri;
2901 
2902 	if (rtp_inst_pvar->setf(msg, &rtp_inst_pvar->pvp, (int)EQ_T, &val) < 0)
2903 	{
2904 		LM_ERR("Failed to add RTPProxy URI to pvar\n");
2905 		return -1;
2906 	}
2907 	return 0;
2908 }
2909 
2910 /**
2911  *
2912  */
ki_rtpproxy_manage0(sip_msg_t * msg)2913 static int ki_rtpproxy_manage0(sip_msg_t *msg)
2914 {
2915 	return rtpproxy_manage(msg, NULL, NULL);
2916 }
2917 
2918 /**
2919  *
2920  */
ki_rtpproxy_manage(sip_msg_t * msg,str * flags)2921 static int ki_rtpproxy_manage(sip_msg_t *msg, str *flags)
2922 {
2923 	return rtpproxy_manage(msg, ((flags && flags->len>0)?flags->s:NULL), NULL);
2924 }
2925 
2926 /**
2927  *
2928  */
ki_rtpproxy_manage_ip(sip_msg_t * msg,str * flags,str * mip)2929 static int ki_rtpproxy_manage_ip(sip_msg_t *msg, str *flags, str *mip)
2930 {
2931 	/* str->s from kemi params is zero-terminated */
2932 	return rtpproxy_manage(msg, ((flags && flags->len>0)?flags->s:NULL),
2933 			((mip && mip->len>0)?mip->s:NULL));
2934 }
2935 
ki_set_rtp_proxy_set(sip_msg_t * msg,int rset)2936 static int ki_set_rtp_proxy_set(sip_msg_t *msg, int rset)
2937 {
2938 	selected_rtpp_set = select_rtpp_set(rset);
2939 	if(selected_rtpp_set==NULL) {
2940 		LM_ERR("could not locate rtpproxy set %d\n", rset);
2941 		return -1;
2942 	}
2943 	current_msg_id = msg->id;
2944 	return 1;
2945 }
2946 
ki_rtpproxy_destroy0(sip_msg_t * msg)2947 static int ki_rtpproxy_destroy0(sip_msg_t *msg)
2948 {
2949 	return unforce_rtp_proxy(msg, NULL);
2950 }
2951 
ki_rtpproxy_destroy(sip_msg_t * msg,str * flags)2952 static int ki_rtpproxy_destroy(sip_msg_t *msg, str *flags)
2953 {
2954 	if(flags==NULL || flags->len<=0)
2955 		return unforce_rtp_proxy(msg, NULL);
2956 	return unforce_rtp_proxy(msg, flags->s);
2957 }
2958 
ki_rtpproxy_offer0(sip_msg_t * msg)2959 static int ki_rtpproxy_offer0(sip_msg_t *msg)
2960 {
2961 	return rtpproxy_offer1_helper_f(msg, NULL);
2962 }
2963 
ki_rtpproxy_offer(sip_msg_t * msg,str * flags)2964 static int ki_rtpproxy_offer(sip_msg_t *msg, str *flags)
2965 {
2966 	if(flags==NULL || flags->len<=0)
2967 		return rtpproxy_offer1_helper_f(msg, NULL);
2968 	return rtpproxy_offer1_helper_f(msg, flags->s);
2969 }
2970 
ki_rtpproxy_offer_ip(sip_msg_t * msg,str * flags,str * mip)2971 static int ki_rtpproxy_offer_ip(sip_msg_t *msg, str *flags, str *mip)
2972 {
2973 	return force_rtp_proxy(msg, flags->s, mip->s, 1, 1);
2974 }
2975 
ki_rtpproxy_answer0(sip_msg_t * msg)2976 static int ki_rtpproxy_answer0(sip_msg_t *msg)
2977 {
2978 	return rtpproxy_answer1_helper_f(msg, NULL);
2979 }
2980 
ki_rtpproxy_answer(sip_msg_t * msg,str * flags)2981 static int ki_rtpproxy_answer(sip_msg_t *msg, str *flags)
2982 {
2983 	if(flags==NULL || flags->len<=0)
2984 		return rtpproxy_answer1_helper_f(msg, NULL);
2985 	return rtpproxy_answer1_helper_f(msg, flags->s);
2986 }
2987 
ki_rtpproxy_answer_ip(sip_msg_t * msg,str * flags,str * mip)2988 static int ki_rtpproxy_answer_ip(sip_msg_t *msg, str *flags, str *mip)
2989 {
2990 	return force_rtp_proxy(msg, flags->s, mip->s, 0, 1);
2991 }
2992 
ki_rtpproxy_stream2uac(sip_msg_t * msg,str * pname,int count)2993 static int ki_rtpproxy_stream2uac(sip_msg_t* msg, str* pname, int count)
2994 {
2995 	return rtpproxy_stream(msg, pname, count, 1);
2996 }
2997 
ki_rtpproxy_stream2uas(sip_msg_t * msg,str * pname,int count)2998 static int ki_rtpproxy_stream2uas(sip_msg_t* msg, str* pname, int count)
2999 {
3000 	return rtpproxy_stream(msg, pname, count, 0);
3001 }
3002 
ki_rtpproxy_stop_stream2uac(sip_msg_t * msg)3003 static int ki_rtpproxy_stop_stream2uac(sip_msg_t *msg)
3004 {
3005 	return rtpproxy_stop_stream(msg, 1);
3006 }
3007 
ki_rtpproxy_stop_stream2uas(sip_msg_t * msg)3008 static int ki_rtpproxy_stop_stream2uas(sip_msg_t* msg)
3009 {
3010 	return rtpproxy_stop_stream(msg, 0);
3011 }
3012 
3013 /**
3014  *
3015  */
3016 /* clang-format off */
3017 static sr_kemi_t sr_kemi_rtpproxy_exports[] = {
3018 	{ str_init("rtpproxy"), str_init("rtpproxy_manage0"),
3019 		SR_KEMIP_INT, ki_rtpproxy_manage0,
3020 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
3021 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
3022 	},
3023 	{ str_init("rtpproxy"), str_init("rtpproxy_manage"),
3024 		SR_KEMIP_INT, ki_rtpproxy_manage,
3025 		{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
3026 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
3027 	},
3028 	{ str_init("rtpproxy"), str_init("rtpproxy_manage_ip"),
3029 		SR_KEMIP_INT, ki_rtpproxy_manage_ip,
3030 		{ SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_NONE,
3031 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
3032 	},
3033 	{ str_init("rtpproxy"), str_init("set_rtpproxy_set"),
3034 		SR_KEMIP_INT, ki_set_rtp_proxy_set,
3035 		{ SR_KEMIP_INT, SR_KEMIP_NONE, SR_KEMIP_NONE,
3036 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
3037 	},
3038 	{ str_init("rtpproxy"), str_init("rtpproxy_destroy0"),
3039 		SR_KEMIP_INT, ki_rtpproxy_destroy0,
3040 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
3041 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
3042 	},
3043 	{ str_init("rtpproxy"), str_init("rtpproxy_destroy"),
3044 		SR_KEMIP_INT, ki_rtpproxy_destroy,
3045 		{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
3046 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
3047 	},
3048 	{ str_init("rtpproxy"), str_init("start_recording"),
3049 		SR_KEMIP_INT, ki_start_recording,
3050 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
3051 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
3052 	},
3053 	{ str_init("rtpproxy"), str_init("rtpproxy_offer0"),
3054 		SR_KEMIP_INT, ki_rtpproxy_offer0,
3055 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
3056 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
3057 	},
3058 	{ str_init("rtpproxy"), str_init("rtpproxy_offer"),
3059 		SR_KEMIP_INT, ki_rtpproxy_offer,
3060 		{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
3061 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
3062 	},
3063 	{ str_init("rtpproxy"), str_init("rtpproxy_offer_ip"),
3064 		SR_KEMIP_INT, ki_rtpproxy_offer_ip,
3065 		{ SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_NONE,
3066 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
3067 	},
3068 	{ str_init("rtpproxy"), str_init("rtpproxy_answer0"),
3069 		SR_KEMIP_INT, ki_rtpproxy_answer0,
3070 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
3071 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
3072 	},
3073 	{ str_init("rtpproxy"), str_init("rtpproxy_answer"),
3074 		SR_KEMIP_INT, ki_rtpproxy_answer,
3075 		{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
3076 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
3077 	},
3078 	{ str_init("rtpproxy"), str_init("rtpproxy_answer_ip"),
3079 		SR_KEMIP_INT, ki_rtpproxy_answer_ip,
3080 		{ SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_NONE,
3081 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
3082 	},
3083 	{ str_init("rtpproxy"), str_init("rtpproxy_stream2uac"),
3084 		SR_KEMIP_INT, ki_rtpproxy_stream2uac,
3085 		{ SR_KEMIP_STR, SR_KEMIP_INT, SR_KEMIP_NONE,
3086 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
3087 	},
3088 	{ str_init("rtpproxy"), str_init("rtpproxy_stream2uas"),
3089 		SR_KEMIP_INT, ki_rtpproxy_stream2uas,
3090 		{ SR_KEMIP_STR, SR_KEMIP_INT, SR_KEMIP_NONE,
3091 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
3092 	},
3093 	{ str_init("rtpproxy"), str_init("rtpproxy_stop_stream2uac"),
3094 		SR_KEMIP_INT, ki_rtpproxy_stop_stream2uac,
3095 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
3096 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
3097 	},
3098 	{ str_init("rtpproxy"), str_init("rtpproxy_stop_stream2uas"),
3099 		SR_KEMIP_INT, ki_rtpproxy_stop_stream2uas,
3100 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
3101 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
3102 	},
3103 
3104 	{ {0, 0}, {0, 0}, 0, NULL, { 0, 0, 0, 0, 0, 0 } }
3105 };
3106 /* clang-format on */
3107 
mod_register(char * path,int * dlflags,void * p1,void * p2)3108 int mod_register(char *path, int *dlflags, void *p1, void *p2)
3109 {
3110 	sr_kemi_modules_add(sr_kemi_rtpproxy_exports);
3111 	return 0;
3112 }
3113