Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ DayOfTheWeek, Month DD, YYYY / The Tcpdump Group
another incorporate-remote-capture project. (issue #1120)
rpcapd: Refine SSL options in printusage().
Fix a possible buffer overflow (Coverity CID 1619148).
Add API to customize the keepalives parameters of a rpcap control socket
Documentation:
Document a standard format for writing out BPF filter programs.
Add a README.hurd.md file.
Expand Down
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3391,6 +3391,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 @@ -202,6 +202,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 @@ -197,6 +197,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 @@ -339,6 +340,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 @@ -41,6 +41,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 @@ -178,6 +183,7 @@ static int rpcap_recv(PCAP_SOCKET sock, SSL *, void *buffer, size_t toread, uint
static void rpcap_msg_err(PCAP_SOCKET sockctrl, SSL *, uint32_t plen, char *remote_errbuf);
static int rpcap_discard(PCAP_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 @@ -2646,6 +2652,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 @@ -3718,3 +3725,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;
}
25 changes: 25 additions & 0 deletions pcap.c
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,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 @@ -2412,6 +2426,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 @@ -3706,6 +3721,10 @@ pcap_statustostr(int errnum)

case PCAP_ERROR_CAPTURE_NOTSUP:
return ("Packet capture is not supported on that device");

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 @@ -3852,6 +3871,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 @@ -370,6 +370,7 @@ typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *,
#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_ERROR_CAPTURE_NOTSUP -13 /* capture mechanism not available */
#define PCAP_WARNING_CONTROL_KEEPALIVE_NOTSUP -14 /* keepalive control is not supported */

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

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 *)
PCAP_WARN_UNUSED_RESULT;
Expand Down
56 changes: 56 additions & 0 deletions pcap_set_control_keepalive.3pcap
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
.\" 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),