#
# Try to enable as many C99 features as we can.
# At minimum, we want C++/C99-style // comments.
-# (Sadly, this won't work with CMake prior to 3.1.)
#
-set(CMAKE_C_STANDARD 99)
+# Newer versions of compilers might default to supporting C99, but older
+# versions may require a special flag.
+#
+# Prior to CMake 3.1, setting CMAKE_C_STANDARD will not have any effect,
+# so, unless and until we require CMake 3.1 or later, we have to do it
+# ourselves on pre-3.1 CMake, so we just do it ourselves on all versions
+# of CMake.
+#
+# Note: with CMake 3.1 through 3.5, the only compilers for which CMake
+# handles CMAKE_C_STANDARD are GCC and Clang. 3.6 adds support only
+# for Intel C; 3.9 adds support for PGI C, Sun C, and IBM XL C, and
+# 3.10 adds support for Cray C and IAR C, but no version of CMake has
+# support for HP C. Therefore, even if we use CMAKE_C_STANDARD with
+# compilers for which CMake supports it, we may still have to do it
+# ourselves on other compilers.
+#
+# See the CMake documentation for the CMAKE_<LANG>_COMPILER_ID variables
+# for a list of compiler IDs.
+#
+# We don't worry about MSVC; it doesn't have such a flag - either it
+# doesn't support the C99 features we need at all, or it supports them
+# regardless of the compiler flag.
+#
+# XXX - this just tests whether the option works and adds it if it does.
+# We don't test whether it's necessary in order to get the C99 features
+# that we use; if we ever have a user who tries to compile with a compiler
+# that can't be made to support those features, we can add a test to make
+# sure we actually *have* C99 support.
+#
+include(CheckCCompilerFlag)
+macro(check_and_add_compiler_option _option)
+ message(STATUS "Checking C compiler flag ${_option}")
+ string(REPLACE "=" "-" _temp_option_variable ${_option})
+ string(REGEX REPLACE "^-" "" _option_variable ${_temp_option_variable})
+ check_c_compiler_flag("${_option}" ${_option_variable})
+ if(${${_option_variable}})
+ set(C_ADDITIONAL_FLAGS "${C_ADDITIONAL_FLAGS} ${_option}")
+ endif()
+endmacro()
+
+set(C_ADDITIONAL_FLAGS "")
+if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR
+ CMAKE_C_COMPILER_ID MATCHES "Clang")
+ check_and_add_compiler_option("-std=gnu99")
+elseif(CMAKE_C_COMPILER_ID MATCHES "XL")
+ #
+ # We want support for extensions picked up for GNU C compatibility,
+ # so we use -qlanglvl=extc99.
+ #
+ check_and_add_compiler_option("-qlanglvl=extc99")
+elseif(CMAKE_C_COMPILER_ID MATCHES "HP")
+ check_and_add_compiler_option("-AC99")
+elseif(CMAKE_C_COMPILER_ID MATCHES "Sun")
+ check_and_add_compiler_option("-xc99")
+elseif(CMAKE_C_COMPILER_ID MATCHES "Intel")
+ check_and_add_compiler_option("-c99")
+endif()
set(LIBRARY_NAME netdissect)
#
# Optional libraries.
#
+
#
# libsmi.
#
endif(HAVE_LIBCAP_NG)
endif(WITH_CAP_NG)
+###################################################################
+# Warning options
+###################################################################
+
+#
+# Check and add warning options if we have a .devel file.
+#
+if(EXISTS ${CMAKE_SOURCE_DIR}/.devel OR EXISTS ${CMAKE_BINARY_DIR}/.devel)
+ #
+ # Warning options.
+ #
+ if(MSVC AND NOT ${CMAKE_C_COMPILER} MATCHES "clang*")
+ #
+ # MSVC, with Microsoft's front end and code generator.
+ # "MSVC" is also set for Microsoft's compiler with a Clang
+ # front end and their code generator ("Clang/C2"), so we
+ # check for clang.exe and treat that differently.
+ #
+ check_and_add_compiler_option(-Wall)
+ #
+ # Disable some pointless warnings that /Wall turns on.
+ #
+ # Unfortunately, MSVC does not appear to have an equivalent
+ # to "__attribute__((unused))" to mark a particular function
+ # parameter as being known to be unused, so that the compiler
+ # won't warn about it (for example, the function might have
+ # that parameter because a pointer to it is being used, and
+ # the signature of that function includes that parameter).
+ # C++ lets you give a parameter a type but no name, but C
+ # doesn't have that.
+ #
+ check_and_add_compiler_option(-wd4100)
+ #
+ # In theory, we care whether somebody uses f() rather than
+ # f(void) to declare a function with no arguments, but, in
+ # practice, there are places in the Windows header files
+ # that appear to do that, so we squelch that warning.
+ #
+ check_and_add_compiler_option(-wd4255)
+ #
+ # Windows FD_SET() generates this, so we suppress it.
+ #
+ check_and_add_compiler_option(-wd4548)
+ #
+ # Perhaps testing something #defined to be 0 with #ifdef is an
+ # error, and it should be tested with #if, but perhaps it's
+ # not, and Microsoft does that in its headers, so we squelch
+ # that warning.
+ #
+ check_and_add_compiler_option(-wd4574)
+ #
+ # The Windows headers also test not-defined values in #if, so
+ # we don't want warnings about that, either.
+ #
+ check_and_add_compiler_option(-wd4668)
+ #
+ # We do *not* care whether some function is, or isn't, going to be
+ # expanded inline.
+ #
+ check_and_add_compiler_option(-wd4710)
+ check_and_add_compiler_option(-wd4711)
+ #
+ # We do *not* care whether we're adding padding bytes after
+ # structure members.
+ #
+ check_and_add_compiler_option(-wd4820)
+ else()
+ #
+ # Other compilers, including MSVC with a Clang front end and
+ # Microsoft's code generator. We currently treat them as if
+ # they might support GCC-style -W options.
+ #
+ check_and_add_compiler_option(-Wall)
+ check_and_add_compiler_option(-Wmissing-prototypes)
+ check_and_add_compiler_option(-Wstrict-prototypes)
+ check_and_add_compiler_option(-Wwrite-strings)
+ check_and_add_compiler_option(-Wpointer-arith)
+ check_and_add_compiler_option(-Wcast-qual)
+ check_and_add_compiler_option(-Wshadow)
+ check_and_add_compiler_option(-Wdeclaration-after-statement)
+ check_and_add_compiler_option(-Wpedantic)
+ check_and_add_compiler_option(-Wold-style-definition)
+ check_and_add_compiler_option(-Wused-but-marked-unused)
+ check_and_add_compiler_option(-W)
+ check_and_add_compiler_option(-Wassign-enum)
+ endif()
+endif()
+
######################################
# Input files
######################################
add_library(netdissect STATIC
${NETDISSECT_SOURCE_LIST_C}
)
+if(NOT C_ADDITIONAL_FLAGS STREQUAL "")
+ set_target_properties(netdissect PROPERTIES COMPILE_FLAGS ${C_ADDITIONAL_FLAGS})
+endif()
set(TCPDUMP_SOURCE_LIST_C tcpdump.c)
######################################
add_executable(tcpdump ${TCPDUMP_SOURCE_LIST_C})
+if(NOT C_ADDITIONAL_FLAGS STREQUAL "")
+ set_target_properties(tcpdump PROPERTIES COMPILE_FLAGS ${C_ADDITIONAL_FLAGS})
+endif()
target_link_libraries(tcpdump netdissect ${TCPDUMP_LINK_LIBRARIES})
######################################
static long
parse_interface_number(const char *device)
{
+ const char *p;
long devnum;
char *end;
+ /*
+ * Search for a colon, terminating any scheme at the beginning
+ * of the device.
+ */
+ p = strchr(device, ':');
+ if (p != NULL) {
+ /*
+ * We found it. Is it followed by "//"?
+ */
+ p++; /* skip the : */
+ if (strncmp(p, "//", 2) == 0) {
+ /*
+ * Yes. Search for the next /, at the end of the
+ * authority part of the URL.
+ */
+ p += 2; /* skip the // */
+ p = strchr(p, '/');
+ if (p != NULL) {
+ /*
+ * OK, past the / is the path.
+ */
+ device = p + 1;
+ }
+ }
+ }
devnum = strtol(device, &end, 10);
if (device != end && *end == '\0') {
/*
}
static char *
-find_interface_by_number(long devnum)
+find_interface_by_number(const char *url, long devnum)
{
pcap_if_t *dev, *devlist;
long i;
char ebuf[PCAP_ERRBUF_SIZE];
char *device;
+#ifdef HAVE_PCAP_FINDALLDEVS_EX
+ const char *endp;
+ char *host_url;
+#endif
+ int status;
- if (pcap_findalldevs(&devlist, ebuf) < 0)
+#ifdef HAVE_PCAP_FINDALLDEVS_EX
+ /*
+ * Search for a colon, terminating any scheme at the beginning
+ * of the URL.
+ */
+ endp = strchr(url, ':');
+ if (endp != NULL) {
+ /*
+ * We found it. Is it followed by "//"?
+ */
+ endp++; /* skip the : */
+ if (strncmp(endp, "//", 2) == 0) {
+ /*
+ * Yes. Search for the next /, at the end of the
+ * authority part of the URL.
+ */
+ endp += 2; /* skip the // */
+ endp = strchr(endp, '/');
+ } else
+ endp = NULL;
+ }
+ if (endp != NULL) {
+ /*
+ * OK, everything from device to endp is a URL to hand
+ * to pcap_findalldevs_ex().
+ */
+ endp++; /* Include the trailing / in the URL; pcap_findalldevs_ex() requires it */
+ host_url = malloc(endp - url + 1);
+ memcpy(host_url, url, endp - url);
+ host_url[endp - url] = '\0';
+ status = pcap_findalldevs_ex(host_url, NULL, &devlist, ebuf);
+ free(host_url);
+ } else
+#endif
+ status = pcap_findalldevs(&devlist, ebuf);
+ if (status < 0)
error("%s", ebuf);
/*
* Look for the devnum-th entry in the list of devices (1-based).
* Yes. Open it with pcap_open().
*/
*ebuf = '\0';
-fprintf(stderr, "Opening %s\n", device);
pc = pcap_open(device, ndo->ndo_snaplen,
pflag ? 0 : PCAP_OPENFLAG_PROMISCUOUS, 1000, NULL,
ebuf);
if (pc == NULL) {
/*
- * If this failed with "No such device", that means
+ * If this failed with "No such device" or "The system
+ * cannot find the device specified", that means
* the interface doesn't exist; return NULL, so that
* the caller can see whether the device name is
* actually an interface index.
*/
- if (strstr(ebuf, "No such device") != NULL)
+ if (strstr(ebuf, "No such device") != NULL ||
+ strstr(ebuf, "The system cannot find the device specified") != NULL)
return (NULL);
error("%s", ebuf);
}
* find_interface_by_number() exits if it
* couldn't be found.
*/
- device = find_interface_by_number(devnum);
+ device = find_interface_by_number(device, devnum);
pd = open_interface(device, ndo, ebuf);
if (pd == NULL)
error("%s", ebuf);
(void)fprintf(stderr,
"\t\t[ -z postrotate-command ] [ -Z user ] [ expression ]\n");
}
-/*
- * Local Variables:
- * c-style: whitesmith
- * c-basic-offset: 8
- * End:
- */