Asterisk - The Open Source Telephony Project GIT-master-2de1a68
Data Structures | Functions | Variables
res_pjsip_logger.c File Reference
#include "asterisk.h"
#include <netinet/in.h>
#include <pjsip.h>
#include "asterisk/res_pjsip.h"
#include "asterisk/vector.h"
#include "asterisk/module.h"
#include "asterisk/logger.h"
#include "asterisk/cli.h"
#include "asterisk/netsock2.h"
#include "asterisk/acl.h"
Include dependency graph for res_pjsip_logger.c:

Go to the source code of this file.

Data Structures

struct  method_logging_info
 
struct  pcap_ethernet_header
 PCAP Ethernet Header. More...
 
struct  pcap_header
 PCAP Header. More...
 
struct  pcap_ipv4_header
 PCAP IPv4 Header. More...
 
struct  pcap_ipv6_header
 PCAP IPv6 Header. More...
 
struct  pcap_record_header
 PCAP Packet Record Header. More...
 
struct  pcap_udp_header
 PCAP UDP Header. More...
 
struct  pjsip_logger_session
 PJSIP Logging Session. More...
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
static int apply_method_filter (const struct pjsip_logger_session *session, const pjsip_method *method)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static void check_debug (void)
 
static void global_reloaded (const char *object_type)
 
static int load_module (void)
 
static pj_bool_t logging_on_rx_msg (pjsip_rx_data *rdata)
 
static pj_status_t logging_on_tx_msg (pjsip_tx_data *tdata)
 
static struct method_logging_infomethod_logging_info_alloc (const char *method)
 
static int method_logging_info_cmp (const struct method_logging_info *element, const struct method_logging_info *candidate)
 
static int method_logging_info_sort_cmp (const void *a, const void *b)
 
static char * pjsip_disable_logger (int fd)
 
static char * pjsip_enable_logger_all (int fd)
 
static char * pjsip_enable_logger_host (int fd, const char *arg, unsigned int add_host)
 
static char * pjsip_enable_logger_method (int fd, const char *arg, int add_method)
 Add the current or an additional method to match for filtering. More...
 
static int pjsip_log_test_filter (const struct pjsip_logger_session *session, const char *address, int port, const pjsip_method *method)
 See if we pass debug filter. More...
 
static struct pjsip_logger_sessionpjsip_logger_session_alloc (void)
 Allocator for logger session. More...
 
static void pjsip_logger_session_destroy (void *obj)
 Destructor for logger session. More...
 
static void pjsip_logger_write_to_pcap (struct pjsip_logger_session *session, const char *msg, size_t msg_len, pj_sockaddr *source, pj_sockaddr *destination)
 
static char * pjsip_set_logger (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * pjsip_set_logger_pcap (int fd, const char *arg)
 
static char * pjsip_set_logger_verbose (int fd, const char *arg)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "PJSIP Packet Logger" , .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", }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static struct ast_cli_entry cli_pjsip []
 
static struct pjsip_logger_sessiondefault_logger
 The default logger session. More...
 
static const struct ast_sorcery_observer global_observer
 
static pjsip_module logging_module
 

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 735 of file res_pjsip_logger.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 735 of file res_pjsip_logger.c.

◆ apply_method_filter()

static int apply_method_filter ( const struct pjsip_logger_session session,
const pjsip_method *  method 
)
static
Note
Must be called with the pjsip_logger_session lock held

Definition at line 166 of file res_pjsip_logger.c.

167{
168 size_t size = AST_VECTOR_SIZE(&session->log_methods);
169 size_t i;
170
171 if (size == 0) {
172 /* Nothing in the vector means everything matches */
173 return 0;
174 }
175
176 for (i = 0; i < size; ++i) {
177 struct method_logging_info *candidate = AST_VECTOR_GET(&session->log_methods, i);
178 if (pjsip_method_cmp(&candidate->method, method) == 0) {
179 return 0;
180 }
181 }
182
183 /* Nothing matched */
184 return 1;
185}
static struct ast_mansession session
const char * method
Definition: res_pjsip.c:1279
pjsip_method method
A PJSIP string for the method.
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:609
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:680

References AST_VECTOR_GET, AST_VECTOR_SIZE, method, method_logging_info::method, and session.

Referenced by pjsip_log_test_filter().

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 735 of file res_pjsip_logger.c.

◆ check_debug()

static void check_debug ( void  )
static

Definition at line 663 of file res_pjsip_logger.c.

664{
666
667 if (ast_false(debug)) {
669 return;
670 }
671
672 if (ast_true(debug)) {
674 return;
675 }
676
678 ast_log(LOG_WARNING, "Could not resolve host %s for debug "
679 "logging\n", debug);
680 }
681}
#define ast_free(a)
Definition: astmm.h:180
#define ast_log
Definition: astobj2.c:42
#define CLI_SUCCESS
Definition: cli.h:44
#define LOG_WARNING
char * ast_sip_get_debug(void)
Retrieve the system debug setting (yes|no|host).
static char * pjsip_enable_logger_all(int fd)
static char * pjsip_enable_logger_host(int fd, const char *arg, unsigned int add_host)
static char * pjsip_disable_logger(int fd)
static int debug
Global debug status.
Definition: res_xmpp.c:441
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
Definition: utils.c:2199
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is "false"....
Definition: utils.c:2216
#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

