823304edf44e223b1c9991db9aaf100dabcdd3e4
[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 static void schedule_retry(struct registration_response *response, unsigned int interval,
376                            const char *server_uri, const char *client_uri)
377 {
378         response->client_state->status = SIP_REGISTRATION_REJECTED_TEMPORARY;
379         schedule_registration(response->client_state, interval);
380
381         if (response->rdata) {
382                 ast_log(LOG_WARNING, "Temporal response '%d' received from '%s' on "
383                         "registration attempt to '%s', retrying in '%d'\n",
384                         response->code, server_uri, client_uri, interval);
385         } else {
386                 ast_log(LOG_WARNING, "No response received from '%s' on "
387                         "registration attempt to '%s', retrying in '%d'\n",
388                         server_uri, client_uri, interval);
389         }
390 }
391
392 /*! \brief Callback function for handling a response to a registration attempt */
393 static int handle_registration_response(void *data)
394 {
395         RAII_VAR(struct registration_response *, response, data, ao2_cleanup);
396         pjsip_regc_info info;
397         char server_uri[PJSIP_MAX_URL_SIZE], client_uri[PJSIP_MAX_URL_SIZE];
398
399         if (response->client_state->status == SIP_REGISTRATION_STOPPED) {
400                 return 0;
401         }
402
403         pjsip_regc_get_info(response->client_state->client, &info);
404         ast_copy_pj_str(server_uri, &info.server_uri, sizeof(server_uri));
405         ast_copy_pj_str(client_uri, &info.client_uri, sizeof(client_uri));
406
407         if (response->code == 401 || response->code == 407) {
408                 pjsip_tx_data *tdata;
409                 if (!ast_sip_create_request_with_auth(&response->client_state->outbound_auths,
410                                 response->rdata, response->tsx, &tdata)) {
411                         ao2_ref(response->client_state, +1);
412                         if (pjsip_regc_send(response->client_state->client, tdata) != PJ_SUCCESS) {
413                                 ao2_cleanup(response->client_state);
414                         }
415                         return 0;
416                 }
417                 /* Otherwise, fall through so the failure is processed appropriately */
418         }
419
420         if (PJSIP_IS_STATUS_IN_CLASS(response->code, 200)) {
421                 /* If the registration went fine simply reschedule registration for the future */
422                 ast_debug(1, "Outbound registration to '%s' with client '%s' successful\n", server_uri, client_uri);
423                 response->client_state->status = SIP_REGISTRATION_REGISTERED;
424                 response->client_state->retries = 0;
425                 schedule_registration(response->client_state, response->expiration - REREGISTER_BUFFER_TIME);
426         } else if (response->retry_after) {
427                 /* If we have been instructed to retry after a period of time, schedule it as such */
428                 schedule_retry(response, response->retry_after, server_uri, client_uri);
429         } else if (response->client_state->retry_interval && sip_outbound_registration_is_temporal(response->code, response->client_state)) {
430                 if (response->client_state->retries == response->client_state->max_retries) {
431                         /* If we received enough temporal responses to exceed our maximum give up permanently */
432                         response->client_state->status = SIP_REGISTRATION_REJECTED_PERMANENT;
433                         ast_log(LOG_WARNING, "Maximum retries reached when attempting outbound registration to '%s' with client '%s', stopping registration attempt\n",
434                                 server_uri, client_uri);
435                 } else {
436                         /* On the other hand if we can still try some more do so */
437                         response->client_state->retries++;
438                         schedule_retry(response, response->client_state->retry_interval, server_uri, client_uri);
439                 }
440         } else {
441                 if (response->code == 403
442                         && response->client_state->forbidden_retry_interval
443                         && response->client_state->retries < response->client_state->max_retries) {
444                         /* A forbidden response retry interval is configured and there are retries remaining */
445                         response->client_state->status = SIP_REGISTRATION_REJECTED_TEMPORARY;
446                         response->client_state->retries++;
447                         schedule_registration(response->client_state, response->client_state->forbidden_retry_interval);
448                         ast_log(LOG_WARNING, "403 Forbidden fatal response received from '%s' on registration attempt to '%s', retrying in '%d' seconds\n",
449                                 server_uri, client_uri, response->client_state->forbidden_retry_interval);
450                 } else {
451                         /* Finally if there's no hope of registering give up */
452                         response->client_state->status = SIP_REGISTRATION_REJECTED_PERMANENT;
453                         if (response->rdata) {
454                                 ast_log(LOG_WARNING, "Fatal response '%d' received from '%s' on registration attempt to '%s', stopping outbound registration\n",
455                                         response->code, server_uri, client_uri);
456                         } else {
457                                 ast_log(LOG_WARNING, "Fatal registration attempt to '%s', stopping outbound registration\n", client_uri);
458                         }
459                 }
460         }
461
462         ast_system_publish_registry("PJSIP", client_uri, server_uri, sip_outbound_registration_status_str[response->client_state->status], NULL);
463
464         /* If deferred destruction is in use see if we need to destroy now */
465         if (response->client_state->destroy) {
466                 handle_client_state_destruction(response->client_state);
467         }
468
469         return 0;
470 }
471
472 /*! \brief Callback function for outbound registration client */
473 static void sip_outbound_registration_response_cb(struct pjsip_regc_cbparam *param)
474 {
475         RAII_VAR(struct sip_outbound_registration_client_state *, client_state, param->token, ao2_cleanup);
476         struct registration_response *response = ao2_alloc(sizeof(*response), registration_response_destroy);
477
478         response->code = param->code;
479         response->expiration = param->expiration;
480         response->client_state = client_state;
481         ao2_ref(response->client_state, +1);
482
483         if (param->rdata) {
484                 struct pjsip_retry_after_hdr *retry_after = pjsip_msg_find_hdr(param->rdata->msg_info.msg, PJSIP_H_RETRY_AFTER, NULL);
485
486                 response->retry_after = retry_after ? retry_after->ivalue : 0;
487                 response->tsx = pjsip_rdata_get_tsx(param->rdata);
488                 pjsip_rx_data_clone(param->rdata, 0, &response->rdata);
489         }
490
491         if (ast_sip_push_task(client_state->serializer, handle_registration_response, response)) {
492                 ast_log(LOG_WARNING, "Failed to pass incoming registration response to threadpool\n");
493                 ao2_cleanup(response);
494         }
495 }
496
497 /*! \brief Destructor function for registration state */
498 static void sip_outbound_registration_state_destroy(void *obj)
499 {
500         struct sip_outbound_registration_state *state = obj;
501
502         if (!state->client_state) {
503                 return;
504         }
505
506         if (state->client_state->serializer && ast_sip_push_task(state->client_state->serializer, handle_client_state_destruction, state->client_state)) {
507                 ast_log(LOG_WARNING, "Failed to pass outbound registration client destruction to threadpool\n");
508                 ao2_ref(state->client_state, -1);
509         }
510 }
511
512 /*! \brief Destructor function for client registration state */
513 static void sip_outbound_registration_client_state_destroy(void *obj)
514 {
515         struct sip_outbound_registration_client_state *client_state = obj;
516
517         ast_taskprocessor_unreference(client_state->serializer);
518 }
519
520 /*! \brief Allocator function for registration state */
521 static struct sip_outbound_registration_state *sip_outbound_registration_state_alloc(void)
522 {
523         struct sip_outbound_registration_state *state = ao2_alloc(sizeof(*state), sip_outbound_registration_state_destroy);
524
525         if (!state || !(state->client_state = ao2_alloc(sizeof(*state->client_state), sip_outbound_registration_client_state_destroy))) {
526                 ao2_cleanup(state);
527                 return NULL;
528         }
529
530         if ((pjsip_regc_create(ast_sip_get_pjsip_endpoint(), state->client_state, sip_outbound_registration_response_cb, &state->client_state->client) != PJ_SUCCESS) ||
531                 !(state->client_state->serializer = ast_sip_create_serializer())) {
532                 /* This is on purpose, normal operation will have it be deallocated within the serializer */
533                 pjsip_regc_destroy(state->client_state->client);
534                 ao2_cleanup(state->client_state);
535                 ao2_cleanup(state);
536                 return NULL;
537         }
538
539         state->client_state->status = SIP_REGISTRATION_UNREGISTERED;
540         state->client_state->timer.user_data = state->client_state;
541         state->client_state->timer.cb = sip_outbound_registration_timer_cb;
542
543         return state;
544 }
545
546 /*! \brief Destructor function for registration information */
547 static void sip_outbound_registration_destroy(void *obj)
548 {
549         struct sip_outbound_registration *registration = obj;
550
551         ao2_cleanup(registration->state);
552         ast_sip_auth_array_destroy(&registration->outbound_auths);
553
554         ast_string_field_free_memory(registration);
555 }
556
557 /*! \brief Allocator function for registration information */
558 static void *sip_outbound_registration_alloc(const char *name)
559 {
560         struct sip_outbound_registration *registration = ast_sorcery_generic_alloc(sizeof(*registration), sip_outbound_registration_destroy);
561
562         if (!registration || ast_string_field_init(registration, 256)) {
563                 ao2_cleanup(registration);
564                 return NULL;
565         }
566
567         return registration;
568 }
569
570 /*! \brief Helper function which populates a pj_str_t with a contact header */
571 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)
572 {
573         pj_str_t tmp, local_addr;
574         pjsip_uri *uri;
575         pjsip_sip_uri *sip_uri;
576         pjsip_transport_type_e type = PJSIP_TRANSPORT_UNSPECIFIED;
577         int local_port;
578
579         pj_strdup_with_null(pool, &tmp, target);
580
581         if (!(uri = pjsip_parse_uri(pool, tmp.ptr, tmp.slen, 0)) ||
582             (!PJSIP_URI_SCHEME_IS_SIP(uri) && !PJSIP_URI_SCHEME_IS_SIPS(uri))) {
583                 return -1;
584         }
585
586         sip_uri = pjsip_uri_get_uri(uri);
587
588         if (PJSIP_URI_SCHEME_IS_SIPS(sip_uri)) {
589                 type = PJSIP_TRANSPORT_TLS;
590         } else if (!sip_uri->transport_param.slen) {
591                 type = PJSIP_TRANSPORT_UDP;
592         } else {
593                 type = pjsip_transport_get_type_from_name(&sip_uri->transport_param);
594         }
595
596         if (type == PJSIP_TRANSPORT_UNSPECIFIED) {
597                 return -1;
598         }
599
600         if (pj_strchr(&sip_uri->host, ':')) {
601                 type = (pjsip_transport_type_e)(((int)type) + PJSIP_TRANSPORT_IPV6);
602         }
603
604         if (pjsip_tpmgr_find_local_addr(pjsip_endpt_get_tpmgr(ast_sip_get_pjsip_endpoint()), pool, type, selector,
605                                                               &local_addr, &local_port) != PJ_SUCCESS) {
606                 return -1;
607         }
608
609         if (!pj_strchr(&sip_uri->host, ':') && pj_strchr(&local_addr, ':')) {
610                 type = (pjsip_transport_type_e)(((int)type) + PJSIP_TRANSPORT_IPV6);
611         }
612
613         contact->ptr = pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE);
614         contact->slen = pj_ansi_snprintf(contact->ptr, PJSIP_MAX_URL_SIZE,
615                                       "<%s:%s@%s%.*s%s:%d%s%s>",
616                                       (pjsip_transport_get_flag_from_type(type) & PJSIP_TRANSPORT_SECURE) ? "sips" : "sip",
617                                       user,
618                                       (type & PJSIP_TRANSPORT_IPV6) ? "[" : "",
619                                       (int)local_addr.slen,
620                                       local_addr.ptr,
621                                       (type & PJSIP_TRANSPORT_IPV6) ? "]" : "",
622                                       local_port,
623                                       (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? ";transport=" : "",
624                                       (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? pjsip_transport_get_type_name(type) : "");
625
626         return 0;
627 }
628
629 /*!
630  * \internal
631  * \brief Check if a registration can be reused
632  *
633  * This checks if the existing outbound registration's configuration differs from a newly-applied
634  * outbound registration to see if the applied one.
635  *
636  * \param existing The pre-existing outbound registration
637  * \param applied The newly-created registration
638  */
639 static int can_reuse_registration(struct sip_outbound_registration *existing, struct sip_outbound_registration *applied)
640 {
641         int i;
642
643         if (strcmp(existing->server_uri, applied->server_uri) || strcmp(existing->client_uri, applied->client_uri) ||
644                 strcmp(existing->transport, applied->transport) || strcmp(existing->contact_user, applied->contact_user) ||
645                 strcmp(existing->outbound_proxy, applied->outbound_proxy) || existing->num_outbound_auths != applied->num_outbound_auths ||
646                 existing->auth_rejection_permanent != applied->auth_rejection_permanent) {
647                 return 0;
648         }
649
650         for (i = 0; i < existing->num_outbound_auths; ++i) {
651                 if (strcmp(existing->outbound_auths.names[i], applied->outbound_auths.names[i])) {
652                         return 0;
653                 }
654         }
655
656         return 1;
657 }
658
659 /*! \brief Helper function that allocates a pjsip registration client and configures it */
660 static int sip_outbound_registration_regc_alloc(void *data)
661 {
662         struct sip_outbound_registration *registration = data;
663         pj_str_t server_uri, client_uri, contact_uri;
664         pjsip_tpselector selector = { .type = PJSIP_TPSELECTOR_NONE, };
665
666         if (!ast_strlen_zero(registration->transport)) {
667                 RAII_VAR(struct ast_sip_transport *, transport, ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "transport", registration->transport), ao2_cleanup);
668
669                 if (!transport || !transport->state) {
670                         ast_log(LOG_ERROR, "Unable to retrieve PJSIP transport '%s' "
671                                 " for outbound registration", registration->transport);
672                         return -1;
673                 }
674
675                 if (transport->state->transport) {
676                         selector.type = PJSIP_TPSELECTOR_TRANSPORT;
677                         selector.u.transport = transport->state->transport;
678                 } else if (transport->state->factory) {
679                         selector.type = PJSIP_TPSELECTOR_LISTENER;
680                         selector.u.listener = transport->state->factory;
681                 } else {
682                         return -1;
683                 }
684         }
685
686         pjsip_regc_set_transport(registration->state->client_state->client, &selector);
687
688         if (!ast_strlen_zero(registration->outbound_proxy)) {
689                 pjsip_route_hdr route_set, *route;
690                 static const pj_str_t ROUTE_HNAME = { "Route", 5 };
691                 pj_str_t tmp;
692
693                 pj_list_init(&route_set);
694
695                 pj_strdup2_with_null(pjsip_regc_get_pool(registration->state->client_state->client), &tmp, registration->outbound_proxy);
696                 if (!(route = pjsip_parse_hdr(pjsip_regc_get_pool(registration->state->client_state->client), &ROUTE_HNAME, tmp.ptr, tmp.slen, NULL))) {
697                         return -1;
698                 }
699                 pj_list_push_back(&route_set, route);
700
701                 pjsip_regc_set_route_set(registration->state->client_state->client, &route_set);
702         }
703
704         pj_cstr(&server_uri, registration->server_uri);
705
706         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)) {
707                 return -1;
708         }
709
710         pj_cstr(&client_uri, registration->client_uri);
711
712         if (pjsip_regc_init(registration->state->client_state->client, &server_uri, &client_uri, &client_uri, 1, &contact_uri, registration->expiration) != PJ_SUCCESS) {
713                 return -1;
714         }
715
716         return 0;
717 }
718
719 /*! \brief Apply function which finds or allocates a state structure */
720 static int sip_outbound_registration_apply(const struct ast_sorcery *sorcery, void *obj)
721 {
722         RAII_VAR(struct sip_outbound_registration *, existing, ast_sorcery_retrieve_by_id(sorcery, "registration", ast_sorcery_object_get_id(obj)), ao2_cleanup);
723         struct sip_outbound_registration *applied = obj;
724
725         if (!existing) {
726                 /* If no existing registration exists we can just start fresh easily */
727                 applied->state = sip_outbound_registration_state_alloc();
728         } else {
729                 /* If there is an existing registration things are more complicated, we can immediately reuse this state if most stuff remains unchanged */
730                 if (can_reuse_registration(existing, applied)) {
731                         applied->state = existing->state;
732                         ao2_ref(applied->state, +1);
733                         return 0;
734                 }
735                 applied->state = sip_outbound_registration_state_alloc();
736         }
737
738         if (!applied->state) {
739                 return -1;
740         }
741
742         return ast_sip_push_task_synchronous(NULL, sip_outbound_registration_regc_alloc, applied);
743 }
744
745 /*! \brief Helper function which performs a single registration */
746 static int sip_outbound_registration_perform(void *data)
747 {
748         RAII_VAR(struct sip_outbound_registration *, registration, data, ao2_cleanup);
749         size_t i;
750
751         /* Just in case the client state is being reused for this registration, free the auth information */
752         ast_sip_auth_array_destroy(&registration->state->client_state->outbound_auths);
753
754         registration->state->client_state->outbound_auths.names = ast_calloc(registration->outbound_auths.num, sizeof(char *));
755         for (i = 0; i < registration->outbound_auths.num; ++i) {
756                 registration->state->client_state->outbound_auths.names[i] = ast_strdup(registration->outbound_auths.names[i]);
757         }
758         registration->state->client_state->outbound_auths.num = registration->outbound_auths.num;
759         registration->state->client_state->retry_interval = registration->retry_interval;
760         registration->state->client_state->forbidden_retry_interval = registration->forbidden_retry_interval;
761         registration->state->client_state->max_retries = registration->max_retries;
762         registration->state->client_state->retries = 0;
763
764         pjsip_regc_update_expires(registration->state->client_state->client, registration->expiration);
765
766         schedule_registration(registration->state->client_state, (ast_random() % 10) + 1);
767
768         return 0;
769 }
770
771 /*! \brief Helper function which performs all registrations */
772 static void sip_outbound_registration_perform_all(void)
773 {
774         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);
775         struct ao2_iterator i;
776         struct sip_outbound_registration *registration;
777
778         if (!registrations) {
779                 return;
780         }
781
782         i = ao2_iterator_init(registrations, 0);
783         while ((registration = ao2_iterator_next(&i))) {
784                 if (ast_sip_push_task(registration->state->client_state->serializer, sip_outbound_registration_perform, registration)) {
785                         ast_log(LOG_ERROR, "Failed to perform outbound registration on '%s'\n", ast_sorcery_object_get_id(registration));
786                         ao2_ref(registration, -1);
787                 }
788         }
789         ao2_iterator_destroy(&i);
790 }
791
792 static int outbound_auth_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
793 {
794         struct sip_outbound_registration *registration = obj;
795
796         return ast_sip_auth_array_init(&registration->outbound_auths, var->value);
797 }
798
799 static struct sip_outbound_registration *retrieve_registration(const char *registration_name)
800 {
801         return ast_sorcery_retrieve_by_id(
802                 ast_sip_get_sorcery(),
803                 "registration",
804                 registration_name);
805 }
806
807 static int unregister_task(void *obj)
808 {
809         RAII_VAR(struct sip_outbound_registration*, registration, obj, ao2_cleanup);
810         struct pjsip_regc *client = registration->state->client_state->client;
811         pjsip_tx_data *tdata;
812
813         if (pjsip_regc_unregister(client, &tdata) != PJ_SUCCESS) {
814                 return 0;
815         }
816
817         ao2_ref(registration->state->client_state, +1);
818         if (pjsip_regc_send(client, tdata) != PJ_SUCCESS) {
819                 ao2_cleanup(registration->state->client_state);
820         }
821
822         return 0;
823 }
824
825 static int queue_unregister(struct sip_outbound_registration *registration)
826 {
827         ao2_ref(registration, +1);
828         if (ast_sip_push_task(registration->state->client_state->serializer, unregister_task, registration)) {
829                 ao2_cleanup(registration);
830                 return -1;
831         }
832         return 0;
833 }
834
835 static char *cli_complete_registration(const char *line, const char *word,
836 int pos, int state)
837 {
838         char *result = NULL;
839         int wordlen;
840         int which = 0;
841         struct sip_outbound_registration *registration;
842         RAII_VAR(struct ao2_container *, registrations, NULL, ao2_cleanup);
843         struct ao2_iterator i;
844
845         if (pos != 3) {
846                 return NULL;
847         }
848
849         wordlen = strlen(word);
850         registrations = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "registration",
851                 AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
852         if (!registrations) {
853                 return NULL;
854         }
855
856         i = ao2_iterator_init(registrations, 0);
857         while ((registration = ao2_iterator_next(&i))) {
858                 const char *name = ast_sorcery_object_get_id(registration);
859                 if (!strncasecmp(word, name, wordlen) && ++which > state) {
860                         result = ast_strdup(name);
861                 }
862
863                 ao2_cleanup(registration);
864                 if (result) {
865                         break;
866                 }
867         }
868         ao2_iterator_destroy(&i);
869         return result;
870 }
871
872 static char *cli_unregister(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
873 {
874         RAII_VAR(struct sip_outbound_registration *, registration, NULL, ao2_cleanup);
875         const char *registration_name;
876
877         switch (cmd) {
878         case CLI_INIT:
879                 e->command = "pjsip send unregister";
880                 e->usage =
881                         "Usage: pjsip send unregister <registration>\n"
882                         "       Send a SIP REGISTER request to the specified outbound "
883                         "registration with an expiration of 0. This will cause the contact "
884                         "added by this registration to be removed on the remote system.\n";
885                 return NULL;
886         case CLI_GENERATE:
887                 return cli_complete_registration(a->line, a->word, a->pos, a->n);
888         }
889
890         if (a->argc != 4) {
891                 return CLI_SHOWUSAGE;
892         }
893
894         registration_name = a->argv[3];
895
896         registration = retrieve_registration(registration_name);
897         if (!registration) {
898                 ast_cli(a->fd, "Unable to retrieve registration %s\n", registration_name);
899                 return CLI_FAILURE;
900         }
901
902         if (queue_unregister(registration)) {
903                 ast_cli(a->fd, "Failed to queue unregistration");
904                 return 0;
905         }
906
907         return CLI_SUCCESS;
908 }
909
910 static int ami_unregister(struct mansession *s, const struct message *m)
911 {
912         const char *registration_name = astman_get_header(m, "Registration");
913         RAII_VAR(struct sip_outbound_registration *, registration, NULL, ao2_cleanup);
914
915         if (ast_strlen_zero(registration_name)) {
916                 astman_send_error(s, m, "Registration parameter missing.");
917                 return 0;
918         }
919
920         registration = retrieve_registration(registration_name);
921         if (!registration) {
922                 astman_send_error(s, m, "Unable to retrieve registration entry\n");
923                 return 0;
924         }
925
926
927         if (queue_unregister(registration)) {
928                 astman_send_ack(s, m, "Failed to queue unregistration");
929                 return 0;
930         }
931
932         astman_send_ack(s, m, "Unregistration sent");
933         return 0;
934 }
935
936 static struct ast_cli_entry cli_outbound_registration[] = {
937         AST_CLI_DEFINE(cli_unregister, "Send a REGISTER request to an outbound registration target with a expiration of 0")
938 };
939
940 static int load_module(void)
941 {
942         ast_sorcery_apply_default(ast_sip_get_sorcery(), "registration", "config", "pjsip.conf,criteria=type=registration");
943
944         if (ast_sorcery_object_register(ast_sip_get_sorcery(), "registration", sip_outbound_registration_alloc, NULL, sip_outbound_registration_apply)) {
945                 return AST_MODULE_LOAD_DECLINE;
946         }
947
948         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "type", "", OPT_NOOP_T, 0, 0);
949         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "server_uri", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, server_uri));
950         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "client_uri", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, client_uri));
951         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "contact_user", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, contact_user));
952         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "transport", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, transport));
953         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "outbound_proxy", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, outbound_proxy));
954         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "expiration", "3600", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, expiration));
955         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "retry_interval", "60", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, retry_interval));
956         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));
957         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "max_retries", "10", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, max_retries));
958         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));
959         ast_sorcery_object_field_register_custom(ast_sip_get_sorcery(), "registration", "outbound_auth", "", outbound_auth_handler, NULL, 0, 0);
960         ast_sorcery_reload_object(ast_sip_get_sorcery(), "registration");
961         sip_outbound_registration_perform_all();
962
963         ast_cli_register_multiple(cli_outbound_registration, ARRAY_LEN(cli_outbound_registration));
964         ast_manager_register_xml("PJSIPUnregister", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, ami_unregister);
965         return AST_MODULE_LOAD_SUCCESS;
966 }
967
968 static int reload_module(void)
969 {
970         ast_sorcery_reload_object(ast_sip_get_sorcery(), "registration");
971         sip_outbound_registration_perform_all();
972         return 0;
973 }
974
975 static int unload_module(void)
976 {
977         ast_cli_unregister_multiple(cli_outbound_registration, ARRAY_LEN(cli_outbound_registration));
978         ast_manager_unregister("PJSIPUnregister");
979         return 0;
980 }
981
982 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP Outbound Registration Support",
983                 .load = load_module,
984                 .reload = reload_module,
985                 .unload = unload_module,
986                 .load_pri = AST_MODPRI_APP_DEPEND,
987                );