config_transport.c 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 2013, Digium, Inc.
  5. *
  6. * Joshua Colp <jcolp@digium.com>
  7. *
  8. * See http://www.asterisk.org for more information about
  9. * the Asterisk project. Please do not directly contact
  10. * any of the maintainers of this project for assistance;
  11. * the project provides a web site, mailing lists and IRC
  12. * channels for your use.
  13. *
  14. * This program is free software, distributed under the terms of
  15. * the GNU General Public License Version 2. See the LICENSE file
  16. * at the top of the source tree.
  17. */
  18. #include "asterisk.h"
  19. #include <math.h>
  20. #include <pjsip.h>
  21. #include <pjlib.h>
  22. #include "asterisk/res_pjsip.h"
  23. #include "asterisk/res_pjsip_cli.h"
  24. #include "asterisk/logger.h"
  25. #include "asterisk/astobj2.h"
  26. #include "asterisk/sorcery.h"
  27. #include "asterisk/acl.h"
  28. #include "asterisk/utils.h"
  29. #include "include/res_pjsip_private.h"
  30. #include "asterisk/http_websocket.h"
  31. #define MAX_POINTER_STRING 33
  32. /*! \brief Default number of state container buckets */
  33. #define DEFAULT_STATE_BUCKETS 53
  34. static struct ao2_container *transport_states;
  35. struct internal_state {
  36. char *id;
  37. /*! Set if there was a change detected */
  38. int change_detected;
  39. /*! \brief Transport configuration object */
  40. struct ast_sip_transport *transport;
  41. /*! \brief Transport state information */
  42. struct ast_sip_transport_state *state;
  43. };
  44. static void temp_state_store_cleanup(void *data)
  45. {
  46. struct ast_sip_transport_state **temp_state = data;
  47. ao2_cleanup(*temp_state);
  48. ast_free(data);
  49. }
  50. AST_THREADSTORAGE_CUSTOM(temp_state_store, NULL, temp_state_store_cleanup);
  51. /*! \brief hashing function for state objects */
  52. static int internal_state_hash(const void *obj, const int flags)
  53. {
  54. const struct internal_state *object;
  55. const char *key;
  56. switch (flags & OBJ_SEARCH_MASK) {
  57. case OBJ_SEARCH_KEY:
  58. key = obj;
  59. break;
  60. case OBJ_SEARCH_OBJECT:
  61. object = obj;
  62. key = object->id;
  63. break;
  64. default:
  65. ast_assert(0);
  66. return 0;
  67. }
  68. return ast_str_hash(key);
  69. }
  70. /*! \brief comparator function for state objects */
  71. static int internal_state_cmp(void *obj, void *arg, int flags)
  72. {
  73. const struct internal_state *object_left = obj;
  74. const struct internal_state *object_right = arg;
  75. const char *right_key = arg;
  76. int cmp;
  77. switch (flags & OBJ_SEARCH_MASK) {
  78. case OBJ_SEARCH_OBJECT:
  79. right_key = object_right->id;
  80. /* Fall through */
  81. case OBJ_SEARCH_KEY:
  82. cmp = strcmp(object_left->id, right_key);
  83. break;
  84. case OBJ_SEARCH_PARTIAL_KEY:
  85. /* Not supported by container. */
  86. ast_assert(0);
  87. return 0;
  88. default:
  89. cmp = 0;
  90. break;
  91. }
  92. if (cmp) {
  93. return 0;
  94. }
  95. return CMP_MATCH;
  96. }
  97. /*! \brief hashing function for state objects */
  98. static int transport_state_hash(const void *obj, const int flags)
  99. {
  100. const struct ast_sip_transport_state *object;
  101. const char *key;
  102. switch (flags & OBJ_SEARCH_MASK) {
  103. case OBJ_SEARCH_KEY:
  104. key = obj;
  105. break;
  106. case OBJ_SEARCH_OBJECT:
  107. object = obj;
  108. key = object->id;
  109. break;
  110. default:
  111. ast_assert(0);
  112. return 0;
  113. }
  114. return ast_str_hash(key);
  115. }
  116. /*! \brief comparator function for state objects */
  117. static int transport_state_cmp(void *obj, void *arg, int flags)
  118. {
  119. const struct ast_sip_transport_state *object_left = obj;
  120. const struct ast_sip_transport_state *object_right = arg;
  121. const char *right_key = arg;
  122. int cmp;
  123. switch (flags & OBJ_SEARCH_MASK) {
  124. case OBJ_SEARCH_OBJECT:
  125. right_key = object_right->id;
  126. /* Fall through */
  127. case OBJ_SEARCH_KEY:
  128. cmp = strcmp(object_left->id, right_key);
  129. break;
  130. case OBJ_SEARCH_PARTIAL_KEY:
  131. /* Not supported by container. */
  132. ast_assert(0);
  133. return 0;
  134. default:
  135. cmp = 0;
  136. break;
  137. }
  138. if (cmp) {
  139. return 0;
  140. }
  141. return CMP_MATCH;
  142. }
  143. static int sip_transport_to_ami(const struct ast_sip_transport *transport,
  144. struct ast_str **buf)
  145. {
  146. return ast_sip_sorcery_object_to_ami(transport, buf);
  147. }
  148. static int format_ami_endpoint_transport(const struct ast_sip_endpoint *endpoint,
  149. struct ast_sip_ami *ami)
  150. {
  151. RAII_VAR(struct ast_str *, buf, NULL, ast_free);
  152. RAII_VAR(struct ast_sip_transport *, transport, NULL, ao2_cleanup);
  153. if (ast_strlen_zero(endpoint->transport)) {
  154. return 0;
  155. }
  156. buf = ast_sip_create_ami_event("TransportDetail", ami);
  157. if (!buf) {
  158. return -1;
  159. }
  160. transport = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "transport",
  161. endpoint->transport);
  162. if (!transport) {
  163. astman_send_error_va(ami->s, ami->m, "Unable to retrieve "
  164. "transport %s\n", endpoint->transport);
  165. return -1;
  166. }
  167. sip_transport_to_ami(transport, &buf);
  168. ast_str_append(&buf, 0, "EndpointName: %s\r\n",
  169. ast_sorcery_object_get_id(endpoint));
  170. astman_append(ami->s, "%s\r\n", ast_str_buffer(buf));
  171. ami->count++;
  172. return 0;
  173. }
  174. struct ast_sip_endpoint_formatter endpoint_transport_formatter = {
  175. .format_ami = format_ami_endpoint_transport
  176. };
  177. static void set_qos(struct ast_sip_transport *transport, pj_qos_params *qos)
  178. {
  179. int tos_as_dscp = transport->tos >> 2;
  180. if (transport->tos) {
  181. qos->flags |= PJ_QOS_PARAM_HAS_DSCP;
  182. qos->dscp_val = tos_as_dscp;
  183. }
  184. if (transport->cos) {
  185. qos->flags |= PJ_QOS_PARAM_HAS_SO_PRIO;
  186. qos->so_prio = transport->cos;
  187. }
  188. }
  189. /*! \brief Destructor for transport */
  190. static void sip_transport_destroy(void *obj)
  191. {
  192. struct ast_sip_transport *transport = obj;
  193. ast_string_field_free_memory(transport);
  194. }
  195. /*! \brief Allocator for transport */
  196. static void *sip_transport_alloc(const char *name)
  197. {
  198. struct ast_sip_transport *transport = ast_sorcery_generic_alloc(sizeof(*transport), sip_transport_destroy);
  199. if (!transport) {
  200. return NULL;
  201. }
  202. if (ast_string_field_init(transport, 256)) {
  203. ao2_cleanup(transport);
  204. return NULL;
  205. }
  206. return transport;
  207. }
  208. static int destroy_sip_transport_state(void *data)
  209. {
  210. struct ast_sip_transport_state *transport_state = data;
  211. ast_free(transport_state->id);
  212. ast_free_ha(transport_state->localnet);
  213. if (transport_state->external_signaling_address_refresher) {
  214. ast_dnsmgr_release(transport_state->external_signaling_address_refresher);
  215. }
  216. if (transport_state->external_media_address_refresher) {
  217. ast_dnsmgr_release(transport_state->external_media_address_refresher);
  218. }
  219. if (transport_state->transport) {
  220. pjsip_transport_shutdown(transport_state->transport);
  221. }
  222. return 0;
  223. }
  224. /*! \brief Destructor for ast_sip_transport state information */
  225. static void sip_transport_state_destroy(void *obj)
  226. {
  227. struct ast_sip_transport_state *state = obj;
  228. ast_sip_push_task_wait_servant(NULL, destroy_sip_transport_state, state);
  229. }
  230. /*! \brief Destructor for ast_sip_transport state information */
  231. static void internal_state_destroy(void *obj)
  232. {
  233. struct internal_state *state = obj;
  234. ast_free(state->id);
  235. ao2_cleanup(state->transport);
  236. ao2_cleanup(state->state);
  237. }
  238. static struct internal_state *find_internal_state_by_transport(const struct ast_sip_transport *transport)
  239. {
  240. const char *key = ast_sorcery_object_get_id(transport);
  241. return ao2_find(transport_states, key, OBJ_SEARCH_KEY | OBJ_NOLOCK);
  242. }
  243. static struct ast_sip_transport_state *find_state_by_transport(const struct ast_sip_transport *transport)
  244. {
  245. struct internal_state *state;
  246. struct ast_sip_transport_state *trans_state;
  247. state = find_internal_state_by_transport(transport);
  248. if (!state) {
  249. return NULL;
  250. }
  251. trans_state = ao2_bump(state->state);
  252. ao2_ref(state, -1);
  253. return trans_state;
  254. }
  255. static int remove_temporary_state(void)
  256. {
  257. struct ast_sip_transport_state **state;
  258. state = ast_threadstorage_get(&temp_state_store, sizeof(state));
  259. if (!state) {
  260. return -1;
  261. }
  262. ao2_cleanup(*state);
  263. *state = NULL;
  264. return 0;
  265. }
  266. static struct ast_sip_transport_state *find_temporary_state(struct ast_sip_transport *transport)
  267. {
  268. struct ast_sip_transport_state **state;
  269. state = ast_threadstorage_get(&temp_state_store, sizeof(state));
  270. if (state && *state) {
  271. ao2_ref(*state, +1);
  272. return *state;
  273. }
  274. return NULL;
  275. }
  276. static struct internal_state *internal_state_alloc(struct ast_sip_transport *transport)
  277. {
  278. struct internal_state *internal_state;
  279. internal_state = ao2_alloc(sizeof(*internal_state), internal_state_destroy);
  280. if (!internal_state) {
  281. return NULL;
  282. }
  283. internal_state->id = ast_strdup(ast_sorcery_object_get_id(transport));
  284. if (!internal_state->id) {
  285. ao2_cleanup(internal_state);
  286. return NULL;
  287. }
  288. /* We're transferring the reference from find_temporary_state */
  289. internal_state->state = find_temporary_state(transport);
  290. if (!internal_state->state) {
  291. ao2_cleanup(internal_state);
  292. return NULL;
  293. }
  294. internal_state->transport = ao2_bump(transport);
  295. internal_state->transport->state = internal_state->state;
  296. remove_temporary_state();
  297. return internal_state;
  298. }
  299. /*!
  300. * \internal
  301. * \brief Should only be called by the individual field handlers
  302. */
  303. static struct ast_sip_transport_state *find_or_create_temporary_state(struct ast_sip_transport *transport)
  304. {
  305. struct ast_sip_transport_state **state;
  306. struct ast_sip_transport_state *new_state;
  307. if ((new_state = find_temporary_state(transport))) {
  308. return new_state;
  309. }
  310. state = ast_threadstorage_get(&temp_state_store, sizeof(state));
  311. if (!state || *state) {
  312. return NULL;
  313. }
  314. new_state = ao2_alloc(sizeof(**state), sip_transport_state_destroy);
  315. if (!new_state) {
  316. return NULL;
  317. }
  318. new_state->id = ast_strdup(ast_sorcery_object_get_id(transport));
  319. new_state->type = transport->type;
  320. pjsip_tls_setting_default(&new_state->tls);
  321. #ifdef HAVE_PJSIP_TLS_TRANSPORT_PROTO
  322. /* proto must be forced to 0 to enable all protocols otherwise only TLS will work */
  323. new_state->tls.proto = 0;
  324. #endif
  325. new_state->tls.ciphers = new_state->ciphers;
  326. ao2_ref(new_state, +1);
  327. *state = new_state;
  328. return new_state;
  329. }
  330. static void copy_state_to_transport(struct ast_sip_transport *transport)
  331. {
  332. ast_assert(transport && transport->state);
  333. memcpy(&transport->host, &transport->state->host, sizeof(transport->host));
  334. memcpy(&transport->tls, &transport->state->tls, sizeof(transport->tls));
  335. memcpy(&transport->ciphers, &transport->state->ciphers, sizeof(transport->ciphers));
  336. transport->localnet = transport->state->localnet;
  337. transport->external_address_refresher = transport->state->external_signaling_address_refresher;
  338. memcpy(&transport->external_address, &transport->state->external_signaling_address, sizeof(transport->external_signaling_address));
  339. }
  340. static int has_state_changed(struct ast_sip_transport_state *a, struct ast_sip_transport_state *b)
  341. {
  342. if (a->type != b->type) {
  343. return -1;
  344. }
  345. if (pj_sockaddr_cmp(&a->host, &b->host)) {
  346. return -1;
  347. }
  348. if ((a->localnet || b->localnet)
  349. && ((!a->localnet != !b->localnet)
  350. || ast_sockaddr_cmp(&a->localnet->addr, &b->localnet->addr)
  351. || ast_sockaddr_cmp(&a->localnet->netmask, &b->localnet->netmask)))
  352. {
  353. return -1;
  354. }
  355. if (ast_sockaddr_cmp(&a->external_signaling_address, &b->external_signaling_address)) {
  356. return -1;
  357. }
  358. if (ast_sockaddr_cmp(&a->external_media_address, &b->external_media_address)) {
  359. return -1;
  360. }
  361. if (a->tls.method != b->tls.method
  362. || a->tls.ciphers_num != b->tls.ciphers_num
  363. #ifdef HAVE_PJSIP_TLS_TRANSPORT_PROTO
  364. || a->tls.proto != b->tls.proto
  365. #endif
  366. || a->tls.verify_client != b->tls.verify_client
  367. || a->tls.verify_server != b->tls.verify_server
  368. || a->tls.require_client_cert != b->tls.require_client_cert) {
  369. return -1;
  370. }
  371. if (memcmp(a->ciphers, b->ciphers, sizeof(pj_ssl_cipher) * fmax(a->tls.ciphers_num, b->tls.ciphers_num))) {
  372. return -1;
  373. }
  374. return 0;
  375. }
  376. static void states_cleanup(void *states)
  377. {
  378. if (states) {
  379. ao2_unlock(states);
  380. }
  381. }
  382. /*! \brief Apply handler for transports */
  383. static int transport_apply(const struct ast_sorcery *sorcery, void *obj)
  384. {
  385. struct ast_sip_transport *transport = obj;
  386. const char *transport_id = ast_sorcery_object_get_id(obj);
  387. RAII_VAR(struct ao2_container *, states, transport_states, states_cleanup);
  388. RAII_VAR(struct internal_state *, temp_state, NULL, ao2_cleanup);
  389. RAII_VAR(struct internal_state *, perm_state, NULL, ao2_cleanup);
  390. RAII_VAR(struct ast_variable *, changes, NULL, ast_variables_destroy);
  391. pj_status_t res = -1;
  392. int i;
  393. #define BIND_TRIES 3
  394. #define BIND_DELAY_US 100000
  395. if (!states) {
  396. return -1;
  397. }
  398. /*
  399. * transport_apply gets called for EVERY retrieval of a transport when using realtime.
  400. * We need to prevent multiple threads from trying to mess with underlying transports
  401. * at the same time. The container is the only thing we have to lock on.
  402. */
  403. ao2_wrlock(states);
  404. temp_state = internal_state_alloc(transport);
  405. if (!temp_state) {
  406. ast_log(LOG_ERROR, "Transport '%s' failed to allocate memory\n", transport_id);
  407. return -1;
  408. }
  409. perm_state = find_internal_state_by_transport(transport);
  410. if (perm_state) {
  411. ast_sorcery_diff(sorcery, perm_state->transport, transport, &changes);
  412. if (!changes && !has_state_changed(perm_state->state, temp_state->state)) {
  413. /* In case someone is using the deprecated fields, reset them */
  414. transport->state = perm_state->state;
  415. copy_state_to_transport(transport);
  416. ao2_replace(perm_state->transport, transport);
  417. return 0;
  418. }
  419. if (!transport->allow_reload) {
  420. if (!perm_state->change_detected) {
  421. perm_state->change_detected = 1;
  422. ast_log(LOG_WARNING, "Transport '%s' is not reloadable, maintaining previous values\n", transport_id);
  423. }
  424. /* In case someone is using the deprecated fields, reset them */
  425. transport->state = perm_state->state;
  426. copy_state_to_transport(transport);
  427. ao2_replace(perm_state->transport, transport);
  428. return 0;
  429. }
  430. }
  431. if (temp_state->state->host.addr.sa_family != PJ_AF_INET && temp_state->state->host.addr.sa_family != PJ_AF_INET6) {
  432. ast_log(LOG_ERROR, "Transport '%s' could not be started as binding not specified\n", transport_id);
  433. return -1;
  434. }
  435. /* Set default port if not present */
  436. if (!pj_sockaddr_get_port(&temp_state->state->host)) {
  437. pj_sockaddr_set_port(&temp_state->state->host, (transport->type == AST_TRANSPORT_TLS) ? 5061 : 5060);
  438. }
  439. /* Now that we know what address family we can set up a dnsmgr refresh for the external addresses if present */
  440. if (!ast_strlen_zero(transport->external_signaling_address)) {
  441. if (temp_state->state->host.addr.sa_family == pj_AF_INET()) {
  442. temp_state->state->external_signaling_address.ss.ss_family = AF_INET;
  443. } else if (temp_state->state->host.addr.sa_family == pj_AF_INET6()) {
  444. temp_state->state->external_signaling_address.ss.ss_family = AF_INET6;
  445. } else {
  446. ast_log(LOG_ERROR, "Unknown address family for transport '%s', could not get external signaling address\n",
  447. transport_id);
  448. return -1;
  449. }
  450. if (ast_dnsmgr_lookup(transport->external_signaling_address, &temp_state->state->external_signaling_address, &temp_state->state->external_signaling_address_refresher, NULL) < 0) {
  451. ast_log(LOG_ERROR, "Could not create dnsmgr for external signaling address on '%s'\n", transport_id);
  452. return -1;
  453. }
  454. }
  455. if (!ast_strlen_zero(transport->external_media_address)) {
  456. if (temp_state->state->host.addr.sa_family == pj_AF_INET()) {
  457. temp_state->state->external_media_address.ss.ss_family = AF_INET;
  458. } else if (temp_state->state->host.addr.sa_family == pj_AF_INET6()) {
  459. temp_state->state->external_media_address.ss.ss_family = AF_INET6;
  460. } else {
  461. ast_log(LOG_ERROR, "Unknown address family for transport '%s', could not get external media address\n",
  462. transport_id);
  463. return -1;
  464. }
  465. if (ast_dnsmgr_lookup(transport->external_media_address, &temp_state->state->external_media_address, &temp_state->state->external_media_address_refresher, NULL) < 0) {
  466. ast_log(LOG_ERROR, "Could not create dnsmgr for external media address on '%s'\n", transport_id);
  467. return -1;
  468. }
  469. }
  470. if (transport->type == AST_TRANSPORT_UDP) {
  471. for (i = 0; i < BIND_TRIES && res != PJ_SUCCESS; i++) {
  472. if (perm_state && perm_state->state && perm_state->state->transport) {
  473. pjsip_udp_transport_pause(perm_state->state->transport,
  474. PJSIP_UDP_TRANSPORT_DESTROY_SOCKET);
  475. usleep(BIND_DELAY_US);
  476. }
  477. if (temp_state->state->host.addr.sa_family == pj_AF_INET()) {
  478. res = pjsip_udp_transport_start(ast_sip_get_pjsip_endpoint(),
  479. &temp_state->state->host.ipv4, NULL, transport->async_operations,
  480. &temp_state->state->transport);
  481. } else if (temp_state->state->host.addr.sa_family == pj_AF_INET6()) {
  482. res = pjsip_udp_transport_start6(ast_sip_get_pjsip_endpoint(),
  483. &temp_state->state->host.ipv6, NULL, transport->async_operations,
  484. &temp_state->state->transport);
  485. }
  486. }
  487. if (res == PJ_SUCCESS) {
  488. temp_state->state->transport->info = pj_pool_alloc(temp_state->state->transport->pool,
  489. (AST_SIP_X_AST_TXP_LEN + strlen(transport_id) + 2));
  490. sprintf(temp_state->state->transport->info, "%s:%s", AST_SIP_X_AST_TXP, transport_id);
  491. if (transport->tos || transport->cos) {
  492. pj_sock_t sock;
  493. pj_qos_params qos_params;
  494. sock = pjsip_udp_transport_get_socket(temp_state->state->transport);
  495. pj_sock_get_qos_params(sock, &qos_params);
  496. set_qos(transport, &qos_params);
  497. pj_sock_set_qos_params(sock, &qos_params);
  498. }
  499. }
  500. } else if (transport->type == AST_TRANSPORT_TCP) {
  501. pjsip_tcp_transport_cfg cfg;
  502. static int option = 1;
  503. pjsip_tcp_transport_cfg_default(&cfg, temp_state->state->host.addr.sa_family);
  504. cfg.bind_addr = temp_state->state->host;
  505. cfg.async_cnt = transport->async_operations;
  506. set_qos(transport, &cfg.qos_params);
  507. /* sockopt_params.options is copied to each newly connected socket */
  508. cfg.sockopt_params.options[0].level = pj_SOL_TCP();
  509. cfg.sockopt_params.options[0].optname = pj_TCP_NODELAY();
  510. cfg.sockopt_params.options[0].optval = &option;
  511. cfg.sockopt_params.options[0].optlen = sizeof(option);
  512. cfg.sockopt_params.cnt = 1;
  513. for (i = 0; i < BIND_TRIES && res != PJ_SUCCESS; i++) {
  514. if (perm_state && perm_state->state && perm_state->state->factory
  515. && perm_state->state->factory->destroy) {
  516. perm_state->state->factory->destroy(perm_state->state->factory);
  517. usleep(BIND_DELAY_US);
  518. }
  519. res = pjsip_tcp_transport_start3(ast_sip_get_pjsip_endpoint(), &cfg,
  520. &temp_state->state->factory);
  521. }
  522. } else if (transport->type == AST_TRANSPORT_TLS) {
  523. static int option = 1;
  524. if (transport->async_operations > 1 && ast_compare_versions(pj_get_version(), "2.5.0") < 0) {
  525. ast_log(LOG_ERROR, "Transport: %s: When protocol=tls and pjproject version < 2.5.0, async_operations can't be > 1\n",
  526. ast_sorcery_object_get_id(obj));
  527. return -1;
  528. }
  529. temp_state->state->tls.password = pj_str((char*)transport->password);
  530. set_qos(transport, &temp_state->state->tls.qos_params);
  531. /* sockopt_params.options is copied to each newly connected socket */
  532. temp_state->state->tls.sockopt_params.options[0].level = pj_SOL_TCP();
  533. temp_state->state->tls.sockopt_params.options[0].optname = pj_TCP_NODELAY();
  534. temp_state->state->tls.sockopt_params.options[0].optval = &option;
  535. temp_state->state->tls.sockopt_params.options[0].optlen = sizeof(option);
  536. temp_state->state->tls.sockopt_params.cnt = 1;
  537. for (i = 0; i < BIND_TRIES && res != PJ_SUCCESS; i++) {
  538. if (perm_state && perm_state->state && perm_state->state->factory
  539. && perm_state->state->factory->destroy) {
  540. perm_state->state->factory->destroy(perm_state->state->factory);
  541. usleep(BIND_DELAY_US);
  542. }
  543. res = pjsip_tls_transport_start2(ast_sip_get_pjsip_endpoint(), &temp_state->state->tls,
  544. &temp_state->state->host, NULL, transport->async_operations,
  545. &temp_state->state->factory);
  546. }
  547. } else if ((transport->type == AST_TRANSPORT_WS) || (transport->type == AST_TRANSPORT_WSS)) {
  548. if (transport->cos || transport->tos) {
  549. ast_log(LOG_WARNING, "TOS and COS values ignored for websocket transport\n");
  550. } else if (!ast_strlen_zero(transport->ca_list_file) || !ast_strlen_zero(transport->ca_list_path) ||
  551. !ast_strlen_zero(transport->cert_file) || !ast_strlen_zero(transport->privkey_file)) {
  552. ast_log(LOG_WARNING, "TLS certificate values ignored for websocket transport as they are configured in http.conf\n");
  553. }
  554. res = PJ_SUCCESS;
  555. }
  556. if (res != PJ_SUCCESS) {
  557. char msg[PJ_ERR_MSG_SIZE];
  558. pj_strerror(res, msg, sizeof(msg));
  559. ast_log(LOG_ERROR, "Transport '%s' could not be started: %s\n", ast_sorcery_object_get_id(obj), msg);
  560. return -1;
  561. }
  562. copy_state_to_transport(transport);
  563. if (perm_state) {
  564. ao2_unlink_flags(states, perm_state, OBJ_NOLOCK);
  565. }
  566. ao2_link_flags(states, temp_state, OBJ_NOLOCK);
  567. return 0;
  568. }
  569. /*! \brief Custom handler for type just makes sure the state is created */
  570. static int transport_state_init(const struct aco_option *opt, struct ast_variable *var, void *obj)
  571. {
  572. struct ast_sip_transport *transport = obj;
  573. struct ast_sip_transport_state *state = find_or_create_temporary_state(transport);
  574. ao2_cleanup(state);
  575. return 0;
  576. }
  577. /*! \brief Custom handler for TLS method setting */
  578. static int transport_tls_file_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
  579. {
  580. struct ast_sip_transport *transport = obj;
  581. RAII_VAR(struct ast_sip_transport_state *, state, find_or_create_temporary_state(transport), ao2_cleanup);
  582. if (!state) {
  583. return -1;
  584. }
  585. if (ast_strlen_zero(var->value)) {
  586. /* Ignore empty options */
  587. return 0;
  588. }
  589. if (!ast_file_is_readable(var->value)) {
  590. ast_log(LOG_ERROR, "Transport: %s: %s %s is either missing or not readable\n",
  591. ast_sorcery_object_get_id(obj), var->name, var->value);
  592. return -1;
  593. }
  594. if (!strcasecmp(var->name, "ca_list_file")) {
  595. state->tls.ca_list_file = pj_str((char*)var->value);
  596. ast_string_field_set(transport, ca_list_file, var->value);
  597. } else if (!strcasecmp(var->name, "ca_list_path")) {
  598. #ifdef HAVE_PJ_SSL_CERT_LOAD_FROM_FILES2
  599. state->tls.ca_list_path = pj_str((char*)var->value);
  600. ast_string_field_set(transport, ca_list_path, var->value);
  601. #else
  602. ast_log(LOG_WARNING, "Asterisk has been built against a version of pjproject that does not "
  603. "support the 'ca_list_path' option. Please upgrade to version 2.4 or later.\n");
  604. #endif
  605. } else if (!strcasecmp(var->name, "cert_file")) {
  606. state->tls.cert_file = pj_str((char*)var->value);
  607. ast_string_field_set(transport, cert_file, var->value);
  608. } else if (!strcasecmp(var->name, "priv_key_file")) {
  609. state->tls.privkey_file = pj_str((char*)var->value);
  610. ast_string_field_set(transport, privkey_file, var->value);
  611. }
  612. return 0;
  613. }
  614. static int ca_list_file_to_str(const void *obj, const intptr_t *args, char **buf)
  615. {
  616. const struct ast_sip_transport *transport = obj;
  617. *buf = ast_strdup(transport->ca_list_file);
  618. return 0;
  619. }
  620. static int ca_list_path_to_str(const void *obj, const intptr_t *args, char **buf)
  621. {
  622. const struct ast_sip_transport *transport = obj;
  623. *buf = ast_strdup(transport->ca_list_path);
  624. return 0;
  625. }
  626. static int cert_file_to_str(const void *obj, const intptr_t *args, char **buf)
  627. {
  628. const struct ast_sip_transport *transport = obj;
  629. *buf = ast_strdup(transport->cert_file);
  630. return 0;
  631. }
  632. static int privkey_file_to_str(const void *obj, const intptr_t *args, char **buf)
  633. {
  634. const struct ast_sip_transport *transport = obj;
  635. *buf = ast_strdup(transport->privkey_file);
  636. return 0;
  637. }
  638. /*! \brief Custom handler for turning a string protocol into an enum */
  639. static int transport_protocol_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
  640. {
  641. struct ast_sip_transport *transport = obj;
  642. RAII_VAR(struct ast_sip_transport_state *, state, find_or_create_temporary_state(transport), ao2_cleanup);
  643. if (!state) {
  644. return -1;
  645. }
  646. if (!strcasecmp(var->value, "udp")) {
  647. transport->type = AST_TRANSPORT_UDP;
  648. } else if (!strcasecmp(var->value, "tcp")) {
  649. transport->type = AST_TRANSPORT_TCP;
  650. } else if (!strcasecmp(var->value, "tls")) {
  651. transport->type = AST_TRANSPORT_TLS;
  652. } else if (!strcasecmp(var->value, "ws")) {
  653. transport->type = AST_TRANSPORT_WS;
  654. } else if (!strcasecmp(var->value, "wss")) {
  655. transport->type = AST_TRANSPORT_WSS;
  656. } else {
  657. return -1;
  658. }
  659. state->type = transport->type;
  660. return 0;
  661. }
  662. static const char *transport_types[] = {
  663. [AST_TRANSPORT_UDP] = "udp",
  664. [AST_TRANSPORT_TCP] = "tcp",
  665. [AST_TRANSPORT_TLS] = "tls",
  666. [AST_TRANSPORT_WS] = "ws",
  667. [AST_TRANSPORT_WSS] = "wss"
  668. };
  669. static int transport_protocol_to_str(const void *obj, const intptr_t *args, char **buf)
  670. {
  671. const struct ast_sip_transport *transport = obj;
  672. if (ARRAY_IN_BOUNDS(transport->type, transport_types)) {
  673. *buf = ast_strdup(transport_types[transport->type]);
  674. }
  675. return 0;
  676. }
  677. /*! \brief Custom handler for turning a string bind into a pj_sockaddr */
  678. static int transport_bind_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
  679. {
  680. struct ast_sip_transport *transport = obj;
  681. pj_str_t buf;
  682. int rc;
  683. RAII_VAR(struct ast_sip_transport_state *, state, find_or_create_temporary_state(transport), ao2_cleanup);
  684. if (!state) {
  685. return -1;
  686. }
  687. rc = pj_sockaddr_parse(pj_AF_UNSPEC(), 0, pj_cstr(&buf, var->value), &state->host);
  688. return rc != PJ_SUCCESS ? -1 : 0;
  689. }
  690. static int transport_bind_to_str(const void *obj, const intptr_t *args, char **buf)
  691. {
  692. const struct ast_sip_transport *transport = obj;
  693. RAII_VAR(struct ast_sip_transport_state *, state, find_state_by_transport(transport), ao2_cleanup);
  694. if (!state) {
  695. return -1;
  696. }
  697. if (!(*buf = ast_calloc(MAX_OBJECT_FIELD, sizeof(char)))) {
  698. return -1;
  699. }
  700. /* include port as well as brackets if IPv6 */
  701. pj_sockaddr_print(&state->host, *buf, MAX_OBJECT_FIELD, 1 | 2);
  702. return 0;
  703. }
  704. /*! \brief Custom handler for TLS boolean settings */
  705. static int transport_tls_bool_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
  706. {
  707. struct ast_sip_transport *transport = obj;
  708. RAII_VAR(struct ast_sip_transport_state *, state, find_or_create_temporary_state(transport), ao2_cleanup);
  709. if (!state) {
  710. return -1;
  711. }
  712. if (!strcasecmp(var->name, "verify_server")) {
  713. state->tls.verify_server = ast_true(var->value) ? PJ_TRUE : PJ_FALSE;
  714. } else if (!strcasecmp(var->name, "verify_client")) {
  715. state->tls.verify_client = ast_true(var->value) ? PJ_TRUE : PJ_FALSE;
  716. } else if (!strcasecmp(var->name, "require_client_cert")) {
  717. state->tls.require_client_cert = ast_true(var->value) ? PJ_TRUE : PJ_FALSE;
  718. } else {
  719. return -1;
  720. }
  721. return 0;
  722. }
  723. static int verify_server_to_str(const void *obj, const intptr_t *args, char **buf)
  724. {
  725. const struct ast_sip_transport *transport = obj;
  726. RAII_VAR(struct ast_sip_transport_state *, state, find_state_by_transport(transport), ao2_cleanup);
  727. if (!state) {
  728. return -1;
  729. }
  730. *buf = ast_strdup(AST_YESNO(state->tls.verify_server));
  731. return 0;
  732. }
  733. static int verify_client_to_str(const void *obj, const intptr_t *args, char **buf)
  734. {
  735. const struct ast_sip_transport *transport = obj;
  736. RAII_VAR(struct ast_sip_transport_state *, state, find_state_by_transport(transport), ao2_cleanup);
  737. if (!state) {
  738. return -1;
  739. }
  740. *buf = ast_strdup(AST_YESNO(state->tls.verify_client));
  741. return 0;
  742. }
  743. static int require_client_cert_to_str(const void *obj, const intptr_t *args, char **buf)
  744. {
  745. const struct ast_sip_transport *transport = obj;
  746. RAII_VAR(struct ast_sip_transport_state *, state, find_state_by_transport(transport), ao2_cleanup);
  747. if (!state) {
  748. return -1;
  749. }
  750. *buf = ast_strdup(AST_YESNO(state->tls.require_client_cert));
  751. return 0;
  752. }
  753. /*! \brief Custom handler for TLS method setting */
  754. static int transport_tls_method_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
  755. {
  756. struct ast_sip_transport *transport = obj;
  757. RAII_VAR(struct ast_sip_transport_state *, state, find_or_create_temporary_state(transport), ao2_cleanup);
  758. if (!state) {
  759. return -1;
  760. }
  761. if (ast_strlen_zero(var->value) || !strcasecmp(var->value, "default")) {
  762. state->tls.method = PJSIP_SSL_DEFAULT_METHOD;
  763. } else if (!strcasecmp(var->value, "unspecified")) {
  764. state->tls.method = PJSIP_SSL_UNSPECIFIED_METHOD;
  765. } else if (!strcasecmp(var->value, "tlsv1")) {
  766. state->tls.method = PJSIP_TLSV1_METHOD;
  767. #ifdef HAVE_PJSIP_TLS_TRANSPORT_PROTO
  768. } else if (!strcasecmp(var->value, "tlsv1_1")) {
  769. state->tls.method = PJSIP_TLSV1_1_METHOD;
  770. } else if (!strcasecmp(var->value, "tlsv1_2")) {
  771. state->tls.method = PJSIP_TLSV1_2_METHOD;
  772. #endif
  773. } else if (!strcasecmp(var->value, "sslv2")) {
  774. state->tls.method = PJSIP_SSLV2_METHOD;
  775. } else if (!strcasecmp(var->value, "sslv3")) {
  776. state->tls.method = PJSIP_SSLV3_METHOD;
  777. } else if (!strcasecmp(var->value, "sslv23")) {
  778. state->tls.method = PJSIP_SSLV23_METHOD;
  779. } else {
  780. return -1;
  781. }
  782. return 0;
  783. }
  784. static const char *tls_method_map[] = {
  785. [PJSIP_SSL_UNSPECIFIED_METHOD] = "unspecified",
  786. [PJSIP_TLSV1_METHOD] = "tlsv1",
  787. #ifdef HAVE_PJSIP_TLS_TRANSPORT_PROTO
  788. [PJSIP_TLSV1_1_METHOD] = "tlsv1_1",
  789. [PJSIP_TLSV1_2_METHOD] = "tlsv1_2",
  790. #endif
  791. [PJSIP_SSLV2_METHOD] = "sslv2",
  792. [PJSIP_SSLV3_METHOD] = "sslv3",
  793. [PJSIP_SSLV23_METHOD] = "sslv23",
  794. };
  795. static int tls_method_to_str(const void *obj, const intptr_t *args, char **buf)
  796. {
  797. const struct ast_sip_transport *transport = obj;
  798. RAII_VAR(struct ast_sip_transport_state *, state, find_state_by_transport(transport), ao2_cleanup);
  799. if (!state) {
  800. return -1;
  801. }
  802. if (ARRAY_IN_BOUNDS(state->tls.method, tls_method_map)) {
  803. *buf = ast_strdup(tls_method_map[state->tls.method]);
  804. }
  805. return 0;
  806. }
  807. /*! \brief Helper function which turns a cipher name into an identifier */
  808. static pj_ssl_cipher cipher_name_to_id(const char *name)
  809. {
  810. pj_ssl_cipher ciphers[PJ_SSL_SOCK_MAX_CIPHERS];
  811. unsigned int cipher_num = PJ_ARRAY_SIZE(ciphers);
  812. unsigned int pos;
  813. if (pj_ssl_cipher_get_availables(ciphers, &cipher_num)) {
  814. return 0;
  815. }
  816. for (pos = 0; pos < cipher_num; ++pos) {
  817. const char *pos_name = pj_ssl_cipher_name(ciphers[pos]);
  818. if (pos_name && !strcmp(pos_name, name)) {
  819. return ciphers[pos];
  820. }
  821. }
  822. return 0;
  823. }
  824. /*!
  825. * \internal
  826. * \brief Add a new cipher to the transport's cipher list array.
  827. *
  828. * \param transport Which transport to add the cipher to.
  829. * \param name Cipher identifier name.
  830. *
  831. * \retval 0 on success.
  832. * \retval -1 on error.
  833. */
  834. static int transport_cipher_add(struct ast_sip_transport_state *state, const char *name)
  835. {
  836. pj_ssl_cipher cipher;
  837. int idx;
  838. cipher = cipher_name_to_id(name);
  839. if (!cipher) {
  840. /* TODO: Check this over/tweak - it's taken from pjsua for now */
  841. if (!strnicmp(name, "0x", 2)) {
  842. pj_str_t cipher_st = pj_str((char *) name + 2);
  843. cipher = pj_strtoul2(&cipher_st, NULL, 16);
  844. } else {
  845. cipher = atoi(name);
  846. }
  847. }
  848. if (pj_ssl_cipher_is_supported(cipher)) {
  849. for (idx = state->tls.ciphers_num; idx--;) {
  850. if (state->ciphers[idx] == cipher) {
  851. /* The cipher is already in the list. */
  852. return 0;
  853. }
  854. }
  855. state->ciphers[state->tls.ciphers_num++] = cipher;
  856. return 0;
  857. } else {
  858. ast_log(LOG_ERROR, "Cipher '%s' is unsupported\n", name);
  859. return -1;
  860. }
  861. }
  862. /*! \brief Custom handler for TLS cipher setting */
  863. static int transport_tls_cipher_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
  864. {
  865. struct ast_sip_transport *transport = obj;
  866. char *parse;
  867. char *name;
  868. int res = 0;
  869. RAII_VAR(struct ast_sip_transport_state *, state, find_or_create_temporary_state(transport), ao2_cleanup);
  870. if (!state) {
  871. return -1;
  872. }
  873. parse = ast_strdupa(S_OR(var->value, ""));
  874. while ((name = ast_strip(strsep(&parse, ",")))) {
  875. if (ast_strlen_zero(name)) {
  876. continue;
  877. }
  878. if (ARRAY_LEN(state->ciphers) <= state->tls.ciphers_num) {
  879. ast_log(LOG_ERROR, "Too many ciphers specified\n");
  880. res = -1;
  881. break;
  882. }
  883. res |= transport_cipher_add(state, name);
  884. }
  885. return res ? -1 : 0;
  886. }
  887. static void cipher_to_str(char **buf, const pj_ssl_cipher *ciphers, unsigned int cipher_num)
  888. {
  889. struct ast_str *str;
  890. unsigned int idx;
  891. str = ast_str_create(128);
  892. if (!str) {
  893. *buf = NULL;
  894. return;
  895. }
  896. for (idx = 0; idx < cipher_num; ++idx) {
  897. ast_str_append(&str, 0, "%s", pj_ssl_cipher_name(ciphers[idx]));
  898. if (idx < cipher_num - 1) {
  899. ast_str_append(&str, 0, ", ");
  900. }
  901. }
  902. *buf = ast_strdup(ast_str_buffer(str));
  903. ast_free(str);
  904. }
  905. static int transport_tls_cipher_to_str(const void *obj, const intptr_t *args, char **buf)
  906. {
  907. const struct ast_sip_transport *transport = obj;
  908. RAII_VAR(struct ast_sip_transport_state *, state, find_state_by_transport(transport), ao2_cleanup);
  909. if (!state) {
  910. return -1;
  911. }
  912. cipher_to_str(buf, state->ciphers, state->tls.ciphers_num);
  913. return *buf ? 0 : -1;
  914. }
  915. static char *handle_pjsip_list_ciphers(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
  916. {
  917. pj_ssl_cipher ciphers[PJ_SSL_SOCK_MAX_CIPHERS];
  918. unsigned int cipher_num = PJ_ARRAY_SIZE(ciphers);
  919. char *buf;
  920. switch (cmd) {
  921. case CLI_INIT:
  922. e->command = "pjsip list ciphers";
  923. e->usage = "Usage: pjsip list ciphers\n"
  924. " List available OpenSSL cipher names.\n";
  925. return NULL;
  926. case CLI_GENERATE:
  927. return NULL;
  928. }
  929. if (pj_ssl_cipher_get_availables(ciphers, &cipher_num) || !cipher_num) {
  930. buf = NULL;
  931. } else {
  932. cipher_to_str(&buf, ciphers, cipher_num);
  933. }
  934. if (!ast_strlen_zero(buf)) {
  935. ast_cli(a->fd, "Available ciphers: '%s'\n", buf);
  936. } else {
  937. ast_cli(a->fd, "No available ciphers\n");
  938. }
  939. ast_free(buf);
  940. return CLI_SUCCESS;
  941. }
  942. /*! \brief Custom handler for localnet setting */
  943. static int transport_localnet_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
  944. {
  945. struct ast_sip_transport *transport = obj;
  946. int error = 0;
  947. RAII_VAR(struct ast_sip_transport_state *, state, find_or_create_temporary_state(transport), ao2_cleanup);
  948. if (!state) {
  949. return -1;
  950. }
  951. if (ast_strlen_zero(var->value)) {
  952. ast_free_ha(state->localnet);
  953. state->localnet = NULL;
  954. return 0;
  955. }
  956. /* We use only the ast_apply_ha() which defaults to ALLOW
  957. * ("permit"), so we add DENY rules. */
  958. if (!(state->localnet = ast_append_ha("deny", var->value, state->localnet, &error))) {
  959. return -1;
  960. }
  961. return error;
  962. }
  963. static int localnet_to_vl(const void *obj, struct ast_variable **fields)
  964. {
  965. const struct ast_sip_transport *transport = obj;
  966. char str[MAX_OBJECT_FIELD];
  967. struct ast_variable *head = NULL;
  968. struct ast_ha *ha;
  969. RAII_VAR(struct ast_sip_transport_state *, state, find_state_by_transport(transport), ao2_cleanup);
  970. if (!state) {
  971. return -1;
  972. }
  973. for (ha = state->localnet; ha; ha = ha->next) {
  974. const char *addr = ast_strdupa(ast_sockaddr_stringify_addr(&ha->addr));
  975. snprintf(str, MAX_OBJECT_FIELD, "%s%s/%s", ha->sense == AST_SENSE_ALLOW ? "!" : "",
  976. addr, ast_sockaddr_stringify_addr(&ha->netmask));
  977. ast_variable_list_append(&head, ast_variable_new("local_net", str, ""));
  978. }
  979. if (head) {
  980. *fields = head;
  981. }
  982. return 0;
  983. }
  984. static int localnet_to_str(const void *obj, const intptr_t *args, char **buf)
  985. {
  986. RAII_VAR(struct ast_str *, str, ast_str_create(MAX_OBJECT_FIELD), ast_free);
  987. const struct ast_sip_transport *transport = obj;
  988. RAII_VAR(struct ast_sip_transport_state *, state, find_state_by_transport(transport), ao2_cleanup);
  989. if (!state) {
  990. return -1;
  991. }
  992. ast_ha_join(state->localnet, &str);
  993. *buf = ast_strdup(ast_str_buffer(str));
  994. return 0;
  995. }
  996. /*! \brief Custom handler for TOS setting */
  997. static int transport_tos_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
  998. {
  999. struct ast_sip_transport *transport = obj;
  1000. unsigned int value;
  1001. if (ast_str2tos(var->value, &value)) {
  1002. ast_log(LOG_ERROR, "Error configuring transport '%s' - Could not "
  1003. "interpret 'tos' value '%s'\n",
  1004. ast_sorcery_object_get_id(transport), var->value);
  1005. return -1;
  1006. }
  1007. if (value % 4) {
  1008. value = value >> 2;
  1009. value = value << 2;
  1010. ast_log(LOG_WARNING,
  1011. "transport '%s' - 'tos' value '%s' uses bits that are "
  1012. "discarded when converted to DSCP. Using equivalent %u instead.\n",
  1013. ast_sorcery_object_get_id(transport), var->value, value);
  1014. }
  1015. transport->tos = value;
  1016. return 0;
  1017. }
  1018. static int tos_to_str(const void *obj, const intptr_t *args, char **buf)
  1019. {
  1020. const struct ast_sip_transport *transport = obj;
  1021. if (ast_asprintf(buf, "%u", transport->tos) == -1) {
  1022. return -1;
  1023. }
  1024. return 0;
  1025. }
  1026. static struct ao2_container *cli_get_container(const char *regex)
  1027. {
  1028. RAII_VAR(struct ao2_container *, container, NULL, ao2_cleanup);
  1029. struct ao2_container *s_container;
  1030. container = ast_sorcery_retrieve_by_regex(ast_sip_get_sorcery(), "transport",
  1031. regex);
  1032. if (!container) {
  1033. return NULL;
  1034. }
  1035. s_container = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, 0,
  1036. ast_sorcery_object_id_sort, ast_sorcery_object_id_compare);
  1037. if (!s_container) {
  1038. return NULL;
  1039. }
  1040. if (ao2_container_dup(s_container, container, 0)) {
  1041. ao2_ref(s_container, -1);
  1042. return NULL;
  1043. }
  1044. return s_container;
  1045. }
  1046. static int cli_iterate(void *container, ao2_callback_fn callback, void *args)
  1047. {
  1048. const struct ast_sip_endpoint *endpoint = container;
  1049. struct ast_sip_transport *transport = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(),
  1050. "transport", endpoint->transport);
  1051. if (!transport) {
  1052. return -1;
  1053. }
  1054. return callback(transport, args, 0);
  1055. }
  1056. static void *cli_retrieve_by_id(const char *id)
  1057. {
  1058. return ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "transport", id);
  1059. }
  1060. static int cli_print_header(void *obj, void *arg, int flags)
  1061. {
  1062. struct ast_sip_cli_context *context = arg;
  1063. int indent = CLI_INDENT_TO_SPACES(context->indent_level);
  1064. int filler = CLI_MAX_WIDTH - indent - 61;
  1065. ast_assert(context->output_buffer != NULL);
  1066. ast_str_append(&context->output_buffer, 0,
  1067. "%*s: <TransportId........> <Type> <cos> <tos> <BindAddress%*.*s>\n",
  1068. indent, "Transport", filler, filler, CLI_HEADER_FILLER);
  1069. return 0;
  1070. }
  1071. static int cli_print_body(void *obj, void *arg, int flags)
  1072. {
  1073. struct ast_sip_transport *transport = obj;
  1074. struct ast_sip_cli_context *context = arg;
  1075. char hoststr[PJ_INET6_ADDRSTRLEN];
  1076. RAII_VAR(struct ast_sip_transport_state *, state, find_state_by_transport(transport), ao2_cleanup);
  1077. if (!state) {
  1078. return -1;
  1079. }
  1080. ast_assert(context->output_buffer != NULL);
  1081. pj_sockaddr_print(&state->host, hoststr, sizeof(hoststr), 3);
  1082. ast_str_append(&context->output_buffer, 0, "%*s: %-21s %6s %5u %5u %s\n",
  1083. CLI_INDENT_TO_SPACES(context->indent_level), "Transport",
  1084. ast_sorcery_object_get_id(transport),
  1085. ARRAY_IN_BOUNDS(transport->type, transport_types) ? transport_types[transport->type] : "Unknown",
  1086. transport->cos, transport->tos, hoststr);
  1087. if (context->show_details
  1088. || (context->show_details_only_level_0 && context->indent_level == 0)) {
  1089. ast_str_append(&context->output_buffer, 0, "\n");
  1090. ast_sip_cli_print_sorcery_objectset(transport, context, 0);
  1091. }
  1092. return 0;
  1093. }
  1094. static struct ast_cli_entry cli_commands[] = {
  1095. AST_CLI_DEFINE(handle_pjsip_list_ciphers, "List available OpenSSL cipher names"),
  1096. AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "List PJSIP Transports",
  1097. .command = "pjsip list transports",
  1098. .usage = "Usage: pjsip list transports [ like <pattern> ]\n"
  1099. " List the configured PJSIP Transports\n"
  1100. " Optional regular expression pattern is used to filter the list.\n"),
  1101. AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "Show PJSIP Transports",
  1102. .command = "pjsip show transports",
  1103. .usage = "Usage: pjsip show transports [ like <pattern> ]\n"
  1104. " Show the configured PJSIP Transport\n"
  1105. " Optional regular expression pattern is used to filter the list.\n"),
  1106. AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "Show PJSIP Transport",
  1107. .command = "pjsip show transport",
  1108. .usage = "Usage: pjsip show transport <id>\n"
  1109. " Show the configured PJSIP Transport\n"),
  1110. };
  1111. static struct ast_sip_cli_formatter_entry *cli_formatter;
  1112. struct ast_sip_transport_state *ast_sip_get_transport_state(const char *transport_id)
  1113. {
  1114. struct internal_state *state = NULL;
  1115. struct ast_sip_transport_state *trans_state;
  1116. if (!transport_states) {
  1117. return NULL;
  1118. }
  1119. state = ao2_find(transport_states, transport_id, OBJ_SEARCH_KEY);
  1120. if (!state) {
  1121. return NULL;
  1122. }
  1123. trans_state = ao2_bump(state->state);
  1124. ao2_ref(state, -1);
  1125. return trans_state;
  1126. }
  1127. static int populate_transport_states(void *obj, void *arg, int flags)
  1128. {
  1129. struct internal_state *state = obj;
  1130. struct ao2_container *container = arg;
  1131. ao2_link(container, state->state);
  1132. return CMP_MATCH;
  1133. }
  1134. struct ao2_container *ast_sip_get_transport_states(void)
  1135. {
  1136. struct ao2_container *states = ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_MUTEX, 0,
  1137. DEFAULT_STATE_BUCKETS, transport_state_hash, NULL, transport_state_cmp);
  1138. if (!states) {
  1139. return NULL;
  1140. }
  1141. ao2_callback(transport_states, OBJ_NODATA | OBJ_MULTIPLE, populate_transport_states, states);
  1142. return states;
  1143. }
  1144. /*! \brief Initialize sorcery with transport support */
  1145. int ast_sip_initialize_sorcery_transport(void)
  1146. {
  1147. struct ast_sorcery *sorcery = ast_sip_get_sorcery();
  1148. struct ao2_container *transports = NULL;
  1149. /* Create outbound registration states container. */
  1150. transport_states = ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_MUTEX, 0,
  1151. DEFAULT_STATE_BUCKETS, internal_state_hash, NULL, internal_state_cmp);
  1152. if (!transport_states) {
  1153. ast_log(LOG_ERROR, "Unable to allocate transport states container\n");
  1154. return -1;
  1155. }
  1156. ast_sorcery_apply_default(sorcery, "transport", "config", "pjsip.conf,criteria=type=transport");
  1157. if (ast_sorcery_object_register(sorcery, "transport", sip_transport_alloc, NULL, transport_apply)) {
  1158. return -1;
  1159. }
  1160. /* Normally type is a OPT_NOOP_T but we're using it to make sure that state is created */
  1161. ast_sorcery_object_field_register_custom(sorcery, "transport", "type", "", transport_state_init, NULL, NULL, 0, 0);
  1162. ast_sorcery_object_field_register_custom(sorcery, "transport", "protocol", "udp", transport_protocol_handler, transport_protocol_to_str, NULL, 0, 0);
  1163. ast_sorcery_object_field_register_custom(sorcery, "transport", "bind", "", transport_bind_handler, transport_bind_to_str, NULL, 0, 0);
  1164. ast_sorcery_object_field_register(sorcery, "transport", "async_operations", "1", OPT_UINT_T, 0, FLDSET(struct ast_sip_transport, async_operations));
  1165. ast_sorcery_object_field_register_custom(sorcery, "transport", "ca_list_file", "", transport_tls_file_handler, ca_list_file_to_str, NULL, 0, 0);
  1166. ast_sorcery_object_field_register_custom(sorcery, "transport", "ca_list_path", "", transport_tls_file_handler, ca_list_path_to_str, NULL, 0, 0);
  1167. ast_sorcery_object_field_register_custom(sorcery, "transport", "cert_file", "", transport_tls_file_handler, cert_file_to_str, NULL, 0, 0);
  1168. ast_sorcery_object_field_register_custom(sorcery, "transport", "priv_key_file", "", transport_tls_file_handler, privkey_file_to_str, NULL, 0, 0);
  1169. ast_sorcery_object_field_register(sorcery, "transport", "password", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_transport, password));
  1170. ast_sorcery_object_field_register(sorcery, "transport", "external_signaling_address", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_transport, external_signaling_address));
  1171. ast_sorcery_object_field_register(sorcery, "transport", "external_signaling_port", "0", OPT_UINT_T, PARSE_IN_RANGE, FLDSET(struct ast_sip_transport, external_signaling_port), 0, 65535);
  1172. ast_sorcery_object_field_register(sorcery, "transport", "external_media_address", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_transport, external_media_address));
  1173. ast_sorcery_object_field_register(sorcery, "transport", "domain", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_transport, domain));
  1174. ast_sorcery_object_field_register_custom(sorcery, "transport", "verify_server", "", transport_tls_bool_handler, verify_server_to_str, NULL, 0, 0);
  1175. ast_sorcery_object_field_register_custom(sorcery, "transport", "verify_client", "", transport_tls_bool_handler, verify_client_to_str, NULL, 0, 0);
  1176. ast_sorcery_object_field_register_custom(sorcery, "transport", "require_client_cert", "", transport_tls_bool_handler, require_client_cert_to_str, NULL, 0, 0);
  1177. ast_sorcery_object_field_register_custom(sorcery, "transport", "method", "", transport_tls_method_handler, tls_method_to_str, NULL, 0, 0);
  1178. ast_sorcery_object_field_register_custom(sorcery, "transport", "cipher", "", transport_tls_cipher_handler, transport_tls_cipher_to_str, NULL, 0, 0);
  1179. ast_sorcery_object_field_register_custom(sorcery, "transport", "local_net", "", transport_localnet_handler, localnet_to_str, localnet_to_vl, 0, 0);
  1180. ast_sorcery_object_field_register_custom(sorcery, "transport", "tos", "0", transport_tos_handler, tos_to_str, NULL, 0, 0);
  1181. ast_sorcery_object_field_register(sorcery, "transport", "cos", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_transport, cos));
  1182. ast_sorcery_object_field_register(sorcery, "transport", "websocket_write_timeout", AST_DEFAULT_WEBSOCKET_WRITE_TIMEOUT_STR, OPT_INT_T, PARSE_IN_RANGE, FLDSET(struct ast_sip_transport, write_timeout), 1, INT_MAX);
  1183. ast_sorcery_object_field_register(sorcery, "transport", "allow_reload", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_transport, allow_reload));
  1184. ast_sorcery_object_field_register(sorcery, "transport", "symmetric_transport", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_transport, symmetric_transport));
  1185. internal_sip_register_endpoint_formatter(&endpoint_transport_formatter);
  1186. cli_formatter = ao2_alloc(sizeof(struct ast_sip_cli_formatter_entry), NULL);
  1187. if (!cli_formatter) {
  1188. ast_log(LOG_ERROR, "Unable to allocate memory for cli formatter\n");
  1189. return -1;
  1190. }
  1191. cli_formatter->name = "transport";
  1192. cli_formatter->print_header = cli_print_header;
  1193. cli_formatter->print_body = cli_print_body;
  1194. cli_formatter->get_container = cli_get_container;
  1195. cli_formatter->iterate = cli_iterate;
  1196. cli_formatter->get_id = ast_sorcery_object_get_id;
  1197. cli_formatter->retrieve_by_id = cli_retrieve_by_id;
  1198. ast_sip_register_cli_formatter(cli_formatter);
  1199. ast_cli_register_multiple(cli_commands, ARRAY_LEN(cli_commands));
  1200. /* trigger load of transports from realtime by trying to revrieve them all */
  1201. transports = ast_sorcery_retrieve_by_fields(sorcery, "transport", AST_RETRIEVE_FLAG_ALL | AST_RETRIEVE_FLAG_MULTIPLE, NULL);
  1202. ao2_cleanup(transports);
  1203. return 0;
  1204. }
  1205. int ast_sip_destroy_sorcery_transport(void)
  1206. {
  1207. ast_cli_unregister_multiple(cli_commands, ARRAY_LEN(cli_commands));
  1208. ast_sip_unregister_cli_formatter(cli_formatter);
  1209. internal_sip_unregister_endpoint_formatter(&endpoint_transport_formatter);
  1210. ao2_ref(transport_states, -1);
  1211. transport_states = NULL;
  1212. return 0;
  1213. }