dect
/
libpcap
Archived
13
0
Fork 0

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

This commit is contained in:
Guy Harris 2010-08-22 19:09:50 -07:00
parent fa4435e65c
commit ce38b0cd9b
5 changed files with 167 additions and 75 deletions

View File

@ -300,7 +300,7 @@ static short int map_packet_type_to_sll_type(short int);
static int pcap_activate_linux(pcap_t *); static int pcap_activate_linux(pcap_t *);
static int activate_old(pcap_t *); static int activate_old(pcap_t *);
static int activate_new(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_can_set_rfmon_linux(pcap_t *);
static int pcap_read_linux(pcap_t *, int, pcap_handler, u_char *); static int pcap_read_linux(pcap_t *, int, pcap_handler, u_char *);
static int pcap_read_packet(pcap_t *, 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]) #define RING_GET_FRAME(h) (((union thdr **)h->buffer)[h->offset])
static void destroy_ring(pcap_t *handle); 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 int prepare_tpacket_socket(pcap_t *handle);
static void pcap_cleanup_linux_mmap(pcap_t *); static void pcap_cleanup_linux_mmap(pcap_t *);
static int pcap_read_linux_mmap(pcap_t *, int, pcap_handler , u_char *); 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 * to be compatible with older kernels for a while so we are
* trying both methods with the newer method preferred. * trying both methods with the newer method preferred.
*/ */
status = activate_new(handle);
if ((status = activate_new(handle)) == 1) { 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. * Success.
* Try to use memory-mapped access. * Try to use memory-mapped access.
*/ */
status = activate_mmap(handle); switch (activate_mmap(handle, &status)) {
switch (status) {
case 1: 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: case 0:
/* /*
@ -1213,11 +1225,11 @@ pcap_activate_linux(pcap_t *handle)
*/ */
break; break;
default: case -1:
/* /*
* We failed to set up to use it, or kernel * We failed to set up to use it, or the kernel
* supports it, but we failed to enable it; * supports it, but we failed to enable it.
* the return value is the error status to * status has been set to the error status to
* return and, if it's PCAP_ERROR, handle->errbuf * return and, if it's PCAP_ERROR, handle->errbuf
* contains the error message. * contains the error message.
*/ */
@ -1234,18 +1246,12 @@ pcap_activate_linux(pcap_t *handle)
*/ */
goto fail; 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. * We set up the socket, but not with memory-mapped access.
*/ */
status = 0;
if (handle->opt.buffer_size != 0) { if (handle->opt.buffer_size != 0) {
/* /*
* Set the socket buffer size to the specified value. * Set the socket buffer size to the specified value.
@ -2982,10 +2988,22 @@ activate_new(pcap_t *handle)
#endif #endif
} }
static int
activate_mmap(pcap_t *handle)
{
#ifdef HAVE_PACKET_RING #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, int *status)
{
int ret; int ret;
/* /*
@ -2997,7 +3015,8 @@ activate_mmap(pcap_t *handle)
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"can't allocate oneshot buffer: %s", "can't allocate oneshot buffer: %s",
pcap_strerror(errno)); pcap_strerror(errno));
return PCAP_ERROR; *status = PCAP_ERROR;
return -1;
} }
if (handle->opt.buffer_size == 0) { if (handle->opt.buffer_size == 0) {
@ -3005,20 +3024,38 @@ activate_mmap(pcap_t *handle)
handle->opt.buffer_size = 2*1024*1024; handle->opt.buffer_size = 2*1024*1024;
} }
ret = prepare_tpacket_socket(handle); ret = prepare_tpacket_socket(handle);
if (ret != 1) { if (ret == -1) {
free(handle->md.oneshot_buffer); free(handle->md.oneshot_buffer);
*status = PCAP_ERROR;
return ret; return ret;
} }
ret = create_ring(handle); ret = create_ring(handle, status);
if (ret != 1) { 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); 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 * Success. *status has been set either to 0 if there are no
* handle->offset is used to get the current position into the rx ring * warnings or to a PCAP_WARNING_ value if there is a warning.
* handle->cc is used to store the ring size */ *
* 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->read_op = pcap_read_linux_mmap;
handle->cleanup_op = pcap_cleanup_linux_mmap; handle->cleanup_op = pcap_cleanup_linux_mmap;
handle->setfilter_op = pcap_setfilter_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->oneshot_callback = pcap_oneshot_mmap;
handle->selectable_fd = handle->fd; handle->selectable_fd = handle->fd;
return 1; return 1;
#else /* HAVE_PACKET_RING */
return 0;
#endif /* HAVE_PACKET_RING */
} }
#else /* HAVE_PACKET_RING */
static int
activate_mmap(pcap_t *handle _U_, int *status _U_)
{
return 0;
}
#endif /* HAVE_PACKET_RING */
#ifdef 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 static int
prepare_tpacket_socket(pcap_t *handle) prepare_tpacket_socket(pcap_t *handle)
{ {
@ -3084,12 +3130,29 @@ prepare_tpacket_socket(pcap_t *handle)
return 1; 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 static int
create_ring(pcap_t *handle) create_ring(pcap_t *handle, int *status)
{ {
unsigned i, j, frames_per_block; unsigned i, j, frames_per_block;
struct tpacket_req req; struct tpacket_req req;
/*
* Start out assuming no warnings or errors.
*/
*status = 0;
/* Note that with large snapshot (say 64K) only a few frames /* Note that with large snapshot (say 64K) only a few frames
* will be available in the ring even with pretty large ring size * will be available in the ring even with pretty large ring size
* (and a lot of memory will be unused). * (and a lot of memory will be unused).
@ -3153,39 +3216,62 @@ create_ring(pcap_t *handle)
switch (errno) { switch (errno) {
case EPERM: 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: 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: default:
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"SIOCSHWTSTAMP failed: %s", "SIOCSHWTSTAMP failed: %s",
pcap_strerror(errno)); 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 { } else {
/* /*
* PCAP_TSTAMP_ADAPTER_UNSYNCED - hardware * Well, that worked. Now specify the type of
* timestamp, not synchronized with the * hardware time stamp we want for this
* system clock. * socket.
*/ */
timesource = SOF_TIMESTAMPING_RAW_HARDWARE; if (handle->opt.tstamp_type == PCAP_TSTAMP_ADAPTER) {
} /*
if (setsockopt(handle->fd, SOL_PACKET, PACKET_TIMESTAMP, * Hardware timestamp, synchronized
(void *)&timesource, sizeof(timesource))) { * with the system clock.
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, */
"can't set PACKET_TIMESTAMP: %s", timesource = SOF_TIMESTAMPING_SYS_HARDWARE;
pcap_strerror(errno)); } else {
return PCAP_ERROR; /*
* 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 */ #endif /* HAVE_LINUX_NET_TSTAMP_H && PACKET_TIMESTAMP */
@ -3224,7 +3310,8 @@ retry:
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"can't create rx ring on packet socket: %s", "can't create rx ring on packet socket: %s",
pcap_strerror(errno)); pcap_strerror(errno));
return PCAP_ERROR; *status = PCAP_ERROR;
return -1;
} }
/* memory map the rx ring */ /* memory map the rx ring */
@ -3237,7 +3324,8 @@ retry:
/* clear the allocated ring on error*/ /* clear the allocated ring on error*/
destroy_ring(handle); destroy_ring(handle);
return PCAP_ERROR; *status = PCAP_ERROR;
return -1;
} }
/* allocate a ring for each frame header pointer*/ /* allocate a ring for each frame header pointer*/
@ -3249,7 +3337,8 @@ retry:
pcap_strerror(errno)); pcap_strerror(errno));
destroy_ring(handle); destroy_ring(handle);
return PCAP_ERROR; *status = PCAP_ERROR;
return -1;
} }
/* fill the header ring with proper frame ptr*/ /* fill the header ring with proper frame ptr*/

