Asterisk - The Open Source Telephony Project GIT-master-f3e88d3
Data Structures | Enumerations | 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...
 

Enumerations

enum  pjsip_logger_mask {
  AST_PJSIP_LOGGER_UNSET = 0 , AST_PJSIP_LOGGER_NONE = (1 << 0) , AST_PJSIP_LOGGER_HOST = (1 << 1) , AST_PJSIP_LOGGER_METHOD = (1 << 2) ,
  AST_PJSIP_LOGGER_VERBOSE = (1 << 3) , AST_PJSIP_LOGGER_PCAP = (1 << 4) , AST_PJSIP_LOGGER_ALL = (1 << 5)
}
 

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 enum pjsip_logger_mask logger_cli_settings = AST_PJSIP_LOGGER_UNSET
 
static enum pjsip_logger_mask logger_config_settings = AST_PJSIP_LOGGER_UNSET
 
static pjsip_module logging_module
 

Enumeration Type Documentation

◆ pjsip_logger_mask

Enumerator
AST_PJSIP_LOGGER_UNSET 
AST_PJSIP_LOGGER_NONE 
AST_PJSIP_LOGGER_HOST 
AST_PJSIP_LOGGER_METHOD 
AST_PJSIP_LOGGER_VERBOSE 
AST_PJSIP_LOGGER_PCAP 
AST_PJSIP_LOGGER_ALL 

Definition at line 601 of file res_pjsip_logger.c.

601 {
603 AST_PJSIP_LOGGER_NONE = (1 << 0),
604 AST_PJSIP_LOGGER_HOST = (1 << 1),
605 AST_PJSIP_LOGGER_METHOD = (1 << 2),
606 AST_PJSIP_LOGGER_VERBOSE = (1 << 3),
607 AST_PJSIP_LOGGER_PCAP = (1 << 4),
608 AST_PJSIP_LOGGER_ALL = (1 << 5),
609};
@ AST_PJSIP_LOGGER_VERBOSE
@ AST_PJSIP_LOGGER_UNSET
@ AST_PJSIP_LOGGER_ALL
@ AST_PJSIP_LOGGER_NONE
@ AST_PJSIP_LOGGER_METHOD
@ AST_PJSIP_LOGGER_HOST
@ AST_PJSIP_LOGGER_PCAP

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 781 of file res_pjsip_logger.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 781 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 781 of file res_pjsip_logger.c.

◆ check_debug()

static void check_debug ( void  )
static

Definition at line 684 of file res_pjsip_logger.c.

685{
687
688 /* Got directive to disable debug */
689 if (ast_false(debug)) {
690 /* If the logger was enabled via the CLI instead of through the config file,
691 * then we shouldn't disable it on a reload.
692 * Only disable logging if logging isn't enabled via the CLI. */
694 /* Logger not enabled via CLI currently so good to go ahead and disable. */
696 } else {
697 ast_debug(3, "Leaving logger enabled since logging settings overridden using CLI\n");
698 }
700 return;
701 }
702
703 /* Got directive to enable debug */
704 if (ast_true(debug)) {
706 /* Logging was modified using the CLI command,
707 * and this overrides the default from the config. */
708 ast_debug(3, "Leaving logger alone since logging has been overridden using CLI\n");
709 return;
710 }
711 /* If logger already enabled via config, then nothing has changed. */
713 /* Logging was not previously enabled via config,
714 * but has been enabled via CLI. */
717 }
718 return;
719 }
720
721 /* Enabling debug, only for specific host */
724 ast_log(LOG_WARNING, "Could not resolve host %s for debug "
725 "logging\n", debug);
726 }
727}
#define ast_free(a)
Definition: astmm.h:180
#define ast_log
Definition: astobj2.c:42
#define CLI_SUCCESS
Definition: cli.h:44
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_WARNING
char * ast_sip_get_debug(void)
Retrieve the system debug setting (yes|no|host).
static enum pjsip_logger_mask logger_config_settings
static enum pjsip_logger_mask logger_cli_settings
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_debug, ast_false(), ast_free, ast_log, AST_PJSIP_LOGGER_ALL, AST_PJSIP_LOGGER_HOST, AST_PJSIP_LOGGER_NONE, AST_PJSIP_LOGGER_UNSET, ast_sip_get_debug(), ast_true(), CLI_SUCCESS, debug, LOG_WARNING, logger_cli_settings, logger_config_settings, 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 729 of file res_pjsip_logger.c.

730{
731 check_debug();
732}
static void check_debug(void)

References check_debug().