References ast_false(), ast_free, ast_log, ast_sip_get_debug(), ast_true(), CLI_SUCCESS, debug, LOG_WARNING, pjsip_disable_logger(), pjsip_enable_logger_all(), pjsip_enable_logger_host(), and RAII_VAR.

Referenced by global_reloaded(), and load_module().

◆ global_reloaded()

static void global_reloaded ( const char *  object_type)
static

Definition at line 683 of file res_pjsip_logger.c.

684{
685 check_debug();
686}
static void check_debug(void)

References check_debug().

◆ load_module()

static int load_module ( void  )
static

Definition at line 692 of file res_pjsip_logger.c.

693{
695 ast_log(LOG_WARNING, "Unable to add global observer\n");
697 }
698
700 if (!default_logger) {
703 ast_log(LOG_WARNING, "Unable to create default logger\n");
705 }
706
707 check_debug();
708
711
713}
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
int ast_sip_register_service(pjsip_module *module)
Register a SIP service in Asterisk.
Definition: res_pjsip.c:117
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
static struct ast_cli_entry cli_pjsip[]
static struct pjsip_logger_session * default_logger
The default logger session.
static pjsip_module logging_module
static struct pjsip_logger_session * pjsip_logger_session_alloc(void)
Allocator for logger session.
static const struct ast_sorcery_observer global_observer
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
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
#define ARRAY_LEN(a)
Definition: utils.h:666

References ARRAY_LEN, ast_cli_register_multiple, ast_log, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_sip_get_sorcery(), ast_sip_register_service(), ast_sorcery_observer_add(), ast_sorcery_observer_remove(), check_debug(), cli_pjsip, default_logger, global_observer, LOG_WARNING, logging_module, and pjsip_logger_session_alloc().

◆ logging_on_rx_msg()

static pj_bool_t logging_on_rx_msg ( pjsip_rx_data *  rdata)
static

Definition at line 338 of file res_pjsip_logger.c.

339{
340 char buffer[AST_SOCKADDR_BUFLEN];
341
342 if (!rdata->msg_info.msg) {
343 return PJ_FALSE;
344 }
345
347 if (!pjsip_log_test_filter(default_logger, rdata->pkt_info.src_name, rdata->pkt_info.src_port, &rdata->msg_info.msg->line.req.method)) {
349 return PJ_FALSE;
350 }
352
354 ast_verbose("<--- Received SIP %s (%d bytes) from %s:%s --->\n%s\n",
355 rdata->msg_info.msg->type == PJSIP_REQUEST_MSG ? "request" : "response",
356 rdata->msg_info.len,
357 rdata->tp_info.transport->type_name,
358 pj_sockaddr_print(&rdata->pkt_info.src_addr, buffer, sizeof(buffer), 3),
359 rdata->pkt_info.packet);
360 }
361
363 pjsip_logger_write_to_pcap(default_logger, rdata->pkt_info.packet, rdata->msg_info.len,
364 &rdata->pkt_info.src_addr, NULL);
365 }
366
367 return PJ_FALSE;
368}
#define ao2_rdlock(a)
Definition: astobj2.h:718
#define ao2_unlock(a)
Definition: astobj2.h:729
void ast_verbose(const char *fmt,...)
Definition: extconf.c:2206
#define AST_SOCKADDR_BUFLEN
Definition: netsock2.h:46
static void pjsip_logger_write_to_pcap(struct pjsip_logger_session *session, const char *msg, size_t msg_len, pj_sockaddr *source, pj_sockaddr *destination)
static int pjsip_log_test_filter(const struct pjsip_logger_session *session, const char *address, int port, const pjsip_method *method)
See if we pass debug filter.
#define NULL
Definition: resample.c:96
unsigned int log_to_verbose
Whether to log to verbose or not.
unsigned int log_to_pcap
Whether to log to pcap or not.

References ao2_rdlock, ao2_unlock, AST_SOCKADDR_BUFLEN, ast_verbose(), default_logger, pjsip_logger_session::log_to_pcap, pjsip_logger_session::log_to_verbose, NULL, pjsip_log_test_filter(), and pjsip_logger_write_to_pcap().

