Prevent potential infinite outbound authentication loops in registration.
[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         /*! \brief Non-zero if we have attempted sending a REGISTER with authentication */
276         unsigned int auth_attempted:1;
277 };
278
279 /*! \brief Outbound registration state information (persists for lifetime that registration should exist) */
280 struct sip_outbound_registration_state {
281         /*! \brief Outbound registration configuration object */
282         struct sip_outbound_registration *registration;
283         /*! \brief Client state information */
284         struct sip_outbound_registration_client_state *client_state;
285 };
286
287 /*! \brief Default number of state container buckets */
288 #define DEFAULT_STATE_BUCKETS 53
289 static AO2_GLOBAL_OBJ_STATIC(current_states);
290
291 /*! \brief hashing function for state objects */
292 static int registration_state_hash(const void *obj, const int flags)
293 {
294         const struct sip_outbound_registration_state *object;
295         const char *key;
296
297         switch (flags & OBJ_SEARCH_MASK) {
298         case OBJ_SEARCH_KEY:
299                 key = obj;
300                 break;
301         case OBJ_SEARCH_OBJECT:
302                 object = obj;
303                 key = ast_sorcery_object_get_id(object->registration);
304                 break;
305         default:
306                 ast_assert(0);
307                 return 0;
308         }
309         return ast_str_hash(key);
310 }
311
312 /*! \brief comparator function for state objects */
313 static int registration_state_cmp(void *obj, void *arg, int flags)
314 {
315         const struct sip_outbound_registration_state *object_left = obj;
316         const struct sip_outbound_registration_state *object_right = arg;
317         const char *right_key = arg;
318         int cmp;
319
320         switch (flags & OBJ_SEARCH_MASK) {
321         case OBJ_SEARCH_OBJECT:
322                 right_key = ast_sorcery_object_get_id(object_right->registration);
323                 /* Fall through */
324         case OBJ_SEARCH_KEY:
325                 cmp = strcmp(ast_sorcery_object_get_id(object_left->registration), right_key);
326                 break;
327         case OBJ_SEARCH_PARTIAL_KEY:
328                 /* Not supported by container. */
329                 ast_assert(0);
330                 return 0;
331         default:
332                 cmp = 0;
333                 break;
334         }
335         if (cmp) {
336                 return 0;
337         }
338         return CMP_MATCH;
339 }
340
341 static struct sip_outbound_registration_state *get_state(const char *id)
342 {
343         RAII_VAR(struct ao2_container *, states,
344                  ao2_global_obj_ref(current_states), ao2_cleanup);
345         return states ? ao2_find(states, id, OBJ_SEARCH_KEY) : NULL;
346 }
347
348 static int registration_state_add(void *obj, void *arg, int flags)
349 {
350         struct sip_outbound_registration_state *state =
351                 get_state(ast_sorcery_object_get_id(obj));
352
353         if (state) {
354                 ao2_link(arg, state);
355                 ao2_ref(state, -1);
356         }
357
358         return 0;
359 }
360
361 static struct ao2_container *get_registrations(void)
362 {
363         RAII_VAR(struct ao2_container *, new_states, NULL, ao2_cleanup);
364         struct ao2_container *registrations = ast_sorcery_retrieve_by_fields(
365                 ast_sip_get_sorcery(), "registration",
366                 AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
367
368         if (!(new_states = ao2_container_alloc(DEFAULT_STATE_BUCKETS,
369                       registration_state_hash, registration_state_cmp))) {
370                 ast_log(LOG_ERROR, "Unable to allocate registration states container\n");
371                 return NULL;
372         }
373
374         if (registrations && ao2_container_count(registrations)) {
375                 ao2_callback(registrations, OBJ_NODATA, registration_state_add, new_states);
376         }
377
378         ao2_global_obj_replace_unref(current_states, new_states);
379         return registrations;
380 }
381
382 /*! \brief Callback function for matching an outbound registration based on line */
383 static int line_identify_relationship(void *obj, void *arg, int flags)
384 {
385         struct sip_outbound_registration_state *state = obj;
386         pjsip_param *line = arg;
387
388         return !pj_strcmp2(&line->value, state->client_state->line) ? CMP_MATCH | CMP_STOP : 0;
389 }
390
391 /*! \brief Endpoint identifier which uses the 'line' parameter to establish a relationship to an outgoing registration */
392 static struct ast_sip_endpoint *line_identify(pjsip_rx_data *rdata)
393 {
394         pjsip_sip_uri *uri;
395         static const pj_str_t LINE_STR = { "line", 4 };
396         pjsip_param *line;
397         RAII_VAR(struct ao2_container *, states, NULL, ao2_cleanup);
398         RAII_VAR(struct sip_outbound_registration_state *, state, NULL, ao2_cleanup);
399
400         if (!PJSIP_URI_SCHEME_IS_SIP(rdata->msg_info.to->uri) && !PJSIP_URI_SCHEME_IS_SIPS(rdata->msg_info.to->uri)) {
401                 return NULL;
402         }
403         uri = pjsip_uri_get_uri(rdata->msg_info.to->uri);
404
405         line = pjsip_param_find(&uri->other_param, &LINE_STR);
406         if (!line) {
407                 return NULL;
408         }
409
410         states = ao2_global_obj_ref(current_states);
411         if (!states) {
412                 return NULL;
413         }
414
415         state = ao2_callback(states, 0, line_identify_relationship, line);
416         if (!state || ast_strlen_zero(state->registration->endpoint)) {
417                 return NULL;
418         }
419
420         ast_debug(3, "Determined relationship to outbound registration '%s' based on line '%s', using configured endpoint '%s'\n",
421                 ast_sorcery_object_get_id(state->registration), state->client_state->line, state->registration->endpoint);
422
423         return ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", state->registration->endpoint);
424 }
425
426 static struct ast_sip_endpoint_identifier line_identifier = {
427         .identify_endpoint = line_identify,
428 };
429
430 /*! \brief Helper function which cancels the timer on a client */
431 static void cancel_registration(struct sip_outbound_registration_client_state *client_state)
432 {
433         if (pj_timer_heap_cancel(pjsip_endpt_get_timer_heap(ast_sip_get_pjsip_endpoint()), &client_state->timer)) {
434                 /* The timer was successfully cancelled, drop the refcount of client_state */
435                 ao2_ref(client_state, -1);
436         }
437 }
438
439 static pj_str_t PATH_NAME = { "path", 4 };
440
441 /*! \brief Callback function for registering */
442 static int handle_client_registration(void *data)
443 {
444         RAII_VAR(struct sip_outbound_registration_client_state *, client_state, data, ao2_cleanup);
445         pjsip_tx_data *tdata;
446         pjsip_regc_info info;
447         char server_uri[PJSIP_MAX_URL_SIZE], client_uri[PJSIP_MAX_URL_SIZE];
448
449         cancel_registration(client_state);
450
451         if ((client_state->status == SIP_REGISTRATION_STOPPED) ||
452                 (pjsip_regc_register(client_state->client, PJ_FALSE, &tdata) != PJ_SUCCESS)) {
453                 return 0;
454         }
455
456         pjsip_regc_get_info(client_state->client, &info);
457         ast_copy_pj_str(server_uri, &info.server_uri, sizeof(server_uri));
458         ast_copy_pj_str(client_uri, &info.client_uri, sizeof(client_uri));
459         ast_debug(3, "REGISTER attempt %u to '%s' with client '%s'\n",
460                   client_state->retries + 1, server_uri, client_uri);
461
462         if (client_state->support_path) {
463                 pjsip_supported_hdr *hdr;
464
465                 hdr = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_SUPPORTED, NULL);
466                 if (!hdr) {
467                         /* insert a new Supported header */
468                         hdr = pjsip_supported_hdr_create(tdata->pool);
469                         if (!hdr) {
470                                 return -1;
471                         }
472
473                         pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *)hdr);
474                 }
475
476                 /* add on to the existing Supported header */
477                 pj_strassign(&hdr->values[hdr->count++], &PATH_NAME);
478         }
479
480         /* Due to the registration the callback may now get called, so bump the ref count */
481         ao2_ref(client_state, +1);
482         if (pjsip_regc_send(client_state->client, tdata) != PJ_SUCCESS) {
483                 ao2_ref(client_state, -1);
484         }
485
486         return 0;
487 }
488
489 /*! \brief Timer callback function, used just for registrations */
490 static void sip_outbound_registration_timer_cb(pj_timer_heap_t *timer_heap, struct pj_timer_entry *entry)
491 {
492         struct sip_outbound_registration_client_state *client_state = entry->user_data;
493
494         ao2_ref(client_state, +1);
495         if (ast_sip_push_task(client_state->serializer, handle_client_registration, client_state)) {
496                 ast_log(LOG_WARNING, "Failed to pass outbound registration to threadpool\n");
497                 ao2_ref(client_state, -1);
498         }
499
500         entry->id = 0;
501 }
502
503 /*! \brief Helper function which sets up the timer to re-register in a specific amount of time */
504 static void schedule_registration(struct sip_outbound_registration_client_state *client_state, unsigned int seconds)
505 {
506         pj_time_val delay = { .sec = seconds, };
507
508         cancel_registration(client_state);
509
510         ao2_ref(client_state, +1);
511         if (pjsip_endpt_schedule_timer(ast_sip_get_pjsip_endpoint(), &client_state->timer, &delay) != PJ_SUCCESS) {
512                 ast_log(LOG_WARNING, "Failed to pass timed registration to scheduler\n");
513                 ao2_ref(client_state, -1);
514         }
515 }
516
517 /*! \brief Callback function for unregistering (potentially) and destroying state */
518 static int handle_client_state_destruction(void *data)
519 {
520         RAII_VAR(struct sip_outbound_registration_client_state *, client_state, data, ao2_cleanup);
521
522         cancel_registration(client_state);
523
524         if (client_state->client) {
525                 pjsip_regc_info info;
526
527                 pjsip_regc_get_info(client_state->client, &info);
528
529                 if (info.is_busy == PJ_TRUE) {
530                         /* If a client transaction is in progress we defer until it is complete */
531                         client_state->destroy = 1;
532                         return 0;
533                 }
534
535                 if (client_state->status != SIP_REGISTRATION_UNREGISTERED && client_state->status != SIP_REGISTRATION_REJECTED_PERMANENT) {
536                         pjsip_tx_data *tdata;
537
538                         if (pjsip_regc_unregister(client_state->client, &tdata) == PJ_SUCCESS) {
539                                 pjsip_regc_send(client_state->client, tdata);
540                         }
541                 }
542
543                 pjsip_regc_destroy(client_state->client);
544         }
545
546         client_state->status = SIP_REGISTRATION_STOPPED;
547         ast_sip_auth_vector_destroy(&client_state->outbound_auths);
548
549         return 0;
550 }
551
552 /*! \brief Structure for registration response */
553 struct registration_response {
554         /*! \brief Response code for the registration attempt */
555         int code;
556         /*! \brief Expiration time for registration */
557         int expiration;
558         /*! \brief Retry-After value */
559         int retry_after;
560         /*! \brief Outbound registration client state */
561         struct sip_outbound_registration_client_state *client_state;
562         /*! \brief The response message */
563         pjsip_rx_data *rdata;
564         /*! \brief The response transaction */
565         pjsip_transaction *tsx;
566 };
567
568 /*! \brief Registration response structure destructor */
569 static void registration_response_destroy(void *obj)
570 {
571         struct registration_response *response = obj;
572
573         if (response->rdata) {
574                 pjsip_rx_data_free_cloned(response->rdata);
575         }
576
577         ao2_cleanup(response->client_state);
578 }
579
580 /* \brief Helper funtion which determines if a response code is temporal or not */
581 static int sip_outbound_registration_is_temporal(unsigned int code,
582                 struct sip_outbound_registration_client_state *client_state)
583 {
584         /* Shamelessly taken from pjsua */
585         if (code == PJSIP_SC_REQUEST_TIMEOUT ||
586                 code == PJSIP_SC_INTERNAL_SERVER_ERROR ||
587                 code == PJSIP_SC_BAD_GATEWAY ||
588                 code == PJSIP_SC_SERVICE_UNAVAILABLE ||
589                 code == PJSIP_SC_SERVER_TIMEOUT ||
590                 ((code == PJSIP_SC_UNAUTHORIZED ||
591                   code == PJSIP_SC_PROXY_AUTHENTICATION_REQUIRED) &&
592                  !client_state->auth_rejection_permanent) ||
593                 PJSIP_IS_STATUS_IN_CLASS(code, 600)) {
594                 return 1;
595         } else {
596                 return 0;
597         }
598 }
599
600 static void schedule_retry(struct registration_response *response, unsigned int interval,
601                            const char *server_uri, const char *client_uri)
602 {
603         response->client_state->status = SIP_REGISTRATION_REJECTED_TEMPORARY;
604         schedule_registration(response->client_state, interval);
605
606         if (response->rdata) {
607                 ast_log(LOG_WARNING, "Temporal response '%d' received from '%s' on "
608                         "registration attempt to '%s', retrying in '%u'\n",
609                         response->code, server_uri, client_uri, interval);
610         } else {
611                 ast_log(LOG_WARNING, "No response received from '%s' on "
612                         "registration attempt to '%s', retrying in '%u'\n",
613                         server_uri, client_uri, interval);
614         }
615 }
616
617 /*! \brief Callback function for handling a response to a registration attempt */
618 static int handle_registration_response(void *data)
619 {
620         RAII_VAR(struct registration_response *, response, data, ao2_cleanup);
621         pjsip_regc_info info;
622         char server_uri[PJSIP_MAX_URL_SIZE], client_uri[PJSIP_MAX_URL_SIZE];
623
624         if (response->client_state->status == SIP_REGISTRATION_STOPPED) {
625                 return 0;
626         }
627
628         pjsip_regc_get_info(response->client_state->client, &info);
629         ast_copy_pj_str(server_uri, &info.server_uri, sizeof(server_uri));
630         ast_copy_pj_str(client_uri, &info.client_uri, sizeof(client_uri));
631
632         if (!response->client_state->auth_attempted &&
633                         (response->code == 401 || response->code == 407)) {
634                 pjsip_tx_data *tdata;
635                 if (!ast_sip_create_request_with_auth(&response->client_state->outbound_auths,
636                                 response->rdata, response->tsx, &tdata)) {
637                         ao2_ref(response->client_state, +1);
638                         response->client_state->auth_attempted = 1;
639                         if (pjsip_regc_send(response->client_state->client, tdata) != PJ_SUCCESS) {
640                                 response->client_state->auth_attempted = 0;
641                                 ao2_cleanup(response->client_state);
642                         }
643                         return 0;
644                 }
645                 /* Otherwise, fall through so the failure is processed appropriately */
646         }
647
648         response->client_state->auth_attempted = 0;
649
650         if (PJSIP_IS_STATUS_IN_CLASS(response->code, 200)) {
651                 /* Check if this is in regards to registering or unregistering */
652                 if (response->expiration) {
653                         /* If the registration went fine simply reschedule registration for the future */
654                         ast_debug(1, "Outbound registration to '%s' with client '%s' successful\n", server_uri, client_uri);
655                         response->client_state->status = SIP_REGISTRATION_REGISTERED;
656                         response->client_state->retries = 0;
657                         schedule_registration(response->client_state, response->expiration - REREGISTER_BUFFER_TIME);
658                 } else {
659                         ast_debug(1, "Outbound unregistration to '%s' with client '%s' successful\n", server_uri, client_uri);
660                         response->client_state->status = SIP_REGISTRATION_UNREGISTERED;
661                 }
662         } else if (response->retry_after) {
663                 /* If we have been instructed to retry after a period of time, schedule it as such */
664                 schedule_retry(response, response->retry_after, server_uri, client_uri);
665         } else if (response->client_state->retry_interval && sip_outbound_registration_is_temporal(response->code, response->client_state)) {
666                 if (response->client_state->retries == response->client_state->max_retries) {
667                         /* If we received enough temporal responses to exceed our maximum give up permanently */
668                         response->client_state->status = SIP_REGISTRATION_REJECTED_PERMANENT;
669                         ast_log(LOG_WARNING, "Maximum retries reached when attempting outbound registration to '%s' with client '%s', stopping registration attempt\n",
670                                 server_uri, client_uri);
671                 } else {
672                         /* On the other hand if we can still try some more do so */
673                         response->client_state->retries++;
674                         schedule_retry(response, response->client_state->retry_interval, server_uri, client_uri);
675                 }
676         } else {
677                 if (response->code == 403
678                         && response->client_state->forbidden_retry_interval
679                         && response->client_state->retries < response->client_state->max_retries) {
680                         /* A forbidden response retry interval is configured and there are retries remaining */
681                         response->client_state->status = SIP_REGISTRATION_REJECTED_TEMPORARY;
682                         response->client_state->retries++;
683                         schedule_registration(response->client_state, response->client_state->forbidden_retry_interval);
684                         ast_log(LOG_WARNING, "403 Forbidden fatal response received from '%s' on registration attempt to '%s', retrying in '%u' seconds\n",
685                                 server_uri, client_uri, response->client_state->forbidden_retry_interval);
686                 } else {
687                         /* Finally if there's no hope of registering give up */
688                         response->client_state->status = SIP_REGISTRATION_REJECTED_PERMANENT;
689                         if (response->rdata) {
690                                 ast_log(LOG_WARNING, "Fatal response '%d' received from '%s' on registration attempt to '%s', stopping outbound registration\n",
691                                         response->code, server_uri, client_uri);
692                         } else {
693                                 ast_log(LOG_WARNING, "Fatal registration attempt to '%s', stopping outbound registration\n", client_uri);
694                         }
695                 }
696         }
697
698         ast_system_publish_registry("PJSIP", client_uri, server_uri, sip_outbound_registration_status_str[response->client_state->status], NULL);
699
700         /* If deferred destruction is in use see if we need to destroy now */
701         if (response->client_state->destroy) {
702                 handle_client_state_destruction(response->client_state);
703         }
704
705         return 0;
706 }
707
708 /*! \brief Callback function for outbound registration client */
709 static void sip_outbound_registration_response_cb(struct pjsip_regc_cbparam *param)
710 {
711         RAII_VAR(struct sip_outbound_registration_client_state *, client_state, param->token, ao2_cleanup);
712         struct registration_response *response = ao2_alloc(sizeof(*response), registration_response_destroy);
713
714         response->code = param->code;
715         response->expiration = param->expiration;
716         response->client_state = client_state;
717         ao2_ref(response->client_state, +1);
718
719         if (param->rdata) {
720                 struct pjsip_retry_after_hdr *retry_after = pjsip_msg_find_hdr(param->rdata->msg_info.msg, PJSIP_H_RETRY_AFTER, NULL);
721
722                 response->retry_after = retry_after ? retry_after->ivalue : 0;
723                 response->tsx = pjsip_rdata_get_tsx(param->rdata);
724                 pjsip_rx_data_clone(param->rdata, 0, &response->rdata);
725         }
726
727         if (ast_sip_push_task(client_state->serializer, handle_registration_response, response)) {
728                 ast_log(LOG_WARNING, "Failed to pass incoming registration response to threadpool\n");
729                 ao2_cleanup(response);
730         }
731 }
732
733 /*! \brief Destructor function for registration state */
734 static void sip_outbound_registration_state_destroy(void *obj)
735 {
736         struct sip_outbound_registration_state *state = obj;
737
738         ao2_cleanup(state->registration);
739
740         if (!state->client_state) {
741                 return;
742         }
743
744         if (state->client_state->serializer && ast_sip_push_task(state->client_state->serializer, handle_client_state_destruction, state->client_state)) {
745                 ast_log(LOG_WARNING, "Failed to pass outbound registration client destruction to threadpool\n");
746                 ao2_ref(state->client_state, -1);
747         }
748 }
749
750 /*! \brief Destructor function for client registration state */
751 static void sip_outbound_registration_client_state_destroy(void *obj)
752 {
753         struct sip_outbound_registration_client_state *client_state = obj;
754
755         ast_taskprocessor_unreference(client_state->serializer);
756 }
757
758 /*! \brief Allocator function for registration state */
759 static struct sip_outbound_registration_state *sip_outbound_registration_state_alloc(struct sip_outbound_registration *registration)
760 {
761         struct sip_outbound_registration_state *state = ao2_alloc(sizeof(*state), sip_outbound_registration_state_destroy);
762
763         if (!state || !(state->client_state = ao2_alloc(sizeof(*state->client_state), sip_outbound_registration_client_state_destroy))) {
764                 ao2_cleanup(state);
765                 return NULL;
766         }
767
768         if (!(state->client_state->serializer = ast_sip_create_serializer())) {
769                 ao2_cleanup(state->client_state);
770                 ao2_cleanup(state);
771                 return NULL;
772         }
773
774         state->client_state->status = SIP_REGISTRATION_UNREGISTERED;
775         state->client_state->timer.user_data = state->client_state;
776         state->client_state->timer.cb = sip_outbound_registration_timer_cb;
777
778         state->registration = ao2_bump(registration);
779         return state;
780 }
781
782 /*! \brief Destructor function for registration information */
783 static void sip_outbound_registration_destroy(void *obj)
784 {
785         struct sip_outbound_registration *registration = obj;
786
787         ast_sip_auth_vector_destroy(&registration->outbound_auths);
788
789         ast_string_field_free_memory(registration);
790 }
791
792 /*! \brief Allocator function for registration information */
793 static void *sip_outbound_registration_alloc(const char *name)
794 {
795         struct sip_outbound_registration *registration = ast_sorcery_generic_alloc(sizeof(*registration), sip_outbound_registration_destroy);
796         if (!registration || ast_string_field_init(registration, 256)) {
797                 ao2_cleanup(registration);
798                 return NULL;
799         }
800
801         return registration;
802 }
803
804 /*! \brief Helper function which populates a pj_str_t with a contact header */
805 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,
806         const char *line)
807 {
808         pj_str_t tmp, local_addr;
809         pjsip_uri *uri;
810         pjsip_sip_uri *sip_uri;
811         pjsip_transport_type_e type = PJSIP_TRANSPORT_UNSPECIFIED;
812         int local_port;
813
814         pj_strdup_with_null(pool, &tmp, target);
815
816         if (!(uri = pjsip_parse_uri(pool, tmp.ptr, tmp.slen, 0)) ||
817             (!PJSIP_URI_SCHEME_IS_SIP(uri) && !PJSIP_URI_SCHEME_IS_SIPS(uri))) {
818                 return -1;
819         }
820
821         sip_uri = pjsip_uri_get_uri(uri);
822
823         if (PJSIP_URI_SCHEME_IS_SIPS(sip_uri)) {
824                 type = PJSIP_TRANSPORT_TLS;
825         } else if (!sip_uri->transport_param.slen) {
826                 type = PJSIP_TRANSPORT_UDP;
827         } else {
828                 type = pjsip_transport_get_type_from_name(&sip_uri->transport_param);
829         }
830
831         if (type == PJSIP_TRANSPORT_UNSPECIFIED) {
832                 return -1;
833         }
834
835         if (pj_strchr(&sip_uri->host, ':')) {
836                 type = (pjsip_transport_type_e)(((int)type) + PJSIP_TRANSPORT_IPV6);
837         }
838
839         if (pjsip_tpmgr_find_local_addr(pjsip_endpt_get_tpmgr(ast_sip_get_pjsip_endpoint()), pool, type, selector,
840                                                               &local_addr, &local_port) != PJ_SUCCESS) {
841                 return -1;
842         }
843
844         if (!pj_strchr(&sip_uri->host, ':') && pj_strchr(&local_addr, ':')) {
845                 type = (pjsip_transport_type_e)(((int)type) + PJSIP_TRANSPORT_IPV6);
846         }
847
848         contact->ptr = pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE);
849         contact->slen = pj_ansi_snprintf(contact->ptr, PJSIP_MAX_URL_SIZE,
850                                       "<%s:%s@%s%.*s%s:%d%s%s%s%s>",
851                                       (pjsip_transport_get_flag_from_type(type) & PJSIP_TRANSPORT_SECURE) ? "sips" : "sip",
852                                       user,
853                                       (type & PJSIP_TRANSPORT_IPV6) ? "[" : "",
854                                       (int)local_addr.slen,
855                                       local_addr.ptr,
856                                       (type & PJSIP_TRANSPORT_IPV6) ? "]" : "",
857                                       local_port,
858                                       (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? ";transport=" : "",
859                                       (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? pjsip_transport_get_type_name(type) : "",
860                                       !ast_strlen_zero(line) ? ";line=" : "",
861                                       S_OR(line, ""));
862
863         return 0;
864 }
865
866 /*!
867  * \internal
868  * \brief Check if a registration can be reused
869  *
870  * This checks if the existing outbound registration's configuration differs from a newly-applied
871  * outbound registration to see if the applied one.
872  *
873  * \param existing The pre-existing outbound registration
874  * \param applied The newly-created registration
875  */
876 static int can_reuse_registration(struct sip_outbound_registration *existing, struct sip_outbound_registration *applied)
877 {
878         int i;
879
880         if (strcmp(existing->server_uri, applied->server_uri) || strcmp(existing->client_uri, applied->client_uri) ||
881                 strcmp(existing->transport, applied->transport) || strcmp(existing->contact_user, applied->contact_user) ||
882                 strcmp(existing->outbound_proxy, applied->outbound_proxy) ||
883                 AST_VECTOR_SIZE(&existing->outbound_auths) != AST_VECTOR_SIZE(&applied->outbound_auths) ||
884                 existing->auth_rejection_permanent != applied->auth_rejection_permanent) {
885                 return 0;
886         }
887
888         for (i = 0; i < AST_VECTOR_SIZE(&existing->outbound_auths); ++i) {
889                 if (strcmp(AST_VECTOR_GET(&existing->outbound_auths, i), AST_VECTOR_GET(&applied->outbound_auths, i))) {
890                         return 0;
891                 }
892         }
893
894         return 1;
895 }
896
897 /*! \brief Helper function that allocates a pjsip registration client and configures it */
898 static int sip_outbound_registration_regc_alloc(void *data)
899 {
900         struct sip_outbound_registration_state *state = data;
901         RAII_VAR(struct sip_outbound_registration *, registration,
902                  ao2_bump(state->registration), ao2_cleanup);
903         pj_pool_t *pool;
904         pj_str_t tmp;
905         pjsip_uri *uri;
906         pj_str_t server_uri, client_uri, contact_uri;
907         pjsip_tpselector selector = { .type = PJSIP_TPSELECTOR_NONE, };
908
909         pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(), "URI Validation", 256, 256);
910         if (!pool) {
911                 ast_log(LOG_ERROR, "Could not create pool for URI validation on outbound registration '%s'\n",
912                         ast_sorcery_object_get_id(registration));
913                 return -1;
914         }
915
916         pj_strdup2_with_null(pool, &tmp, registration->server_uri);
917         uri = pjsip_parse_uri(pool, tmp.ptr, tmp.slen, 0);
918         if (!uri) {
919                 ast_log(LOG_ERROR, "Invalid server URI '%s' specified on outbound registration '%s'\n",
920                         registration->server_uri, ast_sorcery_object_get_id(registration));
921                 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
922                 return -1;
923         }
924
925         pj_strdup2_with_null(pool, &tmp, registration->client_uri);
926         uri = pjsip_parse_uri(pool, tmp.ptr, tmp.slen, 0);
927         if (!uri) {
928                 ast_log(LOG_ERROR, "Invalid client URI '%s' specified on outbound registration '%s'\n",
929                         registration->client_uri, ast_sorcery_object_get_id(registration));
930                 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
931                 return -1;
932         }
933
934         pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
935
936         if (!ast_strlen_zero(registration->transport)) {
937                 RAII_VAR(struct ast_sip_transport *, transport, ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "transport", registration->transport), ao2_cleanup);
938
939                 if (!transport || !transport->state) {
940                         ast_log(LOG_ERROR, "Unable to retrieve PJSIP transport '%s' "
941                                 " for outbound registration", registration->transport);
942                         return -1;
943                 }
944
945                 if (transport->state->transport) {
946                         selector.type = PJSIP_TPSELECTOR_TRANSPORT;
947                         selector.u.transport = transport->state->transport;
948                 } else if (transport->state->factory) {
949                         selector.type = PJSIP_TPSELECTOR_LISTENER;
950                         selector.u.listener = transport->state->factory;
951                 } else {
952                         return -1;
953                 }
954         }
955
956         if (!state->client_state->client &&
957                 pjsip_regc_create(ast_sip_get_pjsip_endpoint(), state->client_state, sip_outbound_registration_response_cb,
958                 &state->client_state->client) != PJ_SUCCESS) {
959                 return -1;
960         }
961
962         pjsip_regc_set_transport(state->client_state->client, &selector);
963
964         if (!ast_strlen_zero(registration->outbound_proxy)) {
965                 pjsip_route_hdr route_set, *route;
966                 static const pj_str_t ROUTE_HNAME = { "Route", 5 };
967                 pj_str_t tmp;
968
969                 pj_list_init(&route_set);
970
971                 pj_strdup2_with_null(pjsip_regc_get_pool(state->client_state->client), &tmp, registration->outbound_proxy);
972                 if (!(route = pjsip_parse_hdr(pjsip_regc_get_pool(state->client_state->client), &ROUTE_HNAME, tmp.ptr, tmp.slen, NULL))) {
973                         return -1;
974                 }
975                 pj_list_insert_nodes_before(&route_set, route);
976
977                 pjsip_regc_set_route_set(state->client_state->client, &route_set);
978         }
979
980         if (state->registration->line) {
981                 ast_generate_random_string(state->client_state->line, sizeof(state->client_state->line));
982         }
983
984         pj_cstr(&server_uri, registration->server_uri);
985
986
987         if (sip_dialog_create_contact(pjsip_regc_get_pool(state->client_state->client), &contact_uri, S_OR(registration->contact_user, "s"), &server_uri, &selector,
988                 state->client_state->line)) {
989                 return -1;
990         }
991
992         pj_cstr(&client_uri, registration->client_uri);
993         if (pjsip_regc_init(state->client_state->client, &server_uri, &client_uri, &client_uri, 1, &contact_uri, registration->expiration) != PJ_SUCCESS) {
994                 return -1;
995         }
996
997         return 0;
998 }
999
1000 /*! \brief Helper function which performs a single registration */
1001 static int sip_outbound_registration_perform(void *data)
1002 {
1003         RAII_VAR(struct sip_outbound_registration_state *, state, data, ao2_cleanup);
1004         RAII_VAR(struct sip_outbound_registration *, registration, ao2_bump(state->registration), ao2_cleanup);
1005         size_t i;
1006
1007         /* Just in case the client state is being reused for this registration, free the auth information */
1008         ast_sip_auth_vector_destroy(&state->client_state->outbound_auths);
1009
1010         AST_VECTOR_INIT(&state->client_state->outbound_auths, AST_VECTOR_SIZE(&registration->outbound_auths));
1011         for (i = 0; i < AST_VECTOR_SIZE(&registration->outbound_auths); ++i) {
1012                 const char *name = ast_strdup(AST_VECTOR_GET(&registration->outbound_auths, i));
1013                 AST_VECTOR_APPEND(&state->client_state->outbound_auths, name);
1014         }
1015         state->client_state->retry_interval = registration->retry_interval;
1016         state->client_state->forbidden_retry_interval = registration->forbidden_retry_interval;
1017         state->client_state->max_retries = registration->max_retries;
1018         state->client_state->retries = 0;
1019         state->client_state->support_path = registration->support_path;
1020         state->client_state->auth_rejection_permanent = registration->auth_rejection_permanent;
1021
1022         pjsip_regc_update_expires(state->client_state->client, registration->expiration);
1023
1024         schedule_registration(state->client_state, (ast_random() % 10) + 1);
1025
1026         return 0;
1027 }
1028
1029 /*! \brief Apply function which finds or allocates a state structure */
1030 static int sip_outbound_registration_apply(const struct ast_sorcery *sorcery, void *obj)
1031 {
1032         RAII_VAR(struct ao2_container *, states, ao2_global_obj_ref(current_states), ao2_cleanup);
1033         RAII_VAR(struct sip_outbound_registration_state *, state,
1034                  ao2_find(states, ast_sorcery_object_get_id(obj), OBJ_SEARCH_KEY), ao2_cleanup);
1035         RAII_VAR(struct sip_outbound_registration_state *, new_state, NULL, ao2_cleanup);
1036         struct sip_outbound_registration *applied = obj;
1037
1038         if (ast_strlen_zero(applied->server_uri)) {
1039                 ast_log(LOG_ERROR, "No server URI specified on outbound registration '%s'",
1040                         ast_sorcery_object_get_id(applied));
1041                 return -1;
1042         } else if (ast_strlen_zero(applied->client_uri)) {
1043                 ast_log(LOG_ERROR, "No client URI specified on outbound registration '%s'\n",
1044                         ast_sorcery_object_get_id(applied));
1045                 return -1;
1046         } else if (applied->line && ast_strlen_zero(applied->endpoint)) {
1047                 ast_log(LOG_ERROR, "Line support has been enabled on outbound registration '%s' without providing an endpoint\n",
1048                         ast_sorcery_object_get_id(applied));
1049                 return -1;
1050         } else if (!ast_strlen_zero(applied->endpoint) && !applied->line) {
1051                 ast_log(LOG_ERROR, "An endpoint has been specified on outbound registration '%s' without enabling line support\n",
1052                         ast_sorcery_object_get_id(applied));
1053                 return -1;
1054         }
1055
1056         if (state && can_reuse_registration(state->registration, applied)) {
1057                 ao2_replace(state->registration, applied);
1058                 return 0;
1059         }
1060
1061         if (!(new_state = sip_outbound_registration_state_alloc(applied))) {
1062                 return -1;
1063         }
1064
1065         if (ast_sip_push_task_synchronous(NULL, sip_outbound_registration_regc_alloc, new_state)) {
1066                 return -1;
1067         }
1068
1069         if (ast_sip_push_task(new_state->client_state->serializer,
1070                               sip_outbound_registration_perform, ao2_bump(new_state))) {
1071                 ast_log(LOG_ERROR, "Failed to perform outbound registration on '%s'\n",
1072                         ast_sorcery_object_get_id(new_state->registration));
1073                 ao2_ref(new_state, -1);
1074                 return -1;
1075         }
1076
1077         ao2_lock(states);
1078
1079         if (state) {
1080                 ao2_unlink(states, state);
1081         }
1082
1083         ao2_link(states, new_state);
1084         ao2_unlock(states);
1085
1086         return 0;
1087 }
1088
1089 static int outbound_auth_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
1090 {
1091         struct sip_outbound_registration *registration = obj;
1092
1093         return ast_sip_auth_vector_init(&registration->outbound_auths, var->value);
1094 }
1095
1096 static int outbound_auths_to_str(const void *obj, const intptr_t *args, char **buf)
1097 {
1098         const struct sip_outbound_registration *registration = obj;
1099
1100         return ast_sip_auths_to_str(&registration->outbound_auths, buf);
1101 }
1102
1103 static int outbound_auths_to_var_list(const void *obj, struct ast_variable **fields)
1104 {
1105         const struct sip_outbound_registration *registration = obj;
1106         int i;
1107         struct ast_variable *head = NULL;
1108
1109         for (i = 0; i < AST_VECTOR_SIZE(&registration->outbound_auths) ; i++) {
1110                 ast_variable_list_append(&head, ast_variable_new("outbound_auth",
1111                         AST_VECTOR_GET(&registration->outbound_auths, i), ""));
1112         }
1113
1114         if (head) {
1115                 *fields = head;
1116         }
1117
1118         return 0;
1119 }
1120
1121 static int unregister_task(void *obj)
1122 {
1123         RAII_VAR(struct sip_outbound_registration_state*, state, obj, ao2_cleanup);
1124         struct pjsip_regc *client = state->client_state->client;
1125         pjsip_tx_data *tdata;
1126
1127         if (pjsip_regc_unregister(client, &tdata) != PJ_SUCCESS) {
1128                 return 0;
1129         }
1130
1131         ao2_ref(state->client_state, +1);
1132         if (pjsip_regc_send(client, tdata) != PJ_SUCCESS) {
1133                 ao2_cleanup(state->client_state);
1134         }
1135
1136         return 0;
1137 }
1138
1139 static int queue_unregister(struct sip_outbound_registration_state *state)
1140 {
1141         ao2_ref(state, +1);
1142         if (ast_sip_push_task(state->client_state->serializer, unregister_task, state)) {
1143                 ao2_ref(state, -1);
1144                 return -1;
1145         }
1146         return 0;
1147 }
1148
1149 static char *cli_complete_registration(const char *line, const char *word,
1150                                        int pos, int state)
1151 {
1152         char *result = NULL;
1153         int wordlen;
1154         int which = 0;
1155         struct sip_outbound_registration *registration;
1156         RAII_VAR(struct ao2_container *, registrations, NULL, ao2_cleanup);
1157         struct ao2_iterator i;
1158
1159         if (pos != 3) {
1160                 return NULL;
1161         }
1162
1163         wordlen = strlen(word);
1164         registrations = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "registration",
1165                 AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
1166         if (!registrations) {
1167                 return NULL;
1168         }
1169
1170         i = ao2_iterator_init(registrations, 0);
1171         while ((registration = ao2_iterator_next(&i))) {
1172                 const char *name = ast_sorcery_object_get_id(registration);
1173                 if (!strncasecmp(word, name, wordlen) && ++which > state) {
1174                         result = ast_strdup(name);
1175                 }
1176
1177                 ao2_cleanup(registration);
1178                 if (result) {
1179                         break;
1180                 }
1181         }
1182         ao2_iterator_destroy(&i);
1183         return result;
1184 }
1185
1186 static char *cli_unregister(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1187 {
1188         RAII_VAR(struct sip_outbound_registration_state *, state, NULL, ao2_cleanup);
1189         const char *registration_name;
1190
1191         switch (cmd) {
1192         case CLI_INIT:
1193                 e->command = "pjsip send unregister";
1194                 e->usage =
1195                         "Usage: pjsip send unregister <registration>\n"
1196                         "       Send a SIP REGISTER request to the specified outbound "
1197                         "registration with an expiration of 0. This will cause the contact "
1198                         "added by this registration to be removed on the remote system. Note: "
1199                         "The specified outbound registration will attempt to re-register "
1200                         "according to its last registration expiration.\n";
1201                 return NULL;
1202         case CLI_GENERATE:
1203                 return cli_complete_registration(a->line, a->word, a->pos, a->n);
1204         }
1205
1206         if (a->argc != 4) {
1207                 return CLI_SHOWUSAGE;
1208         }
1209
1210         registration_name = a->argv[3];
1211
1212         state = get_state(registration_name);
1213         if (!state) {
1214                 ast_cli(a->fd, "Unable to retrieve registration %s\n", registration_name);
1215                 return CLI_FAILURE;
1216         }
1217
1218         if (queue_unregister(state)) {
1219                 ast_cli(a->fd, "Failed to queue unregistration");
1220                 return 0;
1221         }
1222
1223         return CLI_SUCCESS;
1224 }
1225
1226 static int ami_unregister(struct mansession *s, const struct message *m)
1227 {
1228         const char *registration_name = astman_get_header(m, "Registration");
1229         RAII_VAR(struct sip_outbound_registration_state *, state, NULL, ao2_cleanup);
1230
1231         if (ast_strlen_zero(registration_name)) {
1232                 astman_send_error(s, m, "Registration parameter missing.");
1233                 return 0;
1234         }
1235
1236         state = get_state(registration_name);
1237         if (!state) {
1238                 astman_send_error(s, m, "Unable to retrieve registration entry\n");
1239                 return 0;
1240         }
1241
1242         if (queue_unregister(state)) {
1243                 astman_send_ack(s, m, "Failed to queue unregistration");
1244                 return 0;
1245         }
1246
1247         astman_send_ack(s, m, "Unregistration sent");
1248         return 0;
1249 }
1250
1251 struct sip_ami_outbound {
1252         struct ast_sip_ami *ami;
1253         int registered;
1254         int not_registered;
1255         struct sip_outbound_registration *registration;
1256 };
1257
1258 static int ami_outbound_registration_task(void *obj)
1259 {
1260         struct sip_ami_outbound *ami = obj;
1261         RAII_VAR(struct ast_str *, buf,
1262                  ast_sip_create_ami_event("OutboundRegistrationDetail", ami->ami), ast_free);
1263         struct sip_outbound_registration_state *state;
1264
1265         if (!buf) {
1266                 return -1;
1267         }
1268
1269         ast_sip_sorcery_object_to_ami(ami->registration, &buf);
1270
1271         if ((state = get_state(ast_sorcery_object_get_id(ami->registration)))) {
1272                 pjsip_regc_info info;
1273                 if (state->client_state->status == SIP_REGISTRATION_REGISTERED) {
1274                         ++ami->registered;
1275                 } else {
1276                         ++ami->not_registered;
1277                 }
1278
1279                 ast_str_append(&buf, 0, "Status: %s%s",
1280                                sip_outbound_registration_status_str[
1281                                        state->client_state->status], "\r\n");
1282
1283                 pjsip_regc_get_info(state->client_state->client, &info);
1284                 ast_str_append(&buf, 0, "NextReg: %d%s", info.next_reg, "\r\n");
1285                 ao2_ref(state, -1);
1286         }
1287
1288         astman_append(ami->ami->s, "%s\r\n", ast_str_buffer(buf));
1289         return ast_sip_format_auths_ami(&ami->registration->outbound_auths, ami->ami);
1290 }
1291
1292 static int ami_outbound_registration_detail(void *obj, void *arg, int flags)
1293 {
1294         struct sip_ami_outbound *ami = arg;
1295
1296         ami->registration = obj;
1297         return ast_sip_push_task_synchronous(
1298                 NULL, ami_outbound_registration_task, ami);
1299 }
1300
1301 static int ami_show_outbound_registrations(struct mansession *s,
1302                                            const struct message *m)
1303 {
1304         struct ast_sip_ami ami = { .s = s, .m = m, .action_id = astman_get_header(m, "ActionID"), };
1305         struct sip_ami_outbound ami_outbound = { .ami = &ami };
1306         RAII_VAR(struct ao2_container *, regs, get_registrations(), ao2_cleanup);
1307
1308         if (!regs) {
1309                 astman_send_error(s, m, "Unable to retreive "
1310                                   "outbound registrations\n");
1311                 return -1;
1312         }
1313
1314         astman_send_listack(s, m, "Following are Events for each Outbound "
1315                             "registration", "start");
1316
1317         ao2_callback(regs, OBJ_NODATA, ami_outbound_registration_detail, &ami_outbound);
1318
1319         astman_append(s, "Event: OutboundRegistrationDetailComplete\r\n");
1320         if (!ast_strlen_zero(ami.action_id)) {
1321                 astman_append(s, "ActionID: %s\r\n", ami.action_id);
1322         }
1323         astman_append(s, "EventList: Complete\r\n"
1324                       "Registered: %d\r\n"
1325                       "NotRegistered: %d\r\n\r\n",
1326                       ami_outbound.registered,
1327                       ami_outbound.not_registered);
1328         return 0;
1329 }
1330
1331 static struct ao2_container *cli_get_container(void)
1332 {
1333         RAII_VAR(struct ao2_container *, container, get_registrations(), ao2_cleanup);
1334         struct ao2_container *s_container;
1335
1336         if (!container) {
1337                 return NULL;
1338         }
1339
1340         s_container = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, 0,
1341                 ast_sorcery_object_id_sort, ast_sorcery_object_id_compare);
1342         if (!s_container) {
1343                 return NULL;
1344         }
1345
1346         if (ao2_container_dup(s_container, container, 0)) {
1347                 ao2_ref(s_container, -1);
1348                 return NULL;
1349         }
1350
1351         return s_container;
1352 }
1353
1354 static int cli_iterator(void *container, ao2_callback_fn callback, void *args)
1355 {
1356         ao2_callback(container, OBJ_NODATA, callback, args);
1357
1358         return 0;
1359 }
1360
1361 static void *cli_retrieve_by_id(const char *id)
1362 {
1363         struct ao2_container *states;
1364         void *obj = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "registration", id);
1365
1366         if (!obj) {
1367                 /* if the object no longer exists then remove its state  */
1368                 ao2_find((states = ao2_global_obj_ref(current_states)),
1369                          id, OBJ_SEARCH_KEY | OBJ_UNLINK | OBJ_NODATA);
1370                 ao2_ref(states, -1);
1371         }
1372
1373         return obj;
1374 }
1375
1376 static int cli_print_header(void *obj, void *arg, int flags)
1377 {
1378         struct ast_sip_cli_context *context = arg;
1379
1380         ast_assert(context->output_buffer != NULL);
1381
1382         ast_str_append(&context->output_buffer, 0,
1383                 " <Registration/ServerURI..............................>  <Auth..........>  <Status.......>\n");
1384
1385         return 0;
1386 }
1387
1388 static int cli_print_body(void *obj, void *arg, int flags)
1389 {
1390         struct sip_outbound_registration *registration = obj;
1391         struct ast_sip_cli_context *context = arg;
1392         const char *id = ast_sorcery_object_get_id(registration);
1393         struct sip_outbound_registration_state *state = get_state(id);
1394 #define REGISTRATION_URI_FIELD_LEN      53
1395
1396         ast_assert(context->output_buffer != NULL);
1397
1398         ast_str_append(&context->output_buffer, 0, " %-s/%-*.*s  %-16s  %-16s\n",
1399                 id,
1400                 (int) (REGISTRATION_URI_FIELD_LEN - strlen(id)),
1401                 (int) (REGISTRATION_URI_FIELD_LEN - strlen(id)),
1402                 registration->server_uri,
1403                 AST_VECTOR_SIZE(&registration->outbound_auths)
1404                         ? AST_VECTOR_GET(&registration->outbound_auths, 0)
1405                         : "n/a",
1406                 sip_outbound_registration_status_str[state->client_state->status]);
1407         ao2_ref(state, -1);
1408
1409         if (context->show_details
1410                 || (context->show_details_only_level_0 && context->indent_level == 0)) {
1411                 ast_str_append(&context->output_buffer, 0, "\n");
1412                 ast_sip_cli_print_sorcery_objectset(registration, context, 0);
1413         }
1414
1415         return 0;
1416 }
1417
1418 /*
1419  * A function pointer to callback needs to be within the
1420  * module in order to avoid problems with an undefined
1421  * symbol when the module is loaded.
1422  */
1423 static char *my_cli_traverse_objects(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1424 {
1425         return ast_sip_cli_traverse_objects(e, cmd, a);
1426 }
1427
1428 static struct ast_cli_entry cli_outbound_registration[] = {
1429         AST_CLI_DEFINE(cli_unregister, "Send a REGISTER request to an outbound registration target with a expiration of 0"),
1430         AST_CLI_DEFINE(my_cli_traverse_objects, "List PJSIP Registrations",
1431                 .command = "pjsip list registrations",
1432                 .usage = "Usage: pjsip list registrations\n"
1433                                  "       List the configured PJSIP Registrations\n"),
1434         AST_CLI_DEFINE(my_cli_traverse_objects, "Show PJSIP Registrations",
1435                 .command = "pjsip show registrations",
1436                 .usage = "Usage: pjsip show registrations\n"
1437                                  "       Show the configured PJSIP Registrations\n"),
1438         AST_CLI_DEFINE(my_cli_traverse_objects, "Show PJSIP Registration",
1439                 .command = "pjsip show registration",
1440                 .usage = "Usage: pjsip show registration <id>\n"
1441                                  "       Show the configured PJSIP Registration\n"),
1442 };
1443
1444 static struct ast_sip_cli_formatter_entry *cli_formatter;
1445
1446 static int unload_module(void)
1447 {
1448         ast_sip_unregister_endpoint_identifier(&line_identifier);
1449         ast_cli_unregister_multiple(cli_outbound_registration, ARRAY_LEN(cli_outbound_registration));
1450         ast_sip_unregister_cli_formatter(cli_formatter);
1451         ast_manager_unregister("PJSIPShowRegistrationsOutbound");
1452         ast_manager_unregister("PJSIPUnregister");
1453
1454         ao2_global_obj_release(current_states);
1455
1456         return 0;
1457 }
1458
1459 static int load_module(void)
1460 {
1461         struct ao2_container *registrations, *new_states;
1462         CHECK_PJSIP_MODULE_LOADED();
1463
1464         ast_sorcery_apply_config(ast_sip_get_sorcery(), "res_pjsip_outbound_registration");
1465         ast_sorcery_apply_default(ast_sip_get_sorcery(), "registration", "config", "pjsip.conf,criteria=type=registration");
1466
1467         if (ast_sorcery_object_register(ast_sip_get_sorcery(), "registration", sip_outbound_registration_alloc, NULL, sip_outbound_registration_apply)) {
1468                 return AST_MODULE_LOAD_DECLINE;
1469         }
1470
1471         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "type", "", OPT_NOOP_T, 0, 0);
1472         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "server_uri", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, server_uri));
1473         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "client_uri", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, client_uri));
1474         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "contact_user", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, contact_user));
1475         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "transport", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, transport));
1476         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "outbound_proxy", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, outbound_proxy));
1477         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "expiration", "3600", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, expiration));
1478         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "retry_interval", "60", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, retry_interval));
1479         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));
1480         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "max_retries", "10", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, max_retries));
1481         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));
1482         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);
1483         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "support_path", "no", OPT_BOOL_T, 1, FLDSET(struct sip_outbound_registration, support_path));
1484         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "line", "no", OPT_BOOL_T, 1, FLDSET(struct sip_outbound_registration, line));
1485         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "endpoint", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, endpoint));
1486         ast_sip_register_endpoint_identifier(&line_identifier);
1487
1488         ast_manager_register_xml("PJSIPUnregister", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, ami_unregister);
1489         ast_manager_register_xml("PJSIPShowRegistrationsOutbound", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, ami_show_outbound_registrations);
1490
1491         cli_formatter = ao2_alloc(sizeof(struct ast_sip_cli_formatter_entry), NULL);
1492         if (!cli_formatter) {
1493                 ast_log(LOG_ERROR, "Unable to allocate memory for cli formatter\n");
1494                 unload_module();
1495                 return -1;
1496         }
1497         cli_formatter->name = "registration";
1498         cli_formatter->print_header = cli_print_header;
1499         cli_formatter->print_body = cli_print_body;
1500         cli_formatter->get_container = cli_get_container;
1501         cli_formatter->iterate = cli_iterator;
1502         cli_formatter->get_id = ast_sorcery_object_get_id;
1503         cli_formatter->retrieve_by_id = cli_retrieve_by_id;
1504
1505         ast_sip_register_cli_formatter(cli_formatter);
1506         ast_cli_register_multiple(cli_outbound_registration, ARRAY_LEN(cli_outbound_registration));
1507
1508         if (!(new_states = ao2_container_alloc(
1509                       DEFAULT_STATE_BUCKETS, registration_state_hash, registration_state_cmp))) {
1510                 ast_log(LOG_ERROR, "Unable to allocate registration states container\n");
1511                 unload_module();
1512                 return AST_MODULE_LOAD_FAILURE;
1513         }
1514         ao2_global_obj_replace_unref(current_states, new_states);
1515         ao2_ref(new_states, -1);
1516
1517         ast_sorcery_reload_object(ast_sip_get_sorcery(), "registration");
1518         if (!(registrations = get_registrations())) {
1519                 unload_module();
1520                 return AST_MODULE_LOAD_FAILURE;
1521         }
1522         ao2_ref(registrations, -1);
1523
1524         return AST_MODULE_LOAD_SUCCESS;
1525 }
1526
1527 static int reload_module(void)
1528 {
1529         ast_sorcery_reload_object(ast_sip_get_sorcery(), "registration");
1530         ao2_cleanup(get_registrations());
1531         return 0;
1532 }
1533
1534 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP Outbound Registration Support",
1535                 .support_level = AST_MODULE_SUPPORT_CORE,
1536                 .load = load_module,
1537                 .reload = reload_module,
1538                 .unload = unload_module,
1539                 .load_pri = AST_MODPRI_APP_DEPEND,
1540                );