res_pjsip_exten_state: PJSIPShowSubscriptionsInbound causes crash
[asterisk/asterisk.git] / res / res_pjsip_outbound_registration.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2013, Digium, Inc.
5  *
6  * Joshua Colp <jcolp@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*** MODULEINFO
20         <depend>pjproject</depend>
21         <depend>res_pjsip</depend>
22         <support_level>core</support_level>
23  ***/
24
25 #include "asterisk.h"
26
27 #include <pjsip.h>
28 #include <pjsip_ua.h>
29
30 #include "asterisk/res_pjsip.h"
31 #include "asterisk/res_pjsip_cli.h"
32 #include "asterisk/module.h"
33 #include "asterisk/taskprocessor.h"
34 #include "asterisk/cli.h"
35 #include "asterisk/stasis_system.h"
36 #include "res_pjsip/include/res_pjsip_private.h"
37
38 /*** DOCUMENTATION
39         <configInfo name="res_pjsip_outbound_registration" language="en_US">
40                 <synopsis>SIP resource for outbound registrations</synopsis>
41                 <description><para>
42                         <emphasis>Outbound Registration</emphasis>
43                         </para>
44                         <para>This module allows <literal>res_pjsip</literal> to register to other SIP servers.</para>
45                 </description>
46                 <configFile name="pjsip.conf">
47                         <configObject name="registration">
48                                 <synopsis>The configuration for outbound registration</synopsis>
49                                 <description><para>
50                                         Registration is <emphasis>COMPLETELY</emphasis> separate from the rest of
51                                         <literal>pjsip.conf</literal>. A minimal configuration consists of
52                                         setting a <literal>server_uri</literal> and a <literal>client_uri</literal>.
53                                 </para></description>
54                                 <configOption name="auth_rejection_permanent" default="yes">
55                                         <synopsis>Determines whether failed authentication challenges are treated
56                                         as permanent failures.</synopsis>
57                                         <description><para>If this option is enabled and an authentication challenge fails,
58                                         registration will not be attempted again until the configuration is reloaded.</para></description>
59                                 </configOption>
60                                 <configOption name="client_uri">
61                                         <synopsis>Client SIP URI used when attemping outbound registration</synopsis>
62                                         <description><para>
63                                                 This is the address-of-record for the outbound registration (i.e. the URI in
64                                                 the To header of the REGISTER).</para>
65                                                 <para>For registration with an ITSP, the client SIP URI may need to consist of
66                                                 an account name or number and the provider's hostname for their registrar, e.g.
67                                                 client_uri=1234567890@example.com. This may differ between providers.</para>
68                                                 <para>For registration to generic registrars, the client SIP URI will depend
69                                                 on networking specifics and configuration of the registrar.
70                                         </para></description>
71                                 </configOption>
72                                 <configOption name="contact_user">
73                                         <synopsis>Contact User to use in request</synopsis>
74                                 </configOption>
75                                 <configOption name="expiration" default="3600">
76                                         <synopsis>Expiration time for registrations in seconds</synopsis>
77                                 </configOption>
78                                 <configOption name="max_retries" default="10">
79                                         <synopsis>Maximum number of registration attempts.</synopsis>
80                                 </configOption>
81                                 <configOption name="outbound_auth" default="">
82                                         <synopsis>Authentication object to be used for outbound registrations.</synopsis>
83                                 </configOption>
84                                 <configOption name="outbound_proxy" default="">
85                                         <synopsis>Outbound Proxy used to send registrations</synopsis>
86                                 </configOption>
87                                 <configOption name="retry_interval" default="60">
88                                         <synopsis>Interval in seconds between retries if outbound registration is unsuccessful</synopsis>
89                                 </configOption>
90                                 <configOption name="forbidden_retry_interval" default="0">
91                                         <synopsis>Interval used when receiving a 403 Forbidden response.</synopsis>
92                                         <description><para>
93                                                 If a 403 Forbidden is received, chan_pjsip will wait
94                                                 <replaceable>forbidden_retry_interval</replaceable> seconds before
95                                                 attempting registration again. If 0 is specified, chan_pjsip will not
96                                                 retry after receiving a 403 Forbidden response. Setting this to a non-zero
97                                                 value goes against a "SHOULD NOT" in RFC3261, but can be used to work around
98                                                 buggy registrars.
99                                         </para></description>
100                                 </configOption>
101                                 <configOption name="server_uri">
102                                         <synopsis>SIP URI of the server to register against</synopsis>
103                                         <description><para>
104                                                 This is the URI at which to find the registrar to send the outbound REGISTER. This URI
105                                                 is used as the request URI of the outbound REGISTER request from Asterisk.</para>
106                                                 <para>For registration with an ITSP, the setting may often be just the domain of
107                                                 the registrar, e.g. sip:sip.example.com.
108                                         </para></description>
109                                 </configOption>
110                                 <configOption name="transport">
111                                         <synopsis>Transport used for outbound authentication</synopsis>
112                                         <description>
113                                                 <note><para>A <replaceable>transport</replaceable> configured in
114                                                 <literal>pjsip.conf</literal>. As with other <literal>res_pjsip</literal> modules, this will use the first available transport of the appropriate type if unconfigured.</para></note>
115                                         </description>
116                                 </configOption>
117                                 <configOption name="line">
118                                         <synopsis>Whether to add a 'line' parameter to the Contact for inbound call matching</synopsis>
119                                         <description><para>
120                                                 When enabled this option will cause a 'line' parameter to be added to the Contact
121                                                 header placed into the outgoing registration request. If the remote server sends a call
122                                                 this line parameter will be used to establish a relationship to the outbound registration,
123                                                 ultimately causing the configured endpoint to be used.
124                                         </para></description>
125                                 </configOption>
126                                 <configOption name="endpoint">
127                                         <synopsis>Endpoint to use for incoming related calls</synopsis>
128                                         <description><para>
129                                                 When line support is enabled this configured endpoint name is used for incoming calls
130                                                 that are related to the outbound registration.
131                                         </para></description>
132                                 </configOption>
133                                 <configOption name="type">
134                                         <synopsis>Must be of type 'registration'.</synopsis>
135                                 </configOption>
136                                 <configOption name="support_path">
137                                         <synopsis>Enables Path support for outbound REGISTER requests.</synopsis>
138                                         <description><para>
139                                                 When this option is enabled, outbound REGISTER requests will advertise
140                                                 support for Path headers so that intervening proxies can add to the Path
141                                                 header as necessary.
142                                         </para></description>
143                                 </configOption>
144                         </configObject>
145                 </configFile>
146         </configInfo>
147         <manager name="PJSIPUnregister" language="en_US">
148                 <synopsis>
149                         Unregister an outbound registration.
150                 </synopsis>
151                 <syntax>
152                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
153                         <parameter name="Registration" required="true">
154                                 <para>The outbound registration to unregister.</para>
155                         </parameter>
156                 </syntax>
157                 <description>
158                         <para>
159                         Send a SIP REGISTER request to the specified outbound registration with an expiration of 0.
160                         This will cause the contact added by this registration to be removed on the remote system.
161                         Note: The specified outbound registration will attempt to re-register according to it's last
162                         registration expiration.
163                         </para>
164                 </description>
165         </manager>
166         <manager name="PJSIPShowRegistrationsOutbound" language="en_US">
167                 <synopsis>
168                         Lists PJSIP outbound registrations.
169                 </synopsis>
170                 <syntax />
171                 <description>
172                         <para>
173                         In response <literal>OutboundRegistrationDetail</literal> events showing configuration and status
174                         information are raised for each outbound registration object. <literal>AuthDetail</literal>
175                         events are raised for each associated auth object as well.  Once all events are completed an
176                         <literal>OutboundRegistrationDetailComplete</literal> is issued.
177                         </para>
178                 </description>
179         </manager>
180  ***/
181
182 /*! \brief Amount of buffer time (in seconds) before expiration that we re-register at */
183 #define REREGISTER_BUFFER_TIME 10
184
185 /*! \brief Size of the buffer for creating a unique string for the line */
186 #define LINE_PARAMETER_SIZE 8
187
188 /*! \brief Various states that an outbound registration may be in */
189 enum sip_outbound_registration_status {
190         /*! \brief Currently unregistered */
191         SIP_REGISTRATION_UNREGISTERED = 0,
192         /*! \brief Registered, yay! */
193         SIP_REGISTRATION_REGISTERED,
194         /*! \brief Registration was rejected, but response was temporal */
195         SIP_REGISTRATION_REJECTED_TEMPORARY,
196         /*! \brief Registration was rejected, permanently */
197         SIP_REGISTRATION_REJECTED_PERMANENT,
198         /*! \brief Registration has been stopped */
199         SIP_REGISTRATION_STOPPED,
200 };
201
202 static const char *sip_outbound_registration_status_str[] = {
203         [SIP_REGISTRATION_UNREGISTERED] = "Unregistered",
204         [SIP_REGISTRATION_REGISTERED] = "Registered",
205         [SIP_REGISTRATION_REJECTED_TEMPORARY] = "Rejected",
206         [SIP_REGISTRATION_REJECTED_PERMANENT] = "Rejected",
207         [SIP_REGISTRATION_STOPPED] = "Stopped",
208 };
209
210 /*! \brief Outbound registration information */
211 struct sip_outbound_registration {
212         /*! \brief Sorcery object details */
213         SORCERY_OBJECT(details);
214         /*! \brief Stringfields */
215         AST_DECLARE_STRING_FIELDS(
216                 /*! \brief URI for the registrar */
217                 AST_STRING_FIELD(server_uri);
218                 /*! \brief URI for the AOR */
219                 AST_STRING_FIELD(client_uri);
220                 /*! \brief Optional user for contact header */
221                 AST_STRING_FIELD(contact_user);
222                 /*! \brief Explicit transport to use for registration */
223                 AST_STRING_FIELD(transport);
224                 /*! \brief Outbound proxy to use */
225                 AST_STRING_FIELD(outbound_proxy);
226                 /*! \brief Endpoint to use for related incoming calls */
227                 AST_STRING_FIELD(endpoint);
228         );
229         /*! \brief Requested expiration time */
230         unsigned int expiration;
231         /*! \brief Interval at which retries should occur for temporal responses */
232         unsigned int retry_interval;
233         /*! \brief Interval at which retries should occur for permanent responses */
234         unsigned int forbidden_retry_interval;
235         /*! \brief Treat authentication challenges that we cannot handle as permanent failures */
236         unsigned int auth_rejection_permanent;
237         /*! \brief Maximum number of retries permitted */
238         unsigned int max_retries;
239         /*! \brief Whether to add a line parameter to the outbound Contact or not */
240         unsigned int line;
241         /*! \brief Configured authentication credentials */
242         struct ast_sip_auth_vector outbound_auths;
243         /*! \brief Whether Path support is enabled */
244         unsigned int support_path;
245 };
246
247 /*! \brief Outbound registration client state information (persists for lifetime of regc) */
248 struct sip_outbound_registration_client_state {
249         /*! \brief Current status of this registration */
250         enum sip_outbound_registration_status status;
251         /*! \brief Outbound registration client */
252         pjsip_regc *client;
253         /*! \brief Timer entry for retrying on temporal responses */
254         pj_timer_entry timer;
255         /*! \brief Optional line parameter placed into Contact */
256         char line[LINE_PARAMETER_SIZE];
257         /*! \brief Current number of retries */
258         unsigned int retries;
259         /*! \brief Maximum number of retries permitted */
260         unsigned int max_retries;
261         /*! \brief Interval at which retries should occur for temporal responses */
262         unsigned int retry_interval;
263         /*! \brief Interval at which retries should occur for permanent responses */
264         unsigned int forbidden_retry_interval;
265         /*! \brief Treat authentication challenges that we cannot handle as permanent failures */
266         unsigned int auth_rejection_permanent;
267         /*! \brief Determines whether SIP Path support should be advertised */
268         unsigned int support_path;
269         /*! \brief Serializer for stuff and things */
270         struct ast_taskprocessor *serializer;
271         /*! \brief Configured authentication credentials */
272         struct ast_sip_auth_vector outbound_auths;
273         /*! \brief Registration should be destroyed after completion of transaction */
274         unsigned int destroy:1;
275 };
276
277 /*! \brief Outbound registration state information (persists for lifetime that registration should exist) */
278 struct sip_outbound_registration_state {
279         /*! \brief Outbound registration configuration object */
280         struct sip_outbound_registration *registration;
281         /*! \brief Client state information */
282         struct sip_outbound_registration_client_state *client_state;
283 };
284
285 /*! \brief Default number of state container buckets */
286 #define DEFAULT_STATE_BUCKETS 53
287 static AO2_GLOBAL_OBJ_STATIC(current_states);
288
289 /*! \brief hashing function for state objects */
290 static int registration_state_hash(const void *obj, const int flags)
291 {
292         const struct sip_outbound_registration_state *object;
293         const char *key;
294
295         switch (flags & OBJ_SEARCH_MASK) {
296         case OBJ_SEARCH_KEY:
297                 key = obj;
298                 break;
299         case OBJ_SEARCH_OBJECT:
300                 object = obj;
301                 key = ast_sorcery_object_get_id(object->registration);
302                 break;
303         default:
304                 ast_assert(0);
305                 return 0;
306         }
307         return ast_str_hash(key);
308 }
309
310 /*! \brief comparator function for state objects */
311 static int registration_state_cmp(void *obj, void *arg, int flags)
312 {
313         const struct sip_outbound_registration_state *object_left = obj;
314         const struct sip_outbound_registration_state *object_right = arg;
315         const char *right_key = arg;
316         int cmp;
317
318         switch (flags & OBJ_SEARCH_MASK) {
319         case OBJ_SEARCH_OBJECT:
320                 right_key = ast_sorcery_object_get_id(object_right->registration);
321                 /* Fall through */
322         case OBJ_SEARCH_KEY:
323                 cmp = strcmp(ast_sorcery_object_get_id(object_left->registration), right_key);
324                 break;
325         case OBJ_SEARCH_PARTIAL_KEY:
326                 /* Not supported by container. */
327                 ast_assert(0);
328                 return 0;
329         default:
330                 cmp = 0;
331                 break;
332         }
333         if (cmp) {
334                 return 0;
335         }
336         return CMP_MATCH;
337 }
338
339 static struct sip_outbound_registration_state *get_state(const char *id)
340 {
341         RAII_VAR(struct ao2_container *, states,
342                  ao2_global_obj_ref(current_states), ao2_cleanup);
343         return states ? ao2_find(states, id, OBJ_SEARCH_KEY) : NULL;
344 }
345
346 static int registration_state_add(void *obj, void *arg, int flags)
347 {
348         struct sip_outbound_registration_state *state =
349                 get_state(ast_sorcery_object_get_id(obj));
350
351         if (state) {
352                 ao2_link(arg, state);
353                 ao2_ref(state, -1);
354         }
355
356         return 0;
357 }
358
359 static struct ao2_container *get_registrations(void)
360 {
361         RAII_VAR(struct ao2_container *, new_states, NULL, ao2_cleanup);
362         struct ao2_container *registrations = ast_sorcery_retrieve_by_fields(
363                 ast_sip_get_sorcery(), "registration",
364                 AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
365
366         if (!(new_states = ao2_container_alloc(DEFAULT_STATE_BUCKETS,
367                       registration_state_hash, registration_state_cmp))) {
368                 ast_log(LOG_ERROR, "Unable to allocate registration states container\n");
369                 return NULL;
370         }
371
372         if (registrations && ao2_container_count(registrations)) {
373                 ao2_callback(registrations, OBJ_NODATA, registration_state_add, new_states);
374         }
375
376         ao2_global_obj_replace_unref(current_states, new_states);
377         return registrations;
378 }
379
380 /*! \brief Callback function for matching an outbound registration based on line */
381 static int line_identify_relationship(void *obj, void *arg, int flags)
382 {
383         struct sip_outbound_registration_state *state = obj;
384         pjsip_param *line = arg;
385
386         return !pj_strcmp2(&line->value, state->client_state->line) ? CMP_MATCH | CMP_STOP : 0;
387 }
388
389 /*! \brief Endpoint identifier which uses the 'line' parameter to establish a relationship to an outgoing registration */
390 static struct ast_sip_endpoint *line_identify(pjsip_rx_data *rdata)
391 {
392         pjsip_sip_uri *uri;
393         static const pj_str_t LINE_STR = { "line", 4 };
394         pjsip_param *line;
395         RAII_VAR(struct ao2_container *, states, NULL, ao2_cleanup);
396         RAII_VAR(struct sip_outbound_registration_state *, state, NULL, ao2_cleanup);
397
398         if (!PJSIP_URI_SCHEME_IS_SIP(rdata->msg_info.to->uri) && !PJSIP_URI_SCHEME_IS_SIPS(rdata->msg_info.to->uri)) {
399                 return NULL;
400         }
401         uri = pjsip_uri_get_uri(rdata->msg_info.to->uri);
402
403         line = pjsip_param_find(&uri->other_param, &LINE_STR);
404         if (!line) {
405                 return NULL;
406         }
407
408         states = ao2_global_obj_ref(current_states);
409         if (!states) {
410                 return NULL;
411         }
412
413         state = ao2_callback(states, 0, line_identify_relationship, line);
414         if (!state || ast_strlen_zero(state->registration->endpoint)) {
415                 return NULL;
416         }
417
418         ast_debug(3, "Determined relationship to outbound registration '%s' based on line '%s', using configured endpoint '%s'\n",
419                 ast_sorcery_object_get_id(state->registration), state->client_state->line, state->registration->endpoint);
420
421         return ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", state->registration->endpoint);
422 }
423
424 static struct ast_sip_endpoint_identifier line_identifier = {
425         .identify_endpoint = line_identify,
426 };
427
428 /*! \brief Helper function which cancels the timer on a client */
429 static void cancel_registration(struct sip_outbound_registration_client_state *client_state)
430 {
431         if (pj_timer_heap_cancel(pjsip_endpt_get_timer_heap(ast_sip_get_pjsip_endpoint()), &client_state->timer)) {
432                 /* The timer was successfully cancelled, drop the refcount of client_state */
433                 ao2_ref(client_state, -1);
434         }
435 }
436
437 static pj_str_t PATH_NAME = { "path", 4 };
438
439 /*! \brief Callback function for registering */
440 static int handle_client_registration(void *data)
441 {
442         RAII_VAR(struct sip_outbound_registration_client_state *, client_state, data, ao2_cleanup);
443         pjsip_tx_data *tdata;
444         pjsip_regc_info info;
445         char server_uri[PJSIP_MAX_URL_SIZE], client_uri[PJSIP_MAX_URL_SIZE];
446
447         cancel_registration(client_state);
448
449         if ((client_state->status == SIP_REGISTRATION_STOPPED) ||
450                 (pjsip_regc_register(client_state->client, PJ_FALSE, &tdata) != PJ_SUCCESS)) {
451                 return 0;
452         }
453
454         pjsip_regc_get_info(client_state->client, &info);
455         ast_copy_pj_str(server_uri, &info.server_uri, sizeof(server_uri));
456         ast_copy_pj_str(client_uri, &info.client_uri, sizeof(client_uri));
457         ast_debug(3, "REGISTER attempt %u to '%s' with client '%s'\n",
458                   client_state->retries + 1, server_uri, client_uri);
459
460         if (client_state->support_path) {
461                 pjsip_supported_hdr *hdr;
462
463                 hdr = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_SUPPORTED, NULL);
464                 if (!hdr) {
465                         /* insert a new Supported header */
466                         hdr = pjsip_supported_hdr_create(tdata->pool);
467                         if (!hdr) {
468                                 return -1;
469                         }
470
471                         pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *)hdr);
472                 }
473
474                 /* add on to the existing Supported header */
475                 pj_strassign(&hdr->values[hdr->count++], &PATH_NAME);
476         }
477
478         /* Due to the registration the callback may now get called, so bump the ref count */
479         ao2_ref(client_state, +1);
480         if (pjsip_regc_send(client_state->client, tdata) != PJ_SUCCESS) {
481                 ao2_ref(client_state, -1);
482         }
483
484         return 0;
485 }
486
487 /*! \brief Timer callback function, used just for registrations */
488 static void sip_outbound_registration_timer_cb(pj_timer_heap_t *timer_heap, struct pj_timer_entry *entry)
489 {
490         struct sip_outbound_registration_client_state *client_state = entry->user_data;
491
492         ao2_ref(client_state, +1);
493         if (ast_sip_push_task(client_state->serializer, handle_client_registration, client_state)) {
494                 ast_log(LOG_WARNING, "Failed to pass outbound registration to threadpool\n");
495                 ao2_ref(client_state, -1);
496         }
497
498         entry->id = 0;
499 }
500
501 /*! \brief Helper function which sets up the timer to re-register in a specific amount of time */
502 static void schedule_registration(struct sip_outbound_registration_client_state *client_state, unsigned int seconds)
503 {
504         pj_time_val delay = { .sec = seconds, };
505
506         cancel_registration(client_state);
507
508         ao2_ref(client_state, +1);
509         if (pjsip_endpt_schedule_timer(ast_sip_get_pjsip_endpoint(), &client_state->timer, &delay) != PJ_SUCCESS) {
510                 ast_log(LOG_WARNING, "Failed to pass timed registration to scheduler\n");
511                 ao2_ref(client_state, -1);
512         }
513 }
514
515 /*! \brief Callback function for unregistering (potentially) and destroying state */
516 static int handle_client_state_destruction(void *data)
517 {
518         RAII_VAR(struct sip_outbound_registration_client_state *, client_state, data, ao2_cleanup);
519
520         cancel_registration(client_state);
521
522         if (client_state->client) {
523                 pjsip_regc_info info;
524
525                 pjsip_regc_get_info(client_state->client, &info);
526
527                 if (info.is_busy == PJ_TRUE) {
528                         /* If a client transaction is in progress we defer until it is complete */
529                         client_state->destroy = 1;
530                         return 0;
531                 }
532
533                 if (client_state->status != SIP_REGISTRATION_UNREGISTERED && client_state->status != SIP_REGISTRATION_REJECTED_PERMANENT) {
534                         pjsip_tx_data *tdata;
535
536                         if (pjsip_regc_unregister(client_state->client, &tdata) == PJ_SUCCESS) {
537                                 pjsip_regc_send(client_state->client, tdata);
538                         }
539                 }
540
541                 pjsip_regc_destroy(client_state->client);
542         }
543
544         client_state->status = SIP_REGISTRATION_STOPPED;
545         ast_sip_auth_vector_destroy(&client_state->outbound_auths);
546
547         return 0;
548 }
549
550 /*! \brief Structure for registration response */
551 struct registration_response {
552         /*! \brief Response code for the registration attempt */
553         int code;
554         /*! \brief Expiration time for registration */
555         int expiration;
556         /*! \brief Retry-After value */
557         int retry_after;
558         /*! \brief Outbound registration client state */
559         struct sip_outbound_registration_client_state *client_state;
560         /*! \brief The response message */
561         pjsip_rx_data *rdata;
562         /*! \brief The response transaction */
563         pjsip_transaction *tsx;
564 };
565
566 /*! \brief Registration response structure destructor */
567 static void registration_response_destroy(void *obj)
568 {
569         struct registration_response *response = obj;
570
571         if (response->rdata) {
572                 pjsip_rx_data_free_cloned(response->rdata);
573         }
574
575         ao2_cleanup(response->client_state);
576 }
577
578 /* \brief Helper funtion which determines if a response code is temporal or not */
579 static int sip_outbound_registration_is_temporal(unsigned int code,
580                 struct sip_outbound_registration_client_state *client_state)
581 {
582         /* Shamelessly taken from pjsua */
583         if (code == PJSIP_SC_REQUEST_TIMEOUT ||
584                 code == PJSIP_SC_INTERNAL_SERVER_ERROR ||
585                 code == PJSIP_SC_BAD_GATEWAY ||
586                 code == PJSIP_SC_SERVICE_UNAVAILABLE ||
587                 code == PJSIP_SC_SERVER_TIMEOUT ||
588                 ((code == PJSIP_SC_UNAUTHORIZED ||
589                   code == PJSIP_SC_PROXY_AUTHENTICATION_REQUIRED) &&
590                  !client_state->auth_rejection_permanent) ||
591                 PJSIP_IS_STATUS_IN_CLASS(code, 600)) {
592                 return 1;
593         } else {
594                 return 0;
595         }
596 }
597
598 static void schedule_retry(struct registration_response *response, unsigned int interval,
599                            const char *server_uri, const char *client_uri)
600 {
601         response->client_state->status = SIP_REGISTRATION_REJECTED_TEMPORARY;
602         schedule_registration(response->client_state, interval);
603
604         if (response->rdata) {
605                 ast_log(LOG_WARNING, "Temporal response '%d' received from '%s' on "
606                         "registration attempt to '%s', retrying in '%u'\n",
607                         response->code, server_uri, client_uri, interval);
608         } else {
609                 ast_log(LOG_WARNING, "No response received from '%s' on "
610                         "registration attempt to '%s', retrying in '%u'\n",
611                         server_uri, client_uri, interval);
612         }
613 }
614
615 /*! \brief Callback function for handling a response to a registration attempt */
616 static int handle_registration_response(void *data)
617 {
618         RAII_VAR(struct registration_response *, response, data, ao2_cleanup);
619         pjsip_regc_info info;
620         char server_uri[PJSIP_MAX_URL_SIZE], client_uri[PJSIP_MAX_URL_SIZE];
621
622         if (response->client_state->status == SIP_REGISTRATION_STOPPED) {
623                 return 0;
624         }
625
626         pjsip_regc_get_info(response->client_state->client, &info);
627         ast_copy_pj_str(server_uri, &info.server_uri, sizeof(server_uri));
628         ast_copy_pj_str(client_uri, &info.client_uri, sizeof(client_uri));
629
630         if (response->code == 401 || response->code == 407) {
631                 pjsip_tx_data *tdata;
632                 if (!ast_sip_create_request_with_auth(&response->client_state->outbound_auths,
633                                 response->rdata, response->tsx, &tdata)) {
634                         ao2_ref(response->client_state, +1);
635                         if (pjsip_regc_send(response->client_state->client, tdata) != PJ_SUCCESS) {
636                                 ao2_cleanup(response->client_state);
637                         }
638                         return 0;
639                 }
640                 /* Otherwise, fall through so the failure is processed appropriately */
641         }
642
643         if (PJSIP_IS_STATUS_IN_CLASS(response->code, 200)) {
644                 /* Check if this is in regards to registering or unregistering */
645                 if (response->expiration) {
646                         /* If the registration went fine simply reschedule registration for the future */
647                         ast_debug(1, "Outbound registration to '%s' with client '%s' successful\n", server_uri, client_uri);
648                         response->client_state->status = SIP_REGISTRATION_REGISTERED;
649                         response->client_state->retries = 0;
650                         schedule_registration(response->client_state, response->expiration - REREGISTER_BUFFER_TIME);
651                 } else {
652                         ast_debug(1, "Outbound unregistration to '%s' with client '%s' successful\n", server_uri, client_uri);
653                         response->client_state->status = SIP_REGISTRATION_UNREGISTERED;
654                 }
655         } else if (response->retry_after) {
656                 /* If we have been instructed to retry after a period of time, schedule it as such */
657                 schedule_retry(response, response->retry_after, server_uri, client_uri);
658         } else if (response->client_state->retry_interval && sip_outbound_registration_is_temporal(response->code, response->client_state)) {
659                 if (response->client_state->retries == response->client_state->max_retries) {
660                         /* If we received enough temporal responses to exceed our maximum give up permanently */
661                         response->client_state->status = SIP_REGISTRATION_REJECTED_PERMANENT;
662                         ast_log(LOG_WARNING, "Maximum retries reached when attempting outbound registration to '%s' with client '%s', stopping registration attempt\n",
663                                 server_uri, client_uri);
664                 } else {
665                         /* On the other hand if we can still try some more do so */
666                         response->client_state->retries++;
667                         schedule_retry(response, response->client_state->retry_interval, server_uri, client_uri);
668                 }
669         } else {
670                 if (response->code == 403
671                         && response->client_state->forbidden_retry_interval
672                         && response->client_state->retries < response->client_state->max_retries) {
673                         /* A forbidden response retry interval is configured and there are retries remaining */
674                         response->client_state->status = SIP_REGISTRATION_REJECTED_TEMPORARY;
675                         response->client_state->retries++;
676                         schedule_registration(response->client_state, response->client_state->forbidden_retry_interval);
677                         ast_log(LOG_WARNING, "403 Forbidden fatal response received from '%s' on registration attempt to '%s', retrying in '%u' seconds\n",
678                                 server_uri, client_uri, response->client_state->forbidden_retry_interval);
679                 } else {
680                         /* Finally if there's no hope of registering give up */
681                         response->client_state->status = SIP_REGISTRATION_REJECTED_PERMANENT;
682                         if (response->rdata) {
683                                 ast_log(LOG_WARNING, "Fatal response '%d' received from '%s' on registration attempt to '%s', stopping outbound registration\n",
684                                         response->code, server_uri, client_uri);
685                         } else {
686                                 ast_log(LOG_WARNING, "Fatal registration attempt to '%s', stopping outbound registration\n", client_uri);
687                         }
688                 }
689         }
690
691         ast_system_publish_registry("PJSIP", client_uri, server_uri, sip_outbound_registration_status_str[response->client_state->status], NULL);
692
693         /* If deferred destruction is in use see if we need to destroy now */
694         if (response->client_state->destroy) {
695                 handle_client_state_destruction(response->client_state);
696         }
697
698         return 0;
699 }
700
701 /*! \brief Callback function for outbound registration client */
702 static void sip_outbound_registration_response_cb(struct pjsip_regc_cbparam *param)
703 {
704         RAII_VAR(struct sip_outbound_registration_client_state *, client_state, param->token, ao2_cleanup);
705         struct registration_response *response = ao2_alloc(sizeof(*response), registration_response_destroy);
706
707         response->code = param->code;
708         response->expiration = param->expiration;
709         response->client_state = client_state;
710         ao2_ref(response->client_state, +1);
711
712         if (param->rdata) {
713                 struct pjsip_retry_after_hdr *retry_after = pjsip_msg_find_hdr(param->rdata->msg_info.msg, PJSIP_H_RETRY_AFTER, NULL);
714
715                 response->retry_after = retry_after ? retry_after->ivalue : 0;
716                 response->tsx = pjsip_rdata_get_tsx(param->rdata);
717                 pjsip_rx_data_clone(param->rdata, 0, &response->rdata);
718         }
719
720         if (ast_sip_push_task(client_state->serializer, handle_registration_response, response)) {
721                 ast_log(LOG_WARNING, "Failed to pass incoming registration response to threadpool\n");
722                 ao2_cleanup(response);
723         }
724 }
725
726 /*! \brief Destructor function for registration state */
727 static void sip_outbound_registration_state_destroy(void *obj)
728 {
729         struct sip_outbound_registration_state *state = obj;
730
731         ao2_cleanup(state->registration);
732
733         if (!state->client_state) {
734                 return;
735         }
736
737         if (state->client_state->serializer && ast_sip_push_task(state->client_state->serializer, handle_client_state_destruction, state->client_state)) {
738                 ast_log(LOG_WARNING, "Failed to pass outbound registration client destruction to threadpool\n");
739                 ao2_ref(state->client_state, -1);
740         }
741 }
742
743 /*! \brief Destructor function for client registration state */
744 static void sip_outbound_registration_client_state_destroy(void *obj)
745 {
746         struct sip_outbound_registration_client_state *client_state = obj;
747
748         ast_taskprocessor_unreference(client_state->serializer);
749 }
750
751 /*! \brief Allocator function for registration state */
752 static struct sip_outbound_registration_state *sip_outbound_registration_state_alloc(struct sip_outbound_registration *registration)
753 {
754         struct sip_outbound_registration_state *state = ao2_alloc(sizeof(*state), sip_outbound_registration_state_destroy);
755
756         if (!state || !(state->client_state = ao2_alloc(sizeof(*state->client_state), sip_outbound_registration_client_state_destroy))) {
757                 ao2_cleanup(state);
758                 return NULL;
759         }
760
761         if (!(state->client_state->serializer = ast_sip_create_serializer())) {
762                 ao2_cleanup(state->client_state);
763                 ao2_cleanup(state);
764                 return NULL;
765         }
766
767         state->client_state->status = SIP_REGISTRATION_UNREGISTERED;
768         state->client_state->timer.user_data = state->client_state;
769         state->client_state->timer.cb = sip_outbound_registration_timer_cb;
770
771         state->registration = ao2_bump(registration);
772         return state;
773 }
774
775 /*! \brief Destructor function for registration information */
776 static void sip_outbound_registration_destroy(void *obj)
777 {
778         struct sip_outbound_registration *registration = obj;
779
780         ast_sip_auth_vector_destroy(&registration->outbound_auths);
781
782         ast_string_field_free_memory(registration);
783 }
784
785 /*! \brief Allocator function for registration information */
786 static void *sip_outbound_registration_alloc(const char *name)
787 {
788         struct sip_outbound_registration *registration = ast_sorcery_generic_alloc(sizeof(*registration), sip_outbound_registration_destroy);
789         if (!registration || ast_string_field_init(registration, 256)) {
790                 ao2_cleanup(registration);
791                 return NULL;
792         }
793
794         return registration;
795 }
796
797 /*! \brief Helper function which populates a pj_str_t with a contact header */
798 static int sip_dialog_create_contact(pj_pool_t *pool, pj_str_t *contact, const char *user, const pj_str_t *target, pjsip_tpselector *selector,
799         const char *line)
800 {
801         pj_str_t tmp, local_addr;
802         pjsip_uri *uri;
803         pjsip_sip_uri *sip_uri;
804         pjsip_transport_type_e type = PJSIP_TRANSPORT_UNSPECIFIED;
805         int local_port;
806
807         pj_strdup_with_null(pool, &tmp, target);
808
809         if (!(uri = pjsip_parse_uri(pool, tmp.ptr, tmp.slen, 0)) ||
810             (!PJSIP_URI_SCHEME_IS_SIP(uri) && !PJSIP_URI_SCHEME_IS_SIPS(uri))) {
811                 return -1;
812         }
813
814         sip_uri = pjsip_uri_get_uri(uri);
815
816         if (PJSIP_URI_SCHEME_IS_SIPS(sip_uri)) {
817                 type = PJSIP_TRANSPORT_TLS;
818         } else if (!sip_uri->transport_param.slen) {
819                 type = PJSIP_TRANSPORT_UDP;
820         } else {
821                 type = pjsip_transport_get_type_from_name(&sip_uri->transport_param);
822         }
823
824         if (type == PJSIP_TRANSPORT_UNSPECIFIED) {
825                 return -1;
826         }
827
828         if (pj_strchr(&sip_uri->host, ':')) {
829                 type = (pjsip_transport_type_e)(((int)type) + PJSIP_TRANSPORT_IPV6);
830         }
831
832         if (pjsip_tpmgr_find_local_addr(pjsip_endpt_get_tpmgr(ast_sip_get_pjsip_endpoint()), pool, type, selector,
833                                                               &local_addr, &local_port) != PJ_SUCCESS) {
834                 return -1;
835         }
836
837         if (!pj_strchr(&sip_uri->host, ':') && pj_strchr(&local_addr, ':')) {
838                 type = (pjsip_transport_type_e)(((int)type) + PJSIP_TRANSPORT_IPV6);
839         }
840
841         contact->ptr = pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE);
842         contact->slen = pj_ansi_snprintf(contact->ptr, PJSIP_MAX_URL_SIZE,
843                                       "<%s:%s@%s%.*s%s:%d%s%s%s%s>",
844                                       (pjsip_transport_get_flag_from_type(type) & PJSIP_TRANSPORT_SECURE) ? "sips" : "sip",
845                                       user,
846                                       (type & PJSIP_TRANSPORT_IPV6) ? "[" : "",
847                                       (int)local_addr.slen,
848                                       local_addr.ptr,
849                                       (type & PJSIP_TRANSPORT_IPV6) ? "]" : "",
850                                       local_port,
851                                       (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? ";transport=" : "",
852                                       (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? pjsip_transport_get_type_name(type) : "",
853                                       !ast_strlen_zero(line) ? ";line=" : "",
854                                       S_OR(line, ""));
855
856         return 0;
857 }
858
859 /*!
860  * \internal
861  * \brief Check if a registration can be reused
862  *
863  * This checks if the existing outbound registration's configuration differs from a newly-applied
864  * outbound registration to see if the applied one.
865  *
866  * \param existing The pre-existing outbound registration
867  * \param applied The newly-created registration
868  */
869 static int can_reuse_registration(struct sip_outbound_registration *existing, struct sip_outbound_registration *applied)
870 {
871         int i;
872
873         if (strcmp(existing->server_uri, applied->server_uri) || strcmp(existing->client_uri, applied->client_uri) ||
874                 strcmp(existing->transport, applied->transport) || strcmp(existing->contact_user, applied->contact_user) ||
875                 strcmp(existing->outbound_proxy, applied->outbound_proxy) ||
876                 AST_VECTOR_SIZE(&existing->outbound_auths) != AST_VECTOR_SIZE(&applied->outbound_auths) ||
877                 existing->auth_rejection_permanent != applied->auth_rejection_permanent) {
878                 return 0;
879         }
880
881         for (i = 0; i < AST_VECTOR_SIZE(&existing->outbound_auths); ++i) {
882                 if (strcmp(AST_VECTOR_GET(&existing->outbound_auths, i), AST_VECTOR_GET(&applied->outbound_auths, i))) {
883                         return 0;
884                 }
885         }
886
887         return 1;
888 }
889
890 /*! \brief Helper function that allocates a pjsip registration client and configures it */
891 static int sip_outbound_registration_regc_alloc(void *data)
892 {
893         struct sip_outbound_registration_state *state = data;
894         RAII_VAR(struct sip_outbound_registration *, registration,
895                  ao2_bump(state->registration), ao2_cleanup);
896         pj_pool_t *pool;
897         pj_str_t tmp;
898         pjsip_uri *uri;
899         pj_str_t server_uri, client_uri, contact_uri;
900         pjsip_tpselector selector = { .type = PJSIP_TPSELECTOR_NONE, };
901
902         pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(), "URI Validation", 256, 256);
903         if (!pool) {
904                 ast_log(LOG_ERROR, "Could not create pool for URI validation on outbound registration '%s'\n",
905                         ast_sorcery_object_get_id(registration));
906                 return -1;
907         }
908
909         pj_strdup2_with_null(pool, &tmp, registration->server_uri);
910         uri = pjsip_parse_uri(pool, tmp.ptr, tmp.slen, 0);
911         if (!uri) {
912                 ast_log(LOG_ERROR, "Invalid server URI '%s' specified on outbound registration '%s'\n",
913                         registration->server_uri, ast_sorcery_object_get_id(registration));
914                 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
915                 return -1;
916         }
917
918         pj_strdup2_with_null(pool, &tmp, registration->client_uri);
919         uri = pjsip_parse_uri(pool, tmp.ptr, tmp.slen, 0);
920         if (!uri) {
921                 ast_log(LOG_ERROR, "Invalid client URI '%s' specified on outbound registration '%s'\n",
922                         registration->client_uri, ast_sorcery_object_get_id(registration));
923                 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
924                 return -1;
925         }
926
927         pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
928
929         if (!ast_strlen_zero(registration->transport)) {
930                 RAII_VAR(struct ast_sip_transport *, transport, ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "transport", registration->transport), ao2_cleanup);
931
932                 if (!transport || !transport->state) {
933                         ast_log(LOG_ERROR, "Unable to retrieve PJSIP transport '%s' "
934                                 " for outbound registration", registration->transport);
935                         return -1;
936                 }
937
938                 if (transport->state->transport) {
939                         selector.type = PJSIP_TPSELECTOR_TRANSPORT;
940                         selector.u.transport = transport->state->transport;
941                 } else if (transport->state->factory) {
942                         selector.type = PJSIP_TPSELECTOR_LISTENER;
943                         selector.u.listener = transport->state->factory;
944                 } else {
945                         return -1;
946                 }
947         }
948
949         if (!state->client_state->client &&
950                 pjsip_regc_create(ast_sip_get_pjsip_endpoint(), state->client_state, sip_outbound_registration_response_cb,
951                 &state->client_state->client) != PJ_SUCCESS) {
952                 return -1;
953         }
954
955         pjsip_regc_set_transport(state->client_state->client, &selector);
956
957         if (!ast_strlen_zero(registration->outbound_proxy)) {
958                 pjsip_route_hdr route_set, *route;
959                 static const pj_str_t ROUTE_HNAME = { "Route", 5 };
960                 pj_str_t tmp;
961
962                 pj_list_init(&route_set);
963
964                 pj_strdup2_with_null(pjsip_regc_get_pool(state->client_state->client), &tmp, registration->outbound_proxy);
965                 if (!(route = pjsip_parse_hdr(pjsip_regc_get_pool(state->client_state->client), &ROUTE_HNAME, tmp.ptr, tmp.slen, NULL))) {
966                         return -1;
967                 }
968                 pj_list_insert_nodes_before(&route_set, route);
969
970                 pjsip_regc_set_route_set(state->client_state->client, &route_set);
971         }
972
973         if (state->registration->line) {
974                 ast_generate_random_string(state->client_state->line, sizeof(state->client_state->line));
975         }
976
977         pj_cstr(&server_uri, registration->server_uri);
978
979
980         if (sip_dialog_create_contact(pjsip_regc_get_pool(state->client_state->client), &contact_uri, S_OR(registration->contact_user, "s"), &server_uri, &selector,
981                 state->client_state->line)) {
982                 return -1;
983         }
984
985         pj_cstr(&client_uri, registration->client_uri);
986         if (pjsip_regc_init(state->client_state->client, &server_uri, &client_uri, &client_uri, 1, &contact_uri, registration->expiration) != PJ_SUCCESS) {
987                 return -1;
988         }
989
990         return 0;
991 }
992
993 /*! \brief Helper function which performs a single registration */
994 static int sip_outbound_registration_perform(void *data)
995 {
996         RAII_VAR(struct sip_outbound_registration_state *, state, data, ao2_cleanup);
997         RAII_VAR(struct sip_outbound_registration *, registration, ao2_bump(state->registration), ao2_cleanup);
998         size_t i;
999
1000         /* Just in case the client state is being reused for this registration, free the auth information */
1001         ast_sip_auth_vector_destroy(&state->client_state->outbound_auths);
1002
1003         AST_VECTOR_INIT(&state->client_state->outbound_auths, AST_VECTOR_SIZE(&registration->outbound_auths));
1004         for (i = 0; i < AST_VECTOR_SIZE(&registration->outbound_auths); ++i) {
1005                 const char *name = ast_strdup(AST_VECTOR_GET(&registration->outbound_auths, i));
1006                 AST_VECTOR_APPEND(&state->client_state->outbound_auths, name);
1007         }
1008         state->client_state->retry_interval = registration->retry_interval;
1009         state->client_state->forbidden_retry_interval = registration->forbidden_retry_interval;
1010         state->client_state->max_retries = registration->max_retries;
1011         state->client_state->retries = 0;
1012         state->client_state->support_path = registration->support_path;
1013         state->client_state->auth_rejection_permanent = registration->auth_rejection_permanent;
1014
1015         pjsip_regc_update_expires(state->client_state->client, registration->expiration);
1016
1017         schedule_registration(state->client_state, (ast_random() % 10) + 1);
1018
1019         return 0;
1020 }
1021
1022 /*! \brief Apply function which finds or allocates a state structure */
1023 static int sip_outbound_registration_apply(const struct ast_sorcery *sorcery, void *obj)
1024 {
1025         RAII_VAR(struct ao2_container *, states, ao2_global_obj_ref(current_states), ao2_cleanup);
1026         RAII_VAR(struct sip_outbound_registration_state *, state,
1027                  ao2_find(states, ast_sorcery_object_get_id(obj), OBJ_SEARCH_KEY), ao2_cleanup);
1028         RAII_VAR(struct sip_outbound_registration_state *, new_state, NULL, ao2_cleanup);
1029         struct sip_outbound_registration *applied = obj;
1030
1031         if (ast_strlen_zero(applied->server_uri)) {
1032                 ast_log(LOG_ERROR, "No server URI specified on outbound registration '%s'",
1033                         ast_sorcery_object_get_id(applied));
1034                 return -1;
1035         } else if (ast_strlen_zero(applied->client_uri)) {
1036                 ast_log(LOG_ERROR, "No client URI specified on outbound registration '%s'\n",
1037                         ast_sorcery_object_get_id(applied));
1038                 return -1;
1039         } else if (applied->line && ast_strlen_zero(applied->endpoint)) {
1040                 ast_log(LOG_ERROR, "Line support has been enabled on outbound registration '%s' without providing an endpoint\n",
1041                         ast_sorcery_object_get_id(applied));
1042                 return -1;
1043         } else if (!ast_strlen_zero(applied->endpoint) && !applied->line) {
1044                 ast_log(LOG_ERROR, "An endpoint has been specified on outbound registration '%s' without enabling line support\n",
1045                         ast_sorcery_object_get_id(applied));
1046                 return -1;
1047         }
1048
1049         if (state && can_reuse_registration(state->registration, applied)) {
1050                 ao2_replace(state->registration, applied);
1051                 return 0;
1052         }
1053
1054         if (!(new_state = sip_outbound_registration_state_alloc(applied))) {
1055                 return -1;
1056         }
1057
1058         if (ast_sip_push_task_synchronous(NULL, sip_outbound_registration_regc_alloc, new_state)) {
1059                 return -1;
1060         }
1061
1062         if (ast_sip_push_task(new_state->client_state->serializer,
1063                               sip_outbound_registration_perform, ao2_bump(new_state))) {
1064                 ast_log(LOG_ERROR, "Failed to perform outbound registration on '%s'\n",
1065                         ast_sorcery_object_get_id(new_state->registration));
1066                 ao2_ref(new_state, -1);
1067                 return -1;
1068         }
1069
1070         ao2_lock(states);
1071
1072         if (state) {
1073                 ao2_unlink(states, state);
1074         }
1075
1076         ao2_link(states, new_state);
1077         ao2_unlock(states);
1078
1079         return 0;
1080 }
1081
1082 static int outbound_auth_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
1083 {
1084         struct sip_outbound_registration *registration = obj;
1085
1086         return ast_sip_auth_vector_init(&registration->outbound_auths, var->value);
1087 }
1088
1089 static int outbound_auths_to_str(const void *obj, const intptr_t *args, char **buf)
1090 {
1091         const struct sip_outbound_registration *registration = obj;
1092
1093         return ast_sip_auths_to_str(&registration->outbound_auths, buf);
1094 }
1095
1096 static int outbound_auths_to_var_list(const void *obj, struct ast_variable **fields)
1097 {
1098         const struct sip_outbound_registration *registration = obj;
1099         int i;
1100         struct ast_variable *head = NULL;
1101
1102         for (i = 0; i < AST_VECTOR_SIZE(&registration->outbound_auths) ; i++) {
1103                 ast_variable_list_append(&head, ast_variable_new("outbound_auth",
1104                         AST_VECTOR_GET(&registration->outbound_auths, i), ""));
1105         }
1106
1107         if (head) {
1108                 *fields = head;
1109         }
1110
1111         return 0;
1112 }
1113
1114 static int unregister_task(void *obj)
1115 {
1116         RAII_VAR(struct sip_outbound_registration_state*, state, obj, ao2_cleanup);
1117         struct pjsip_regc *client = state->client_state->client;
1118         pjsip_tx_data *tdata;
1119
1120         if (pjsip_regc_unregister(client, &tdata) != PJ_SUCCESS) {
1121                 return 0;
1122         }
1123
1124         ao2_ref(state->client_state, +1);
1125         if (pjsip_regc_send(client, tdata) != PJ_SUCCESS) {
1126                 ao2_cleanup(state->client_state);
1127         }
1128
1129         return 0;
1130 }
1131
1132 static int queue_unregister(struct sip_outbound_registration_state *state)
1133 {
1134         ao2_ref(state, +1);
1135         if (ast_sip_push_task(state->client_state->serializer, unregister_task, state)) {
1136                 ao2_ref(state, -1);
1137                 return -1;
1138         }
1139         return 0;
1140 }
1141
1142 static char *cli_complete_registration(const char *line, const char *word,
1143                                        int pos, int state)
1144 {
1145         char *result = NULL;
1146         int wordlen;
1147         int which = 0;
1148         struct sip_outbound_registration *registration;
1149         RAII_VAR(struct ao2_container *, registrations, NULL, ao2_cleanup);
1150         struct ao2_iterator i;
1151
1152         if (pos != 3) {
1153                 return NULL;
1154         }
1155
1156         wordlen = strlen(word);
1157         registrations = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "registration",
1158                 AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
1159         if (!registrations) {
1160                 return NULL;
1161         }
1162
1163         i = ao2_iterator_init(registrations, 0);
1164         while ((registration = ao2_iterator_next(&i))) {
1165                 const char *name = ast_sorcery_object_get_id(registration);
1166                 if (!strncasecmp(word, name, wordlen) && ++which > state) {
1167                         result = ast_strdup(name);
1168                 }
1169
1170                 ao2_cleanup(registration);
1171                 if (result) {
1172                         break;
1173                 }
1174         }
1175         ao2_iterator_destroy(&i);
1176         return result;
1177 }
1178
1179 static char *cli_unregister(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1180 {
1181         RAII_VAR(struct sip_outbound_registration_state *, state, NULL, ao2_cleanup);
1182         const char *registration_name;
1183
1184         switch (cmd) {
1185         case CLI_INIT:
1186                 e->command = "pjsip send unregister";
1187                 e->usage =
1188                         "Usage: pjsip send unregister <registration>\n"
1189                         "       Send a SIP REGISTER request to the specified outbound "
1190                         "registration with an expiration of 0. This will cause the contact "
1191                         "added by this registration to be removed on the remote system. Note: "
1192                         "The specified outbound registration will attempt to re-register "
1193                         "according to its last registration expiration.\n";
1194                 return NULL;
1195         case CLI_GENERATE:
1196                 return cli_complete_registration(a->line, a->word, a->pos, a->n);
1197         }
1198
1199         if (a->argc != 4) {
1200                 return CLI_SHOWUSAGE;
1201         }
1202
1203         registration_name = a->argv[3];
1204
1205         state = get_state(registration_name);
1206         if (!state) {
1207                 ast_cli(a->fd, "Unable to retrieve registration %s\n", registration_name);
1208                 return CLI_FAILURE;
1209         }
1210
1211         if (queue_unregister(state)) {
1212                 ast_cli(a->fd, "Failed to queue unregistration");
1213                 return 0;
1214         }
1215
1216         return CLI_SUCCESS;
1217 }
1218
1219 static int ami_unregister(struct mansession *s, const struct message *m)
1220 {
1221         const char *registration_name = astman_get_header(m, "Registration");
1222         RAII_VAR(struct sip_outbound_registration_state *, state, NULL, ao2_cleanup);
1223
1224         if (ast_strlen_zero(registration_name)) {
1225                 astman_send_error(s, m, "Registration parameter missing.");
1226                 return 0;
1227         }
1228
1229         state = get_state(registration_name);
1230         if (!state) {
1231                 astman_send_error(s, m, "Unable to retrieve registration entry\n");
1232                 return 0;
1233         }
1234
1235         if (queue_unregister(state)) {
1236                 astman_send_ack(s, m, "Failed to queue unregistration");
1237                 return 0;
1238         }
1239
1240         astman_send_ack(s, m, "Unregistration sent");
1241         return 0;
1242 }
1243
1244 struct sip_ami_outbound {
1245         struct ast_sip_ami *ami;
1246         int registered;
1247         int not_registered;
1248         struct sip_outbound_registration *registration;
1249 };
1250
1251 static int ami_outbound_registration_task(void *obj)
1252 {
1253         struct sip_ami_outbound *ami = obj;
1254         RAII_VAR(struct ast_str *, buf,
1255                  ast_sip_create_ami_event("OutboundRegistrationDetail", ami->ami), ast_free);
1256         struct sip_outbound_registration_state *state;
1257
1258         if (!buf) {
1259                 return -1;
1260         }
1261
1262         ast_sip_sorcery_object_to_ami(ami->registration, &buf);
1263
1264         if ((state = get_state(ast_sorcery_object_get_id(ami->registration)))) {
1265                 pjsip_regc_info info;
1266                 if (state->client_state->status == SIP_REGISTRATION_REGISTERED) {
1267                         ++ami->registered;
1268                 } else {
1269                         ++ami->not_registered;
1270                 }
1271
1272                 ast_str_append(&buf, 0, "Status: %s%s",
1273                                sip_outbound_registration_status_str[
1274                                        state->client_state->status], "\r\n");
1275
1276                 pjsip_regc_get_info(state->client_state->client, &info);
1277                 ast_str_append(&buf, 0, "NextReg: %d%s", info.next_reg, "\r\n");
1278                 ao2_ref(state, -1);
1279         }
1280
1281         astman_append(ami->ami->s, "%s\r\n", ast_str_buffer(buf));
1282         return ast_sip_format_auths_ami(&ami->registration->outbound_auths, ami->ami);
1283 }
1284
1285 static int ami_outbound_registration_detail(void *obj, void *arg, int flags)
1286 {
1287         struct sip_ami_outbound *ami = arg;
1288
1289         ami->registration = obj;
1290         return ast_sip_push_task_synchronous(
1291                 NULL, ami_outbound_registration_task, ami);
1292 }
1293
1294 static int ami_show_outbound_registrations(struct mansession *s,
1295                                            const struct message *m)
1296 {
1297         struct ast_sip_ami ami = { .s = s, .m = m, .action_id = astman_get_header(m, "ActionID"), };
1298         struct sip_ami_outbound ami_outbound = { .ami = &ami };
1299         RAII_VAR(struct ao2_container *, regs, get_registrations(), ao2_cleanup);
1300
1301         if (!regs) {
1302                 astman_send_error(s, m, "Unable to retreive "
1303                                   "outbound registrations\n");
1304                 return -1;
1305         }
1306
1307         astman_send_listack(s, m, "Following are Events for each Outbound "
1308                             "registration", "start");
1309
1310         ao2_callback(regs, OBJ_NODATA, ami_outbound_registration_detail, &ami_outbound);
1311
1312         astman_append(s, "Event: OutboundRegistrationDetailComplete\r\n");
1313         if (!ast_strlen_zero(ami.action_id)) {
1314                 astman_append(s, "ActionID: %s\r\n", ami.action_id);
1315         }
1316         astman_append(s, "EventList: Complete\r\n"
1317                       "Registered: %d\r\n"
1318                       "NotRegistered: %d\r\n\r\n",
1319                       ami_outbound.registered,
1320                       ami_outbound.not_registered);
1321         return 0;
1322 }
1323
1324 static struct ao2_container *cli_get_container(void)
1325 {
1326         RAII_VAR(struct ao2_container *, container, get_registrations(), ao2_cleanup);
1327         struct ao2_container *s_container;
1328
1329         if (!container) {
1330                 return NULL;
1331         }
1332
1333         s_container = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, 0,
1334                 ast_sorcery_object_id_sort, ast_sorcery_object_id_compare);
1335         if (!s_container) {
1336                 return NULL;
1337         }
1338
1339         if (ao2_container_dup(s_container, container, 0)) {
1340                 ao2_ref(s_container, -1);
1341                 return NULL;
1342         }
1343
1344         return s_container;
1345 }
1346
1347 static int cli_iterator(void *container, ao2_callback_fn callback, void *args)
1348 {
1349         ao2_callback(container, OBJ_NODATA, callback, args);
1350
1351         return 0;
1352 }
1353
1354 static void *cli_retrieve_by_id(const char *id)
1355 {
1356         struct ao2_container *states;
1357         void *obj = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "registration", id);
1358
1359         if (!obj) {
1360                 /* if the object no longer exists then remove its state  */
1361                 ao2_find((states = ao2_global_obj_ref(current_states)),
1362                          id, OBJ_SEARCH_KEY | OBJ_UNLINK | OBJ_NODATA);
1363                 ao2_ref(states, -1);
1364         }
1365
1366         return obj;
1367 }
1368
1369 static int cli_print_header(void *obj, void *arg, int flags)
1370 {
1371         struct ast_sip_cli_context *context = arg;
1372
1373         ast_assert(context->output_buffer != NULL);
1374
1375         ast_str_append(&context->output_buffer, 0,
1376                 " <Registration/ServerURI..............................>  <Auth..........>  <Status.......>\n");
1377
1378         return 0;
1379 }
1380
1381 static int cli_print_body(void *obj, void *arg, int flags)
1382 {
1383         struct sip_outbound_registration *registration = obj;
1384         struct ast_sip_cli_context *context = arg;
1385         const char *id = ast_sorcery_object_get_id(registration);
1386         struct sip_outbound_registration_state *state = get_state(id);
1387 #define REGISTRATION_URI_FIELD_LEN      53
1388
1389         ast_assert(context->output_buffer != NULL);
1390
1391         ast_str_append(&context->output_buffer, 0, " %-s/%-*.*s  %-16s  %-16s\n",
1392                 id,
1393                 (int) (REGISTRATION_URI_FIELD_LEN - strlen(id)),
1394                 (int) (REGISTRATION_URI_FIELD_LEN - strlen(id)),
1395                 registration->server_uri,
1396                 AST_VECTOR_SIZE(&registration->outbound_auths)
1397                         ? AST_VECTOR_GET(&registration->outbound_auths, 0)
1398                         : "n/a",
1399                 sip_outbound_registration_status_str[state->client_state->status]);
1400         ao2_ref(state, -1);
1401
1402         if (context->show_details
1403                 || (context->show_details_only_level_0 && context->indent_level == 0)) {
1404                 ast_str_append(&context->output_buffer, 0, "\n");
1405                 ast_sip_cli_print_sorcery_objectset(registration, context, 0);
1406         }
1407
1408         return 0;
1409 }
1410
1411 /*
1412  * A function pointer to callback needs to be within the
1413  * module in order to avoid problems with an undefined
1414  * symbol when the module is loaded.
1415  */
1416 static char *my_cli_traverse_objects(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1417 {
1418         return ast_sip_cli_traverse_objects(e, cmd, a);
1419 }
1420
1421 static struct ast_cli_entry cli_outbound_registration[] = {
1422         AST_CLI_DEFINE(cli_unregister, "Send a REGISTER request to an outbound registration target with a expiration of 0"),
1423         AST_CLI_DEFINE(my_cli_traverse_objects, "List PJSIP Registrations",
1424                 .command = "pjsip list registrations",
1425                 .usage = "Usage: pjsip list registrations\n"
1426                                  "       List the configured PJSIP Registrations\n"),
1427         AST_CLI_DEFINE(my_cli_traverse_objects, "Show PJSIP Registrations",
1428                 .command = "pjsip show registrations",
1429                 .usage = "Usage: pjsip show registrations\n"
1430                                  "       Show the configured PJSIP Registrations\n"),
1431         AST_CLI_DEFINE(my_cli_traverse_objects, "Show PJSIP Registration",
1432                 .command = "pjsip show registration",
1433                 .usage = "Usage: pjsip show registration <id>\n"
1434                                  "       Show the configured PJSIP Registration\n"),
1435 };
1436
1437 static struct ast_sip_cli_formatter_entry *cli_formatter;
1438
1439 static int unload_module(void)
1440 {
1441         ast_sip_unregister_endpoint_identifier(&line_identifier);
1442         ast_cli_unregister_multiple(cli_outbound_registration, ARRAY_LEN(cli_outbound_registration));
1443         ast_sip_unregister_cli_formatter(cli_formatter);
1444         ast_manager_unregister("PJSIPShowRegistrationsOutbound");
1445         ast_manager_unregister("PJSIPUnregister");
1446
1447         ao2_global_obj_release(current_states);
1448
1449         return 0;
1450 }
1451
1452 static int load_module(void)
1453 {
1454         struct ao2_container *registrations, *new_states;
1455         CHECK_PJSIP_MODULE_LOADED();
1456
1457         ast_sorcery_apply_config(ast_sip_get_sorcery(), "res_pjsip_outbound_registration");
1458         ast_sorcery_apply_default(ast_sip_get_sorcery(), "registration", "config", "pjsip.conf,criteria=type=registration");
1459
1460         if (ast_sorcery_object_register(ast_sip_get_sorcery(), "registration", sip_outbound_registration_alloc, NULL, sip_outbound_registration_apply)) {
1461                 return AST_MODULE_LOAD_DECLINE;
1462         }
1463
1464         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "type", "", OPT_NOOP_T, 0, 0);
1465         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "server_uri", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, server_uri));
1466         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "client_uri", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, client_uri));
1467         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "contact_user", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, contact_user));
1468         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "transport", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, transport));
1469         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "outbound_proxy", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, outbound_proxy));
1470         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "expiration", "3600", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, expiration));
1471         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "retry_interval", "60", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, retry_interval));
1472         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "forbidden_retry_interval", "0", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, forbidden_retry_interval));
1473         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "max_retries", "10", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, max_retries));
1474         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "auth_rejection_permanent", "yes", OPT_BOOL_T, 1, FLDSET(struct sip_outbound_registration, auth_rejection_permanent));
1475         ast_sorcery_object_field_register_custom(ast_sip_get_sorcery(), "registration", "outbound_auth", "", outbound_auth_handler, outbound_auths_to_str, outbound_auths_to_var_list, 0, 0);
1476         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "support_path", "no", OPT_BOOL_T, 1, FLDSET(struct sip_outbound_registration, support_path));
1477         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "line", "no", OPT_BOOL_T, 1, FLDSET(struct sip_outbound_registration, line));
1478         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "endpoint", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, endpoint));
1479         ast_sip_register_endpoint_identifier(&line_identifier);
1480
1481         ast_manager_register_xml("PJSIPUnregister", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, ami_unregister);
1482         ast_manager_register_xml("PJSIPShowRegistrationsOutbound", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, ami_show_outbound_registrations);
1483
1484         cli_formatter = ao2_alloc(sizeof(struct ast_sip_cli_formatter_entry), NULL);
1485         if (!cli_formatter) {
1486                 ast_log(LOG_ERROR, "Unable to allocate memory for cli formatter\n");
1487                 unload_module();
1488                 return -1;
1489         }
1490         cli_formatter->name = "registration";
1491         cli_formatter->print_header = cli_print_header;
1492         cli_formatter->print_body = cli_print_body;
1493         cli_formatter->get_container = cli_get_container;
1494         cli_formatter->iterate = cli_iterator;
1495         cli_formatter->get_id = ast_sorcery_object_get_id;
1496         cli_formatter->retrieve_by_id = cli_retrieve_by_id;
1497
1498         ast_sip_register_cli_formatter(cli_formatter);
1499         ast_cli_register_multiple(cli_outbound_registration, ARRAY_LEN(cli_outbound_registration));
1500
1501         if (!(new_states = ao2_container_alloc(
1502                       DEFAULT_STATE_BUCKETS, registration_state_hash, registration_state_cmp))) {
1503                 ast_log(LOG_ERROR, "Unable to allocate registration states container\n");
1504                 unload_module();
1505                 return AST_MODULE_LOAD_FAILURE;
1506         }
1507         ao2_global_obj_replace_unref(current_states, new_states);
1508         ao2_ref(new_states, -1);
1509
1510         ast_sorcery_reload_object(ast_sip_get_sorcery(), "registration");
1511         if (!(registrations = get_registrations())) {
1512                 unload_module();
1513                 return AST_MODULE_LOAD_FAILURE;
1514         }
1515         ao2_ref(registrations, -1);
1516
1517         return AST_MODULE_LOAD_SUCCESS;
1518 }
1519
1520 static int reload_module(void)
1521 {
1522         ast_sorcery_reload_object(ast_sip_get_sorcery(), "registration");
1523         ao2_cleanup(get_registrations());
1524         return 0;
1525 }
1526
1527 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP Outbound Registration Support",
1528                 .support_level = AST_MODULE_SUPPORT_CORE,
1529                 .load = load_module,
1530                 .reload = reload_module,
1531                 .unload = unload_module,
1532                 .load_pri = AST_MODPRI_APP_DEPEND,
1533                );