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