Asterisk - The Open Source Telephony Project  18.5.0
res_pjsip_registrar.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2013, Digium, Inc.
5  *
6  * Joshua Colp <[email protected]>
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_pjproject</depend>
22  <depend>res_pjsip</depend>
23  <support_level>core</support_level>
24  ***/
25 
26 #include "asterisk.h"
27 
28 #include <signal.h>
29 #include <pjsip.h>
30 #include <pjsip_ua.h>
31 
32 #include "asterisk/res_pjsip.h"
33 #include "asterisk/module.h"
34 #include "asterisk/paths.h"
35 #include "asterisk/test.h"
36 #include "asterisk/taskprocessor.h"
37 #include "asterisk/manager.h"
38 #include "asterisk/named_locks.h"
39 #include "asterisk/res_pjproject.h"
41 
42 /*** DOCUMENTATION
43  <manager name="PJSIPShowRegistrationsInbound" language="en_US">
44  <synopsis>
45  Lists PJSIP inbound registrations.
46  </synopsis>
47  <syntax />
48  <description>
49  <para>
50  In response, <literal>InboundRegistrationDetail</literal> events showing configuration
51  and status information are raised for all contacts, static or dynamic. Once all events
52  are completed an <literal>InboundRegistrationDetailComplete</literal> is issued.
53  </para>
54  <warning><para>
55  This command just dumps all coonfigured AORs with contacts, even if the contact
56  is a permanent one. To really get just inbound registrations, use
57  <literal>PJSIPShowRegistrationInboundContactStatuses</literal>.
58  </para>
59  </warning>
60  </description>
61  <see-also>
62  <ref type="manager" module="res_pjsip_registrar">PJSIPShowRegistrationInboundContactStatuses</ref>
63  </see-also>
64  </manager>
65  <manager name="PJSIPShowRegistrationInboundContactStatuses" language="en_US">
66  <synopsis>
67  Lists ContactStatuses for PJSIP inbound registrations.
68  </synopsis>
69  <syntax />
70  <description>
71  <para>
72  In response, <literal>ContactStatusDetail</literal> events showing status information
73  are raised for each inbound registration (dynamic contact) object. Once all events
74  are completed a <literal>ContactStatusDetailComplete</literal> event is issued.
75  </para>
76  </description>
77  </manager>
78  ***/
79 
80 static int pj_max_hostname = PJ_MAX_HOSTNAME;
81 static int pjsip_max_url_size = PJSIP_MAX_URL_SIZE;
82 
83 /*! \brief Internal function which returns the expiration time for a contact */
84 static unsigned int registrar_get_expiration(const struct ast_sip_aor *aor, const pjsip_contact_hdr *contact, const pjsip_rx_data *rdata)
85 {
86  pjsip_expires_hdr *expires;
87  unsigned int expiration = aor->default_expiration;
88 
89  if (contact && contact->expires != PJSIP_EXPIRES_NOT_SPECIFIED) {
90  /* Expiration was provided with the contact itself */
91  expiration = contact->expires;
92  } else if ((expires = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_EXPIRES, NULL))) {
93  /* Expiration was provided using the Expires header */
94  expiration = expires->ivalue;
95  }
96 
97  /* If the value has explicitly been set to 0, do not enforce */
98  if (!expiration) {
99  return expiration;
100  }
101 
102  /* Enforce the range that we will allow for expiration */
103  if (expiration < aor->minimum_expiration) {
104  expiration = aor->minimum_expiration;
105  } else if (expiration > aor->maximum_expiration) {
106  expiration = aor->maximum_expiration;
107  }
108 
109  return expiration;
110 }
111 
112 /*! \brief Structure used for finding contact */
114  /*! \brief Pool used for parsing URI */
115  pj_pool_t *pool;
116  /*! \brief URI being looked for */
117  pjsip_sip_uri *uri;
118 };
119 
120 /*! \brief Callback function for finding a contact */
121 static int registrar_find_contact(void *obj, void *arg, int flags)
122 {
123  struct ast_sip_contact *contact = obj;
124  const struct registrar_contact_details *details = arg;
125  pjsip_uri *contact_uri;
126 
127  if (ast_tvzero(contact->expiration_time)) {
128  return 0;
129  }
130 
131  contact_uri = pjsip_parse_uri(details->pool, (char*)contact->uri, strlen(contact->uri), 0);
132  if (!contact_uri) {
133  ast_log(LOG_WARNING, "Unable to parse contact URI from '%s'.\n", contact->uri);
134  return 0;
135  }
136 
137  return (pjsip_uri_cmp(PJSIP_URI_IN_CONTACT_HDR, details->uri, contact_uri) == PJ_SUCCESS) ? CMP_MATCH : 0;
138 }
139 
140 /*! \brief Internal function which validates provided Contact headers to confirm that they are acceptable, and returns number of contacts */
141 static int registrar_validate_contacts(const pjsip_rx_data *rdata, pj_pool_t *pool, struct ao2_container *contacts,
142  struct ast_sip_aor *aor, int permanent, int *added, int *updated, int *deleted)
143 {
144  pjsip_contact_hdr *previous = NULL;
145  pjsip_contact_hdr *contact = (pjsip_contact_hdr *)&rdata->msg_info.msg->hdr;
146  struct registrar_contact_details details = {
147  .pool = pool,
148  };
149 
150  for (; (contact = (pjsip_contact_hdr *) pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT, contact->next)); pj_pool_reset(pool)) {
151  unsigned int expiration = registrar_get_expiration(aor, contact, rdata);
152  struct ast_sip_contact *existing;
153  char contact_uri[pjsip_max_url_size];
154 
155  if (contact->star) {
156  /* The expiration MUST be 0 when a '*' contact is used and there must be no other contact */
157  if (expiration != 0 || previous) {
158  return -1;
159  }
160  /* Count all contacts to delete */
161  *deleted = ao2_container_count(contacts) - permanent;
162  previous = contact;
163  continue;
164  } else if (previous && previous->star) {
165  /* If there is a previous contact and it is a '*' this is a deal breaker */
166  return -1;
167  }
168  previous = contact;
169 
170  if (!PJSIP_URI_SCHEME_IS_SIP(contact->uri) && !PJSIP_URI_SCHEME_IS_SIPS(contact->uri)) {
171  continue;
172  }
173 
174  details.uri = pjsip_uri_get_uri(contact->uri);
175 
176  /* pjsip_uri_print returns -1 if there's not enough room in the buffer */
177  if (pjsip_uri_print(PJSIP_URI_IN_CONTACT_HDR, details.uri, contact_uri, sizeof(contact_uri)) < 0) {
178  /* If the total length of the uri is greater than pjproject can handle, go no further */
179  return -1;
180  }
181 
182  if (details.uri->host.slen >= pj_max_hostname) {
183  /* If the length of the hostname is greater than pjproject can handle, go no further */
184  return -1;
185  }
186 
187  /* Determine if this is an add, update, or delete for policy enforcement purposes */
188  existing = ao2_callback(contacts, 0, registrar_find_contact, &details);
189  ao2_cleanup(existing);
190  if (!existing) {
191  if (expiration) {
192  ++*added;
193  }
194  } else if (expiration) {
195  ++*updated;
196  } else {
197  ++*deleted;
198  }
199  }
200 
201  return 0;
202 }
203 
210 };
211 
212 static int registrar_contact_delete(enum contact_delete_type type, pjsip_transport *transport,
213  struct ast_sip_contact *contact, const char *aor_name);
214 
215 /*! \brief Internal function used to delete a contact from an AOR */
216 static int registrar_delete_contact(void *obj, void *arg, int flags)
217 {
219  CONTACT_DELETE_REQUEST, NULL, obj, arg) ? 0 : CMP_MATCH;
220 }
221 
222 /*! \brief Internal function which adds a contact to a response */
223 static int registrar_add_contact(void *obj, void *arg, int flags)
224 {
225  struct ast_sip_contact *contact = obj;
226  pjsip_tx_data *tdata = arg;
227  pj_str_t uri;
228  pjsip_uri *parsed;
229 
230  pj_strdup2_with_null(tdata->pool, &uri, contact->uri);
231  parsed = pjsip_parse_uri(tdata->pool, uri.ptr, uri.slen, PJSIP_PARSE_URI_AS_NAMEADDR);
232 
233  if (parsed && (PJSIP_URI_SCHEME_IS_SIP(parsed) || PJSIP_URI_SCHEME_IS_SIPS(parsed))) {
234  pjsip_contact_hdr *hdr = pjsip_contact_hdr_create(tdata->pool);
235  hdr->uri = parsed;
236  if (!ast_tvzero(contact->expiration_time)) {
237  hdr->expires = ast_tvdiff_ms(contact->expiration_time, ast_tvnow()) / 1000;
238  } else {
239  hdr->expires = PJSIP_EXPIRES_NOT_SPECIFIED;
240  }
241  pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *) hdr);
242  } else {
243  ast_log(LOG_WARNING, "Skipping invalid Contact URI \"%.*s\" for AOR %s\n",
244  (int) uri.slen, uri.ptr, contact->aor);
245  }
246 
247  return 0;
248 }
249 
250 static const pj_str_t path_hdr_name = { "Path", 4 };
251 
252 static int build_path_data(pjsip_rx_data *rdata, struct ast_str **path_str)
253 {
254  pjsip_generic_string_hdr *path_hdr = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &path_hdr_name, NULL);
255 
256  if (!path_hdr) {
257  return 0;
258  }
259 
260  *path_str = ast_str_create(64);
261  if (!*path_str) {
262  return -1;
263  }
264 
265  ast_str_set(path_str, 0, "%.*s", (int)path_hdr->hvalue.slen, path_hdr->hvalue.ptr);
266 
267  while ((path_hdr = (pjsip_generic_string_hdr *) pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &path_hdr_name, path_hdr->next))) {
268  ast_str_append(path_str, 0, ",%.*s", (int)path_hdr->hvalue.slen, path_hdr->hvalue.ptr);
269  }
270 
271  return 0;
272 }
273 
274 static int registrar_validate_path(pjsip_rx_data *rdata, struct ast_sip_aor *aor, struct ast_str **path_str)
275 {
276  const pj_str_t path_supported_name = { "path", 4 };
277  pjsip_supported_hdr *supported_hdr;
278  int i;
279 
280  if (!aor->support_path) {
281  return 0;
282  }
283 
284  if (build_path_data(rdata, path_str)) {
285  return -1;
286  }
287 
288  if (!*path_str) {
289  return 0;
290  }
291 
292  supported_hdr = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_SUPPORTED, NULL);
293  if (!supported_hdr) {
294  return -1;
295  }
296 
297  /* Find advertised path support */
298  for (i = 0; i < supported_hdr->count; i++) {
299  if (!pj_stricmp(&supported_hdr->values[i], &path_supported_name)) {
300  return 0;
301  }
302  }
303 
304  /* Path header present, but support not advertised */
305  return -1;
306 }
307 
308 /*! Transport monitor for incoming REGISTER contacts */
310  /*!
311  * \brief Sorcery contact name to remove on transport shutdown
312  * \note Stored after aor_name in space reserved when struct allocated.
313  */
315  /*! Indicates that the monitor is in the process of removing a contact */
316  int removing;
317  /*! AOR name the contact is associated */
318  char aor_name[0];
319 };
320 
321 static int contact_transport_monitor_matcher(void *a, void *b)
322 {
323  struct contact_transport_monitor *ma = a;
324  struct contact_transport_monitor *mb = b;
325 
326  return strcmp(ma->aor_name, mb->aor_name) == 0
327  && strcmp(ma->contact_name, mb->contact_name) == 0;
328 }
329 
331 {
332  struct contact_transport_monitor *monitor = data;
333  struct ast_sip_contact *contact;
334  struct ast_sip_aor *aor;
335 
336  aor = ast_sip_location_retrieve_aor(monitor->aor_name);
337  if (!aor) {
338  ao2_lock(monitor);
339  monitor->removing = 0;
340  ao2_unlock(monitor);
341  ao2_ref(monitor, -1);
342  return 0;
343  }
344 
345  ao2_lock(aor);
346 
348  if (contact) {
350  ao2_ref(contact, -1);
351  }
352  ao2_unlock(aor);
353  ao2_ref(aor, -1);
354 
355  ao2_ref(monitor, -1);
356  return 0;
357 }
358 
359 /*!
360  * \internal
361  * \brief The reliable transport we registered as a contact has shutdown.
362  *
363  * \param data What contact needs to be removed.
364  *
365  * \note Normally executed by the pjsip monitor thread.
366  *
367  * \return Nothing
368  */
370 {
371  struct contact_transport_monitor *monitor = data;
372 
373  /*
374  * It's possible for this shutdown handler to get called multiple times for the
375  * same monitor from different threads. Only one of the calls needs to do the
376  * actual removing of the contact, so if one is currently removing then any
377  * subsequent calls can skip.
378  */
379  ao2_lock(monitor);
380  if (monitor->removing) {
381  ao2_unlock(monitor);
382  return;
383  }
384 
385  monitor->removing = 1;
386 
387  /*
388  * Push off to a default serializer. This is in case sorcery
389  * does database accesses for contacts. Database accesses may
390  * not be on this machine. We don't want to tie up the pjsip
391  * monitor thread with potentially long access times.
392  */
393  ao2_ref(monitor, +1);
395  monitor->removing = 0;
396  ao2_ref(monitor, -1);
397  }
398 
399  ao2_unlock(monitor);
400 }
401 
402 
403 static int registrar_contact_delete(enum contact_delete_type type, pjsip_transport *transport,
404  struct ast_sip_contact *contact, const char *aor_name)
405 {
406  int aor_size;
407 
408  /* Permanent contacts can't be deleted */
409  if (ast_tvzero(contact->expiration_time)) {
410  return -1;
411  }
412 
413  aor_size = aor_name ? strlen(aor_name) : 0;
414  if (contact->prune_on_boot && type != CONTACT_DELETE_SHUTDOWN && aor_size) {
415  const char *contact_name = ast_sorcery_object_get_id(contact);
416  size_t contact_name_len = strlen(contact_name) + 1;
418  sizeof(*monitor) + 1 + aor_size + contact_name_len);
419 
420  strcpy(monitor->aor_name, aor_name); /* Safe */
421  monitor->contact_name = monitor->aor_name + aor_size + 1;
422  ast_copy_string(monitor->contact_name, contact_name, contact_name_len); /* Safe */
423 
424  if (transport) {
428  } else {
429  /*
430  * If a specific transport is not supplied then unregister the matching
431  * monitor from all reliable transports.
432  */
435  }
436  }
437 
439 
440  if (aor_size) {
441  if (VERBOSITY_ATLEAST(3)) {
442  const char *reason = "none";
443 
444  switch (type) {
446  reason = "registration failure";
447  break;
449  reason = "remove existing";
450  break;
452  reason = "expiration";
453  break;
455  reason = "request";
456  break;
458  reason = "shutdown";
459  break;
460  }
461 
462  ast_verb(3, "Removed contact '%s' from AOR '%s' due to %s\n",
463  contact->uri, aor_name, reason);
464  }
465 
466  ast_test_suite_event_notify("AOR_CONTACT_REMOVED",
467  "Contact: %s\r\n"
468  "AOR: %s\r\n"
469  "UserAgent: %s",
470  contact->uri,
471  aor_name,
472  contact->user_agent);
473  }
474 
475  return 0;
476 }
477 
478 AST_VECTOR(excess_contact_vector, struct ast_sip_contact *);
479 
480 static int vec_contact_cmp(struct ast_sip_contact *left, struct ast_sip_contact *right)
481 {
482  struct ast_sip_contact *left_contact = left;
483  struct ast_sip_contact *right_contact = right;
484 
485  /* Sort from soonest to expire to last to expire */
486  return ast_tvcmp(left_contact->expiration_time, right_contact->expiration_time);
487 }
488 
489 static int vec_contact_add(void *obj, void *arg, int flags)
490 {
491  struct ast_sip_contact *contact = obj;
492  struct excess_contact_vector *contact_vec = arg;
493 
494  /*
495  * Performance wise, an insertion sort is fine because we
496  * shouldn't need to remove more than a handful of contacts.
497  * I expect we'll typically be removing only one contact.
498  */
499  AST_VECTOR_ADD_SORTED(contact_vec, contact, vec_contact_cmp);
500  if (AST_VECTOR_SIZE(contact_vec) == AST_VECTOR_MAX_SIZE(contact_vec)) {
501  /*
502  * We added a contact over the number we need to remove.
503  * Remove the longest to expire contact from the vector
504  * which is the last element in the vector. It may be
505  * the one we just added or the one we just added pushed
506  * out an earlier contact from removal consideration.
507  */
508  --AST_VECTOR_SIZE(contact_vec);
509  }
510  return 0;
511 }
512 
513 /*!
514  * \internal
515  * \brief Remove excess existing contacts that expire the soonest.
516  * \since 13.18.0
517  *
518  * \param contacts Container of unmodified contacts that could remove.
519  * \param to_remove Maximum number of contacts to remove.
520  *
521  * \return Nothing
522  */
523 static void remove_excess_contacts(struct ao2_container *contacts, struct ao2_container *response_contacts,
524  unsigned int to_remove)
525 {
526  struct excess_contact_vector contact_vec;
527 
528  /*
529  * Create a sorted vector to hold the to_remove soonest to
530  * expire contacts. The vector has an extra space to
531  * temporarily hold the longest to expire contact that we
532  * won't remove.
533  */
534  if (AST_VECTOR_INIT(&contact_vec, to_remove + 1)) {
535  return;
536  }
537  ao2_callback(contacts, OBJ_NODATA | OBJ_MULTIPLE, vec_contact_add, &contact_vec);
538 
539  /*
540  * The vector should always be populated with the number
541  * of contacts we need to remove. Just in case, we will
542  * remove all contacts in the vector even if the contacts
543  * container had fewer contacts than there should be.
544  */
545  ast_assert(AST_VECTOR_SIZE(&contact_vec) == to_remove);
546  to_remove = AST_VECTOR_SIZE(&contact_vec);
547 
548  /* Remove the excess contacts that expire the soonest */
549  while (to_remove--) {
550  struct ast_sip_contact *contact;
551 
552  contact = AST_VECTOR_GET(&contact_vec, to_remove);
553 
555 
556  ao2_unlink(response_contacts, contact);
557  }
558 
559  AST_VECTOR_FREE(&contact_vec);
560 }
561 
562 /*! \brief Callback function which adds non-permanent contacts to a container */
563 static int registrar_add_non_permanent(void *obj, void *arg, int flags)
564 {
565  struct ast_sip_contact *contact = obj;
566  struct ao2_container *container = arg;
567 
568  if (ast_tvzero(contact->expiration_time)) {
569  return 0;
570  }
571 
572  ao2_link(container, contact);
573 
574  return 0;
575 }
576 
578  /*! Tx data to use for statefull response. NULL for stateless response. */
579  pjsip_tx_data *tdata;
580  /*! SIP response code to send in stateless response */
581  int code;
582 };
583 
584 static void register_aor_core(pjsip_rx_data *rdata,
585  struct ast_sip_endpoint *endpoint,
586  struct ast_sip_aor *aor,
587  const char *aor_name,
588  struct ao2_container *contacts,
589  struct aor_core_response *response)
590 {
591  static const pj_str_t USER_AGENT = { "User-Agent", 10 };
592 
593  int added = 0;
594  int updated = 0;
595  int deleted = 0;
596  int permanent = 0;
597  int contact_count;
598  struct ao2_container *existing_contacts = NULL;
599  pjsip_contact_hdr *contact_hdr = (pjsip_contact_hdr *)&rdata->msg_info.msg->hdr;
600  struct registrar_contact_details details = { 0, };
601  pjsip_tx_data *tdata;
602  RAII_VAR(struct ast_str *, path_str, NULL, ast_free);
603  struct ast_sip_contact *response_contact;
604  char *user_agent = NULL;
605  pjsip_user_agent_hdr *user_agent_hdr;
606  pjsip_expires_hdr *expires_hdr;
607  pjsip_via_hdr *via_hdr;
608  pjsip_via_hdr *via_hdr_last;
609  char *via_addr = NULL;
610  int via_port = 0;
611  pjsip_cid_hdr *call_id_hdr;
612  char *call_id = NULL;
613  size_t alloc_size;
614 
615  /* We create a single pool and use it throughout this function where we need one */
616  details.pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(),
617  "Contact Comparison", 1024, 256);
618  if (!details.pool) {
619  response->code = 500;
620  return;
621  }
622 
623  /* If there are any permanent contacts configured on the AOR we need to take them
624  * into account when counting contacts.
625  */
626  if (aor->permanent_contacts) {
627  permanent = ao2_container_count(aor->permanent_contacts);
628  }
629 
630  if (registrar_validate_contacts(rdata, details.pool, contacts, aor, permanent, &added, &updated, &deleted)) {
631  /* The provided Contact headers do not conform to the specification */
632  ast_sip_report_failed_acl(endpoint, rdata, "registrar_invalid_contacts_provided");
633  ast_log(LOG_WARNING, "Failed to validate contacts in REGISTER request from '%s'\n",
635  response->code = 400;
636  pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), details.pool);
637  return;
638  }
639 
640  if (registrar_validate_path(rdata, aor, &path_str)) {
641  /* Ensure that intervening proxies did not make invalid modifications to the request */
642  ast_log(LOG_WARNING, "Invalid modifications made to REGISTER request from '%s' by intervening proxy\n",
644  response->code = 420;
645  pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), details.pool);
646  return;
647  }
648 
649  if (aor->remove_existing) {
650  /* Cumulative number of contacts affected by this registration */
651  contact_count = MAX(updated + added - deleted, 0);
652 
653  /* We need to keep track of only existing contacts so we can later
654  * remove them if need be.
655  */
658  if (!existing_contacts) {
659  response->code = 500;
660  pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), details.pool);
661  return;
662  }
663 
664  ao2_callback(contacts, OBJ_NODATA, registrar_add_non_permanent, existing_contacts);
665  } else {
666  /* Total contacts after this registration */
667  contact_count = ao2_container_count(contacts) - permanent + added - deleted;
668  }
669  if (contact_count > aor->max_contacts) {
670  /* Enforce the maximum number of contacts */
671  ast_sip_report_failed_acl(endpoint, rdata, "registrar_attempt_exceeds_maximum_configured_contacts");
672  ast_log(LOG_WARNING, "Registration attempt from endpoint '%s' (%s:%d) to AOR '%s' will exceed max contacts of %u\n",
673  ast_sorcery_object_get_id(endpoint), rdata->pkt_info.src_name, rdata->pkt_info.src_port,
674  aor_name, aor->max_contacts);
675  response->code = 403;
676  pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), details.pool);
677  ao2_cleanup(existing_contacts);
678  return;
679  }
680 
681  user_agent_hdr = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &USER_AGENT, NULL);
682  if (user_agent_hdr) {
683  alloc_size = pj_strlen(&user_agent_hdr->hvalue) + 1;
684  user_agent = ast_alloca(alloc_size);
685  ast_copy_pj_str(user_agent, &user_agent_hdr->hvalue, alloc_size);
686  }
687 
688  /* Find the first Via header */
689  via_hdr = via_hdr_last = (pjsip_via_hdr*) pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_VIA, NULL);
690  if (via_hdr) {
691  /* Find the last Via header */
692  while ( (via_hdr = (pjsip_via_hdr*) pjsip_msg_find_hdr(rdata->msg_info.msg,
693  PJSIP_H_VIA, via_hdr->next)) != NULL) {
694  via_hdr_last = via_hdr;
695  }
696  alloc_size = pj_strlen(&via_hdr_last->sent_by.host) + 1;
697  via_addr = ast_alloca(alloc_size);
698  ast_copy_pj_str(via_addr, &via_hdr_last->sent_by.host, alloc_size);
699  via_port=via_hdr_last->sent_by.port;
700  }
701 
702  call_id_hdr = (pjsip_cid_hdr*) pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CALL_ID, NULL);
703  if (call_id_hdr) {
704  alloc_size = pj_strlen(&call_id_hdr->id) + 1;
705  call_id = ast_alloca(alloc_size);
706  ast_copy_pj_str(call_id, &call_id_hdr->id, alloc_size);
707  }
708 
709  /* Iterate each provided Contact header and add, update, or delete */
710  for (; (contact_hdr = (pjsip_contact_hdr *) pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT, contact_hdr->next)); pj_pool_reset(details.pool)) {
711  int expiration;
712  char contact_uri[pjsip_max_url_size];
714 
715  if (contact_hdr->star) {
716  /* A star means to unregister everything, so do so for the possible contacts */
718  registrar_delete_contact, (void *)aor_name);
719  /* If we are keeping track of existing contacts for removal then, well, there is
720  * absolutely nothing left so no need to try to remove any.
721  */
722  if (existing_contacts) {
723  ao2_ref(existing_contacts, -1);
724  existing_contacts = NULL;
725  }
726  break;
727  }
728 
729  if (!PJSIP_URI_SCHEME_IS_SIP(contact_hdr->uri) && !PJSIP_URI_SCHEME_IS_SIPS(contact_hdr->uri)) {
730  /* This registrar only currently supports sip: and sips: URI schemes */
731  continue;
732  }
733 
734  expiration = registrar_get_expiration(aor, contact_hdr, rdata);
735  details.uri = pjsip_uri_get_uri(contact_hdr->uri);
736  pjsip_uri_print(PJSIP_URI_IN_CONTACT_HDR, details.uri, contact_uri, sizeof(contact_uri));
737 
738  contact = ao2_callback(contacts, OBJ_UNLINK, registrar_find_contact, &details);
739 
740  /* If a contact was returned and we need to keep track of existing contacts then it
741  * should be removed.
742  */
743  if (contact && existing_contacts) {
744  ao2_unlink(existing_contacts, contact);
745  }
746 
747  if (!contact) {
748  int prune_on_boot;
749 
750  /* If they are actually trying to delete a contact that does not exist... be forgiving */
751  if (!expiration) {
752  ast_verb(3, "Attempted to remove non-existent contact '%s' from AOR '%s' by request\n",
753  contact_uri, aor_name);
754  continue;
755  }
756 
757  prune_on_boot = !ast_sip_will_uri_survive_restart(details.uri, endpoint, rdata);
758 
760  ast_tvadd(ast_tvnow(), ast_samp2tv(expiration, 1)),
761  path_str ? ast_str_buffer(path_str) : NULL,
762  user_agent, via_addr, via_port, call_id, prune_on_boot, endpoint);
763  if (!contact) {
764  ast_log(LOG_ERROR, "Unable to bind contact '%s' to AOR '%s'\n",
765  contact_uri, aor_name);
766  continue;
767  }
768 
769  if (prune_on_boot) {
770  size_t contact_name_len;
771  const char *contact_name;
773 
774  /*
775  * Monitor the transport in case it gets disconnected because
776  * the contact won't be valid anymore if that happens.
777  */
778  contact_name = ast_sorcery_object_get_id(contact);
779  contact_name_len = strlen(contact_name) + 1;
780  monitor = ao2_alloc(sizeof(*monitor) + 1 + strlen(aor_name)
781  + contact_name_len, NULL);
782  if (monitor) {
783  strcpy(monitor->aor_name, aor_name);/* Safe */
784  monitor->contact_name = monitor->aor_name + strlen(aor_name) + 1;
785  ast_copy_string(monitor->contact_name, contact_name, contact_name_len);/* Safe */
786 
787  ast_sip_transport_monitor_register_replace(rdata->tp_info.transport,
789  ao2_ref(monitor, -1);
790  }
791  }
792 
793  ast_verb(3, "Added contact '%s' to AOR '%s' with expiration of %d seconds\n",
794  contact_uri, aor_name, expiration);
795  ast_test_suite_event_notify("AOR_CONTACT_ADDED",
796  "Contact: %s\r\n"
797  "AOR: %s\r\n"
798  "Expiration: %d\r\n"
799  "UserAgent: %s",
800  contact_uri,
801  aor_name,
802  expiration,
803  user_agent);
804 
805  ao2_link(contacts, contact);
806  } else if (expiration) {
807  struct ast_sip_contact *contact_update;
808 
809  contact_update = ast_sorcery_copy(ast_sip_get_sorcery(), contact);
810  if (!contact_update) {
811  ast_log(LOG_ERROR, "Failed to update contact '%s' expiration time to %d seconds.\n",
812  contact->uri, expiration);
813  continue;
814  }
815 
816  contact_update->expiration_time = ast_tvadd(ast_tvnow(), ast_samp2tv(expiration, 1));
817  contact_update->qualify_frequency = aor->qualify_frequency;
818  contact_update->authenticate_qualify = aor->authenticate_qualify;
819  if (path_str) {
820  ast_string_field_set(contact_update, path, ast_str_buffer(path_str));
821  }
822  if (user_agent) {
823  ast_string_field_set(contact_update, user_agent, user_agent);
824  }
827  }
828 
829  if (ast_sip_location_update_contact(contact_update)) {
830  ast_log(LOG_ERROR, "Failed to update contact '%s' expiration time to %d seconds.\n",
831  contact->uri, expiration);
832  registrar_contact_delete(CONTACT_DELETE_ERROR, rdata->tp_info.transport,
833  contact, aor_name);
834  continue;
835  }
836  ast_debug(3, "Refreshed contact '%s' on AOR '%s' with new expiration of %d seconds\n",
837  contact_uri, aor_name, expiration);
838  ast_test_suite_event_notify("AOR_CONTACT_REFRESHED",
839  "Contact: %s\r\n"
840  "AOR: %s\r\n"
841  "Expiration: %d\r\n"
842  "UserAgent: %s",
843  contact_uri,
844  aor_name,
845  expiration,
846  contact_update->user_agent);
847  ao2_link(contacts, contact_update);
848  ao2_cleanup(contact_update);
849  } else {
850  registrar_contact_delete(CONTACT_DELETE_REQUEST, rdata->tp_info.transport,
851  contact, aor_name);
852  }
853  }
854 
855  pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), details.pool);
856 
857  /*
858  * If the AOR is configured to remove any contacts over max_contacts
859  * that have not been updated/added/deleted as a result of this
860  * REGISTER do so.
861  *
862  * The existing contacts container holds all contacts that were not
863  * involved in this REGISTER.
864  * The contacts container holds the current contacts of the AOR.
865  */
866  if (aor->remove_existing && existing_contacts) {
867  /* Total contacts after this registration */
868  contact_count = ao2_container_count(existing_contacts) + updated + added;
869  if (contact_count > aor->max_contacts) {
870  /* Remove excess existing contacts that expire the soonest */
871  remove_excess_contacts(existing_contacts, contacts, contact_count - aor->max_contacts);
872  }
873  ao2_ref(existing_contacts, -1);
874  }
875 
876  response_contact = ao2_callback(contacts, 0, NULL, NULL);
877 
878  /* Send a response containing all of the contacts (including static) that are present on this AOR */
879  if (ast_sip_create_response(rdata, 200, response_contact, &tdata) != PJ_SUCCESS) {
880  ao2_cleanup(response_contact);
881  ao2_cleanup(contacts);
882  response->code = 500;
883  return;
884  }
885  ao2_cleanup(response_contact);
886 
887  /* Add the date header to the response, some UAs use this to set their date and time */
889 
890  ao2_callback(contacts, 0, registrar_add_contact, tdata);
891 
892  if ((expires_hdr = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_EXPIRES, NULL))) {
893  expires_hdr = pjsip_expires_hdr_create(tdata->pool, registrar_get_expiration(aor, NULL, rdata));
894  pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)expires_hdr);
895  }
896 
897  response->tdata = tdata;
898 }
899 
900 static int register_aor(pjsip_rx_data *rdata,
901  struct ast_sip_endpoint *endpoint,
902  struct ast_sip_aor *aor,
903  const char *aor_name)
904 {
905  struct aor_core_response response = {
906  .code = 500,
907  };
908  struct ao2_container *contacts = NULL;
909 
910  ao2_lock(aor);
912  if (!contacts) {
913  ao2_unlock(aor);
914  pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(),
915  rdata, response.code, NULL, NULL, NULL);
916  return PJ_TRUE;
917  }
918 
919  register_aor_core(rdata, endpoint, aor, aor_name, contacts, &response);
920  ao2_cleanup(contacts);
921  ao2_unlock(aor);
922 
923  /* Now send the REGISTER response to the peer */
924  if (response.tdata) {
925  ast_sip_send_stateful_response(rdata, response.tdata, endpoint);
926  } else {
927  pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(),
928  rdata, response.code, NULL, NULL, NULL);
929  }
930  return PJ_TRUE;
931 }
932 
933 static int match_aor(const char *aor_name, const char *id)
934 {
935  if (ast_strlen_zero(aor_name)) {
936  return 0;
937  }
938 
939  if (!strcmp(aor_name, id)) {
940  ast_debug(3, "Matched id '%s' to aor '%s'\n", id, aor_name);
941  return 1;
942  }
943 
944  return 0;
945 }
946 
947 static char *find_aor_name(const pj_str_t *pj_username, const pj_str_t *pj_domain, const char *aors)
948 {
949  char *configured_aors;
950  char *aors_buf;
951  char *aor_name;
952  char *id_domain;
953  char *username, *domain;
954  struct ast_sip_domain_alias *alias;
955 
956  /* Turn these into C style strings for convenience */
957  username = ast_alloca(pj_strlen(pj_username) + 1);
958  ast_copy_pj_str(username, pj_username, pj_strlen(pj_username) + 1);
959  domain = ast_alloca(pj_strlen(pj_domain) + 1);
960  ast_copy_pj_str(domain, pj_domain, pj_strlen(pj_domain) + 1);
961 
962  id_domain = ast_alloca(strlen(username) + strlen(domain) + 2);
963  sprintf(id_domain, "%s@%s", username, domain);
964 
965  aors_buf = ast_strdupa(aors);
966 
967  /* Look for exact match on username@domain */
968  configured_aors = aors_buf;
969  while ((aor_name = ast_strip(strsep(&configured_aors, ",")))) {
970  if (match_aor(aor_name, id_domain)) {
971  return ast_strdup(aor_name);
972  }
973  }
974 
975  /* If there's a domain alias, look for exact match on username@domain_alias */
976  alias = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "domain_alias", domain);
977  if (alias) {
978  char *id_domain_alias = ast_alloca(strlen(username) + strlen(alias->domain) + 2);
979 
980  sprintf(id_domain_alias, "%s@%s", username, alias->domain);
981  ao2_cleanup(alias);
982 
983  configured_aors = strcpy(aors_buf, aors);/* Safe */
984  while ((aor_name = ast_strip(strsep(&configured_aors, ",")))) {
985  if (match_aor(aor_name, id_domain_alias)) {
986  return ast_strdup(aor_name);
987  }
988  }
989  }
990 
991  if (ast_strlen_zero(username)) {
992  /* No username, no match */
993  return NULL;
994  }
995 
996  /* Look for exact match on username only */
997  configured_aors = strcpy(aors_buf, aors);/* Safe */
998  while ((aor_name = ast_strip(strsep(&configured_aors, ",")))) {
999  if (match_aor(aor_name, username)) {
1000  return ast_strdup(aor_name);
1001  }
1002  }
1003 
1004  return NULL;
1005 }
1006 
1007 static struct ast_sip_aor *find_registrar_aor(struct pjsip_rx_data *rdata, struct ast_sip_endpoint *endpoint)
1008 {
1009  struct ast_sip_aor *aor = NULL;
1010  char *aor_name = NULL;
1011  int i;
1012 
1013  for (i = 0; i < AST_VECTOR_SIZE(&endpoint->ident_method_order); ++i) {
1014  pj_str_t username;
1015  pjsip_sip_uri *uri;
1016  pjsip_authorization_hdr *header = NULL;
1017 
1018  switch (AST_VECTOR_GET(&endpoint->ident_method_order, i)) {
1020  uri = pjsip_uri_get_uri(rdata->msg_info.to->uri);
1021 
1022  pj_strassign(&username, &uri->user);
1023 
1024  /*
1025  * We may want to match without any user options getting
1026  * in the way.
1027  *
1028  * Logic adapted from AST_SIP_USER_OPTIONS_TRUNCATE_CHECK for pj_str_t.
1029  */
1031  pj_ssize_t semi = pj_strcspn2(&username, ";");
1032  if (semi < pj_strlen(&username)) {
1033  username.slen = semi;
1034  }
1035  }
1036 
1037  aor_name = find_aor_name(&username, &uri->host, endpoint->aors);
1038  if (aor_name) {
1039  ast_debug(3, "Matched aor '%s' by To username\n", aor_name);
1040  }
1041  break;
1043  while ((header = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_AUTHORIZATION,
1044  header ? header->next : NULL))) {
1045  if (header && !pj_stricmp2(&header->scheme, "digest")) {
1046  aor_name = find_aor_name(&header->credential.digest.username,
1047  &header->credential.digest.realm, endpoint->aors);
1048  if (aor_name) {
1049  ast_debug(3, "Matched aor '%s' by Authentication username\n", aor_name);
1050  break;
1051  }
1052  }
1053  }
1054  break;
1055  default:
1056  continue;
1057  }
1058 
1059  if (aor_name) {
1060  break;
1061  }
1062  }
1063 
1064  if (ast_strlen_zero(aor_name) || !(aor = ast_sip_location_retrieve_aor(aor_name))) {
1065  /* The provided AOR name was not found (be it within the configuration or sorcery itself) */
1066  pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 404, NULL, NULL, NULL);
1067  ast_sip_report_req_no_support(endpoint, rdata, "registrar_requested_aor_not_found");
1068  ast_log(LOG_WARNING, "AOR '%s' not found for endpoint '%s' (%s:%d)\n",
1069  aor_name ?: "", ast_sorcery_object_get_id(endpoint),
1070  rdata->pkt_info.src_name, rdata->pkt_info.src_port);
1071  }
1072  ast_free(aor_name);
1073  return aor;
1074 }
1075 
1076 static pj_bool_t registrar_on_rx_request(struct pjsip_rx_data *rdata)
1077 {
1078  RAII_VAR(struct ast_sip_endpoint *, endpoint,
1080  struct ast_sip_aor *aor;
1081  const char *aor_name;
1082 
1083  if (pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_register_method) || !endpoint) {
1084  return PJ_FALSE;
1085  }
1086 
1087  if (ast_strlen_zero(endpoint->aors)) {
1088  /* Short circuit early if the endpoint has no AORs configured on it, which means no registration possible */
1089  pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 403, NULL, NULL, NULL);
1090  ast_sip_report_failed_acl(endpoint, rdata, "registrar_attempt_without_configured_aors");
1091  ast_log(LOG_WARNING, "Endpoint '%s' (%s:%d) has no configured AORs\n", ast_sorcery_object_get_id(endpoint),
1092  rdata->pkt_info.src_name, rdata->pkt_info.src_port);
1093  return PJ_TRUE;
1094  }
1095 
1096  if (!PJSIP_URI_SCHEME_IS_SIP(rdata->msg_info.to->uri) && !PJSIP_URI_SCHEME_IS_SIPS(rdata->msg_info.to->uri)) {
1097  pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 416, NULL, NULL, NULL);
1098  ast_sip_report_failed_acl(endpoint, rdata, "registrar_invalid_uri_in_to_received");
1099  ast_log(LOG_WARNING, "Endpoint '%s' (%s:%d) attempted to register to an AOR with a non-SIP URI\n", ast_sorcery_object_get_id(endpoint),
1100  rdata->pkt_info.src_name, rdata->pkt_info.src_port);
1101  return PJ_TRUE;
1102  }
1103 
1104  aor = find_registrar_aor(rdata, endpoint);
1105  if (!aor) {
1106  /* We've already responded about not finding an AOR. */
1107  return PJ_TRUE;
1108  }
1109 
1110  aor_name = ast_sorcery_object_get_id(aor);
1111 
1112  if (!aor->max_contacts) {
1113  /* Registration is not permitted for this AOR */
1114  pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 403, NULL, NULL, NULL);
1115  ast_sip_report_req_no_support(endpoint, rdata, "registrar_attempt_without_registration_permitted");
1116  ast_log(LOG_WARNING, "AOR '%s' has no configured max_contacts. Endpoint '%s' (%s:%d) unable to register\n",
1117  aor_name, ast_sorcery_object_get_id(endpoint),
1118  rdata->pkt_info.src_name, rdata->pkt_info.src_port);
1119  } else {
1120  register_aor(rdata, endpoint, aor, aor_name);
1121  }
1122  ao2_ref(aor, -1);
1123  return PJ_TRUE;
1124 }
1125 
1126 /* function pointer to callback needs to be within the module
1127  in order to avoid problems with an undefined symbol */
1128 static int sip_contact_to_str(void *acp, void *arg, int flags)
1129 {
1130  return ast_sip_contact_to_str(acp, arg, flags);
1131 }
1132 
1133 static int ami_registrations_aor(void *obj, void *arg, int flags)
1134 {
1135  struct ast_sip_aor *aor = obj;
1136  struct ast_sip_ami *ami = arg;
1137  int *count = ami->arg;
1138  RAII_VAR(struct ast_str *, buf,
1139  ast_sip_create_ami_event("InboundRegistrationDetail", ami), ast_free);
1140 
1141  if (!buf) {
1142  return -1;
1143  }
1144 
1146  ast_str_append(&buf, 0, "Contacts: ");
1148  ast_str_append(&buf, 0, "\r\n");
1149 
1150  astman_append(ami->s, "%s\r\n", ast_str_buffer(buf));
1151  (*count)++;
1152  return 0;
1153 }
1154 
1155 static int ami_registrations_endpoint(void *obj, void *arg, int flags)
1156 {
1157  struct ast_sip_endpoint *endpoint = obj;
1158  return ast_sip_for_each_aor(
1159  endpoint->aors, ami_registrations_aor, arg);
1160 }
1161 
1162 static int ami_registrations_endpoints(void *arg)
1163 {
1164  RAII_VAR(struct ao2_container *, endpoints,
1166 
1167  if (!endpoints) {
1168  return 0;
1169  }
1170 
1172  return 0;
1173 }
1174 
1175 static int ami_show_registrations(struct mansession *s, const struct message *m)
1176 {
1177  int count = 0;
1178  struct ast_sip_ami ami = { .s = s, .m = m, .arg = &count, .action_id = astman_get_header(m, "ActionID"), };
1179 
1180  astman_send_listack(s, m, "Following are Events for each Inbound registration",
1181  "start");
1182 
1184 
1185  astman_send_list_complete_start(s, m, "InboundRegistrationDetailComplete", count);
1187  return 0;
1188 }
1189 
1191 {
1192  int count = 0;
1193  struct ast_sip_ami ami = { .s = s, .m = m, .arg = NULL, .action_id = astman_get_header(m, "ActionID"), };
1194  struct ao2_container *contacts = ast_sorcery_retrieve_by_fields(
1196  struct ao2_iterator i;
1197  struct ast_sip_contact *contact;
1198 
1199  astman_send_listack(s, m, "Following are ContactStatusEvents for each Inbound "
1200  "registration", "start");
1201 
1202  if (contacts) {
1203  i = ao2_iterator_init(contacts, 0);
1204  while ((contact = ao2_iterator_next(&i))) {
1205  struct ast_sip_contact_wrapper wrapper;
1206 
1207  wrapper.aor_id = (char *)contact->aor;
1208  wrapper.contact = contact;
1209  wrapper.contact_id = (char *)ast_sorcery_object_get_id(contact);
1210 
1211  ast_sip_format_contact_ami(&wrapper, &ami, 0);
1212  count++;
1213 
1214  ao2_ref(contact, -1);
1215  }
1217  ao2_ref(contacts, -1);
1218  }
1219 
1220  astman_send_list_complete_start(s, m, "ContactStatusDetailComplete", count);
1222  return 0;
1223 }
1224 
1225 #define AMI_SHOW_REGISTRATION_CONTACT_STATUSES "PJSIPShowRegistrationInboundContactStatuses"
1226 #define AMI_SHOW_REGISTRATIONS "PJSIPShowRegistrationsInbound"
1227 
1228 static pjsip_module registrar_module = {
1229  .name = { "Registrar", 9 },
1230  .id = -1,
1231  .priority = PJSIP_MOD_PRIORITY_APPLICATION,
1232  .on_rx_request = registrar_on_rx_request,
1233 };
1234 
1235 /*! \brief Thread keeping things alive */
1236 static pthread_t check_thread = AST_PTHREADT_NULL;
1237 
1238 /*! \brief The global interval at which to check for contact expiration */
1239 static unsigned int check_interval;
1240 
1241 /*! \brief Callback function which deletes a contact */
1242 static int expire_contact(void *obj, void *arg, int flags)
1243 {
1244  struct ast_sip_contact *contact = obj;
1245  struct ast_named_lock *lock;
1246 
1247  lock = ast_named_lock_get(AST_NAMED_LOCK_TYPE_MUTEX, "aor", contact->aor);
1248  if (!lock) {
1249  return 0;
1250  }
1251 
1252  /*
1253  * We need to check the expiration again with the aor lock held
1254  * in case another thread is attempting to renew the contact.
1255  */
1256  ao2_lock(lock);
1257  if (ast_tvdiff_ms(ast_tvnow(), contact->expiration_time) > 0) {
1259  }
1260  ao2_unlock(lock);
1261  ast_named_lock_put(lock);
1262 
1263  return 0;
1264 }
1265 
1266 static void *check_expiration_thread(void *data)
1267 {
1268  struct ao2_container *contacts;
1269  struct ast_variable *var;
1270  char *time = alloca(64);
1271 
1272  while (check_interval) {
1273  sleep(check_interval);
1274 
1275  sprintf(time, "%ld", ast_tvnow().tv_sec);
1276  var = ast_variable_new("expiration_time <=", time, "");
1277 
1278  ast_debug(4, "Woke up at %s Interval: %d\n", time, check_interval);
1279 
1280  contacts = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "contact",
1282 
1283  ast_variables_destroy(var);
1284  if (contacts) {
1285  ast_debug(3, "Expiring %d contacts\n", ao2_container_count(contacts));
1287  ao2_ref(contacts, -1);
1288  }
1289  }
1290 
1291  return NULL;
1292 }
1293 
1294 static void expiration_global_loaded(const char *object_type)
1295 {
1297 
1298  /* Observer calls are serialized so this is safe without it's own lock */
1299  if (check_interval) {
1300  if (check_thread == AST_PTHREADT_NULL) {
1302  ast_log(LOG_ERROR, "Could not create thread for checking contact expiration.\n");
1303  return;
1304  }
1305  ast_debug(3, "Interval = %d, starting thread\n", check_interval);
1306  }
1307  } else {
1308  if (check_thread != AST_PTHREADT_NULL) {
1309  pthread_kill(check_thread, SIGURG);
1310  pthread_join(check_thread, NULL);
1311  check_thread = AST_PTHREADT_NULL;
1312  ast_debug(3, "Interval = 0, shutting thread down\n");
1313  }
1314  }
1315 }
1316 
1317 /*! \brief Observer which is used to update our interval when the global setting changes */
1320 };
1321 
1322 static int load_module(void)
1323 {
1324  const pj_str_t STR_REGISTER = { "REGISTER", 8 };
1325 
1326  ast_pjproject_get_buildopt("PJ_MAX_HOSTNAME", "%d", &pj_max_hostname);
1327  /* As of pjproject 2.4.5, PJSIP_MAX_URL_SIZE isn't exposed yet but we try anyway. */
1328  ast_pjproject_get_buildopt("PJSIP_MAX_URL_SIZE", "%d", &pjsip_max_url_size);
1329 
1330  if (ast_sip_register_service(&registrar_module)) {
1331  return AST_MODULE_LOAD_DECLINE;
1332  }
1333 
1334  if (pjsip_endpt_add_capability(ast_sip_get_pjsip_endpoint(), NULL, PJSIP_H_ALLOW, NULL, 1, &STR_REGISTER) != PJ_SUCCESS) {
1335  ast_sip_unregister_service(&registrar_module);
1336  return AST_MODULE_LOAD_DECLINE;
1337  }
1338 
1343 
1344  ast_sorcery_observer_add(ast_sip_get_sorcery(), "global", &expiration_global_observer);
1346 
1347  return AST_MODULE_LOAD_SUCCESS;
1348 }
1349 
1350 static int unload_module(void)
1351 {
1352  if (check_thread != AST_PTHREADT_NULL) {
1353  check_interval = 0;
1354  pthread_kill(check_thread, SIGURG);
1355  pthread_join(check_thread, NULL);
1356 
1357  check_thread = AST_PTHREADT_NULL;
1358  }
1359 
1360  ast_sorcery_observer_remove(ast_sip_get_sorcery(), "global", &expiration_global_observer);
1361 
1364  ast_sip_unregister_service(&registrar_module);
1366  return 0;
1367 }
1368 
1369 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP Registrar Support",
1370  .support_level = AST_MODULE_SUPPORT_CORE,
1371  .load = load_module,
1372  .unload = unload_module,
1373  .load_pri = AST_MODPRI_CHANNEL_DEPEND - 3,
1374  .requires = "res_pjproject,res_pjsip",
1375 );
static int load_module(void)
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition: vector.h:174
static const char type[]
Definition: chan_ooh323.c:109
int authenticate_qualify
Definition: res_pjsip.h:309
#define AST_VECTOR_ADD_SORTED(vec, elem, cmp)
Add an element into a sorted vector.
Definition: vector.h:371
AST_VECTOR(excess_contact_vector, struct ast_sip_contact *)
static pthread_t check_thread
Thread keeping things alive.
static pj_bool_t registrar_on_rx_request(struct pjsip_rx_data *rdata)
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:3080
Asterisk main include file. File version handling, generic pbx functions.
A SIP address of record.
Definition: res_pjsip.h:361
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
int ast_sip_for_each_aor(const char *aors, ao2_callback_fn on_aor, void *arg)
For every aor in the comma separated aors string call the given &#39;on_aor&#39; handler. ...
Definition: location.c:684
struct ao2_container * ast_sip_location_retrieve_aor_contacts_nolock(const struct ast_sip_aor *aor)
Retrieve all contacts currently available for an AOR without locking the AOR.
Definition: location.c:214
static int registrar_delete_contact(void *obj, void *arg, int flags)
Internal function used to delete a contact from an AOR.
static int register_aor(pjsip_rx_data *rdata, struct ast_sip_endpoint *endpoint, struct ast_sip_aor *aor, const char *aor_name)
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1263
const ast_string_field call_id
Definition: res_pjsip.h:303
const ast_string_field user_agent
Definition: res_pjsip.h:303
const ast_string_field path
Definition: res_pjsip.h:303
static int registrar_add_non_permanent(void *obj, void *arg, int flags)
Callback function which adds non-permanent contacts to a container.
const struct message * m
Definition: res_pjsip.h:2741
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
unsigned int max_contacts
Definition: res_pjsip.h:379
void astman_send_list_complete_start(struct mansession *s, const struct message *m, const char *event_name, int count)
Start the list complete event.
Definition: manager.c:3237
static int match_aor(const char *aor_name, const char *id)
static int build_path_data(pjsip_rx_data *rdata, struct ast_str **path_str)
#define LOG_WARNING
Definition: logger.h:274
static char * find_aor_name(const pj_str_t *pj_username, const pj_str_t *pj_domain, const char *aors)
const ast_string_field via_addr
Definition: res_pjsip.h:303
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
pjsip_tx_data * tdata
static int pjsip_max_url_size
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:1716
#define VERBOSITY_ATLEAST(level)
Definition: logger.h:461
void * arg
Definition: res_pjsip.h:2745
AMI variable container.
Definition: res_pjsip.h:2737
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
Definition: astobj2.h:1335
Structure for variables, used for configurations and for channel variables.
#define var
Definition: ast_expr2f.c:614
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:108
Test Framework API.
Perform no matching, return all objects.
Definition: sorcery.h:123
static int unload_module(void)
int ast_sorcery_object_id_compare(void *obj, void *arg, int flags)
ao2 object comparator based on sorcery id.
Definition: sorcery.c:2459
static int registrar_find_contact(void *obj, void *arg, int flags)
Callback function for finding a contact.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1091
unsigned int qualify_frequency
Definition: res_pjsip.h:307
static unsigned int registrar_get_expiration(const struct ast_sip_aor *aor, const pjsip_contact_hdr *contact, const pjsip_rx_data *rdata)
Internal function which returns the expiration time for a contact.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
Return all matching objects.
Definition: sorcery.h:120
#define ast_assert(a)
Definition: utils.h:695
static int contact_transport_monitor_matcher(void *a, void *b)
#define ao2_unlock(a)
Definition: astobj2.h:730
int ast_pjproject_get_buildopt(char *option, char *format_string,...)
Retrieve a pjproject build option.
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:98
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
void ast_copy_pj_str(char *dest, const pj_str_t *src, size_t size)
Copy a pj_str_t into a standard character buffer.
Definition: res_pjsip.c:5240
static void remove_excess_contacts(struct ao2_container *contacts, struct ao2_container *response_contacts, unsigned int to_remove)
int ast_sip_contact_to_str(void *object, void *arg, int flags)
Handler used to convert a contact to a string.
Definition: location.c:767
const ast_string_field reg_server
Definition: res_pjsip.h:303
#define NULL
Definition: resample.c:96
Domain data structure.
Definition: sip.h:888
static int vec_contact_cmp(struct ast_sip_contact *left, struct ast_sip_contact *right)
#define ast_verb(level,...)
Definition: logger.h:463
pjsip_sip_uri * uri
URI being looked for.
static int ami_show_registration_contact_statuses(struct mansession *s, const struct message *m)
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:2820
#define ast_strlen_zero(foo)
Definition: strings.h:52
void * ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
Retrieve an object using its unique identifier.
Definition: sorcery.c:1853
struct ast_sip_endpoint * ast_pjsip_rdata_get_endpoint(pjsip_rx_data *rdata)
Get the looked-up endpoint on an out-of dialog request or response.
static int ami_registrations_aor(void *obj, void *arg, int flags)
#define ast_pthread_create_background(a, b, c, d)
Definition: utils.h:567
const char * ast_config_AST_SYSTEM_NAME
Definition: options.c:170
int ast_sip_create_response(const pjsip_rx_data *rdata, int st_code, struct ast_sip_contact *contact, pjsip_tx_data **p_tdata)
General purpose method for creating a SIP response.
Definition: res_pjsip.c:5448
struct ast_sip_endpoint * endpoint
Definition: res_pjsip.h:313
static void register_aor_core(pjsip_rx_data *rdata, struct ast_sip_endpoint *endpoint, struct ast_sip_aor *aor, const char *aor_name, struct ao2_container *contacts, struct aor_core_response *response)
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1065
#define EVENT_FLAG_SYSTEM
Definition: manager.h:71
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
void ast_sip_report_failed_acl(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, const char *name)
Send a security event notification for when an ACL check fails.
#define ast_log
Definition: astobj2.c:42
#define MAX(a, b)
Definition: utils.h:228
struct ast_sip_identify_by_vector ident_method_order
Definition: res_pjsip.h:861
void ast_sip_report_req_no_support(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, const char *req_type)
Send a security event notification for when a request is not supported.
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:113
A wrapper for contact that adds the aor_id and a consistent contact id. Used by ast_sip_for_each_cont...
Definition: res_pjsip.h:396
Asterisk file paths, configured in asterisk.conf.
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition: manager.c:3245
struct ast_sip_contact * ast_sip_location_create_contact(struct ast_sip_aor *aor, const char *uri, struct timeval expiration_time, const char *path_info, const char *user_agent, const char *via_addr, int via_port, const char *call_id, int prune_on_boot, struct ast_sip_endpoint *endpoint)
Create a new contact for an AOR without locking the AOR.
Definition: location.c:355
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
#define AST_PTHREADT_NULL
Definition: lock.h:66
ast_mutex_t lock
Definition: app_meetme.c:1091
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: strings.h:219
static struct ao2_container * endpoints
#define ao2_ref(o, delta)
Definition: astobj2.h:464
In case you didn&#39;t read that giant block of text above the mansession_session struct, the struct mansession is named this solely to keep the API the same in Asterisk. This structure really represents data that is different from Manager action to Manager action. The mansession_session pointer contained within points to session-specific data.
Definition: manager.c:1625
int ast_sip_send_stateful_response(pjsip_rx_data *rdata, pjsip_tx_data *tdata, struct ast_sip_endpoint *sip_endpoint)
Send a stateful response to an out of dialog request.
Definition: res_pjsip.c:5420
#define ao2_lock(a)
Definition: astobj2.h:718
struct timeval ast_samp2tv(unsigned int _nsamp, unsigned int _rate)
Returns a timeval corresponding to the duration of n samples at rate r. Useful to convert samples to ...
Definition: time.h:238
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
struct mansession * s
Definition: res_pjsip.h:2739
struct ao2_container * container
Definition: res_fax.c:502
static int ami_show_registrations(struct mansession *s, const struct message *m)
char * contact_name
Sorcery contact name to remove on transport shutdown.
#define ast_variable_new(name, value, filename)
An entity with which Asterisk communicates.
Definition: res_pjsip.h:812
unsigned int support_path
Definition: res_pjsip.h:385
Named Locks.
static void expiration_global_loaded(const char *object_type)
int ast_sip_register_service(pjsip_module *module)
Register a SIP service in Asterisk.
Definition: res_pjsip.c:3315
static int registrar_validate_path(pjsip_rx_data *rdata, struct ast_sip_aor *aor, struct ast_str **path_str)
static int ami_registrations_endpoint(void *obj, void *arg, int flags)
int ast_sorcery_observer_add(const struct ast_sorcery *sorcery, const char *type, const struct ast_sorcery_observer *callbacks)
Add an observer to a specific object type.
Definition: sorcery.c:2386
int ast_sip_location_delete_contact(struct ast_sip_contact *contact)
Delete a contact.
Definition: location.c:450
void ast_sip_transport_monitor_unregister(pjsip_transport *transport, ast_transport_monitor_shutdown_cb cb, void *data, ast_transport_monitor_data_matcher matches)
Unregister a reliable transport shutdown monitor.
#define ast_test_suite_event_notify(s, f,...)
Definition: test.h:196
struct ast_sip_aor * ast_sip_location_retrieve_aor(const char *aor_name)
Retrieve a named AOR.
Definition: location.c:147
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
struct ast_sip_contact * contact
Definition: res_pjsip.h:402
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:7258
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
static struct ast_sip_aor * find_registrar_aor(struct pjsip_rx_data *rdata, struct ast_sip_endpoint *endpoint)
enum ast_transport_monitor_reg ast_sip_transport_monitor_register_replace(pjsip_transport *transport, ast_transport_monitor_shutdown_cb cb, void *ao2_data, ast_transport_monitor_data_matcher matches)
Register a reliable transport shutdown monitor callback replacing any duplicate.
static int ami_registrations_endpoints(void *arg)
static int register_contact_transport_remove_cb(void *data)
static int vec_contact_add(void *obj, void *arg, int flags)
#define LOG_ERROR
Definition: logger.h:285
int ast_tvcmp(struct timeval _a, struct timeval _b)
Compres two struct timeval instances returning -1, 0, 1 if the first arg is smaller, equal or greater to the second.
Definition: time.h:128
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
#define ao2_unlink(container, obj)
Definition: astobj2.h:1598
#define AMI_SHOW_REGISTRATIONS
int ast_sip_push_task(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Pushes a task to SIP servants.
Definition: res_pjsip.c:5138
pj_pool_t * pool
Pool used for parsing URI.
static void register_contact_transport_shutdown_cb(void *data)
Interface for a sorcery object type observer.
Definition: sorcery.h:332
static unsigned int monitor
Definition: chan_phone.c:116
Contact associated with an address of record.
Definition: res_pjsip.h:281
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
Definition: extconf.c:2283
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
void ast_sip_add_date_header(pjsip_tx_data *tdata)
Adds a Date header to the tdata, formatted like: Date: Wed, 01 Jan 2021 14:53:01 GMT.
Definition: res_pjsip.c:3288
static int registrar_validate_contacts(const pjsip_rx_data *rdata, pj_pool_t *pool, struct ao2_container *contacts, struct ast_sip_aor *aor, int permanent, int *added, int *updated, int *deleted)
Internal function which validates provided Contact headers to confirm that they are acceptable...
struct timeval expiration_time
Definition: res_pjsip.h:305
#define ast_free(a)
Definition: astmm.h:182
unsigned int ast_sip_get_contact_expiration_check_interval(void)
Retrieve the system contact expiration check interval setting.
int ast_sip_will_uri_survive_restart(pjsip_sip_uri *uri, struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata)
Definition: res_pjsip.c:3723
static int pj_max_hostname
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
An API for managing task processing threads that can be shared across modules.
static void * check_expiration_thread(void *data)
void(* loaded)(const char *object_type)
Callback for when an object type is loaded/reloaded.
Definition: sorcery.h:343
int ast_sip_format_contact_ami(void *obj, void *arg, int flags)
Formats the contact and sends over AMI.
struct ast_str * ast_sip_create_ami_event(const char *event, struct ast_sip_ami *ami)
Creates a string to store AMI event data in.
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS|AST_MODFLAG_LOAD_ORDER, "HTTP Phone Provisioning",.support_level=AST_MODULE_SUPPORT_EXTENDED,.load=load_module,.unload=unload_module,.reload=reload,.load_pri=AST_MODPRI_CHANNEL_DEPEND,.requires="http",)
void * ast_sorcery_retrieve_by_fields(const struct ast_sorcery *sorcery, const char *type, unsigned int flags, struct ast_variable *fields)
Retrieve an object or multiple objects using specific fields.
Definition: sorcery.c:1897
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
Definition: res_pjsip.c:3718
static pjsip_module registrar_module
const ast_string_field aor
Definition: res_pjsip.h:303
static int sip_contact_to_str(void *acp, void *arg, int flags)
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:682
void ast_sorcery_observer_remove(const struct ast_sorcery *sorcery, const char *type, const struct ast_sorcery_observer *callbacks)
Remove an observer from a specific object type.
Definition: sorcery.c:2418
char * strsep(char **str, const char *delims)
static int registrar_contact_delete(enum contact_delete_type type, pjsip_transport *transport, struct ast_sip_contact *contact, const char *aor_name)
const ast_string_field domain
Definition: res_pjsip.h:265
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
void * ast_sorcery_copy(const struct ast_sorcery *sorcery, const void *object)
Create a copy of an object.
Definition: sorcery.c:1778
Structure used for finding contact.
void ast_sip_unregister_service(pjsip_module *module)
Definition: res_pjsip.c:3331
int ast_sip_sorcery_object_to_ami(const void *obj, struct ast_str **buf)
Converts a sorcery object to a string of object properties.
static struct test_val b
struct ao2_container * ast_sip_get_endpoints(void)
Retrieve any endpoints available to sorcery.
Generic container type.
static const pj_str_t path_hdr_name
int ast_sip_location_update_contact(struct ast_sip_contact *contact)
Update a contact.
Definition: location.c:445
int ast_sip_for_each_contact(const struct ast_sip_aor *aor, ao2_callback_fn on_contact, void *arg)
For every contact on an AOR call the given &#39;on_contact&#39; handler.
Definition: location.c:719
contact_delete_type
const ast_string_field aors
Definition: res_pjsip.h:821
#define AMI_SHOW_REGISTRATION_CONTACT_STATUSES
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:186
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
static unsigned int check_interval
The global interval at which to check for contact expiration.
const ast_string_field uri
Definition: res_pjsip.h:303
Asterisk module definitions.
struct ast_sip_contact * ast_sip_location_retrieve_contact(const char *contact_name)
Retrieve a named contact.
Definition: location.c:350
unsigned int minimum_expiration
Definition: res_pjsip.h:369
unsigned int default_expiration
Definition: res_pjsip.h:373
unsigned int maximum_expiration
Definition: res_pjsip.h:371
static int expire_contact(void *obj, void *arg, int flags)
Callback function which deletes a contact.
void ast_sip_transport_monitor_unregister_all(ast_transport_monitor_shutdown_cb cb, void *data, ast_transport_monitor_data_matcher matches)
Unregister a transport shutdown monitor from all reliable transports.
static struct ast_sorcery_observer expiration_global_observer
Observer which is used to update our interval when the global setting changes.
#define PJSIP_EXPIRES_NOT_SPECIFIED
Definition: res_pjsip.h:63
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:611
static int registrar_add_contact(void *obj, void *arg, int flags)
Internal function which adds a contact to a response.
void ast_sorcery_reload_object(const struct ast_sorcery *sorcery, const char *type)
Inform any wizards of a specific object type to reload persistent objects.
Definition: sorcery.c:1442
#define ast_named_lock_get(lock_type, keyspace, key)
Geta named lock handle.
Definition: named_locks.h:83
unsigned int ast_sip_get_ignore_uri_user_options(void)
Retrieve the global setting &#39;ignore_uri_user_options&#39;.
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620
#define ast_named_lock_put(lock)
Put a named lock handle away.
Definition: named_locks.h:93
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514
void astman_send_listack(struct mansession *s, const struct message *m, char *msg, char *listflag)
Send ack in manager transaction to begin a list.
Definition: manager.c:3201
static struct test_val a
#define AST_VECTOR_MAX_SIZE(vec)
Get the maximum number of elements the vector can currently hold.
Definition: vector.h:619
#define ao2_link(container, obj)
Definition: astobj2.h:1549