dect
/
libpcap
Archived
1
0
Fork 0

If the specified time stamp type isn't supported, treat that as a warning.

master
Guy Harris 12 years ago
parent fa4435e65c
commit ce38b0cd9b
  1. 203
      pcap-linux.c
  2. 8
      pcap.c
  3. 2
      pcap/pcap.h
  4. 11
      pcap_activate.3pcap
  5. 12
      pcap_set_tstamp_type.3pcap.in

@ -300,7 +300,7 @@ static short int map_packet_type_to_sll_type(short int);
static int pcap_activate_linux(pcap_t *);
static int activate_old(pcap_t *);
static int activate_new(pcap_t *);
static int activate_mmap(pcap_t *);
static int activate_mmap(pcap_t *, int *);
static int pcap_can_set_rfmon_linux(pcap_t *);
static int pcap_read_linux(pcap_t *, int, pcap_handler, u_char *);
static int pcap_read_packet(pcap_t *, pcap_handler, u_char *);
@ -320,7 +320,7 @@ union thdr {
#define RING_GET_FRAME(h) (((union thdr **)h->buffer)[h->offset])
static void destroy_ring(pcap_t *handle);
static int create_ring(pcap_t *handle);
static int create_ring(pcap_t *handle, int *status);
static int prepare_tpacket_socket(pcap_t *handle);
static void pcap_cleanup_linux_mmap(pcap_t *);
static int pcap_read_linux_mmap(pcap_t *, int, pcap_handler , u_char *);
@ -1193,18 +1193,30 @@ pcap_activate_linux(pcap_t *handle)
* to be compatible with older kernels for a while so we are
* trying both methods with the newer method preferred.
*/
if ((status = activate_new(handle)) == 1) {
status = activate_new(handle);
if (status < 0) {
/*
* Fatal error with the new way; just fail.
* status has the error return; if it's PCAP_ERROR,
* handle->errbuf has been set appropriately.
*/
goto fail;
}
if (status == 1) {
/*
* Success.
* Try to use memory-mapped access.
*/
status = activate_mmap(handle);
switch (status) {
switch (activate_mmap(handle, &status)) {
case 1:
/* we succeeded; nothing more to do */
return 0;
/*
* We succeeded. status has been
* set to the status to return,
* which might be 0, or might be
* a PCAP_WARNING_ value.
*/
return status;
case 0:
/*
@ -1213,11 +1225,11 @@ pcap_activate_linux(pcap_t *handle)
*/
break;
default:
case -1:
/*
* We failed to set up to use it, or kernel
* supports it, but we failed to enable it;
* the return value is the error status to
* We failed to set up to use it, or the kernel
* supports it, but we failed to enable it.
* status has been set to the error status to
* return and, if it's PCAP_ERROR, handle->errbuf
* contains the error message.
*/
@ -1234,18 +1246,12 @@ pcap_activate_linux(pcap_t *handle)
*/
goto fail;
}
} else {
/*
* Fatal error with the new way; just fail.
* status has the error return; if it's PCAP_ERROR,
* handle->errbuf has been set appropriately.
*/
goto fail;
}
/*
* We set up the socket, but not with memory-mapped access.
*/
status = 0;
if (handle->opt.buffer_size != 0) {
/*
* Set the socket buffer size to the specified value.
@ -2982,10 +2988,22 @@ activate_new(pcap_t *handle)
#endif
}
#ifdef HAVE_PACKET_RING
/*
* Attempt to activate with memory-mapped access.
*
* On success, returns 1, and sets *status to 0 if there are no warnings
* or to a PCAP_WARNING_ code if there is a warning.
*
* On failure due to lack of support for memory-mapped capture, returns
* 0.
*
* On error, returns -1, and sets *status to the appropriate error code;
* if that is PCAP_ERROR, sets handle->errbuf to the appropriate message.
*/
static int
activate_mmap(pcap_t *handle)
activate_mmap(pcap_t *handle, int *status)
{
#ifdef HAVE_PACKET_RING
int ret;
/*
@ -2997,7 +3015,8 @@ activate_mmap(pcap_t *handle)
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"can't allocate oneshot buffer: %s",
pcap_strerror(errno));
return PCAP_ERROR;
*status = PCAP_ERROR;
return -1;
}
if (handle->opt.buffer_size == 0) {
@ -3005,20 +3024,38 @@ activate_mmap(pcap_t *handle)
handle->opt.buffer_size = 2*1024*1024;
}
ret = prepare_tpacket_socket(handle);
if (ret != 1) {
if (ret == -1) {
free(handle->md.oneshot_buffer);
*status = PCAP_ERROR;
return ret;
}
ret = create_ring(handle);
if (ret != 1) {
ret = create_ring(handle, status);
if (ret == 0) {
/*
* We don't support memory-mapped capture; our caller
* will fall back on reading from the socket.
*/
free(handle->md.oneshot_buffer);
return ret;
return 0;
}
if (ret == -1) {
/*
* Error attempting to enable memory-mapped capture;
* fail. create_ring() has set *status.
*/
free(handle->md.oneshot_buffer);
return -1;
}
/* override some defaults and inherit the other fields from
* activate_new
* handle->offset is used to get the current position into the rx ring
* handle->cc is used to store the ring size */
/*
* Success. *status has been set either to 0 if there are no
* warnings or to a PCAP_WARNING_ value if there is a warning.
*
* Override some defaults and inherit the other fields from
* activate_new.
* handle->offset is used to get the current position into the rx ring.
* handle->cc is used to store the ring size.
*/
handle->read_op = pcap_read_linux_mmap;
handle->cleanup_op = pcap_cleanup_linux_mmap;
handle->setfilter_op = pcap_setfilter_linux_mmap;
@ -3027,12 +3064,21 @@ activate_mmap(pcap_t *handle)
handle->oneshot_callback = pcap_oneshot_mmap;
handle->selectable_fd = handle->fd;
return 1;
}
#else /* HAVE_PACKET_RING */
static int
activate_mmap(pcap_t *handle _U_, int *status _U_)
{
return 0;
#endif /* HAVE_PACKET_RING */
}
#endif /* HAVE_PACKET_RING */
#ifdef HAVE_PACKET_RING
/*
* Attempt to set the socket to version 2 of the memory-mapped header.
* Return 1 if we succeed or if we fail because version 2 isn't
* supported; return -1 on any other error, and set handle->errbuf.
*/
static int
prepare_tpacket_socket(pcap_t *handle)
{
@ -3084,12 +3130,29 @@ prepare_tpacket_socket(pcap_t *handle)
return 1;
}
/*
* Attempt to set up memory-mapped access.
*
* On success, returns 1, and sets *status to 0 if there are no warnings
* or to a PCAP_WARNING_ code if there is a warning.
*
* On failure due to lack of support for memory-mapped capture, returns
* 0.
*
* On error, returns -1, and sets *status to the appropriate error code;
* if that is PCAP_ERROR, sets handle->errbuf to the appropriate message.
*/
static int
create_ring(pcap_t *handle)
create_ring(pcap_t *handle, int *status)
{
unsigned i, j, frames_per_block;
struct tpacket_req req;
/*
* Start out assuming no warnings or errors.
*/
*status = 0;
/* Note that with large snapshot (say 64K) only a few frames
* will be available in the ring even with pretty large ring size
* (and a lot of memory will be unused).
@ -3153,39 +3216,62 @@ create_ring(pcap_t *handle)
switch (errno) {
case EPERM:
return PCAP_ERROR_PERM_DENIED;
/*
* Treat this as an error, as the
* user should try to run this
* with the appropriate privileges -
* and, if they can't, shouldn't
* try requesting hardware time stamps.
*/
*status = PCAP_ERROR_PERM_DENIED;
return -1;
case EOPNOTSUPP:
return PCAP_ERROR_TSTAMP_TYPE_NOTSUP:
/*
* Treat this as a warning, as the
* only way to fix the warning is to
* get an adapter that supports hardware
* time stamps. We'll just fall back
* on the standard host time stamps.
*/
*status = PCAP_WARNING_TSTAMP_TYPE_NOTSUP:
break;
default:
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"SIOCSHWTSTAMP failed: %s",
pcap_strerror(errno));
return PCAP_ERROR;
*status = PCAP_ERROR;
return -1;
}
}
if (handle->opt.tstamp_type == PCAP_TSTAMP_ADAPTER) {
/*
* Hardware timestamp, synchronized
* with the system clock.
*/
timesource = SOF_TIMESTAMPING_SYS_HARDWARE;
} else {
/*
* PCAP_TSTAMP_ADAPTER_UNSYNCED - hardware
* timestamp, not synchronized with the
* system clock.
* Well, that worked. Now specify the type of
* hardware time stamp we want for this
* socket.
*/
timesource = SOF_TIMESTAMPING_RAW_HARDWARE;
}
if (setsockopt(handle->fd, SOL_PACKET, PACKET_TIMESTAMP,
(void *)&timesource, sizeof(timesource))) {
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"can't set PACKET_TIMESTAMP: %s",
pcap_strerror(errno));
return PCAP_ERROR;
if (handle->opt.tstamp_type == PCAP_TSTAMP_ADAPTER) {
/*
* Hardware timestamp, synchronized
* with the system clock.
*/
timesource = SOF_TIMESTAMPING_SYS_HARDWARE;
} else {
/*
* PCAP_TSTAMP_ADAPTER_UNSYNCED - hardware
* timestamp, not synchronized with the
* system clock.
*/
timesource = SOF_TIMESTAMPING_RAW_HARDWARE;
}
if (setsockopt(handle->fd, SOL_PACKET, PACKET_TIMESTAMP,
(void *)&timesource, sizeof(timesource))) {
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"can't set PACKET_TIMESTAMP: %s",
pcap_strerror(errno));
*status = PCAP_ERROR;
return -1;
}
}
}
#endif /* HAVE_LINUX_NET_TSTAMP_H && PACKET_TIMESTAMP */
@ -3224,7 +3310,8 @@ retry:
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"can't create rx ring on packet socket: %s",
pcap_strerror(errno));
return PCAP_ERROR;
*status = PCAP_ERROR;
return -1;
}
/* memory map the rx ring */
@ -3237,7 +3324,8 @@ retry:
/* clear the allocated ring on error*/
destroy_ring(handle);
return PCAP_ERROR;
*status = PCAP_ERROR;
return -1;
}
/* allocate a ring for each frame header pointer*/
@ -3249,7 +3337,8 @@ retry:
pcap_strerror(errno));
destroy_ring(handle);
return PCAP_ERROR;
*status = PCAP_ERROR;
return -1;
}
/* fill the header ring with proper frame ptr*/

