Asterisk - The Open Source Telephony Project  18.5.0
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/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  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)
 
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 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 int pjsip_log_test_addr (const struct pjsip_logger_session *session, const char *address, int port)
 See if we pass debug IP 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 = "30ef0c93b36035ec78c9cfd712d36d9b" , .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 586 of file res_pjsip_logger.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 586 of file res_pjsip_logger.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 586 of file res_pjsip_logger.c.

◆ check_debug()

static void check_debug ( void  )
static

Definition at line 514 of file res_pjsip_logger.c.

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().

515 {
517 
518  if (ast_false(debug)) {
520  return;
521  }
522 
523  if (ast_true(debug)) {
525  return;
526  }
527 
528  if (pjsip_enable_logger_host(-1, debug, 0) != CLI_SUCCESS) {
529  ast_log(LOG_WARNING, "Could not resolve host %s for debug "
530  "logging\n", debug);
531  }
532 }
#define LOG_WARNING
Definition: logger.h:274
static int debug
Global debug status.
Definition: res_xmpp.c:435
char * ast_sip_get_debug(void)
Retrieve the system debug setting (yes|no|host).
static char * pjsip_disable_logger(int fd)
#define ast_log
Definition: astobj2.c:42
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
Definition: main/utils.c:1951
static char * pjsip_enable_logger_all(int fd)
#define ast_free(a)
Definition: astmm.h:182
static char * pjsip_enable_logger_host(int fd, const char *arg, unsigned int add_host)
#define CLI_SUCCESS
Definition: cli.h:44
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is "false"...
Definition: main/utils.c:1968

◆ global_reloaded()

static void global_reloaded ( const char *  object_type)
static

Definition at line 534 of file res_pjsip_logger.c.

References check_debug().

535 {
536  check_debug();
537 }
static void check_debug(void)

◆ load_module()

static int load_module ( void  )
static

Definition at line 543 of file res_pjsip_logger.c.

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(), LOG_WARNING, and pjsip_logger_session_alloc().

Referenced by unload_module().

544 {
546  ast_log(LOG_WARNING, "Unable to add global observer\n");
548  }
549 
551  if (!default_logger) {
553  ast_sip_get_sorcery(), "global", &global_observer);
554  ast_log(LOG_WARNING, "Unable to create default logger\n");
556  }
557 
558  check_debug();
559 
562 
564 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static void check_debug(void)
#define LOG_WARNING
Definition: logger.h:274
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
static const struct ast_sorcery_observer global_observer
#define ast_log
Definition: astobj2.c:42
static pjsip_module logging_module
int ast_sip_register_service(pjsip_module *module)
Register a SIP service in Asterisk.
Definition: res_pjsip.c:3315
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
static struct pjsip_logger_session * pjsip_logger_session_alloc(void)
Allocator for logger session.
static struct ast_cli_entry cli_pjsip[]
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
static struct pjsip_logger_session * default_logger
The default logger session.
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
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.

◆ logging_on_rx_msg()

static pj_bool_t logging_on_rx_msg ( pjsip_rx_data *  rdata)
static

Definition at line 296 of file res_pjsip_logger.c.

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