◆ logging_on_tx_msg()

static pj_status_t logging_on_tx_msg ( pjsip_tx_data *  tdata)
static

Definition at line 310 of file res_pjsip_logger.c.

311{
312 char buffer[AST_SOCKADDR_BUFLEN];
313
315 if (!pjsip_log_test_filter(default_logger, tdata->tp_info.dst_name, tdata->tp_info.dst_port, &tdata->msg->line.req.method)) {
317 return PJ_SUCCESS;
318 }
320
322 ast_verbose("<--- Transmitting SIP %s (%d bytes) to %s:%s --->\n%.*s\n",
323 tdata->msg->type == PJSIP_REQUEST_MSG ? "request" : "response",
324 (int) (tdata->buf.cur - tdata->buf.start),
325 tdata->tp_info.transport->type_name,
326 pj_sockaddr_print(&tdata->tp_info.dst_addr, buffer, sizeof(buffer), 3),
327 (int) (tdata->buf.end - tdata->buf.start), tdata->buf.start);
328 }
329
331 pjsip_logger_write_to_pcap(default_logger, tdata->buf.start, (int) (tdata->buf.cur - tdata->buf.start),
332 NULL, &tdata->tp_info.dst_addr);
333 }
334
335 return PJ_SUCCESS;
336}

References ao2_rdlock, ao2_unlock, AST_SOCKADDR_BUFLEN, ast_verbose(), default_logger, pjsip_logger_session::log_to_pcap, pjsip_logger_session::log_to_verbose, NULL, pjsip_log_test_filter(), and pjsip_logger_write_to_pcap().

◆ method_logging_info_alloc()

static struct method_logging_info * method_logging_info_alloc ( const char *  method)
static

Definition at line 438 of file res_pjsip_logger.c.

439{
440 size_t method_bytes = strlen(method);
442
443 info = ast_calloc(1, sizeof(struct method_logging_info) + method_bytes + 1);
444 if (!info) {
445 return NULL;
446 }
447
448 memcpy(info->name, method, method_bytes + 1);
449 pj_strset(&info->pj_name, info->name, method_bytes);
450 pjsip_method_init_np(&info->method, &info->pj_name);
451
452 return info;
453}
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
def info(msg)

References ast_calloc, sip_to_pjsip::info(), method, and NULL.

Referenced by pjsip_enable_logger_method().

◆ method_logging_info_cmp()

static int method_logging_info_cmp ( const struct method_logging_info element,
const struct method_logging_info candidate 
)
static

Definition at line 455 of file res_pjsip_logger.c.

457{
458 return pjsip_method_cmp(&element->method, &candidate->method) == 0
460 : 0;
461}
@ CMP_MATCH
Definition: astobj2.h:1027
@ CMP_STOP
Definition: astobj2.h:1028

References CMP_MATCH, CMP_STOP, and method_logging_info::method.

Referenced by pjsip_enable_logger_method().

◆ method_logging_info_sort_cmp()

static int method_logging_info_sort_cmp ( const void *  a,
const void *  b 
)
static

Definition at line 463 of file res_pjsip_logger.c.

464{
465 const struct method_logging_info *const *m_a = a;
466 const struct method_logging_info *const *m_b = b;
467 return strcasecmp((*m_a)->name, (*m_b)->name);
468}
static struct test_val b
static struct test_val a

References a, and b.

Referenced by pjsip_enable_logger_method().

◆ pjsip_disable_logger()

static char * pjsip_disable_logger ( int  fd)
static

Definition at line 525 of file res_pjsip_logger.c.

526{
528
529 /* Default the settings back to the way they were */
532 default_logger->pcap_filename[0] = '\0';
535
537
538 /* Stop logging to the PCAP file if active */
540 fclose(default_logger->pcap_file);
542 }
543
546
548
549 if (fd >= 0) {
550 ast_cli(fd, "PJSIP Logging disabled\n");
551 }
552
553 return CLI_SUCCESS;
554}
void ast_free_ha(struct ast_ha *ha)
Free a list of HAs.
Definition: acl.c:222
#define ao2_wrlock(a)
Definition: astobj2.h:719
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
struct ast_ha * matches
Explicit addresses or ranges being logged.
struct pjsip_logger_session::@459 log_methods
Vector of SIP methods to log.
unsigned int enabled
Whether the session is enabled or not.
unsigned int log_all_traffic
Whether the session is logging all traffic or not.
char pcap_filename[PATH_MAX]
Filename used for the pcap file.
FILE * pcap_file
The pcap file itself.
#define AST_VECTOR_RESET(vec, cleanup)
Reset vector.
Definition: vector.h:625

