Skip to content

Commit a2eb579

Browse files
committed
rpcap: set keepalives on rpcap's control socket
Signed-off-by: Kevin Boulain <[email protected]> Signed-off-by: Gabriel Ganne <[email protected]>
1 parent 8ed0757 commit a2eb579

File tree

8 files changed

+140
-0
lines changed

8 files changed

+140
-0
lines changed

CHANGES

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ DayOfTheWeek, Month DD, YYYY / The Tcpdump Group
4040
another incorporate-remote-capture project. (issue #1120)
4141
rpcapd: Refine SSL options in printusage().
4242
Fix a possible buffer overflow (Coverity CID 1619148).
43+
Add API to customize the keepalives parameters of a rpcap control socket
4344
Documentation:
4445
Document a standard format for writing out BPF filter programs.
4546
Add a README.hurd.md file.

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3391,6 +3391,7 @@ set(MAN3PCAP_NOEXPAND
33913391
pcap_offline_filter.3pcap
33923392
pcap_open_live.3pcap
33933393
pcap_set_buffer_size.3pcap
3394+
pcap_set_control_keepalive.3pcap
33943395
pcap_set_datalink.3pcap
33953396
pcap_set_promisc.3pcap
33963397
pcap_set_protocol_linux.3pcap

Makefile.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ MAN3PCAP_NOEXPAND = \
202202
pcap_offline_filter.3pcap \
203203
pcap_open_live.3pcap \
204204
pcap_set_buffer_size.3pcap \
205+
pcap_set_control_keepalive.3pcap \
205206
pcap_set_datalink.3pcap \
206207
pcap_set_promisc.3pcap \
207208
pcap_set_protocol_linux.3pcap \

pcap-int.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ typedef int (*getnonblock_op_t)(pcap_t *);
197197
typedef int (*setnonblock_op_t)(pcap_t *, int);
198198
typedef int (*stats_op_t)(pcap_t *, struct pcap_stat *);
199199
typedef void (*breakloop_op_t)(pcap_t *);
200+
typedef int (*set_control_keepalive_op_t)(pcap_t *, int, int, int, int);
200201
#ifdef _WIN32
201202
typedef struct pcap_stat *(*stats_ex_op_t)(pcap_t *, int *);
202203
typedef int (*setbuff_op_t)(pcap_t *, int);
@@ -339,6 +340,7 @@ struct pcap {
339340
setnonblock_op_t setnonblock_op;
340341
stats_op_t stats_op;
341342
breakloop_op_t breakloop_op;
343+
set_control_keepalive_op_t set_control_keepalive_op;
342344

343345
/*
344346
* Routine to use as callback for pcap_next()/pcap_next_ex().

pcap-rpcap.c

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@
4141
#include <stdarg.h> /* for functions with variable number of arguments */
4242
#include <errno.h> /* for the errno variable */
4343
#include <limits.h> /* for INT_MAX */
44+
45+
#ifndef _WIN32
46+
#include <netinet/tcp.h> /* for TCP_KEEP* */
47+
#endif
48+
4449
#include "sockutils.h"
4550
#include "pcap-int.h"
4651
#include "pcap-util.h"
@@ -178,6 +183,7 @@ static int rpcap_recv(PCAP_SOCKET sock, SSL *, void *buffer, size_t toread, uint
178183
static void rpcap_msg_err(PCAP_SOCKET sockctrl, SSL *, uint32_t plen, char *remote_errbuf);
179184
static int rpcap_discard(PCAP_SOCKET sock, SSL *, uint32_t len, char *errbuf);
180185
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);
181187

182188
/****************************************************
183189
* *
@@ -2646,6 +2652,7 @@ pcap_t *pcap_open_rpcap(const char *source, int snaplen, int flags, int read_tim
26462652
#ifdef _WIN32
26472653
fp->stats_ex_op = pcap_stats_ex_rpcap;
26482654
#endif
2655+
fp->set_control_keepalive_op = pcap_set_control_keepalive_rpcap;
26492656
fp->cleanup_op = pcap_cleanup_rpcap;
26502657

26512658
fp->activated = 1;
@@ -3718,3 +3725,46 @@ static int rpcap_read_packet_msg(struct pcap_rpcap const *rp, pcap_t *p, size_t
37183725
p->cc = cc;
37193726
return 0;
37203727
}
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+
}

pcap.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,20 @@ pcap_stats_not_initialized(pcap_t *pcap, struct pcap_stat *ps _U_)
379379
return (PCAP_ERROR_NOT_ACTIVATED);
380380
}
381381

382+
static int
383+
pcap_set_control_keepalive_not_initialized(pcap_t *pcap, int enable _U_,
384+
int keepcnt _U_, int keepidle _U_, int keepintvl _U_)
385+
{
386+
if (pcap->activated) {
387+
/* Not set by the module, so probably not supported */
388+
return PCAP_WARNING_CONTROL_KEEPALIVE_NOTSUP;
389+
}
390+
/* in case the caller doesn't check for PCAP_ERROR_NOT_ACTIVATED */
391+
(void)snprintf(pcap->errbuf, sizeof(pcap->errbuf),
392+
"This handle hasn't been activated yet");
393+
return (PCAP_ERROR_NOT_ACTIVATED);
394+
}
395+
382396
#ifdef _WIN32
383397
static struct pcap_stat *
384398
pcap_stats_ex_not_initialized(pcap_t *pcap, int *pcap_stat_size _U_)
@@ -2412,6 +2426,7 @@ initialize_ops(pcap_t *p)
24122426
p->set_datalink_op = pcap_set_datalink_not_initialized;
24132427
p->getnonblock_op = pcap_getnonblock_not_initialized;
24142428
p->stats_op = pcap_stats_not_initialized;
2429+
p->set_control_keepalive_op = pcap_set_control_keepalive_not_initialized;
24152430
#ifdef _WIN32
24162431
p->stats_ex_op = pcap_stats_ex_not_initialized;
24172432
p->setbuff_op = pcap_setbuff_not_initialized;
@@ -3706,6 +3721,10 @@ pcap_statustostr(int errnum)
37063721

37073722
case PCAP_ERROR_CAPTURE_NOTSUP:
37083723
return ("Packet capture is not supported on that device");
3724+
3725+
case PCAP_WARNING_CONTROL_KEEPALIVE_NOTSUP:
3726+
return ("Keepalive control is not supported");
3727+
37093728
}
37103729
(void)snprintf(ebuf, sizeof ebuf, "Unknown error: %d", errnum);
37113730
return(ebuf);
@@ -3852,6 +3871,12 @@ pcap_stats(pcap_t *p, struct pcap_stat *ps)
38523871
return (p->stats_op(p, ps));
38533872
}
38543873

