Skip to content

Commit f178a33

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 d23acc6 commit f178a33

File tree

8 files changed

+141
-0
lines changed

8 files changed

+141
-0
lines changed

CHANGES

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ Monthday, Month DD, YYYY:
2323
Support user names and passwords in rpcap:// and rpcaps:// URLs.
2424
Add a -t flag to rpcapd to specify the data channel port; from
2525
another incorporate-remote-capture project. (issue #1120)
26+
Add API to customize the keepalives parameters of a rpcap control socket
2627
Documentation:
2728
Document a standard format for writing out BPF filter programs.
2829
Building and testing:

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2839,6 +2839,7 @@ set(MAN3PCAP_NOEXPAND
28392839
pcap_offline_filter.3pcap
28402840
pcap_open_live.3pcap
28412841
pcap_set_buffer_size.3pcap
2842+
pcap_set_control_keepalive.3pcap
28422843
pcap_set_datalink.3pcap
28432844
pcap_set_promisc.3pcap
28442845
pcap_set_protocol_linux.3pcap

Makefile.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,7 @@ MAN3PCAP_NOEXPAND = \
217217
pcap_offline_filter.3pcap \
218218
pcap_open_live.3pcap \
219219
pcap_set_buffer_size.3pcap \
220+
pcap_set_control_keepalive.3pcap \
220221
pcap_set_datalink.3pcap \
221222
pcap_set_promisc.3pcap \
222223
pcap_set_protocol_linux.3pcap \

pcap-int.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ typedef int (*getnonblock_op_t)(pcap_t *);
195195
typedef int (*setnonblock_op_t)(pcap_t *, int);
196196
typedef int (*stats_op_t)(pcap_t *, struct pcap_stat *);
197197
typedef void (*breakloop_op_t)(pcap_t *);
198+
typedef int (*set_control_keepalive_op_t)(pcap_t *, int, int, int, int);
198199
#ifdef _WIN32
199200
typedef struct pcap_stat *(*stats_ex_op_t)(pcap_t *, int *);
200201
typedef int (*setbuff_op_t)(pcap_t *, int);
@@ -337,6 +338,7 @@ struct pcap {
337338
setnonblock_op_t setnonblock_op;
338339
stats_op_t stats_op;
339340
breakloop_op_t breakloop_op;
341+
set_control_keepalive_op_t set_control_keepalive_op;
340342

341343
/*
342344
* 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
@@ -43,6 +43,11 @@
4343
#include <stdarg.h> /* for functions with variable number of arguments */
4444
#include <errno.h> /* for the errno variable */
4545
#include <limits.h> /* for INT_MAX */
46+
47+
#ifndef _WIN32
48+
#include <netinet/tcp.h> /* for TCP_KEEP* */
49+
#endif
50+
4651
#include "sockutils.h"
4752
#include "pcap-int.h"
4853
#include "pcap-util.h"
@@ -180,6 +185,7 @@ static int rpcap_recv(SOCKET sock, SSL *, void *buffer, size_t toread, uint32_t
180185
static void rpcap_msg_err(SOCKET sockctrl, SSL *, uint32_t plen, char *remote_errbuf);
181186
static int rpcap_discard(SOCKET sock, SSL *, uint32_t len, char *errbuf);
182187
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);
183189

184190
/****************************************************
185191
* *
@@ -2641,6 +2647,7 @@ pcap_t *pcap_open_rpcap(const char *source, int snaplen, int flags, int read_tim
26412647
#ifdef _WIN32
26422648
fp->stats_ex_op = pcap_stats_ex_rpcap;
26432649
#endif
2650+
fp->set_control_keepalive_op = pcap_set_control_keepalive_rpcap;
26442651
fp->cleanup_op = pcap_cleanup_rpcap;
26452652

26462653
fp->activated = 1;
@@ -3714,3 +3721,46 @@ static int rpcap_read_packet_msg(struct pcap_rpcap const *rp, pcap_t *p, size_t
37143721
p->cc = cc;
37153722
return 0;
37163723
}
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+
}

pcap.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,20 @@ pcap_stats_not_initialized(pcap_t *pcap, struct pcap_stat *ps _U_)
399399
return (PCAP_ERROR_NOT_ACTIVATED);
400400
}
401401

402+
static int
403+
pcap_set_control_keepalive_not_initialized(pcap_t *pcap, int enable _U_,
404+
int keepcnt _U_, int keepidle _U_, int keepintvl _U_)
405+
{
406+
if (pcap->activated) {
407+
/* Not set by the module, so probably not supported */
408+
return PCAP_WARNING_CONTROL_KEEPALIVE_NOTSUP;
409+
}
410+
/* in case the caller doesn't check for PCAP_ERROR_NOT_ACTIVATED */
411+
(void)snprintf(pcap->errbuf, sizeof(pcap->errbuf),
412+
"This handle hasn't been activated yet");
413+
return (PCAP_ERROR_NOT_ACTIVATED);
414+
}
415+
402416
#ifdef _WIN32
403417
static struct pcap_stat *
404418
pcap_stats_ex_not_initialized(pcap_t *pcap, int *pcap_stat_size _U_)
@@ -2408,6 +2422,7 @@ initialize_ops(pcap_t *p)
24082422
p->set_datalink_op = pcap_set_datalink_not_initialized;
24092423
p->getnonblock_op = pcap_getnonblock_not_initialized;
24102424
p->stats_op = pcap_stats_not_initialized;
2425+
p->set_control_keepalive_op = pcap_set_control_keepalive_not_initialized;
24112426
#ifdef _WIN32
24122427
p->stats_ex_op = pcap_stats_ex_not_initialized;
24132428
p->setbuff_op = pcap_setbuff_not_initialized;
@@ -3695,6 +3710,9 @@ pcap_statustostr(int errnum)
36953710

36963711
case PCAP_ERROR_TSTAMP_PRECISION_NOTSUP:
36973712
return ("That device doesn't support that time stamp precision");
3713+
3714+
case PCAP_WARNING_CONTROL_KEEPALIVE_NOTSUP:
3715+
return ("Keepalive control is not supported");
36983716
}
36993717
(void)snprintf(ebuf, sizeof ebuf, "Unknown error: %d", errnum);
37003718
return(ebuf);
@@ -3776,6 +3794,12 @@ pcap_stats(pcap_t *p, struct pcap_stat *ps)
37763794
return (p->stats_op(p, ps));
37773795
}
37783796