297 {
298  char buffer[AST_SOCKADDR_BUFLEN];
299 
300  if (!rdata->msg_info.msg) {
301  return PJ_FALSE;
302  }
303 
305  if (!pjsip_log_test_addr(default_logger, rdata->pkt_info.src_name, rdata->pkt_info.src_port)) {
307  return PJ_FALSE;
308  }
310 
312  ast_verbose("<--- Received SIP %s (%d bytes) from %s:%s --->\n%s\n",
313  rdata->msg_info.msg->type == PJSIP_REQUEST_MSG ? "request" : "response",
314  rdata->msg_info.len,
315  rdata->tp_info.transport->type_name,
316  pj_sockaddr_print(&rdata->pkt_info.src_addr, buffer, sizeof(buffer), 3),
317  rdata->pkt_info.packet);
318  }
319 
321  pjsip_logger_write_to_pcap(default_logger, rdata->pkt_info.packet, rdata->msg_info.len,
322  &rdata->pkt_info.src_addr, NULL);
323  }
324 
325  return PJ_FALSE;
326 }
#define AST_SOCKADDR_BUFLEN
Definition: netsock2.h:46
unsigned int log_to_verbose
Whether to log to verbose or not.
#define ao2_unlock(a)
Definition: astobj2.h:730
void ast_verbose(const char *fmt,...)
Definition: extconf.c:2207
#define NULL
Definition: resample.c:96
unsigned int log_to_pcap
Whether to log to pcap or not.
#define ao2_rdlock(a)
Definition: astobj2.h:719
static struct pjsip_logger_session * default_logger
The default logger session.
static int pjsip_log_test_addr(const struct pjsip_logger_session *session, const char *address, int port)
See if we pass debug IP filter.
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)

◆ logging_on_tx_msg()

static pj_status_t logging_on_tx_msg ( pjsip_tx_data *  tdata)
static

Definition at line 268 of file res_pjsip_logger.c.

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

269 {
270  char buffer[AST_SOCKADDR_BUFLEN];
271 
273  if (!pjsip_log_test_addr(default_logger, tdata->tp_info.dst_name, tdata->tp_info.dst_port)) {
275  return PJ_SUCCESS;
276  }
278 
280  ast_verbose("<--- Transmitting SIP %s (%d bytes) to %s:%s --->\n%.*s\n",
281  tdata->msg->type == PJSIP_REQUEST_MSG ? "request" : "response",
282  (int) (tdata->buf.cur - tdata->buf.start),
283  tdata->tp_info.transport->type_name,
284  pj_sockaddr_print(&tdata->tp_info.dst_addr, buffer, sizeof(buffer), 3),
285  (int) (tdata->buf.end - tdata->buf.start), tdata->buf.start);
286  }
287 
289  pjsip_logger_write_to_pcap(default_logger, tdata->buf.start, (int) (tdata->buf.cur - tdata->buf.start),
290  NULL, &tdata->tp_info.dst_addr);
291  }
292 
293  return PJ_SUCCESS;
294 }
#define AST_SOCKADDR_BUFLEN
Definition: netsock2.h:46
unsigned int log_to_verbose
Whether to log to verbose or not.
#define ao2_unlock(a)
Definition: astobj2.h:730
void ast_verbose(const char *fmt,...)
Definition: extconf.c:2207
#define NULL
Definition: resample.c:96
unsigned int log_to_pcap
Whether to log to pcap or not.
#define ao2_rdlock(a)
Definition: astobj2.h:719
static struct pjsip_logger_session * default_logger
The default logger session.
static int pjsip_log_test_addr(const struct pjsip_logger_session *session, const char *address, int port)
See if we pass debug IP filter.
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)

◆ pjsip_disable_logger()

static char* pjsip_disable_logger ( int  fd)
static

Definition at line 396 of file res_pjsip_logger.c.

References ao2_unlock, ao2_wrlock, ast_cli(), ast_free_ha(), CLI_SUCCESS, pjsip_logger_session::enabled, pjsip_logger_session::log_all_traffic, 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().