8
pcap.c
View File

@ -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 * No. We support setting the time stamp type, but not to this
* particular value. * particular value.
*/ */
return PCAP_ERROR_TSTAMP_TYPE_NOTSUP; return PCAP_WARNING_TSTAMP_TYPE_NOTSUP;
} }
int int
@ -1114,6 +1114,9 @@ pcap_statustostr(int errnum)
case PCAP_WARNING: case PCAP_WARNING:
return("Generic 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: case PCAP_WARNING_PROMISC_NOTSUP:
return ("That device doesn't support promiscuous mode"); return ("That device doesn't support promiscuous mode");
@ -1146,9 +1149,6 @@ pcap_statustostr(int errnum)
case PCAP_ERROR_CANTSET_TSTAMP_TYPE: case PCAP_ERROR_CANTSET_TSTAMP_TYPE:
return ("That device doesn't support setting the time stamp 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); (void)snprintf(ebuf, sizeof ebuf, "Unknown error: %d", errnum);
return(ebuf); return(ebuf);

View File

@ -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_PERM_DENIED -8 /* no permission to open the device */
#define PCAP_ERROR_IFACE_NOT_UP -9 /* interface isn't up */ #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_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. * 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 1 /* generic warning code */
#define PCAP_WARNING_PROMISC_NOTSUP 2 /* this device doesn't support promiscuous mode */ #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 * Value to pass to pcap_compile() as the netmask if you don't know what

View File

@ -43,6 +43,11 @@ returns 0 on success without warnings,
.B PCAP_WARNING_PROMISC_NOTSUP .B PCAP_WARNING_PROMISC_NOTSUP
on success on a device that doesn't support promiscuous mode if on success on a device that doesn't support promiscuous mode if
promiscuous mode was requested, 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 .B PCAP_WARNING
on success with any other warning, on success with any other warning,
.B PCAP_ERROR_ACTIVATED .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 if monitor mode was specified but the capture source doesn't support
monitor mode, monitor mode,
.B PCAP_ERROR_IFACE_NOT_UP .B PCAP_ERROR_IFACE_NOT_UP
if the capture source is not up, if the capture source is not up, and
.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
.B PCAP_ERROR .B PCAP_ERROR
if another error occurred. if another error occurred.
If If

View File

@ -49,13 +49,15 @@ See
for a list of all the time stamp types. for a list of all the time stamp types.
.SH RETURN VALUE .SH RETURN VALUE
.B pcap_set_tstamp_type() .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 .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 .B PCAP_ERROR_CANTSET_TSTAMP_TYPE
if the capture device doesn't support setting the time stamp type, and if the capture device doesn't support setting the time stamp type.
.B PCAP_ERROR_TSTAMP_TYPE_NOTSUP
if the specified time stamp type is not supported by the capture device.
.SH SEE ALSO .SH SEE ALSO
pcap(3PCAP), pcap(3PCAP),
pcap_list_tstamp_types(3PCAP), pcap_list_tstamp_types(3PCAP),