3874+
int
3875+
pcap_set_control_keepalive(pcap_t *p, int enable, int keepcnt, int keepidle, int keepintvl)
3876+
{
3877+
return p->set_control_keepalive_op(p, enable, keepcnt, keepidle, keepintvl);
3878+
}
3879+
38553880
#ifdef _WIN32
38563881
struct pcap_stat *
38573882
pcap_stats_ex(pcap_t *p, int *pcap_stat_size)

pcap/pcap.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,7 @@ typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *,
370370
#define PCAP_ERROR_PROMISC_PERM_DENIED -11 /* you don't have permission to capture in promiscuous mode */
371371
#define PCAP_ERROR_TSTAMP_PRECISION_NOTSUP -12 /* the requested time stamp precision is not supported */
372372
#define PCAP_ERROR_CAPTURE_NOTSUP -13 /* capture mechanism not available */
373+
#define PCAP_WARNING_CONTROL_KEEPALIVE_NOTSUP -14 /* keepalive control is not supported */
373374

374375
/*
375376
* Warning codes for the pcap API.
@@ -612,6 +613,9 @@ PCAP_AVAILABLE_0_4
612613
PCAP_API int pcap_stats(pcap_t *, struct pcap_stat *)
613614
PCAP_WARN_UNUSED_RESULT;
614615

616+
PCAP_AVAILABLE_1_11
617+
PCAP_API int pcap_set_control_keepalive(pcap_t *, int, int, int, int);
618+
615619
PCAP_AVAILABLE_0_4
616620
PCAP_API int pcap_setfilter(pcap_t *, struct bpf_program *)
617621
PCAP_WARN_UNUSED_RESULT;

pcap_set_control_keepalive.3pcap

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
.\" Copyright (c) 1994, 1996, 1997
2+
.\" The Regents of the University of California. All rights reserved.
3+
.\"
4+
.\" Redistribution and use in source and binary forms, with or without
5+
.\" modification, are permitted provided that: (1) source code distributions
6+
.\" retain the above copyright notice and this paragraph in its entirety, (2)
7+
.\" distributions including binary code include the above copyright notice and
8+
.\" this paragraph in its entirety in the documentation or other materials
9+
.\" provided with the distribution, and (3) all advertising materials mentioning
10+
.\" features or use of this software display the following acknowledgement:
11+
.\" ``This product includes software developed by the University of California,
12+
.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
13+
.\" the University nor the names of its contributors may be used to endorse
14+
.\" or promote products derived from this software without specific prior
15+
.\" written permission.
16+
.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
17+
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
18+
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19+
.\"
20+
.TH PCAP_SET_CONTROL_KEEPALIVE 3PCAP "20 September 2022"
21+
.SH NAME
22+
pcap_set_control_keepalive \- set the keepalives parameters on a rpcap control socket.
23+
.SH SYNOPSIS
24+
.nf
25+
.ft B
26+
#include <pcap/pcap.h>
27+
.LP
28+
.ft B
29+
int pcap_set_control_keepalive(pcap_t *p, int enable, int keepcnt, int keepidle, int keepintvl)
30+
.ft
31+
.fi
32+
.SH DESCRIPTION
33+
.BR pcap_set_control_keepalive ()
34+
set the keepalives parameters on the control socket.
35+
The arguments
36+
.I keepcnt
37+
,
38+
.I keepidle
39+
, and
40+
.I keepintvl
41+
are used to set the corresponding tcp options. Respectively
42+
.B TCP_KEEPCNT
43+
(The maximum number of keepalive probes TCP should send before dropping the connection),
44+
.B TCP_KEEPIDLE
45+
(The time in seconds the connection needs to remain idle before TCP starts sending keepalive probes), and
46+
.B TCP_KEEPINTVL
47+
(The time in seconds between individual keepalive probes).
48+
.SH RETURN VALUE
49+
.BR pcap_set_control_keepalive ()
50+
returns
51+
.B 0
52+
on success or
53+
.B PCAP_ERROR
54+
if we failed to set the socket options.
55+
.SH SEE ALSO
56+
.BR pcap (3PCAP),

0 commit comments

Comments
 (0)