397 {
399 
400  /* Default the settings back to the way they were */
401  default_logger->enabled = 0;
403  default_logger->pcap_filename[0] = '\0';
406 
407  /* Stop logging to the PCAP file if active */
408  if (default_logger->pcap_file) {
409  fclose(default_logger->pcap_file);
411  }
412 
415 
417 
418  if (fd >= 0) {
419  ast_cli(fd, "PJSIP Logging disabled\n");
420  }
421 
422  return CLI_SUCCESS;
423 }
char pcap_filename[PATH_MAX]
Filename used for the pcap file.
unsigned int log_to_verbose
Whether to log to verbose or not.
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
#define ao2_wrlock(a)
Definition: astobj2.h:720
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
unsigned int log_to_pcap
Whether to log to pcap or not.
void ast_free_ha(struct ast_ha *ha)
Free a list of HAs.
Definition: acl.c:222
#define CLI_SUCCESS
Definition: cli.h:44
static struct pjsip_logger_session * default_logger
The default logger session.
FILE * pcap_file
The pcap file itself.
unsigned int enabled
Whether the session is enabled or not.
unsigned int log_all_traffic
Whether the session is logging all traffic or not.
struct ast_ha * matches
Explicit addresses or ranges being logged.

◆ pjsip_enable_logger_all()

static char* pjsip_enable_logger_all ( int  fd)
static

Definition at line 337 of file res_pjsip_logger.c.

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

Referenced by check_debug(), and pjsip_set_logger().

338 {
340  default_logger->enabled = 1;
343 
344  if (fd >= 0) {
345  ast_cli(fd, "PJSIP Logging enabled\n");
346  }
347 
348  return CLI_SUCCESS;
349 }
#define ao2_unlock(a)
Definition: astobj2.h:730
#define ao2_wrlock(a)
Definition: astobj2.h:720
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
#define CLI_SUCCESS
Definition: cli.h:44
static struct pjsip_logger_session * default_logger
The default logger session.
unsigned int enabled
Whether the session is enabled or not.
unsigned int log_all_traffic
Whether the session is logging all traffic or not.

◆ pjsip_enable_logger_host()

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

Definition at line 351 of file res_pjsip_logger.c.

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, pjsip_logger_session::enabled, error(), host, pjsip_logger_session::matches, and NULL.

Referenced by check_debug(), and pjsip_set_logger().

352 {
353  const char *host = arg;
354  char *mask;
355  struct ast_sockaddr address;
356  int error = 0;
357 
359  default_logger->enabled = 1;
360 
361  if (!add_host) {
362  /* If this is not adding an additional host or subnet then we have to
363  * remove what already exists.
364  */
367  }
368 
369  mask = strrchr(host, '/');
370  if (!mask && !ast_sockaddr_parse(&address, arg, 0)) {
373  return CLI_SHOWUSAGE;
374  }
376  }
377 
379  if (!default_logger->matches || error) {
380  if (fd >= 0) {
381  ast_cli(fd, "Failed to add address '%s' for logging\n", host);
382  }
384  return CLI_SUCCESS;
385  }
386 
388 
389  if (fd >= 0) {
390  ast_cli(fd, "PJSIP Logging Enabled for host: %s\n", ast_sockaddr_stringify_addr(&address));
391  }
392 
393  return CLI_SUCCESS;
394 }
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:290
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
Parse an IPv4 or IPv6 address string.
Definition: netsock2.c:230
char * address
Definition: f2c.h:59
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
#define ao2_wrlock(a)
Definition: astobj2.h:720
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
Socket address structure.
Definition: netsock2.h:97
static char host[256]
Definition: muted.c:77
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
#define CLI_SHOWUSAGE
Definition: cli.h:45
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:260
void ast_free_ha(struct ast_ha *ha)
Free a list of HAs.
Definition: acl.c:222
#define CLI_SUCCESS
Definition: cli.h:44
static struct pjsip_logger_session * default_logger
The default logger session.
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:718
unsigned int enabled
Whether the session is enabled or not.
struct ast_ha * matches
Explicit addresses or ranges being logged.
int error(const char *format,...)
Definition: utils/frame.c:999

◆ pjsip_log_test_addr()

static int pjsip_log_test_addr ( const struct pjsip_logger_session session,
const char *  address,
int  port 
)
inlinestatic

See if we pass debug IP filter.

Definition at line 152 of file res_pjsip_logger.c.

