Skip to content

Commit

Permalink
rpcap: set keepalives on rpcap's control socket
Browse files Browse the repository at this point in the history
Signed-off-by: Kevin Boulain <[email protected]>
Signed-off-by: Gabriel Ganne <[email protected]>
  • Loading branch information
GabrielGanne committed Sep 20, 2022
1 parent d23acc6 commit f178a33
Show file tree
Hide file tree
Showing 8 changed files with 141 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Monthday, Month DD, YYYY:
Support user names and passwords in rpcap:// and rpcaps:// URLs.
Add a -t flag to rpcapd to specify the data channel port; from
another incorporate-remote-capture project. (issue #1120)
Add API to customize the keepalives parameters of a rpcap control socket
Documentation:
Document a standard format for writing out BPF filter programs.
Building and testing:
Expand Down
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2839,6 +2839,7 @@ set(MAN3PCAP_NOEXPAND
pcap_offline_filter.3pcap
pcap_open_live.3pcap
pcap_set_buffer_size.3pcap
pcap_set_control_keepalive.3pcap
pcap_set_datalink.3pcap
pcap_set_promisc.3pcap
pcap_set_protocol_linux.3pcap
Expand Down
1 change: 1 addition & 0 deletions Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ MAN3PCAP_NOEXPAND = \
pcap_offline_filter.3pcap \
pcap_open_live.3pcap \
pcap_set_buffer_size.3pcap \
pcap_set_control_keepalive.3pcap \
pcap_set_datalink.3pcap \
pcap_set_promisc.3pcap \
pcap_set_protocol_linux.3pcap \
Expand Down
2 changes: 2 additions & 0 deletions pcap-int.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ typedef int (*getnonblock_op_t)(pcap_t *);
typedef int (*setnonblock_op_t)(pcap_t *, int);
typedef int (*stats_op_t)(pcap_t *, struct pcap_stat *);
typedef void (*breakloop_op_t)(pcap_t *);
typedef int (*set_control_keepalive_op_t)(pcap_t *, int, int, int, int);
#ifdef _WIN32
typedef struct pcap_stat *(*stats_ex_op_t)(pcap_t *, int *);
typedef int (*setbuff_op_t)(pcap_t *, int);
Expand Down Expand Up @@ -337,6 +338,7 @@ struct pcap {
setnonblock_op_t setnonblock_op;
stats_op_t stats_op;
breakloop_op_t breakloop_op;
set_control_keepalive_op_t set_control_keepalive_op;

/*
* Routine to use as callback for pcap_next()/pcap_next_ex().
Expand Down
50 changes: 50 additions & 0 deletions pcap-rpcap.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@
#include <stdarg.h> /* for functions with variable number of arguments */
#include <errno.h> /* for the errno variable */
#include <limits.h> /* for INT_MAX */

#ifndef _WIN32
#include <netinet/tcp.h> /* for TCP_KEEP* */
#endif

#include "sockutils.h"
#include "pcap-int.h"
#include "pcap-util.h"
Expand Down Expand Up @@ -180,6 +185,7 @@ static int rpcap_recv(SOCKET sock, SSL *, void *buffer, size_t toread, uint32_t
static void rpcap_msg_err(SOCKET sockctrl, SSL *, uint32_t plen, char *remote_errbuf);
static int rpcap_discard(SOCKET sock, SSL *, uint32_t len, char *errbuf);
static int rpcap_read_packet_msg(struct pcap_rpcap const *, pcap_t *p, size_t size);
static int pcap_set_control_keepalive_rpcap(pcap_t *p, int enable, int keepcnt, int keepidle, int keepintvl);

/****************************************************
* *
Expand Down Expand Up @@ -2641,6 +2647,7 @@ pcap_t *pcap_open_rpcap(const char *source, int snaplen, int flags, int read_tim
#ifdef _WIN32
fp->stats_ex_op = pcap_stats_ex_rpcap;
#endif
fp->set_control_keepalive_op = pcap_set_control_keepalive_rpcap;
fp->cleanup_op = pcap_cleanup_rpcap;

fp->activated = 1;
Expand Down Expand Up @@ -3714,3 +3721,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.
*/
static int
pcap_set_control_keepalive_rpcap(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_geterrmsg(p->errbuf, PCAP_ERRBUF_SIZE, "setsockopt(): ");
return PCAP_ERROR;
}

/* 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_geterrmsg(p->errbuf, PCAP_ERRBUF_SIZE, "setsockopt(): ");
return PCAP_ERROR;
}
#else
if (keepcnt || keepidle || keepintvl)
{
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"TCP_KEEPCNT, TCP_KEEPIDLE or TCP_KEEPINTVL not supported on this platform");
return PCAP_ERROR;
}
#endif

return 0;
}
24 changes: 24 additions & 0 deletions pcap.c
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,20 @@ pcap_stats_not_initialized(pcap_t *pcap, struct pcap_stat *ps _U_)
return (PCAP_ERROR_NOT_ACTIVATED);
}

static int
pcap_set_control_keepalive_not_initialized(pcap_t *pcap, int enable _U_,
int keepcnt _U_, int keepidle _U_, int keepintvl _U_)
{
if (pcap->activated) {
/* Not set by the module, so probably not supported */
return PCAP_WARNING_CONTROL_KEEPALIVE_NOTSUP;
}
/* in case the caller doesn't check for PCAP_ERROR_NOT_ACTIVATED */
(void)snprintf(pcap->errbuf, sizeof(pcap->errbuf),
"This handle hasn't been activated yet");
return (PCAP_ERROR_NOT_ACTIVATED);
}

#ifdef _WIN32
static struct pcap_stat *
pcap_stats_ex_not_initialized(pcap_t *pcap, int *pcap_stat_size _U_)
Expand Down Expand Up @@ -2408,6 +2422,7 @@ initialize_ops(pcap_t *p)
p->set_datalink_op = pcap_set_datalink_not_initialized;
p->getnonblock_op = pcap_getnonblock_not_initialized;
p->stats_op = pcap_stats_not_initialized;
p->set_control_keepalive_op = pcap_set_control_keepalive_not_initialized;
#ifdef _WIN32
p->stats_ex_op = pcap_stats_ex_not_initialized;
p->setbuff_op = pcap_setbuff_not_initialized;
Expand Down Expand Up @@ -3695,6 +3710,9 @@ pcap_statustostr(int errnum)

case PCAP_ERROR_TSTAMP_PRECISION_NOTSUP:
return ("That device doesn't support that time stamp precision");

case PCAP_WARNING_CONTROL_KEEPALIVE_NOTSUP:
return ("Keepalive control is not supported");
}
(void)snprintf(ebuf, sizeof ebuf, "Unknown error: %d", errnum);
return(ebuf);
Expand Down Expand Up @@ -3776,6 +3794,12 @@ pcap_stats(pcap_t *p, struct pcap_stat *ps)
return (p->stats_op(p, ps));
}

