|
41 | 41 | #include <stdarg.h> /* for functions with variable number of arguments */ |
42 | 42 | #include <errno.h> /* for the errno variable */ |
43 | 43 | #include <limits.h> /* for INT_MAX */ |
| 44 | + |
| 45 | +#ifndef _WIN32 |
| 46 | + #include <netinet/tcp.h> /* for TCP_KEEP* */ |
| 47 | +#endif |
| 48 | + |
44 | 49 | #include "sockutils.h" |
45 | 50 | #include "pcap-int.h" |
46 | 51 | #include "pcap-util.h" |
@@ -178,6 +183,7 @@ static int rpcap_recv(PCAP_SOCKET sock, SSL *, void *buffer, size_t toread, uint |
178 | 183 | static void rpcap_msg_err(PCAP_SOCKET sockctrl, SSL *, uint32_t plen, char *remote_errbuf); |
179 | 184 | static int rpcap_discard(PCAP_SOCKET sock, SSL *, uint32_t len, char *errbuf); |
180 | 185 | static int rpcap_read_packet_msg(struct pcap_rpcap const *, pcap_t *p, size_t size); |
| 186 | +static int pcap_set_control_keepalive_rpcap(pcap_t *p, int enable, int keepcnt, int keepidle, int keepintvl); |
181 | 187 |
|
182 | 188 | /**************************************************** |
183 | 189 | * * |
@@ -2646,6 +2652,7 @@ pcap_t *pcap_open_rpcap(const char *source, int snaplen, int flags, int read_tim |
2646 | 2652 | #ifdef _WIN32 |
2647 | 2653 | fp->stats_ex_op = pcap_stats_ex_rpcap; |
2648 | 2654 | #endif |
| 2655 | + fp->set_control_keepalive_op = pcap_set_control_keepalive_rpcap; |
2649 | 2656 | fp->cleanup_op = pcap_cleanup_rpcap; |
2650 | 2657 |
|
2651 | 2658 | fp->activated = 1; |
@@ -3718,3 +3725,46 @@ static int rpcap_read_packet_msg(struct pcap_rpcap const *rp, pcap_t *p, size_t |
3718 | 3725 | p->cc = cc; |
3719 | 3726 | return 0; |
3720 | 3727 | } |
| 3728 | + |
| 3729 | +/* |
| 3730 | + * Set the keepalives parameters on the control socket. |
| 3731 | + * An rpcap-based application may detect more rapidly a network error. |
| 3732 | + * |
| 3733 | + * It may not be necessary to set them on the data socket as it may use UDP. |
| 3734 | + * See pcap_read_nocb_remote for the select logic that will take into |
| 3735 | + * account the error on the control socket. |
| 3736 | + */ |
| 3737 | +static int |
| 3738 | +pcap_set_control_keepalive_rpcap(pcap_t *p, int enable, int keepcnt, int keepidle, int keepintvl) |
| 3739 | +{ |
| 3740 | + struct pcap_rpcap *pr = p->priv; /* structure used when doing a remote live capture */ |
| 3741 | + |
| 3742 | + if (setsockopt(pr->rmt_sockctrl, SOL_SOCKET, SO_KEEPALIVE, (char *)&enable, sizeof(enable)) < 0) |
| 3743 | + { |
| 3744 | + sock_geterrmsg(p->errbuf, PCAP_ERRBUF_SIZE, "setsockopt(): "); |
| 3745 | + return PCAP_ERROR; |
| 3746 | + } |
| 3747 | + |
| 3748 | + /* when SO_KEEPALIVE isn't active, the following options aren't used */ |
| 3749 | + if (!enable) |
| 3750 | + return 0; |
| 3751 | + |
| 3752 | +#if defined(TCP_KEEPCNT) && defined(TCP_KEEPIDLE) && defined(TCP_KEEPINTVL) |
| 3753 | + if (setsockopt(pr->rmt_sockctrl, IPPROTO_TCP, TCP_KEEPCNT, (char *)&keepcnt, sizeof(keepcnt)) < 0 || |
| 3754 | + setsockopt(pr->rmt_sockctrl, IPPROTO_TCP, TCP_KEEPIDLE, (char *)&keepidle, sizeof(keepidle)) < 0 || |
| 3755 | + setsockopt(pr->rmt_sockctrl, IPPROTO_TCP, TCP_KEEPINTVL, (char *)&keepintvl, sizeof(keepintvl)) < 0) |
| 3756 | + { |
| 3757 | + sock_geterrmsg(p->errbuf, PCAP_ERRBUF_SIZE, "setsockopt(): "); |
| 3758 | + return PCAP_ERROR; |
| 3759 | + } |
| 3760 | +#else |
| 3761 | + if (keepcnt || keepidle || keepintvl) |
| 3762 | + { |
| 3763 | + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, |
| 3764 | + "TCP_KEEPCNT, TCP_KEEPIDLE or TCP_KEEPINTVL not supported on this platform"); |
| 3765 | + return PCAP_ERROR; |
| 3766 | + } |
| 3767 | +#endif |
| 3768 | + |
| 3769 | + return 0; |
| 3770 | +} |
0 commit comments