References ast_apply_ha(), AST_SENSE_ALLOW, ast_sockaddr_parse(), ast_sockaddr_set_port, ast_strlen_zero, pjsip_logger_session::enabled, pjsip_logger_session::log_all_traffic, pjsip_logger_session::matches, and PARSE_PORT_IGNORE.

Referenced by logging_on_rx_msg(), and logging_on_tx_msg().

153 {
154  struct ast_sockaddr test_addr;
155 
156  if (!session->enabled) {
157  return 0;
158  }
159 
160  if (session->log_all_traffic) {
161  return 1;
162  }
163 
164  /* A null address was passed in or no explicit matches. Just reject it. */
165  if (ast_strlen_zero(address) || !session->matches) {
166  return 0;
167  }
168 
170  ast_sockaddr_set_port(&test_addr, port);
171 
172  /* Compare the address against the matches */
173  if (ast_apply_ha(session->matches, &test_addr) != AST_SENSE_ALLOW) {
174  return 1;
175  } else {
176  return 0;
177  }
178 }
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
Parse an IPv4 or IPv6 address string.
Definition: netsock2.c:230
char * address
Definition: f2c.h:59
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:808
Socket address structure.
Definition: netsock2.h:97
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
Definition: netsock2.h:537
unsigned int enabled
Whether the session is enabled or not.
unsigned int log_all_traffic
Whether the session is logging all traffic or not.
struct ast_ha * matches
Explicit addresses or ranges being logged.

◆ pjsip_logger_session_alloc()

static struct pjsip_logger_session* pjsip_logger_session_alloc ( void  )
static

Allocator for logger session.

Definition at line 136 of file res_pjsip_logger.c.

References AO2_ALLOC_OPT_LOCK_RWLOCK, ao2_alloc_options, pjsip_logger_session::log_to_verbose, NULL, pjsip_logger_session_destroy(), and session.

Referenced by load_module().

137 {
139 
142  if (!session) {
143  return NULL;
144  }
145 
146  session->log_to_verbose = 1;
147 
148  return session;
149 }
unsigned int log_to_verbose
Whether to log to verbose or not.
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:406
#define NULL
Definition: resample.c:96
PJSIP Logging Session.
static void pjsip_logger_session_destroy(void *obj)
Destructor for logger session.
static struct ast_mansession session

◆ pjsip_logger_session_destroy()

static void pjsip_logger_session_destroy ( void *  obj)
static

Destructor for logger session.

Definition at line 124 of file res_pjsip_logger.c.

References ast_free_ha(), pjsip_logger_session::matches, pjsip_logger_session::pcap_file, and session.

Referenced by pjsip_logger_session_alloc().

125 {
126  struct pjsip_logger_session *session = obj;
127 
128  if (session->pcap_file) {
129  fclose(session->pcap_file);
130  }
131 
132  ast_free_ha(session->matches);
133 }
PJSIP Logging Session.
static struct ast_mansession session
void ast_free_ha(struct ast_ha *ha)
Free a list of HAs.
Definition: acl.c:222
FILE * pcap_file
The pcap file itself.
struct ast_ha * matches
Explicit addresses or ranges being logged.

◆ 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 180 of file res_pjsip_logger.c.

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, pjsip_logger_session::pcap_file, 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().

