489ba6aec70333f88c5f7542136d72260953201e
[asterisk/asterisk.git] / res / res_sip / sip_configuration.c
1 /*
2  * sip_cli_commands.c
3  *
4  *  Created on: Jan 25, 2013
5  *      Author: mjordan
6  */
7
8 #include "asterisk.h"
9
10 #include <pjsip.h>
11 #include <pjsip_ua.h>
12
13 #include "asterisk/res_sip.h"
14 #include "include/res_sip_private.h"
15 #include "asterisk/cli.h"
16 #include "asterisk/astobj2.h"
17 #include "asterisk/utils.h"
18 #include "asterisk/sorcery.h"
19 #include "asterisk/callerid.h"
20
21 static struct ast_sorcery *sip_sorcery;
22
23 static char *handle_cli_show_endpoints(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
24 {
25         RAII_VAR(struct ao2_container *, endpoints, NULL, ao2_cleanup);
26         struct ao2_iterator it_endpoints;
27         struct ast_sip_endpoint *endpoint;
28
29         switch (cmd) {
30         case CLI_INIT:
31                 e->command = "sip show endpoints";
32                 e->usage =
33                         "Usage: sip show endpoints\n"
34                         "       Show the registered SIP endpoints\n";
35                 return NULL;
36         case CLI_GENERATE:
37                 return NULL;
38         }
39
40         endpoints = ast_res_sip_get_endpoints();
41         if (!endpoints) {
42                 return CLI_FAILURE;
43         }
44
45         if (!ao2_container_count(endpoints)) {
46                 ast_cli(a->fd, "No endpoints found\n");
47                 return CLI_SUCCESS;
48         }
49
50         ast_cli(a->fd, "Endpoints:\n");
51         it_endpoints = ao2_iterator_init(endpoints, 0);
52         while ((endpoint = ao2_iterator_next(&it_endpoints))) {
53                 ast_cli(a->fd, "%s\n", ast_sorcery_object_get_id(endpoint));
54                 ao2_ref(endpoint, -1);
55         }
56         ao2_iterator_destroy(&it_endpoints);
57         return CLI_SUCCESS;
58 }
59
60 static struct ast_cli_entry cli_commands[] = {
61         AST_CLI_DEFINE(handle_cli_show_endpoints, "Show SIP Endpoints"),
62 };
63
64 static int dtmf_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
65 {
66         struct ast_sip_endpoint *endpoint = obj;
67
68         if (!strcasecmp(var->value, "rfc4733")) {
69                 endpoint->dtmf = AST_SIP_DTMF_RFC_4733;
70         } else if (!strcasecmp(var->value, "inband")) {
71                 endpoint->dtmf = AST_SIP_DTMF_INBAND;
72         } else if (!strcasecmp(var->value, "info")) {
73                 endpoint->dtmf = AST_SIP_DTMF_INFO;
74         } else if (!strcasecmp(var->value, "none")) {
75                 endpoint->dtmf = AST_SIP_DTMF_NONE;
76         } else {
77                 return -1;
78         }
79
80         return 0;
81 }
82
83 static int prack_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
84 {
85         struct ast_sip_endpoint *endpoint = obj;
86
87         if (ast_true(var->value)) {
88                 endpoint->extensions |= PJSIP_INV_SUPPORT_100REL;
89         } else if (ast_false(var->value)) {
90                 endpoint->extensions &= PJSIP_INV_SUPPORT_100REL;
91         } else if (!strcasecmp(var->value, "required")) {
92                 endpoint->extensions |= PJSIP_INV_REQUIRE_100REL;
93         } else {
94                 return -1;
95         }
96
97         return 0;
98 }
99
100 static int timers_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
101 {
102         struct ast_sip_endpoint *endpoint = obj;
103
104         if (ast_true(var->value)) {
105                 endpoint->extensions |= PJSIP_INV_SUPPORT_TIMER;
106         } else if (ast_false(var->value)) {
107                 endpoint->extensions &= PJSIP_INV_SUPPORT_TIMER;
108         } else if (!strcasecmp(var->value, "required")) {
109                 endpoint->extensions |= PJSIP_INV_REQUIRE_TIMER;
110         } else if (!strcasecmp(var->value, "always")) {
111                 endpoint->extensions |= PJSIP_INV_ALWAYS_USE_TIMER;
112         } else {
113                 return -1;
114         }
115
116         return 0;
117 }
118
119 static void destroy_auths(const char **auths, size_t num_auths)
120 {
121         int i;
122         for (i = 0; i < num_auths; ++i) {
123                 ast_free((char *) auths[i]);
124         }
125         ast_free(auths);
126 }
127
128 #define AUTH_INCREMENT 4
129
130 static const char **auth_alloc(const char *value, size_t *num_auths)
131 {
132         char *auths = ast_strdupa(value);
133         char *val;
134         int num_alloced = 0;
135         const char **alloced_auths = NULL;
136
137         while ((val = strsep(&auths, ","))) {
138                 if (*num_auths >= num_alloced) {
139                         size_t size;
140                         num_alloced += AUTH_INCREMENT;
141                         size = num_alloced * sizeof(char *);
142                         alloced_auths = ast_realloc(alloced_auths, size);
143                         if (!alloced_auths) {
144                                 goto failure;
145                         }
146                 }
147                 alloced_auths[*num_auths] = ast_strdup(val);
148                 if (!alloced_auths[*num_auths]) {
149                         goto failure;
150                 }
151                 ++(*num_auths);
152         }
153         return alloced_auths;
154
155 failure:
156         destroy_auths(alloced_auths, *num_auths);
157         return NULL;
158 }
159
160 static int inbound_auth_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
161 {
162         struct ast_sip_endpoint *endpoint = obj;
163
164         endpoint->sip_inbound_auths = auth_alloc(var->value, &endpoint->num_inbound_auths);
165         if (!endpoint->sip_inbound_auths) {
166                 return -1;
167         }
168         return 0;
169 }
170 static int outbound_auth_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
171 {
172         struct ast_sip_endpoint *endpoint = obj;
173
174         endpoint->sip_outbound_auths = auth_alloc(var->value, &endpoint->num_outbound_auths);
175         if (!endpoint->sip_outbound_auths) {
176                 return -1;
177         }
178         return 0;
179 }
180
181 static int ident_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
182 {
183         struct ast_sip_endpoint *endpoint = obj;
184         char *idents = ast_strdupa(var->value);
185         char *val;
186
187         while ((val = strsep(&idents, ","))) {
188                 if (!strcasecmp(val, "username")) {
189                         endpoint->ident_method |= AST_SIP_ENDPOINT_IDENTIFY_BY_USERNAME;
190                 } else if (!strcasecmp(val, "location")) {
191                         endpoint->ident_method |= AST_SIP_ENDPOINT_IDENTIFY_BY_LOCATION;
192                 } else {
193                         ast_log(LOG_ERROR, "Unrecognized identification method %s specified for endpoint %s\n",
194                                         val, ast_sorcery_object_get_id(endpoint));
195                         return -1;
196                 }
197         }
198         return 0;
199 }
200
201 static int direct_media_method_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
202 {
203         struct ast_sip_endpoint *endpoint = obj;
204
205         if (!strcasecmp(var->value, "invite") || !strcasecmp(var->value, "reinvite")) {
206                 endpoint->direct_media_method = AST_SIP_SESSION_REFRESH_METHOD_INVITE;
207         } else if (!strcasecmp(var->value, "update")) {
208                 endpoint->direct_media_method = AST_SIP_SESSION_REFRESH_METHOD_UPDATE;
209         } else {
210                 ast_log(LOG_NOTICE, "Unrecognized option value %s for %s on endpoint %s\n",
211                                 var->value, var->name, ast_sorcery_object_get_id(endpoint));
212                 return -1;
213         }
214         return 0;
215 }
216
217 static int direct_media_glare_mitigation_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
218 {
219         struct ast_sip_endpoint *endpoint = obj;
220
221         if (!strcasecmp(var->value, "none")) {
222                 endpoint->direct_media_glare_mitigation = AST_SIP_DIRECT_MEDIA_GLARE_MITIGATION_NONE;
223         } else if (!strcasecmp(var->value, "outgoing")) {
224                 endpoint->direct_media_glare_mitigation = AST_SIP_DIRECT_MEDIA_GLARE_MITIGATION_OUTGOING;
225         } else if (!strcasecmp(var->value, "incoming")) {
226                 endpoint->direct_media_glare_mitigation = AST_SIP_DIRECT_MEDIA_GLARE_MITIGATION_INCOMING;
227         } else {
228                 ast_log(LOG_NOTICE, "Unrecognized option value %s for %s on endpoint %s\n",
229                                 var->value, var->name, ast_sorcery_object_get_id(endpoint));
230                 return -1;
231         }
232
233         return 0;
234 }
235
236 static int caller_id_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
237 {
238         struct ast_sip_endpoint *endpoint = obj;
239         char cid_name[80] = { '\0' };
240         char cid_num[80] = { '\0' };
241
242         ast_callerid_split(var->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num));
243         if (!ast_strlen_zero(cid_name)) {
244                 endpoint->id.name.str = ast_strdup(cid_name);
245                 if (!endpoint->id.name.str) {
246                         return -1;
247                 }
248                 endpoint->id.name.valid = 1;
249         }
250         if (!ast_strlen_zero(cid_num)) {
251                 endpoint->id.number.str = ast_strdup(cid_num);
252                 if (!endpoint->id.number.str) {
253                         return -1;
254                 }
255                 endpoint->id.number.valid = 1;
256         }
257         return 0;
258 }
259
260 static int caller_id_privacy_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
261 {
262         struct ast_sip_endpoint *endpoint = obj;
263         int callingpres = ast_parse_caller_presentation(var->value);
264         if (callingpres == -1 && sscanf(var->value, "%d", &callingpres) != 1) {
265                 return -1;
266         }
267         endpoint->id.number.presentation = callingpres;
268         endpoint->id.name.presentation = callingpres;
269         return 0;
270 }
271
272 static int caller_id_tag_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
273 {
274         struct ast_sip_endpoint *endpoint = obj;
275         endpoint->id.tag = ast_strdup(var->value);
276         return endpoint->id.tag ? 0 : -1;
277 }
278
279 static void *sip_nat_hook_alloc(const char *name)
280 {
281         return ao2_alloc(sizeof(struct ast_sip_nat_hook), NULL);
282 }
283
284 int ast_res_sip_initialize_configuration(void)
285 {
286         if (ast_cli_register_multiple(cli_commands, ARRAY_LEN(cli_commands))) {
287                 return -1;
288         }
289
290         if (!(sip_sorcery = ast_sorcery_open())) {
291                 ast_log(LOG_ERROR, "Failed to open SIP sorcery failed to open\n");
292                 return -1;
293         }
294
295         ast_sorcery_apply_config(sip_sorcery, "res_sip");
296
297         if (ast_sip_initialize_sorcery_auth(sip_sorcery)) {
298                 ast_log(LOG_ERROR, "Failed to register SIP authentication support\n");
299                 ast_sorcery_unref(sip_sorcery);
300                 sip_sorcery = NULL;
301                 return -1;
302         }
303
304         ast_sorcery_apply_default(sip_sorcery, "endpoint", "config", "res_sip.conf,criteria=type=endpoint");
305
306         ast_sorcery_apply_default(sip_sorcery, "nat_hook", "memory", NULL);
307
308         if (ast_sorcery_object_register(sip_sorcery, "endpoint", ast_sip_endpoint_alloc, NULL, NULL)) {
309                 ast_log(LOG_ERROR, "Failed to register SIP endpoint object with sorcery\n");
310                 ast_sorcery_unref(sip_sorcery);
311                 sip_sorcery = NULL;
312                 return -1;
313         }
314
315         ast_sorcery_object_register(sip_sorcery, "nat_hook", sip_nat_hook_alloc, NULL, NULL);
316
317         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "type", "", OPT_NOOP_T, 0, 0);
318         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "context", "default", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, context));
319         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "disallow", "", OPT_CODEC_T, 0, FLDSET(struct ast_sip_endpoint, prefs, codecs));
320         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "allow", "", OPT_CODEC_T, 1, FLDSET(struct ast_sip_endpoint, prefs, codecs));
321         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "qualify_frequency", 0, OPT_UINT_T, PARSE_IN_RANGE, FLDSET(struct ast_sip_endpoint, qualify_frequency), 0, 86400);
322         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtmfmode", "rfc4733", dtmf_handler, NULL, 0, 0);
323         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "rtp_ipv6", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, rtp_ipv6));
324         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "rtp_symmetric", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, rtp_symmetric));
325         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "ice_support", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, ice_support));
326         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "use_ptime", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, use_ptime));
327         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "force_rport", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, force_rport));
328         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "rewrite_contact", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, rewrite_contact));
329         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "transport", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, transport));
330         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "outbound_proxy", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, outbound_proxy));
331         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "mohsuggest", "default", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, mohsuggest));
332         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "100rel", "yes", prack_handler, NULL, 0, 0);
333         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "timers", "yes", timers_handler, NULL, 0, 0);
334         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "timers_min_se", "90", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, min_se));
335         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "timers_sess_expires", "1800", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, sess_expires));
336         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "auth", "", inbound_auth_handler, NULL, 0, 0);
337         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "outbound_auth", "", outbound_auth_handler, NULL, 0, 0);
338         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "aors", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, aors));
339         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "external_media_address", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, external_media_address));
340         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "identify_by", "username,location", ident_handler, NULL, 0, 0);
341         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "direct_media", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, direct_media));
342         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "direct_media_method", "invite", direct_media_method_handler, NULL, 0, 0);
343         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "direct_media_glare_mitigation", "none", direct_media_glare_mitigation_handler, NULL, 0, 0);
344         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "disable_direct_media_on_nat", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, disable_direct_media_on_nat));
345         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "callerid", "", caller_id_handler, NULL, 0, 0);
346         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "callerid_privacy", "", caller_id_privacy_handler, NULL, 0, 0);
347         ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "callerid_tag", "", caller_id_tag_handler, NULL, 0, 0);
348         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "trust_id_inbound", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, trust_id_inbound));
349         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "trust_id_outbound", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, trust_id_outbound));
350         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "send_pai", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, send_pai));
351         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "send_rpid", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, send_rpid));
352         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "mailboxes", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, mailboxes));
353         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "aggregate_mwi", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, aggregate_mwi));
354
355         if (ast_sip_initialize_sorcery_transport(sip_sorcery)) {
356                 ast_log(LOG_ERROR, "Failed to register SIP transport support with sorcery\n");
357                 ast_sorcery_unref(sip_sorcery);
358                 sip_sorcery = NULL;
359                 return -1;
360         }
361
362         if (ast_sip_initialize_sorcery_location(sip_sorcery)) {
363                 ast_log(LOG_ERROR, "Failed to register SIP location support with sorcery\n");
364                 ast_sorcery_unref(sip_sorcery);
365                 sip_sorcery = NULL;
366                 return -1;
367         }
368
369         if (ast_sip_initialize_sorcery_domain_alias(sip_sorcery)) {
370                 ast_log(LOG_ERROR, "Failed to register SIP domain aliases support with sorcery\n");
371                 ast_sorcery_unref(sip_sorcery);
372                 sip_sorcery = NULL;
373                 return -1;
374         }
375
376         ast_sorcery_load(sip_sorcery);
377
378         return 0;
379 }
380
381 void ast_res_sip_destroy_configuration(void)
382 {
383         ast_cli_unregister_multiple(cli_commands, ARRAY_LEN(cli_commands));
384         ast_sorcery_unref(sip_sorcery);
385 }
386
387 int ast_res_sip_reload_configuration(void)
388 {
389         if (sip_sorcery) {
390                 ast_sorcery_reload(sip_sorcery);
391         }
392         return 0;
393 }
394
395 static void endpoint_destructor(void* obj)
396 {
397         struct ast_sip_endpoint *endpoint = obj;
398
399         ast_string_field_free_memory(endpoint);
400
401         if (endpoint->codecs) {
402                 ast_format_cap_destroy(endpoint->codecs);
403         }
404         destroy_auths(endpoint->sip_inbound_auths, endpoint->num_inbound_auths);
405         destroy_auths(endpoint->sip_outbound_auths, endpoint->num_outbound_auths);
406         ast_party_id_free(&endpoint->id);
407 }
408
409 void *ast_sip_endpoint_alloc(const char *name)
410 {
411         struct ast_sip_endpoint *endpoint = ao2_alloc(sizeof(*endpoint), endpoint_destructor);
412         if (!endpoint) {
413                 return NULL;
414         }
415         if (ast_string_field_init(endpoint, 64)) {
416                 ao2_cleanup(endpoint);
417                 return NULL;
418         }
419         if (!(endpoint->codecs = ast_format_cap_alloc_nolock())) {
420                 ao2_cleanup(endpoint);
421                 return NULL;
422         }
423         ast_party_id_init(&endpoint->id);
424         return endpoint;
425 }
426
427 struct ao2_container *ast_res_sip_get_endpoints(void)
428 {
429         struct ao2_container *endpoints;
430
431         endpoints = ast_sorcery_retrieve_by_fields(sip_sorcery, "endpoint", AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
432
433         return endpoints;
434 }
435
436 int ast_sip_retrieve_auths(const char *auth_names[], size_t num_auths, struct ast_sip_auth **out)
437 {
438         int i;
439
440         for (i = 0; i < num_auths; ++i) {
441                 out[i] = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), SIP_SORCERY_AUTH_TYPE, auth_names[i]);
442                 if (!out[i]) {
443                         ast_log(LOG_NOTICE, "Couldn't find auth '%s'. Cannot authenticate\n", auth_names[i]);
444                         return -1;
445                 }
446         }
447
448         return 0;
449 }
450
451 void ast_sip_cleanup_auths(struct ast_sip_auth *auths[], size_t num_auths)
452 {
453         int i;
454         for (i = 0; i < num_auths; ++i) {
455                 ao2_cleanup(auths[i]);
456         }
457 }
458
459 struct ast_sorcery *ast_sip_get_sorcery(void)
460 {
461         return sip_sorcery;
462 }
463