Asterisk - The Open Source Telephony Project GIT-master-a358458
res_pjsip_logger.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 2013, Digium, Inc.
5 *
6 * Mark Michelson <mmichelson@digium.com>
7 *
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
13 *
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
17 */
18
19/*** MODULEINFO
20 <depend>pjproject</depend>
21 <depend>res_pjsip</depend>
22 <defaultenabled>yes</defaultenabled>
23 <support_level>core</support_level>
24 ***/
25
26#include "asterisk.h"
27
28#include <netinet/in.h> /* For IPPROTO_UDP and in6_addr */
29
30#include <pjsip.h>
31
32#include "asterisk/res_pjsip.h"
33#include "asterisk/vector.h"
34#include "asterisk/module.h"
35#include "asterisk/logger.h"
36#include "asterisk/cli.h"
37#include "asterisk/netsock2.h"
38#include "asterisk/acl.h"
39
40/*! \brief PCAP Header */
42 uint32_t magic_number; /*! \brief PCAP file format magic number */
43 uint16_t version_major; /*! \brief Major version number of the file format */
44 uint16_t version_minor; /*! \brief Minor version number of the file format */
45 int32_t thiszone; /*! \brief GMT to local correction */
46 uint32_t sigfigs; /*! \brief Accuracy of timestamps */
47 uint32_t snaplen; /*! \brief The maximum size that can be recorded in the file */
48 uint32_t network; /*! \brief Type of packets held within the file */
49};
50
51/*! \brief PCAP Packet Record Header */
53 uint32_t ts_sec; /*! \brief When the record was created */
54 uint32_t ts_usec; /*! \brief When the record was created */
55 uint32_t incl_len; /*! \brief Length of packet as saved in the file */
56 uint32_t orig_len; /*! \brief Length of packet as sent over network */
57};
58
59/*! \brief PCAP Ethernet Header */
61 uint8_t dst[6]; /*! \brief Destination MAC address */
62 uint8_t src[6]; /*! \brief Source MAD address */
63 uint16_t type; /*! \brief The type of packet contained within */
64} __attribute__((__packed__));
65
66/*! \brief PCAP IPv4 Header */
68 uint8_t ver_ihl; /*! \brief IP header version and other bits */
69 uint8_t ip_tos; /*! \brief Type of service details */
70 uint16_t ip_len; /*! \brief Total length of the packet (including IPv4 header) */
71 uint16_t ip_id; /*! \brief Identification value */
72 uint16_t ip_off; /*! \brief Fragment offset */
73 uint8_t ip_ttl; /*! \brief Time to live for the packet */
74 uint8_t ip_protocol; /*! \brief Protocol of the data held within the packet (always UDP) */
75 uint16_t ip_sum; /*! \brief Checksum (not calculated for our purposes */
76 uint32_t ip_src; /*! \brief Source IP address */
77 uint32_t ip_dst; /*! \brief Destination IP address */
78};
79
80/*! \brief PCAP IPv6 Header */
82 union {
83 struct ip6_hdrctl {
84 uint32_t ip6_un1_flow; /*! \brief Version, traffic class, flow label */
85 uint16_t ip6_un1_plen; /*! \brief Length of the packet (not including IPv6 header) */
86 uint8_t ip6_un1_nxt; /*! \brief Next header field */
87 uint8_t ip6_un1_hlim; /*! \brief Hop Limit */
89 uint8_t ip6_un2_vfc; /*! \brief Version, traffic class */
91 struct in6_addr ip6_src; /*! \brief Source IP address */
92 struct in6_addr ip6_dst; /*! \brief Destination IP address */
93};
94
95/*! \brief PCAP UDP Header */
97 uint16_t src; /*! \brief Source IP port */
98 uint16_t dst; /*! \brief Destination IP port */
99 uint16_t length; /*! \brief Length of the UDP header plus UDP packet */
100 uint16_t checksum; /*! \brief Packet checksum, left uncalculated for our purposes */
101};
102
104 pj_str_t pj_name; /*! \brief A PJSIP string for the method */
105 pjsip_method method; /*! \brief The PJSIP method structure used for comparisons */
106 char name[]; /*! \brief The method name */
107};
108
109/*! \brief PJSIP Logging Session */
111 /*! \brief Explicit addresses or ranges being logged */
113 /*! \brief Filename used for the pcap file */
115 /*! \brief The pcap file itself */
117 /*! \brief Whether the session is enabled or not */
118 unsigned int enabled:1;
119 /*! \brief Whether the session is logging all traffic or not */
120 unsigned int log_all_traffic:1;
121 /*! \brief Whether to log to verbose or not */
122 unsigned int log_to_verbose:1;
123 /*! \brief Whether to log to pcap or not */
124 unsigned int log_to_pcap:1;
125 /*! \brief Vector of SIP methods to log */
127};
128
129/*! \brief The default logger session */
131
132/*! \brief Destructor for logger session */
133static void pjsip_logger_session_destroy(void *obj)
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}
146
147/*! \brief Allocator for logger session */
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}
164
165/*! \note Must be called with the pjsip_logger_session lock held */
166static int apply_method_filter(const struct pjsip_logger_session *session, const pjsip_method *method)
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}
186
187/*! \brief See if we pass debug filter */
188static inline int pjsip_log_test_filter(const struct pjsip_logger_session *session, const char *address, int port, const pjsip_method *method)
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}
221
222static void pjsip_logger_write_to_pcap(struct pjsip_logger_session *session, const char *msg, size_t msg_len,
223 pj_sockaddr *source, pj_sockaddr *destination)
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}
309
310static pj_status_t logging_on_tx_msg(pjsip_tx_data *tdata)
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}
337
338static pj_bool_t logging_on_rx_msg(pjsip_rx_data *rdata)
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}
369
370static pjsip_module logging_module = {
371 .name = { "Logging Module", 14 },
372 .priority = 0,
373 .on_rx_request = logging_on_rx_msg,
374 .on_rx_response = logging_on_rx_msg,
375 .on_tx_request = logging_on_tx_msg,
376 .on_tx_response = logging_on_tx_msg,
377};
378
379static char *pjsip_enable_logger_all(int fd)
380{
385
386 if (fd >= 0) {
387 ast_cli(fd, "PJSIP Logging enabled\n");
388 }
389
390 return CLI_SUCCESS;
391}
392
393static char *pjsip_enable_logger_host(int fd, const char *arg, unsigned int add_host)
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}
437
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}
454
455static int method_logging_info_cmp(const struct method_logging_info *element,
456 const struct method_logging_info *candidate)
457{
458 return pjsip_method_cmp(&element->method, &candidate->method) == 0
460 : 0;
461}
462
463static int method_logging_info_sort_cmp(const void *a, const void *b)
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}
469
470/*! \brief Add the current or an additional method to match for filtering */
471static char *pjsip_enable_logger_method(int fd, const char *arg, int add_method)
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}
524
525static char *pjsip_disable_logger(int fd)
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}
555
556static char *pjsip_set_logger_verbose(int fd, const char *arg)
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}
566
567static char *pjsip_set_logger_pcap(int fd, const char *arg)
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}
600
601static char *pjsip_set_logger(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
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}
658
659static struct ast_cli_entry cli_pjsip[] = {
660 AST_CLI_DEFINE(pjsip_set_logger, "Enable/Disable PJSIP Logger Output")
661};
662
663static void check_debug(void)
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}
682
683static void global_reloaded(const char *object_type)
684{
685 check_debug();
686}
687
690};
691
692static int load_module(void)
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}
714
715static int unload_module(void)
716{
719
722
725
726 return 0;
727}
728
730 .support_level = AST_MODULE_SUPPORT_CORE,
731 .load = load_module,
732 .unload = unload_module,
733 .load_pri = AST_MODPRI_APP_DEPEND,
734 .requires = "res_pjsip",
Access Control of various sorts.
void ast_free_ha(struct ast_ha *ha)
Free a list of HAs.
Definition: acl.c:222
@ 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
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
const char * str
Definition: app_jack.c:147
Asterisk main include file. File version handling, generic pbx functions.
#define PATH_MAX
Definition: asterisk.h:40
static struct ast_mansession session
#define ast_free(a)
Definition: astmm.h:180
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define ast_log
Definition: astobj2.c:42
@ CMP_MATCH
Definition: astobj2.h:1027
@ CMP_STOP
Definition: astobj2.h:1028
#define ao2_rdlock(a)
Definition: astobj2.h:718
@ AO2_ALLOC_OPT_LOCK_RWLOCK
Definition: astobj2.h:365
#define ao2_wrlock(a)
Definition: astobj2.h:719
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#define ao2_unlock(a)
Definition: astobj2.h:729
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:404
Standard Command Line Interface.
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define CLI_SUCCESS
Definition: cli.h:44
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:197
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
char * ast_cli_complete(const char *word, const char *const choices[], int pos)
Definition: main/cli.c:1841
@ CLI_INIT
Definition: cli.h:152
@ CLI_GENERATE
Definition: cli.h:153
#define CLI_FAILURE
Definition: cli.h:46
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
int int32_t
Definition: db.h:60
void ast_verbose(const char *fmt,...)
Definition: extconf.c:2206
char * address
Definition: f2c.h:59
Support for logging to various files, console and syslog Configuration in file logger....
#define LOG_ERROR
#define LOG_WARNING
int errno
Asterisk module definitions.
@ AST_MODFLAG_LOAD_ORDER
Definition: module.h:317
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
Definition: module.h:543
@ AST_MODPRI_APP_DEPEND
Definition: module.h:328
@ AST_MODULE_SUPPORT_CORE
Definition: module.h:121
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
@ 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
def info(msg)
Network socket handling.
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
#define ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
Definition: netsock2.h:532
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
#define AST_SOCKADDR_BUFLEN
Definition: netsock2.h:46
const char * method
Definition: res_pjsip.c:1279
void ast_sip_unregister_service(pjsip_module *module)
Definition: res_pjsip.c:133
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.
char * ast_sip_get_debug(void)
Retrieve the system debug setting (yes|no|host).
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_enable_logger_method(int fd, const char *arg, int add_method)
Add the current or an additional method to match for filtering.
static int apply_method_filter(const struct pjsip_logger_session *session, const pjsip_method *method)
static struct method_logging_info * method_logging_info_alloc(const char *method)
static struct ast_cli_entry cli_pjsip[]
static char * pjsip_enable_logger_all(int fd)
static char * pjsip_set_logger(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static struct pjsip_logger_session * default_logger
The default logger session.
static pjsip_module logging_module
static char * pjsip_set_logger_verbose(int fd, const char *arg)
static pj_status_t logging_on_tx_msg(pjsip_tx_data *tdata)
static int method_logging_info_cmp(const struct method_logging_info *element, const struct method_logging_info *candidate)
static char * pjsip_set_logger_pcap(int fd, const char *arg)
static void check_debug(void)
static int method_logging_info_sort_cmp(const void *a, const void *b)
static struct pjsip_logger_session * pjsip_logger_session_alloc(void)
Allocator for logger session.
static int load_module(void)
static void global_reloaded(const char *object_type)
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.
static int unload_module(void)
static const struct ast_sorcery_observer global_observer
static void pjsip_logger_session_destroy(void *obj)
Destructor for logger session.
static char * pjsip_enable_logger_host(int fd, const char *arg, unsigned int add_host)
static char * pjsip_disable_logger(int fd)
static pj_bool_t logging_on_rx_msg(pjsip_rx_data *rdata)
static int debug
Global debug status.
Definition: res_xmpp.c:441
#define NULL
Definition: resample.c:96
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
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
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
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
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 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
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
descriptor for a cli entry.
Definition: cli.h:171
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
internal representation of ACL entries In principle user applications would have no need for this,...
Definition: acl.h:51
Socket address structure.
Definition: netsock2.h:97
Interface for a sorcery object type observer.
Definition: sorcery.h:332
void(* loaded)(const char *object_type)
Callback for when an object type is loaded/reloaded.
Definition: sorcery.h:343
Support for dynamic strings.
Definition: strings.h:623
char name[]
The PJSIP method structure used for comparisons.
pjsip_method method
A PJSIP string for the method.
PCAP Ethernet Header.
uint8_t src[6]
Destination MAC address.
uint16_t type
Source MAD address.
PCAP Header.
uint16_t version_minor
Major version number of the file format.
uint32_t magic_number
uint32_t sigfigs
GMT to local correction.
uint32_t snaplen
Accuracy of timestamps.
uint32_t network
The maximum size that can be recorded in the file.
uint16_t version_major
PCAP file format magic number.
int32_t thiszone
Minor version number of the file format.
PCAP IPv4 Header.
uint32_t ip_dst
Source IP address.
uint16_t ip_off
Identification value.
uint16_t ip_id
Total length of the packet (including IPv4 header)
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.
uint8_t ip_ttl
Fragment offset.
uint16_t ip_sum
Protocol of the data held within the packet (always UDP)
uint8_t ip_tos
IP header version and other bits.
PCAP IPv6 Header.
uint8_t ip6_un1_nxt
Length of the packet (not including IPv6 header)
uint16_t ip6_un1_plen
Version, traffic class, flow label.
struct pcap_ipv6_header::@458::ip6_hdrctl ip6_un1
struct in6_addr ip6_dst
Source IP address.
uint8_t ip6_un1_hlim
Next header field.
struct in6_addr ip6_src
union pcap_ipv6_header::@458 ip6_ctlun
PCAP Packet Record Header.
uint32_t ts_usec
When the record was created.
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 checksum
Length of the UDP header plus UDP packet.
uint16_t dst
Source IP port.
PJSIP Logging Session.
struct ast_ha * matches
Explicit addresses or ranges being logged.
unsigned int log_to_verbose
Whether to log to verbose or not.
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.
unsigned int log_to_pcap
Whether to log to pcap or not.
static struct test_val b
static struct test_val a
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
int error(const char *format,...)
Definition: utils/frame.c:999
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941
#define ARRAY_LEN(a)
Definition: utils.h:666
Vector container support.
#define AST_VECTOR_RESET(vec, cleanup)
Reset vector.
Definition: vector.h:625
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:609
#define AST_VECTOR_SORT(vec, cmp)
Sort a vector in-place.
Definition: vector.h:396
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition: vector.h:174
#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_INIT(vec, size)
Initialize a vector.
Definition: vector.h:113
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256
#define AST_VECTOR(name, type)
Define a vector structure.
Definition: vector.h:44
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:680