]> The Tcpdump Group git mirrors - libpcap/commitdiff
Remove Linux-specific time stamp precision stuff from pcap.c.
authorGuy Harris <[email protected]>
Tue, 2 Jul 2013 02:09:41 +0000 (19:09 -0700)
committerGuy Harris <[email protected]>
Tue, 2 Jul 2013 02:09:41 +0000 (19:09 -0700)
Do time stamp precisions the way we do time stamp types - if a module
supports more than one time stamp precision, have it attach a table of
time stamp precisions to the pcap_t, and have the code to set the time
stamp check that list.

Check for the two #ifdefs in pcap-linux.c to see whether it supports
nanosecond time stamps - and don't use the ioctl or the socket option
for those #ifdefs if they're not defined.

This means we don't need to check for it in the configure script.

Also, have both the time stamp type-setting and precision-setting
routines allow the default value (PCAP_TSTAMP_NONE/PCAP_TSTAMP_PRECISION_MICRO)
if no list is supplied.

Make "can't set the precision" an error; not being able to set the time
stamp *type* doesn't mean your code won't work at all, it just means the
time stamps won't be as accurate as you'd like, but not being able to
set the time stamp *precision* means you'll be getting
seconds/microseconds, and your code may have to cope with that.

config.h.in
configure
configure.in
pcap-int.h
pcap-linux.c
pcap.c
pcap/pcap.h

index bb30cfcb3d9fa8ef40e295125834192819b33c5a..1351a79cf1101092c62f4cd95acf2bc7fc1ecc7d 100644 (file)
@@ -85,9 +85,6 @@
 /* if tp_vlan_tci exists */
 #undef HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI
 
-/* define if we can use nanosecond timestamps */
-#undef HAVE_LINUX_TSTAMP_NANO
-
 /* Define to 1 if you have the <linux/types.h> header file. */
 #undef HAVE_LINUX_TYPES_H
 
index cb11d192849ab0ecb59917d975a5ddff7fa011b4..ab808d3acf3b101c20ed6a95200ffe7761e0333a 100755 (executable)
--- a/configure
+++ b/configure
@@ -8045,60 +8045,6 @@ echo "$as_me: error: libnl support requested but libnl not found" >&2;}
                fi
        fi
 
