Asterisk - The Open Source Telephony Project GIT-master-abe0018
Data Structures | Functions | Variables
res_pjsip_rfc3329.c File Reference
#include "asterisk.h"
#include <pjsip.h>
#include <pjsip_ua.h>
#include "asterisk/res_pjsip.h"
#include "asterisk/res_pjsip_session.h"
#include "asterisk/module.h"
#include "asterisk/causes.h"
#include "asterisk/threadpool.h"
Include dependency graph for res_pjsip_rfc3329.c:

Go to the source code of this file.

Data Structures

struct  rfc3329_store_data
 Private data structure used with the modules's datastore. More...
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
static void add_outgoing_request_headers (struct ast_sip_endpoint *endpoint, struct ast_sip_contact *contact, struct pjsip_tx_data *tdata, struct ast_datastore *datastore)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static void datastore_destroy_cb (void *data)
 
static int load_module (void)
 
static void rfc3329_incoming_response (struct ast_sip_session *session, struct pjsip_rx_data *rdata)
 
static void rfc3329_options_request (struct ast_sip_endpoint *endpoint, struct ast_sip_contact *contact, struct pjsip_tx_data *tdata)
 
static void rfc3329_outgoing_request (struct ast_sip_session *session, struct pjsip_tx_data *tdata)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "PJSIP RFC3329 Support (partial)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_APP_DEPEND, .requires = "res_pjsip,res_pjsip_session", }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static struct ast_sip_supplement rfc3329_options_supplement
 
static const struct ast_datastore_info rfc3329_store_datastore
 The channel datastore the module uses to store state. More...
 
static struct ast_sip_session_supplement rfc3329_supplement
 

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 189 of file res_pjsip_rfc3329.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 189 of file res_pjsip_rfc3329.c.

◆ add_outgoing_request_headers()

static void add_outgoing_request_headers ( struct ast_sip_endpoint endpoint,
struct ast_sip_contact contact,
struct pjsip_tx_data *  tdata,
struct ast_datastore datastore 
)
static

Definition at line 109 of file res_pjsip_rfc3329.c.

111{
112 static const pj_str_t security_verify = { "Security-Verify", 15 };
113 struct pjsip_generic_string_hdr *hdr = NULL;
114 struct ast_sip_contact_status *contact_status = NULL;
115 struct rfc3329_store_data *store_data;
116
118 return;
119 }
120
121 contact_status = ast_sip_get_contact_status(contact);
122 hdr = pjsip_msg_find_hdr_by_name(tdata->msg, &security_verify, NULL);
123
124 if (contact_status == NULL) {
125 return;
126 }
127
128 ao2_lock(contact_status);
129 if (AST_VECTOR_SIZE(&contact_status->security_mechanisms) && hdr == NULL) {
130 /* Add Security-Verify headers (with q-value) */
131 ast_sip_add_security_headers(&contact_status->security_mechanisms, "Security-Verify", 0, tdata);
132 }
133 if (datastore) {
134 store_data = datastore->data;
135 if (store_data->last_rx_status_code == 401) {
136 /* Add Security-Client headers (no q-value) */
137 ast_sip_add_security_headers(&endpoint->security_mechanisms, "Security-Client", 0, tdata);
138 }
139 }
140 ao2_unlock(contact_status);
141
142 ao2_cleanup(contact_status);
143}
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#define ao2_unlock(a)
Definition: astobj2.h:729
#define ao2_lock(a)
Definition: astobj2.h:717
@ AST_SIP_SECURITY_NEG_MEDIASEC
Definition: res_pjsip.h:357
struct ast_sip_contact_status * ast_sip_get_contact_status(const struct ast_sip_contact *contact)
Retrieve the current status for a contact.
int ast_sip_add_security_headers(struct ast_sip_security_mechanism_vector *security_mechanisms, const char *header_name, int add_qval, pjsip_tx_data *tdata)
Add security headers to transmission data.
#define NULL
Definition: resample.c:96
void * data
Definition: datastore.h:66
A contact's status.
Definition: res_pjsip.h:451
struct ast_sip_security_mechanism_vector security_mechanisms
Definition: res_pjsip.h:466
enum ast_sip_security_negotiation security_negotiation
Definition: res_pjsip.h:1058
struct ast_sip_security_mechanism_vector security_mechanisms
Definition: res_pjsip.h:1060
Private data structure used with the modules's datastore.
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:609

References ao2_cleanup, ao2_lock, ao2_unlock, ast_sip_add_security_headers(), ast_sip_get_contact_status(), AST_SIP_SECURITY_NEG_MEDIASEC, AST_VECTOR_SIZE, ast_datastore::data, rfc3329_store_data::last_rx_status_code, NULL, ast_sip_contact_status::security_mechanisms, ast_sip_endpoint::security_mechanisms, and ast_sip_endpoint::security_negotiation.

