Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package sngrep for openSUSE:Factory checked in at 2022-09-23 14:15:24 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/sngrep (Old) and /work/SRC/openSUSE:Factory/.sngrep.new.2275 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "sngrep" Fri Sep 23 14:15:24 2022 rev:8 rq:1005522 version:1.6.0 Changes: -------- --- /work/SRC/openSUSE:Factory/sngrep/sngrep.changes 2022-05-09 18:45:19.516293457 +0200 +++ /work/SRC/openSUSE:Factory/.sngrep.new.2275/sngrep.changes 2022-09-23 14:16:01.538093444 +0200 @@ -1,0 +2,15 @@ +Wed Sep 7 10:29:07 UTC 2022 - Martin Hauke <mar...@gmx.de> + +- Update to version 1.6.0 + * capture: added compatibility with openssl >= 3.5.0 + * capture: fixed memory leak while rotating dialogs + * capture: added save file rotation through SIPHUP signal + * capture: added support for opening gzip compressed input files + * hep: received HEP packets can now be saved to PCAP files + * core: added support for PCRE2 library + * cf: raw payload preview now properly displays characters near + window borders + * cli: properly display captured dialog count when no interface + is used + +------------------------------------------------------------------- Old: ---- sngrep-1.5.0.tar.gz New: ---- sngrep-1.6.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ sngrep.spec ++++++ --- /var/tmp/diff_new_pack.APIZFa/_old 2022-09-23 14:16:02.078094703 +0200 +++ /var/tmp/diff_new_pack.APIZFa/_new 2022-09-23 14:16:02.082094712 +0200 @@ -18,7 +18,7 @@ Name: sngrep -Version: 1.5.0 +Version: 1.6.0 Release: 0 Summary: Ncurses SIP Messages flow viewer License: GPL-3.0-or-later ++++++ sngrep-1.5.0.tar.gz -> sngrep-1.6.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sngrep-1.5.0/ChangeLog new/sngrep-1.6.0/ChangeLog --- old/sngrep-1.5.0/ChangeLog 2022-04-26 15:59:33.000000000 +0200 +++ new/sngrep-1.6.0/ChangeLog 2022-08-31 16:02:22.000000000 +0200 @@ -1,11 +1,23 @@ -2021-04-26 Ivan Alonso <ka...@irontec.com> - * sngrep 1.5.0 released +2022-08-31 Ivan Alonso <ka...@irontec.com> + * sngrep 1.6.0 released - * capture: add support for IP-IP encapsulation - * capture: add support for IPv6 fragments reassembly - * hep: add support for saving HEP received packets to PCAP - * tls: check client TLS version in gnutls code - * ui: fixed a crash when leaving ncurses screens + * capture: added compatibility with openssl >= 3.5.0 + * capture: fixed memory leak while rotating dialogs + * capture: added save file rotation through SIPHUP signal + * capture: added support for opening gzip compressed input files + * hep: received HEP packets can now be saved to PCAP files + * core: added support for PCRE2 library + * cf: raw payload preview now properly displays characters near window borders + * cli: properly display captured dialog count when no interface is used + +2022-04-26 Ivan Alonso <ka...@irontec.com> + * sngrep 1.5.0 released + + * capture: add support for IP-IP encapsulation + * capture: add support for IPv6 fragments reassembly + * hep: add support for saving HEP received packets to PCAP + * tls: check client TLS version in gnutls code + * ui: fixed a crash when leaving ncurses screens 2021-11-19 Ivan Alonso <ka...@irontec.com> * sngrep 1.4.10 released diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sngrep-1.5.0/README new/sngrep-1.6.0/README --- old/sngrep-1.5.0/README 2022-04-26 15:59:33.000000000 +0200 +++ new/sngrep-1.6.0/README 2022-08-31 16:02:22.000000000 +0200 @@ -27,6 +27,7 @@ - gnutls - (optional) for TLS transport decrypt using GnuTLS and libgcrypt - libncursesw5 - (optional) for UI, windows, panels (wide-character support) - libpcre - (optional) for Perl Compatible regular expressions + - zlib - (optional) for gzip compressed pcap files On most systems the commands to build will be the standard autotools procedure: @@ -42,6 +43,7 @@ | `--with-openssl` | Adds OpenSSL support to parse TLS captured messages (req. libssl) | | `--with-gnutls` | Adds GnuTLS support to parse TLS captured messages (req. gnutls) | | `--with-pcre`| Adds Perl Compatible regular expressions support in regexp fields | +| `--with-zlib`| Enable zlib to support gzip compressed pcap files | | `--enable-unicode` | Adds Ncurses UTF-8/Unicode support (req. libncursesw5) | | `--enable-ipv6` | Enable IPv6 packet capture support. | | `--enable-eep` | Enable EEP packet send/receive support. | diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sngrep-1.5.0/configure.ac new/sngrep-1.6.0/configure.ac --- old/sngrep-1.5.0/configure.ac 2022-04-26 15:59:33.000000000 +0200 +++ new/sngrep-1.6.0/configure.ac 2022-08-31 16:02:22.000000000 +0200 @@ -1,5 +1,5 @@ AC_PREREQ([2.59]) -AC_INIT([sngrep], [1.5.0], [ka...@irontec.com], [sngrep], [http://www.irontec.com/]) +AC_INIT([sngrep], [1.6.0], [ka...@irontec.com], [sngrep], [http://www.irontec.com/]) AM_INIT_AUTOMAKE([1.9]) AC_CONFIG_HEADERS([src/config.h]) m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) @@ -29,6 +29,9 @@ AC_LANG(C) AM_PROG_CC_C_O +# we might want to use this with zlib for compressed pcap support +AC_CHECK_FUNCS([fopencookie]) + ####################################################################### # Check for other REQUIRED libraries AC_CHECK_LIB([pthread], [pthread_create], [], [ @@ -51,7 +54,7 @@ [AC_SUBST(UNICODE, no)] ) -AS_IF([test "x$enable_unicode" == "xyes"], [ +AS_IF([test "x$enable_unicode" = "xyes"], [ # Ncurses with wide-character support AC_DEFINE([WITH_UNICODE], [], [Compile With Unicode compatibility]) @@ -115,7 +118,7 @@ [AC_SUBST(WITH_GNUTLS, no)] ) -AS_IF([test "x$WITH_GNUTLS" == "xyes"], [ +AS_IF([test "x$WITH_GNUTLS" = "xyes"], [ m4_ifdef([PKG_CHECK_MODULES], [ PKG_CHECK_MODULES([LIBGNUTLS], [gnutls]) @@ -152,8 +155,8 @@ [AC_SUBST(WITH_OPENSSL, no)] ) -AS_IF([test "x$WITH_OPENSSL" == "xyes"], [ - AS_IF([test "x$WITH_GNUTLS" == "xyes"], [ +AS_IF([test "x$WITH_OPENSSL" = "xyes"], [ + AS_IF([test "x$WITH_GNUTLS" = "xyes"], [ AC_MSG_ERROR([ GnuTLS and OpenSSL can not be enabled at the same time ]) ], []) m4_ifdef([PKG_CHECK_MODULES], [ @@ -179,7 +182,7 @@ [AC_SUBST(WITH_PCRE, no)] ) -AS_IF([test "x$WITH_PCRE" == "xyes"], [ +AS_IF([test "x$WITH_PCRE" = "xyes"], [ AC_CHECK_HEADER([pcre.h], [], [ AC_MSG_ERROR([ You need libpcre development files installed to compile with pcre support.]) ]) @@ -190,6 +193,34 @@ ], []) #### +#### PCRE2 Support +#### +AC_ARG_WITH([pcre2], + AS_HELP_STRING([--with-pcre2], [Enable Perl compatible regular expressions (v2)]), + [AC_SUBST(WITH_PCRE2, $withval)], + [AC_SUBST(WITH_PCRE2, no)] +) + +AS_IF([test "x$WITH_PCRE2" = "xyes"], [ + AS_IF([test "x$WITH_PCRE" = "xyes"], [ + AC_MSG_ERROR([libpcre-2 and libpcre-3 can not be enabled at the same time ]) + ], []) + AC_DEFINE([PCRE2_CODE_UNIT_WIDTH], [8], [Required for including pcre2.h]) + AC_SUBST(PCRE2_CODE_UNIT_WIDTH, 8) + m4_ifdef([PKG_CHECK_MODULES], [ + PKG_CHECK_MODULES([PCRE2], [libpcre2-8]) + ], [ + AC_CHECK_HEADER([pcre2.h], [], [ + AC_MSG_ERROR([ You need libpcre2 development files installed to compile with pcre support.]) + ]) + AC_CHECK_LIB([pcre2-8], [pcre2_compile_8], [], [ + AC_MSG_ERROR([ You need libpcre2 library installed to compile with pcre support.]) + ]) + ]) + AC_DEFINE([WITH_PCRE2],[],[Compile With Perl Compatible regular expressions support]) +], []) + +#### #### IPv6 Support #### AC_ARG_ENABLE([ipv6], @@ -198,7 +229,7 @@ [AC_SUBST(USE_IPV6, no)] ) -AS_IF([test "x$USE_IPV6" == "xyes"], [ +AS_IF([test "x$USE_IPV6" = "xyes"], [ AC_CHECK_HEADERS([netinet/in.h netinet/ip6.h], [], [ AC_MSG_ERROR([ You dont seem to have ipv6 support (no ip6.h found).]) ], [ @@ -223,15 +254,37 @@ [AC_SUBST(USE_EEP, no)] ) -AS_IF([test "x$USE_EEP" == "xyes"], [ +AS_IF([test "x$USE_EEP" = "xyes"], [ AC_DEFINE([USE_EEP],[],[Compile With EEP support]) ], []) +#### +#### zlib Support +#### +AC_ARG_WITH([zlib], + AS_HELP_STRING([--with-zlib], [Enable zlib to support gzip compressed pcap files]), + [AC_SUBST(WITH_ZLIB, $withval)], + [AC_SUBST(WITH_ZLIB, no)] +) + +AS_IF([test "x$WITH_ZLIB" = "xyes"], [ + AC_CHECK_HEADER([zlib.h], [], [ + AC_MSG_ERROR([ You need libz header files installed to compile with zlib support.]) + ]) + AC_CHECK_LIB([z], [gzdopen], [], [ + AC_MSG_ERROR([ You need libz library installed to compile with zlib support.]) + ]) + AC_DEFINE([WITH_ZLIB],[],[Compile With zlib support]) +], []) + + -# Conditional Source inclusion -AM_CONDITIONAL([WITH_GNUTLS], [test "x$WITH_GNUTLS" == "xyes"]) -AM_CONDITIONAL([WITH_OPENSSL], [test "x$WITH_OPENSSL" == "xyes"]) -AM_CONDITIONAL([USE_EEP], [test "x$USE_EEP" == "xyes"]) +# Conditional Source inclusion +AM_CONDITIONAL([WITH_PCRE2], [test "x$WITH_PCRE2" = "xyes"]) +AM_CONDITIONAL([WITH_GNUTLS], [test "x$WITH_GNUTLS" = "xyes"]) +AM_CONDITIONAL([WITH_OPENSSL], [test "x$WITH_OPENSSL" = "xyes"]) +AM_CONDITIONAL([USE_EEP], [test "x$USE_EEP" = "xyes"]) +AM_CONDITIONAL([WITH_ZLIB], [test "x$WITH_ZLIB" = "xyes"]) ###################################################################### @@ -241,7 +294,7 @@ [ enable_logo=$enableval], [ enable_logo=yes]) -AS_IF([test "x$enable_logo" == "xyes"], [ +AS_IF([test "x$enable_logo" = "xyes"], [ echo '' echo ' ?????????????????????????????? ????????????????????? ???????????? ???????????????????????????????????????????????????????????? ?????????????????????' echo ' ??????????????????????????????????????????????????????????????????????????? ????????????????????????????????????????????????????????????????????????????????????' @@ -259,8 +312,10 @@ AC_MSG_NOTICE( OpenSSL Support : ${WITH_OPENSSL} ) AC_MSG_NOTICE( Unicode Support : ${UNICODE} ) AC_MSG_NOTICE( Perl Expressions Support : ${WITH_PCRE} ) +AC_MSG_NOTICE( Perl Expressions Support (v2): ${WITH_PCRE2} ) AC_MSG_NOTICE( IPv6 Support : ${USE_IPV6} ) AC_MSG_NOTICE( EEP Support : ${USE_EEP} ) +AC_MSG_NOTICE( Zlib Support : ${WITH_ZLIB} ) AC_MSG_NOTICE( ====================================================== ) AC_MSG_NOTICE diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sngrep-1.5.0/doc/sngrep.8 new/sngrep-1.6.0/doc/sngrep.8 --- old/sngrep-1.5.0/doc/sngrep.8 2022-04-26 15:59:33.000000000 +0200 +++ new/sngrep-1.6.0/doc/sngrep.8 2022-08-31 16:02:22.000000000 +0200 @@ -3,7 +3,7 @@ .\" Copyright (c) 2013-2021 Ivan Alonso <ka...@irontec.com> .\" Copyright (c) 2013-2021 Irontec S.L. -.TH SNGREP 8 "May 2021" "sngrep 1.5.0" +.TH SNGREP 8 "May 2021" "sngrep 1.6.0" .SH NAME diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sngrep-1.5.0/pkg/apk/APKBUILD new/sngrep-1.6.0/pkg/apk/APKBUILD --- old/sngrep-1.5.0/pkg/apk/APKBUILD 2022-04-26 15:59:33.000000000 +0200 +++ new/sngrep-1.6.0/pkg/apk/APKBUILD 2022-08-31 16:02:22.000000000 +0200 @@ -1,7 +1,7 @@ # Contributor: Francesco Colista <fcoli...@alpinelinux.org> # Maintainer: Francesco Colista <fcoli...@alpinelinux.org> pkgname=sngrep -pkgver=1.5.0 +pkgver=1.6.0 pkgrel=0 pkgdesc="display SIP call message flows from a terminal" url="https://github.com/irontec/sngrep" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sngrep-1.5.0/pkg/debian/changelog new/sngrep-1.6.0/pkg/debian/changelog --- old/sngrep-1.5.0/pkg/debian/changelog 2022-04-26 15:59:33.000000000 +0200 +++ new/sngrep-1.6.0/pkg/debian/changelog 2022-08-31 16:02:22.000000000 +0200 @@ -1,3 +1,9 @@ +sngrep (1.6.0) experimental; urgency=low + + * sngrep 1.6.0 released + + -- Ivan Alonso <ka...@irontec.com> Wed, 31 Aug 2022 11:56:30 +0200 + sngrep (1.5.0) experimental; urgency=low * sngrep 1.5.0 released diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sngrep-1.5.0/pkg/debian/control new/sngrep-1.6.0/pkg/debian/control --- old/sngrep-1.5.0/pkg/debian/control 2022-04-26 15:59:33.000000000 +0200 +++ new/sngrep-1.6.0/pkg/debian/control 2022-08-31 16:02:22.000000000 +0200 @@ -1,6 +1,6 @@ Source: sngrep Section: comm -Build-Depends: dh-autoreconf, debhelper, libpcap-dev, libncursesw5-dev, gnutls-dev, libgcrypt-dev, libpcre3-dev, libncurses5-dev, pkg-config +Build-Depends: dh-autoreconf, debhelper, libpcap-dev, libncursesw5-dev, gnutls-dev, libgcrypt-dev, libpcre2-dev, libncurses5-dev, pkg-config Priority: optional Standards-Version: 3.9.6 Homepage: https://github.com/irontec/sngrep @@ -9,7 +9,7 @@ Package: sngrep Architecture: any Pre-Depends: ${misc:Pre-Depends} -Depends: ${misc:Depends}, ${shlibs:Depends}, libpcap0.8, libncursesw5, libpcre3 +Depends: ${misc:Depends}, ${shlibs:Depends}, libpcap0.8, libncursesw5, libpcre2 Description: Ncurses SIP Messages flow viewer sngrep displays SIP Messages grouped by Call-Id into flow diagrams. It can be used as an offline PCAP viewer or online diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sngrep-1.5.0/pkg/rpm/SPECS/sngrep.spec new/sngrep-1.6.0/pkg/rpm/SPECS/sngrep.spec --- old/sngrep-1.5.0/pkg/rpm/SPECS/sngrep.spec 2022-04-26 15:59:33.000000000 +0200 +++ new/sngrep-1.6.0/pkg/rpm/SPECS/sngrep.spec 2022-08-31 16:02:22.000000000 +0200 @@ -2,7 +2,7 @@ Summary: SIP Messages flow viewer Name: sngrep -Version: 1.5.0 +Version: 1.6.0 Release: 0%{?dist} License: GPLv3 Group: Applications/Engineering @@ -59,6 +59,8 @@ %{__rm} -rf %{buildroot} %changelog +* Wed Aug 31 2022 Ivan Alonso <ka...@irontec.com> - 1.6.0 + - Version 1.6.0 * Tue Apr 26 2022 Ivan Alonso <ka...@irontec.com> - 1.5.0 - Version 1.5.0 * Fri Nov 19 2021 Ivan Alonso <ka...@irontec.com> - 1.4.10 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sngrep-1.5.0/src/Makefile.am new/sngrep-1.6.0/src/Makefile.am --- old/sngrep-1.5.0/src/Makefile.am 2022-04-26 15:59:33.000000000 +0200 +++ new/sngrep-1.6.0/src/Makefile.am 2022-08-31 16:02:22.000000000 +0200 @@ -16,6 +16,15 @@ sngrep_CFLAGS+=$(SSL_CFLAGS) sngrep_LDADD+=$(SSL_LIBS) endif +if WITH_PCRE2 +sngrep_CFLAGS+=$(PCRE2_CFLAGS) +sngrep_LDADD+=$(PCRE2_LIBS) +endif +if WITH_ZLIB +sngrep_CFLAGS+=$(ZLIB_CFLAGS) +sngrep_LDADD+=$(ZLIB_LIBS) +endif + sngrep_SOURCES+=address.c packet.c sip.c sip_call.c sip_msg.c sip_attr.c main.c sngrep_SOURCES+=option.c group.c filter.c keybinding.c media.c setting.c rtp.c sngrep_SOURCES+=util.c hash.c vector.c curses/ui_panel.c curses/scrollbar.c diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sngrep-1.5.0/src/capture.c new/sngrep-1.6.0/src/capture.c --- old/sngrep-1.5.0/src/capture.c 2022-04-26 15:59:33.000000000 +0200 +++ new/sngrep-1.6.0/src/capture.c 2022-08-31 16:02:22.000000000 +0200 @@ -34,6 +34,8 @@ #include <netdb.h> #include <string.h> #include <stdbool.h> +#include <signal.h> +#include <sys/stat.h> #include "capture.h" #ifdef USE_EEP #include "capture_eep.h" @@ -44,15 +46,54 @@ #ifdef WITH_OPENSSL #include "capture_openssl.h" #endif +#ifdef WITH_ZLIB +#include <zlib.h> +#endif #include "sip.h" #include "rtp.h" #include "setting.h" #include "util.h" +#if __STDC_VERSION__ >= 201112L && __STDC_NO_ATOMICS__ != 1 +// modern C with atomics +#include <stdatomic.h> +typedef atomic_int signal_flag_type; +#else +// no atomics available +typedef volatile sig_atomic_t signal_flag_type; +#endif + // Capture information capture_config_t capture_cfg = { 0 }; +signal_flag_type sighup_received = 0; + +void sighup_handler(int signum) +{ + sighup_received = 1; +} + +#if defined(WITH_ZLIB) +static ssize_t +gzip_cookie_write(void *cookie, const char *buf, size_t size) +{ + return gzwrite((gzFile)cookie, (voidpc)buf, size); +} + +static ssize_t +gzip_cookie_read(void *cookie, char *buf, size_t size) +{ + return gzread((gzFile)cookie, (voidp)buf, size); +} + +static int +gzip_cookie_close(void *cookie) +{ + return gzclose((gzFile)cookie); +} +#endif + void capture_init(size_t limit, bool rtp_capture, bool rotate, size_t pcap_buffer_size) { @@ -63,6 +104,13 @@ capture_cfg.paused = 0; capture_cfg.sources = vector_create(1, 1); + // set up SIGHUP handler + // the handler will be served by any of the running threads + // so we just set a flag and check it in dump_packet + // so it is only acted upon before then next packed will be dumped + if (signal(SIGHUP, sighup_handler) == SIG_ERR) + exit(EXIT_FAILURE); + // Fixme if (setting_has_value(SETTING_CAPTURE_STORAGE, "none")) { capture_cfg.storage = CAPTURE_STORAGE_NONE; @@ -104,7 +152,7 @@ } int -capture_online(const char *dev, const char *outfile) +capture_online(const char *dev) { capture_info_t *capinfo; @@ -155,9 +203,12 @@ return 2; } + // Set capture thread function + capinfo->capture_fn = capture_thread; // Store capture device capinfo->device = dev; + capinfo->ispcap = true; // Get datalink to parse packets correctly capinfo->link = pcap_datalink(capinfo->handle); @@ -175,20 +226,11 @@ // Add this capture information as packet source capture_add_source(capinfo); - // If requested store packets in a dump file - if (outfile && !capture_cfg.pd) { - if ((capture_cfg.pd = dump_open(outfile)) == NULL) { - fprintf(stderr, "Couldn't open output dump file %s: %s\n", outfile, - pcap_geterr(capinfo->handle)); - return 2; - } - } - return 0; } int -capture_offline(const char *infile, const char *outfile) +capture_offline(const char *infile) { capture_info_t *capinfo; FILE *fstdin; @@ -207,14 +249,45 @@ infile = "/dev/stdin"; } + // Set capture thread function + capinfo->capture_fn = capture_thread; + // Set capture input file capinfo->infile = infile; + capinfo->ispcap = true; // Open PCAP file if ((capinfo->handle = pcap_open_offline(infile, errbuf)) == NULL) { +#if defined(HAVE_FOPENCOOKIE) && defined(WITH_ZLIB) + // we can't directly parse the file as pcap - could it be gzip compressed? + gzFile zf = gzopen(infile, "rb"); + if (!zf) + goto openerror; + + static cookie_io_functions_t cookiefuncs = { + gzip_cookie_read, NULL, NULL, gzip_cookie_close + }; + + // reroute the file access functions + // use the gzip read+close functions when accessing the file + FILE *fp = fopencookie(zf, "r", cookiefuncs); + if (!fp) + { + gzclose(zf); + goto openerror; + } + + if ((capinfo->handle = pcap_fopen_offline(fp, errbuf)) == NULL) { +openerror: + fprintf(stderr, "Couldn't open pcap file %s: %s\n", infile, errbuf); + return 1; + } + } +#else fprintf(stderr, "Couldn't open pcap file %s: %s\n", infile, errbuf); return 1; } +#endif // Reopen tty for ncurses after pcap have used stdin if (!strncmp(infile, "/dev/stdin", 10)) { @@ -240,15 +313,6 @@ // Add this capture information as packet source capture_add_source(capinfo); - // If requested store packets in a dump file - if (outfile && !capture_cfg.pd) { - if ((capture_cfg.pd = dump_open(outfile)) == NULL) { - fprintf(stderr, "Couldn't open output dump file %s: %s\n", outfile, - pcap_geterr(capinfo->handle)); - return 2; - } - } - return 0; } @@ -394,7 +458,7 @@ capture_eep_send(pkt); #endif // Store this packets in output file - dump_packet(capture_cfg.pd, pkt); + capture_dump_packet(pkt);; // If storage is disabled, delete frames payload if (capture_cfg.storage == 0) { packet_free_frames(pkt); @@ -744,6 +808,12 @@ sng_free(new_payload); } + // Check if packet is too large after assembly + if (pkt->payload_len > MAX_CAPTURE_LEN) { + vector_remove(capinfo->tcp_reasm, pkt); + return NULL; + } + // Store full payload content memset(full_payload, 0, MAX_CAPTURE_LEN); memcpy(full_payload, pkt->payload, pkt->payload_len); @@ -931,7 +1001,9 @@ * you can only break pcap_loop from within the same thread. * @see: https://www.tcpdump.org/manpages/pcap_breakloop.3pcap.html */ - pcap_breakloop(capinfo->handle); + if (capinfo->ispcap) { + pcap_breakloop(capinfo->handle); + } pthread_cancel(capinfo->capture_t); pthread_join(capinfo->capture_t, NULL); } @@ -952,7 +1024,7 @@ while ((capinfo = vector_iterator_next(&it))) { // Mark capture as running capinfo->running = true; - if (pthread_create(&capinfo->capture_t, &attr, (void *) capture_thread, capinfo)) { + if (pthread_create(&capinfo->capture_t, &attr, (void *) capinfo->capture_fn, capinfo)) { return 1; } } @@ -961,7 +1033,7 @@ return 0; } -void +void * capture_thread(void *info) { capture_info_t *capinfo = (capture_info_t *) info; @@ -969,6 +1041,8 @@ // Parse available packets pcap_loop(capinfo->handle, -1, parse_packet, (u_char *) capinfo); capinfo->running = false; + + return NULL; } int @@ -1204,6 +1278,40 @@ vector_insert(vector, item, 0); } +void +capture_set_dumper(pcap_dumper_t *dumper, ino_t dump_inode) +{ + capture_cfg.pd = dumper; + capture_cfg.dump_inode = dump_inode; +} + +void +capture_dump_packet(packet_t *packet) +{ + if (sighup_received && capture_cfg.pd) { + // we got a SIGHUP: reopen the dump file because it could have been renamed + // we don't need to care about locking or other threads accessing in parallel + // because dump_open ensures count(capture_cfg.sources) == 1 + + // check if the file has actually changed + // only reopen if it has, otherwise we would overwrite the existing one + struct stat sb; + if (stat(capture_cfg.dumpfilename, &sb) == -1 || + sb.st_ino != capture_cfg.dump_inode) + { + pcap_dump_close(capture_cfg.pd); + capture_cfg.pd = dump_open(capture_cfg.dumpfilename, &capture_cfg.dump_inode); + } + + sighup_received = 0; + + // error reopening capture file: we can't capture anymore + if (!capture_cfg.pd) + return; + } + + dump_packet(capture_cfg.pd, packet); +} int8_t datalink_size(int datalink) @@ -1237,6 +1345,10 @@ case DLT_LINUX_SLL: return 16; #endif +#ifdef DLT_LINUX_SLL2 + case DLT_LINUX_SLL2: + return 20; +#endif #ifdef DLT_IPNET case DLT_IPNET: return 24; @@ -1248,14 +1360,67 @@ } +bool +is_gz_filename(const char *filename) +{ + // does the filename end on ".gz"? + char *dotpos = strrchr(filename, '.'); + if (dotpos && (strcmp(dotpos, ".gz") == 0)) + return true; + else + return false; +} + pcap_dumper_t * -dump_open(const char *dumpfile) +dump_open(const char *dumpfile, ino_t* dump_inode) { capture_info_t *capinfo; if (vector_count(capture_cfg.sources) == 1) { + capture_cfg.dumpfilename = dumpfile; capinfo = vector_first(capture_cfg.sources); - return pcap_dump_open(capinfo->handle, dumpfile); + + FILE *fp = fopen(dumpfile,"wb+"); + if (!fp) + return NULL; + + struct stat sb; + if (fstat(fileno(fp), &sb) == -1) + return NULL; + + if (dump_inode) { + // read out the files inode, allows to later check if it has changed + struct stat sb; + if (fstat(fileno(fp), &sb) == -1) + return NULL; + *dump_inode = sb.st_ino; + } + + if (is_gz_filename(dumpfile)) + { +#if defined(HAVE_FOPENCOOKIE) && defined(WITH_ZLIB) + // create a gzip file stream out of the already opened file + gzFile zf = gzdopen(fileno(fp), "w"); + if (!zf) + return NULL; + + static cookie_io_functions_t cookiefuncs = { + NULL, gzip_cookie_write, NULL, gzip_cookie_close + }; + + // reroute the file access functions + // use the gzip write+close functions when accessing the file + fp = fopencookie(zf, "w", cookiefuncs); + if (!fp) + return NULL; +#else + // no support for gzip compressed pcap files compiled in -> abort + fclose(fp); + return NULL; +#endif + } + + return pcap_dump_fopen(capinfo->handle, fp); } return NULL; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sngrep-1.5.0/src/capture.h new/sngrep-1.6.0/src/capture.h --- old/sngrep-1.5.0/src/capture.h 2022-04-26 15:59:33.000000000 +0200 +++ new/sngrep-1.6.0/src/capture.h 2022-08-31 16:02:22.000000000 +0200 @@ -139,6 +139,10 @@ struct bpf_program fp; //! libpcap dump file handler pcap_dumper_t *pd; + //! libpcap dump file name + const char *dumpfilename; + //! inode of the dump file we have open + ino_t dump_inode; //! Capture sources vector_t *sources; //! Capture Lock. Avoid parsing and handling data at the same time @@ -154,6 +158,8 @@ { //! Flag to determine if capture is running bool running; + //! Flag to determine if this capture is libpcap + bool ispcap; //! libpcap link type int link; //! libpcap link header size @@ -172,6 +178,8 @@ vector_t *ip_reasm; //! Packets pending TCP reassembly vector_t *tcp_reasm; + //! Capture thread function + void *(*capture_fn)(void *data); //! Capture thread for online capturing pthread_t capture_t; }; @@ -197,12 +205,11 @@ * @brief Online capture function * * @param device Device to start capture from - * @param outfile Dumpfile for captured packets * * @return 0 on spawn success, 1 otherwise */ int -capture_online(const char *dev, const char *outfile); +capture_online(const char *dev); /** * @brief Read from pcap file and fill sngrep sctuctures @@ -215,7 +222,7 @@ * @return 0 if load has been successfull, 1 otherwise */ int -capture_offline(const char *infile, const char *outfile); +capture_offline(const char *infile); /** * @brief Read the next package and parse SIP messages @@ -314,7 +321,7 @@ * This function is used as worker thread for capturing filtered packets and * pass them to the UI layer. */ -void +void * capture_thread(void *none); /** @@ -463,6 +470,18 @@ capture_close(); /** + * @brief Set general capture dumper + */ +void +capture_set_dumper(pcap_dumper_t *dumper, ino_t dump_inode); + +/** + * @brief Store a packet in dumper file + */ +void +capture_dump_packet(packet_t *packet); + +/** * @brief Get datalink header size * */ @@ -473,7 +492,7 @@ * @brief Open a new dumper file for capture handler */ pcap_dumper_t * -dump_open(const char *dumpfile); +dump_open(const char *dumpfile, ino_t* dump_inode); /** * @brief Store a packet in dump file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sngrep-1.5.0/src/capture_eep.c new/sngrep-1.6.0/src/capture_eep.c --- old/sngrep-1.5.0/src/capture_eep.c 2022-04-26 15:59:33.000000000 +0200 +++ new/sngrep-1.6.0/src/capture_eep.c 2022-08-31 16:02:22.000000000 +0200 @@ -53,7 +53,7 @@ capture_eep_config_t eep_cfg = { 0 }; void * -accept_eep_client(void *data); +accept_eep_client(void *info); int capture_eep_init() @@ -125,12 +125,6 @@ return 1; } - // Create a new thread for accepting client connections - if (pthread_create(&eep_cfg.server_thread, NULL, accept_eep_client, NULL) != 0) { - fprintf(stderr, "Error creating accept thread: %s\n", strerror(errno)); - return 1; - } - capture_info_t *capinfo; // Create a new structure to handle this capture source @@ -139,6 +133,10 @@ return 1; } + // Set capture thread function + capinfo->capture_fn = accept_eep_client; + capinfo->ispcap = false; + // Open capture device capinfo->handle = pcap_open_dead(DLT_EN10MB, MAXIMUM_SNAPLEN); @@ -165,9 +163,10 @@ void * -accept_eep_client(void *data) +accept_eep_client(void *info) { packet_t *pkt; + capture_info_t *capinfo = (capture_info_t *) info; // Begin accepting connections while (eep_cfg.server_sock > 0) { @@ -182,6 +181,9 @@ } } + // Mark capture as not longer running + capinfo->running = false; + // Leave the thread gracefully pthread_exit(NULL); return 0; @@ -196,7 +198,6 @@ if (eep_cfg.server_sock) { close(eep_cfg.server_sock); eep_cfg.server_sock = -1; - //pthread_join(&eep_cfg.server_thread, &ret); } } @@ -594,8 +595,8 @@ //! New created packet pointer packet_t *pkt; //! EEP client data - struct sockaddr eep_client; - socklen_t eep_client_len; + struct sockaddr_storage eep_client; + socklen_t eep_client_len=sizeof(eep_client); struct hep_hdr hdr; struct hep_timehdr hep_time; struct hep_iphdr hep_ipheader; @@ -610,7 +611,7 @@ memset(buffer, 0, MAX_CAPTURE_LEN); /* Receive EEP generic header */ - if (recvfrom(eep_cfg.server_sock, buffer, MAX_CAPTURE_LEN, 0, &eep_client, &eep_client_len) == -1) + if (recvfrom(eep_cfg.server_sock, buffer, MAX_CAPTURE_LEN, 0, (struct sockaddr*)&eep_client, &eep_client_len) == -1) return NULL; /* Copy initial bytes to HEPv2 header */ @@ -674,6 +675,12 @@ packet_set_type(pkt, PACKET_SIP_UDP); packet_set_payload(pkt, payload, header.caplen); + // We don't longer require frame payload anymore, because adding the frame to packet clones its memory + sng_free(frame_payload); + + // Store this packets in output file + capture_dump_packet(pkt); + /* FREE */ sng_free(payload); return pkt; @@ -709,8 +716,8 @@ //! Source and Destination Address address_t src, dst; //! EEP client data - struct sockaddr eep_client; - socklen_t eep_client_len; + struct sockaddr_storage eep_client; + socklen_t eep_client_len=sizeof(eep_client); //! Packet header struct pcap_pkthdr header; //! New created packet pointer @@ -721,7 +728,7 @@ if(!pkt) { /* Receive EEP generic header */ - if (recvfrom(eep_cfg.server_sock, buffer, MAX_CAPTURE_LEN, 0, &eep_client, &eep_client_len) == -1) + if (recvfrom(eep_cfg.server_sock, buffer, MAX_CAPTURE_LEN, 0, (struct sockaddr*)&eep_client, &eep_client_len) == -1) return NULL; } else { memcpy(&buffer, pkt, size); @@ -853,6 +860,12 @@ packet_set_type(pkt_new, PACKET_SIP_UDP); packet_set_payload(pkt_new, payload, header.caplen); + // We don't longer require frame payload anymore, because adding the frame to packet clones its memory + sng_free(frame_payload); + + // Store this packets in output file + capture_dump_packet(pkt_new); + /* FREE */ sng_free(payload); return pkt_new; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sngrep-1.5.0/src/capture_openssl.h new/sngrep-1.6.0/src/capture_openssl.h --- old/sngrep-1.5.0/src/capture_openssl.h 2022-04-26 15:59:33.000000000 +0200 +++ new/sngrep-1.6.0/src/capture_openssl.h 2022-08-31 16:02:22.000000000 +0200 @@ -67,10 +67,11 @@ #endif /* LibreSSL declares OPENSSL_VERSION_NUMBER == 2.0 but does not include most - * changes from OpenSSL >= 1.1 (new functions, macros, deprecations, ...) + * changes from OpenSSL >= 1.1 (new functions, macros, deprecations, ...) until + * version 3.5.0 */ #if defined(LIBRESSL_VERSION_NUMBER) -#define MODSSL_USE_OPENSSL_PRE_1_1_API (1) +#define MODSSL_USE_OPENSSL_PRE_1_1_API (LIBRESSL_VERSION_NUMBER < 0x30500000L) #else #define MODSSL_USE_OPENSSL_PRE_1_1_API (OPENSSL_VERSION_NUMBER < 0x10100000L) #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sngrep-1.5.0/src/curses/ui_manager.c new/sngrep-1.6.0/src/curses/ui_manager.c --- old/sngrep-1.5.0/src/curses/ui_manager.c 2022-04-26 15:59:33.000000000 +0200 +++ new/sngrep-1.6.0/src/curses/ui_manager.c 2022-08-31 16:02:22.000000000 +0200 @@ -192,6 +192,9 @@ // While there are still panels while ((panel = panel_below(NULL))) { + if (was_sigterm_received()) + return 0; + // Get panel interface structure ui = ui_find_by_panel(panel); @@ -445,12 +448,15 @@ cur_line =payload + i + 1; // Move to the next line if line is filled or a we reach a line break - if (column > width || payload[i] == '\n') { + if (column > width - 1 || payload[i] == '\n') { line++; column = 0; - continue; } + // No need to print new line characters + if (payload[i] == '\n') + continue; + // Put next character in position if (isascii(payload[i])) { mvwaddch(win, line, column++, payload[i]); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sngrep-1.5.0/src/curses/ui_save.c new/sngrep-1.6.0/src/curses/ui_save.c --- old/sngrep-1.5.0/src/curses/ui_save.c 2022-04-26 15:59:33.000000000 +0200 +++ new/sngrep-1.6.0/src/curses/ui_save.c 2022-08-31 16:02:22.000000000 +0200 @@ -465,7 +465,7 @@ if (info->saveformat == SAVE_PCAP || info->saveformat == SAVE_PCAP_RTP) { // Open dump file - pd = dump_open(fullfile); + pd = dump_open(fullfile, NULL); if (access(fullfile, W_OK) != 0) { dialog_run("%s", capture_last_error()); return 1; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sngrep-1.5.0/src/filter.c new/sngrep-1.6.0/src/filter.c --- old/sngrep-1.5.0/src/filter.c 2022-04-26 15:59:33.000000000 +0200 +++ new/sngrep-1.6.0/src/filter.c 2022-08-31 16:02:22.000000000 +0200 @@ -61,7 +61,29 @@ // Set new expresion values filters[type].expr = (expr) ? strdup(expr) : NULL; filters[type].regex = regex; +#elif defined(WITH_PCRE2) + pcre2_code *regex = NULL; + // If we have an expression, check if compiles before changing the filter + if (expr) { + int re_err = 0; + PCRE2_SIZE err_offset = 0; + uint32_t pcre_options = PCRE2_UNGREEDY | PCRE2_CASELESS; + + // Check if we have a valid expression + if (!(regex = pcre2_compile((PCRE2_SPTR) expr, PCRE2_ZERO_TERMINATED, pcre_options, &re_err, &err_offset, NULL))) + return 1; + } + + // Remove previous value + if (filters[type].expr) { + sng_free(filters[type].expr); + pcre2_code_free(filters[type].regex); + } + + // Set new expresion values + filters[type].expr = (expr) ? strdup(expr) : NULL; + filters[type].regex = regex; #else regex_t regex; // If we have an expression, check if compiles before changing the filter @@ -184,6 +206,11 @@ { #ifdef WITH_PCRE return pcre_exec(filter.regex, 0, data, strlen(data), 0, 0, 0, 0); +#elif defined(WITH_PCRE2) + pcre2_match_data *match_data = pcre2_match_data_create_from_pattern(filter.regex, NULL); + int ret = pcre2_match(filter.regex, (PCRE2_SPTR) data, (PCRE2_SIZE) strlen(data), 0, 0, match_data, NULL); + pcre2_match_data_free(match_data); + return (ret == PCRE2_ERROR_NOMATCH) ? 1 : 0; #else // Call doesn't match this filter return regexec(&filter.regex, data, 0, NULL, 0); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sngrep-1.5.0/src/filter.h new/sngrep-1.6.0/src/filter.h --- old/sngrep-1.5.0/src/filter.h 2022-04-26 15:59:33.000000000 +0200 +++ new/sngrep-1.6.0/src/filter.h 2022-08-31 16:02:22.000000000 +0200 @@ -43,6 +43,8 @@ #include "config.h" #ifdef WITH_PCRE #include <pcre.h> +#elif defined(WITH_PCRE2) +#include <pcre2.h> #else #include <regex.h> #endif @@ -82,6 +84,9 @@ #ifdef WITH_PCRE //! The filter compiled expression pcre *regex; +#elif defined(WITH_PCRE2) + //! The filter compiled expression + pcre2_code *regex; #else //! The filter compiled expression regex_t regex; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sngrep-1.5.0/src/hash.c new/sngrep-1.6.0/src/hash.c --- old/sngrep-1.5.0/src/hash.c 2022-04-26 15:59:33.000000000 +0200 +++ new/sngrep-1.6.0/src/hash.c 2022-08-31 16:02:22.000000000 +0200 @@ -107,6 +107,7 @@ } // Remove item memory free(entry); + return; } } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sngrep-1.5.0/src/main.c new/sngrep-1.6.0/src/main.c --- old/sngrep-1.5.0/src/main.c 2022-04-26 15:59:33.000000000 +0200 +++ new/sngrep-1.6.0/src/main.c 2022-08-31 16:02:22.000000000 +0200 @@ -327,6 +327,8 @@ } } + setup_sigterm_handler(); + #if defined(WITH_GNUTLS) || defined(WITH_OPENSSL) // Set capture decrypt key file capture_set_keyfile(keyfile); @@ -370,17 +372,24 @@ // If we have an input file, load it for (i = 0; i < vector_count(infiles); i++) { // Try to load file - if (capture_offline(vector_item(infiles, i), outfile) != 0) + if (capture_offline(vector_item(infiles, i)) != 0) return 1; } // If we have an input device, load it for (i = 0; i < vector_count(indevices); i++) { // Check if all capture data is valid - if (capture_online(vector_item(indevices, i), outfile) != 0) + if (capture_online(vector_item(indevices, i)) != 0) return 1; } + if (outfile) + { + ino_t dump_inode; + pcap_dumper_t *dumper = dump_open(outfile, &dump_inode); + capture_set_dumper(dumper, dump_inode); + } + // Remove Input files vector vector_destroy(infiles); @@ -436,13 +445,13 @@ ui_wait_for_input(); } else { setbuf(stdout, NULL); - while(capture_is_running()) { + while(capture_is_running() && !was_sigterm_received()) { if (!quiet) - printf("\rDialog count: %d", sip_calls_count()); + printf("\rDialog count: %d", sip_calls_count_unrotated()); usleep(500 * 1000); } if (!quiet) - printf("\rDialog count: %d\n", sip_calls_count()); + printf("\rDialog count: %d\n", sip_calls_count_unrotated()); } // Capture deinit diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sngrep-1.5.0/src/sip.c new/sngrep-1.6.0/src/sip.c --- old/sngrep-1.5.0/src/sip.c 2022-04-26 15:59:33.000000000 +0200 +++ new/sngrep-1.6.0/src/sip.c 2022-08-31 16:02:22.000000000 +0200 @@ -149,6 +149,7 @@ calls.only_calls = only_calls; calls.ignore_incomplete = no_incomplete; calls.last_index = 0; + calls.call_count_unrotated = 0; // Create a vector to store calls calls.list = vector_create(200, 50); @@ -438,6 +439,7 @@ if (newcall) { // Append this call to the call list vector_append(calls.list, call); + ++calls.call_count_unrotated; } // Mark the list as changed @@ -467,6 +469,12 @@ return vector_count(calls.list); } +int +sip_calls_count_unrotated() +{ + return calls.call_count_unrotated; +} + vector_iter_t sip_calls_iterator() { @@ -832,6 +840,17 @@ // Check if we have a valid expression calls.match_regex = pcre_compile(expr, pflags, &re_err, &err_offset, 0); return calls.match_regex == NULL; +#elif defined(WITH_PCRE2) + int re_err = 0; + PCRE2_SIZE err_offset = 0; + uint32_t pflags = PCRE2_UNGREEDY | PCRE2_CASELESS; + + if (insensitive) + pflags |= PCRE2_CASELESS; + + // Check if we have a valid expression + calls.match_regex = pcre2_compile((PCRE2_SPTR) expr, PCRE2_ZERO_TERMINATED, pflags, &re_err, &err_offset, NULL); + return calls.match_regex == NULL; #else int cflags = REG_EXTENDED; @@ -864,6 +883,16 @@ } return 0 == calls.match_invert; +#elif defined(WITH_PCRE2) + pcre2_match_data *match_data = pcre2_match_data_create_from_pattern(calls.match_regex, NULL); + int ret = pcre2_match(calls.match_regex, (PCRE2_SPTR) payload, (PCRE2_SIZE) strlen(payload), 0, 0, match_data, NULL); + pcre2_match_data_free(match_data); + + if (ret == PCRE2_ERROR_NOMATCH) { + return 1 == calls.match_invert; + } + + return 0 == calls.match_invert; #else // Check if payload matches the given expresion return (regexec(&calls.match_regex, payload, 0, NULL, 0) == calls.match_invert); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sngrep-1.5.0/src/sip.h new/sngrep-1.6.0/src/sip.h --- old/sngrep-1.5.0/src/sip.h 2022-04-26 15:59:33.000000000 +0200 +++ new/sngrep-1.6.0/src/sip.h 2022-08-31 16:02:22.000000000 +0200 @@ -37,6 +37,8 @@ #include <regex.h> #ifdef WITH_PCRE #include <pcre.h> +#elif defined(WITH_PCRE2) +#include <pcre2.h> #endif #include "sip_call.h" #include "vector.h" @@ -130,6 +132,8 @@ //! Call-Ids hash table htable_t *callids; + //! Full count of all captured calls, regardless of rotation + int call_count_unrotated; // Max call limit int limit; //! Only store dialogs starting with INVITE @@ -141,6 +145,9 @@ #ifdef WITH_PCRE //! Compiled match expression pcre *match_regex; +#elif defined(WITH_PCRE2) + //! Compiled match expression + pcre2_code *match_regex; #else //! Compiled match expression regex_t match_regex; @@ -255,6 +262,14 @@ sip_calls_count(); /** + * @brief Getter for full count of calls since program start + * + * @return full number of calls since program start, regardless of rotation + */ +int +sip_calls_count_unrotated(); + +/** * @brief Return an iterator of call list */ vector_iter_t diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sngrep-1.5.0/src/sip_msg.c new/sngrep-1.6.0/src/sip_msg.c --- old/sngrep-1.5.0/src/sip_msg.c 2022-04-26 15:59:33.000000000 +0200 +++ new/sngrep-1.6.0/src/sip_msg.c 2022-08-31 16:02:22.000000000 +0200 @@ -145,13 +145,15 @@ sprintf(value, "%.*s", SIP_ATTR_MAXLEN, msg->sip_to); break; case SIP_ATTR_SIPFROMUSER: - if ((ar = strchr(msg->sip_from, '@'))) { + if (msg->sip_from && (ar = strchr(msg->sip_from, '@'))) { strncpy(value, msg->sip_from, ar - msg->sip_from); + value[ar - msg->sip_from] = '\0'; } break; case SIP_ATTR_SIPTOUSER: - if ((ar = strchr(msg->sip_to, '@'))) { + if (msg->sip_to && (ar = strchr(msg->sip_to, '@'))) { strncpy(value, msg->sip_to, ar - msg->sip_to); + value[ar - msg->sip_to] = '\0'; } break; case SIP_ATTR_DATE: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sngrep-1.5.0/src/util.c new/sngrep-1.6.0/src/util.c --- old/sngrep-1.5.0/src/util.c 2022-04-26 15:59:33.000000000 +0200 +++ new/sngrep-1.6.0/src/util.c 2022-08-31 16:02:22.000000000 +0200 @@ -32,8 +32,45 @@ #include <stdio.h> #include <stdlib.h> #include <ctype.h> +#include <signal.h> #include "util.h" +#if __STDC_VERSION__ >= 201112L && __STDC_NO_ATOMICS__ != 1 +// modern C with atomics +#include <stdatomic.h> +typedef atomic_int signal_flag_type; +#else +// no atomics available +typedef volatile sig_atomic_t signal_flag_type; +#endif + +static signal_flag_type sigterm_received = 0; + +static void sigterm_handler(int signum) +{ + sigterm_received = 1; +} + +void setup_sigterm_handler(void) +{ + // set up SIGTERM handler (also used for SIGINT and SIGQUIT) + // the handler will be served by any of the running threads + // so we just set a flag and check it in one of the two available + // main loops of the program (main for --no-interface and + // ui_wait_for_input() for curses) + + if (signal(SIGTERM, sigterm_handler) == SIG_ERR) + exit(EXIT_FAILURE); + if (signal(SIGINT, sigterm_handler) == SIG_ERR) + exit(EXIT_FAILURE); + if (signal(SIGQUIT, sigterm_handler) == SIG_ERR) + exit(EXIT_FAILURE); +} + +bool was_sigterm_received(void) +{ + return (sigterm_received == 1); +} void * sng_malloc(size_t size) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sngrep-1.5.0/src/util.h new/sngrep-1.6.0/src/util.h --- old/sngrep-1.5.0/src/util.h 2022-04-26 15:59:33.000000000 +0200 +++ new/sngrep-1.6.0/src/util.h 2022-08-31 16:02:22.000000000 +0200 @@ -99,4 +99,16 @@ char * strtrim(char *str); +/** + * @brief Set up handler for SIGTERM, SIGINT and SIGQUIT + */ +void setup_sigterm_handler(void); + +/** + * @brief Check if SIGTERM, SIGINT or SIGQUIT were received + * + * @return true if any of the exit signals were received + */ +bool was_sigterm_received(void); + #endif /* __SNGREP_UTIL_H */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sngrep-1.5.0/tests/test_007.c new/sngrep-1.6.0/tests/test_007.c --- old/sngrep-1.5.0/tests/test_007.c 2022-04-26 15:59:33.000000000 +0200 +++ new/sngrep-1.6.0/tests/test_007.c 2022-08-31 16:02:22.000000000 +0200 @@ -29,8 +29,8 @@ #include "config.h" #include <assert.h> #include <stdlib.h> -#include "vector.h" -#include "util.h" +#include "../src/vector.h" +#include "../src/util.h" int main () { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sngrep-1.5.0/tests/test_010.c new/sngrep-1.6.0/tests/test_010.c --- old/sngrep-1.5.0/tests/test_010.c 2022-04-26 15:59:33.000000000 +0200 +++ new/sngrep-1.6.0/tests/test_010.c 2022-08-31 16:02:22.000000000 +0200 @@ -29,7 +29,7 @@ #include "config.h" #include <assert.h> #include <string.h> -#include "hash.h" +#include "../src/hash.h" int main () {