iptrtpproxy.c 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426
  1. /* $Id$
  2. *
  3. * Copyright (C) 2007 Tomas Mandys
  4. *
  5. * This file is part of ser, a free SIP server.
  6. *
  7. * ser 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. * For a license to use the ser software under conditions
  13. * other than those described here, or to purchase support for this
  14. * software, please contact iptel.org by e-mail at the following addresses:
  15. * [email protected]
  16. *
  17. * ser is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. * GNU General Public License for more details.
  21. *
  22. * You should have received a copy of the GNU General Public License
  23. * along with this program; if not, write to the Free Software
  24. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  25. *
  26. */
  27. #include "../../sr_module.h"
  28. #include "../../dprint.h"
  29. #include "../../data_lump.h"
  30. #include "../../data_lump_rpl.h"
  31. #include "../../error.h"
  32. #include "../../forward.h"
  33. #include "../../mem/mem.h"
  34. #include "../../parser/parse_content.h"
  35. #include "../../parser/parse_uri.h"
  36. #include "../../parser/parser_f.h"
  37. #include "../../parser/parse_body.h"
  38. #include "../../resolve.h"
  39. #include "../../trim.h"
  40. #include "../../ut.h"
  41. #include "../../msg_translator.h"
  42. #include "../../socket_info.h"
  43. #include "../../select.h"
  44. #include "../../select_buf.h"
  45. #include "../../script_cb.h"
  46. #include "../../cfg_parser.h"
  47. #include <sys/types.h>
  48. #include <sys/socket.h>
  49. #include <sys/time.h>
  50. #include <netinet/in.h>
  51. #include <arpa/inet.h>
  52. #include <sys/uio.h>
  53. #include <sys/un.h>
  54. #include <ctype.h>
  55. #include <errno.h>
  56. #include <netdb.h>
  57. #include <poll.h>
  58. #include <stdio.h>
  59. #include <stdlib.h>
  60. #include <string.h>
  61. #include <unistd.h>
  62. #include <linux/netfilter/xt_RTPPROXY.h>
  63. #include <arpa/inet.h>
  64. MODULE_VERSION
  65. #define MODULE_NAME "iptrtpproxy"
  66. /* max.number of RTP streams per session */
  67. #define MAX_MEDIA_NUMBER 20
  68. #define MAX_SWITCHBOARD_NAME_LEN 20
  69. struct switchboard_item {
  70. str name;
  71. int ringing_timeout;
  72. struct xt_rtpproxy_sockopt_in_switchboard in_switchboard;
  73. struct xt_rtpproxy_sockopt_in_alloc_session in_session;
  74. unsigned int param_ids;
  75. struct switchboard_item* next;
  76. };
  77. static char* global_session_ids;
  78. static str sdp_ip;
  79. static struct xt_rtpproxy_handle handle = {.sockfd = 0};
  80. static struct switchboard_item* switchboards = NULL;
  81. static struct switchboard_item* found_switchboard;
  82. static int found_direction;
  83. static int switchboard_count = 0;
  84. static str iptrtpproxy_cfg_filename = STR_STATIC_INIT("/etc/iptrtpproxy.cfg");
  85. static int iptrtpproxy_cfg_flag = 0;
  86. static struct switchboard_item* find_switchboard(str *name) {
  87. struct switchboard_item* p;
  88. for (p = switchboards; p; p=p->next) {
  89. if (name->len == p->name.len && strncasecmp(p->name.s, name->s, name->len)==0) break;
  90. }
  91. return p;
  92. }
  93. /** if succesfull allocated sessions available @rtpproxy.session_ids
  94. */
  95. static int rtpproxy_alloc_fixup(void** param, int param_no) {
  96. switch (param_no) {
  97. case 1:
  98. return fixup_var_int_12(param, param_no);
  99. case 2:
  100. return fixup_var_str_12(param, param_no);
  101. default:
  102. return 0;
  103. }
  104. }
  105. static int rtpproxy_update_fixup(void** param, int param_no) {
  106. switch (param_no) {
  107. case 1:
  108. return rtpproxy_alloc_fixup(param, param_no);
  109. case 2:
  110. return fixup_var_str_12(param, param_no);
  111. default:
  112. return 0;
  113. }
  114. }
  115. static int rtpproxy_delete_fixup(void** param, int param_no) {
  116. return rtpproxy_update_fixup(param, 2);
  117. }
  118. static int rtpproxy_find_fixup(void** param, int param_no) {
  119. return fixup_var_str_12(param, param_no);
  120. }
  121. struct sdp_session {
  122. unsigned int media_count;
  123. struct {
  124. int active;
  125. unsigned short port;
  126. unsigned int ip;
  127. str ip_s;
  128. str port_s;
  129. } media[MAX_MEDIA_NUMBER];
  130. };
  131. struct ipt_session {
  132. struct switchboard_item *switchboard;
  133. unsigned int stream_count;
  134. struct {
  135. int sess_id;
  136. int created;
  137. unsigned short proxy_port;
  138. } streams[MAX_MEDIA_NUMBER];
  139. };
  140. static unsigned int s2ip4(str *s) {
  141. struct in_addr res;
  142. char c2;
  143. c2 = s->s[s->len];
  144. s->s[s->len] = '\0';
  145. if (!inet_aton(s->s, &res)) {
  146. s->s[s->len] = c2;
  147. return 0;
  148. }
  149. s->s[s->len] = c2;
  150. return res.s_addr;
  151. }
  152. static void ip42s(unsigned int ip, str *s) {
  153. struct in_addr ip2 = { ip };
  154. s->s = inet_ntoa(ip2);
  155. s->len = strlen(s->s);
  156. }
  157. #define is_alpha(_c) (((_c) >= 'a' && (_c) <= 'z') || ((_c) >= 'A' && (_c) <= 'Z') || ((_c) >= '0' && (_c) <= '9') || ((_c) == '_') || ((_c) == '-'))
  158. inline static int next_sdp_line(char** p, char* pend, char *ltype, str* line) {
  159. char *cp;
  160. while (*p < pend) {
  161. while (*p < pend && (**p == '\n' || **p == '\r')) (*p)++;
  162. for (cp = *p; cp < pend && *cp != '\n' && *cp != '\r'; cp++);
  163. if (cp-*p > 2 && (*p)[1] == '=') {
  164. *ltype = **p;
  165. line->s = (*p)+2;
  166. line->len = cp-line->s;
  167. *p = cp;
  168. return 0;
  169. }
  170. *p = cp;
  171. }
  172. return -1;
  173. };
  174. /* SDP RFC2327 */
  175. static int parse_sdp_content(struct sip_msg* msg, struct sdp_session *sess) {
  176. char *p, *pend, *cp, *cp2, *lend;
  177. str line, cline_ip_s, body;
  178. int sess_fl, i, cline_count;
  179. char ltype, savec;
  180. unsigned int cline_ip;
  181. static str supported_media_types[] = {
  182. STR_STATIC_INIT("udp"),
  183. STR_STATIC_INIT("udptl"),
  184. STR_STATIC_INIT("rtp/avp"),
  185. STR_STATIC_INIT("rtp/savpf"),
  186. STR_NULL
  187. };
  188. memset(sess, 0, sizeof(*sess));
  189. /* try to get the body part with application/sdp */
  190. body.s = get_body_part(msg, TYPE_APPLICATION, SUBTYPE_SDP, &body.len);
  191. if (!body.s) {
  192. ERR(MODULE_NAME": parse_sdp_content: failed to get the application/sdp body\n");
  193. return -1;
  194. }
  195. #if 0
  196. body.s = get_body(msg);
  197. if (body.s==0) {
  198. ERR(MODULE_NAME": parse_sdp_content: failed to get the message body\n");
  199. return -1;
  200. }
  201. body.len = msg->len -(int)(body.s - msg->buf);
  202. if (body.len==0) {
  203. ERR(MODULE_NAME": parse_sdp_content: message body has length zero\n");
  204. return -1;
  205. }
  206. /* no need for parse_headers(msg, EOH), get_body will parse everything */
  207. if (!msg->content_type)
  208. {
  209. WARN(MODULE_NAME": parse_sdp_content: Content-TYPE header absent!"
  210. "let's assume the content is text/plain\n");
  211. }
  212. else {
  213. trim_len(line.len, line.s, msg->content_type->body);
  214. if (line.len != sizeof("application/sdp")-1 || strncasecmp(line.s, "application/sdp", line.len) != 0) {
  215. ERR(MODULE_NAME": parse_sdp_content: bad content type '%.*s'\n", line.len, line.s);
  216. return -1;
  217. }
  218. }
  219. #endif
  220. /*
  221. * Parsing of SDP body.
  222. * It can contain a few session descriptions (each starts with
  223. * v-line), and each session may contain a few media descriptions
  224. * (each starts with m-line).
  225. * We have to change ports in m-lines, and also change IP addresses in
  226. * c-lines which can be placed either in session header (fallback for
  227. * all medias) or media description.
  228. * Ports should be allocated for any media. IPs all should be changed
  229. * to the same value (RTP proxy IP), so we can change all c-lines
  230. * unconditionally.
  231. * There are sendonly,recvonly modifiers which signalize one-way
  232. * streaming, it probably won't work but it's handled the same way,
  233. * RTCP commands are still bi-directional. "Inactive" modifier
  234. * is not handled anyway. See RFC3264
  235. */
  236. p = body.s;
  237. pend = body.s + body.len;
  238. sess_fl = 0;
  239. sess->media_count = 0;
  240. cline_ip_s.s = NULL; /* make gcc happy */
  241. cline_ip_s.len = 0;
  242. cline_ip = 0;
  243. cline_count = 0;
  244. while (p < pend) {
  245. if (next_sdp_line(&p, pend, &ltype, &line) < 0) break;
  246. switch (ltype) {
  247. case 'v':
  248. /* Protocol Version: v=0 */
  249. if (sess_fl != 0) {
  250. ERR(MODULE_NAME": parse_sdp_content: only one session allowed\n"); /* RFC3264 */
  251. return -1;
  252. }
  253. sess_fl = 1;
  254. break;
  255. case 'c':
  256. /* Connection Data: c=<network type> <address type> <connection address>, ex. c=IN IP4 224.2.17.12/127 */
  257. switch (sess_fl) {
  258. case 0:
  259. ERR(MODULE_NAME": parse_sdp_content: c= line is not in session section\n");
  260. return -1;
  261. case 1:
  262. case 2:
  263. cline_count++;
  264. if (cline_count > 1) {
  265. /* multicast not supported */
  266. if (sess_fl == 2) {
  267. goto invalidate;
  268. }
  269. else {
  270. cline_ip_s.len = 0;
  271. }
  272. break;
  273. }
  274. lend = line.s + line.len;
  275. cp = eat_token_end(line.s, lend);
  276. if (cp-line.s != 2 || memcmp(line.s, "IN", 2) != 0) {
  277. goto invalidate;
  278. }
  279. cp = eat_space_end(cp, lend);
  280. line.s = cp;
  281. cp = eat_token_end(cp, lend);
  282. if (cp-line.s != 3 || memcmp(line.s, "IP4", 3) != 0) {
  283. goto invalidate;
  284. }
  285. cp = eat_space_end(cp, lend);
  286. line.s = cp;
  287. cp = eat_token_end(cp, lend);
  288. line.len = cp-line.s;
  289. if (line.len == 0 || q_memchr(line.s, '/', line.len)) {
  290. /* multicast address not supported */
  291. goto invalidate;
  292. }
  293. if (sess_fl == 1) {
  294. cline_ip_s = line;
  295. cline_ip = s2ip4(&line);
  296. }
  297. else {
  298. sess->media[sess->media_count-1].ip = s2ip4(&line);
  299. sess->media[sess->media_count-1].active = 1; /* IP may by specified by hostname */
  300. sess->media[sess->media_count-1].ip_s = line;
  301. }
  302. break;
  303. default:
  304. ;
  305. }
  306. break;
  307. invalidate:
  308. if (sess_fl == 2) {
  309. sess->media[sess->media_count-1].active = 0;
  310. }
  311. break;
  312. case 'm':
  313. /* Media Announcements: m=<media> <port>[/<number of ports>] <transport> <fmt list>, eg. m=audio 49170 RTP/AVP 0 */
  314. switch (sess_fl) {
  315. case 0:
  316. ERR(MODULE_NAME": parse_sdp_content: m= line is not in session section\n");
  317. return -1;
  318. case 1:
  319. case 2:
  320. if (sess->media_count >= MAX_MEDIA_NUMBER) {
  321. ERR(MODULE_NAME": parse_sdp_content: max.number of medias (%d) exceeded\n", MAX_MEDIA_NUMBER);
  322. return -1;
  323. }
  324. cline_count = 0;
  325. sess_fl = 2;
  326. sess->media_count++;
  327. sess->media[sess->media_count-1].active = 0;
  328. lend = line.s + line.len;
  329. cp = eat_token_end(line.s, lend);
  330. if (cp-line.s == 0) {
  331. break;
  332. }
  333. cp = eat_space_end(cp, lend);
  334. line.s = cp;
  335. cp = eat_token_end(cp, lend);
  336. line.len = cp-line.s;
  337. cp2 = q_memchr(line.s, '/', line.len);
  338. if (cp2) {
  339. /* strip optional number of ports, if present should be 2 */
  340. line.len = cp2-line.s;
  341. }
  342. sess->media[sess->media_count-1].port_s = line;
  343. if (line.len == 0) { /* invalid port? */
  344. break;
  345. }
  346. savec = line.s[line.len];
  347. line.s[line.len] = '\0';
  348. sess->media[sess->media_count-1].port = atol(line.s);
  349. line.s[line.len] = savec;
  350. if (sess->media[sess->media_count-1].port == 0) {
  351. break;
  352. }
  353. cp = eat_space_end(cp, lend);
  354. line.s = cp;
  355. cp = eat_token_end(cp, lend);
  356. line.len = cp-line.s;
  357. for (i = 0; supported_media_types[i].s != NULL; i++) {
  358. if (line.len == supported_media_types[i].len &&
  359. strncasecmp(line.s, supported_media_types[i].s, line.len) == 0) {
  360. sess->media[sess->media_count-1].active = cline_ip_s.len != 0; /* IP may by specified by hostname */
  361. sess->media[sess->media_count-1].ip_s = cline_ip_s;
  362. sess->media[sess->media_count-1].ip = cline_ip;
  363. break;
  364. }
  365. }
  366. break;
  367. default:
  368. ;
  369. }
  370. break;
  371. default:
  372. ;
  373. }
  374. }
  375. return 0;
  376. }
  377. static int prepare_lumps(struct sip_msg* msg, str* position, str* s) {
  378. struct lump* anchor;
  379. char *buf;
  380. //ERR("'%.*s' --> '%.*s'\n", position->len, position->s, s->len, s->s);
  381. anchor = del_lump(msg, position->s - msg->buf, position->len, 0);
  382. if (anchor == NULL) {
  383. ERR(MODULE_NAME": prepare_lumps: del_lump failed\n");
  384. return -1;
  385. }
  386. buf = pkg_malloc(s->len);
  387. if (buf == NULL) {
  388. ERR(MODULE_NAME": prepare_lumps: out of memory\n");
  389. return -1;
  390. }
  391. memcpy(buf, s->s, s->len);
  392. if (insert_new_lump_after(anchor, buf, s->len, 0) == 0) {
  393. ERR(MODULE_NAME": prepare_lumps: insert_new_lump_after failed\n");
  394. pkg_free(buf);
  395. return -1;
  396. }
  397. return 0;
  398. }
  399. static int update_sdp_content(struct sip_msg* msg, int gate_a_to_b, struct sdp_session *sdp_sess, struct ipt_session *ipt_sess) {
  400. int i, j;
  401. str s;
  402. /* we must apply lumps for relevant c= and m= lines */
  403. sdp_ip.len = 0;
  404. for (i=0; i<sdp_sess->media_count; i++) {
  405. if (sdp_sess->media[i].active) {
  406. for (j=0; j<i; j++) {
  407. if (sdp_sess->media[j].active && sdp_sess->media[i].ip_s.s == sdp_sess->media[j].ip_s.s) {
  408. goto cline_fixed;
  409. }
  410. }
  411. if (sdp_ip.len == 0) {
  412. /* takes 1st ip to be rewritten, for aux purposes only */
  413. sdp_ip = sdp_sess->media[i].ip_s;
  414. }
  415. /* apply lump for ip address in c= line */
  416. ip42s(ipt_sess->switchboard->in_switchboard.gate[!gate_a_to_b].ip, &s);
  417. if (prepare_lumps(msg, &sdp_sess->media[i].ip_s, &s) < 0)
  418. return -1;
  419. cline_fixed:
  420. /* apply lump for port in m= line */
  421. s.s = int2str(ipt_sess->streams[i].proxy_port, &s.len);
  422. if (prepare_lumps(msg, &sdp_sess->media[i].port_s, &s) < 0)
  423. return -1;
  424. }
  425. }
  426. return 0;
  427. }
  428. /* null terminated result is allocated at static buffer */
  429. static void serialize_ipt_session(struct ipt_session* sess, str* session_ids) {
  430. static char buf[MAX_SWITCHBOARD_NAME_LEN+1+(5+1+1+10)*MAX_MEDIA_NUMBER+1];
  431. char *p;
  432. int i;
  433. buf[0] = '\0';
  434. p = buf;
  435. memcpy(p, sess->switchboard->name.s, sess->switchboard->name.len);
  436. p += sess->switchboard->name.len;
  437. *p = ':';
  438. p++;
  439. for (i=0; i<sess->stream_count; i++) {
  440. if (sess->streams[i].sess_id >= 0) {
  441. p += sprintf(p, "%u/%u", sess->streams[i].sess_id, sess->streams[i].created);
  442. }
  443. *p = ',';
  444. p++;
  445. }
  446. p--;
  447. *p = '\0';
  448. session_ids->s = buf;
  449. session_ids->len = p - buf;
  450. }
  451. /* switchboardname [":" [sess_id "/" created] [ * ( "," [sess_id "/" created] )] ] */
  452. static int unserialize_ipt_session(str* session_ids, struct ipt_session* sess) {
  453. char *p, *pend, savec;
  454. str s;
  455. memset(sess, 0, sizeof(*sess));
  456. p = session_ids->s;
  457. pend = session_ids->s+session_ids->len;
  458. s.s = p;
  459. while (p < pend && is_alpha(*p)) p++;
  460. s.len = p-s.s;
  461. sess->switchboard = find_switchboard(&s);
  462. if (!sess->switchboard) {
  463. ERR(MODULE_NAME": unserialize_ipt_session: '%.*s', switchboard '%.*s' not found\n", session_ids->len, session_ids->s, s.len, s.s);
  464. return -1;
  465. }
  466. if (p == pend) return 0;
  467. if (*p != ':') {
  468. ERR(MODULE_NAME": unserialize_ipt_session: '%.*s', colon expected near '%.*s'\n", session_ids->len, session_ids->s, pend-p, p);
  469. return -1;
  470. }
  471. do {
  472. if (sess->stream_count >= MAX_MEDIA_NUMBER) {
  473. ERR(MODULE_NAME": unserialize_ipt_session: '%.*s', max.media number (%d) exceeded\n", session_ids->len, session_ids->s, MAX_MEDIA_NUMBER);
  474. return -1;
  475. }
  476. p++;
  477. sess->stream_count++;
  478. sess->streams[sess->stream_count-1].sess_id = -1;
  479. sess->streams[sess->stream_count-1].created = 0;
  480. s.s = p;
  481. while (p < pend && (*p >= '0' && *p <= '9')) p++;
  482. if (p != pend && *p != '/') {
  483. ERR(MODULE_NAME": unserialize_ipt_session: '%.*s', '/' expected near '%.*s'\n", session_ids->len, session_ids->s, pend-p, p);
  484. return -1;
  485. }
  486. s.len = p-s.s;
  487. if (s.len > 0) {
  488. savec = s.s[s.len];
  489. s.s[s.len] = '\0';
  490. sess->streams[sess->stream_count-1].sess_id = atol(s.s);
  491. s.s[s.len] = savec;
  492. }
  493. p++;
  494. s.s = p;
  495. while (p < pend && (*p >= '0' && *p <= '9')) p++;
  496. if (p != pend && *p != ',') {
  497. sess->streams[sess->stream_count-1].sess_id = -1;
  498. ERR(MODULE_NAME": unserialize_ipt_session: '%.*s', comma expected near '%.*s'\n", session_ids->len, session_ids->s, pend-p, p);
  499. return -1;
  500. }
  501. s.len = p-s.s;
  502. if (s.len > 0) {
  503. savec = s.s[s.len];
  504. s.s[s.len] = '\0';
  505. sess->streams[sess->stream_count-1].created = atol(s.s);
  506. s.s[s.len] = savec;
  507. }
  508. } while (p < pend);
  509. return 0;
  510. }
  511. static void delete_ipt_sessions(struct ipt_session* ipt_sess) {
  512. struct xt_rtpproxy_sockopt_in_sess_id in_sess_id;
  513. int i, j;
  514. for (i=0; i < ipt_sess->stream_count; i++) {
  515. if (ipt_sess->streams[i].sess_id >= 0) {
  516. j = i;
  517. in_sess_id.sess_id_min = ipt_sess->streams[i].sess_id;
  518. in_sess_id.sess_id_max = in_sess_id.sess_id_min;
  519. in_sess_id.created = ipt_sess->streams[i].created;
  520. /* group more sessions if possible */
  521. for (; i < ipt_sess->stream_count-1; i++) {
  522. if (ipt_sess->streams[i+1].sess_id >= 0) {
  523. if (ipt_sess->streams[i+1].sess_id == in_sess_id.sess_id_max+1) {
  524. in_sess_id.sess_id_max = ipt_sess->streams[i+1].sess_id;
  525. continue;
  526. }
  527. break;
  528. }
  529. }
  530. if (xt_RTPPROXY_delete_session(&handle, &ipt_sess->switchboard->in_switchboard, &in_sess_id) < 0) {
  531. ERR(MODULE_NAME": rtpproxy_delete: xt_RTPPROXY_delete_session error: %s (%d)\n", handle.err_str, handle.err_no);
  532. /* what to do ? */
  533. }
  534. /* invalidate sessions including duplicates */
  535. for (; j<ipt_sess->stream_count; j++) {
  536. if (ipt_sess->streams[j].sess_id >= in_sess_id.sess_id_min && ipt_sess->streams[j].sess_id <= in_sess_id.sess_id_max)
  537. ipt_sess->streams[j].sess_id = -1;
  538. }
  539. }
  540. }
  541. }
  542. #define GATE_FLAG 0x01
  543. #define RINGING_TIMEOUT_FLAG 0x02
  544. /* gate_a_to_b has index 0, gate_b_to_a 1 */
  545. #define GATE_A_TO_B(flags) (((flags) & GATE_FLAG) == 0)
  546. inline static void fill_in_session(int flags, int media_idx, struct sdp_session *sdp_sess, struct ipt_session *ipt_sess, struct xt_rtpproxy_sockopt_in_alloc_session *in_session) {
  547. int j;
  548. for (j=0; j<2; j++) {
  549. in_session->source[GATE_A_TO_B(flags)].stream[j].flags =
  550. XT_RTPPROXY_SOCKOPT_FLAG_SESSION_ADDR |
  551. ipt_sess->switchboard->in_session.source[GATE_A_TO_B(flags)].stream[j].flags |
  552. ((flags & RINGING_TIMEOUT_FLAG) ? XT_RTPPROXY_SOCKOPT_FLAG_SESSION_LEARNING_TIMEOUT : 0);
  553. in_session->source[GATE_A_TO_B(flags)].stream[j].learning_timeout = (flags & RINGING_TIMEOUT_FLAG) ?
  554. ipt_sess->switchboard->ringing_timeout :
  555. ipt_sess->switchboard->in_session.source[GATE_A_TO_B(flags)].stream[j].learning_timeout;
  556. in_session->source[GATE_A_TO_B(flags)].stream[j].addr.ip = sdp_sess->media[media_idx].ip;
  557. in_session->source[GATE_A_TO_B(flags)].stream[j].addr.port = sdp_sess->media[media_idx].port+j;
  558. }
  559. in_session->source[GATE_A_TO_B(flags)].always_learn = ipt_sess->switchboard->in_session.source[GATE_A_TO_B(flags)].always_learn;
  560. }
  561. static int rtpproxy_alloc(struct sip_msg* msg, char* _flags, char* _switchboard_id) {
  562. int flags;
  563. struct switchboard_item* si = 0;
  564. struct sdp_session sdp_sess;
  565. struct ipt_session ipt_sess;
  566. struct xt_rtpproxy_sockopt_in_alloc_session in_session;
  567. struct xt_rtpproxy_session out_session;
  568. str s;
  569. int i;
  570. if (get_int_fparam(&flags, msg, (fparam_t*) _flags) < 0) {
  571. return -1;
  572. }
  573. if (get_str_fparam(&s, msg, (fparam_t*) _switchboard_id) < 0) {
  574. return -1;
  575. }
  576. if (s.len) {
  577. /* switchboard must be fully qualified, it simplifies helper because it's not necessary to store full identification to session_ids - name is sufficient */
  578. si = find_switchboard(&s);
  579. if (!si) {
  580. ERR(MODULE_NAME": rtpproxy_alloc: switchboard '%.*s' not found\n", s.len, s.s);
  581. return -1;
  582. }
  583. }
  584. else {
  585. if (!found_switchboard) {
  586. ERR(MODULE_NAME": rtpproxy_alloc: no implicit switchboard\n");
  587. return -1;
  588. }
  589. si = found_switchboard;
  590. }
  591. if (parse_sdp_content(msg, &sdp_sess) < 0)
  592. return -1;
  593. memset(&ipt_sess, 0, sizeof(ipt_sess));
  594. ipt_sess.switchboard = si;
  595. memset(&in_session, 0, sizeof(in_session));
  596. for (i = 0; i < sdp_sess.media_count; i++) {
  597. ipt_sess.streams[i].sess_id = -1;
  598. ipt_sess.stream_count = i+1;
  599. if (sdp_sess.media[i].active) {
  600. int j;
  601. for (j = 0; j < i; j++) {
  602. /* if two media streams have equal source address than we will allocate only one ipt session */
  603. if (sdp_sess.media[j].active && sdp_sess.media[i].ip == sdp_sess.media[j].ip && sdp_sess.media[i].port == sdp_sess.media[j].port) {
  604. ipt_sess.streams[i].sess_id = ipt_sess.streams[j].sess_id;
  605. ipt_sess.streams[i].proxy_port = ipt_sess.streams[j].proxy_port;
  606. ipt_sess.streams[i].created = ipt_sess.streams[j].created;
  607. goto cont;
  608. }
  609. }
  610. fill_in_session(flags, i, &sdp_sess, &ipt_sess, &in_session);
  611. if (xt_RTPPROXY_alloc_session(&handle, &ipt_sess.switchboard->in_switchboard, &in_session, NULL, &out_session) < 0) {
  612. ERR(MODULE_NAME": rtpproxy_alloc: xt_RTPPROXY_alloc_session error: %s (%d)\n", handle.err_str, handle.err_no);
  613. delete_ipt_sessions(&ipt_sess);
  614. return -1;
  615. }
  616. ipt_sess.streams[i].sess_id = out_session.sess_id;
  617. ipt_sess.streams[i].created = out_session.created;
  618. ipt_sess.streams[i].proxy_port = out_session.gate[!GATE_A_TO_B(flags)].stream[0].port;
  619. cont: ;
  620. }
  621. }
  622. if (update_sdp_content(msg, GATE_A_TO_B(flags), &sdp_sess, &ipt_sess) < 0) {
  623. delete_ipt_sessions(&ipt_sess);
  624. return -1;
  625. }
  626. serialize_ipt_session(&ipt_sess, &s);
  627. global_session_ids = s.s; /* it's static and null terminated */
  628. return 1;
  629. }
  630. static int rtpproxy_update(struct sip_msg* msg, char* _flags, char* _session_ids) {
  631. str session_ids;
  632. int flags, i;
  633. struct sdp_session sdp_sess;
  634. struct ipt_session ipt_sess;
  635. struct xt_rtpproxy_sockopt_in_sess_id in_sess_id;
  636. struct xt_rtpproxy_sockopt_in_alloc_session in_session;
  637. if (get_int_fparam(&flags, msg, (fparam_t*) _flags) < 0) {
  638. return -1;
  639. }
  640. if (get_str_fparam(&session_ids, msg, (fparam_t*) _session_ids) < 0) {
  641. return -1;
  642. }
  643. if (unserialize_ipt_session(&session_ids, &ipt_sess) < 0) {
  644. return -1;
  645. }
  646. if (parse_sdp_content(msg, &sdp_sess) < 0)
  647. return -1;
  648. if (ipt_sess.stream_count != sdp_sess.media_count) {
  649. ERR(MODULE_NAME": rtpproxy_update: number of m= item in offer (%d) and answer (%d) do not correspond\n", ipt_sess.stream_count, sdp_sess.media_count);
  650. return -1;
  651. }
  652. /* first we check for unexpected duplicate source ports */
  653. for (i = 0; i < sdp_sess.media_count; i++) {
  654. if (ipt_sess.streams[i].sess_id >= 0 && sdp_sess.media[i].active) {
  655. int j;
  656. for (j = i+1; j < sdp_sess.media_count; j++) {
  657. if (ipt_sess.streams[j].sess_id >= 0 && sdp_sess.media[j].active) {
  658. /* if two media streams have equal source address XOR have equal session */
  659. if ( (sdp_sess.media[i].ip == sdp_sess.media[j].ip && sdp_sess.media[i].port == sdp_sess.media[j].port) ^
  660. (ipt_sess.streams[i].sess_id == ipt_sess.streams[j].sess_id) ) {
  661. ERR(MODULE_NAME": rtpproxy_update: media (%d,%d) violation number\n", i, j);
  662. return -1;
  663. }
  664. }
  665. }
  666. }
  667. }
  668. memset(&in_session, 0, sizeof(in_session));
  669. for (i = 0; i < sdp_sess.media_count; i++) {
  670. if (ipt_sess.streams[i].sess_id >= 0) {
  671. in_sess_id.sess_id_min = ipt_sess.streams[i].sess_id;
  672. in_sess_id.created = ipt_sess.streams[i].created;
  673. in_sess_id.sess_id_max = in_sess_id.sess_id_min;
  674. if (sdp_sess.media[i].active) {
  675. fill_in_session(flags, i, &sdp_sess, &ipt_sess, &in_session);
  676. if (xt_RTPPROXY_update_session(&handle, &ipt_sess.switchboard->in_switchboard, &in_sess_id, &in_session) < 0) {
  677. ERR(MODULE_NAME": rtpproxy_alloc: xt_RTPPROXY_update_session error: %s (%d)\n", handle.err_str, handle.err_no);
  678. /* delete all sessions ? */
  679. return -1;
  680. }
  681. /* we don't know proxy port - it was known when being allocated so we got from switchboard - it's not too clear solution because it requires knowledge how ports are allocated */
  682. ipt_sess.streams[i].proxy_port = ipt_sess.switchboard->in_switchboard.gate[!GATE_A_TO_B(flags)].port + 2*ipt_sess.streams[i].sess_id;
  683. }
  684. else {
  685. /* can we delete any session allocated during offer? */
  686. if (xt_RTPPROXY_delete_session(&handle, &ipt_sess.switchboard->in_switchboard, &in_sess_id) < 0) {
  687. ERR(MODULE_NAME": rtpproxy_update: xt_RTPPROXY_delete_session error: %s (%d)\n", handle.err_str, handle.err_no);
  688. }
  689. ipt_sess.streams[i].sess_id = -1;
  690. }
  691. }
  692. }
  693. if (update_sdp_content(msg, GATE_A_TO_B(flags), &sdp_sess, &ipt_sess) < 0) {
  694. /* delete all sessions ? */
  695. return -1;
  696. }
  697. serialize_ipt_session(&ipt_sess, &session_ids);
  698. global_session_ids = session_ids.s; /* it's static and null terminated */
  699. return 1;
  700. }
  701. static int rtpproxy_adjust_timeout(struct sip_msg* msg, char* _flags, char* _session_ids) {
  702. str session_ids;
  703. int flags, i;
  704. struct ipt_session ipt_sess;
  705. struct xt_rtpproxy_sockopt_in_sess_id in_sess_id;
  706. struct xt_rtpproxy_sockopt_in_alloc_session in_session;
  707. if (get_int_fparam(&flags, msg, (fparam_t*) _flags) < 0) {
  708. return -1;
  709. }
  710. if (get_str_fparam(&session_ids, msg, (fparam_t*) _session_ids) < 0) {
  711. return -1;
  712. }
  713. if (unserialize_ipt_session(&session_ids, &ipt_sess) < 0) {
  714. return -1;
  715. }
  716. memset(&in_session, 0, sizeof(in_session));
  717. for (i = 0; i < ipt_sess.stream_count; i++) {
  718. if (ipt_sess.streams[i].sess_id >= 0) {
  719. int j;
  720. in_sess_id.sess_id_min = ipt_sess.streams[i].sess_id;
  721. in_sess_id.created = ipt_sess.streams[i].created;
  722. in_sess_id.sess_id_max = in_sess_id.sess_id_min;
  723. for (j=0; j<2; j++) {
  724. in_session.source[GATE_A_TO_B(flags)].stream[j].flags =
  725. (flags & RINGING_TIMEOUT_FLAG) ?
  726. XT_RTPPROXY_SOCKOPT_FLAG_SESSION_LEARNING_TIMEOUT :
  727. (ipt_sess.switchboard->in_session.source[GATE_A_TO_B(flags)].stream[j].flags & XT_RTPPROXY_SOCKOPT_FLAG_SESSION_LEARNING_TIMEOUT)
  728. ;
  729. in_session.source[GATE_A_TO_B(flags)].stream[j].learning_timeout = (flags & RINGING_TIMEOUT_FLAG) ?
  730. ipt_sess.switchboard->ringing_timeout :
  731. ipt_sess.switchboard->in_session.source[GATE_A_TO_B(flags)].stream[j].learning_timeout;
  732. }
  733. if (xt_RTPPROXY_update_session(&handle, &ipt_sess.switchboard->in_switchboard, &in_sess_id, &in_session) < 0) {
  734. ERR(MODULE_NAME": rtpproxy_alloc: xt_RTPPROXY_adjust_timeout error: %s (%d)\n", handle.err_str, handle.err_no);
  735. return -1;
  736. }
  737. }
  738. }
  739. /* do not serialize sessions because it affect static buffer and more valuable values disappears */
  740. return 1;
  741. }
  742. static int rtpproxy_delete(struct sip_msg* msg, char* _session_ids, char* dummy) {
  743. str session_ids;
  744. struct ipt_session ipt_sess;
  745. if (get_str_fparam(&session_ids, msg, (fparam_t*) _session_ids) < 0) {
  746. return -1;
  747. }
  748. if (unserialize_ipt_session(&session_ids, &ipt_sess) < 0) {
  749. return -1;
  750. }
  751. delete_ipt_sessions(&ipt_sess);
  752. /* do not serialize sessions because it affect static buffer and more valuable values disappears */
  753. return 1;
  754. }
  755. static int rtpproxy_find(struct sip_msg* msg, char* _gate_a, char* _gate_b) {
  756. unsigned int ip_a, ip_b;
  757. str gate_a, gate_b;
  758. if (get_str_fparam(&gate_a, msg, (fparam_t*) _gate_a) < 0) {
  759. return -1;
  760. }
  761. ip_a = s2ip4(&gate_a);
  762. if (get_str_fparam(&gate_b, msg, (fparam_t*) _gate_b) < 0) {
  763. return -1;
  764. }
  765. ip_b = s2ip4(&gate_b);
  766. found_direction = -1;
  767. for (found_switchboard = switchboards; found_switchboard; found_switchboard=found_switchboard->next) {
  768. if (ip_a == found_switchboard->in_switchboard.gate[0].ip) {
  769. if (ip_b == found_switchboard->in_switchboard.gate[1].ip) {
  770. found_direction = 1;
  771. return 1;
  772. break;
  773. }
  774. }
  775. else if (ip_a == found_switchboard->in_switchboard.gate[1].ip) {
  776. if (ip_b == found_switchboard->in_switchboard.gate[0].ip) {
  777. found_direction = 0;
  778. return 1;
  779. }
  780. }
  781. }
  782. return -1;
  783. }
  784. /* @select implementation */
  785. static int sel_rtpproxy(str* res, select_t* s, struct sip_msg* msg) { /* dummy */
  786. return 0;
  787. }
  788. static int sel_sdp_ip(str* res, select_t* s, struct sip_msg* msg) {
  789. *res = sdp_ip;
  790. return 0;
  791. }
  792. static int sel_session_ids(str* res, select_t* s, struct sip_msg* msg) {
  793. if (!global_session_ids)
  794. return 1;
  795. res->s = global_session_ids;
  796. res->len = strlen(res->s);
  797. return 0;
  798. }
  799. static int sel_switchboard(str* res, select_t* s, struct sip_msg* msg) {
  800. if (!found_switchboard)
  801. return 1;
  802. *res = found_switchboard->name;
  803. return 0;
  804. }
  805. static int sel_direction(str* res, select_t* s, struct sip_msg* msg) {
  806. static char buf[2] = {'0', '1'};
  807. if (!found_direction < 0)
  808. return 1;
  809. res->s = buf+found_direction;
  810. res->len = 1;
  811. return 0;
  812. }
  813. select_row_t sel_declaration[] = {
  814. { NULL, SEL_PARAM_STR, STR_STATIC_INIT(MODULE_NAME), sel_rtpproxy, SEL_PARAM_EXPECTED},
  815. { sel_rtpproxy, SEL_PARAM_STR, STR_STATIC_INIT("sdp_ip"), sel_sdp_ip, 0 },
  816. { sel_rtpproxy, SEL_PARAM_STR, STR_STATIC_INIT("session_ids"), sel_session_ids, 0 },
  817. { sel_rtpproxy, SEL_PARAM_STR, STR_STATIC_INIT("switchboard"), sel_switchboard, 0 },
  818. { sel_rtpproxy, SEL_PARAM_STR, STR_STATIC_INIT("direction"), sel_direction, 0 },
  819. { NULL, SEL_PARAM_INT, STR_NULL, NULL, 0}
  820. };
  821. static int mod_pre_script_cb(struct sip_msg *msg, unsigned int flags, void *param) {
  822. sdp_ip.s = "";
  823. sdp_ip.len = 0;
  824. found_switchboard = NULL;
  825. found_direction = -1;
  826. global_session_ids = NULL;
  827. return 1;
  828. }
  829. static struct {
  830. int flag;
  831. struct switchboard_item *si;
  832. struct xt_rtpproxy_sockopt_in_switchboard in_switchboard;
  833. } parse_config_vals;
  834. int cfg_parse_addr_port(void* param, cfg_parser_t* st, unsigned int flags) {
  835. struct xt_rtpproxy_sockopt_in_switchboard *sw;
  836. int i, ret;
  837. cfg_token_t t;
  838. ret = cfg_get_token(&t, st, 0);
  839. if (ret < 0) return ret;
  840. if (ret > 0) return 0;
  841. if (t.type != '-') return 0;
  842. ret = cfg_get_token(&t, st, 0);
  843. if (ret < 0) return ret;
  844. if (ret > 0) return 0;
  845. if (parse_config_vals.flag == 1) {
  846. sw = &parse_config_vals.in_switchboard;
  847. }
  848. else {
  849. sw = &parse_config_vals.si->in_switchboard;
  850. }
  851. if (t.type == CFG_TOKEN_ALPHA && t.val.len == 1) {
  852. switch (t.val.s[0]) {
  853. case 'a':
  854. case 'b':
  855. i = t.val.s[0]-'a';
  856. ret = cfg_get_token(&t, st, 0);
  857. if (ret < 0) return ret;
  858. if (ret > 0) return 0;
  859. if (t.type != '=') break;
  860. if (param == NULL) {
  861. str val;
  862. char buff[50];
  863. val.s = buff;
  864. val.len = sizeof(buff)-1;
  865. if (cfg_parse_str(&val, st, CFG_STR_STATIC|CFG_EXTENDED_ALPHA) < 0) return -1;
  866. sw->gate[i].ip = s2ip4(&val);
  867. if (sw->gate[i].ip == 0) {
  868. ERR(MODULE_NAME": parse_switchboard_section: bad ip address '%.*s'\n", val.len, val.s);
  869. return -1;
  870. }
  871. }
  872. else {
  873. int val;
  874. if (cfg_parse_int(&val, st, 0) < 0)
  875. return -1;
  876. sw->gate[i].port = val;
  877. }
  878. break;
  879. default:;
  880. }
  881. }
  882. return 0;
  883. }
  884. int cfg_parse_dummy(void* param, cfg_parser_t* st, unsigned int flags) {
  885. int ret;
  886. cfg_token_t t;
  887. str val;
  888. do {
  889. ret = cfg_get_token(&t, st, 0);
  890. if (ret < 0) return ret;
  891. if (ret > 0) return 0;
  892. }
  893. while (t.type != '=');
  894. if (cfg_parse_str(&val, st, CFG_EXTENDED_ALPHA) < 0) return -1;
  895. return 0;
  896. }
  897. static cfg_option_t section_options[] = {
  898. {"addr", .f = cfg_parse_addr_port, .flags = CFG_PREFIX|CFG_CASE_SENSITIVE, .param = NULL},
  899. {"port", .f = cfg_parse_addr_port, .flags = CFG_PREFIX|CFG_CASE_SENSITIVE, .param = (void*) 1},
  900. {NULL, .flags = CFG_DEFAULT, .f = cfg_parse_dummy},
  901. };
  902. #define DEFAULT_SECTION "default"
  903. #define SWITCHBOARD_PREFIX "switchboard"
  904. static int parse_switchboard_section(void* param, cfg_parser_t* st, unsigned int flags) {
  905. str name;
  906. cfg_token_t t;
  907. int ret, fl;
  908. parse_config_vals.flag = 0;
  909. ret = cfg_get_token(&t, st, 0);
  910. if (ret != 0) return ret;
  911. if (t.type != CFG_TOKEN_ALPHA)
  912. goto skip;
  913. if (t.val.len == (sizeof(DEFAULT_SECTION)-1) && strncmp(t.val.s, DEFAULT_SECTION, t.val.len) == 0)
  914. fl = 1;
  915. else if (t.val.len == (sizeof(SWITCHBOARD_PREFIX)-1) && strncmp(t.val.s, SWITCHBOARD_PREFIX, t.val.len) == 0)
  916. fl = 2;
  917. else
  918. goto skip;
  919. ret = cfg_get_token(&t, st, 0);
  920. if (ret != 0) return ret;
  921. if (t.type != ':')
  922. goto skip;
  923. name.s = NULL; name.len = 0;
  924. ret = cfg_parse_section(&name, st, CFG_STR_PKGMEM);
  925. if (ret != 0) return ret;
  926. if (fl==1 && name.len == (sizeof(SWITCHBOARD_PREFIX)-1) && strncmp(name.s, SWITCHBOARD_PREFIX, name.len) == 0) {
  927. parse_config_vals.flag = 1;
  928. if (name.s)
  929. pkg_free(name.s);
  930. }
  931. else if (fl == 2) {
  932. int i;
  933. if (find_switchboard(&name)) {
  934. ERR(MODULE_NAME": parse_switchboard_section: name '%.*s' already declared\n", name.len, name.s);
  935. return -1;
  936. }
  937. for (i=0; i<name.len; i++) {
  938. if (!is_alpha(name.s[i])) {
  939. ERR(MODULE_NAME": parse_switchboard_section: bad section name '%.*s'\n", name.len, name.s);
  940. return -1;
  941. }
  942. }
  943. if (name.len > MAX_SWITCHBOARD_NAME_LEN) {
  944. ERR(MODULE_NAME": parse_switchboard_section: name '%.*s' is too long (%d>%d)\n", name.len, name.s, name.len, MAX_SWITCHBOARD_NAME_LEN);
  945. return -1;
  946. }
  947. parse_config_vals.si = pkg_malloc(sizeof(*parse_config_vals.si));
  948. if (!parse_config_vals.si) {
  949. ERR(MODULE_NAME": parse_switchboard_section: not enough pkg memory\n");
  950. return -1;
  951. }
  952. memset(parse_config_vals.si, 0, sizeof(*parse_config_vals.si));
  953. parse_config_vals.si->name = name;
  954. parse_config_vals.si->ringing_timeout = 60;
  955. parse_config_vals.si->next = switchboards;
  956. switchboards = parse_config_vals.si;
  957. parse_config_vals.flag = 2;
  958. }
  959. return 0;
  960. skip:
  961. while (t.type != ']') {
  962. ret = cfg_get_token(&t, st, 0);
  963. if (ret != 0) return ret;
  964. }
  965. return cfg_eat_eol(st, 0);
  966. }
  967. static int parse_iptrtpproxy_cfg() {
  968. cfg_parser_t* parser = NULL;
  969. struct switchboard_item *si;
  970. if ((parser = cfg_parser_init(&iptrtpproxy_cfg_filename)) == NULL) {
  971. ERR(MODULE_NAME"parse_iptrtpproxy_cfg: Error while initializing configuration file parser.\n");
  972. return -1;
  973. }
  974. cfg_section_parser(parser, parse_switchboard_section, NULL);
  975. cfg_set_options(parser, section_options);
  976. memset(&parse_config_vals, 0, sizeof(parse_config_vals));
  977. if (cfg_parse(parser)) {
  978. return -1;
  979. }
  980. cfg_parser_close(parser);
  981. for (si = switchboards; si; si = si->next) {
  982. int i;
  983. for (i=0; i<2; i++) {
  984. if (!si->in_switchboard.gate[i].ip)
  985. si->in_switchboard.gate[i].ip = parse_config_vals.in_switchboard.gate[i].ip;
  986. if (!si->in_switchboard.gate[i].port)
  987. si->in_switchboard.gate[i].port = parse_config_vals.in_switchboard.gate[i].port;
  988. }
  989. for (i=0; i<2; i++) {
  990. if (!si->in_switchboard.gate[i^1].ip)
  991. si->in_switchboard.gate[i^1].ip = si->in_switchboard.gate[i].ip;
  992. if (!si->in_switchboard.gate[i^1].port)
  993. si->in_switchboard.gate[i^1].port = si->in_switchboard.gate[i].port;
  994. }
  995. }
  996. return 0;
  997. }
  998. /* module initialization */
  999. static int mod_init(void) {
  1000. struct switchboard_item *si;
  1001. int i;
  1002. if (iptrtpproxy_cfg_flag == 0) {
  1003. if (parse_iptrtpproxy_cfg() < 0)
  1004. return E_CFG;
  1005. }
  1006. for (si = switchboards; si; si=si->next) {
  1007. str ips[2];
  1008. char buf[17];
  1009. ip42s(si->in_switchboard.gate[0].ip, ips+0);
  1010. strncpy(buf, ips[0].s, sizeof(buf)-1);
  1011. ips[0].s = buf;
  1012. ip42s(si->in_switchboard.gate[1].ip, ips+1);
  1013. DBG(MODULE_NAME": mod_init: name=%.*s;addr-a=%.*s;port-a=%d;addr-b=%.*s;port-b=%d;learning-timeout-a=%d;learning-timeout-b=%d;always-learn-a=%d;always-learn-b=%d;ringing-timeout=%d\n",
  1014. STR_FMT(&si->name),
  1015. STR_FMT(ips+0),
  1016. si->in_switchboard.gate[0].port,
  1017. STR_FMT(ips+1),
  1018. si->in_switchboard.gate[1].port,
  1019. si->in_session.source[0].stream[0].learning_timeout,
  1020. si->in_session.source[1].stream[0].learning_timeout,
  1021. si->in_session.source[0].always_learn,
  1022. si->in_session.source[1].always_learn,
  1023. si->ringing_timeout
  1024. );
  1025. }
  1026. if (xt_RTPPROXY_open(&handle) < 0) goto err;
  1027. for (si = switchboards; si; si=si->next) {
  1028. struct xt_rtpproxy_switchboard *out_switchboard;
  1029. if (xt_RTPPROXY_get_switchboards(&handle, &si->in_switchboard, NULL, XT_RTPPROXY_SOCKOPT_FLAG_OUT_SWITCHBOARD, &out_switchboard) < 0) {
  1030. goto err;
  1031. }
  1032. /* update switchboard info, we need real ports for rtpproxy_update, it may sometimes differ from in_switchboard when addr-a=addr-b. We'll take first switchboard returned, should be always only one */
  1033. if (!out_switchboard) {
  1034. ERR(MODULE_NAME": switchboard '%.*s' not found in iptables\n", si->name.len, si->name.s);
  1035. goto err2;
  1036. }
  1037. if (si->in_switchboard.gate[0].ip == si->in_switchboard.gate[1].ip) {
  1038. for (i=0; i<XT_RTPPROXY_MAX_GATE; i++) {
  1039. si->in_switchboard.gate[i].port = out_switchboard->so.gate[i].addr.port;
  1040. }
  1041. }
  1042. xt_RTPPROXY_release_switchboards(&handle, out_switchboard);
  1043. }
  1044. register_script_cb(mod_pre_script_cb, REQUEST_CB | ONREPLY_CB | PRE_SCRIPT_CB, 0);
  1045. register_select_table(sel_declaration);
  1046. return 0;
  1047. err:
  1048. ERR(MODULE_NAME": %s (%d)\n", handle.err_str, handle.err_no);
  1049. err2:
  1050. if (handle.sockfd >= 0) {
  1051. xt_RTPPROXY_close(&handle);
  1052. }
  1053. return -1;
  1054. }
  1055. static void mod_cleanup(void) {
  1056. if (handle.sockfd >= 0) {
  1057. xt_RTPPROXY_close(&handle);
  1058. }
  1059. }
  1060. static int child_init(int rank) {
  1061. return 0;
  1062. }
  1063. #define eat_spaces(_p) \
  1064. while( *(_p)==' ' || *(_p)=='\t' ){\
  1065. (_p)++;}
  1066. static int declare_config(modparam_t type, void* val) {
  1067. if (!val) return 0;
  1068. if (iptrtpproxy_cfg_flag == 0) {
  1069. iptrtpproxy_cfg_flag = 1;
  1070. iptrtpproxy_cfg_filename = * (str*) val;
  1071. if (parse_iptrtpproxy_cfg() == 0)
  1072. return 0;
  1073. }
  1074. else {
  1075. switch (iptrtpproxy_cfg_flag) {
  1076. case 1:
  1077. ERR(MODULE_NAME": declare_config: config param may be used only once\n");
  1078. break;
  1079. case 2:
  1080. ERR(MODULE_NAME": declare_config: config param may not be used after 'switchboard'\n");
  1081. break;
  1082. default:
  1083. BUG(MODULE_NAME": declare_config: unexpected 'iptrtpproxy_cfg_filename' value %d\n", iptrtpproxy_cfg_flag);
  1084. }
  1085. }
  1086. return E_CFG;
  1087. }
  1088. static int declare_switchboard_param(modparam_t type, void* val) {
  1089. char *s, *c;
  1090. int i, all_flag;
  1091. struct switchboard_item *si = NULL;
  1092. enum param_id {
  1093. par_GateB = 8,
  1094. par_Name = 0x000001,
  1095. par_RingingTimeout = 0x000002,
  1096. par_AlwaysLearn = 0x000400,
  1097. par_LearningTimeout = 0x000800
  1098. };
  1099. #define IS_GATE_B(id) ((id & 0xFF0000)!=0)
  1100. static struct {
  1101. char *name;
  1102. unsigned int id;
  1103. } params[] = {
  1104. {.name = "name", .id = par_Name},
  1105. {.name = "always-learn-a", .id = par_AlwaysLearn},
  1106. {.name = "always-learn-b", .id = par_AlwaysLearn << par_GateB},
  1107. {.name = "learning-timeout-a", .id = par_LearningTimeout},
  1108. {.name = "learning-timeout-b", .id = par_LearningTimeout << par_GateB},
  1109. {.name = "ringing-timeout", .id = par_RingingTimeout},
  1110. {.name = 0, .id = 0}
  1111. };
  1112. if (!val) return 0;
  1113. if (iptrtpproxy_cfg_flag == 0) {
  1114. iptrtpproxy_cfg_flag = 2;
  1115. if (parse_iptrtpproxy_cfg() < 0)
  1116. return E_CFG;
  1117. }
  1118. s = val;
  1119. all_flag = -1;
  1120. eat_spaces(s);
  1121. if (!*s) return 0;
  1122. /* parse param: name=;addr-a=;addr-b=;port-a=;port-b=; */
  1123. while (*s) {
  1124. str p, val;
  1125. unsigned int id;
  1126. c = s;
  1127. while ( is_alpha(*c) ) {
  1128. c++;
  1129. }
  1130. if (c == s) {
  1131. ERR(MODULE_NAME": declare_switchboard_param: param name expected near '%s'\n", s);
  1132. goto err_E_CFG;
  1133. }
  1134. p.s = s;
  1135. p.len = c-s;
  1136. eat_spaces(c);
  1137. s = c;
  1138. if (*c != '=') {
  1139. ERR(MODULE_NAME": declare_switchboard_param: equal char expected near '%s'\n", s);
  1140. goto err_E_CFG;
  1141. }
  1142. c++;
  1143. eat_spaces(c);
  1144. s = c;
  1145. while (*c && *c != ';') c++;
  1146. val.s = s;
  1147. val.len = c-s;
  1148. while (val.len > 0 && val.s[val.len-1]<=' ') val.len--;
  1149. if (*c) c++;
  1150. eat_spaces(c);
  1151. id = 0;
  1152. for (i=0; params[i].id; i++) {
  1153. if (strlen(params[i].name)==p.len && strncasecmp(params[i].name, p.s, p.len) == 0) {
  1154. id = params[i].id;
  1155. break;
  1156. }
  1157. }
  1158. if (!id) {
  1159. ERR(MODULE_NAME": declare_switchboard_param: unknown param name '%.*s'\n", p.len, p.s);
  1160. goto err_E_CFG;
  1161. }
  1162. if (all_flag >= 0 && id == par_Name) {
  1163. ERR(MODULE_NAME": declare_switchboard_param: name must be the first param\n");
  1164. goto err_E_CFG;
  1165. }
  1166. if (id == par_Name) {
  1167. all_flag = 0;
  1168. si = find_switchboard(&val);
  1169. if (!si) {
  1170. if (val.len == 1 && val.s[0] == '*')
  1171. all_flag = 1;
  1172. else {
  1173. ERR(MODULE_NAME": declare_switchboard_param: switchboard '%.*s' not found\n", val.len, val.s);
  1174. goto err_E_CFG;
  1175. }
  1176. }
  1177. }
  1178. else {
  1179. if (all_flag)
  1180. si = switchboards;
  1181. while (si) {
  1182. switch (id) {
  1183. case par_Name:
  1184. break;
  1185. case par_AlwaysLearn:
  1186. case par_AlwaysLearn << par_GateB: {
  1187. unsigned int u;
  1188. if (str2int(&val, &u) < 0) {
  1189. goto err_E_CFG;
  1190. }
  1191. si->in_session.source[IS_GATE_B(id)].always_learn = u != 0;
  1192. break;
  1193. }
  1194. case par_LearningTimeout:
  1195. case par_LearningTimeout << par_GateB: {
  1196. unsigned int u;
  1197. if (str2int(&val, &u) < 0) {
  1198. goto err_E_CFG;
  1199. }
  1200. if (u) {
  1201. for (i=0; i<2; i++) {
  1202. si->in_session.source[IS_GATE_B(id)].stream[i].learning_timeout = u;
  1203. si->in_session.source[IS_GATE_B(id)].stream[i].flags = XT_RTPPROXY_SOCKOPT_FLAG_SESSION_LEARNING_TIMEOUT;
  1204. }
  1205. }
  1206. break;
  1207. }
  1208. case par_RingingTimeout: {
  1209. unsigned int u;
  1210. if (str2int(&val, &u) < 0) {
  1211. goto err_E_CFG;
  1212. }
  1213. if (u) {
  1214. si->ringing_timeout = u;
  1215. }
  1216. break;
  1217. }
  1218. default:
  1219. BUG(MODULE_NAME": declare_switchboard_param: unknown id '%x\n", id);
  1220. goto err_E_CFG;
  1221. }
  1222. si->param_ids |= id;
  1223. if (!all_flag) break;
  1224. si = si->next;
  1225. }
  1226. }
  1227. s = c;
  1228. }
  1229. if (all_flag) {
  1230. return 0;
  1231. }
  1232. #define DEF_PARAMS(_id,_s,_fld) \
  1233. if ( (si->param_ids & (_id)) && !(si->param_ids & ((_id) << par_GateB)) ) \
  1234. si->_s[1]._fld = si->_s[0]._fld; \
  1235. if ( !(si->param_ids & (_id)) && (si->param_ids & ((_id) << par_GateB)) ) \
  1236. si->_s[0]._fld = si->_s[1]._fld;
  1237. DEF_PARAMS(par_AlwaysLearn,in_session.source,always_learn);
  1238. for (i=0; i<2; i++) {
  1239. DEF_PARAMS(par_LearningTimeout,in_session.source,stream[i].learning_timeout);
  1240. DEF_PARAMS(par_LearningTimeout,in_session.source,stream[i].flags);
  1241. }
  1242. switchboard_count++;
  1243. return 0;
  1244. err_E_CFG:
  1245. ERR(MODULE_NAME": declare_switchboard_param(#%d): parse error near \"%s\"\n", switchboard_count, s);
  1246. return E_CFG;
  1247. }
  1248. static cmd_export_t cmds[] = {
  1249. {MODULE_NAME "_alloc", rtpproxy_alloc, 2, rtpproxy_alloc_fixup, REQUEST_ROUTE | ONREPLY_ROUTE },
  1250. {MODULE_NAME "_update", rtpproxy_update, 2, rtpproxy_update_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE },
  1251. {MODULE_NAME "_adjust_timeout", rtpproxy_adjust_timeout, 2, rtpproxy_update_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE },
  1252. {MODULE_NAME "_delete", rtpproxy_delete, 1, rtpproxy_delete_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE },
  1253. {MODULE_NAME "_find", rtpproxy_find, 2, rtpproxy_find_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE },
  1254. {0, 0, 0, 0, 0}
  1255. };
  1256. static param_export_t params[] = {
  1257. {"config", PARAM_STR | PARAM_USE_FUNC, &declare_config},
  1258. {"switchboard", PARAM_STRING | PARAM_USE_FUNC, &declare_switchboard_param},
  1259. {0, 0, 0}
  1260. };
  1261. struct module_exports exports = {
  1262. MODULE_NAME,
  1263. cmds,
  1264. 0, /* RPC methods */
  1265. params,
  1266. mod_init,
  1267. 0, /* reply processing */
  1268. mod_cleanup, /* destroy function */
  1269. 0, /* on_break */
  1270. child_init
  1271. };
  1272. #if !defined(NO_SHARED_LIBS) || NO_SHARED_LIBS==0
  1273. /* make compiler happy and give it missing symbols */
  1274. #include <iptables.h>
  1275. #include <stdarg.h>
  1276. void xtables_register_target(struct xtables_target *me) {
  1277. }
  1278. void exit_error(enum exittype status, const char *msg, ...)
  1279. {
  1280. va_list args;
  1281. va_start(args, msg);
  1282. // ERR(msg/*, args*/); /* TODO: how to pass ... to macro? */
  1283. ERR(MODULE_NAME": %s", msg);
  1284. va_end(args);
  1285. }
  1286. #ifndef TRUE
  1287. #define TRUE 1
  1288. #endif
  1289. #ifndef FALSE
  1290. #define FALSE 0
  1291. #endif
  1292. int check_inverse(const char option[], int *invert, int *optind, int argc)
  1293. {
  1294. if (option && strcmp(option, "!") == 0) {
  1295. if (*invert)
  1296. exit_error(PARAMETER_PROBLEM, "Multiple `!' flags not allowed");
  1297. *invert = TRUE;
  1298. if (optind) {
  1299. *optind = *optind+1;
  1300. if (argc && *optind > argc)
  1301. exit_error(PARAMETER_PROBLEM, "no argument following `!'");
  1302. }
  1303. return TRUE;
  1304. }
  1305. return FALSE;
  1306. }
  1307. #endif