@ -391,7 +391,7 @@ pcap_set_tstamp_type(pcap_t *p, int tstamp_type)
* No. We support setting the time stamp type, but not to this
* particular value.
*/
return PCAP_ERROR_TSTAMP_TYPE_NOTSUP;
return PCAP_WARNING_TSTAMP_TYPE_NOTSUP;
}
int
@ -1114,6 +1114,9 @@ pcap_statustostr(int errnum)
case PCAP_WARNING:
return("Generic warning");
case PCAP_WARNING_TSTAMP_TYPE_NOTSUP:
return ("That type of time stamp is not supported by that device");
case PCAP_WARNING_PROMISC_NOTSUP:
return ("That device doesn't support promiscuous mode");
@ -1146,9 +1149,6 @@ pcap_statustostr(int errnum)
case PCAP_ERROR_CANTSET_TSTAMP_TYPE:
return ("That device doesn't support setting the time stamp type");
case PCAP_ERROR_TSTAMP_TYPE_NOTSUP:
return ("That type of time stamp is not supported by that device");
}
(void)snprintf(ebuf, sizeof ebuf, "Unknown error: %d", errnum);
return(ebuf);

@ -252,7 +252,6 @@ typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *,
#define PCAP_ERROR_PERM_DENIED -8 /* no permission to open the device */
#define PCAP_ERROR_IFACE_NOT_UP -9 /* interface isn't up */
#define PCAP_ERROR_CANTSET_TSTAMP_TYPE -10 /* this device doesn't support setting the time stamp type */
#define PCAP_ERROR_TSTAMP_TYPE_NOTSUP -11 /* the requested time stamp type is not supported */
/*
* Warning codes for the pcap API.
@ -261,6 +260,7 @@ typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *,
*/
#define PCAP_WARNING 1 /* generic warning code */
#define PCAP_WARNING_PROMISC_NOTSUP 2 /* this device doesn't support promiscuous mode */
#define PCAP_WARNING_TSTAMP_TYPE_NOTSUP 3 /* the requested time stamp type is not supported */
/*
* Value to pass to pcap_compile() as the netmask if you don't know what

@ -43,6 +43,11 @@ returns 0 on success without warnings,
.B PCAP_WARNING_PROMISC_NOTSUP
on success on a device that doesn't support promiscuous mode if
promiscuous mode was requested,
.B PCAP_WARNING_TSTAMP_TYPE_NOTSUP
on success if the time stamp type specified in a previous
.B pcap_set_tstamp_type()
call isn't supported by the capture source (the time stamp type is
left as the default),
.B PCAP_WARNING
on success with any other warning,
.B PCAP_ERROR_ACTIVATED
@ -56,11 +61,7 @@ if the process doesn't have permission to open the capture source,
if monitor mode was specified but the capture source doesn't support
monitor mode,
.B PCAP_ERROR_IFACE_NOT_UP
if the capture source is not up,
.B PCAP_ERROR_TSTAMP_TYPE_NOTSUP
if the time stamp specified in a previous
.B pcap_set_tstamp_type()
call isn't supported by the capture source, and
if the capture source is not up, and
.B PCAP_ERROR
if another error occurred.
If

@ -49,13 +49,15 @@ See
for a list of all the time stamp types.
.SH RETURN VALUE
.B pcap_set_tstamp_type()
returns 0 on success,
returns 0 on success if the specified time stamp type is expected to be
supported by the capture device,
.B PCAP_WARNING_TSTAMP_TYPE_NOTSUP
on success if the specified time stamp type is not supported by the
capture device,
.B PCAP_ERROR_ACTIVATED
if called on a capture handle that has been activated,
if called on a capture handle that has been activated, and
.B PCAP_ERROR_CANTSET_TSTAMP_TYPE
if the capture device doesn't support setting the time stamp type, and
.B PCAP_ERROR_TSTAMP_TYPE_NOTSUP
if the specified time stamp type is not supported by the capture device.
if the capture device doesn't support setting the time stamp type.
.SH SEE ALSO
pcap(3PCAP),
pcap_list_tstamp_types(3PCAP),