3797+
int
3798+
pcap_set_control_keepalive(pcap_t *p, int enable, int keepcnt, int keepidle, int keepintvl)
3799+
{
3800+
return p->set_control_keepalive_op(p, enable, keepcnt, keepidle, keepintvl);
3801+
}
3802+
37793803
#ifdef _WIN32
37803804
struct pcap_stat *
37813805
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
@@ -396,6 +396,7 @@ typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *,
396396
#define PCAP_ERROR_CANTSET_TSTAMP_TYPE -10 /* this device doesn't support setting the time stamp type */
397397
#define PCAP_ERROR_PROMISC_PERM_DENIED -11 /* you don't have permission to capture in promiscuous mode */
398398
#define PCAP_ERROR_TSTAMP_PRECISION_NOTSUP -12 /* the requested time stamp precision is not supported */
399+
#define PCAP_WARNING_CONTROL_KEEPALIVE_NOTSUP -13 /* keepalive control is not supported */
399400

400401
/*
401402
* Warning codes for the pcap API.
@@ -627,6 +628,9 @@ PCAP_API void pcap_breakloop(pcap_t *);
627628
PCAP_AVAILABLE_0_4
628629
PCAP_API int pcap_stats(pcap_t *, struct pcap_stat *);
629630

631+
PCAP_AVAILABLE_1_11
632+
PCAP_API int pcap_set_control_keepalive(pcap_t *, int, int, int, int);
633+
630634
PCAP_AVAILABLE_0_4
631635
PCAP_API int pcap_setfilter(pcap_t *, struct bpf_program *);
632636

pcap_set_control_keepalive.3pcap

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
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
37+
keepcnt,
38+
.I
39+
keepidle, and
40+
.I keepintvl
41+
are used to set the corresponding tcp options. Respectively
42+
.B
43+
TCP_KEEPCNT
44+
(The maximum number of keepalive probes TCP should send before dropping the connection),
45+
.B TCP_KEEPIDLE
46+
(The time (in seconds) the connection needs to remain idle before TCP starts sending keepalive probes), and
47+
.B
48+
TCP_KEEPINTVL
49+
(The time (in seconds) between individual keepalive probes.)
50+
.SH RETURN VALUE
51+
.BR pcap_set_control_keepalive ()
52+
returns
53+
.B 0
54+
on success or
55+
.B PCAP_ERROR
56+
if we failed to set the socket options.
57+
.SH SEE ALSO
58+
.BR pcap (3PCAP),

0 commit comments

Comments
 (0)