◆ load_module()

static int load_module ( void  )
static

Definition at line 738 of file res_pjsip_logger.c.

739{
741 ast_log(LOG_WARNING, "Unable to add global observer\n");
743 }
744
746 if (!default_logger) {
749 ast_log(LOG_WARNING, "Unable to create default logger\n");
751 }
752
753 check_debug();
754
757
759}
#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:2423
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:2391
#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 614 of file res_pjsip_logger.c.

615{
616 static const char * const method_choices[] = {
617 "INVITE", "CANCEL", "ACK",
618 "BYE", "REGISTER", "OPTION",
619 "SUBSCRIBE", "NOTIFY", "PUBLISH",
620 "INFO", "MESSAGE",
621 NULL
622 };
623
624 const char *what;
625
626 if (cmd == CLI_INIT) {
627 e->command = "pjsip set logger {on|off|host|add|method|methodadd|verbose|pcap}";
628 e->usage =
629 "Usage: pjsip set logger {on|off|host <name/subnet>|add <name/subnet>|method <method>|methodadd <method>|verbose <on/off>|pcap <filename>}\n"
630 " Enables or disabling logging of SIP packets\n"
631 " read on ports bound to PJSIP transports either\n"
632 " globally or enables logging for an individual\n"
633 " host or particular SIP method(s).\n"
634 " Messages can be filtered by SIP request methods\n"
635 " INVITE, CANCEL, ACK, BYE, REGISTER, OPTION\n"
636 " SUBSCRIBE, NOTIFY, PUBLISH, INFO, and MESSAGE\n";
637 return NULL;
638 } else if (cmd == CLI_GENERATE) {
639 if (a->argc && !strncasecmp(a->argv[e->args - 1], "method", 6)) {
640 return ast_cli_complete(a->word, method_choices, a->n);
641 }
642 return NULL;
643 }
644
645 what = a->argv[e->args - 1]; /* Guaranteed to exist */
646
647 if (a->argc == e->args) { /* on/off */
648 if (!strcasecmp(what, "on")) {
650 return pjsip_enable_logger_all(a->fd);
651 } else if (!strcasecmp(what, "off")) {
653 return pjsip_disable_logger(a->fd);
654 }
655 } else if (a->argc == e->args + 1) {
656 if (!strcasecmp(what, "host")) {
658 return pjsip_enable_logger_host(a->fd, a->argv[e->args], 0);
659 } else if (!strcasecmp(what, "add")) {
661 return pjsip_enable_logger_host(a->fd, a->argv[e->args], 1);
662 } else if (!strcasecmp(what, "method")) {
664 return pjsip_enable_logger_method(a->fd, a->argv[e->args], 0);
665 } else if (!strcasecmp(what, "methodadd")) {
667 return pjsip_enable_logger_method(a->fd, a->argv[e->args], 1);
668 } else if (!strcasecmp(what, "verbose")) {
670 return pjsip_set_logger_verbose(a->fd, a->argv[e->args]);
671 } else if (!strcasecmp(what, "pcap")) {
673 return pjsip_set_logger_pcap(a->fd, a->argv[e->args]);
674 }
675 }
676
677 return CLI_SHOWUSAGE;
678}
char * ast_cli_complete(const char *word, const char *const choices[], int pos)
Definition: main/cli.c:1846
@ 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(), AST_PJSIP_LOGGER_ALL, AST_PJSIP_LOGGER_HOST, AST_PJSIP_LOGGER_METHOD, AST_PJSIP_LOGGER_NONE, AST_PJSIP_LOGGER_PCAP, AST_PJSIP_LOGGER_VERBOSE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, ast_cli_entry::command, logger_cli_settings, 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 761 of file res_pjsip_logger.c.

762{
765
768
771
772 return 0;
773}
#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 781 of file res_pjsip_logger.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 781 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 680 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 734 of file res_pjsip_logger.c.

Referenced by load_module(), and unload_module().

◆ logger_cli_settings

enum pjsip_logger_mask logger_cli_settings = AST_PJSIP_LOGGER_UNSET
static

Definition at line 611 of file res_pjsip_logger.c.

Referenced by check_debug(), and pjsip_set_logger().

◆ logger_config_settings

enum pjsip_logger_mask logger_config_settings = AST_PJSIP_LOGGER_UNSET
static

Definition at line 612 of file res_pjsip_logger.c.

Referenced by check_debug().

◆ logging_module

pjsip_module logging_module
static

Definition at line 370 of file res_pjsip_logger.c.

Referenced by load_module(), and unload_module().