References ao2_unlock, ao2_wrlock, ast_cli(), ast_free, ast_free_ha(), AST_VECTOR_RESET, CLI_SUCCESS, default_logger, pjsip_logger_session::enabled, pjsip_logger_session::log_all_traffic, pjsip_logger_session::log_methods, pjsip_logger_session::log_to_pcap, pjsip_logger_session::log_to_verbose, pjsip_logger_session::matches, NULL, pjsip_logger_session::pcap_file, and pjsip_logger_session::pcap_filename.

Referenced by check_debug(), and pjsip_set_logger().

◆ pjsip_enable_logger_all()

static char * pjsip_enable_logger_all ( int  fd)
static

Definition at line 379 of file res_pjsip_logger.c.

380{
385
386 if (fd >= 0) {
387 ast_cli(fd, "PJSIP Logging enabled\n");
388 }
389
390 return CLI_SUCCESS;
391}

References ao2_unlock, ao2_wrlock, ast_cli(), CLI_SUCCESS, default_logger, pjsip_logger_session::enabled, and pjsip_logger_session::log_all_traffic.

Referenced by check_debug(), and pjsip_set_logger().

◆ pjsip_enable_logger_host()

static char * pjsip_enable_logger_host ( int  fd,
const char *  arg,
unsigned int  add_host 
)
static

Definition at line 393 of file res_pjsip_logger.c.

394{
395 const char *host = arg;
396 char *mask;
397 struct ast_sockaddr address;
398 int error = 0;
399
402
403 if (!add_host) {
404 /* If this is not adding an additional host or subnet then we have to
405 * remove what already exists.
406 */
409 }
410
411 mask = strrchr(host, '/');
412 if (!mask && !ast_sockaddr_parse(&address, arg, 0)) {
415 return CLI_SHOWUSAGE;
416 }
418 }
419
421 if (!default_logger->matches || error) {
422 if (fd >= 0) {
423 ast_cli(fd, "Failed to add address '%s' for logging\n", host);
424 }
426 return CLI_SUCCESS;
427 }
428
430
431 if (fd >= 0) {
432 ast_cli(fd, "PJSIP Logging Enabled for host: %s\n", ast_sockaddr_stringify_addr(&address));
433 }
434
435 return CLI_SUCCESS;
436}
struct ast_ha * ast_append_ha_with_port(const char *sense, const char *stuff, struct ast_ha *path, int *error)
Add a new rule with optional port to a list of HAs.
Definition: acl.c:717
#define CLI_SHOWUSAGE
Definition: cli.h:45
char * address
Definition: f2c.h:59
int ast_sockaddr_resolve_first_af(struct ast_sockaddr *addr, const char *name, int flag, int family)
Return the first entry from ast_sockaddr_resolve filtered by address family.
Definition: netsock2.c:337
@ AST_AF_UNSPEC
Definition: netsock2.h:54
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:256
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
Parse an IPv4 or IPv6 address string.
Definition: netsock2.c:230
static char * ast_sockaddr_stringify_addr(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() to return an address only.
Definition: netsock2.h:286
Socket address structure.
Definition: netsock2.h:97
int error(const char *format,...)
Definition: utils/frame.c:999

References ao2_unlock, ao2_wrlock, AST_AF_UNSPEC, ast_append_ha_with_port(), ast_cli(), ast_free_ha(), ast_sockaddr_parse(), ast_sockaddr_resolve_first_af(), ast_sockaddr_stringify(), ast_sockaddr_stringify_addr(), CLI_SHOWUSAGE, CLI_SUCCESS, default_logger, pjsip_logger_session::enabled, error(), pjsip_logger_session::matches, and NULL.

Referenced by check_debug(), and pjsip_set_logger().

◆ pjsip_enable_logger_method()

static char * pjsip_enable_logger_method ( int  fd,
const char *  arg,
int  add_method 
)
static

Add the current or an additional method to match for filtering.

Definition at line 471 of file res_pjsip_logger.c.

472{
473 struct ast_str *str;
475
477 if (!method) {
478 return CLI_FAILURE;
479 }
480
483
484 if (!add_method) {
485 /* Remove what already exists */
487 }
488
489 /* Already in the list? */
491 ast_cli(fd, "Method '%s' is already enabled\n", method->name);
494 return CLI_SUCCESS;
495 }
496
498 ast_log(LOG_ERROR, "Cannot register logger method '%s'. Unable to append.\n", method->name);
501 return CLI_SUCCESS;
502 }
503
505
506 str = ast_str_create(256);
507 if (str) {
508 size_t i;
509 for (i = 0; i < AST_VECTOR_SIZE(&default_logger->log_methods); i++) {
511 ast_str_append(&str, 0, "%s%.*s",
512 ast_str_strlen(str) ? ", " : "",
513 (int) method->pj_name.slen, method->pj_name.ptr);
514 }
515
516 ast_cli(fd, "PJSIP Logging Enabled for SIP Methods: %s\n", ast_str_buffer(str));
517 ast_free(str);
518 }
519
521
522 return CLI_SUCCESS;
523}
const char * str
Definition: app_jack.c:147
#define CLI_FAILURE
Definition: cli.h:46
#define LOG_ERROR
static struct method_logging_info * method_logging_info_alloc(const char *method)
static int method_logging_info_cmp(const struct method_logging_info *element, const struct method_logging_info *candidate)
static int method_logging_info_sort_cmp(const void *a, const void *b)
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:1139
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition: strings.h:730
Support for dynamic strings.
Definition: strings.h:623
#define AST_VECTOR_SORT(vec, cmp)
Sort a vector in-place.
Definition: vector.h:396
#define AST_VECTOR_CALLBACK(vec, callback, default_value,...)
Execute a callback on every element in a vector returning the first matched.
Definition: vector.h:765
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256