-       # Do we have support for nanosecond timestamps in kernel?
-       { echo "$as_me:$LINENO: checking whether the system supports timestamps with nanosecond resolution" >&5
-echo $ECHO_N "checking whether the system supports timestamps with nanosecond resolution... $ECHO_C" >&6; }
-       cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-
-               #include <linux/sockios.h>
-               #include <linux/net.h>
-int
-main ()
-{
-return SIOCGSTAMPNS && SO_TIMESTAMPNS
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-        test -z "$ac_c_werror_flag" ||
-        test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_LINUX_TSTAMP_NANO 1
-_ACEOF
-
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-       { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
 
 for ac_header in linux/ethtool.h
 do
index 4d44af8c7b059c21f71859218ad47529dcd69090..b7924129114dd337d2974e689e6757b540447c8f 100644 (file)
@@ -507,16 +507,6 @@ linux)
                fi
        fi
 
-       # Do we have support for nanosecond timestamps in kernel?
-       AC_MSG_CHECKING(whether the system supports timestamps with nanosecond resolution)
-       AC_TRY_COMPILE([
-               #include <linux/sockios.h>
-               #include <linux/net.h>],
-               [return SIOCGSTAMPNS && SO_TIMESTAMPNS],
-               [AC_MSG_RESULT(yes)
-                       AC_DEFINE([HAVE_LINUX_TSTAMP_NANO], 1, [define if we can use nanosecond timestamps])],
-               AC_MSG_RESULT(no))
-
        AC_CHECK_HEADERS(linux/ethtool.h,,,
            [
 AC_INCLUDES_DEFAULT
index 74db6aefaec104aeb5ad532e5001a2719907c4dc..2d7ae6f58c34455b4f7a27b251d582c902e16ac0 100644 (file)
@@ -191,6 +191,8 @@ struct pcap {
        u_int *dlt_list;
        int tstamp_type_count;
        u_int *tstamp_type_list;
+       int tstamp_precision_count;
+       u_int *tstamp_precision_list;
 
        struct pcap_pkthdr pcap_header; /* This is needed for the pcap_next_ex() to work */
 
index f88270b26d9425282e744b5176ccdc1f6284741d..7c14821a0475b62ec185c1df61ce2780c1bbbcb9 100644 (file)
@@ -134,6 +134,7 @@ static const char rcsid[] _U_ =
 #include <sys/mman.h>
 #include <linux/if.h>
 #include <linux/if_packet.h>
+#include <linux/sockios.h>
 #include <netinet/in.h>
 #include <linux/if_ether.h>
 #include <net/if_arp.h>
@@ -208,15 +209,6 @@ static const char rcsid[] _U_ =
 #include <linux/filter.h>
 #endif
 
-/*
- * We need linux/sockios.h if we have linux/net_tstamp.h (for time stamp
- * specification) or linux/ethtool.h (for ethtool ioctls to get offloading
- * information).
- */
-#if defined(HAVE_LINUX_NET_TSTAMP_H) || defined(HAVE_LINUX_ETHTOOL_H)
-#include <linux/sockios.h>
-#endif
-
 #ifdef HAVE_LINUX_NET_TSTAMP_H
 #include <linux/net_tstamp.h>
 #endif
@@ -423,6 +415,27 @@ pcap_create_interface(const char *device, char *ebuf)
        handle->tstamp_type_list[2] = PCAP_TSTAMP_ADAPTER_UNSYNCED;
 #endif
 
+#if defined(SIOCGSTAMPNS) && defined(SO_TIMESTAMPNS)
+       /*
+        * We claim that we support microsecond and nanosecond time
+        * stamps.
+        *
+        * XXX - with adapter-supplied time stamps, can we choose
+        * microsecond or nanosecond time stamps on arbitrary
+        * adapters?
+        */
+       handle->tstamp_precision_count = 2;
+       handle->tstamp_type_list = malloc(2 * sizeof(u_int));
+       if (handle->tstamp_type_list == NULL) {
+               if (handle->tstamp_type_list != NULL)
+                       free(handle->tstamp_type_list);
+               free(handle);
+               return NULL;
+       }
+       handle->tstamp_type_list[0] = PCAP_TSTAMP_PRECISION_MICRO;
+       handle->tstamp_type_list[1] = PCAP_TSTAMP_PRECISION_NANO;
+#endif /* defined(SIOCGSTAMPNS) && defined(SO_TIMESTAMPNS) */
+
        return handle;
 }
 
@@ -1682,13 +1695,16 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)
        /* Fill in our own header data */
 
        /* get timestamp for this packet */
+#if defined(SIOCGSTAMPNS) && defined(SO_TIMESTAMPNS)
        if (handle->opt.tstamp_precision == PCAP_TSTAMP_PRECISION_NANO) {
                if (ioctl(handle->fd, SIOCGSTAMPNS, &pcap_header.ts) == -1) {
                        snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
                                        "SIOCGSTAMPNS: %s", pcap_strerror(errno));
                        return PCAP_ERROR;
                }
-        } else {
+        } else
+#endif
+       {
                if (ioctl(handle->fd, SIOCGSTAMP, &pcap_header.ts) == -1) {
                        snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
                                        "SIOCGSTAMP: %s", pcap_strerror(errno));
@@ -3259,6 +3275,7 @@ activate_new(pcap_t *handle)
        /* Save the socket FD in the pcap structure */
        handle->fd = sock_fd;
 
+#if defined(SIOCGSTAMPNS) && defined(SO_TIMESTAMPNS)
        if (handle->opt.tstamp_precision == PCAP_TSTAMP_PRECISION_NANO) {
                int nsec_tstamps = 1;
 
@@ -3267,14 +3284,15 @@ activate_new(pcap_t *handle)
                        return PCAP_ERROR;
                }
        }
+#endif /* defined(SIOCGSTAMPNS) && defined(SO_TIMESTAMPNS) */
 
        return 1;
-#else
+#else /* HAVE_PF_PACKET_SOCKETS */
        strncpy(ebuf,
                "New packet capturing interface not supported by build "
                "environment", PCAP_ERRBUF_SIZE);
        return 0;
-#endif
+#endif /* HAVE_PF_PACKET_SOCKETS */
 }
 
 #ifdef HAVE_PACKET_RING
diff --git a/pcap.c b/pcap.c
index 3c3dccdd8e78c1d7ef20ddfc2cd80567496efe05..002e8fc1d5cd8a70ca862a96ae169a9e1465e066 100644 (file)
--- a/pcap.c
+++ b/pcap.c
@@ -617,28 +617,31 @@ pcap_set_tstamp_type(pcap_t *p, int tstamp_type)
                return (PCAP_ERROR_ACTIVATED);
 
        /*
-        * If p->tstamp_type_count is 0, we don't support setting
-        * the time stamp type at all.
+        * If p->tstamp_type_count is 0, we only support PCAP_TSTAMP_HOST;
+        * the default time stamp type is PCAP_TSTAMP_HOST.
         */
-       if (p->tstamp_type_count == 0)
-               return (PCAP_ERROR_CANTSET_TSTAMP_TYPE);
-
-       /*
-        * Check whether we claim to support this type of time stamp.
-        */
-       for (i = 0; i < p->tstamp_type_count; i++) {
-               if (p->tstamp_type_list[i] == tstamp_type) {
-                       /*
-                        * Yes.
-                        */
+       if (p->tstamp_type_count == 0) {
+               if (tstamp_type == PCAP_TSTAMP_HOST) {
                        p->opt.tstamp_type = tstamp_type;
                        return (0);
                }
+       } else {
+               /*
+                * Check whether we claim to support this type of time stamp.
+                */
+               for (i = 0; i < p->tstamp_type_count; i++) {
+                       if (p->tstamp_type_list[i] == tstamp_type) {
+                               /*
+                                * Yes.
+                                */
+                               p->opt.tstamp_type = tstamp_type;
+                               return (0);
+                       }
+               }
        }
 
        /*
-        * No.  We support setting the time stamp type, but not to this
-        * particular value.
+        * We don't support this type of time stamp.
         */
        return (PCAP_WARNING_TSTAMP_TYPE_NOTSUP);
 }
@@ -662,29 +665,45 @@ pcap_set_buffer_size(pcap_t *p, int buffer_size)
 }
 
 int
-pcap_set_tstamp_precision(pcap_t *p, int precision)
+pcap_set_tstamp_precision(pcap_t *p, int tstamp_precision)
 {
+       int i;
+
        if (pcap_check_activated(p))
                return PCAP_ERROR_ACTIVATED;
 
-       if (precision == PCAP_TSTAMP_PRECISION_NANO) {
-#ifdef HAVE_LINUX_TSTAMP_NANO
-               /* We should be able to get timestamp with nanosecond precision */
-               p->opt.tstamp_precision = PCAP_TSTAMP_PRECISION_NANO;
-#else
-               /* TODO: We don't know anything about other platforms yet */
-               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "nanosecond timestamps are not supported");
-               return PCAP_WARNING_TSTAMP_PRECISION_NOTSUP;
-#endif
-       } else if (precision == PCAP_TSTAMP_PRECISION_MICRO) {
-               p->opt.tstamp_precision = PCAP_TSTAMP_PRECISION_MICRO;
+       /*
+        * If p->tstamp_precision_count is 0, we only support setting
+        * the time stamp precision to microsecond precision; every
+        * pcap module *MUST* support microsecond precision, even if
+        * it does so by converting the native precision to
+        * microseconds.
+        */
+       if (p->tstamp_precision_count == 0) {
+               if (tstamp_precision == PCAP_TSTAMP_PRECISION_MICRO) {
+                       p->opt.tstamp_precision = tstamp_precision;
+                       return (0);
+               }
        } else {
-               /* unknown precision requested */
-               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "nanosecond timestamps are not supported");
-               return PCAP_WARNING_TSTAMP_PRECISION_NOTSUP;
+               /*
+                * Check whether we claim to support this precision of
+                * time stamp.
+                */
+               for (i = 0; i < p->tstamp_precision_count; i++) {
+                       if (p->tstamp_precision_list[i] == tstamp_precision) {
+                               /*
+                                * Yes.
+                                */
+                               p->opt.tstamp_precision = tstamp_precision;
+                               return (0);
+                       }
+               }
        }
 
-       return 0;
+       /*
+        * We don't support this time stamp precision.
+        */
+       return (PCAP_ERROR_TSTAMP_PRECISION_NOTSUP);
 }
 
 int