Referenced by rfc3329_options_request(), and rfc3329_outgoing_request().

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 189 of file res_pjsip_rfc3329.c.

◆ datastore_destroy_cb()

static void datastore_destroy_cb ( void *  data)
static

Definition at line 42 of file res_pjsip_rfc3329.c.

43{
44 struct rfc3329_store_data *d = data;
45 if (d) {
46 ast_free(d);
47 }
48}
#define ast_free(a)
Definition: astmm.h:180
static struct test_val d

References ast_free, and d.

◆ load_module()

static int load_module ( void  )
static

Definition at line 169 of file res_pjsip_rfc3329.c.

170{
174}
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
void ast_sip_register_supplement(struct ast_sip_supplement *supplement)
Register a supplement to SIP out of dialog processing.
Definition: res_pjsip.c:1456
static struct ast_sip_supplement rfc3329_options_supplement
static struct ast_sip_session_supplement rfc3329_supplement
#define ast_sip_session_register_supplement(supplement)

References AST_MODULE_LOAD_SUCCESS, ast_sip_register_supplement(), ast_sip_session_register_supplement, rfc3329_options_supplement, and rfc3329_supplement.

◆ rfc3329_incoming_response()

static void rfc3329_incoming_response ( struct ast_sip_session session,
struct pjsip_rx_data *  rdata 
)
static

Definition at line 56 of file res_pjsip_rfc3329.c.

57{
58 RAII_VAR(struct ast_datastore *, datastore, ast_sip_session_get_datastore(session, "rfc3329_store"), ao2_cleanup);
59 static const pj_str_t str_security_server = { "Security-Server", 15 };
60 struct ast_sip_contact_status *contact_status = NULL;
61 struct ast_sip_security_mechanism *mech;
62 struct rfc3329_store_data *store_data;
63 pjsip_generic_string_hdr *header;
64 char buf[128];
65 char *hdr_val;
66 char *mechanism;
67
68 if (!session || !session->endpoint || !session->endpoint->security_negotiation
69 || !session->contact || !(contact_status = ast_sip_get_contact_status(session->contact))
70 || !session->inv_session->dlg) {
71 return;
72 }
73
74 ao2_lock(contact_status);
75 if (AST_VECTOR_SIZE(&contact_status->security_mechanisms)) {
76 goto out;
77 }
78
79 if (!datastore
80 && (datastore = ast_sip_session_alloc_datastore(&rfc3329_store_datastore, "rfc3329_store"))
81 && (store_data = ast_calloc(1, sizeof(struct rfc3329_store_data)))) {
82
83 store_data->last_rx_status_code = rdata->msg_info.msg->line.status.code;
84 datastore->data = store_data;
86 } else {
87 ast_log(AST_LOG_WARNING, "Could not store session data. Still attempting requests, but they might be missing necessary headers.\n");
88 }
89
90 header = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &str_security_server, NULL);
91 for (; header;
92 header = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &str_security_server, header->next)) {
93 /* Parse Security-Server headers and add to contact status to use for future requests. */
94 ast_copy_pj_str(buf, &header->hvalue, sizeof(buf));
95 hdr_val = ast_skip_blanks(buf);
96
97 while ((mechanism = ast_strsep(&hdr_val, ',', AST_STRSEP_ALL))) {
98 if (!ast_sip_str_to_security_mechanism(&mech, mechanism)) {
99 AST_VECTOR_APPEND(&contact_status->security_mechanisms, mech);
100 }
101 }
102 }
103
104out:
105 ao2_unlock(contact_status);
106 ao2_cleanup(contact_status);
107}
static struct ast_mansession session
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define ast_log
Definition: astobj2.c:42
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define AST_LOG_WARNING
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:2201
int ast_sip_str_to_security_mechanism(struct ast_sip_security_mechanism **security_mechanism, const char *value)
Allocate a security mechanism from a string.
static const struct ast_datastore_info rfc3329_store_datastore
The channel datastore the module uses to store state.
struct ast_datastore * ast_sip_session_get_datastore(struct ast_sip_session *session, const char *name)
Retrieve a session datastore.
int ast_sip_session_add_datastore(struct ast_sip_session *session, struct ast_datastore *datastore)
Add a datastore to a SIP session.
struct ast_datastore * ast_sip_session_alloc_datastore(const struct ast_datastore_info *info, const char *uid)
Alternative for ast_datastore_alloc()
@ AST_STRSEP_ALL
Definition: strings.h:258
char * ast_strsep(char **s, const char sep, uint32_t flags)
Act like strsep but ignore separators inside quotes.
Definition: utils.c:1835
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
Definition: strings.h:161
Structure for a data store object.
Definition: datastore.h:64
Structure representing a security mechanism as defined in RFC 3329.
Definition: res_pjsip.h:378
struct header * next
FILE * out
Definition: utils/frame.c:33
#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:941
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256

