From 3698268efd94ef9d11aeff143067b938280cf289 Mon Sep 17 00:00:00 2001 From: Shane Alcock Date: Fri, 24 Nov 2023 15:29:04 +1300 Subject: [PATCH 01/12] ndagtcp: fix bug where ERF header length could be miscalculated This was causing errors when decoding these packets, as the packet->payload was not pointing at the start of the IP header. --- lib/format_erf.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/format_erf.c b/lib/format_erf.c index c51fcddc..3665f49d 100644 --- a/lib/format_erf.c +++ b/lib/format_erf.c @@ -154,6 +154,7 @@ int erf_get_padding(const libtrace_packet_t *packet) case TRACE_FORMAT_NDAG: case TRACE_FORMAT_RAWERF: case TRACE_FORMAT_DPDK_NDAG: + case TRACE_FORMAT_NDAG_TCP: switch((erfptr->type & 0x7f)) { case TYPE_ETH: case TYPE_COLOR_ETH: From 2b3e302a60f9ce034a46ebae267e58ae5af2f2f9 Mon Sep 17 00:00:00 2001 From: Shane Alcock Date: Fri, 24 Nov 2023 15:30:35 +1300 Subject: [PATCH 02/12] traceucast: better handling of client disconnection Instead of exiting with SIGPIPE, traceucast will now attempt to continually reconnect to the client if they disappear for any reason. --- tools/tracemcast/traceucast.c | 219 ++++++++++++++++++++++------------ 1 file changed, 146 insertions(+), 73 deletions(-) diff --git a/tools/tracemcast/traceucast.c b/tools/tracemcast/traceucast.c index 0b115a9f..d79a2a3f 100644 --- a/tools/tracemcast/traceucast.c +++ b/tools/tracemcast/traceucast.c @@ -255,54 +255,132 @@ static void *init_reader_thread(libtrace_t *trace, return rdata; } -static int send_ndag_packet(read_thread_data_t *rdata) { +static int connect_stream_fd(read_thread_data_t *rdata, + struct global_params *gparams) { - int s; + int fd; + uint8_t block; + + if (rdata->livesource) { + block = 0; + } else { + block = 1; + } + fd = create_stream_socket(rdata->streamport, + gparams->clientaddr, &(rdata->target), block); + + if (fd == 0) { + return 0; + } + + if (fd == -1) { + if (errno != ECONNREFUSED) { + fprintf(stderr, "traceucast: failed to create TCP socket for reader thread %d\n", rdata->threadid); + return -1; + } else { + return 0; + } + } else if (rdata->target == NULL) { + fprintf(stderr, "traceucast: failed to get addrinfo for reader socket %d\n", rdata->threadid); + close(rdata->streamfd); + rdata->streamfd = -1; + return -1; + } + rdata->streamfd = fd; + return fd; +} + +#define HANDLE_SEND_ERROR \ + if (s < 0) { \ + if ((errno == EAGAIN || errno == EWOULDBLOCK) && attempts < 20) { \ + attempts ++; \ + usleep(backoff); \ + backoff = backoff * 2; \ + if (backoff > 1000000) { \ + backoff = 1000000; \ + } \ + continue; \ + } \ + fprintf(stderr, "traceucast: thread %d failed to send streamed ERF packet: %s\n", \ + rdata->threadid, strerror(errno)); \ + close(rdata->streamfd); \ + rdata->streamfd = -1; \ + usleep(200000); \ + continue; \ + } + +static int send_ndag_packet(read_thread_data_t *rdata, + struct global_params *gparams) { + + int s, r; int rem = (rdata->writeptr - rdata->pbuffer); int sentsofar = 0; - int ret = 0; int attempts = 0; int backoff = 5000; + int firstsend = 0; + int fs_amount = 0; + rdata->encaphdr->recordcount = ntohs(rdata->reccount); while (rem > 0) { - s = send(rdata->streamfd, rdata->pbuffer + sentsofar, rem, MSG_DONTWAIT); - - if (s < 0) { - if ((errno == EAGAIN || errno == EWOULDBLOCK) && attempts < 20) { - attempts ++; - usleep(backoff); - backoff = backoff * 2; - if (backoff > 1000000) { - backoff = 1000000; + if (rdata->streamfd == -1) { + if ((r = connect_stream_fd(rdata, gparams)) < 0) { + rdata->failed = 1; + trace_interrupt(); + return -1; + } + if (r == 0) { + if (rdata->livesource) { + return 0; } + sleep(1); continue; } - fprintf(stderr, "traceucast: thread %d failed to send streamed ERF packet: %s\n", - rdata->threadid, strerror(errno)); - fprintf(stderr, "%u\n", rdata->seqno); - ret = -1; - break; + fprintf(stderr, + "traceucast: streaming thread %d established connection\n", + rdata->threadid); } - sentsofar += s; - rem -= s; + if (firstsend == 0 && rem > 8) { + /* try to detect a broken pipe by attempting a "canary" send + * of 8 bytes so that the main send is more likely to trigger + * EPIPE + */ + s = send(rdata->streamfd, rdata->pbuffer, 8, + MSG_DONTWAIT | MSG_NOSIGNAL); + HANDLE_SEND_ERROR + fs_amount = s; + + s = send(rdata->streamfd, rdata->pbuffer + fs_amount, + rem - fs_amount, MSG_DONTWAIT | MSG_NOSIGNAL); + HANDLE_SEND_ERROR + sentsofar += (s + fs_amount); + rem -= (s + fs_amount); + firstsend = 1; + } else { + s = send(rdata->streamfd, rdata->pbuffer + sentsofar, + rem, MSG_DONTWAIT | MSG_NOSIGNAL); + HANDLE_SEND_ERROR + sentsofar += s; + rem -= s; + } } rdata->writeptr = rdata->pbuffer; rdata->encaphdr = NULL; rdata->reccount = 0; - return ret; + return sentsofar; } static void halt_reader_thread(libtrace_t *trace UNUSED, - libtrace_thread_t *t UNUSED, void *global UNUSED, void *tls) { + libtrace_thread_t *t UNUSED, void *global, void *tls) { read_thread_data_t *rdata = (read_thread_data_t *)tls; + struct global_params *gparams = (struct global_params *)global; if (rdata->writeptr > rdata->pbuffer) { - send_ndag_packet(rdata); + send_ndag_packet(rdata, gparams); } if (rdata->pbuffer) { @@ -354,15 +432,16 @@ static uint16_t construct_erf_header(read_thread_data_t *rdata, } static void tick_reader_thread(libtrace_t *trace UNUSED, - libtrace_thread_t *t UNUSED, void *global UNUSED, void *tls, + libtrace_thread_t *t UNUSED, void *global, void *tls, uint64_t order) { read_thread_data_t *rdata = (read_thread_data_t *)tls; + struct global_params *gparams = (struct global_params *)global; if (rdata->writeptr > rdata->pbuffer && (order >> 32) >= rdata->lastsend + 3) { - if (send_ndag_packet(rdata) < 0) { + if (send_ndag_packet(rdata, gparams) < 0) { rdata->failed = 1; } rdata->lastsend = (order >> 32); @@ -379,6 +458,7 @@ static libtrace_packet_t *packet_reader_thread(libtrace_t *trace UNUSED, uint32_t rem; void *l2; uint64_t erfts; + int r; if (rdata->failed) { trace_interrupt(); @@ -389,36 +469,6 @@ static libtrace_packet_t *packet_reader_thread(libtrace_t *trace UNUSED, return packet; } - if (rdata->streamfd == -1) { - int fd; - uint8_t block; - - if (rdata->livesource) { - block = 0; - } else { - block = 1; - } - fd = create_stream_socket(rdata->streamport, - gparams->clientaddr, &(rdata->target), block); - - if (fd == 0) { - return packet; - } - if (fd == -1) { - fprintf(stderr, "traceucast: failed to create TCP socket for reader thread %d\n", rdata->threadid); - trace_interrupt(); - return packet; - - } else if (rdata->target == NULL) { - fprintf(stderr, "traceucast: failed to get addrinfo for reader socket %d\n", rdata->threadid); - close(rdata->streamfd); - rdata->streamfd = -1; - trace_interrupt(); - return packet; - } - rdata->streamfd = fd; - } - /* first, check if there is going to be space in the buffer for this * packet + an ERF header */ l2 = trace_get_layer2(packet, <ype, &rem); @@ -432,9 +482,12 @@ static libtrace_packet_t *packet_reader_thread(libtrace_t *trace UNUSED, */ if (rdata->writeptr > rdata->pbuffer + sizeof(ndag_common_t) + sizeof(ndag_encap_t)) { - - if (send_ndag_packet(rdata) < 0) { + if ((r = send_ndag_packet(rdata, gparams)) < 0) { rdata->failed = 1; + close(rdata->streamfd); + rdata->streamfd = -1; + return packet; + } else if (r == 0) { return packet; } rdata->lastsend = (erfts >> 32); @@ -471,10 +524,11 @@ static libtrace_packet_t *packet_reader_thread(libtrace_t *trace UNUSED, /* if the buffer is close to full, just send the buffer anyway */ if (MAX_PACKET_SIZE - (rdata->writeptr - rdata->pbuffer) - (dag_record_size + 2) < 64) { - if (send_ndag_packet(rdata) < 0) { + if ((r = send_ndag_packet(rdata, gparams)) < 0) { rdata->failed = 1; + } else if (r != 0) { + rdata->lastsend = (erfts >> 32); } - rdata->lastsend = (erfts >> 32); } return packet; @@ -574,22 +628,11 @@ static uint32_t form_beacon(char **buffer, struct beacon_params *bparams) { static void *beaconer_thread(void *tdata) { struct beacon_params *bparams = (struct beacon_params *)tdata; - int sock; + int sock = -1; char *beaconpacket = NULL; uint32_t beaconsize; struct addrinfo *targetinfo = NULL; - sock = create_stream_socket(bparams->beaconport, - bparams->gparams->clientaddr, &targetinfo, 1); - - if (sock == -1) { - fprintf(stderr, "traceucast: failed to create TCP socket for beaconer thread\n"); - halted = 1; - } else if (targetinfo == NULL) { - fprintf(stderr, "traceucast: failed to get addrinfo for beaconer socket\n"); - halted = 1; - } - beaconsize = form_beacon(&beaconpacket, bparams); if (beaconsize <= 0 || beaconpacket == NULL) { @@ -597,10 +640,40 @@ static void *beaconer_thread(void *tdata) { } while (!halted) { - if (send(sock, beaconpacket, beaconsize, 0) != beaconsize) { + if (sock == -1) { + sock = create_stream_socket(bparams->beaconport, + bparams->gparams->clientaddr, &targetinfo, 1); + } + + if (sock == 0) { + sleep(1); + continue; + } + + if (sock == -1) { + if (errno != ECONNREFUSED) { + fprintf(stderr, + "traceucast: failed to create TCP socket for beacon thread\n"); + halted = 1; + break; + } else { + sleep(1); + continue; + } + } else if (targetinfo == NULL) { + fprintf(stderr, + "traceucast: failed to get addrinfo for beaconer socket\n"); + halted = 1; + break; + } + + if (send(sock, beaconpacket, beaconsize, MSG_NOSIGNAL) != beaconsize) { fprintf(stderr, "traceucast: failed to send a beacon packet: %s\n", strerror(errno)); - break; + close(sock); + sock = -1; + usleep(200000); + continue; } usleep(1000 * bparams->frequency); } @@ -611,7 +684,7 @@ static void *beaconer_thread(void *tdata) { if (targetinfo) { free(targetinfo); } - if (sock >= 0) { + if (sock > 0) { close(sock); } From a767a0bf288f8433eb4945912eb963754db653b8 Mon Sep 17 00:00:00 2001 From: Shane Alcock Date: Fri, 24 Nov 2023 15:35:44 +1300 Subject: [PATCH 03/12] clang-format fixes --- tools/tracemcast/traceucast.c | 362 ++++++++++++++++++---------------- 1 file changed, 190 insertions(+), 172 deletions(-) diff --git a/tools/tracemcast/traceucast.c b/tools/tracemcast/traceucast.c index d79a2a3f..94fb940b 100644 --- a/tools/tracemcast/traceucast.c +++ b/tools/tracemcast/traceucast.c @@ -256,143 +256,157 @@ static void *init_reader_thread(libtrace_t *trace, } static int connect_stream_fd(read_thread_data_t *rdata, - struct global_params *gparams) { + struct global_params *gparams) +{ - int fd; - uint8_t block; + int fd; + uint8_t block; - if (rdata->livesource) { - block = 0; - } else { - block = 1; - } - fd = create_stream_socket(rdata->streamport, - gparams->clientaddr, &(rdata->target), block); + if (rdata->livesource) { + block = 0; + } else { + block = 1; + } + fd = create_stream_socket(rdata->streamport, gparams->clientaddr, + &(rdata->target), block); - if (fd == 0) { - return 0; - } + if (fd == 0) { + return 0; + } - if (fd == -1) { - if (errno != ECONNREFUSED) { - fprintf(stderr, "traceucast: failed to create TCP socket for reader thread %d\n", rdata->threadid); - return -1; - } else { - return 0; + if (fd == -1) { + if (errno != ECONNREFUSED) { + fprintf(stderr, + "traceucast: failed to create TCP socket for " + "reader thread %d\n", + rdata->threadid); + return -1; + } else { + return 0; + } + } else if (rdata->target == NULL) { + fprintf( + stderr, + "traceucast: failed to get addrinfo for reader socket %d\n", + rdata->threadid); + close(rdata->streamfd); + rdata->streamfd = -1; + return -1; } - } else if (rdata->target == NULL) { - fprintf(stderr, "traceucast: failed to get addrinfo for reader socket %d\n", rdata->threadid); - close(rdata->streamfd); - rdata->streamfd = -1; - return -1; - } - rdata->streamfd = fd; - return fd; + rdata->streamfd = fd; + return fd; } -#define HANDLE_SEND_ERROR \ - if (s < 0) { \ - if ((errno == EAGAIN || errno == EWOULDBLOCK) && attempts < 20) { \ - attempts ++; \ - usleep(backoff); \ - backoff = backoff * 2; \ - if (backoff > 1000000) { \ - backoff = 1000000; \ - } \ - continue; \ - } \ - fprintf(stderr, "traceucast: thread %d failed to send streamed ERF packet: %s\n", \ - rdata->threadid, strerror(errno)); \ - close(rdata->streamfd); \ - rdata->streamfd = -1; \ - usleep(200000); \ - continue; \ - } +#define HANDLE_SEND_ERROR \ + if (s < 0) { \ + if ((errno == EAGAIN || errno == EWOULDBLOCK) && \ + attempts < 20) { \ + attempts++; \ + usleep(backoff); \ + backoff = backoff * 2; \ + if (backoff > 1000000) { \ + backoff = 1000000; \ + } \ + continue; \ + } \ + fprintf(stderr, \ + "traceucast: thread %d failed to send streamed ERF " \ + "packet: %s\n", \ + rdata->threadid, strerror(errno)); \ + close(rdata->streamfd); \ + rdata->streamfd = -1; \ + usleep(200000); \ + continue; \ + } static int send_ndag_packet(read_thread_data_t *rdata, - struct global_params *gparams) { - - int s, r; - int rem = (rdata->writeptr - rdata->pbuffer); - int sentsofar = 0; - int attempts = 0; - int backoff = 5000; - - int firstsend = 0; - int fs_amount = 0; - - rdata->encaphdr->recordcount = ntohs(rdata->reccount); - - while (rem > 0) { - if (rdata->streamfd == -1) { - if ((r = connect_stream_fd(rdata, gparams)) < 0) { - rdata->failed = 1; - trace_interrupt(); - return -1; - } - if (r == 0) { - if (rdata->livesource) { - return 0; + struct global_params *gparams) +{ + + int s, r; + int rem = (rdata->writeptr - rdata->pbuffer); + int sentsofar = 0; + int attempts = 0; + int backoff = 5000; + + int firstsend = 0; + int fs_amount = 0; + + rdata->encaphdr->recordcount = ntohs(rdata->reccount); + + while (rem > 0) { + if (rdata->streamfd == -1) { + if ((r = connect_stream_fd(rdata, gparams)) < 0) { + rdata->failed = 1; + trace_interrupt(); + return -1; + } + if (r == 0) { + if (rdata->livesource) { + return 0; + } + sleep(1); + continue; + } + fprintf(stderr, + "traceucast: streaming thread %d established " + "connection\n", + rdata->threadid); } - sleep(1); - continue; - } - fprintf(stderr, - "traceucast: streaming thread %d established connection\n", - rdata->threadid); - } - if (firstsend == 0 && rem > 8) { - /* try to detect a broken pipe by attempting a "canary" send - * of 8 bytes so that the main send is more likely to trigger - * EPIPE - */ - s = send(rdata->streamfd, rdata->pbuffer, 8, - MSG_DONTWAIT | MSG_NOSIGNAL); - HANDLE_SEND_ERROR - fs_amount = s; - - s = send(rdata->streamfd, rdata->pbuffer + fs_amount, - rem - fs_amount, MSG_DONTWAIT | MSG_NOSIGNAL); - HANDLE_SEND_ERROR - sentsofar += (s + fs_amount); - rem -= (s + fs_amount); - firstsend = 1; - } else { - s = send(rdata->streamfd, rdata->pbuffer + sentsofar, - rem, MSG_DONTWAIT | MSG_NOSIGNAL); - HANDLE_SEND_ERROR - sentsofar += s; - rem -= s; + if (firstsend == 0 && rem > 8) { + /* try to detect a broken pipe by attempting a "canary" + * send of 8 bytes so that the main send is more likely + * to trigger EPIPE + */ + s = send(rdata->streamfd, rdata->pbuffer, 8, + MSG_DONTWAIT | MSG_NOSIGNAL); + HANDLE_SEND_ERROR + fs_amount = s; + + s = send(rdata->streamfd, rdata->pbuffer + fs_amount, + rem - fs_amount, MSG_DONTWAIT | MSG_NOSIGNAL); + HANDLE_SEND_ERROR + sentsofar += (s + fs_amount); + rem -= (s + fs_amount); + firstsend = 1; + } else { + s = send(rdata->streamfd, rdata->pbuffer + sentsofar, + rem, MSG_DONTWAIT | MSG_NOSIGNAL); + HANDLE_SEND_ERROR + sentsofar += s; + rem -= s; + } } - } - rdata->writeptr = rdata->pbuffer; - rdata->encaphdr = NULL; - rdata->reccount = 0; - return sentsofar; + rdata->writeptr = rdata->pbuffer; + rdata->encaphdr = NULL; + rdata->reccount = 0; + return sentsofar; } static void halt_reader_thread(libtrace_t *trace UNUSED, - libtrace_thread_t *t UNUSED, void *global, void *tls) { + libtrace_thread_t *t UNUSED, void *global, + void *tls) +{ - read_thread_data_t *rdata = (read_thread_data_t *)tls; - struct global_params *gparams = (struct global_params *)global; + read_thread_data_t *rdata = (read_thread_data_t *)tls; + struct global_params *gparams = (struct global_params *)global; - if (rdata->writeptr > rdata->pbuffer) { - send_ndag_packet(rdata, gparams); - } + if (rdata->writeptr > rdata->pbuffer) { + send_ndag_packet(rdata, gparams); + } - if (rdata->pbuffer) { - free(rdata->pbuffer); - } - if (rdata->target) { - freeaddrinfo(rdata->target); - } - if (rdata->streamfd != -1) { - close(rdata->streamfd); - } - free(rdata); + if (rdata->pbuffer) { + free(rdata->pbuffer); + } + if (rdata->target) { + freeaddrinfo(rdata->target); + } + if (rdata->streamfd != -1) { + close(rdata->streamfd); + } + free(rdata); } static uint16_t construct_erf_header(read_thread_data_t *rdata, @@ -432,20 +446,21 @@ static uint16_t construct_erf_header(read_thread_data_t *rdata, } static void tick_reader_thread(libtrace_t *trace UNUSED, - libtrace_thread_t *t UNUSED, void *global, void *tls, - uint64_t order) { + libtrace_thread_t *t UNUSED, void *global, + void *tls, uint64_t order) +{ - read_thread_data_t *rdata = (read_thread_data_t *)tls; - struct global_params *gparams = (struct global_params *)global; + read_thread_data_t *rdata = (read_thread_data_t *)tls; + struct global_params *gparams = (struct global_params *)global; - if (rdata->writeptr > rdata->pbuffer && + if (rdata->writeptr > rdata->pbuffer && (order >> 32) >= rdata->lastsend + 3) { - if (send_ndag_packet(rdata, gparams) < 0) { - rdata->failed = 1; + if (send_ndag_packet(rdata, gparams) < 0) { + rdata->failed = 1; + } + rdata->lastsend = (order >> 32); } - rdata->lastsend = (order >> 32); - } } static libtrace_packet_t *packet_reader_thread(libtrace_t *trace UNUSED, @@ -482,14 +497,14 @@ static libtrace_packet_t *packet_reader_thread(libtrace_t *trace UNUSED, */ if (rdata->writeptr > rdata->pbuffer + sizeof(ndag_common_t) + sizeof(ndag_encap_t)) { - if ((r = send_ndag_packet(rdata, gparams)) < 0) { - rdata->failed = 1; - close(rdata->streamfd); - rdata->streamfd = -1; - return packet; - } else if (r == 0) { - return packet; - } + if ((r = send_ndag_packet(rdata, gparams)) < 0) { + rdata->failed = 1; + close(rdata->streamfd); + rdata->streamfd = -1; + return packet; + } else if (r == 0) { + return packet; + } rdata->lastsend = (erfts >> 32); } } @@ -524,11 +539,11 @@ static libtrace_packet_t *packet_reader_thread(libtrace_t *trace UNUSED, /* if the buffer is close to full, just send the buffer anyway */ if (MAX_PACKET_SIZE - (rdata->writeptr - rdata->pbuffer) - (dag_record_size + 2) < 64) { - if ((r = send_ndag_packet(rdata, gparams)) < 0) { - rdata->failed = 1; - } else if (r != 0) { - rdata->lastsend = (erfts >> 32); - } + if ((r = send_ndag_packet(rdata, gparams)) < 0) { + rdata->failed = 1; + } else if (r != 0) { + rdata->lastsend = (erfts >> 32); + } } return packet; @@ -640,41 +655,44 @@ static void *beaconer_thread(void *tdata) { } while (!halted) { - if (sock == -1) { - sock = create_stream_socket(bparams->beaconport, - bparams->gparams->clientaddr, &targetinfo, 1); - } + if (sock == -1) { + sock = create_stream_socket(bparams->beaconport, + bparams->gparams->clientaddr, + &targetinfo, 1); + } - if (sock == 0) { - sleep(1); - continue; - } + if (sock == 0) { + sleep(1); + continue; + } - if (sock == -1) { - if (errno != ECONNREFUSED) { - fprintf(stderr, - "traceucast: failed to create TCP socket for beacon thread\n"); - halted = 1; - break; - } else { - sleep(1); - continue; + if (sock == -1) { + if (errno != ECONNREFUSED) { + fprintf(stderr, "traceucast: failed to create TCP " + "socket for beacon thread\n"); + halted = 1; + break; + } else { + sleep(1); + continue; + } + } else if (targetinfo == NULL) { + fprintf(stderr, "traceucast: failed to get addrinfo for " + "beaconer socket\n"); + halted = 1; + break; } - } else if (targetinfo == NULL) { - fprintf(stderr, - "traceucast: failed to get addrinfo for beaconer socket\n"); - halted = 1; - break; - } - if (send(sock, beaconpacket, beaconsize, MSG_NOSIGNAL) != beaconsize) { - fprintf(stderr, "traceucast: failed to send a beacon packet: %s\n", - strerror(errno)); - close(sock); - sock = -1; - usleep(200000); - continue; - } + if (send(sock, beaconpacket, beaconsize, MSG_NOSIGNAL) != + beaconsize) { + fprintf(stderr, + "traceucast: failed to send a beacon packet: %s\n", + strerror(errno)); + close(sock); + sock = -1; + usleep(200000); + continue; + } usleep(1000 * bparams->frequency); } @@ -685,7 +703,7 @@ static void *beaconer_thread(void *tdata) { free(targetinfo); } if (sock > 0) { - close(sock); + close(sock); } pthread_exit(NULL); From a884abcf70b102de12443cefb6353bfa3ce9658d Mon Sep 17 00:00:00 2001 From: Shane Alcock Date: Sat, 25 Nov 2023 10:32:06 +1300 Subject: [PATCH 04/12] Bump version to 4.0.24 --- README | 2 +- configure.in | 4 ++-- debian/changelog | 9 +++++++++ lib/Makefile.am | 2 +- rpm/libtrace4.spec | 5 ++++- 5 files changed, 17 insertions(+), 5 deletions(-) diff --git a/README b/README index 568f35fa..9df3f106 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ -libtrace 4.0.23 +libtrace 4.0.24 Code and documentation added since version 4.0.20 is Copyright (c) 2023 Shane Alcock and has been contributed as per diff --git a/configure.in b/configure.in index 06ba372c..72e56831 100644 --- a/configure.in +++ b/configure.in @@ -3,11 +3,11 @@ # Now you only need to update the version number in two places - below, # and in the README -AC_INIT([libtrace],[4.0.23],[shane@alcock.co.nz],[libtrace]) +AC_INIT([libtrace],[4.0.24],[shane@alcock.co.nz],[libtrace]) LIBTRACE_MAJOR=4 LIBTRACE_MID=0 -LIBTRACE_MINOR=23 +LIBTRACE_MINOR=24 # OpenSolaris hides libraries like libncurses in /usr/gnu/lib, which is not # searched by default - add it to LDFLAGS so we at least have a chance of diff --git a/debian/changelog b/debian/changelog index fdf18b27..7f46d973 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,12 @@ +libtrace4 (4.0.24-1) unstable; urgency=medium + + * ndagtcp: fix miscalculation of ERF header length that would + prevent packets from being able to be decoded correctly. + * traceucast: do not exit if the client disconnects, instead try to + reconnect and resume unicasting. + + -- Shane Alcock Sat, 25 Nov 2023 09:58:02 +1300 + libtrace4 (4.0.23-1) unstable; urgency=medium * Add new tool: traceucast, a TCP unicast variant of tracemcast. diff --git a/lib/Makefile.am b/lib/Makefile.am index fafa62b5..f4f0e296 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -146,7 +146,7 @@ endif AM_CPPFLAGS= @ADD_INCLS@ libtrace_la_LIBADD = @LIBTRACE_LIBS@ @LTLIBOBJS@ $(DPDKLIBS) -libtrace_la_LDFLAGS=-version-info 7:7:0 @ADD_LDFLAGS@ +libtrace_la_LDFLAGS=-version-info 7:8:0 @ADD_LDFLAGS@ dagapi.c: cp @DAG_TOOLS_DIR@/dagapi.c . diff --git a/rpm/libtrace4.spec b/rpm/libtrace4.spec index 11e8935f..c3e7546d 100644 --- a/rpm/libtrace4.spec +++ b/rpm/libtrace4.spec @@ -1,5 +1,5 @@ Name: libtrace4 -Version: 4.0.23 +Version: 4.0.24 Release: 1%{?dist} Summary: C Library for capturing and analysing network packets @@ -127,6 +127,9 @@ find $RPM_BUILD_ROOT -name '*.la' -exec rm -f {} ';' %changelog +* Sat Nov 25 2023 Shane Alcock - 4.0.24-1 +- Updated for 4.0.24 release + * Fri Nov 10 2023 Shane Alcock - 4.0.23-1 - Updated for 4.0.23 release From 34ce09db5b4051df457747f9b4426c3703a24df3 Mon Sep 17 00:00:00 2001 From: Shane Alcock Date: Fri, 1 Dec 2023 18:20:55 +1300 Subject: [PATCH 05/12] traceucast: fix some reconnection bugs * fix endless reconnect loop under certain circumstances * fix threading race when halting via Ctrl-C --- tools/tracemcast/traceucast.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/tools/tracemcast/traceucast.c b/tools/tracemcast/traceucast.c index 94fb940b..47ddd8e4 100644 --- a/tools/tracemcast/traceucast.c +++ b/tools/tracemcast/traceucast.c @@ -118,7 +118,7 @@ volatile int halted = 0; static void cleanup_signal(int signal UNUSED) { if (currenttrace) { - trace_pstop(currenttrace); + trace_interrupt(); } halted = 1; } @@ -130,7 +130,7 @@ static int create_stream_socket(uint16_t port, char *clientaddr, struct addrinfo *gotten; char portstr[16]; int sock; - int bufsize, reuse=1; + int bufsize, reuse=1, connected = 0; hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; @@ -201,9 +201,14 @@ static int create_stream_socket(uint16_t port, char *clientaddr, } else { fprintf(stderr, "traceucast connected to %s:%s\n", clientaddr, portstr); + connected = 1; break; } } + if (!connected && sock > 0) { + close(sock); + sock = -1; + } sockcreateover: if (targetinfo == NULL) { @@ -278,8 +283,8 @@ static int connect_stream_fd(read_thread_data_t *rdata, if (errno != ECONNREFUSED) { fprintf(stderr, "traceucast: failed to create TCP socket for " - "reader thread %d\n", - rdata->threadid); + "reader thread %d: %s\n", + rdata->threadid, strerror(errno)); return -1; } else { return 0; @@ -334,7 +339,7 @@ static int send_ndag_packet(read_thread_data_t *rdata, rdata->encaphdr->recordcount = ntohs(rdata->reccount); - while (rem > 0) { + while (rem > 0 && !halted) { if (rdata->streamfd == -1) { if ((r = connect_stream_fd(rdata, gparams)) < 0) { rdata->failed = 1; @@ -669,7 +674,8 @@ static void *beaconer_thread(void *tdata) { if (sock == -1) { if (errno != ECONNREFUSED) { fprintf(stderr, "traceucast: failed to create TCP " - "socket for beacon thread\n"); + "socket for beacon thread: %s\n", + strerror(errno)); halted = 1; break; } else { From 92531cb972b1bdd52e8db657372b11d71d099135 Mon Sep 17 00:00:00 2001 From: Shane Alcock Date: Mon, 4 Dec 2023 15:07:49 +1300 Subject: [PATCH 06/12] Fix more traceucast / ndagtcp bugs * fix bugs that occur when handling a packet larger than 10K bytes (both in traceucast and in the ndagtcp receiving code). * fix lock-up when trying to halt a program that is reading from an ndagtcp input. * fix erroneous "Malformed beacon" message when reconnecting a disconnected ndagtcp input. * fix "getaddrinfo" memory leak in traceucast. --- lib/format_ndag.c | 11 +++++------ tools/tracemcast/traceucast.c | 22 +++++++++++++++++++++- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/lib/format_ndag.c b/lib/format_ndag.c index c6eb35c1..90a13844 100644 --- a/lib/format_ndag.c +++ b/lib/format_ndag.c @@ -50,7 +50,7 @@ #include "format_ndag.h" #define NDAG_IDLE_TIMEOUT (600) -#define ENCAP_BUFSIZE (10000) +#define ENCAP_BUFSIZE (65536) #define CTRL_BUF_SIZE (10000) #define ENCAP_BUFFERS (1000) @@ -440,7 +440,7 @@ static int ndag_parse_control_message(libtrace_t *libtrace, char *msgbuf, numstreams = ntohs(*ptr); ptr ++; - if ((uint32_t)msgsize != ((numstreams + 1) * sizeof(uint16_t))) + if ((uint32_t)msgsize < ((numstreams + 1) * sizeof(uint16_t))) { fprintf(stderr, "Malformed beacon (length doesn't match number of streams).\n"); fprintf(stderr, "%u %u\n", msgsize, numstreams); @@ -556,7 +556,7 @@ static int accept_ndagtcp_connection(libtrace_t *libtrace, fcntl(sock, F_SETFL, O_NONBLOCK); - while (is_halted(libtrace) == -1) { + while (is_halted(libtrace) == -1 && !ndag_paused) { r = select_on_sock(sock); if (r < 0) { fprintf(stderr, "Error in select while accepting connection on socket for %s:%s -- %s\n", @@ -1098,7 +1098,7 @@ static int ndag_prepare_packet_stream_encaperf(libtrace_t *restrict libtrace, nr = ssock->nextreadind; available = ssock->savedsize[nr] - (ssock->nextread - ssock->saved[nr]); - if (ssock->nextrlen == 0 || ssock->nextrlen > ENCAP_BUFSIZE) { + if (ssock->nextrlen == 0) { return -1; } @@ -1175,7 +1175,7 @@ static int ndag_prepare_packet_stream_corsarotag(libtrace_t *restrict libtrace, nr = ssock->nextreadind; available = ssock->savedsize[nr] - (ssock->nextread - ssock->saved[nr]); - if (ssock->nextrlen == 0 || ssock->nextrlen > ENCAP_BUFSIZE) { + if (ssock->nextrlen == 0) { return -1; } @@ -1574,7 +1574,6 @@ static int receive_from_single_socket(streamsock_t *ssock, struct timeval *tv, ssock->sock = -1; return 0; } - ssock->startidle = 0; ssock->savedsize[ssock->nextwriteind] = ret; diff --git a/tools/tracemcast/traceucast.c b/tools/tracemcast/traceucast.c index 47ddd8e4..91c6af5e 100644 --- a/tools/tracemcast/traceucast.c +++ b/tools/tracemcast/traceucast.c @@ -100,6 +100,7 @@ typedef struct read_thread_data { int streamfd; uint8_t *pbuffer; + uint32_t bufsize; ndag_encap_t *encaphdr; uint8_t *writeptr; uint32_t seqno; @@ -146,6 +147,9 @@ static int create_stream_socket(uint16_t port, char *clientaddr, return -1; } if (targetinfo) { + if (*targetinfo) { + free(*targetinfo); + } *targetinfo = gotten; } @@ -247,6 +251,7 @@ static void *init_reader_thread(libtrace_t *trace, rdata->streamport = gparams->firstport + rdata->threadid; rdata->streamfd = -1; rdata->pbuffer = calloc(MAX_PACKET_SIZE, sizeof(uint8_t)); + rdata->bufsize = MAX_PACKET_SIZE; rdata->writeptr = rdata->pbuffer; rdata->seqno = 1; rdata->target = NULL; @@ -514,7 +519,22 @@ static libtrace_packet_t *packet_reader_thread(libtrace_t *trace UNUSED, } } - /* append this packet to the buffer (truncate if necessary) */ + /* extend the buffer size if we happen to be working with very large + * packets + */ + while (rem + dag_record_size + sizeof(ndag_encap_t) + sizeof(ndag_common_t) + > rdata->bufsize) { + int writeoff = rdata->writeptr - rdata->pbuffer; + int encapoff = ((uint8_t *)rdata->encaphdr) - rdata->pbuffer; + + rdata->pbuffer = realloc(rdata->pbuffer, + rdata->bufsize + MAX_PACKET_SIZE); + rdata->bufsize += MAX_PACKET_SIZE; + rdata->writeptr = rdata->pbuffer + writeoff; + rdata->encaphdr = rdata->pbuffer + encapoff; + } + + /* append this packet to the buffer */ /* if the buffer is empty, put on a common and encap header on the * front, before adding any packets */ From 2656a165bf36793fad779b07e7ea3b1e1cdf6fb2 Mon Sep 17 00:00:00 2001 From: Shane Alcock Date: Mon, 4 Dec 2023 15:16:15 +1300 Subject: [PATCH 07/12] Update debian changelog --- debian/changelog | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/debian/changelog b/debian/changelog index 7f46d973..e7472140 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,11 +1,23 @@ -libtrace4 (4.0.24-1) unstable; urgency=medium +libtrace4 (4.0.24-1~rc02) unstable; urgency=medium * ndagtcp: fix miscalculation of ERF header length that would prevent packets from being able to be decoded correctly. * traceucast: do not exit if the client disconnects, instead try to reconnect and resume unicasting. - - -- Shane Alcock Sat, 25 Nov 2023 09:58:02 +1300 + * traceucast: fix memory errors when attempting to send a captured + packet that is larger than 10K bytes. + * ndagtcp: fix issue that would cause input to silently stop reading + if it received a packet larger than 10K bytes. + * ndagtcp: fix lock-up that occurred when trying to halt a program + that was reading from an ndagtcp input. + * ndagtcp: fix erroneous "Malformed beacon" message when an ndagtcp + input reconnects to traceucast. + * traceucast: fix getaddrinfo memory leak. + * traceucast: fix endless reconnection loop bug. + * traceucast: fix race condition that would prevent Ctrl-C from + halting traceucast properly. + + -- Shane Alcock Mon, 4 Dec 2023 15:15:09 +1300 libtrace4 (4.0.23-1) unstable; urgency=medium From 9084fe5e91e084aaf262d5462d63d94adf5c1c56 Mon Sep 17 00:00:00 2001 From: Shane Alcock Date: Wed, 24 Jan 2024 13:44:21 +1300 Subject: [PATCH 08/12] Update debian changelog --- debian/changelog | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index e7472140..9748c1aa 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -libtrace4 (4.0.24-1~rc02) unstable; urgency=medium +libtrace4 (4.0.24-1) unstable; urgency=medium * ndagtcp: fix miscalculation of ERF header length that would prevent packets from being able to be decoded correctly. @@ -17,7 +17,7 @@ libtrace4 (4.0.24-1~rc02) unstable; urgency=medium * traceucast: fix race condition that would prevent Ctrl-C from halting traceucast properly. - -- Shane Alcock Mon, 4 Dec 2023 15:15:09 +1300 + -- Shane Alcock Wed, 24 Jan 2024 13:43:51 +1300 libtrace4 (4.0.23-1) unstable; urgency=medium From fac7055f3b83baa57ad7c6f5ae6719f61f7e29ed Mon Sep 17 00:00:00 2001 From: Shane Alcock Date: Wed, 24 Jan 2024 13:56:11 +1300 Subject: [PATCH 09/12] Update github workflows for packaging * implement build-test-publish workflow, so we actually test if the built packages are installable (and removable). * remove bionic from list of packages built * replace fedora 37 with fedora 39 --- .github/workflows/pkg-build.yaml | 92 ++++++++++++++++++--- .github/workflows/rpm-build.yaml | 138 +++++++++++++++++++++++++------ 2 files changed, 193 insertions(+), 37 deletions(-) diff --git a/.github/workflows/pkg-build.yaml b/.github/workflows/pkg-build.yaml index 3d0b9283..ec78501b 100644 --- a/.github/workflows/pkg-build.yaml +++ b/.github/workflows/pkg-build.yaml @@ -16,10 +16,9 @@ jobs: arch: - amd64 target: + - "debian:bookworm" - "debian:buster" - "debian:bullseye" - - "debian:bookworm" - - "ubuntu:bionic" - "ubuntu:focal" - "ubuntu:jammy" @@ -30,16 +29,89 @@ jobs: run: ./debpkg-setup.sh - name: Build packages run: ./debpkg-build.sh - - name: Store packages + - name: Set environment variables for upload + run: echo DIRNAME=${{ matrix.target }} | tr ':' '_' >> $GITHUB_ENV + - name: Copy packages to uploadable location run: | - export DIRNAME=`echo ${{ matrix.target }} | tr ':' '_'` mkdir -p packages/${DIRNAME} cp ../*.deb packages/${DIRNAME}/ - - name: Publish packages to cloudsmith - uses: wandnz/action-cloudsmith-upload-packages@v1.6 + - name: Store packages + uses: actions/upload-artifact@v3 with: - path: packages/ - repo: ${{ secrets.CLOUDSMITH_OWNER }}/libtrace - username: salcock - api_key: ${{ secrets.CLOUDSMITH_API_KEY }} + name: packages-${{ env.DIRNAME }} + path: packages/${{ env.DIRNAME }}/*.deb + retention-days: 1 + test: + runs-on: ubuntu-latest + container: + image: ${{ matrix.target }} + strategy: + fail-fast: false + matrix: + arch: + - amd64 + target: + - "debian:buster" + - "debian:bullseye" + - "ubuntu:focal" + - "ubuntu:jammy" + - "debian:bookworm" + needs: build + steps: + - name: Set environment variables for download + run: echo DIRNAME=${{ matrix.target }} | tr ':' '_' >> $GITHUB_ENV + - name: Download artifact + uses: actions/download-artifact@v3 + with: + name: packages-${{ env.DIRNAME }} + - name: Add repositories + run: | + apt update -y + apt install -y apt-transport-https curl + - name: Test package install + env: + DEBIAN_FRONTEND: noninteractive + run: | + apt update -y + find . -name "*.deb" | xargs apt install -y + - name: Test package removal + env: + DEBIAN_FRONTEND: noninteractive + run: | + apt remove -y --purge libtrace4 + + publish: + runs-on: ubuntu-latest + container: + image: ${{ matrix.target }} + strategy: + fail-fast: false + matrix: + arch: + - amd64 + target: + - "debian:buster" + - "debian:bullseye" + - "debian:bookworm" + - "ubuntu:focal" + - "ubuntu:jammy" + needs: test + steps: + - name: Set environment variables for download + run: echo DIRNAME=${{ matrix.target }} | tr ':' '_' >> $GITHUB_ENV + - name: Download artifact + uses: actions/download-artifact@v3 + with: + name: packages-${{ env.DIRNAME }} + - name: Copy packages + run: | + mkdir -p packages/${DIRNAME} + find . -name "*.deb" | xargs cp -t packages/${DIRNAME}/ + - name: Publish package to cloudsmith + uses: wanduow/action-cloudsmith-upload-packages@v1 + with: + path: packages/ + repo: ${{ secrets.CLOUDSMITH_OWNER }}/libtrace + username: salcock + api_key: ${{ secrets.CLOUDSMITH_API_KEY }} diff --git a/.github/workflows/rpm-build.yaml b/.github/workflows/rpm-build.yaml index ce88c231..454976b8 100644 --- a/.github/workflows/rpm-build.yaml +++ b/.github/workflows/rpm-build.yaml @@ -1,4 +1,4 @@ -name: Packaging for Centos and Fedora +name: Packaging for RPM on: push: @@ -7,40 +7,124 @@ on: jobs: build: - runs-on: ubuntu-latest - container: - image: ${{ matrix.target }} - strategy: - fail-fast: false - matrix: - arch: - - amd64 - target: - - "centos:7" - - "fedora:37" - - "fedora:38" - - "rockylinux:8" - - "rockylinux:9" - - - steps: + runs-on: ubuntu-latest + container: + image: ${{ matrix.target }} + strategy: + fail-fast: false + matrix: + arch: + - amd64 + target: + - "rockylinux:8" + - "rockylinux:9" + - "fedora:39" + - "fedora:38" + - "centos:7" + + steps: - name: Checkout repo uses: actions/checkout@v3 - name: Install prereq packages run: ./rpmpkg-setup.sh ${{ matrix.target }} - name: Build packages - run: ./rpmpkg-build.sh ${{ matrix.target }} - - name: Store packages + run: ./rpmpkg-build.sh + - name: Set environment variables for upload + run: echo DIRNAME=${{ matrix.target }} | tr ':' '_' >> $GITHUB_ENV + - name: Copy packages to uploadable location run: | - export DIRNAME=`echo ${{ matrix.target }} | tr ':' '_'` mkdir -p packages/${DIRNAME} cp ~/rpmbuild/RPMS/x86_64/*.rpm packages/${DIRNAME}/ - - name: Publish packages to cloudsmith - uses: salcock/action-cloudsmith-upload-packages@v1.7 + - name: Store packages + uses: actions/upload-artifact@v3 with: - path: packages/ - repo: ${{ secrets.CLOUDSMITH_OWNER }}/libtrace - username: salcock - api_key: ${{ secrets.CLOUDSMITH_API_KEY }} + name: packages-${{ env.DIRNAME }} + path: packages/${{ env.DIRNAME }}/*.rpm + retention-days: 1 + + test: + runs-on: ubuntu-latest + container: + image: ${{ matrix.target }} + strategy: + fail-fast: false + matrix: + arch: + - amd64 + target: + - "rockylinux:8" + - "rockylinux:9" + - "fedora:39" + - "fedora:38" + - "centos:7" + needs: build + steps: + - name: Set environment variables for download + run: echo DIRNAME=${{ matrix.target }} | tr ':' '_' >> $GITHUB_ENV + - name: Download artifact + uses: actions/download-artifact@v3 + with: + name: packages-${{ env.DIRNAME }} + - name: Add repositories + env: + TARGET: ${{ matrix.target }} + run: | + if [ "${TARGET}" == "centos:7" ]; then + yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm || true + fi + if [[ "${TARGET}" =~ rocky* ]]; then + dnf install -y dnf-plugins-core epel-release || true + dnf config-manager --set-enabled powertools || true + /usr/bin/crb enable || true + fi + - name: Test package install + run: | + yum install -y findutils + find . -name "*.rpm" | xargs yum install -y + - name: Test package removal + run: | + rpm -e libtrace4-tools + rpm -e libtrace4-devel + rpm -e libtrace4 + rpm -e libpacketdump4-devel + rpm -e libpacketdump4 + + + publish: + runs-on: ubuntu-latest + container: + image: ${{ matrix.target }} + strategy: + fail-fast: false + matrix: + arch: + - amd64 + target: + - "rockylinux:8" + - "rockylinux:9" + - "fedora:39" + - "fedora:38" + - "centos:7" + needs: test + steps: + - name: Set environment variables for download + run: echo DIRNAME=${{ matrix.target }} | tr ':' '_' >> $GITHUB_ENV + - name: Download artifact + uses: actions/download-artifact@v3 + with: + name: packages-${{ env.DIRNAME }} + - name: Copy packages + run: | + mkdir -p packages/${DIRNAME} + yum install -y findutils + find . -name "*.rpm" | xargs cp -t packages/${DIRNAME}/ + - name: Publish package to cloudsmith + uses: wanduow/action-cloudsmith-upload-packages@v1 + with: + path: packages/ + repo: ${{ secrets.CLOUDSMITH_OWNER }}/libtrace + username: salcock + api_key: ${{ secrets.CLOUDSMITH_API_KEY }} + From a677e0d60b1176d8435fbdd56b3656ca21f6e141 Mon Sep 17 00:00:00 2001 From: Shane Alcock Date: Wed, 24 Jan 2024 14:06:12 +1300 Subject: [PATCH 10/12] github workflows: add missing repos for wandio and wandder --- .github/workflows/pkg-build.yaml | 2 ++ .github/workflows/rpm-build.yaml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/.github/workflows/pkg-build.yaml b/.github/workflows/pkg-build.yaml index ec78501b..08b0f901 100644 --- a/.github/workflows/pkg-build.yaml +++ b/.github/workflows/pkg-build.yaml @@ -69,6 +69,8 @@ jobs: run: | apt update -y apt install -y apt-transport-https curl + curl -1sLf 'https://dl.cloudsmith.io/public/wand/libwandio/cfg/setup/bash.deb.sh' | bash + curl -1sLf 'https://dl.cloudsmith.io/public/wand/libwandder/cfg/setup/bash.deb.sh' | bash - name: Test package install env: DEBIAN_FRONTEND: noninteractive diff --git a/.github/workflows/rpm-build.yaml b/.github/workflows/rpm-build.yaml index 454976b8..0e4c85d1 100644 --- a/.github/workflows/rpm-build.yaml +++ b/.github/workflows/rpm-build.yaml @@ -69,6 +69,8 @@ jobs: env: TARGET: ${{ matrix.target }} run: | + curl -1sLf 'https://dl.cloudsmith.io/public/wand/libwandio/cfg/setup/bash.rpm.sh' | bash + curl -1sLf 'https://dl.cloudsmith.io/public/wand/libwandder/cfg/setup/bash.rpm.sh' | bash if [ "${TARGET}" == "centos:7" ]; then yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm || true fi From 07c991bddc97bac5c34d21c07202c05071905a3a Mon Sep 17 00:00:00 2001 From: Shane Alcock Date: Wed, 24 Jan 2024 14:33:10 +1300 Subject: [PATCH 11/12] rpm workflow: fix removal order of packages during test phase --- .github/workflows/rpm-build.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/rpm-build.yaml b/.github/workflows/rpm-build.yaml index 0e4c85d1..676dfe5f 100644 --- a/.github/workflows/rpm-build.yaml +++ b/.github/workflows/rpm-build.yaml @@ -86,10 +86,10 @@ jobs: - name: Test package removal run: | rpm -e libtrace4-tools - rpm -e libtrace4-devel - rpm -e libtrace4 rpm -e libpacketdump4-devel + rpm -e libtrace4-devel rpm -e libpacketdump4 + rpm -e libtrace4 publish: From 975aec9ea7b2b156e90988f67d7e9b123d1336f6 Mon Sep 17 00:00:00 2001 From: Shane Alcock Date: Wed, 24 Jan 2024 14:47:17 +1300 Subject: [PATCH 12/12] Update rpm spec file --- rpm/libtrace4.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpm/libtrace4.spec b/rpm/libtrace4.spec index c3e7546d..08e2074d 100644 --- a/rpm/libtrace4.spec +++ b/rpm/libtrace4.spec @@ -127,7 +127,7 @@ find $RPM_BUILD_ROOT -name '*.la' -exec rm -f {} ';' %changelog -* Sat Nov 25 2023 Shane Alcock - 4.0.24-1 +* Wed Jan 24 2024 Shane Alcock - 4.0.24-1 - Updated for 4.0.24 release * Fri Nov 10 2023 Shane Alcock - 4.0.23-1