References ao2_unlock, ao2_wrlock, ast_cli(), ast_free, ast_log, ast_str_append(), ast_str_buffer(), ast_str_create, ast_str_strlen(), AST_VECTOR_APPEND, AST_VECTOR_CALLBACK, AST_VECTOR_GET, AST_VECTOR_RESET, AST_VECTOR_SIZE, AST_VECTOR_SORT, CLI_FAILURE, CLI_SUCCESS, default_logger, pjsip_logger_session::enabled, LOG_ERROR, pjsip_logger_session::log_methods, method, method_logging_info_alloc(), method_logging_info_cmp(), method_logging_info_sort_cmp(), NULL, and str.

Referenced by pjsip_set_logger().

◆ pjsip_log_test_filter()

static int pjsip_log_test_filter ( const struct pjsip_logger_session session,
const char *  address,
int  port,
const pjsip_method *  method 
)
inlinestatic

See if we pass debug filter.

Definition at line 188 of file res_pjsip_logger.c.

189{
190 struct ast_sockaddr test_addr;
191
192 if (!session->enabled) {
193 return 0;
194 }
195
196 if (session->log_all_traffic) {
197 return 1;
198 }
199
201 /* The method filter didn't match anything, so reject. */
202 return 0;
203 }
204
205 /* A null address was passed in or no explicit matches. Just reject it. */
206 if (ast_strlen_zero(address) || !session->matches) {
207 /* If we matched on method and host is empty, accept, otherwise reject. */
208 return AST_VECTOR_SIZE(&session->log_methods) > 0;
209 }
210
212 ast_sockaddr_set_port(&test_addr, port);
213
214 /* Compare the address against the matches */
215 if (ast_apply_ha(session->matches, &test_addr) != AST_SENSE_ALLOW) {
216 return 1;
217 } else {
218 return 0;
219 }
220}
@ AST_SENSE_ALLOW
Definition: acl.h:38
enum ast_acl_sense ast_apply_ha(const struct ast_ha *ha, const struct ast_sockaddr *addr)
Apply a set of rules to a given IP address.
Definition: acl.c:807
#define ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
Definition: netsock2.h:532
static int apply_method_filter(const struct pjsip_logger_session *session, const pjsip_method *method)
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65

References apply_method_filter(), ast_apply_ha(), AST_SENSE_ALLOW, ast_sockaddr_parse(), ast_sockaddr_set_port, ast_strlen_zero(), AST_VECTOR_SIZE, method, PARSE_PORT_IGNORE, and session.

Referenced by logging_on_rx_msg(), and logging_on_tx_msg().

◆ pjsip_logger_session_alloc()

static struct pjsip_logger_session * pjsip_logger_session_alloc ( void  )
static

Allocator for logger session.

Definition at line 148 of file res_pjsip_logger.c.

149{
151
154 if (!session) {
155 return NULL;
156 }
157
158 session->log_to_verbose = 1;
159
160 AST_VECTOR_INIT(&session->log_methods, 0);
161
162 return session;
163}
@ AO2_ALLOC_OPT_LOCK_RWLOCK
Definition: astobj2.h:365
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:404
static void pjsip_logger_session_destroy(void *obj)
Destructor for logger session.
PJSIP Logging Session.
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:113

References AO2_ALLOC_OPT_LOCK_RWLOCK, ao2_alloc_options, AST_VECTOR_INIT, NULL, pjsip_logger_session_destroy(), and session.

Referenced by load_module().

◆ pjsip_logger_session_destroy()

static void pjsip_logger_session_destroy ( void *  obj)
static

Destructor for logger session.

Definition at line 133 of file res_pjsip_logger.c.

