chan_sip: Allow Asterisk to retry after 403 on register
[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/module.h"
32 #include "asterisk/taskprocessor.h"
33 #include "asterisk/cli.h"
34 #include "asterisk/stasis_system.h"
35
36 /*** DOCUMENTATION
37         <configInfo name="res_pjsip_outbound_registration" language="en_US">
38                 <synopsis>SIP resource for outbound registrations</synopsis>
39                 <description><para>
40                         <emphasis>Outbound Registration</emphasis>
41                         </para>
42                         <para>This module allows <literal>res_pjsip</literal> to register to other SIP servers.</para>
43                 </description>
44                 <configFile name="pjsip.conf">
45                         <configObject name="registration">
46                                 <synopsis>The configuration for outbound registration</synopsis>
47                                 <description><para>
48                                         Registration is <emphasis>COMPLETELY</emphasis> separate from the rest of
49                                         <literal>pjsip.conf</literal>. A minimal configuration consists of
50                                         setting a <literal>server_uri</literal> and a <literal>client_uri</literal>.
51                                 </para></description>
52                                 <configOption name="auth_rejection_permanent" default="yes">
53                                         <synopsis>Determines whether failed authentication challenges are treated
54                                         as permanent failures.</synopsis>
55                                         <description><para>If this option is enabled and an authentication challenge fails,
56                                         registration will not be attempted again until the configuration is reloaded.</para></description>
57                                 </configOption>
58                                 <configOption name="client_uri">
59                                         <synopsis>Client SIP URI used when attemping outbound registration</synopsis>
60                                         <description><para>
61                                                 This is the address-of-record for the outbound registration (i.e. the URI in
62                                                 the To header of the REGISTER).</para>
63                                                 <para>For registration with an ITSP, the client SIP URI may need to consist of
64                                                 an account name or number and the provider's hostname for their registrar, e.g.
65                                                 client_uri=1234567890@example.com. This may differ between providers.</para>
66                                                 <para>For registration to generic registrars, the client SIP URI will depend
67                                                 on networking specifics and configuration of the registrar.
68                                         </para></description>
69                                 </configOption>
70                                 <configOption name="contact_user">
71                                         <synopsis>Contact User to use in request</synopsis>
72                                 </configOption>
73                                 <configOption name="expiration" default="3600">
74                                         <synopsis>Expiration time for registrations in seconds</synopsis>
75                                 </configOption>
76                                 <configOption name="max_retries" default="10">
77                                         <synopsis>Maximum number of registration attempts.</synopsis>
78                                 </configOption>
79                                 <configOption name="outbound_auth" default="">
80                                         <synopsis>Authentication object to be used for outbound registrations.</synopsis>
81                                 </configOption>
82                                 <configOption name="outbound_proxy" default="">
83                                         <synopsis>Outbound Proxy used to send registrations</synopsis>
84                                 </configOption>
85                                 <configOption name="retry_interval" default="60">
86                                         <synopsis>Interval in seconds between retries if outbound registration is unsuccessful</synopsis>
87                                 </configOption>
88                                 <configOption name="forbidden_retry_interval" default="0">
89                                         <synopsis>Interval used when receiving a 403 Forbidden response.</synopsis>
90                                         <description><para>
91                                                 If a 403 Forbidden is received, chan_pjsip will wait
92                                                 <replaceable>forbidden_retry_interval</replaceable> seconds before
93                                                 attempting registration again. If 0 is specified, chan_pjsip will not
94                                                 retry after receiving a 403 Forbidden response. Setting this to a non-zero
95                                                 value goes against a "SHOULD NOT" in RFC3261, but can be used to work around
96                                                 buggy registrars.
97                                         </para></description>
98                                 </configOption>
99                                 <configOption name="server_uri">
100                                         <synopsis>SIP URI of the server to register against</synopsis>
101                                         <description><para>
102                                                 This is the URI at which to find the registrar to send the outbound REGISTER. This URI
103                                                 is used as the request URI of the outbound REGISTER request from Asterisk.</para>
104                                                 <para>For registration with an ITSP, the setting may often be just the domain of
105                                                 the registrar, e.g. sip:sip.example.com.
106                                         </para></description>
107                                 </configOption>
108                                 <configOption name="transport">
109                                         <synopsis>Transport used for outbound authentication</synopsis>
110                                         <description>
111                                                 <note><para>A <replaceable>transport</replaceable> configured in
112                                                 <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>
113                                         </description>
114                                 </configOption>
115                                 <configOption name="type">
116                                         <synopsis>Must be of type 'registration'.</synopsis>
117                                 </configOption>
118                         </configObject>
119                 </configFile>
120         </configInfo>
121         <manager name="PJSIPUnregister" language="en_US">
122                 <synopsis>
123                         Unregister an outbound registration.
124                 </synopsis>
125                 <syntax>
126                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
127                         <parameter name="Registration" required="true">
128                                 <para>The outbound registration to unregister.</para>
129                         </parameter>
130                 </syntax>
131         </manager>
132  ***/
133
134 /*! \brief Amount of buffer time (in seconds) before expiration that we re-register at */
135 #define REREGISTER_BUFFER_TIME 10
136
137 /*! \brief Various states that an outbound registration may be in */
138 enum sip_outbound_registration_status {
139         /*! \brief Currently unregistered */
140         SIP_REGISTRATION_UNREGISTERED = 0,
141         /*! \brief Registered, yay! */
142         SIP_REGISTRATION_REGISTERED,
143         /*! \brief Registration was rejected, but response was temporal */
144         SIP_REGISTRATION_REJECTED_TEMPORARY,
145         /*! \brief Registration was rejected, permanently */
146         SIP_REGISTRATION_REJECTED_PERMANENT,
147         /*! \brief Registration has been stopped */
148         SIP_REGISTRATION_STOPPED,
149 };
150
151 static const char *sip_outbound_registration_status_str[] = {
152         [SIP_REGISTRATION_UNREGISTERED] = "Unregistered",
153         [SIP_REGISTRATION_REGISTERED] = "Registered",
154         [SIP_REGISTRATION_REJECTED_TEMPORARY] = "Rejected",
155         [SIP_REGISTRATION_REJECTED_PERMANENT] = "Rejected",
156         [SIP_REGISTRATION_STOPPED] = "Stopped",
157 };
158
159 /*! \brief Outbound registration client state information (persists for lifetime of regc) */
160 struct sip_outbound_registration_client_state {
161         /*! \brief Current status of this registration */
162         enum sip_outbound_registration_status status;
163         /*! \brief Outbound registration client */
164         pjsip_regc *client;
165         /*! \brief Timer entry for retrying on temporal responses */
166         pj_timer_entry timer;
167         /*! \brief Current number of retries */
168         unsigned int retries;
169         /*! \brief Maximum number of retries permitted */
170         unsigned int max_retries;
171         /*! \brief Interval at which retries should occur for temporal responses */
172         unsigned int retry_interval;
173         /*! \brief Interval at which retries should occur for permanent responses */
174         unsigned int forbidden_retry_interval;
175         /*! \brief Treat authentication challenges that we cannot handle as permanent failures */
176         unsigned int auth_rejection_permanent;
177         /*! \brief Serializer for stuff and things */
178         struct ast_taskprocessor *serializer;
179         /*! \brief Configured authentication credentials */
180         struct ast_sip_auth_array outbound_auths;
181         /*! \brief Number of configured auths */
182         size_t num_outbound_auths;
183         /*! \brief Registration should be destroyed after completion of transaction */
184         unsigned int destroy:1;
185 };
186
187 /*! \brief Outbound registration state information (persists for lifetime that registration should exist) */
188 struct sip_outbound_registration_state {
189         /*! \brief Client state information */
190         struct sip_outbound_registration_client_state *client_state;
191 };
192
193 /*! \brief Outbound registration information */
194 struct sip_outbound_registration {
195         /*! \brief Sorcery object details */
196         SORCERY_OBJECT(details);
197         /*! \brief Stringfields */
198         AST_DECLARE_STRING_FIELDS(
199                 /*! \brief URI for the registrar */
200                 AST_STRING_FIELD(server_uri);
201                 /*! \brief URI for the AOR */
202                 AST_STRING_FIELD(client_uri);
203                 /*! \brief Optional user for contact header */
204                 AST_STRING_FIELD(contact_user);
205                 /*! \brief Explicit transport to use for registration */
206                 AST_STRING_FIELD(transport);
207                 /*! \brief Outbound proxy to use */
208                 AST_STRING_FIELD(outbound_proxy);
209         );
210         /*! \brief Requested expiration time */
211         unsigned int expiration;
212         /*! \brief Interval at which retries should occur for temporal responses */
213         unsigned int retry_interval;
214         /*! \brief Interval at which retries should occur for permanent responses */
215         unsigned int forbidden_retry_interval;
216         /*! \brief Treat authentication challenges that we cannot handle as permanent failures */
217         unsigned int auth_rejection_permanent;
218         /*! \brief Maximum number of retries permitted */
219         unsigned int max_retries;
220         /*! \brief Outbound registration state */
221         struct sip_outbound_registration_state *state;
222         /*! \brief Configured authentication credentials */
223         struct ast_sip_auth_array outbound_auths;
224         /*! \brief Number of configured auths */
225         size_t num_outbound_auths;
226 };
227
228 /*! \brief Helper function which cancels the timer on a client */
229 static void cancel_registration(struct sip_outbound_registration_client_state *client_state)
230 {
231         if (pj_timer_heap_cancel(pjsip_endpt_get_timer_heap(ast_sip_get_pjsip_endpoint()), &client_state->timer)) {
232                 /* The timer was successfully cancelled, drop the refcount of client_state */
233                 ao2_ref(client_state, -1);
234         }
235 }
236
237 /*! \brief Callback function for registering */
238 static int handle_client_registration(void *data)
239 {
240         RAII_VAR(struct sip_outbound_registration_client_state *, client_state, data, ao2_cleanup);
241         pjsip_tx_data *tdata;
242         pjsip_regc_info info;
243         char server_uri[PJSIP_MAX_URL_SIZE], client_uri[PJSIP_MAX_URL_SIZE];
244
245         cancel_registration(client_state);
246
247         if ((client_state->status == SIP_REGISTRATION_STOPPED) ||
248                 (pjsip_regc_register(client_state->client, PJ_FALSE, &tdata) != PJ_SUCCESS)) {
249                 return 0;
250         }
251
252         pjsip_regc_get_info(client_state->client, &info);
253         ast_copy_pj_str(server_uri, &info.server_uri, sizeof(server_uri));
254         ast_copy_pj_str(client_uri, &info.client_uri, sizeof(client_uri));
255         ast_debug(3, "REGISTER attempt %d to '%s' with client '%s'\n",
256                   client_state->retries + 1, server_uri, client_uri);
257
258         /* Due to the registration the callback may now get called, so bump the ref count */
259         ao2_ref(client_state, +1);
260         if (pjsip_regc_send(client_state->client, tdata) != PJ_SUCCESS) {
261                 ao2_ref(client_state, -1);
262         }
263
264         return 0;
265 }
266
267 /*! \brief Timer callback function, used just for registrations */
268 static void sip_outbound_registration_timer_cb(pj_timer_heap_t *timer_heap, struct pj_timer_entry *entry)
269 {
270         struct sip_outbound_registration_client_state *client_state = entry->user_data;
271
272         ao2_ref(client_state, +1);
273         if (ast_sip_push_task(client_state->serializer, handle_client_registration, client_state)) {
274                 ast_log(LOG_WARNING, "Failed to pass outbound registration to threadpool\n");
275                 ao2_ref(client_state, -1);
276         }
277
278         entry->id = 0;
279 }
280
281 /*! \brief Helper function which sets up the timer to re-register in a specific amount of time */
282 static void schedule_registration(struct sip_outbound_registration_client_state *client_state, unsigned int seconds)
283 {
284         pj_time_val delay = { .sec = seconds, };
285
286         cancel_registration(client_state);
287
288         ao2_ref(client_state, +1);
289         if (pjsip_endpt_schedule_timer(ast_sip_get_pjsip_endpoint(), &client_state->timer, &delay) != PJ_SUCCESS) {
290                 ast_log(LOG_WARNING, "Failed to pass timed registration to scheduler\n");
291                 ao2_ref(client_state, -1);
292         }
293 }
294
295 /*! \brief Callback function for unregistering (potentially) and destroying state */
296 static int handle_client_state_destruction(void *data)
297 {
298         RAII_VAR(struct sip_outbound_registration_client_state *, client_state, data, ao2_cleanup);
299         pjsip_regc_info info;
300
301         cancel_registration(client_state);
302
303         pjsip_regc_get_info(client_state->client, &info);
304
305         if (info.is_busy == PJ_TRUE) {
306                 /* If a client transaction is in progress we defer until it is complete */
307                 client_state->destroy = 1;
308                 return 0;
309         }
310
311         if (client_state->status != SIP_REGISTRATION_UNREGISTERED && client_state->status != SIP_REGISTRATION_REJECTED_PERMANENT) {
312                 pjsip_tx_data *tdata;
313
314                 if (pjsip_regc_unregister(client_state->client, &tdata) == PJ_SUCCESS) {
315                         pjsip_regc_send(client_state->client, tdata);
316                 }
317         }
318
319         pjsip_regc_destroy(client_state->client);
320
321         client_state->status = SIP_REGISTRATION_STOPPED;
322         ast_sip_auth_array_destroy(&client_state->outbound_auths);
323
324         return 0;
325 }
326
327 /*! \brief Structure for registration response */
328 struct registration_response {
329         /*! \brief Response code for the registration attempt */
330         int code;
331         /*! \brief Expiration time for registration */
332         int expiration;
333         /*! \brief Retry-After value */
334         int retry_after;
335         /*! \brief Outbound registration client state */
336         struct sip_outbound_registration_client_state *client_state;
337         /*! \brief The response message */
338         pjsip_rx_data *rdata;
339         /*! \brief The response transaction */
340         pjsip_transaction *tsx;
341 };
342
343 /*! \brief Registration response structure destructor */
344 static void registration_response_destroy(void *obj)
345 {
346         struct registration_response *response = obj;
347
348         if (response->rdata) {
349                 pjsip_rx_data_free_cloned(response->rdata);
350         }
351
352         ao2_cleanup(response->client_state);
353 }
354
355 /* \brief Helper funtion which determines if a response code is temporal or not */
356 static int sip_outbound_registration_is_temporal(unsigned int code,
357                 struct sip_outbound_registration_client_state *client_state)
358 {
359         /* Shamelessly taken from pjsua */
360         if (code == PJSIP_SC_REQUEST_TIMEOUT ||
361                 code == PJSIP_SC_INTERNAL_SERVER_ERROR ||
362                 code == PJSIP_SC_BAD_GATEWAY ||
363                 code == PJSIP_SC_SERVICE_UNAVAILABLE ||
364                 code == PJSIP_SC_SERVER_TIMEOUT ||
365                 ((code == PJSIP_SC_UNAUTHORIZED ||
366                   code == PJSIP_SC_PROXY_AUTHENTICATION_REQUIRED) &&
367                  !client_state->auth_rejection_permanent) ||
368                 PJSIP_IS_STATUS_IN_CLASS(code, 600)) {
369                 return 1;
370         } else {
371                 return 0;
372         }
373 }
374
375 /*! \brief Callback function for handling a response to a registration attempt */
376 static int handle_registration_response(void *data)
377 {
378         RAII_VAR(struct registration_response *, response, data, ao2_cleanup);
379         pjsip_regc_info info;
380         char server_uri[PJSIP_MAX_URL_SIZE], client_uri[PJSIP_MAX_URL_SIZE];
381
382         if (response->client_state->status == SIP_REGISTRATION_STOPPED) {
383                 return 0;
384         }
385
386         pjsip_regc_get_info(response->client_state->client, &info);
387         ast_copy_pj_str(server_uri, &info.server_uri, sizeof(server_uri));
388         ast_copy_pj_str(client_uri, &info.client_uri, sizeof(client_uri));
389
390         if (response->code == 401 || response->code == 407) {
391                 pjsip_tx_data *tdata;
392                 if (!ast_sip_create_request_with_auth(&response->client_state->outbound_auths,
393                                 response->rdata, response->tsx, &tdata)) {
394                         ao2_ref(response->client_state, +1);
395                         if (pjsip_regc_send(response->client_state->client, tdata) != PJ_SUCCESS) {
396                                 ao2_cleanup(response->client_state);
397                         }
398                         return 0;
399                 }
400                 /* Otherwise, fall through so the failure is processed appropriately */
401         }
402
403         if (PJSIP_IS_STATUS_IN_CLASS(response->code, 200)) {
404                 /* If the registration went fine simply reschedule registration for the future */
405                 ast_debug(1, "Outbound registration to '%s' with client '%s' successful\n", server_uri, client_uri);
406                 response->client_state->status = SIP_REGISTRATION_REGISTERED;
407                 response->client_state->retries = 0;
408                 schedule_registration(response->client_state, response->expiration - REREGISTER_BUFFER_TIME);
409         } else if (response->retry_after) {
410                 /* If we have been instructed to retry after a period of time, schedule it as such */
411                 response->client_state->status = SIP_REGISTRATION_REJECTED_TEMPORARY;
412                 schedule_registration(response->client_state, response->retry_after);
413                 ast_log(LOG_WARNING, "Temporal response '%d' received from '%s' on registration attempt to '%s', instructed to retry in '%d'\n",
414                         response->code, server_uri, client_uri, response->retry_after);
415         } else if (response->client_state->retry_interval && sip_outbound_registration_is_temporal(response->code, response->client_state)) {
416                 if (response->client_state->retries == response->client_state->max_retries) {
417                         /* If we received enough temporal responses to exceed our maximum give up permanently */
418                         response->client_state->status = SIP_REGISTRATION_REJECTED_PERMANENT;
419                         ast_log(LOG_WARNING, "Maximum retries reached when attempting outbound registration to '%s' with client '%s', stopping registration attempt\n",
420                                 server_uri, client_uri);
421                 } else {
422                         /* On the other hand if we can still try some more do so */
423                         response->client_state->status = SIP_REGISTRATION_REJECTED_TEMPORARY;
424                         response->client_state->retries++;
425                         schedule_registration(response->client_state, response->client_state->retry_interval);
426                         ast_log(LOG_WARNING, "Temporal response '%d' received from '%s' on registration attempt to '%s', retrying in '%d' seconds\n",
427                                 response->code, server_uri, client_uri, response->client_state->retry_interval);
428                 }
429         } else {
430                 if (response->code == 403
431                         && response->client_state->forbidden_retry_interval
432                         && response->client_state->retries < response->client_state->max_retries) {
433                         /* A forbidden response retry interval is configured and there are retries remaining */
434                         response->client_state->status = SIP_REGISTRATION_REJECTED_TEMPORARY;
435                         response->client_state->retries++;
436                         schedule_registration(response->client_state, response->client_state->forbidden_retry_interval);
437                         ast_log(LOG_WARNING, "403 Forbidden fatal response received from '%s' on registration attempt to '%s', retrying in '%d' seconds\n",
438                                 server_uri, client_uri, response->client_state->forbidden_retry_interval);
439                 } else {
440                         /* Finally if there's no hope of registering give up */
441                         response->client_state->status = SIP_REGISTRATION_REJECTED_PERMANENT;
442                         ast_log(LOG_WARNING, "Fatal response '%d' received from '%s' on registration attempt to '%s', stopping outbound registration\n",
443                                 response->code, server_uri, client_uri);
444                 }
445         }
446
447         ast_system_publish_registry("PJSIP", client_uri, server_uri, sip_outbound_registration_status_str[response->client_state->status], NULL);
448
449         /* If deferred destruction is in use see if we need to destroy now */
450         if (response->client_state->destroy) {
451                 handle_client_state_destruction(response->client_state);
452         }
453
454         return 0;
455 }
456
457 /*! \brief Callback function for outbound registration client */
458 static void sip_outbound_registration_response_cb(struct pjsip_regc_cbparam *param)
459 {
460         RAII_VAR(struct sip_outbound_registration_client_state *, client_state, param->token, ao2_cleanup);
461         struct registration_response *response = ao2_alloc(sizeof(*response), registration_response_destroy);
462
463         response->code = param->code;
464         response->expiration = param->expiration;
465         response->client_state = client_state;
466         ao2_ref(response->client_state, +1);
467
468         if (param->rdata) {
469                 struct pjsip_retry_after_hdr *retry_after = pjsip_msg_find_hdr(param->rdata->msg_info.msg, PJSIP_H_RETRY_AFTER, NULL);
470
471                 response->retry_after = retry_after ? retry_after->ivalue : 0;
472                 response->tsx = pjsip_rdata_get_tsx(param->rdata);
473                 pjsip_rx_data_clone(param->rdata, 0, &response->rdata);
474         }
475
476         if (ast_sip_push_task(client_state->serializer, handle_registration_response, response)) {
477                 ast_log(LOG_WARNING, "Failed to pass incoming registration response to threadpool\n");
478                 ao2_cleanup(response);
479         }
480 }
481
482 /*! \brief Destructor function for registration state */
483 static void sip_outbound_registration_state_destroy(void *obj)
484 {
485         struct sip_outbound_registration_state *state = obj;
486
487         if (!state->client_state) {
488                 return;
489         }
490
491         if (state->client_state->serializer && ast_sip_push_task(state->client_state->serializer, handle_client_state_destruction, state->client_state)) {
492                 ast_log(LOG_WARNING, "Failed to pass outbound registration client destruction to threadpool\n");
493                 ao2_ref(state->client_state, -1);
494         }
495 }
496
497 /*! \brief Destructor function for client registration state */
498 static void sip_outbound_registration_client_state_destroy(void *obj)
499 {
500         struct sip_outbound_registration_client_state *client_state = obj;
501
502         ast_taskprocessor_unreference(client_state->serializer);
503 }
504
505 /*! \brief Allocator function for registration state */
506 static struct sip_outbound_registration_state *sip_outbound_registration_state_alloc(void)
507 {
508         struct sip_outbound_registration_state *state = ao2_alloc(sizeof(*state), sip_outbound_registration_state_destroy);
509
510         if (!state || !(state->client_state = ao2_alloc(sizeof(*state->client_state), sip_outbound_registration_client_state_destroy))) {
511                 ao2_cleanup(state);
512                 return NULL;
513         }
514
515         if ((pjsip_regc_create(ast_sip_get_pjsip_endpoint(), state->client_state, sip_outbound_registration_response_cb, &state->client_state->client) != PJ_SUCCESS) ||
516                 !(state->client_state->serializer = ast_sip_create_serializer())) {
517                 /* This is on purpose, normal operation will have it be deallocated within the serializer */
518                 pjsip_regc_destroy(state->client_state->client);
519                 ao2_cleanup(state->client_state);
520                 ao2_cleanup(state);
521                 return NULL;
522         }
523
524         state->client_state->status = SIP_REGISTRATION_UNREGISTERED;
525         state->client_state->timer.user_data = state->client_state;
526         state->client_state->timer.cb = sip_outbound_registration_timer_cb;
527
528         return state;
529 }
530
531 /*! \brief Destructor function for registration information */
532 static void sip_outbound_registration_destroy(void *obj)
533 {
534         struct sip_outbound_registration *registration = obj;
535
536         ao2_cleanup(registration->state);
537         ast_sip_auth_array_destroy(&registration->outbound_auths);
538
539         ast_string_field_free_memory(registration);
540 }
541
542 /*! \brief Allocator function for registration information */
543 static void *sip_outbound_registration_alloc(const char *name)
544 {
545         struct sip_outbound_registration *registration = ast_sorcery_generic_alloc(sizeof(*registration), sip_outbound_registration_destroy);
546
547         if (!registration || ast_string_field_init(registration, 256)) {
548                 ao2_cleanup(registration);
549                 return NULL;
550         }
551
552         return registration;
553 }
554
555 /*! \brief Helper function which populates a pj_str_t with a contact header */
556 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)
557 {
558         pj_str_t tmp, local_addr;
559         pjsip_uri *uri;
560         pjsip_sip_uri *sip_uri;
561         pjsip_transport_type_e type = PJSIP_TRANSPORT_UNSPECIFIED;
562         int local_port;
563
564         pj_strdup_with_null(pool, &tmp, target);
565
566         if (!(uri = pjsip_parse_uri(pool, tmp.ptr, tmp.slen, 0)) ||
567             (!PJSIP_URI_SCHEME_IS_SIP(uri) && !PJSIP_URI_SCHEME_IS_SIPS(uri))) {
568                 return -1;
569         }
570
571         sip_uri = pjsip_uri_get_uri(uri);
572
573         if (PJSIP_URI_SCHEME_IS_SIPS(sip_uri)) {
574                 type = PJSIP_TRANSPORT_TLS;
575         } else if (!sip_uri->transport_param.slen) {
576                 type = PJSIP_TRANSPORT_UDP;
577         } else {
578                 type = pjsip_transport_get_type_from_name(&sip_uri->transport_param);
579         }
580
581         if (type == PJSIP_TRANSPORT_UNSPECIFIED) {
582                 return -1;
583         }
584
585         if (pj_strchr(&sip_uri->host, ':')) {
586                 type = (pjsip_transport_type_e)(((int)type) + PJSIP_TRANSPORT_IPV6);
587         }
588
589         if (pjsip_tpmgr_find_local_addr(pjsip_endpt_get_tpmgr(ast_sip_get_pjsip_endpoint()), pool, type, selector,
590                                                               &local_addr, &local_port) != PJ_SUCCESS) {
591                 return -1;
592         }
593
594         if (!pj_strchr(&sip_uri->host, ':') && pj_strchr(&local_addr, ':')) {
595                 type = (pjsip_transport_type_e)(((int)type) + PJSIP_TRANSPORT_IPV6);
596         }
597
598         contact->ptr = pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE);
599         contact->slen = pj_ansi_snprintf(contact->ptr, PJSIP_MAX_URL_SIZE,
600                                       "<%s:%s@%s%.*s%s:%d%s%s>",
601                                       (pjsip_transport_get_flag_from_type(type) & PJSIP_TRANSPORT_SECURE) ? "sips" : "sip",
602                                       user,
603                                       (type & PJSIP_TRANSPORT_IPV6) ? "[" : "",
604                                       (int)local_addr.slen,
605                                       local_addr.ptr,
606                                       (type & PJSIP_TRANSPORT_IPV6) ? "]" : "",
607                                       local_port,
608                                       (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? ";transport=" : "",
609                                       (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? pjsip_transport_get_type_name(type) : "");
610
611         return 0;
612 }
613
614 /*!
615  * \internal
616  * \brief Check if a registration can be reused
617  *
618  * This checks if the existing outbound registration's configuration differs from a newly-applied
619  * outbound registration to see if the applied one.
620  *
621  * \param existing The pre-existing outbound registration
622  * \param applied The newly-created registration
623  */
624 static int can_reuse_registration(struct sip_outbound_registration *existing, struct sip_outbound_registration *applied)
625 {
626         int i;
627
628         if (strcmp(existing->server_uri, applied->server_uri) || strcmp(existing->client_uri, applied->client_uri) ||
629                 strcmp(existing->transport, applied->transport) || strcmp(existing->contact_user, applied->contact_user) ||
630                 strcmp(existing->outbound_proxy, applied->outbound_proxy) || existing->num_outbound_auths != applied->num_outbound_auths ||
631                 existing->auth_rejection_permanent != applied->auth_rejection_permanent) {
632                 return 0;
633         }
634
635         for (i = 0; i < existing->num_outbound_auths; ++i) {
636                 if (strcmp(existing->outbound_auths.names[i], applied->outbound_auths.names[i])) {
637                         return 0;
638                 }
639         }
640
641         return 1;
642 }
643
644 /*! \brief Helper function that allocates a pjsip registration client and configures it */
645 static int sip_outbound_registration_regc_alloc(void *data)
646 {
647         struct sip_outbound_registration *registration = data;
648         pj_str_t server_uri, client_uri, contact_uri;
649         pjsip_tpselector selector = { .type = PJSIP_TPSELECTOR_NONE, };
650
651         if (!ast_strlen_zero(registration->transport)) {
652                 RAII_VAR(struct ast_sip_transport *, transport, ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "transport", registration->transport), ao2_cleanup);
653
654                 if (!transport || !transport->state) {
655                         ast_log(LOG_ERROR, "Unable to retrieve PJSIP transport '%s' "
656                                 " for outbound registration", registration->transport);
657                         return -1;
658                 }
659
660                 if (transport->state->transport) {
661                         selector.type = PJSIP_TPSELECTOR_TRANSPORT;
662                         selector.u.transport = transport->state->transport;
663                 } else if (transport->state->factory) {
664                         selector.type = PJSIP_TPSELECTOR_LISTENER;
665                         selector.u.listener = transport->state->factory;
666                 } else {
667                         return -1;
668                 }
669         }
670
671         pjsip_regc_set_transport(registration->state->client_state->client, &selector);
672
673         if (!ast_strlen_zero(registration->outbound_proxy)) {
674                 pjsip_route_hdr route_set, *route;
675                 static const pj_str_t ROUTE_HNAME = { "Route", 5 };
676                 pj_str_t tmp;
677
678                 pj_list_init(&route_set);
679
680                 pj_strdup2_with_null(pjsip_regc_get_pool(registration->state->client_state->client), &tmp, registration->outbound_proxy);
681                 if (!(route = pjsip_parse_hdr(pjsip_regc_get_pool(registration->state->client_state->client), &ROUTE_HNAME, tmp.ptr, tmp.slen, NULL))) {
682                         return -1;
683                 }
684                 pj_list_push_back(&route_set, route);
685
686                 pjsip_regc_set_route_set(registration->state->client_state->client, &route_set);
687         }
688
689         pj_cstr(&server_uri, registration->server_uri);
690
691         if (sip_dialog_create_contact(pjsip_regc_get_pool(registration->state->client_state->client), &contact_uri, S_OR(registration->contact_user, "s"), &server_uri, &selector)) {
692                 return -1;
693         }
694
695         pj_cstr(&client_uri, registration->client_uri);
696
697         if (pjsip_regc_init(registration->state->client_state->client, &server_uri, &client_uri, &client_uri, 1, &contact_uri, registration->expiration) != PJ_SUCCESS) {
698                 return -1;
699         }
700
701         return 0;
702 }
703
704 /*! \brief Apply function which finds or allocates a state structure */
705 static int sip_outbound_registration_apply(const struct ast_sorcery *sorcery, void *obj)
706 {
707         RAII_VAR(struct sip_outbound_registration *, existing, ast_sorcery_retrieve_by_id(sorcery, "registration", ast_sorcery_object_get_id(obj)), ao2_cleanup);
708         struct sip_outbound_registration *applied = obj;
709
710         if (!existing) {
711                 /* If no existing registration exists we can just start fresh easily */
712                 applied->state = sip_outbound_registration_state_alloc();
713         } else {
714                 /* If there is an existing registration things are more complicated, we can immediately reuse this state if most stuff remains unchanged */
715                 if (can_reuse_registration(existing, applied)) {
716                         applied->state = existing->state;
717                         ao2_ref(applied->state, +1);
718                         return 0;
719                 }
720                 applied->state = sip_outbound_registration_state_alloc();
721         }
722
723         if (!applied->state) {
724                 return -1;
725         }
726
727         return ast_sip_push_task_synchronous(NULL, sip_outbound_registration_regc_alloc, applied);
728 }
729
730 /*! \brief Helper function which performs a single registration */
731 static int sip_outbound_registration_perform(void *data)
732 {
733         RAII_VAR(struct sip_outbound_registration *, registration, data, ao2_cleanup);
734         size_t i;
735
736         /* Just in case the client state is being reused for this registration, free the auth information */
737         ast_sip_auth_array_destroy(&registration->state->client_state->outbound_auths);
738
739         registration->state->client_state->outbound_auths.names = ast_calloc(registration->outbound_auths.num, sizeof(char *));
740         for (i = 0; i < registration->outbound_auths.num; ++i) {
741                 registration->state->client_state->outbound_auths.names[i] = ast_strdup(registration->outbound_auths.names[i]);
742         }
743         registration->state->client_state->outbound_auths.num = registration->outbound_auths.num;
744         registration->state->client_state->retry_interval = registration->retry_interval;
745         registration->state->client_state->forbidden_retry_interval = registration->forbidden_retry_interval;
746         registration->state->client_state->max_retries = registration->max_retries;
747         registration->state->client_state->retries = 0;
748
749         pjsip_regc_update_expires(registration->state->client_state->client, registration->expiration);
750
751         schedule_registration(registration->state->client_state, (ast_random() % 10) + 1);
752
753         return 0;
754 }
755
756 /*! \brief Helper function which performs all registrations */
757 static void sip_outbound_registration_perform_all(void)
758 {
759         RAII_VAR(struct ao2_container *, registrations, ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "registration", AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL), ao2_cleanup);
760         struct ao2_iterator i;
761         struct sip_outbound_registration *registration;
762
763         if (!registrations) {
764                 return;
765         }
766
767         i = ao2_iterator_init(registrations, 0);
768         while ((registration = ao2_iterator_next(&i))) {
769                 if (ast_sip_push_task(registration->state->client_state->serializer, sip_outbound_registration_perform, registration)) {
770                         ast_log(LOG_ERROR, "Failed to perform outbound registration on '%s'\n", ast_sorcery_object_get_id(registration));
771                         ao2_ref(registration, -1);
772                 }
773         }
774         ao2_iterator_destroy(&i);
775 }
776
777 static int outbound_auth_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
778 {
779         struct sip_outbound_registration *registration = obj;
780
781         return ast_sip_auth_array_init(&registration->outbound_auths, var->value);
782 }
783
784 static struct sip_outbound_registration *retrieve_registration(const char *registration_name)
785 {
786         return ast_sorcery_retrieve_by_id(
787                 ast_sip_get_sorcery(),
788                 "registration",
789                 registration_name);
790 }
791
792 static int unregister_task(void *obj)
793 {
794         RAII_VAR(struct sip_outbound_registration*, registration, obj, ao2_cleanup);
795         struct pjsip_regc *client = registration->state->client_state->client;
796         pjsip_tx_data *tdata;
797
798         if (pjsip_regc_unregister(client, &tdata) != PJ_SUCCESS) {
799                 return 0;
800         }
801
802         ao2_ref(registration->state->client_state, +1);
803         if (pjsip_regc_send(client, tdata) != PJ_SUCCESS) {
804                 ao2_cleanup(registration->state->client_state);
805         }
806
807         return 0;
808 }
809
810 static int queue_unregister(struct sip_outbound_registration *registration)
811 {
812         ao2_ref(registration, +1);
813         if (ast_sip_push_task(registration->state->client_state->serializer, unregister_task, registration)) {
814                 ao2_cleanup(registration);
815                 return -1;
816         }
817         return 0;
818 }
819
820 static char *cli_complete_registration(const char *line, const char *word,
821 int pos, int state)
822 {
823         char *result = NULL;
824         int wordlen;
825         int which = 0;
826         struct sip_outbound_registration *registration;
827         RAII_VAR(struct ao2_container *, registrations, NULL, ao2_cleanup);
828         struct ao2_iterator i;
829
830         if (pos != 3) {
831                 return NULL;
832         }
833
834         wordlen = strlen(word);
835         registrations = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "registration",
836                 AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
837         if (!registrations) {
838                 return NULL;
839         }
840
841         i = ao2_iterator_init(registrations, 0);
842         while ((registration = ao2_iterator_next(&i))) {
843                 const char *name = ast_sorcery_object_get_id(registration);
844                 if (!strncasecmp(word, name, wordlen) && ++which > state) {
845                         result = ast_strdup(name);
846                 }
847
848                 ao2_cleanup(registration);
849                 if (result) {
850                         break;
851                 }
852         }
853         ao2_iterator_destroy(&i);
854         return result;
855 }
856
857 static char *cli_unregister(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
858 {
859         RAII_VAR(struct sip_outbound_registration *, registration, NULL, ao2_cleanup);
860         const char *registration_name;
861
862         switch (cmd) {
863         case CLI_INIT:
864                 e->command = "pjsip send unregister";
865                 e->usage =
866                         "Usage: pjsip send unregister <registration>\n"
867                         "       Send a SIP REGISTER request to the specified outbound "
868                         "registration with an expiration of 0. This will cause the contact "
869                         "added by this registration to be removed on the remote system.\n";
870                 return NULL;
871         case CLI_GENERATE:
872                 return cli_complete_registration(a->line, a->word, a->pos, a->n);
873         }
874
875         if (a->argc != 4) {
876                 return CLI_SHOWUSAGE;
877         }
878
879         registration_name = a->argv[3];
880
881         registration = retrieve_registration(registration_name);
882         if (!registration) {
883                 ast_cli(a->fd, "Unable to retrieve registration %s\n", registration_name);
884                 return CLI_FAILURE;
885         }
886
887         if (queue_unregister(registration)) {
888                 ast_cli(a->fd, "Failed to queue unregistration");
889                 return 0;
890         }
891
892         return CLI_SUCCESS;
893 }
894
895 static int ami_unregister(struct mansession *s, const struct message *m)
896 {
897         const char *registration_name = astman_get_header(m, "Registration");
898         RAII_VAR(struct sip_outbound_registration *, registration, NULL, ao2_cleanup);
899
900         if (ast_strlen_zero(registration_name)) {
901                 astman_send_error(s, m, "Registration parameter missing.");
902                 return 0;
903         }
904
905         registration = retrieve_registration(registration_name);
906         if (!registration) {
907                 astman_send_error(s, m, "Unable to retrieve registration entry\n");
908                 return 0;
909         }
910
911
912         if (queue_unregister(registration)) {
913                 astman_send_ack(s, m, "Failed to queue unregistration");
914                 return 0;
915         }
916
917         astman_send_ack(s, m, "Unregistration sent");
918         return 0;
919 }
920
921 static struct ast_cli_entry cli_outbound_registration[] = {
922         AST_CLI_DEFINE(cli_unregister, "Send a REGISTER request to an outbound registration target with a expiration of 0")
923 };
924
925 static int load_module(void)
926 {
927         ast_sorcery_apply_default(ast_sip_get_sorcery(), "registration", "config", "pjsip.conf,criteria=type=registration");
928
929         if (ast_sorcery_object_register(ast_sip_get_sorcery(), "registration", sip_outbound_registration_alloc, NULL, sip_outbound_registration_apply)) {
930                 return AST_MODULE_LOAD_DECLINE;
931         }
932
933         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "type", "", OPT_NOOP_T, 0, 0);
934         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "server_uri", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, server_uri));
935         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "client_uri", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, client_uri));
936         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "contact_user", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, contact_user));
937         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "transport", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, transport));
938         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "outbound_proxy", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, outbound_proxy));
939         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "expiration", "3600", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, expiration));
940         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "retry_interval", "60", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, retry_interval));
941         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));
942         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "max_retries", "10", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, max_retries));
943         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));
944         ast_sorcery_object_field_register_custom(ast_sip_get_sorcery(), "registration", "outbound_auth", "", outbound_auth_handler, NULL, 0, 0);
945         ast_sorcery_reload_object(ast_sip_get_sorcery(), "registration");
946         sip_outbound_registration_perform_all();
947
948         ast_cli_register_multiple(cli_outbound_registration, ARRAY_LEN(cli_outbound_registration));
949         ast_manager_register_xml("PJSIPUnregister", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, ami_unregister);
950         return AST_MODULE_LOAD_SUCCESS;
951 }
952
953 static int reload_module(void)
954 {
955         ast_sorcery_reload_object(ast_sip_get_sorcery(), "registration");
956         sip_outbound_registration_perform_all();
957         return 0;
958 }
959
960 static int unload_module(void)
961 {
962         ast_cli_unregister_multiple(cli_outbound_registration, ARRAY_LEN(cli_outbound_registration));
963         ast_manager_unregister("PJSIPUnregister");
964         return 0;
965 }
966
967 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP Outbound Registration Support",
968                 .load = load_module,
969                 .reload = reload_module,
970                 .unload = unload_module,
971                 .load_pri = AST_MODPRI_APP_DEPEND,
972                );