int
pcap_set_control_keepalive(pcap_t *p, int enable, int keepcnt, int keepidle, int keepintvl)
{
return p->set_control_keepalive_op(p, enable, keepcnt, keepidle, keepintvl);
}

#ifdef _WIN32
struct pcap_stat *
pcap_stats_ex(pcap_t *p, int *pcap_stat_size)
Expand Down
4 changes: 4 additions & 0 deletions pcap/pcap.h
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,7 @@ typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *,
#define PCAP_ERROR_CANTSET_TSTAMP_TYPE -10 /* this device doesn't support setting the time stamp type */
#define PCAP_ERROR_PROMISC_PERM_DENIED -11 /* you don't have permission to capture in promiscuous mode */
#define PCAP_ERROR_TSTAMP_PRECISION_NOTSUP -12 /* the requested time stamp precision is not supported */
#define PCAP_WARNING_CONTROL_KEEPALIVE_NOTSUP -13 /* keepalive control is not supported */

/*
* Warning codes for the pcap API.
Expand Down Expand Up @@ -627,6 +628,9 @@ PCAP_API void pcap_breakloop(pcap_t *);
PCAP_AVAILABLE_0_4
PCAP_API int pcap_stats(pcap_t *, struct pcap_stat *);

PCAP_AVAILABLE_1_11
PCAP_API int pcap_set_control_keepalive(pcap_t *, int, int, int, int);

PCAP_AVAILABLE_0_4
PCAP_API int pcap_setfilter(pcap_t *, struct bpf_program *);

Expand Down
58 changes: 58 additions & 0 deletions pcap_set_control_keepalive.3pcap
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
.\" Copyright (c) 1994, 1996, 1997
.\" The Regents of the University of California. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that: (1) source code distributions
.\" retain the above copyright notice and this paragraph in its entirety, (2)
.\" distributions including binary code include the above copyright notice and
.\" this paragraph in its entirety in the documentation or other materials
.\" provided with the distribution, and (3) all advertising materials mentioning
.\" features or use of this software display the following acknowledgement:
.\" ``This product includes software developed by the University of California,
.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
.\" the University nor the names of its contributors may be used to endorse
.\" or promote products derived from this software without specific prior
.\" written permission.
.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
.TH PCAP_SET_CONTROL_KEEPALIVE 3PCAP "20 September 2022"
.SH NAME
pcap_set_control_keepalive \- set the keepalives parameters on a rpcap control socket.
.SH SYNOPSIS
.nf
.ft B
#include <pcap/pcap.h>
.LP
.ft B
int pcap_set_control_keepalive(pcap_t *p, int enable, int keepcnt, int keepidle, int keepintvl)
.ft
.fi
.SH DESCRIPTION
.BR pcap_set_control_keepalive ()
set the keepalives parameters on the control socket.
The arguments
.I
keepcnt,
.I
keepidle, and
.I keepintvl
are used to set the corresponding tcp options. Respectively
.B
TCP_KEEPCNT
(The maximum number of keepalive probes TCP should send before dropping the connection),
.B TCP_KEEPIDLE
(The time (in seconds) the connection needs to remain idle before TCP starts sending keepalive probes), and
.B
TCP_KEEPINTVL
(The time (in seconds) between individual keepalive probes.)
.SH RETURN VALUE
.BR pcap_set_control_keepalive ()
returns
.B 0
on success or
.B PCAP_ERROR
if we failed to set the socket options.
.SH SEE ALSO
.BR pcap (3PCAP),

0 comments on commit f178a33

Please sign in to comment.