134{
135 struct pjsip_logger_session *session = obj;
136
137 if (session->pcap_file) {
138 fclose(session->pcap_file);
139 }
140
141 ast_free_ha(session->matches);
142
143 AST_VECTOR_RESET(&session->log_methods, ast_free);
144 AST_VECTOR_FREE(&session->log_methods);
145}
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition: vector.h:174

References ast_free, ast_free_ha(), AST_VECTOR_FREE, AST_VECTOR_RESET, and session.

Referenced by pjsip_logger_session_alloc().

◆ pjsip_logger_write_to_pcap()

static void pjsip_logger_write_to_pcap ( struct pjsip_logger_session session,
const char *  msg,
size_t  msg_len,
pj_sockaddr *  source,
pj_sockaddr *  destination 
)
static

Definition at line 222 of file res_pjsip_logger.c.

224{
225 struct timeval now = ast_tvnow();
227 .ts_sec = now.tv_sec,
228 .ts_usec = now.tv_usec,
229 };
231 .type = 0,
232 };
234 .ver_ihl = 0x45, /* IPv4 + 20 bytes of header */
235 .ip_ttl = 128, /* We always put a TTL of 128 to keep Wireshark less blue */
236 };
238 .ip6_ctlun.ip6_un2_vfc = 0x60,
239 };
240 void *pcap_ip_header;
241 size_t pcap_ip_header_len;
243
244 /* Packets are always stored as UDP to simplify this logic */
245 if (source) {
246 pcap_udp_header.src = ntohs(pj_sockaddr_get_port(source));
247 } else {
248 pcap_udp_header.src = ntohs(0);
249 }
250 if (destination) {
251 pcap_udp_header.dst = ntohs(pj_sockaddr_get_port(destination));
252 } else {
253 pcap_udp_header.dst = ntohs(0);
254 }
255 pcap_udp_header.length = ntohs(sizeof(struct pcap_udp_header) + msg_len);
256
257 /* Construct the appropriate IP header */
258 if ((source && source->addr.sa_family == pj_AF_INET()) ||
259 (destination && destination->addr.sa_family == pj_AF_INET())) {
260 pcap_ethernet_header.type = htons(0x0800); /* We are providing an IPv4 packet */
261 pcap_ip_header = &pcap_ipv4_header;
262 pcap_ip_header_len = sizeof(struct pcap_ipv4_header);
263 if (source) {
264 memcpy(&pcap_ipv4_header.ip_src, pj_sockaddr_get_addr(source), pj_sockaddr_get_addr_len(source));
265 }
266 if (destination) {
267 memcpy(&pcap_ipv4_header.ip_dst, pj_sockaddr_get_addr(destination), pj_sockaddr_get_addr_len(destination));
268 }
269 pcap_ipv4_header.ip_len = htons(sizeof(struct pcap_udp_header) + sizeof(struct pcap_ipv4_header) + msg_len);
270 pcap_ipv4_header.ip_protocol = IPPROTO_UDP; /* We always provide UDP */
271 } else {
272 pcap_ethernet_header.type = htons(0x86DD); /* We are providing an IPv6 packet */
273 pcap_ip_header = &pcap_ipv6_header;
274 pcap_ip_header_len = sizeof(struct pcap_ipv6_header);
275 if (source) {
276 memcpy(&pcap_ipv6_header.ip6_src, pj_sockaddr_get_addr(source), pj_sockaddr_get_addr_len(source));
277 }
278 if (destination) {
279 memcpy(&pcap_ipv6_header.ip6_dst, pj_sockaddr_get_addr(destination), pj_sockaddr_get_addr_len(destination));
280 }
281 pcap_ipv6_header.ip6_ctlun.ip6_un1.ip6_un1_plen = htons(sizeof(struct pcap_udp_header) + msg_len);
282 pcap_ipv6_header.ip6_ctlun.ip6_un1.ip6_un1_nxt = IPPROTO_UDP;
283 }
284
285 /* Add up all the sizes for this record */
286 pcap_record_header.incl_len = pcap_record_header.orig_len = sizeof(pcap_ethernet_header) + pcap_ip_header_len + sizeof(pcap_udp_header) + msg_len;
287
288 /* We lock the logger session since we're writing these out in parts */
290 if (session->pcap_file) {
291 if (fwrite(&pcap_record_header, sizeof(struct pcap_record_header), 1, session->pcap_file) != 1) {
292 ast_log(LOG_WARNING, "Writing PCAP header failed: %s\n", strerror(errno));
293 }
294 if (fwrite(&pcap_ethernet_header, sizeof(struct pcap_ethernet_header), 1, session->pcap_file) != 1) {
295 ast_log(LOG_WARNING, "Writing ethernet header to pcap failed: %s\n", strerror(errno));
296 }
297 if (fwrite(pcap_ip_header, pcap_ip_header_len, 1, session->pcap_file) != 1) {
298 ast_log(LOG_WARNING, "Writing IP header to pcap failed: %s\n", strerror(errno));
299 }
300 if (fwrite(&pcap_udp_header, sizeof(struct pcap_udp_header), 1, session->pcap_file) != 1) {
301 ast_log(LOG_WARNING, "Writing UDP header to pcap failed: %s\n", strerror(errno));
302 }
303 if (fwrite(msg, msg_len, 1, session->pcap_file) != 1) {
304 ast_log(LOG_WARNING, "Writing UDP payload to pcap failed: %s\n", strerror(errno));
305 }
306 }
308}
int errno
PCAP Ethernet Header.
uint16_t type
Source MAD address.
PCAP IPv4 Header.
uint32_t ip_dst
Source IP address.
uint8_t ip_protocol
Time to live for the packet.
uint32_t ip_src
Checksum (not calculated for our purposes.
uint16_t ip_len
Type of service details.
PCAP IPv6 Header.
struct pcap_ipv6_header::@458::ip6_hdrctl ip6_un1
struct in6_addr ip6_dst
Source IP address.
struct in6_addr ip6_src
union pcap_ipv6_header::@458 ip6_ctlun
PCAP Packet Record Header.
uint32_t orig_len
Length of packet as saved in the file.
uint32_t incl_len
When the record was created.
PCAP UDP Header.
uint16_t length
Destination IP port.
uint16_t dst
Source IP port.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159

References ao2_unlock, ao2_wrlock, ast_log, ast_tvnow(), pcap_udp_header::dst, errno, pcap_record_header::incl_len, pcap_ipv6_header::ip6_ctlun, pcap_ipv6_header::ip6_dst, pcap_ipv6_header::ip6_src, pcap_ipv6_header::ip6_un1, pcap_ipv6_header::ip6_un2_vfc, pcap_ipv4_header::ip_dst, pcap_ipv4_header::ip_len, pcap_ipv4_header::ip_protocol, pcap_ipv4_header::ip_src, pcap_udp_header::length, LOG_WARNING, pcap_record_header::orig_len, session, pcap_udp_header::src, pcap_record_header::ts_sec, pcap_ethernet_header::type, and pcap_ipv4_header::ver_ihl.

Referenced by logging_on_rx_msg(), and logging_on_tx_msg().

◆ pjsip_set_logger()

static char * pjsip_set_logger ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 601 of file res_pjsip_logger.c.

602{
603 static const char * const method_choices[] = {
604 "INVITE", "CANCEL", "ACK",
605 "BYE", "REGISTER", "OPTION",
606 "SUBSCRIBE", "NOTIFY", "PUBLISH",
607 "INFO", "MESSAGE",
608 NULL
609 };
610
611 const char *what;
612
613 if (cmd == CLI_INIT) {
614 e->command = "pjsip set logger {on|off|host|add|method|methodadd|verbose|pcap}";
615 e->usage =
616 "Usage: pjsip set logger {on|off|host <name/subnet>|add <name/subnet>|method <method>|methodadd <method>|verbose <on/off>|pcap <filename>}\n"
617 " Enables or disabling logging of SIP packets\n"
618 " read on ports bound to PJSIP transports either\n"
619 " globally or enables logging for an individual\n"
620 " host or particular SIP method(s).\n"
621 " Messages can be filtered by SIP request methods\n"
622 " INVITE, CANCEL, ACK, BYE, REGISTER, OPTION\n"
623 " SUBSCRIBE, NOTIFY, PUBLISH, INFO, and MESSAGE\n";
624 return NULL;
625 } else if (cmd == CLI_GENERATE) {
626 if (a->argc && !strncasecmp(a->argv[e->args - 1], "method", 6)) {
627 return ast_cli_complete(a->word, method_choices, a->n);
628 }
629 return NULL;
630 }
631
632 what = a->argv[e->args - 1]; /* Guaranteed to exist */
633
634 if (a->argc == e->args) { /* on/off */
635 if (!strcasecmp(what, "on")) {
636 return pjsip_enable_logger_all(a->fd);
637 } else if (!strcasecmp(what, "off")) {
638 return pjsip_disable_logger(a->fd);
639 }
640 } else if (a->argc == e->args + 1) {
641 if (!strcasecmp(what, "host")) {
642 return pjsip_enable_logger_host(a->fd, a->argv[e->args], 0);
643 } else if (!strcasecmp(what, "add")) {
644 return pjsip_enable_logger_host(a->fd, a->argv[e->args], 1);
645 } else if (!strcasecmp(what, "method")) {
646 return pjsip_enable_logger_method(a->fd, a->argv[e->args], 0);
647 } else if (!strcasecmp(what, "methodadd")) {
648 return pjsip_enable_logger_method(a->fd, a->argv[e->args], 1);
649 } else if (!strcasecmp(what, "verbose")) {
650 return pjsip_set_logger_verbose(a->fd, a->argv[e->args]);
651 } else if (!strcasecmp(what, "pcap")) {
652 return pjsip_set_logger_pcap(a->fd, a->argv[e->args]);
653 }
654 }
655
656 return CLI_SHOWUSAGE;
657}
char * ast_cli_complete(const char *word, const char *const choices[], int pos)
Definition: main/cli.c:1843
@ CLI_INIT
Definition: cli.h:152
@ CLI_GENERATE
Definition: cli.h:153
static char * pjsip_enable_logger_method(int fd, const char *arg, int add_method)
Add the current or an additional method to match for filtering.
static char * pjsip_set_logger_verbose(int fd, const char *arg)
static char * pjsip_set_logger_pcap(int fd, const char *arg)
int args
This gets set in ast_cli_register()
Definition: cli.h:185
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177

References a, ast_cli_entry::args, ast_cli_complete(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, ast_cli_entry::command, NULL, pjsip_disable_logger(), pjsip_enable_logger_all(), pjsip_enable_logger_host(), pjsip_enable_logger_method(), pjsip_set_logger_pcap(), pjsip_set_logger_verbose(), and ast_cli_entry::usage.

◆ pjsip_set_logger_pcap()

static char * pjsip_set_logger_pcap ( int  fd,
const char *  arg 
)
static

Definition at line 567 of file res_pjsip_logger.c.

568{
569 struct pcap_header pcap_header = {
570 .magic_number = 0xa1b2c3d4,
571 .version_major = 2,
572 .version_minor = 4,
573 .snaplen = 65535,
574 .network = 1, /* We always use ethernet so we can combine IPv4 and IPv6 in same pcap */
575 };
576
579
581 fclose(default_logger->pcap_file);
583 }
584
585 default_logger->pcap_file = fopen(arg, "wb");
588 ast_cli(fd, "Failed to open file '%s' for pcap writing\n", arg);
589 return CLI_SUCCESS;
590 }
591 fwrite(&pcap_header, 1, sizeof(struct pcap_header), default_logger->pcap_file);
592
595
596 ast_cli(fd, "PJSIP logging to pcap file '%s'\n", arg);
597
598 return CLI_SUCCESS;
599}
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
PCAP Header.
uint32_t magic_number