References ao2_cleanup, ao2_lock, ao2_unlock, ast_calloc, ast_copy_pj_str(), ast_log, AST_LOG_WARNING, ast_sip_get_contact_status(), ast_sip_session_add_datastore(), ast_sip_session_alloc_datastore(), ast_sip_session_get_datastore(), ast_sip_str_to_security_mechanism(), ast_skip_blanks(), ast_strsep(), AST_STRSEP_ALL, AST_VECTOR_APPEND, AST_VECTOR_SIZE, buf, rfc3329_store_data::last_rx_status_code, header::next, NULL, out, RAII_VAR, rfc3329_store_datastore, ast_sip_contact_status::security_mechanisms, and session.

◆ rfc3329_options_request()

static void rfc3329_options_request ( struct ast_sip_endpoint endpoint,
struct ast_sip_contact contact,
struct pjsip_tx_data *  tdata 
)
static

Definition at line 159 of file res_pjsip_rfc3329.c.

160{
161 add_outgoing_request_headers(endpoint, contact, tdata, NULL);
162}
static void add_outgoing_request_headers(struct ast_sip_endpoint *endpoint, struct ast_sip_contact *contact, struct pjsip_tx_data *tdata, struct ast_datastore *datastore)

References add_outgoing_request_headers(), and NULL.

◆ rfc3329_outgoing_request()

static void rfc3329_outgoing_request ( struct ast_sip_session session,
struct pjsip_tx_data *  tdata 
)
static

Definition at line 145 of file res_pjsip_rfc3329.c.

146{
147 RAII_VAR(struct ast_datastore *, datastore, ast_sip_session_get_datastore(session, "rfc3329_store"), ao2_cleanup);
148 if (session->contact == NULL) {
149 return;
150 }
151 add_outgoing_request_headers(session->endpoint, session->contact, tdata, datastore);
152}

References add_outgoing_request_headers(), ao2_cleanup, ast_sip_session_get_datastore(), NULL, RAII_VAR, and session.

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 176 of file res_pjsip_rfc3329.c.

177{
180 return 0;
181}
void ast_sip_unregister_supplement(struct ast_sip_supplement *supplement)
Unregister a an supplement to SIP out of dialog processing.
Definition: res_pjsip.c:1476
void ast_sip_session_unregister_supplement(struct ast_sip_session_supplement *supplement)
Unregister a an supplement to SIP session processing.
Definition: pjsip_session.c:63

References ast_sip_session_unregister_supplement(), ast_sip_unregister_supplement(), rfc3329_options_supplement, and rfc3329_supplement.

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "PJSIP RFC3329 Support (partial)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_APP_DEPEND, .requires = "res_pjsip,res_pjsip_session", }
static

Definition at line 189 of file res_pjsip_rfc3329.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 189 of file res_pjsip_rfc3329.c.

◆ rfc3329_options_supplement

struct ast_sip_supplement rfc3329_options_supplement
static
Initial value:
= {
.method = "OPTIONS",
.outgoing_request = rfc3329_options_request,
}
static void rfc3329_options_request(struct ast_sip_endpoint *endpoint, struct ast_sip_contact *contact, struct pjsip_tx_data *tdata)

Definition at line 164 of file res_pjsip_rfc3329.c.

Referenced by load_module(), and unload_module().

◆ rfc3329_store_datastore

const struct ast_datastore_info rfc3329_store_datastore
static
Initial value:
= {
.type = "rfc3329_store",
}
static void datastore_destroy_cb(void *data)

The channel datastore the module uses to store state.

Definition at line 51 of file res_pjsip_rfc3329.c.

Referenced by rfc3329_incoming_response().

◆ rfc3329_supplement

struct ast_sip_session_supplement rfc3329_supplement
static
Initial value:
= {
.incoming_response = rfc3329_incoming_response,
.outgoing_request = rfc3329_outgoing_request,
}
static void rfc3329_incoming_response(struct ast_sip_session *session, struct pjsip_rx_data *rdata)
static void rfc3329_outgoing_request(struct ast_sip_session *session, struct pjsip_tx_data *tdata)

Definition at line 154 of file res_pjsip_rfc3329.c.

Referenced by load_module(), and unload_module().