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