References ao2_unlock, ao2_wrlock, ast_cli(), ast_copy_string(), CLI_SUCCESS, default_logger, pjsip_logger_session::log_to_pcap, pcap_header::magic_number, NULL, pjsip_logger_session::pcap_file, and pjsip_logger_session::pcap_filename.

Referenced by pjsip_set_logger().

◆ pjsip_set_logger_verbose()

static char * pjsip_set_logger_verbose ( int  fd,
const char *  arg 
)
static

Definition at line 556 of file res_pjsip_logger.c.

557{
561
562 ast_cli(fd, "PJSIP Logging to verbose has been %s\n", ast_true(arg) ? "enabled" : "disabled");
563
564 return CLI_SUCCESS;
565}

References ao2_unlock, ao2_wrlock, ast_cli(), ast_true(), CLI_SUCCESS, default_logger, and pjsip_logger_session::log_to_verbose.

Referenced by pjsip_set_logger().

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 715 of file res_pjsip_logger.c.

716{
719
722
725
726 return 0;
727}
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
void ast_sip_unregister_service(pjsip_module *module)
Definition: res_pjsip.c:133

References ao2_cleanup, ARRAY_LEN, ast_cli_unregister_multiple(), ast_sip_get_sorcery(), ast_sip_unregister_service(), ast_sorcery_observer_remove(), cli_pjsip, default_logger, global_observer, logging_module, and NULL.

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "PJSIP Packet Logger" , .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", }
static

Definition at line 735 of file res_pjsip_logger.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 735 of file res_pjsip_logger.c.

◆ cli_pjsip

struct ast_cli_entry cli_pjsip[]
static
Initial value:
= {
{ .handler = pjsip_set_logger , .summary = "Enable/Disable PJSIP Logger Output" ,}
}
static char * pjsip_set_logger(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)

Definition at line 659 of file res_pjsip_logger.c.

Referenced by load_module(), and unload_module().

◆ default_logger

struct pjsip_logger_session* default_logger
static

◆ global_observer

const struct ast_sorcery_observer global_observer
static
Initial value:
= {
.loaded = global_reloaded
}
static void global_reloaded(const char *object_type)

Definition at line 688 of file res_pjsip_logger.c.

Referenced by load_module(), and unload_module().

◆ logging_module

pjsip_module logging_module
static

Definition at line 370 of file res_pjsip_logger.c.

Referenced by load_module(), and unload_module().