From b3d6978dd167abdf6e7e46fb61b2955b5d4100e3 Mon Sep 17 00:00:00 2001 From: Gabriel Ganne Date: Thu, 25 Nov 2021 14:29:56 +0100 Subject: [PATCH] rpcap: set keepalives on rpcap's control socket Signed-off-by: Kevin Boulain Signed-off-by: Gabriel Ganne --- pcap-rpcap.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ pcap/pcap.h | 1 + 2 files changed, 49 insertions(+) diff --git a/pcap-rpcap.c b/pcap-rpcap.c index 7c42cf3a77..fda2503602 100644 --- a/pcap-rpcap.c +++ b/pcap-rpcap.c @@ -43,6 +43,11 @@ #include /* for functions with variable number of arguments */ #include /* for the errno variable */ #include /* for INT_MAX */ + +#ifndef _WIN32 + #include /* for TCP_KEEP* */ +#endif + #include "sockutils.h" #include "pcap-int.h" #include "rpcap-protocol.h" @@ -3536,3 +3541,46 @@ static int rpcap_read_packet_msg(struct pcap_rpcap const *rp, pcap_t *p, size_t p->cc = cc; return 0; } + +/* + * Set the keepalives parameters on the control socket. + * An rpcap-based application may detect more rapidly a network error. + * + * It may not be necessary to set them on the data socket as it may use UDP. + * See pcap_read_nocb_remote for the select logic that will take into + * account the error on the control socket. + */ +int +pcap_set_control_keepalive(pcap_t *p, int enable, int keepcnt, int keepidle, int keepintvl) +{ + struct pcap_rpcap *pr = p->priv; /* structure used when doing a remote live capture */ + + if (setsockopt(pr->rmt_sockctrl, SOL_SOCKET, SO_KEEPALIVE, (char *)&enable, sizeof(enable)) < 0) + { + sock_geterror("setsockopt(): ", p->errbuf, PCAP_ERRBUF_SIZE); + return -1; + } + + /* when SO_KEEPALIVE isn't active, the following options aren't used */ + if (!enable) + return 0; + +#if defined(TCP_KEEPCNT) && defined(TCP_KEEPIDLE) && defined(TCP_KEEPINTVL) + if (setsockopt(pr->rmt_sockctrl, IPPROTO_TCP, TCP_KEEPCNT, (char *)&keepcnt, sizeof(keepcnt)) < 0 || + setsockopt(pr->rmt_sockctrl, IPPROTO_TCP, TCP_KEEPIDLE, (char *)&keepidle, sizeof(keepidle)) < 0 || + setsockopt(pr->rmt_sockctrl, IPPROTO_TCP, TCP_KEEPINTVL, (char *)&keepintvl, sizeof(keepintvl)) < 0) + { + sock_geterror("setsockopt(): ", p->errbuf, PCAP_ERRBUF_SIZE); + return -1; + } +#else + if (keepcnt || keepidle || keepintvl) + { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + "TCP_KEEPCNT, TCP_KEEPIDLE or TCP_KEEPINTVL not supported on this platform"); + return -1; + } +#endif + + return 0; +} diff --git a/pcap/pcap.h b/pcap/pcap.h index e66abb04f0..3eb775998a 100644 --- a/pcap/pcap.h +++ b/pcap/pcap.h @@ -432,6 +432,7 @@ PCAP_API int pcap_get_tstamp_precision(pcap_t *); PCAP_AVAILABLE_1_0 PCAP_API int pcap_activate(pcap_t *); +PCAP_API int pcap_set_control_keepalive(pcap_t *, int, int, int, int); PCAP_AVAILABLE_1_2 PCAP_API int pcap_list_tstamp_types(pcap_t *, int **);