@@ -1507,6 +1526,9 @@ pcap_statustostr(int errnum)
 
        case PCAP_ERROR_PROMISC_PERM_DENIED:
                return ("You don't have permission to capture in promiscuous mode on that device");
+
+       case PCAP_ERROR_TSTAMP_PRECISION_NOTSUP:
+               return ("That device doesn't support that time stamp precision");
        }
        (void)snprintf(ebuf, sizeof ebuf, "Unknown error: %d", errnum);
        return(ebuf);
@@ -1725,6 +1747,11 @@ pcap_cleanup_live_common(pcap_t *p)
                p->tstamp_type_list = NULL;
                p->tstamp_type_count = 0;
        }
+       if (p->tstamp_precision_list != NULL) {
+               free(p->tstamp_precision_list);
+               p->tstamp_precision_list = NULL;
+               p->tstamp_precision_count = 0;
+       }
        pcap_freecode(&p->fcode);
 #if !defined(WIN32) && !defined(MSDOS)
        if (p->fd >= 0) {
index e30c5ee70c4a360e5d70e697f5b35c726066632d..4bc6a45bab7a9412d792e64912e8ed640998fedb 100644 (file)
@@ -254,6 +254,7 @@ typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *,
 #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_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 */
 
 /*
  * Warning codes for the pcap API.
@@ -263,7 +264,6 @@ 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 */
-#define  PCAP_WARNING_TSTAMP_PRECISION_NOTSUP  4  /* the requested time stamp precision is not supported */
 
 /*
  * Value to pass to pcap_compile() as the netmask if you don't know what