182 {
183  struct timeval now = ast_tvnow();
185  .ts_sec = now.tv_sec,
186  .ts_usec = now.tv_usec,
187  };
189  .type = 0,
190  };
192  .ver_ihl = 0x45, /* IPv4 + 20 bytes of header */
193  .ip_ttl = 128, /* We always put a TTL of 128 to keep Wireshark less blue */
194  };
196  .ip6_ctlun.ip6_un2_vfc = 0x60,
197  };
198  void *pcap_ip_header;
199  size_t pcap_ip_header_len;
201 
202  /* Packets are always stored as UDP to simplify this logic */
203  if (source) {
204  pcap_udp_header.src = ntohs(pj_sockaddr_get_port(source));
205  } else {
206  pcap_udp_header.src = ntohs(0);
207  }
208  if (destination) {
209  pcap_udp_header.dst = ntohs(pj_sockaddr_get_port(destination));
210  } else {
211  pcap_udp_header.dst = ntohs(0);
212  }
213  pcap_udp_header.length = ntohs(sizeof(struct pcap_udp_header) + msg_len);
214 
215  /* Construct the appropriate IP header */
216  if ((source && source->addr.sa_family == pj_AF_INET()) ||
217  (destination && destination->addr.sa_family == pj_AF_INET())) {
218  pcap_ethernet_header.type = htons(0x0800); /* We are providing an IPv4 packet */
219  pcap_ip_header = &pcap_ipv4_header;
220  pcap_ip_header_len = sizeof(struct pcap_ipv4_header);
221  if (source) {
222  memcpy(&pcap_ipv4_header.ip_src, pj_sockaddr_get_addr(source), pj_sockaddr_get_addr_len(source));
223  }
224  if (destination) {
225  memcpy(&pcap_ipv4_header.ip_dst, pj_sockaddr_get_addr(destination), pj_sockaddr_get_addr_len(destination));
226  }
227  pcap_ipv4_header.ip_len = htons(sizeof(struct pcap_udp_header) + sizeof(struct pcap_ipv4_header) + msg_len);
228  pcap_ipv4_header.ip_protocol = IPPROTO_UDP; /* We always provide UDP */
229  } else {
230  pcap_ethernet_header.type = htons(0x86DD); /* We are providing an IPv6 packet */
231  pcap_ip_header = &pcap_ipv6_header;
232  pcap_ip_header_len = sizeof(struct pcap_ipv6_header);
233  if (source) {
234  memcpy(&pcap_ipv6_header.ip6_src, pj_sockaddr_get_addr(source), pj_sockaddr_get_addr_len(source));
235  }
236  if (destination) {
237  memcpy(&pcap_ipv6_header.ip6_dst, pj_sockaddr_get_addr(destination), pj_sockaddr_get_addr_len(destination));
238  }
239  pcap_ipv6_header.ip6_ctlun.ip6_un1.ip6_un1_plen = htons(sizeof(struct pcap_udp_header) + msg_len);
240  pcap_ipv6_header.ip6_ctlun.ip6_un1.ip6_un1_nxt = IPPROTO_UDP;
241  }
242 
243  /* Add up all the sizes for this record */
244  pcap_record_header.incl_len = pcap_record_header.orig_len = sizeof(pcap_ethernet_header) + pcap_ip_header_len + sizeof(pcap_udp_header) + msg_len;
245 
246  /* We lock the logger session since we're writing these out in parts */
247  ao2_wrlock(session);
248  if (session->pcap_file) {
249  if (fwrite(&pcap_record_header, sizeof(struct pcap_record_header), 1, session->pcap_file) != 1) {
250  ast_log(LOG_WARNING, "Writing PCAP header failed: %s\n", strerror(errno));
251  }
252  if (fwrite(&pcap_ethernet_header, sizeof(struct pcap_ethernet_header), 1, session->pcap_file) != 1) {
253  ast_log(LOG_WARNING, "Writing ethernet header to pcap failed: %s\n", strerror(errno));
254  }
255  if (fwrite(pcap_ip_header, pcap_ip_header_len, 1, session->pcap_file) != 1) {
256  ast_log(LOG_WARNING, "Writing IP header to pcap failed: %s\n", strerror(errno));
257  }
258  if (fwrite(&pcap_udp_header, sizeof(struct pcap_udp_header), 1, session->pcap_file) != 1) {
259  ast_log(LOG_WARNING, "Writing UDP header to pcap failed: %s\n", strerror(errno));
260  }
261  if (fwrite(msg, msg_len, 1, session->pcap_file) != 1) {
262  ast_log(LOG_WARNING, "Writing UDP payload to pcap failed: %s\n", strerror(errno));
263  }
264  }
265  ao2_unlock(session);
266 }
uint32_t ip_src
Checksum (not calculated for our purposes.
#define LOG_WARNING
Definition: logger.h:274
uint32_t orig_len
Length of packet as saved in the file.
struct in6_addr ip6_dst
Source IP address.
uint16_t dst
Source IP port.
uint16_t type
Source MAD address.
PCAP Packet Record Header.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
uint32_t incl_len
When the record was created.
#define ao2_unlock(a)
Definition: astobj2.h:730
uint8_t ip_protocol
Time to live for the packet.
#define ao2_wrlock(a)
Definition: astobj2.h:720
union pcap_ipv6_header::@483 ip6_ctlun
uint16_t ip_len
Type of service details.
uint16_t length
Destination IP port.
#define ast_log
Definition: astobj2.c:42
uint32_t ip_dst
Source IP address.
PCAP IPv6 Header.
PCAP IPv4 Header.
struct pcap_ipv6_header::@483::ip6_hdrctl ip6_un1
int errno
struct in6_addr ip6_src
FILE * pcap_file
The pcap file itself.
PCAP UDP Header.
PCAP Ethernet Header.

◆ pjsip_set_logger()

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

Definition at line 470 of file res_pjsip_logger.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, ast_cli_entry::command, ast_cli_args::fd, NULL, pjsip_disable_logger(), pjsip_enable_logger_all(), pjsip_enable_logger_host(), pjsip_set_logger_pcap(), pjsip_set_logger_verbose(), and ast_cli_entry::usage.

471 {
472  const char *what;
473 
474  if (cmd == CLI_INIT) {
475  e->command = "pjsip set logger {on|off|host|add|verbose|pcap}";
476  e->usage =
477  "Usage: pjsip set logger {on|off|host <name/subnet>|add <name/subnet>|verbose <on/off>|pcap <filename>}\n"
478  " Enables or disabling logging of SIP packets\n"
479  " read on ports bound to PJSIP transports either\n"
480  " globally or enables logging for an individual\n"
481  " host.\n";
482  return NULL;
483  } else if (cmd == CLI_GENERATE) {
484  return NULL;
485  }
486 
487  what = a->argv[e->args - 1]; /* Guaranteed to exist */
488 
489  if (a->argc == e->args) { /* on/off */
490  if (!strcasecmp(what, "on")) {
491  return pjsip_enable_logger_all(a->fd);
492  } else if (!strcasecmp(what, "off")) {
493  return pjsip_disable_logger(a->fd);
494  }
495  } else if (a->argc == e->args + 1) {
496  if (!strcasecmp(what, "host")) {
497  return pjsip_enable_logger_host(a->fd, a->argv[e->args], 0);
498  } else if (!strcasecmp(what, "add")) {
499  return pjsip_enable_logger_host(a->fd, a->argv[e->args], 1);
500  } else if (!strcasecmp(what, "verbose")) {
501  return pjsip_set_logger_verbose(a->fd, a->argv[e->args]);
502  } else if (!strcasecmp(what, "pcap")) {
503  return pjsip_set_logger_pcap(a->fd, a->argv[e->args]);
504  }
505  }
506 
507  return CLI_SHOWUSAGE;
508 }
const int argc
Definition: cli.h:160
Definition: cli.h:152
#define NULL
Definition: resample.c:96
int args
This gets set in ast_cli_register()
Definition: cli.h:185
static char * pjsip_disable_logger(int fd)
static char * pjsip_set_logger_pcap(int fd, const char *arg)
const int fd
Definition: cli.h:159
const char *const * argv
Definition: cli.h:161
#define CLI_SHOWUSAGE
Definition: cli.h:45
static char * pjsip_enable_logger_all(int fd)
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
static char * pjsip_enable_logger_host(int fd, const char *arg, unsigned int add_host)
static char * pjsip_set_logger_verbose(int fd, const char *arg)

◆ pjsip_set_logger_pcap()

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

Definition at line 436 of file res_pjsip_logger.c.

References ao2_unlock, ao2_wrlock, ast_cli(), ast_copy_string(), CLI_SUCCESS, 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().

437 {
438  struct pcap_header pcap_header = {
439  .magic_number = 0xa1b2c3d4,
440  .version_major = 2,
441  .version_minor = 4,
442  .snaplen = 65535,
443  .network = 1, /* We always use ethernet so we can combine IPv4 and IPv6 in same pcap */
444  };
445 
448 
449  if (default_logger->pcap_file) {
450  fclose(default_logger->pcap_file);
452  }
453 
454  default_logger->pcap_file = fopen(arg, "wb");
455  if (!default_logger->pcap_file) {
457  ast_cli(fd, "Failed to open file '%s' for pcap writing\n", arg);
458  return CLI_SUCCESS;
459  }
460  fwrite(&pcap_header, 1, sizeof(struct pcap_header), default_logger->pcap_file);
461 
464 
465  ast_cli(fd, "PJSIP logging to pcap file '%s'\n", arg);
466 
467  return CLI_SUCCESS;
468 }
PCAP Header.
char pcap_filename[PATH_MAX]
Filename used for the pcap file.
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
#define ao2_wrlock(a)
Definition: astobj2.h:720
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
unsigned int log_to_pcap
Whether to log to pcap or not.
uint32_t magic_number
#define CLI_SUCCESS
Definition: cli.h:44
static struct pjsip_logger_session * default_logger
The default logger session.
FILE * pcap_file
The pcap file itself.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401

◆ pjsip_set_logger_verbose()

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

Definition at line 425 of file res_pjsip_logger.c.

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

Referenced by pjsip_set_logger().

426 {
430 
431  ast_cli(fd, "PJSIP Logging to verbose has been %s\n", ast_true(arg) ? "enabled" : "disabled");
432 
433  return CLI_SUCCESS;
434 }
unsigned int log_to_verbose
Whether to log to verbose or not.
#define ao2_unlock(a)
Definition: astobj2.h:730
#define ao2_wrlock(a)
Definition: astobj2.h:720
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
Definition: main/utils.c:1951
#define CLI_SUCCESS
Definition: cli.h:44
static struct pjsip_logger_session * default_logger
The default logger session.

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 566 of file res_pjsip_logger.c.

References ao2_cleanup, ARRAY_LEN, ast_cli_unregister_multiple(), AST_MODFLAG_LOAD_ORDER, AST_MODPRI_APP_DEPEND, AST_MODULE_INFO(), AST_MODULE_SUPPORT_CORE, ast_sip_get_sorcery(), ast_sip_unregister_service(), ast_sorcery_observer_remove(), ASTERISK_GPL_KEY, load_module(), and NULL.

567 {
570 
572  ast_sip_get_sorcery(), "global", &global_observer);
573 
576 
577  return 0;
578 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
static const struct ast_sorcery_observer global_observer
#define NULL
Definition: resample.c:96
static pjsip_module logging_module
static struct ast_cli_entry cli_pjsip[]
static struct pjsip_logger_session * default_logger
The default logger session.
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
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
void ast_sip_unregister_service(pjsip_module *module)
Definition: res_pjsip.c:3331

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 = "30ef0c93b36035ec78c9cfd712d36d9b" , .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 586 of file res_pjsip_logger.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

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

◆ default_logger

struct pjsip_logger_session* default_logger
static

The default logger session.

Definition at line 121 of file res_pjsip_logger.c.

◆ 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 539 of file res_pjsip_logger.c.

◆ logging_module

pjsip_module logging_module
static

Definition at line 328 of file res_pjsip_logger.c.