res_pjsip_diversion: implement support for History-Info
[asterisk/asterisk.git] / res / res_pjsip / pjsip_configuration.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2013, Digium, Inc.
5  *
6  * Matt Jordan <mjordan@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 <pjsip_ua.h>
23
24 #include "asterisk/res_pjsip.h"
25 #include "include/res_pjsip_private.h"
26 #include "asterisk/res_pjsip_cli.h"
27 #include "asterisk/acl.h"
28 #include "asterisk/manager.h"
29 #include "asterisk/astobj2.h"
30 #include "asterisk/utils.h"
31 #include "asterisk/sorcery.h"
32 #include "asterisk/callerid.h"
33 #include "asterisk/test.h"
34 #include "asterisk/statsd.h"
35 #include "asterisk/pbx.h"
36 #include "asterisk/stream.h"
37 #include "asterisk/stasis.h"
38 #include "asterisk/security_events.h"
39
40 /*! \brief Number of buckets for persistent endpoint information */
41 #define PERSISTENT_BUCKETS 53
42
43 /*! \brief Persistent endpoint information */
44 struct sip_persistent_endpoint {
45         /*! \brief Asterisk endpoint itself */
46         struct ast_endpoint *endpoint;
47 };
48
49 /*! \brief Container for persistent endpoint information */
50 static struct ao2_container *persistent_endpoints;
51
52 static struct ast_sorcery *sip_sorcery;
53
54 static struct stasis_subscription *acl_change_sub;
55
56 /*! \brief Hashing function for persistent endpoint information */
57 static int persistent_endpoint_hash(const void *obj, const int flags)
58 {
59         const struct sip_persistent_endpoint *persistent = obj;
60         const char *id = (flags & OBJ_KEY ? obj : ast_endpoint_get_resource(persistent->endpoint));
61
62         return ast_str_hash(id);
63 }
64
65 /*! \brief Comparison function for persistent endpoint information */
66 static int persistent_endpoint_cmp(void *obj, void *arg, int flags)
67 {
68         const struct sip_persistent_endpoint *persistent1 = obj;
69         const struct sip_persistent_endpoint *persistent2 = arg;
70         const char *id = (flags & OBJ_KEY ? arg : ast_endpoint_get_resource(persistent2->endpoint));
71
72         return !strcmp(ast_endpoint_get_resource(persistent1->endpoint), id) ? CMP_MATCH | CMP_STOP : 0;
73 }
74
75 static void endpoint_deleted_observer(const void *object)
76 {
77         const struct ast_sip_endpoint *endpoint = object;
78
79         ao2_find(persistent_endpoints, ast_endpoint_get_resource(endpoint->persistent),
80                 OBJ_SEARCH_KEY | OBJ_UNLINK | OBJ_NODATA);
81 }
82
83 static const struct ast_sorcery_observer endpoint_observers = {
84         .deleted = endpoint_deleted_observer,
85 };
86
87 static int endpoint_acl_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
88 {
89         struct ast_sip_endpoint *endpoint = obj;
90         int error = 0;
91         int ignore;
92
93         if (ast_strlen_zero(var->value)) return 0;
94
95         if (!strncmp(var->name, "contact_", 8)) {
96                 ast_append_acl(var->name + 8, var->value, &endpoint->contact_acl, &error, &ignore);
97         } else {
98                 ast_append_acl(var->name, var->value, &endpoint->acl, &error, &ignore);
99         }
100
101         return error;
102 }
103
104 static int acl_to_str(const void *obj, const intptr_t *args, char **buf)
105 {
106         const struct ast_sip_endpoint *endpoint = obj;
107         struct ast_acl_list *acl_list;
108         struct ast_acl *first_acl;
109
110         if (endpoint && !ast_acl_list_is_empty(acl_list=endpoint->acl)) {
111                 AST_LIST_LOCK(acl_list);
112                 first_acl = AST_LIST_FIRST(acl_list);
113                 if (ast_strlen_zero(first_acl->name)) {
114                         *buf = "deny/permit";
115                 } else {
116                         *buf = first_acl->name;
117                 }
118                 AST_LIST_UNLOCK(acl_list);
119         }
120
121         *buf = ast_strdup(*buf);
122         return 0;
123 }
124
125 static int contact_acl_to_str(const void *obj, const intptr_t *args, char **buf)
126 {
127         const struct ast_sip_endpoint *endpoint = obj;
128         struct ast_acl_list *acl_list;
129         struct ast_acl *first_acl;
130
131         if (endpoint && !ast_acl_list_is_empty(acl_list=endpoint->contact_acl)) {
132                 AST_LIST_LOCK(acl_list);
133                 first_acl = AST_LIST_FIRST(acl_list);
134                 if (ast_strlen_zero(first_acl->name)) {
135                         *buf = "deny/permit";
136                 } else {
137                         *buf = first_acl->name;
138                 }
139                 AST_LIST_UNLOCK(acl_list);
140         }
141
142         *buf = ast_strdup(*buf);
143         return 0;
144 }
145
146 static int dtmf_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
147 {
148         struct ast_sip_endpoint *endpoint = obj;
149         int dtmf = ast_sip_str_to_dtmf(var->value);
150
151         if (dtmf == -1) {
152                 return -1;
153         }
154
155         endpoint->dtmf = dtmf;
156         return 0;
157 }
158
159 static int dtmf_to_str(const void *obj, const intptr_t *args, char **buf)
160 {
161         const struct ast_sip_endpoint *endpoint = obj;
162         char dtmf_str[20];
163         int result = -1;
164
165         result = ast_sip_dtmf_to_str(endpoint->dtmf, dtmf_str, sizeof(dtmf_str));
166
167         if (result == 0) {
168                 *buf = ast_strdup(dtmf_str);
169         } else {
170                 *buf = ast_strdup("none");
171         }
172         return 0;
173 }
174
175 static int prack_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
176 {
177         struct ast_sip_endpoint *endpoint = obj;
178
179         /* clear all */
180         endpoint->extensions.flags &= ~(PJSIP_INV_SUPPORT_100REL | PJSIP_INV_REQUIRE_100REL);
181
182         if (ast_true(var->value)) {
183                 endpoint->extensions.flags |= PJSIP_INV_SUPPORT_100REL;
184         } else if (!strcasecmp(var->value, "required")) {
185                 endpoint->extensions.flags |= PJSIP_INV_REQUIRE_100REL;
186         } else if (!ast_false(var->value)){
187                 return -1;
188         }
189
190         return 0;
191 }
192
193 static int prack_to_str(const void *obj, const intptr_t *args, char **buf)
194 {
195         const struct ast_sip_endpoint *endpoint = obj;
196
197         if (endpoint->extensions.flags & PJSIP_INV_REQUIRE_100REL) {
198                 *buf = "required";
199         } else if (endpoint->extensions.flags & PJSIP_INV_SUPPORT_100REL) {
200                 *buf = "yes";
201         } else {
202                 *buf = "no";
203         }
204
205         *buf = ast_strdup(*buf);
206         return 0;
207 }
208
209 static int timers_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
210 {
211         struct ast_sip_endpoint *endpoint = obj;
212
213         /* clear all */
214         endpoint->extensions.flags &= ~(PJSIP_INV_SUPPORT_TIMER | PJSIP_INV_REQUIRE_TIMER
215                                         | PJSIP_INV_ALWAYS_USE_TIMER);
216
217         /* set only the specified flag and let pjsip normalize if needed */
218         if (ast_true(var->value)) {
219                 endpoint->extensions.flags |= PJSIP_INV_SUPPORT_TIMER;
220         } else if (!strcasecmp(var->value, "required")) {
221                 endpoint->extensions.flags |= PJSIP_INV_REQUIRE_TIMER;
222         } else if (!strcasecmp(var->value, "always") || !strcasecmp(var->value, "forced")) {
223                 endpoint->extensions.flags |= PJSIP_INV_ALWAYS_USE_TIMER;
224         } else if (!ast_false(var->value)) {
225                 return -1;
226         }
227
228         return 0;
229 }
230
231 static int timers_to_str(const void *obj, const intptr_t *args, char **buf)
232 {
233         const struct ast_sip_endpoint *endpoint = obj;
234
235         if (endpoint->extensions.flags & PJSIP_INV_ALWAYS_USE_TIMER) {
236                 *buf = "always";
237         } else if (endpoint->extensions.flags & PJSIP_INV_REQUIRE_TIMER) {
238                 *buf = "required";
239         } else if (endpoint->extensions.flags & PJSIP_INV_SUPPORT_TIMER) {
240                 *buf = "yes";
241         } else {
242                 *buf = "no";
243         }
244
245         *buf = ast_strdup(*buf);
246         return 0;
247 }
248
249 void ast_sip_auth_vector_destroy(struct ast_sip_auth_vector *auths)
250 {
251         int i;
252         size_t size;
253
254         if (!auths) {
255                 return;
256         }
257
258         size = AST_VECTOR_SIZE(auths);
259
260         for (i = 0; i < size; ++i) {
261                 const char *name = AST_VECTOR_REMOVE_UNORDERED(auths, 0);
262                 ast_free((char *) name);
263         }
264         AST_VECTOR_FREE(auths);
265 }
266
267 int ast_sip_auth_vector_init(struct ast_sip_auth_vector *auths, const char *value)
268 {
269         char *auth_names = ast_strdupa(value);
270         char *val;
271
272         ast_assert(auths != NULL);
273
274         if (AST_VECTOR_SIZE(auths)) {
275                 ast_sip_auth_vector_destroy(auths);
276         }
277         if (AST_VECTOR_INIT(auths, 1)) {
278                 return -1;
279         }
280
281         while ((val = ast_strip(strsep(&auth_names, ",")))) {
282                 if (ast_strlen_zero(val)) {
283                         continue;
284                 }
285
286                 val = ast_strdup(val);
287                 if (!val) {
288                         goto failure;
289                 }
290                 if (AST_VECTOR_APPEND(auths, val)) {
291                         ast_free(val);
292
293                         goto failure;
294                 }
295         }
296         return 0;
297
298 failure:
299         ast_sip_auth_vector_destroy(auths);
300         return -1;
301 }
302
303 static int inbound_auth_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
304 {
305         struct ast_sip_endpoint *endpoint = obj;
306
307         return ast_sip_auth_vector_init(&endpoint->inbound_auths, var->value);
308 }
309
310 static int outbound_auth_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
311 {
312         struct ast_sip_endpoint *endpoint = obj;
313
314         return ast_sip_auth_vector_init(&endpoint->outbound_auths, var->value);
315 }
316
317 int ast_sip_auths_to_str(const struct ast_sip_auth_vector *auths, char **buf)
318 {
319         if (!auths || !AST_VECTOR_SIZE(auths)) {
320                 return 0;
321         }
322
323         if (!(*buf = ast_calloc(MAX_OBJECT_FIELD, sizeof(char)))) {
324                 return -1;
325         }
326
327         /* I feel like accessing the vector's elem array directly is cheating...*/
328         ast_join_delim(*buf, MAX_OBJECT_FIELD, auths->elems, AST_VECTOR_SIZE(auths), ',');
329         return 0;
330 }
331
332 static int inbound_auths_to_str(const void *obj, const intptr_t *args, char **buf)
333 {
334         const struct ast_sip_endpoint *endpoint = obj;
335         return ast_sip_auths_to_str(&endpoint->inbound_auths, buf);
336 }
337
338 static int outbound_auths_to_str(const void *obj, const intptr_t *args, char **buf)
339 {
340         const struct ast_sip_endpoint *endpoint = obj;
341         return ast_sip_auths_to_str(&endpoint->outbound_auths, buf);
342 }
343
344 /*!
345  * \internal
346  * \brief Convert identify_by method to string.
347  *
348  * \param method Method value to convert to string
349  *
350  * \return String representation.
351  */
352 static const char *sip_endpoint_identifier_type2str(enum ast_sip_endpoint_identifier_type method)
353 {
354         const char *str = "<unknown>";
355
356         switch (method) {
357         case AST_SIP_ENDPOINT_IDENTIFY_BY_USERNAME:
358                 str = "username";
359                 break;
360         case AST_SIP_ENDPOINT_IDENTIFY_BY_AUTH_USERNAME:
361                 str = "auth_username";
362                 break;
363         case AST_SIP_ENDPOINT_IDENTIFY_BY_IP:
364                 str = "ip";
365                 break;
366         case AST_SIP_ENDPOINT_IDENTIFY_BY_HEADER:
367                 str = "header";
368                 break;
369         }
370         return str;
371 }
372
373 /*!
374  * \internal
375  * \brief Convert string to an endpoint identifier token.
376  *
377  * \param str String to convert
378  *
379  * \retval enum ast_sip_endpoint_identifier_type token value on success.
380  * \retval -1 on failure.
381  */
382 static int sip_endpoint_identifier_str2type(const char *str)
383 {
384         int method;
385
386         if (!strcasecmp(str, "username")) {
387                 method = AST_SIP_ENDPOINT_IDENTIFY_BY_USERNAME;
388         } else if (!strcasecmp(str, "auth_username")) {
389                 method = AST_SIP_ENDPOINT_IDENTIFY_BY_AUTH_USERNAME;
390         } else if (!strcasecmp(str, "ip")) {
391                 method = AST_SIP_ENDPOINT_IDENTIFY_BY_IP;
392         } else if (!strcasecmp(str, "header")) {
393                 method = AST_SIP_ENDPOINT_IDENTIFY_BY_HEADER;
394         } else {
395                 method = -1;
396         }
397         return method;
398 }
399
400 static int ident_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
401 {
402         struct ast_sip_endpoint *endpoint = obj;
403         char *idents = ast_strdupa(var->value);
404         char *val;
405         int method;
406
407         /*
408          * If there's already something in the vector when we get here,
409          * it's the default value so we need to clean it out.
410          */
411         if (AST_VECTOR_SIZE(&endpoint->ident_method_order)) {
412                 AST_VECTOR_RESET(&endpoint->ident_method_order, AST_VECTOR_ELEM_CLEANUP_NOOP);
413                 endpoint->ident_method = 0;
414         }
415
416         while ((val = ast_strip(strsep(&idents, ",")))) {
417                 if (ast_strlen_zero(val)) {
418                         continue;
419                 }
420
421                 method = sip_endpoint_identifier_str2type(val);
422                 if (method == -1) {
423                         ast_log(LOG_ERROR, "Unrecognized identification method %s specified for endpoint %s\n",
424                                         val, ast_sorcery_object_get_id(endpoint));
425                         AST_VECTOR_RESET(&endpoint->ident_method_order, AST_VECTOR_ELEM_CLEANUP_NOOP);
426                         endpoint->ident_method = 0;
427                         return -1;
428                 }
429                 if (endpoint->ident_method & method) {
430                         /* We are already indentifying by this method.  No need to do it again. */
431                         continue;
432                 }
433
434                 endpoint->ident_method |= method;
435                 AST_VECTOR_APPEND(&endpoint->ident_method_order, method);
436         }
437
438         return 0;
439 }
440
441 static int ident_to_str(const void *obj, const intptr_t *args, char **buf)
442 {
443         const struct ast_sip_endpoint *endpoint = obj;
444         int methods;
445         int idx;
446         int buf_used = 0;
447         int buf_size = MAX_OBJECT_FIELD;
448
449         methods = AST_VECTOR_SIZE(&endpoint->ident_method_order);
450         if (!methods) {
451                 return 0;
452         }
453
454         *buf = ast_malloc(buf_size);
455         if (!*buf) {
456                 return -1;
457         }
458
459         for (idx = 0; idx < methods; ++idx) {
460                 enum ast_sip_endpoint_identifier_type method;
461                 const char *method_str;
462
463                 method = AST_VECTOR_GET(&endpoint->ident_method_order, idx);
464                 method_str = sip_endpoint_identifier_type2str(method);
465
466                 /* Should never have an "<unknown>" method string */
467                 ast_assert(strcmp(method_str, "<unknown>"));
468                 if (!strcmp(method_str, "<unknown>")) {
469                         continue;
470                 }
471
472                 buf_used += snprintf(*buf + buf_used, buf_size - buf_used, "%s%s",
473                         method_str, idx < methods - 1 ? "," : "");
474                 if (buf_size <= buf_used) {
475                         /* Need more room than available, truncating. */
476                         *(*buf + (buf_size - 1)) = '\0';
477                         ast_log(LOG_WARNING, "Truncated identify_by string: %s\n", *buf);
478                         break;
479                 }
480         }
481
482         return 0;
483 }
484
485 static int redirect_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
486 {
487         struct ast_sip_endpoint *endpoint = obj;
488
489         if (!strcasecmp(var->value, "user")) {
490                 endpoint->redirect_method = AST_SIP_REDIRECT_USER;
491         } else if (!strcasecmp(var->value, "uri_core")) {
492                 endpoint->redirect_method = AST_SIP_REDIRECT_URI_CORE;
493         } else if (!strcasecmp(var->value, "uri_pjsip")) {
494                 endpoint->redirect_method = AST_SIP_REDIRECT_URI_PJSIP;
495         } else {
496                 ast_log(LOG_ERROR, "Unrecognized redirect method %s specified for endpoint %s\n",
497                         var->value, ast_sorcery_object_get_id(endpoint));
498                 return -1;
499         }
500
501         return 0;
502 }
503
504 static int direct_media_method_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
505 {
506         struct ast_sip_endpoint *endpoint = obj;
507
508         if (!strcasecmp(var->value, "invite") || !strcasecmp(var->value, "reinvite")) {
509                 endpoint->media.direct_media.method = AST_SIP_SESSION_REFRESH_METHOD_INVITE;
510         } else if (!strcasecmp(var->value, "update")) {
511                 endpoint->media.direct_media.method = AST_SIP_SESSION_REFRESH_METHOD_UPDATE;
512         } else {
513                 ast_log(LOG_NOTICE, "Unrecognized option value %s for %s on endpoint %s\n",
514                                 var->value, var->name, ast_sorcery_object_get_id(endpoint));
515                 return -1;
516         }
517         return 0;
518 }
519
520 static const char *id_configuration_refresh_methods[] = {
521         [AST_SIP_SESSION_REFRESH_METHOD_INVITE] = "invite",
522         [AST_SIP_SESSION_REFRESH_METHOD_UPDATE] = "update"
523 };
524
525 static int direct_media_method_to_str(const void *obj, const intptr_t *args, char **buf)
526 {
527         const struct ast_sip_endpoint *endpoint = obj;
528         if (ARRAY_IN_BOUNDS(endpoint->id.refresh_method, id_configuration_refresh_methods)) {
529                 *buf = ast_strdup(id_configuration_refresh_methods[endpoint->id.refresh_method]);
530         }
531         return 0;
532 }
533
534 static int connected_line_method_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
535 {
536         struct ast_sip_endpoint *endpoint = obj;
537
538         if (!strcasecmp(var->value, "invite") || !strcasecmp(var->value, "reinvite")) {
539                 endpoint->id.refresh_method = AST_SIP_SESSION_REFRESH_METHOD_INVITE;
540         } else if (!strcasecmp(var->value, "update")) {
541                 endpoint->id.refresh_method = AST_SIP_SESSION_REFRESH_METHOD_UPDATE;
542         } else {
543                 ast_log(LOG_NOTICE, "Unrecognized option value %s for %s on endpoint %s\n",
544                                 var->value, var->name, ast_sorcery_object_get_id(endpoint));
545                 return -1;
546         }
547         return 0;
548 }
549
550 static int connected_line_method_to_str(const void *obj, const intptr_t *args, char **buf)
551 {
552         const struct ast_sip_endpoint *endpoint = obj;
553         *buf = ast_strdup(id_configuration_refresh_methods[endpoint->id.refresh_method]);
554         return 0;
555 }
556
557 static int direct_media_glare_mitigation_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
558 {
559         struct ast_sip_endpoint *endpoint = obj;
560
561         if (!strcasecmp(var->value, "none")) {
562                 endpoint->media.direct_media.glare_mitigation = AST_SIP_DIRECT_MEDIA_GLARE_MITIGATION_NONE;
563         } else if (!strcasecmp(var->value, "outgoing")) {
564                 endpoint->media.direct_media.glare_mitigation = AST_SIP_DIRECT_MEDIA_GLARE_MITIGATION_OUTGOING;
565         } else if (!strcasecmp(var->value, "incoming")) {
566                 endpoint->media.direct_media.glare_mitigation = AST_SIP_DIRECT_MEDIA_GLARE_MITIGATION_INCOMING;
567         } else {
568                 ast_log(LOG_NOTICE, "Unrecognized option value %s for %s on endpoint %s\n",
569                                 var->value, var->name, ast_sorcery_object_get_id(endpoint));
570                 return -1;
571         }
572
573         return 0;
574 }
575
576 static const char *direct_media_glare_mitigation_map[] = {
577         [AST_SIP_DIRECT_MEDIA_GLARE_MITIGATION_NONE] = "none",
578         [AST_SIP_DIRECT_MEDIA_GLARE_MITIGATION_OUTGOING] = "outgoing",
579         [AST_SIP_DIRECT_MEDIA_GLARE_MITIGATION_INCOMING] = "incoming"
580 };
581
582 static int direct_media_glare_mitigation_to_str(const void *obj, const intptr_t *args, char **buf)
583 {
584         const struct ast_sip_endpoint *endpoint = obj;
585         if (ARRAY_IN_BOUNDS(endpoint->media.direct_media.glare_mitigation, direct_media_glare_mitigation_map)) {
586                 *buf = ast_strdup(direct_media_glare_mitigation_map[endpoint->media.direct_media.glare_mitigation]);
587         }
588
589         return 0;
590 }
591
592 static int caller_id_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
593 {
594         struct ast_sip_endpoint *endpoint = obj;
595         char cid_name[80] = { '\0' };
596         char cid_num[80] = { '\0' };
597
598         ast_free(endpoint->id.self.name.str);
599         endpoint->id.self.name.str = NULL;
600         endpoint->id.self.name.valid = 0;
601         ast_free(endpoint->id.self.number.str);
602         endpoint->id.self.number.str = NULL;
603         endpoint->id.self.number.valid = 0;
604
605         ast_callerid_split(var->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num));
606         if (!ast_strlen_zero(cid_name)) {
607                 endpoint->id.self.name.str = ast_strdup(cid_name);
608                 if (!endpoint->id.self.name.str) {
609                         return -1;
610                 }
611                 endpoint->id.self.name.valid = 1;
612         }
613         if (!ast_strlen_zero(cid_num)) {
614                 endpoint->id.self.number.str = ast_strdup(cid_num);
615                 if (!endpoint->id.self.number.str) {
616                         return -1;
617                 }
618                 endpoint->id.self.number.valid = 1;
619         }
620         return 0;
621 }
622
623 static int caller_id_to_str(const void *obj, const intptr_t *args, char **buf)
624 {
625         const struct ast_sip_endpoint *endpoint = obj;
626         const char *name = S_COR(endpoint->id.self.name.valid,
627                                  endpoint->id.self.name.str, NULL);
628         const char *number = S_COR(endpoint->id.self.number.valid,
629                                    endpoint->id.self.number.str, NULL);
630
631         /* make sure size is at least 10 - that should cover the "<unknown>"
632            case as well as any additional formatting characters added in
633            the name and/or number case. */
634         int size = 10;
635         size += name ? strlen(name) : 0;
636         size += number ? strlen(number) : 0;
637
638         if (!(*buf = ast_calloc(size + 1, sizeof(char)))) {
639                 return -1;
640         }
641
642         ast_callerid_merge(*buf, size + 1, name, number, NULL);
643         return 0;
644 }
645
646 static int caller_id_privacy_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
647 {
648         struct ast_sip_endpoint *endpoint = obj;
649         int callingpres = ast_parse_caller_presentation(var->value);
650         if (callingpres == -1 && sscanf(var->value, "%d", &callingpres) != 1) {
651                 return -1;
652         }
653         endpoint->id.self.number.presentation = callingpres;
654         endpoint->id.self.name.presentation = callingpres;
655         return 0;
656 }
657
658 static int caller_id_privacy_to_str(const void *obj, const intptr_t *args, char **buf)
659 {
660         const struct ast_sip_endpoint *endpoint = obj;
661         const char *presentation = ast_named_caller_presentation(
662                 endpoint->id.self.name.presentation);
663
664         *buf = ast_strdup(presentation);
665         return 0;
666 }
667
668 static int caller_id_tag_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
669 {
670         struct ast_sip_endpoint *endpoint = obj;
671
672         ast_free(endpoint->id.self.tag);
673         endpoint->id.self.tag = ast_strdup(var->value);
674
675         return endpoint->id.self.tag ? 0 : -1;
676 }
677
678 static int caller_id_tag_to_str(const void *obj, const intptr_t *args, char **buf)
679 {
680         const struct ast_sip_endpoint *endpoint = obj;
681         *buf = ast_strdup(endpoint->id.self.tag);
682         return 0;
683 }
684
685 static int media_encryption_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
686 {
687         struct ast_sip_endpoint *endpoint = obj;
688
689         if (!strcasecmp("no", var->value)) {
690                 endpoint->media.rtp.encryption = AST_SIP_MEDIA_ENCRYPT_NONE;
691         } else if (!strcasecmp("sdes", var->value)) {
692                 endpoint->media.rtp.encryption = AST_SIP_MEDIA_ENCRYPT_SDES;
693         } else if (!strcasecmp("dtls", var->value)) {
694                 endpoint->media.rtp.encryption = AST_SIP_MEDIA_ENCRYPT_DTLS;
695                 return ast_rtp_dtls_cfg_parse(&endpoint->media.rtp.dtls_cfg, "dtlsenable", "yes");
696         } else {
697                 return -1;
698         }
699
700         return 0;
701 }
702
703 static const char *media_encryption_map[] = {
704         [AST_SIP_MEDIA_TRANSPORT_INVALID] = "invalid",
705         [AST_SIP_MEDIA_ENCRYPT_NONE] = "no",
706         [AST_SIP_MEDIA_ENCRYPT_SDES] = "sdes",
707         [AST_SIP_MEDIA_ENCRYPT_DTLS] = "dtls",
708 };
709
710 static int media_encryption_to_str(const void *obj, const intptr_t *args, char **buf)
711 {
712         const struct ast_sip_endpoint *endpoint = obj;
713         if (ARRAY_IN_BOUNDS(endpoint->media.rtp.encryption, media_encryption_map)) {
714                 *buf = ast_strdup(media_encryption_map[
715                                           endpoint->media.rtp.encryption]);
716         }
717         return 0;
718 }
719
720 static int group_handler(const struct aco_option *opt,
721                          struct ast_variable *var, void *obj)
722 {
723         struct ast_sip_endpoint *endpoint = obj;
724
725         if (!strncmp(var->name, "call_group", 10)) {
726                 endpoint->pickup.callgroup = ast_get_group(var->value);
727         } else if (!strncmp(var->name, "pickup_group", 12)) {
728                 endpoint->pickup.pickupgroup = ast_get_group(var->value);
729         } else {
730                 return -1;
731         }
732
733         return 0;
734 }
735
736 static int callgroup_to_str(const void *obj, const intptr_t *args, char **buf)
737 {
738         const struct ast_sip_endpoint *endpoint = obj;
739
740         if (!(*buf = ast_calloc(MAX_OBJECT_FIELD, sizeof(char)))) {
741                 return -1;
742         }
743
744         ast_print_group(*buf, MAX_OBJECT_FIELD, endpoint->pickup.callgroup);
745         return 0;
746 }
747
748 static int pickupgroup_to_str(const void *obj, const intptr_t *args, char **buf)
749 {
750         const struct ast_sip_endpoint *endpoint = obj;
751
752         if (!(*buf = ast_calloc(MAX_OBJECT_FIELD, sizeof(char)))) {
753                 return -1;
754         }
755
756         ast_print_group(*buf, MAX_OBJECT_FIELD, endpoint->pickup.pickupgroup);
757         return 0;
758 }
759
760 static int named_groups_handler(const struct aco_option *opt,
761                                 struct ast_variable *var, void *obj)
762 {
763         struct ast_sip_endpoint *endpoint = obj;
764
765         if (!strncmp(var->name, "named_call_group", 16)) {
766                 if (ast_strlen_zero(var->value)) {
767                         endpoint->pickup.named_callgroups =
768                                 ast_unref_namedgroups(endpoint->pickup.named_callgroups);
769                 } else if (!(endpoint->pickup.named_callgroups =
770                       ast_get_namedgroups(var->value))) {
771                         return -1;
772                 }
773         } else if (!strncmp(var->name, "named_pickup_group", 18)) {
774                 if (ast_strlen_zero(var->value)) {
775                         endpoint->pickup.named_pickupgroups =
776                                 ast_unref_namedgroups(endpoint->pickup.named_pickupgroups);
777                 } else if (!(endpoint->pickup.named_pickupgroups =
778                       ast_get_namedgroups(var->value))) {
779                         return -1;
780                 }
781         } else {
782                 return -1;
783         }
784
785         return 0;
786 }
787
788 static int named_callgroups_to_str(const void *obj, const intptr_t *args, char **buf)
789 {
790         const struct ast_sip_endpoint *endpoint = obj;
791         RAII_VAR(struct ast_str *, str, ast_str_create(MAX_OBJECT_FIELD), ast_free);
792
793         ast_print_namedgroups(&str, endpoint->pickup.named_callgroups);
794         *buf = ast_strdup(ast_str_buffer(str));
795         return 0;
796 }
797
798 static int named_pickupgroups_to_str(const void *obj, const intptr_t *args, char **buf)
799 {
800         const struct ast_sip_endpoint *endpoint = obj;
801         RAII_VAR(struct ast_str *, str, ast_str_create(MAX_OBJECT_FIELD), ast_free);
802
803         ast_print_namedgroups(&str, endpoint->pickup.named_pickupgroups);
804         *buf = ast_strdup(ast_str_buffer(str));
805         return 0;
806 }
807
808 static int dtls_handler(const struct aco_option *opt,
809                          struct ast_variable *var, void *obj)
810 {
811         struct ast_sip_endpoint *endpoint = obj;
812         char *name = ast_strdupa(var->name);
813         char *front = NULL;
814         char *back = NULL;
815         char *buf = name;
816
817         /* strip out underscores in the name */
818         front = strtok_r(buf, "_", &back);
819         while (front) {
820                 int size = strlen(front);
821                 ast_copy_string(buf, front, size + 1);
822                 buf += size;
823                 front = strtok_r(NULL, "_", &back);
824         }
825
826         return ast_rtp_dtls_cfg_parse(&endpoint->media.rtp.dtls_cfg, name, var->value);
827 }
828
829 static int dtlsverify_to_str(const void *obj, const intptr_t *args, char **buf)
830 {
831         const struct ast_sip_endpoint *endpoint = obj;
832         *buf = ast_strdup(AST_YESNO(endpoint->media.rtp.dtls_cfg.verify));
833         return 0;
834 }
835
836 static int dtlsrekey_to_str(const void *obj, const intptr_t *args, char **buf)
837 {
838         const struct ast_sip_endpoint *endpoint = obj;
839
840         return ast_asprintf(
841                 buf, "%u", endpoint->media.rtp.dtls_cfg.rekey) >=0 ? 0 : -1;
842 }
843
844 static int dtlsautogeneratecert_to_str(const void *obj, const intptr_t *args, char **buf)
845 {
846         const struct ast_sip_endpoint *endpoint = obj;
847         *buf = ast_strdup(AST_YESNO(endpoint->media.rtp.dtls_cfg.ephemeral_cert));
848         return 0;
849 }
850
851 static int dtlscertfile_to_str(const void *obj, const intptr_t *args, char **buf)
852 {
853         const struct ast_sip_endpoint *endpoint = obj;
854         *buf = ast_strdup(endpoint->media.rtp.dtls_cfg.certfile);
855         return 0;
856 }
857
858 static int dtlsprivatekey_to_str(const void *obj, const intptr_t *args, char **buf)
859 {
860         const struct ast_sip_endpoint *endpoint = obj;
861         *buf = ast_strdup(endpoint->media.rtp.dtls_cfg.pvtfile);
862         return 0;
863 }
864
865 static int dtlscipher_to_str(const void *obj, const intptr_t *args, char **buf)
866 {
867         const struct ast_sip_endpoint *endpoint = obj;
868         *buf = ast_strdup(endpoint->media.rtp.dtls_cfg.cipher);
869         return 0;
870 }
871
872 static int dtlscafile_to_str(const void *obj, const intptr_t *args, char **buf)
873 {
874         const struct ast_sip_endpoint *endpoint = obj;
875         *buf = ast_strdup(endpoint->media.rtp.dtls_cfg.cafile);
876         return 0;
877 }
878
879 static int dtlscapath_to_str(const void *obj, const intptr_t *args, char **buf)
880 {
881         const struct ast_sip_endpoint *endpoint = obj;
882         *buf = ast_strdup(endpoint->media.rtp.dtls_cfg.capath);
883         return 0;
884 }
885
886 static const char *ast_rtp_dtls_setup_map[] = {
887         [AST_RTP_DTLS_SETUP_ACTIVE] = "active",
888         [AST_RTP_DTLS_SETUP_PASSIVE] = "passive",
889         [AST_RTP_DTLS_SETUP_ACTPASS] = "actpass",
890         [AST_RTP_DTLS_SETUP_HOLDCONN] = "holdconn",
891 };
892
893 static int dtlssetup_to_str(const void *obj, const intptr_t *args, char **buf)
894 {
895         const struct ast_sip_endpoint *endpoint = obj;
896         if (ARRAY_IN_BOUNDS(endpoint->media.rtp.dtls_cfg.default_setup, ast_rtp_dtls_setup_map)) {
897                 *buf = ast_strdup(ast_rtp_dtls_setup_map[endpoint->media.rtp.dtls_cfg.default_setup]);
898         }
899         return 0;
900 }
901
902 static const char *ast_rtp_dtls_fingerprint_map[] = {
903         [AST_RTP_DTLS_HASH_SHA256] = "SHA-256",
904         [AST_RTP_DTLS_HASH_SHA1] = "SHA-1",
905 };
906
907 static int dtlsfingerprint_to_str(const void *obj, const intptr_t *args, char **buf)
908 {
909         const struct ast_sip_endpoint *endpoint = obj;
910         if (ARRAY_IN_BOUNDS(endpoint->media.rtp.dtls_cfg.hash, ast_rtp_dtls_fingerprint_map)) {
911                 *buf = ast_strdup(ast_rtp_dtls_fingerprint_map[endpoint->media.rtp.dtls_cfg.hash]);
912         }
913         return 0;
914 }
915
916 static int t38udptl_ec_handler(const struct aco_option *opt,
917         struct ast_variable *var, void *obj)
918 {
919         struct ast_sip_endpoint *endpoint = obj;
920
921         if (!strcmp(var->value, "none")) {
922                 endpoint->media.t38.error_correction = UDPTL_ERROR_CORRECTION_NONE;
923         } else if (!strcmp(var->value, "fec")) {
924                 endpoint->media.t38.error_correction = UDPTL_ERROR_CORRECTION_FEC;
925         } else if (!strcmp(var->value, "redundancy")) {
926                 endpoint->media.t38.error_correction = UDPTL_ERROR_CORRECTION_REDUNDANCY;
927         } else {
928                 return -1;
929         }
930
931         return 0;
932 }
933
934 static const char *ast_t38_ec_modes_map[] = {
935         [UDPTL_ERROR_CORRECTION_NONE] = "none",
936         [UDPTL_ERROR_CORRECTION_FEC] = "fec",
937         [UDPTL_ERROR_CORRECTION_REDUNDANCY] = "redundancy"
938 };
939
940 static int t38udptl_ec_to_str(const void *obj, const intptr_t *args, char **buf)
941 {
942         const struct ast_sip_endpoint *endpoint = obj;
943         if (ARRAY_IN_BOUNDS(endpoint->media.t38.error_correction, ast_t38_ec_modes_map)) {
944                 *buf = ast_strdup(ast_t38_ec_modes_map[
945                                           endpoint->media.t38.error_correction]);
946         }
947         return 0;
948 }
949
950 static int tos_handler(const struct aco_option *opt,
951         struct ast_variable *var, void *obj)
952 {
953         struct ast_sip_endpoint *endpoint = obj;
954         unsigned int value;
955
956         if (ast_str2tos(var->value, &value)) {
957                 ast_log(LOG_ERROR, "Error configuring endpoint '%s' - Could not "
958                         "interpret '%s' value '%s'\n",
959                         ast_sorcery_object_get_id(endpoint), var->name, var->value);
960                 return -1;
961         }
962
963         if (!strcmp(var->name, "tos_audio")) {
964                 endpoint->media.tos_audio = value;
965         } else if (!strcmp(var->name, "tos_video")) {
966                 endpoint->media.tos_video = value;
967         } else {
968                 /* If we reach this point, someone called the tos_handler when they shouldn't have. */
969                 ast_assert(0);
970                 return -1;
971         }
972         return 0;
973 }
974
975 static int tos_audio_to_str(const void *obj, const intptr_t *args, char **buf)
976 {
977         const struct ast_sip_endpoint *endpoint = obj;
978
979         if (ast_asprintf(buf, "%u", endpoint->media.tos_audio) == -1) {
980                 return -1;
981         }
982         return 0;
983 }
984
985 static int tos_video_to_str(const void *obj, const intptr_t *args, char **buf)
986 {
987         const struct ast_sip_endpoint *endpoint = obj;
988
989         if (ast_asprintf(buf, "%u", endpoint->media.tos_video) == -1) {
990                 return -1;
991         }
992         return 0;
993 }
994
995 static int from_user_handler(const struct aco_option *opt,
996         struct ast_variable *var, void *obj)
997 {
998         struct ast_sip_endpoint *endpoint = obj;
999         /* Valid non-alphanumeric characters for URI */
1000         char *valid_uri_marks = "-._~%!$&'()*+,;=:";
1001         const char *val;
1002
1003         for (val = var->value; *val; val++) {
1004                 if (!isalpha(*val) && !isdigit(*val) && !strchr(valid_uri_marks, *val)) {
1005                         ast_log(LOG_ERROR, "Error configuring endpoint '%s' - '%s' field "
1006                         "contains invalid character '%c'\n",
1007                         ast_sorcery_object_get_id(endpoint), var->name, *val);
1008                         return -1;
1009                 }
1010         }
1011
1012         ast_string_field_set(endpoint, fromuser, var->value);
1013
1014         return 0;
1015 }
1016
1017 static int from_user_to_str(const void *obj, const intptr_t *args, char **buf)
1018 {
1019         const struct ast_sip_endpoint *endpoint = obj;
1020
1021         *buf = ast_strdup(endpoint->fromuser);
1022
1023         return 0;
1024 }
1025
1026 static int set_var_handler(const struct aco_option *opt,
1027         struct ast_variable *var, void *obj)
1028 {
1029         struct ast_sip_endpoint *endpoint = obj;
1030         struct ast_variable *new_var;
1031         char *name;
1032         char *val;
1033
1034         if (ast_strlen_zero(var->value)) {
1035                 return 0;
1036         }
1037
1038         name = ast_strdupa(var->value);
1039         val = strchr(name, '=');
1040
1041         if (!val) {
1042                 return -1;
1043         }
1044
1045         *val++ = '\0';
1046
1047         if (!(new_var = ast_variable_new(name, val, ""))) {
1048                 return -1;
1049         }
1050
1051         if (ast_variable_list_replace(&endpoint->channel_vars, new_var)) {
1052                 ast_variable_list_append(&endpoint->channel_vars, new_var);
1053         }
1054
1055         return 0;
1056 }
1057
1058 static int set_var_to_str(const void *obj, const intptr_t *args, char **buf)
1059 {
1060         struct ast_str *str = ast_str_create(MAX_OBJECT_FIELD);
1061         const struct ast_sip_endpoint *endpoint = obj;
1062         struct ast_variable *var;
1063
1064         for (var = endpoint->channel_vars; var; var = var->next) {
1065                 ast_str_append(&str, 0, "%s=%s,", var->name, var->value);
1066         }
1067
1068         *buf = ast_strdup(ast_str_truncate(str, -1));
1069         ast_free(str);
1070         return 0;
1071 }
1072
1073 static int set_var_to_vl(const void *obj, struct ast_variable **fields)
1074 {
1075         const struct ast_sip_endpoint *endpoint = obj;
1076         if (endpoint->channel_vars) {
1077                 *fields = ast_variables_dup(endpoint->channel_vars);
1078         }
1079         return 0;
1080 }
1081
1082 static int voicemail_extension_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
1083 {
1084         struct ast_sip_endpoint *endpoint = obj;
1085
1086         ast_free(endpoint->subscription.mwi.voicemail_extension);
1087         endpoint->subscription.mwi.voicemail_extension = ast_strdup(var->value);
1088
1089         return endpoint->subscription.mwi.voicemail_extension ? 0 : -1;
1090 }
1091
1092 static int voicemail_extension_to_str(const void *obj, const intptr_t *args, char **buf)
1093 {
1094         const struct ast_sip_endpoint *endpoint = obj;
1095
1096         *buf = ast_strdup(endpoint->subscription.mwi.voicemail_extension);
1097
1098         return 0;
1099 }
1100
1101 static int contact_user_handler(const struct aco_option *opt,
1102         struct ast_variable *var, void *obj)
1103 {
1104         struct ast_sip_endpoint *endpoint = obj;
1105
1106         ast_free(endpoint->contact_user);
1107         endpoint->contact_user = ast_strdup(var->value);
1108
1109         return endpoint->contact_user ? 0 : -1;
1110 }
1111
1112 static int contact_user_to_str(const void *obj, const intptr_t *args, char **buf)
1113 {
1114         const struct ast_sip_endpoint *endpoint = obj;
1115
1116         *buf = ast_strdup(endpoint->contact_user);
1117         if (!(*buf)) {
1118                 return -1;
1119         }
1120
1121         return 0;
1122 }
1123
1124 static int call_offer_pref_handler(const struct aco_option *opt,
1125         struct ast_variable *var, void *obj)
1126 {
1127         struct ast_sip_endpoint *endpoint = obj;
1128         struct ast_flags pref = { 0, };
1129         int outgoing = strcmp(var->name, "outgoing_call_offer_pref") == 0;
1130
1131         int res = ast_sip_call_codec_str_to_pref(&pref, var->value, outgoing);
1132         if (res != 0) {
1133                 return -1;
1134         }
1135
1136         if (outgoing) {
1137                 endpoint->media.outgoing_call_offer_pref = pref;
1138         } else {
1139                 endpoint->media.incoming_call_offer_pref = pref;
1140         }
1141
1142         return 0;
1143 }
1144
1145 static int incoming_call_offer_pref_to_str(const void *obj, const intptr_t *args, char **buf)
1146 {
1147         const struct ast_sip_endpoint *endpoint = obj;
1148
1149         *buf = ast_strdup(ast_sip_call_codec_pref_to_str(endpoint->media.incoming_call_offer_pref));
1150         if (!(*buf)) {
1151                 return -1;
1152         }
1153
1154         return 0;
1155 }
1156
1157 static int outgoing_call_offer_pref_to_str(const void *obj, const intptr_t *args, char **buf)
1158 {
1159         const struct ast_sip_endpoint *endpoint = obj;
1160
1161         *buf = ast_strdup(ast_sip_call_codec_pref_to_str(endpoint->media.outgoing_call_offer_pref));
1162         if (!(*buf)) {
1163                 return -1;
1164         }
1165
1166         return 0;
1167 }
1168
1169 static int codec_prefs_handler(const struct aco_option *opt,
1170         struct ast_variable *var, void *obj)
1171 {
1172         struct ast_sip_endpoint *endpoint = obj;
1173         struct ast_stream_codec_negotiation_prefs *option_prefs;
1174         struct ast_stream_codec_negotiation_prefs prefs;
1175         struct ast_str *error_message = ast_str_create(128);
1176         enum ast_stream_codec_negotiation_prefs_prefer_values default_prefer;
1177         enum ast_stream_codec_negotiation_prefs_operation_values default_operation;
1178         int res = 0;
1179
1180         res = ast_stream_codec_prefs_parse(var->value, &prefs, &error_message);
1181         if (res < 0) {
1182                 ast_log(LOG_ERROR, "Endpoint '%s': %s for option '%s'\n",
1183                         ast_sorcery_object_get_id(endpoint), ast_str_buffer(error_message), var->name);
1184                 ast_free(error_message);
1185                 return -1;
1186         }
1187         ast_free(error_message);
1188
1189         if (strcmp(var->name, "codec_prefs_incoming_offer") == 0) {
1190                 if (prefs.operation == CODEC_NEGOTIATION_OPERATION_UNION) {
1191                         ast_log(LOG_ERROR, "Endpoint '%s': Codec preference '%s' has invalid value '%s' for option: '%s'",
1192                                 ast_sorcery_object_get_id(endpoint),
1193                                 ast_stream_codec_param_to_str(CODEC_NEGOTIATION_PARAM_OPERATION),
1194                                 ast_stream_codec_operation_to_str(CODEC_NEGOTIATION_OPERATION_UNION),
1195                                 var->name);
1196                         return -1;
1197                 }
1198                 option_prefs = &endpoint->media.codec_prefs_incoming_offer;
1199                 default_prefer = CODEC_NEGOTIATION_PREFER_PENDING;
1200                 default_operation = CODEC_NEGOTIATION_OPERATION_INTERSECT;
1201         } else if (strcmp(var->name, "codec_prefs_outgoing_offer") == 0) {
1202                 option_prefs = &endpoint->media.codec_prefs_outgoing_offer;
1203                 default_prefer = CODEC_NEGOTIATION_PREFER_PENDING;
1204                 default_operation = CODEC_NEGOTIATION_OPERATION_UNION;
1205         } else if (strcmp(var->name, "codec_prefs_incoming_answer") == 0) {
1206                 option_prefs = &endpoint->media.codec_prefs_incoming_answer;
1207                 default_prefer = CODEC_NEGOTIATION_PREFER_PENDING;
1208                 default_operation = CODEC_NEGOTIATION_OPERATION_INTERSECT;
1209         } else if (strcmp(var->name, "codec_prefs_outgoing_answer") == 0) {
1210                 option_prefs = &endpoint->media.codec_prefs_outgoing_answer;
1211                 default_prefer = CODEC_NEGOTIATION_PREFER_PENDING;
1212                 default_operation = CODEC_NEGOTIATION_OPERATION_INTERSECT;
1213         } else {
1214                 ast_log(LOG_ERROR, "Endpoint '%s': Unsupported option '%s'\n",
1215                         ast_sorcery_object_get_id(endpoint),
1216                         var->name);
1217                 return -1;
1218         }
1219
1220         if (prefs.prefer == CODEC_NEGOTIATION_PREFER_UNSPECIFIED) {
1221                 prefs.prefer = default_prefer;
1222         }
1223
1224         if (prefs.operation == CODEC_NEGOTIATION_OPERATION_UNSPECIFIED) {
1225                 prefs.operation = default_operation;
1226         }
1227
1228         if (prefs.keep == CODEC_NEGOTIATION_KEEP_UNSPECIFIED) {
1229                 prefs.keep = CODEC_NEGOTIATION_KEEP_ALL;
1230         }
1231
1232         if (prefs.transcode == CODEC_NEGOTIATION_TRANSCODE_UNSPECIFIED) {
1233                 prefs.transcode = CODEC_NEGOTIATION_TRANSCODE_ALLOW;
1234         }
1235
1236         /* Now that defaults have been applied as needed we apply the full codec
1237          * preference configuration to the option.
1238          */
1239         *option_prefs = prefs;
1240
1241         return 0;
1242 }
1243
1244 static int codec_prefs_to_str(const struct ast_stream_codec_negotiation_prefs *prefs,
1245         const void *obj, const intptr_t *args, char **buf)
1246 {
1247         struct ast_str *codecs = ast_str_create(AST_STREAM_MAX_CODEC_PREFS_LENGTH);
1248
1249         if (!codecs) {
1250                 return -1;
1251         }
1252
1253         *buf = ast_strdup(ast_stream_codec_prefs_to_str(prefs, &codecs));
1254         ast_free(codecs);
1255
1256         return 0;
1257 }
1258
1259 static int incoming_offer_codec_prefs_to_str(const void *obj, const intptr_t *args, char **buf)
1260 {
1261         const struct ast_sip_endpoint *endpoint = obj;
1262         return codec_prefs_to_str(&endpoint->media.codec_prefs_incoming_offer, obj, args, buf);
1263 }
1264
1265 static int outgoing_offer_codec_prefs_to_str(const void *obj, const intptr_t *args, char **buf)
1266 {
1267         const struct ast_sip_endpoint *endpoint = obj;
1268         return codec_prefs_to_str(&endpoint->media.codec_prefs_outgoing_offer, obj, args, buf);
1269 }
1270
1271 static int incoming_answer_codec_prefs_to_str(const void *obj, const intptr_t *args, char **buf)
1272 {
1273         const struct ast_sip_endpoint *endpoint = obj;
1274         return codec_prefs_to_str(&endpoint->media.codec_prefs_incoming_answer, obj, args, buf);
1275 }
1276
1277 static int outgoing_answer_codec_prefs_to_str(const void *obj, const intptr_t *args, char **buf)
1278 {
1279         const struct ast_sip_endpoint *endpoint = obj;
1280         return codec_prefs_to_str(&endpoint->media.codec_prefs_outgoing_answer, obj, args, buf);
1281 }
1282
1283 static void *sip_nat_hook_alloc(const char *name)
1284 {
1285         return ast_sorcery_generic_alloc(sizeof(struct ast_sip_nat_hook), NULL);
1286 }
1287
1288 /*! \brief Destructor function for persistent endpoint information */
1289 static void persistent_endpoint_destroy(void *obj)
1290 {
1291         struct sip_persistent_endpoint *persistent = obj;
1292
1293         ast_endpoint_shutdown(persistent->endpoint);
1294 }
1295
1296 static int add_to_regcontext(void *obj, void *arg, int flags)
1297 {
1298         struct sip_persistent_endpoint *persistent = obj;
1299         const char *regcontext = arg;
1300
1301         if (ast_endpoint_get_state(persistent->endpoint) == AST_ENDPOINT_ONLINE) {
1302                 if (!ast_exists_extension(NULL, regcontext, ast_endpoint_get_resource(
1303                                 persistent->endpoint), 1, NULL)) {
1304                         ast_add_extension(regcontext, 1, ast_endpoint_get_resource(persistent->endpoint), 1, NULL, NULL,
1305                                 "Noop", ast_strdup(ast_endpoint_get_resource(persistent->endpoint)), ast_free_ptr, "PJSIP");
1306                 }
1307         }
1308
1309         return 0;
1310 }
1311
1312 int ast_sip_persistent_endpoint_add_to_regcontext(const char *regcontext)
1313 {
1314         if (ast_strlen_zero(regcontext)) {
1315                 return 0;
1316         }
1317
1318         /* Make sure the regcontext exists */
1319         if (!ast_context_find_or_create(NULL, NULL, regcontext, "PJSIP")) {
1320                 ast_log(LOG_ERROR, "Failed to create regcontext '%s'\n", regcontext);
1321                 return -1;
1322         }
1323
1324         /* Add any online endpoints */
1325         ao2_callback(persistent_endpoints, OBJ_NODATA, add_to_regcontext, (void *)regcontext);
1326         return 0;
1327 }
1328
1329 int ast_sip_persistent_endpoint_update_state(const char *endpoint_name, enum ast_endpoint_state state)
1330 {
1331         struct sip_persistent_endpoint *persistent;
1332         struct ast_json *blob;
1333         char *regcontext;
1334
1335         persistent = ao2_find(persistent_endpoints, endpoint_name, OBJ_SEARCH_KEY);
1336         if (!persistent) {
1337                 return -1;
1338         }
1339
1340         /* If there was no state change, don't publish anything. */
1341         if (ast_endpoint_get_state(persistent->endpoint) == state) {
1342                 ao2_ref(persistent, -1);
1343                 return 0;
1344         }
1345
1346         regcontext = ast_sip_get_regcontext();
1347
1348         if (state == AST_ENDPOINT_ONLINE) {
1349                 ast_endpoint_set_state(persistent->endpoint, AST_ENDPOINT_ONLINE);
1350                 blob = ast_json_pack("{s: s}", "peer_status", "Reachable");
1351
1352                 if (!ast_strlen_zero(regcontext)) {
1353                         if (!ast_exists_extension(NULL, regcontext, ast_endpoint_get_resource(persistent->endpoint), 1, NULL)) {
1354                                 ast_add_extension(regcontext, 1, ast_endpoint_get_resource(persistent->endpoint), 1, NULL, NULL,
1355                                         "Noop", ast_strdup(ast_endpoint_get_resource(persistent->endpoint)), ast_free_ptr, "PJSIP");
1356                         }
1357                 }
1358
1359                 ast_verb(2, "Endpoint %s is now Reachable\n", ast_endpoint_get_resource(persistent->endpoint));
1360         } else {
1361                 ast_endpoint_set_state(persistent->endpoint, AST_ENDPOINT_OFFLINE);
1362                 blob = ast_json_pack("{s: s}", "peer_status", "Unreachable");
1363
1364                 if (!ast_strlen_zero(regcontext)) {
1365                         struct pbx_find_info q = { .stacklen = 0 };
1366
1367                         if (pbx_find_extension(NULL, NULL, &q, regcontext, ast_endpoint_get_resource(persistent->endpoint), 1, NULL, "", E_MATCH)) {
1368                                 ast_context_remove_extension(regcontext, ast_endpoint_get_resource(persistent->endpoint), 1, NULL);
1369                         }
1370                 }
1371
1372                 ast_verb(2, "Endpoint %s is now Unreachable\n", ast_endpoint_get_resource(persistent->endpoint));
1373         }
1374
1375         ast_free(regcontext);
1376
1377         ast_endpoint_blob_publish(persistent->endpoint, ast_endpoint_state_type(), blob);
1378         ast_json_unref(blob);
1379         ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_CACHABLE, "PJSIP/%s", ast_endpoint_get_resource(persistent->endpoint));
1380
1381         ao2_ref(persistent, -1);
1382
1383         return 0;
1384 }
1385
1386 void ast_sip_persistent_endpoint_publish_contact_state(const char *endpoint_name, const struct ast_sip_contact_status *contact_status)
1387 {
1388         struct sip_persistent_endpoint *persistent;
1389         struct ast_json *blob;
1390         char rtt[32];
1391
1392         persistent = ao2_find(persistent_endpoints, endpoint_name, OBJ_SEARCH_KEY);
1393         if (!persistent) {
1394                 return;
1395         }
1396
1397         snprintf(rtt, sizeof(rtt), "%" PRId64, contact_status->rtt);
1398         blob = ast_json_pack("{s: s, s: s, s: s, s: s, s: s}",
1399                 "contact_status", ast_sip_get_contact_status_label(contact_status->status),
1400                 "aor", contact_status->aor,
1401                 "uri", contact_status->uri,
1402                 "roundtrip_usec", rtt,
1403                 "endpoint_name", ast_endpoint_get_resource(persistent->endpoint));
1404         if (blob) {
1405                 ast_endpoint_blob_publish(persistent->endpoint, ast_endpoint_contact_state_type(), blob);
1406                 ast_json_unref(blob);
1407         }
1408
1409         ao2_ref(persistent, -1);
1410 }
1411
1412 /*! \brief Internal function which finds (or creates) persistent endpoint information */
1413 static struct ast_endpoint *persistent_endpoint_find_or_create(const struct ast_sip_endpoint *endpoint)
1414 {
1415         RAII_VAR(struct sip_persistent_endpoint *, persistent, NULL, ao2_cleanup);
1416         SCOPED_AO2LOCK(lock, persistent_endpoints);
1417
1418         persistent = ao2_find(persistent_endpoints, ast_sorcery_object_get_id(endpoint),
1419                 OBJ_SEARCH_KEY | OBJ_NOLOCK);
1420         if (!persistent) {
1421                 persistent = ao2_alloc_options(sizeof(*persistent), persistent_endpoint_destroy,
1422                         AO2_ALLOC_OPT_LOCK_NOLOCK);
1423                 if (!persistent) {
1424                         return NULL;
1425                 }
1426
1427                 persistent->endpoint = ast_endpoint_create("PJSIP",
1428                         ast_sorcery_object_get_id(endpoint));
1429                 if (!persistent->endpoint) {
1430                         return NULL;
1431                 }
1432
1433                 ast_endpoint_set_state(persistent->endpoint, AST_ENDPOINT_OFFLINE);
1434
1435                 ao2_link_flags(persistent_endpoints, persistent, OBJ_NOLOCK);
1436         }
1437
1438         ao2_ref(persistent->endpoint, +1);
1439         return persistent->endpoint;
1440 }
1441
1442 /*! \brief Callback function for when an object is finalized */
1443 static int sip_endpoint_apply_handler(const struct ast_sorcery *sorcery, void *obj)
1444 {
1445         struct ast_sip_endpoint *endpoint = obj;
1446
1447         if (!(endpoint->persistent = persistent_endpoint_find_or_create(endpoint))) {
1448                 return -1;
1449         }
1450
1451         if (endpoint->extensions.timer.min_se < 90) {
1452                 ast_log(LOG_ERROR, "Session timer minimum expires time must be 90 or greater on endpoint '%s'\n",
1453                         ast_sorcery_object_get_id(endpoint));
1454                 return -1;
1455         } else if (endpoint->extensions.timer.sess_expires < endpoint->extensions.timer.min_se) {
1456                 ast_log(LOG_ERROR, "Session timer expires must be greater than minimum session expires time on endpoint '%s'\n",
1457                         ast_sorcery_object_get_id(endpoint));
1458                 return -1;
1459         }
1460
1461         if (ast_rtp_dtls_cfg_validate(&endpoint->media.rtp.dtls_cfg)) {
1462                 return -1;
1463         }
1464
1465         if (endpoint->preferred_codec_only) {
1466                 if (endpoint->media.incoming_call_offer_pref.flags != (AST_SIP_CALL_CODEC_PREF_LOCAL | AST_SIP_CALL_CODEC_PREF_INTERSECT | AST_SIP_CALL_CODEC_PREF_ALL)) {
1467                         ast_log(LOG_ERROR, "Setting both preferred_codec_only and incoming_call_offer_pref is not supported on endpoint '%s'\n",
1468                                 ast_sorcery_object_get_id(endpoint));
1469                         return -1;
1470                 }
1471                 ast_clear_flag(&endpoint->media.incoming_call_offer_pref, AST_SIP_CALL_CODEC_PREF_ALL);
1472                 ast_set_flag(&endpoint->media.incoming_call_offer_pref, AST_SIP_CALL_CODEC_PREF_FIRST);
1473         }
1474
1475         endpoint->media.topology = ast_stream_topology_create_from_format_cap(endpoint->media.codecs);
1476         if (!endpoint->media.topology) {
1477                 return -1;
1478         }
1479
1480         endpoint->media.rtcp_mux |= endpoint->media.bundle;
1481
1482         /*
1483          * If webrtc has been enabled then enable those attributes, and default
1484          * some, that are needed in order for webrtc to work.
1485          */
1486         endpoint->media.bundle |= endpoint->media.webrtc;
1487         endpoint->media.rtcp_mux |= endpoint->media.webrtc;
1488         endpoint->media.rtp.use_avpf |= endpoint->media.webrtc;
1489         endpoint->media.rtp.ice_support |= endpoint->media.webrtc;
1490         endpoint->media.rtp.use_received_transport |= endpoint->media.webrtc;
1491
1492         if (endpoint->media.webrtc) {
1493                 endpoint->media.rtp.encryption = AST_SIP_MEDIA_ENCRYPT_DTLS;
1494                 endpoint->media.rtp.dtls_cfg.enabled = 1;
1495                 endpoint->media.rtp.dtls_cfg.default_setup = AST_RTP_DTLS_SETUP_ACTPASS;
1496                 endpoint->media.rtp.dtls_cfg.verify = AST_RTP_DTLS_VERIFY_FINGERPRINT;
1497
1498                 if (ast_strlen_zero(endpoint->media.rtp.dtls_cfg.certfile)) {
1499                         /* If no certificate has been specified, try to automatically create one */
1500                         endpoint->media.rtp.dtls_cfg.ephemeral_cert = 1;
1501                 }
1502         }
1503
1504         return 0;
1505 }
1506
1507 const char *ast_sip_get_device_state(const struct ast_sip_endpoint *endpoint)
1508 {
1509         char device[MAX_OBJECT_FIELD];
1510
1511         snprintf(device, MAX_OBJECT_FIELD, "PJSIP/%s", ast_sorcery_object_get_id(endpoint));
1512         return ast_devstate2str(ast_device_state(device));
1513 }
1514
1515 struct ast_endpoint_snapshot *ast_sip_get_endpoint_snapshot(
1516         const struct ast_sip_endpoint *endpoint)
1517 {
1518         return ast_endpoint_latest_snapshot(
1519                 ast_endpoint_get_tech(endpoint->persistent),
1520                 ast_endpoint_get_resource(endpoint->persistent));
1521 }
1522
1523 int ast_sip_for_each_channel_snapshot(
1524         const struct ast_endpoint_snapshot *endpoint_snapshot,
1525         ao2_callback_fn on_channel_snapshot, void *arg)
1526 {
1527         int num, num_channels = endpoint_snapshot->num_channels;
1528
1529         if (!on_channel_snapshot || !num_channels) {
1530                 return 0;
1531         }
1532
1533         for (num = 0; num < num_channels; ++num) {
1534                 RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
1535                 int res;
1536
1537                 snapshot = ast_channel_snapshot_get_latest(endpoint_snapshot->channel_ids[num]);
1538                 if (!snapshot) {
1539                         continue;
1540                 }
1541
1542                 res = on_channel_snapshot(snapshot, arg, 0);
1543                 if (res) {
1544                         return -1;
1545                 }
1546         }
1547         return 0;
1548 }
1549
1550 int ast_sip_for_each_channel(
1551         const struct ast_sip_endpoint *endpoint,
1552         ao2_callback_fn on_channel_snapshot, void *arg)
1553 {
1554         RAII_VAR(struct ast_endpoint_snapshot *, endpoint_snapshot, ast_sip_get_endpoint_snapshot(endpoint), ao2_cleanup);
1555         return ast_sip_for_each_channel_snapshot(endpoint_snapshot, on_channel_snapshot, arg);
1556 }
1557
1558 static int active_channels_to_str_cb(void *object, void *arg, int flags)
1559 {
1560         const struct ast_channel_snapshot *snapshot = object;
1561         struct ast_str **buf = arg;
1562         ast_str_append(buf, 0, "%s,", snapshot->base->name);
1563         return 0;
1564 }
1565
1566 static void active_channels_to_str(const struct ast_sip_endpoint *endpoint,
1567                                    struct ast_str **str)
1568 {
1569
1570         RAII_VAR(struct ast_endpoint_snapshot *, endpoint_snapshot,
1571                  ast_sip_get_endpoint_snapshot(endpoint), ao2_cleanup);
1572
1573         if (endpoint_snapshot) {
1574                 return;
1575         }
1576
1577         ast_sip_for_each_channel_snapshot(endpoint_snapshot,
1578                                           active_channels_to_str_cb, str);
1579         ast_str_truncate(*str, -1);
1580 }
1581
1582 #define AMI_DEFAULT_STR_SIZE 512
1583
1584 struct ast_str *ast_sip_create_ami_event(const char *event, struct ast_sip_ami *ami)
1585 {
1586         struct ast_str *buf = ast_str_create(AMI_DEFAULT_STR_SIZE);
1587
1588         if (!(buf)) {
1589                 astman_send_error_va(ami->s, ami->m, "Unable create event "
1590                                      "for %s\n", event);
1591                 return NULL;
1592         }
1593
1594         ast_str_set(&buf, 0, "Event: %s\r\n", event);
1595         if (!ast_strlen_zero(ami->action_id)) {
1596                 ast_str_append(&buf, 0, "ActionID: %s\r\n", ami->action_id);
1597         }
1598         return buf;
1599 }
1600
1601 static void sip_sorcery_object_ami_set_type_name(const void *obj, struct ast_str **buf)
1602 {
1603         ast_str_append(buf, 0, "ObjectType: %s\r\n",
1604                        ast_sorcery_object_get_type(obj));
1605         ast_str_append(buf, 0, "ObjectName: %s\r\n",
1606                        ast_sorcery_object_get_id(obj));
1607 }
1608
1609 int ast_sip_sorcery_object_to_ami(const void *obj, struct ast_str **buf)
1610 {
1611         RAII_VAR(struct ast_variable *, objset, ast_sorcery_objectset_create2(
1612                          ast_sip_get_sorcery(), obj, AST_HANDLER_ONLY_STRING), ast_variables_destroy);
1613         struct ast_variable *i;
1614
1615         if (!objset) {
1616                 return -1;
1617         }
1618
1619         sip_sorcery_object_ami_set_type_name(obj, buf);
1620
1621         for (i = objset; i; i = i->next) {
1622                 RAII_VAR(char *, camel, ast_to_camel_case(i->name), ast_free);
1623                 ast_str_append(buf, 0, "%s: %s\r\n", camel, i->value);
1624         }
1625
1626         return 0;
1627 }
1628
1629 static int sip_endpoints_aors_ami(void *obj, void *arg, int flags)
1630 {
1631         struct ast_sip_aor *aor = obj;
1632         struct ast_str **buf = arg;
1633
1634         ast_str_append(buf, 0, "Contacts: ");
1635         ast_sip_for_each_contact(aor, ast_sip_contact_to_str, arg);
1636         ast_str_append(buf, 0, "\r\n");
1637
1638         return 0;
1639 }
1640
1641 static int sip_endpoint_to_ami(const struct ast_sip_endpoint *endpoint,
1642                                struct ast_str **buf)
1643 {
1644         if (ast_sip_sorcery_object_to_ami(endpoint, buf)) {
1645                 return -1;
1646         }
1647
1648         ast_str_append(buf, 0, "DeviceState: %s\r\n",
1649                        ast_sip_get_device_state(endpoint));
1650
1651         ast_str_append(buf, 0, "ActiveChannels: ");
1652         active_channels_to_str(endpoint, buf);
1653         ast_str_append(buf, 0, "\r\n");
1654
1655         return 0;
1656 }
1657
1658 static int format_ami_endpoint(const struct ast_sip_endpoint *endpoint,
1659                                struct ast_sip_ami *ami)
1660 {
1661         RAII_VAR(struct ast_str *, buf,
1662                  ast_sip_create_ami_event("EndpointDetail", ami), ast_free);
1663
1664         if (!buf) {
1665                 return -1;
1666         }
1667
1668         sip_endpoint_to_ami(endpoint, &buf);
1669         astman_append(ami->s, "%s\r\n", ast_str_buffer(buf));
1670         return 0;
1671 }
1672
1673 #define AMI_SHOW_ENDPOINTS "PJSIPShowEndpoints"
1674 #define AMI_SHOW_ENDPOINT "PJSIPShowEndpoint"
1675
1676 static int ami_show_endpoint(struct mansession *s, const struct message *m)
1677 {
1678         struct ast_sip_ami ami = { .s = s, .m = m, .action_id = astman_get_header(m, "ActionID"),
1679                 .count = 0, };
1680         RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);
1681         const char *endpoint_name = astman_get_header(m, "Endpoint");
1682         int count = 0;
1683
1684         if (ast_strlen_zero(endpoint_name)) {
1685                 astman_send_error_va(s, m, "%s requires an endpoint name\n",
1686                         AMI_SHOW_ENDPOINT);
1687                 return 0;
1688         }
1689
1690         if (!strncasecmp(endpoint_name, "pjsip/", 6)) {
1691                 endpoint_name += 6;
1692         }
1693
1694         if (!(endpoint = ast_sorcery_retrieve_by_id(
1695                       ast_sip_get_sorcery(), "endpoint", endpoint_name))) {
1696                 astman_send_error_va(s, m, "Unable to retrieve endpoint %s\n",
1697                         endpoint_name);
1698                 return 0;
1699         }
1700
1701         astman_send_listack(s, m, "Following are Events for each object associated with the Endpoint",
1702                 "start");
1703
1704         /* the endpoint detail needs to always come first so apply as such */
1705         if (format_ami_endpoint(endpoint, &ami) ||
1706             ast_sip_format_endpoint_ami(endpoint, &ami, &count)) {
1707                 astman_send_error_va(s, m, "Unable to format endpoint %s\n",
1708                         endpoint_name);
1709         }
1710
1711         astman_send_list_complete_start(s, m, "EndpointDetailComplete", ami.count + 1);
1712         astman_send_list_complete_end(s);
1713
1714         return 0;
1715 }
1716
1717 static int format_str_append_auth(const struct ast_sip_auth_vector *auths,
1718                                   struct ast_str **buf)
1719 {
1720         char *str = NULL;
1721         if (ast_sip_auths_to_str(auths, &str)) {
1722                 return -1;
1723         }
1724         ast_str_append(buf, 0, "%s", str ? str : "");
1725         ast_free(str);
1726         return 0;
1727 }
1728
1729 static int format_ami_endpoints(void *obj, void *arg, int flags)
1730 {
1731
1732         struct ast_sip_endpoint *endpoint = obj;
1733         struct ast_sip_ami *ami = arg;
1734         RAII_VAR(struct ast_str *, buf,
1735                  ast_sip_create_ami_event("EndpointList", ami), ast_free);
1736
1737         if (!buf) {
1738                 return CMP_STOP;
1739         }
1740
1741         sip_sorcery_object_ami_set_type_name(endpoint, &buf);
1742         ast_str_append(&buf, 0, "Transport: %s\r\n",
1743                        endpoint->transport);
1744         ast_str_append(&buf, 0, "Aor: %s\r\n",
1745                        endpoint->aors);
1746
1747         ast_str_append(&buf, 0, "Auths: ");
1748         format_str_append_auth(&endpoint->inbound_auths, &buf);
1749         ast_str_append(&buf, 0, "\r\n");
1750
1751         ast_str_append(&buf, 0, "OutboundAuths: ");
1752         format_str_append_auth(&endpoint->outbound_auths, &buf);
1753         ast_str_append(&buf, 0, "\r\n");
1754
1755         ast_sip_for_each_aor(endpoint->aors,
1756                              sip_endpoints_aors_ami, &buf);
1757
1758         ast_str_append(&buf, 0, "DeviceState: %s\r\n",
1759                        ast_sip_get_device_state(endpoint));
1760
1761         ast_str_append(&buf, 0, "ActiveChannels: ");
1762         active_channels_to_str(endpoint, &buf);
1763         ast_str_append(&buf, 0, "\r\n");
1764
1765         astman_append(ami->s, "%s\r\n", ast_str_buffer(buf));
1766         return 0;
1767 }
1768
1769 static int ami_show_endpoints(struct mansession *s, const struct message *m)
1770 {
1771         struct ast_sip_ami ami = { .s = s, .m = m, .action_id = astman_get_header(m, "ActionID"), };
1772         RAII_VAR(struct ao2_container *, endpoints, NULL, ao2_cleanup);
1773         int num;
1774
1775         endpoints = ast_sip_get_endpoints();
1776         if (!endpoints) {
1777                 astman_send_error(s, m, "Could not get endpoints\n");
1778                 return 0;
1779         }
1780
1781         if (!(num = ao2_container_count(endpoints))) {
1782                 astman_send_error(s, m, "No endpoints found\n");
1783                 return 0;
1784         }
1785
1786         astman_send_listack(s, m, "A listing of Endpoints follows, presented as EndpointList events",
1787                 "start");
1788
1789         ao2_callback(endpoints, OBJ_NODATA, format_ami_endpoints, &ami);
1790
1791         astman_send_list_complete_start(s, m, "EndpointListComplete", num);
1792         astman_send_list_complete_end(s);
1793         return 0;
1794 }
1795
1796 static struct ao2_container *cli_endpoint_get_container(const char *regex)
1797 {
1798         RAII_VAR(struct ao2_container *, container, NULL, ao2_cleanup);
1799         struct ao2_container *s_container;
1800
1801         container = ast_sorcery_retrieve_by_regex(sip_sorcery, "endpoint", regex);
1802         if (!container) {
1803                 return NULL;
1804         }
1805
1806         s_container = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, 0,
1807                 (void *)ast_sorcery_object_id_sort, (void *)ast_sorcery_object_id_compare);
1808         if (!s_container) {
1809                 return NULL;
1810         }
1811
1812         if (ao2_container_dup(s_container, container, 0)) {
1813                 ao2_ref(s_container, -1);
1814                 return NULL;
1815         }
1816
1817         return s_container;
1818 }
1819
1820 static int cli_endpoint_iterate(void *obj, ao2_callback_fn callback, void *args)
1821 {
1822         ao2_callback(obj, OBJ_NODATA, callback, args);
1823
1824         return 0;
1825 }
1826
1827 static void *cli_endpoint_retrieve_by_id(const char *id)
1828 {
1829         return ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", id);
1830 }
1831
1832 static void cli_endpoint_print_child_header(char *type, struct ast_sip_cli_context *context)
1833 {
1834         RAII_VAR(struct ast_sip_cli_formatter_entry *, formatter_entry, NULL, ao2_cleanup);
1835
1836         formatter_entry = ast_sip_lookup_cli_formatter(type);
1837         if (formatter_entry) {
1838                 formatter_entry->print_header(NULL, context, 0);
1839         }
1840 }
1841
1842 static int cli_endpoint_print_header(void *obj, void *arg, int flags)
1843 {
1844         struct ast_sip_cli_context *context = arg;
1845
1846         ast_assert(context->output_buffer != NULL);
1847
1848         ast_str_append(&context->output_buffer, 0,
1849                         " Endpoint:  <Endpoint/CID.....................................>  <State.....>  <Channels.>\n");
1850
1851         if (context->recurse) {
1852                 context->indent_level++;
1853                 cli_endpoint_print_child_header("auth", context);
1854                 cli_endpoint_print_child_header("aor", context);
1855                 cli_endpoint_print_child_header("transport", context);
1856                 cli_endpoint_print_child_header("identify", context);
1857                 cli_endpoint_print_child_header("channel", context);
1858                 context->indent_level--;
1859         }
1860
1861         return 0;
1862 }
1863
1864 static void cli_endpoint_print_child_body(char *type, const void *obj, struct ast_sip_cli_context *context)
1865 {
1866         RAII_VAR(struct ast_sip_cli_formatter_entry *, formatter_entry, NULL, ao2_cleanup);
1867
1868         formatter_entry = ast_sip_lookup_cli_formatter(type);
1869         if (formatter_entry) {
1870                 formatter_entry->iterate((void *)obj, formatter_entry->print_body, context);
1871         }
1872 }
1873
1874 static int cli_endpoint_print_body(void *obj, void *arg, int flags)
1875 {
1876         struct ast_sip_endpoint *endpoint = obj;
1877         RAII_VAR(struct ast_endpoint_snapshot *, endpoint_snapshot, ast_sip_get_endpoint_snapshot(endpoint), ao2_cleanup);
1878         struct ast_sip_cli_context *context = arg;
1879         const char *id = ast_sorcery_object_get_id(endpoint);
1880         char *print_name = NULL;
1881         int print_name_len;
1882         char *number = S_COR(endpoint->id.self.number.valid,
1883                 endpoint->id.self.number.str, NULL);
1884         int indent;
1885         int flexwidth;
1886
1887         ast_assert(context->output_buffer != NULL);
1888
1889         if (number) {
1890                 print_name_len = strlen(id) + strlen(number) + 2;
1891                 print_name = ast_alloca(print_name_len);
1892                 snprintf(print_name, print_name_len, "%s/%s", id, number);
1893         }
1894
1895         indent = CLI_INDENT_TO_SPACES(context->indent_level);
1896         flexwidth = CLI_LAST_TABSTOP - indent - 2;
1897
1898         ast_str_append(&context->output_buffer, 0, "%*s:  %-*.*s  %-12.12s  %d of %.0f\n",
1899                 indent, "Endpoint",
1900                 flexwidth, flexwidth, print_name ? print_name : id,
1901                 ast_sip_get_device_state(endpoint),
1902                 endpoint_snapshot->num_channels,
1903                 (double) endpoint->devicestate_busy_at ? endpoint->devicestate_busy_at :
1904                                                                                                                 INFINITY
1905                                                                                                                 );
1906
1907         if (context->recurse) {
1908                 context->indent_level++;
1909
1910                 context->auth_direction = "Out";
1911                 cli_endpoint_print_child_body("auth", &endpoint->outbound_auths, context);
1912                 context->auth_direction = "In";
1913                 cli_endpoint_print_child_body("auth", &endpoint->inbound_auths, context);
1914
1915                 cli_endpoint_print_child_body("aor", endpoint->aors, context);
1916                 cli_endpoint_print_child_body("transport", endpoint, context);
1917                 cli_endpoint_print_child_body("identify", endpoint, context);
1918                 cli_endpoint_print_child_body("channel", endpoint, context);
1919
1920                 context->indent_level--;
1921
1922                 if (context->indent_level == 0) {
1923                         ast_str_append(&context->output_buffer, 0, "\n");
1924                 }
1925         }
1926
1927         if (context->show_details || (context->show_details_only_level_0 && context->indent_level == 0)) {
1928                 ast_str_append(&context->output_buffer, 0, "\n");
1929                 ast_sip_cli_print_sorcery_objectset(endpoint, context, 0);
1930         }
1931
1932         return 0;
1933 }
1934
1935 static struct ast_cli_entry cli_commands[] = {
1936         AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "List PJSIP Endpoints",
1937                 .command = "pjsip list endpoints",
1938                 .usage = "Usage: pjsip list endpoints [ like <pattern> ]\n"
1939                                 "       List the configured PJSIP endpoints\n"
1940                                 "       Optional regular expression pattern is used to filter the list.\n"),
1941         AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "Show PJSIP Endpoints",
1942                 .command = "pjsip show endpoints",
1943                 .usage = "Usage: pjsip show endpoints [ like <pattern> ]\n"
1944                                 "       List(detailed) the configured PJSIP endpoints\n"
1945                                 "       Optional regular expression pattern is used to filter the list.\n"),
1946         AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "Show PJSIP Endpoint",
1947                 .command = "pjsip show endpoint",
1948                 .usage = "Usage: pjsip show endpoint <id>\n"
1949                                  "       Show the configured PJSIP endpoint\n"),
1950 };
1951
1952 struct ast_sip_cli_formatter_entry *channel_formatter;
1953 struct ast_sip_cli_formatter_entry *endpoint_formatter;
1954
1955 static void load_all_endpoints(void)
1956 {
1957         struct ao2_container *endpoints;
1958
1959         endpoints = ast_sorcery_retrieve_by_fields(sip_sorcery, "endpoint", AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
1960         ao2_cleanup(endpoints);
1961 }
1962
1963 static void acl_change_stasis_cb(void *data, struct stasis_subscription *sub,
1964         struct stasis_message *message)
1965 {
1966         if (stasis_message_type(message) != ast_named_acl_change_type()) {
1967                 return;
1968         }
1969
1970         ast_sorcery_force_reload_object(sip_sorcery, "endpoint");
1971 }
1972
1973 int ast_res_pjsip_initialize_configuration(void)
1974 {
1975         if (ast_manager_register_xml(AMI_SHOW_ENDPOINTS, EVENT_FLAG_SYSTEM, ami_show_endpoints) ||
1976             ast_manager_register_xml(AMI_SHOW_ENDPOINT, EVENT_FLAG_SYSTEM, ami_show_endpoint)) {
1977                 return -1;
1978         }
1979
1980         persistent_endpoints = ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_MUTEX, 0,
1981                 PERSISTENT_BUCKETS, persistent_endpoint_hash, NULL, persistent_endpoint_cmp);
1982         if (!persistent_endpoints) {
1983                 return -1;
1984         }
1985
1986         if (!(sip_sorcery = ast_sorcery_open())) {
1987                 ast_log(LOG_ERROR, "Failed to open SIP sorcery failed to open\n");
1988                 return -1;
1989         }
1990
1991         ast_sip_initialize_cli();
1992
1993         if (ast_sip_initialize_sorcery_auth()) {
1994                 ast_log(LOG_ERROR, "Failed to register SIP authentication support\n");
1995                 ast_sorcery_unref(sip_sorcery);
1996                 sip_sorcery = NULL;
1997                 return -1;
1998         }
1999
2000         ast_sorcery_apply_default(sip_sorcery, "endpoint", "config", "pjsip.conf,criteria=type=endpoint");
2001         ast_sorcery_apply_default(sip_sorcery, "nat_hook", "memory", NULL);
2002
2003         if (ast_sorcery_object_register(sip_sorcery, "endpoint", ast_sip_endpoint_alloc, NULL, sip_endpoint_apply_handler)) {
2004                 ast_log(LOG_ERROR, "Failed to register SIP endpoint object with sorcery\n");
2005                 ast_sorcery_unref(sip_sorcery);
2006                 sip_sorcery = NULL;
2007                 return -1;
2008         }
2009
2010         if (ast_sorcery_internal_object_register(sip_sorcery, "nat_hook", sip_nat_hook_alloc, NULL, NULL)) {
2011                 ast_log(LOG_ERROR, "Failed to register nat_hook\n");
2012         }
2013
2014         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "type", "", OPT_NOOP_T, 0, 0);
2015         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "context", "default", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, context));
2016         ast_sorcery_object_field_register_alias(sip_sorcery, "endpoint", "disallow", "", OPT_CODEC_T, 0, FLDSET(struct ast_sip_endpoint, media.codecs));
2017         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "allow", "", OPT_CODEC_T, 1, FLDSET(struct ast_sip_endpoint, media.codecs));
2018         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtmf_mode", "rfc4733", dtmf_handler, dtmf_to_str, NULL, 0, 0);
2019         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "rtp_ipv6", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.ipv6));
2020         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "rtp_symmetric", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.symmetric));
2021         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "ice_support", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.ice_support));
2022         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "use_ptime", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.use_ptime));
2023         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "force_rport", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, nat.force_rport));
2024         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "rewrite_contact", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, nat.rewrite_contact));
2025         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "transport", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, transport));
2026         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "outbound_proxy", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, outbound_proxy));
2027         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "moh_suggest", "default", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, mohsuggest));
2028         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "100rel", "yes", prack_handler, prack_to_str, NULL, 0, 0);
2029         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "timers", "yes", timers_handler, timers_to_str, NULL, 0, 0);
2030         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "timers_min_se", "90", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, extensions.timer.min_se));
2031         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "timers_sess_expires", "1800", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, extensions.timer.sess_expires));
2032         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "auth", "", inbound_auth_handler, inbound_auths_to_str, NULL, 0, 0);
2033         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "outbound_auth", "", outbound_auth_handler, outbound_auths_to_str, NULL, 0, 0);
2034         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "aors", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, aors));
2035         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "media_address", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, media.address));
2036         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "bind_rtp_to_media_address", "no", OPT_BOOL_T, 1, STRFLDSET(struct ast_sip_endpoint, media.bind_rtp_to_media_address));
2037         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "identify_by", "username,ip", ident_handler, ident_to_str, NULL, 0, 0);
2038         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "direct_media", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.direct_media.enabled));
2039         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "direct_media_method", "invite", direct_media_method_handler, direct_media_method_to_str, NULL, 0, 0);
2040         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "trust_connected_line", "yes", OPT_YESNO_T, 1, FLDSET(struct ast_sip_endpoint, id.trust_connected_line));
2041         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "send_connected_line", "yes", OPT_YESNO_T, 1, FLDSET(struct ast_sip_endpoint, id.send_connected_line));
2042         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "connected_line_method", "invite", connected_line_method_handler, connected_line_method_to_str, NULL, 0, 0);
2043         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "direct_media_glare_mitigation", "none", direct_media_glare_mitigation_handler, direct_media_glare_mitigation_to_str, NULL, 0, 0);
2044         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "disable_direct_media_on_nat", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.direct_media.disable_on_nat));
2045         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "callerid", "", caller_id_handler, caller_id_to_str, NULL, 0, 0);
2046         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "callerid_privacy", "allowed_not_screened", caller_id_privacy_handler, caller_id_privacy_to_str, NULL, 0, 0);
2047         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "callerid_tag", "", caller_id_tag_handler, caller_id_tag_to_str, NULL, 0, 0);
2048         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "trust_id_inbound", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, id.trust_inbound));
2049         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "trust_id_outbound", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, id.trust_outbound));
2050         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "send_pai", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, id.send_pai));
2051         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "send_rpid", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, id.send_rpid));
2052         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "rpid_immediate", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, id.rpid_immediate));
2053         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "send_diversion", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, id.send_diversion));
2054         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "send_history_info", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, id.send_history_info));
2055         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "mailboxes", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, subscription.mwi.mailboxes));
2056         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "voicemail_extension", "", voicemail_extension_handler, voicemail_extension_to_str, NULL, 0, 0);
2057         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "aggregate_mwi", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, subscription.mwi.aggregate));
2058         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "mwi_subscribe_replaces_unsolicited", "no", OPT_YESNO_T, 1, FLDSET(struct ast_sip_endpoint, subscription.mwi.subscribe_replaces_unsolicited));
2059         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "media_encryption", "no", media_encryption_handler, media_encryption_to_str, NULL, 0, 0);
2060         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "use_avpf", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.use_avpf));
2061         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "force_avp", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.force_avp));
2062         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "media_use_received_transport", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.use_received_transport));
2063         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "rtp_keepalive", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, media.rtp.keepalive));
2064         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "rtp_timeout", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, media.rtp.timeout));
2065         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "rtp_timeout_hold", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, media.rtp.timeout_hold));
2066         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "one_touch_recording", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, info.recording.enabled));
2067         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "inband_progress", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, inband_progress));
2068         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "call_group", "", group_handler, callgroup_to_str, NULL, 0, 0);
2069         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "pickup_group", "", group_handler, pickupgroup_to_str, NULL, 0, 0);
2070         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "named_call_group", "", named_groups_handler, named_callgroups_to_str, NULL, 0, 0);
2071         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "named_pickup_group", "", named_groups_handler, named_pickupgroups_to_str, NULL, 0, 0);
2072         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "device_state_busy_at", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, devicestate_busy_at));
2073         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "t38_udptl", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.t38.enabled));
2074         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "t38_udptl_ec", "none", t38udptl_ec_handler, t38udptl_ec_to_str, NULL, 0, 0);
2075         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "t38_udptl_maxdatagram", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, media.t38.maxdatagram));
2076         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "fax_detect", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, faxdetect));
2077         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "fax_detect_timeout", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, faxdetect_timeout));
2078         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "t38_udptl_nat", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.t38.nat));
2079         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "t38_udptl_ipv6", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.t38.ipv6));
2080         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "tone_zone", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, zone));
2081         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "language", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, language));
2082         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "record_on_feature", "automixmon", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, info.recording.onfeature));
2083         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "record_off_feature", "automixmon", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, info.recording.offfeature));
2084         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "allow_transfer", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, allowtransfer));
2085         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "user_eq_phone", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, usereqphone));
2086         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "moh_passthrough", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, moh_passthrough));
2087         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "sdp_owner", "-", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, media.sdpowner));
2088         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "sdp_session", "Asterisk", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, media.sdpsession));
2089         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "tos_audio", "0", tos_handler, tos_audio_to_str, NULL, 0, 0);
2090         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "tos_video", "0", tos_handler, tos_video_to_str, NULL, 0, 0);
2091         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "cos_audio", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, media.cos_audio));
2092         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "cos_video", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, media.cos_video));
2093         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "allow_subscribe", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, subscription.allow));
2094         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "sub_min_expiry", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, subscription.minexpiry));
2095         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "from_user", "", from_user_handler, from_user_to_str, NULL, 0, 0);
2096         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "from_domain", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, fromdomain));
2097         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "mwi_from_user", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, subscription.mwi.fromuser));
2098         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "rtp_engine", "asterisk", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, media.rtp.engine));
2099         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_verify", "no", dtls_handler, dtlsverify_to_str, NULL, 0, 0);
2100         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_rekey", "0", dtls_handler, dtlsrekey_to_str, NULL, 0, 0);
2101         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_auto_generate_cert", "no", dtls_handler, dtlsautogeneratecert_to_str, NULL, 0, 0);
2102         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_cert_file", "", dtls_handler, dtlscertfile_to_str, NULL, 0, 0);
2103         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_private_key", "", dtls_handler, dtlsprivatekey_to_str, NULL, 0, 0);
2104         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_cipher", "", dtls_handler, dtlscipher_to_str, NULL, 0, 0);
2105         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_ca_file", "", dtls_handler, dtlscafile_to_str, NULL, 0, 0);
2106         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_ca_path", "", dtls_handler, dtlscapath_to_str, NULL, 0, 0);
2107         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_setup", "", dtls_handler, dtlssetup_to_str, NULL, 0, 0);
2108         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_fingerprint", "", dtls_handler, dtlsfingerprint_to_str, NULL, 0, 0);
2109         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "srtp_tag_32", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.srtp_tag_32));
2110         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "media_encryption_optimistic", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.encryption_optimistic));
2111         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "g726_non_standard", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.g726_non_standard));
2112         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "redirect_method", "user", redirect_handler, NULL, NULL, 0, 0);
2113         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "set_var", "", set_var_handler, set_var_to_str, set_var_to_vl, 0, 0);
2114         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "message_context", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, message_context));
2115         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "accountcode", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, accountcode));
2116         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "deny", "", endpoint_acl_handler, NULL, NULL, 0, 0);
2117         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "permit", "", endpoint_acl_handler, NULL, NULL, 0, 0);
2118         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "acl", "", endpoint_acl_handler, acl_to_str, NULL, 0, 0);
2119         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "contact_deny", "", endpoint_acl_handler, NULL, NULL, 0, 0);
2120         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "contact_permit", "", endpoint_acl_handler, NULL, NULL, 0, 0);
2121         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "contact_acl", "", endpoint_acl_handler, contact_acl_to_str, NULL, 0, 0);
2122         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "subscribe_context", "", OPT_CHAR_ARRAY_T, 0, CHARFLDSET(struct ast_sip_endpoint, subscription.context));
2123         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "contact_user", "", contact_user_handler, contact_user_to_str, NULL, 0, 0);
2124         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "preferred_codec_only", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, preferred_codec_only));
2125         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "asymmetric_rtp_codec", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, asymmetric_rtp_codec));
2126         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "rtcp_mux", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtcp_mux));
2127         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "allow_overlap", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, allow_overlap));
2128         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "refer_blind_progress", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, refer_blind_progress));
2129         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "notify_early_inuse_ringing", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, notify_early_inuse_ringing));
2130         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "max_audio_streams", "1", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, media.max_audio_streams));
2131         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "max_video_streams", "1", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, media.max_video_streams));
2132         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "bundle", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.bundle));
2133         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "webrtc", "no", OPT_YESNO_T, 1, FLDSET(struct ast_sip_endpoint, media.webrtc));
2134         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "incoming_mwi_mailbox", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, incoming_mwi_mailbox));
2135         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "follow_early_media_fork", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.follow_early_media_fork));
2136         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "accept_multiple_sdp_answers", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.accept_multiple_sdp_answers));
2137         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "suppress_q850_reason_headers", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, suppress_q850_reason_headers));
2138         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "ignore_183_without_sdp", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, ignore_183_without_sdp));
2139         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "incoming_call_offer_pref", "local",
2140                 call_offer_pref_handler, incoming_call_offer_pref_to_str, NULL, 0, 0);
2141         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "outgoing_call_offer_pref", "remote",
2142                 call_offer_pref_handler, outgoing_call_offer_pref_to_str, NULL, 0, 0);
2143         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "codec_prefs_incoming_offer",
2144                 "prefer: pending, operation: intersect, keep: all, transcode: allow",
2145                 codec_prefs_handler, incoming_offer_codec_prefs_to_str, NULL, 0, 0);
2146         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "codec_prefs_outgoing_offer",
2147                 "prefer: pending, operation: union, keep: all, transcode: allow",
2148                 codec_prefs_handler, outgoing_offer_codec_prefs_to_str, NULL, 0, 0);
2149         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "codec_prefs_incoming_answer",
2150                 "prefer: pending, operation: intersect, keep: all",
2151                 codec_prefs_handler, incoming_answer_codec_prefs_to_str, NULL, 0, 0);
2152         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "codec_prefs_outgoing_answer",
2153                 "prefer: pending, operation: intersect, keep: all",
2154                 codec_prefs_handler, outgoing_answer_codec_prefs_to_str, NULL, 0, 0);
2155         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "stir_shaken", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, stir_shaken));
2156
2157         if (ast_sip_initialize_sorcery_transport()) {
2158                 ast_log(LOG_ERROR, "Failed to register SIP transport support with sorcery\n");
2159                 ast_sorcery_unref(sip_sorcery);
2160                 sip_sorcery = NULL;
2161                 return -1;
2162         }
2163
2164         if (ast_sip_initialize_sorcery_location()) {
2165                 ast_log(LOG_ERROR, "Failed to register SIP location support with sorcery\n");
2166                 ast_sorcery_unref(sip_sorcery);
2167                 sip_sorcery = NULL;
2168                 return -1;
2169         }
2170
2171         ast_sorcery_observer_add(sip_sorcery, "endpoint", &endpoint_observers);
2172
2173         if (ast_sip_initialize_sorcery_domain_alias()) {
2174                 ast_log(LOG_ERROR, "Failed to register SIP domain aliases support with sorcery\n");
2175                 ast_sorcery_unref(sip_sorcery);
2176                 sip_sorcery = NULL;
2177                 return -1;
2178         }
2179
2180         if (ast_sip_initialize_sorcery_global()) {
2181                 ast_log(LOG_ERROR, "Failed to register SIP Global support\n");
2182                 ast_sorcery_unref(sip_sorcery);
2183                 sip_sorcery = NULL;
2184                 return -1;
2185         }
2186
2187         endpoint_formatter = ao2_alloc(sizeof(struct ast_sip_cli_formatter_entry), NULL);
2188         if (!endpoint_formatter) {
2189                 ast_log(LOG_ERROR, "Unable to allocate memory for endpoint_formatter\n");
2190                 ast_sorcery_unref(sip_sorcery);
2191                 sip_sorcery = NULL;
2192                 return -1;
2193         }
2194         endpoint_formatter->name = "endpoint";
2195         endpoint_formatter->print_header = cli_endpoint_print_header;
2196         endpoint_formatter->print_body = cli_endpoint_print_body;
2197         endpoint_formatter->get_container = cli_endpoint_get_container;
2198         endpoint_formatter->iterate = cli_endpoint_iterate;
2199         endpoint_formatter->retrieve_by_id = cli_endpoint_retrieve_by_id;
2200         endpoint_formatter->get_id = ast_sorcery_object_get_id;
2201
2202         ast_sip_register_cli_formatter(endpoint_formatter);
2203         ast_cli_register_multiple(cli_commands, ARRAY_LEN(cli_commands));
2204
2205         ast_sorcery_load(sip_sorcery);
2206
2207         load_all_endpoints();
2208
2209         ast_sip_location_prune_boot_contacts();
2210
2211         acl_change_sub = stasis_subscribe(ast_security_topic(), acl_change_stasis_cb, NULL);
2212         stasis_subscription_accept_message_type(acl_change_sub, ast_named_acl_change_type());
2213         stasis_subscription_set_filter(acl_change_sub, STASIS_SUBSCRIPTION_FILTER_SELECTIVE);
2214
2215         return 0;
2216 }
2217
2218 void ast_res_pjsip_destroy_configuration(void)
2219 {
2220         if (!sip_sorcery) {
2221                 return;
2222         }
2223
2224         acl_change_sub = stasis_unsubscribe_and_join(acl_change_sub);
2225         ast_sip_destroy_sorcery_global();
2226         ast_sip_destroy_sorcery_location();
2227         ast_sip_destroy_sorcery_auth();
2228         ast_sip_destroy_sorcery_transport();
2229         ast_sorcery_unref(sip_sorcery);
2230         sip_sorcery = NULL;
2231         ast_manager_unregister(AMI_SHOW_ENDPOINT);
2232         ast_manager_unregister(AMI_SHOW_ENDPOINTS);
2233         ast_cli_unregister_multiple(cli_commands, ARRAY_LEN(cli_commands));
2234         ast_sip_unregister_cli_formatter(endpoint_formatter);
2235         ast_sip_destroy_cli();
2236         ao2_cleanup(persistent_endpoints);
2237         persistent_endpoints = NULL;
2238 }
2239
2240 int ast_res_pjsip_reload_configuration(void)
2241 {
2242         if (sip_sorcery) {
2243                 ast_sorcery_reload(sip_sorcery);
2244         }
2245         return 0;
2246 }
2247
2248 static void subscription_configuration_destroy(struct ast_sip_endpoint_subscription_configuration *subscription)
2249 {
2250         ast_string_field_free_memory(&subscription->mwi);
2251         ast_free(subscription->mwi.voicemail_extension);
2252 }
2253
2254 static void info_configuration_destroy(struct ast_sip_endpoint_info_configuration *info)
2255 {
2256         ast_string_field_free_memory(&info->recording);
2257 }
2258
2259 static void media_configuration_destroy(struct ast_sip_endpoint_media_configuration *media)
2260 {
2261         ast_rtp_dtls_cfg_free(&media->rtp.dtls_cfg);
2262         ast_string_field_free_memory(&media->rtp);
2263         ast_string_field_free_memory(media);
2264 }
2265
2266 static void endpoint_destructor(void* obj)
2267 {
2268         struct ast_sip_endpoint *endpoint = obj;
2269
2270         ast_string_field_free_memory(endpoint);
2271
2272         ao2_cleanup(endpoint->media.codecs);
2273         ast_stream_topology_free(endpoint->media.topology);
2274         subscription_configuration_destroy(&endpoint->subscription);
2275         info_configuration_destroy(&endpoint->info);
2276         media_configuration_destroy(&endpoint->media);
2277         ast_sip_auth_vector_destroy(&endpoint->inbound_auths);
2278         ast_sip_auth_vector_destroy(&endpoint->outbound_auths);
2279         ast_party_id_free(&endpoint->id.self);
2280         endpoint->pickup.named_callgroups = ast_unref_namedgroups(endpoint->pickup.named_callgroups);
2281         endpoint->pickup.named_pickupgroups = ast_unref_namedgroups(endpoint->pickup.named_pickupgroups);
2282         ao2_cleanup(endpoint->persistent);
2283         ast_variables_destroy(endpoint->channel_vars);
2284         AST_VECTOR_FREE(&endpoint->ident_method_order);
2285         ast_free(endpoint->contact_user);
2286         ast_free_acl_list(endpoint->contact_acl);
2287         ast_free_acl_list(endpoint->acl);
2288 }
2289
2290 static int init_subscription_configuration(struct ast_sip_endpoint_subscription_configuration *subscription)
2291 {
2292         return ast_string_field_init(&subscription->mwi, 64);
2293 }
2294
2295 static int init_info_configuration(struct ast_sip_endpoint_info_configuration *info)
2296 {
2297         return ast_string_field_init(&info->recording, 32);
2298 }
2299
2300 static int init_media_configuration(struct ast_sip_endpoint_media_configuration *media)
2301 {
2302         return ast_string_field_init(media, 64) || ast_string_field_init(&media->rtp, 32);
2303 }
2304
2305 void *ast_sip_endpoint_alloc(const char *name)
2306 {
2307         struct ast_sip_endpoint *endpoint = ast_sorcery_generic_alloc(sizeof(*endpoint), endpoint_destructor);
2308         if (!endpoint) {
2309                 return NULL;
2310         }
2311         if (ast_string_field_init(endpoint, 64)) {
2312                 ao2_cleanup(endpoint);
2313                 return NULL;
2314         }
2315
2316         if (!(endpoint->media.codecs = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
2317                 ao2_cleanup(endpoint);
2318                 return NULL;
2319         }
2320         if (init_subscription_configuration(&endpoint->subscription)) {
2321                 ao2_cleanup(endpoint);
2322                 return NULL;
2323         }
2324         if (init_info_configuration(&endpoint->info)) {
2325                 ao2_cleanup(endpoint);
2326                 return NULL;
2327         }
2328         if (init_media_configuration(&endpoint->media)) {
2329                 ao2_cleanup(endpoint);
2330                 return NULL;
2331         }
2332
2333         ast_party_id_init(&endpoint->id.self);
2334         endpoint->id.self.tag = ast_strdup("");
2335
2336         if (AST_VECTOR_INIT(&endpoint->ident_method_order, 1)) {
2337                 return NULL;
2338         }
2339
2340         return endpoint;
2341 }
2342
2343 struct ao2_container *ast_sip_get_endpoints(void)
2344 {
2345         struct ao2_container *endpoints;
2346
2347         endpoints = ast_sorcery_retrieve_by_fields(sip_sorcery, "endpoint", AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
2348
2349         return endpoints;
2350 }
2351
2352 struct ast_sip_endpoint *ast_sip_default_outbound_endpoint(void)
2353 {
2354         RAII_VAR(char *, name, ast_sip_global_default_outbound_endpoint(), ast_free);
2355         return ast_strlen_zero(name) ? NULL : ast_sorcery_retrieve_by_id(
2356                 sip_sorcery, "endpoint", name);
2357 }
2358
2359 int ast_sip_retrieve_auths(const struct ast_sip_auth_vector *auths, struct ast_sip_auth **out)
2360 {
2361         int i;
2362
2363         for (i = 0; i < AST_VECTOR_SIZE(auths); ++i) {
2364                 /* Using AST_VECTOR_GET is safe since the vector is immutable */
2365                 const char *name = AST_VECTOR_GET(auths, i);
2366                 out[i] = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), SIP_SORCERY_AUTH_TYPE, name);
2367                 if (!out[i]) {
2368                         ast_log(LOG_NOTICE, "Couldn't find auth '%s'. Cannot authenticate\n", name);
2369                         return -1;
2370                 }
2371         }
2372
2373         return 0;
2374 }
2375
2376 void ast_sip_cleanup_auths(struct ast_sip_auth *auths[], size_t num_auths)
2377 {
2378         int i;
2379         for (i = 0; i < num_auths; ++i) {
2380                 ao2_cleanup(auths[i]);
2381         }
2382 }
2383
2384 struct ast_sorcery *ast_sip_get_sorcery(void)
2385 {
2386         return sip_sorcery;
2387 }