diff options
-rw-r--r-- | .github/workflows/build.yml | 93 | ||||
-rw-r--r-- | CMakeLists.txt | 22 | ||||
-rw-r--r-- | dependencies/nDPIsrvd.h | 1 | ||||
-rw-r--r-- | nDPId-test.c | 16 | ||||
-rw-r--r-- | nDPId.c | 92 | ||||
-rw-r--r-- | nDPIsrvd.c | 63 | ||||
-rwxr-xr-x | scripts/daemon.sh | 24 | ||||
-rwxr-xr-x | scripts/get-and-build-libndpi.sh | 6 | ||||
-rw-r--r-- | utils.c | 48 | ||||
-rw-r--r-- | utils.h | 2 |
10 files changed, 268 insertions, 99 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 83b98ac50..291d86fd2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -18,13 +18,17 @@ jobs: runs-on: ${{ matrix.os }} env: CMAKE_C_COMPILER: ${{ matrix.compiler }} - CMAKE_C_FLAGS: -Werror + CMAKE_C_FLAGS: -Werror ${{ matrix.cflags }} + CMAKE_C_EXE_LINKER_FLAGS: ${{ matrix.ldflags }} + CMAKE_MODULE_LINKER_FLAGS: ${{ matrix.ldflags }} strategy: fail-fast: true matrix: include: - compiler: "gcc" os: "ubuntu-latest" + ndpi_build: "-DBUILD_NDPI=ON" + ndpid_examples: "-DBUILD_EXAMPLES=ON" ndpid_gcrypt: "-DNDPI_WITH_GCRYPT=OFF" ndpid_zlib: "-DENABLE_ZLIB=ON" sanitizer: "-DENABLE_SANITIZER=OFF -DENABLE_SANITIZER_THREAD=OFF" @@ -35,6 +39,8 @@ jobs: ndpi_min_version: "4.8" - compiler: "gcc" os: "ubuntu-latest" + ndpi_build: "-DBUILD_NDPI=ON" + ndpid_examples: "-DBUILD_EXAMPLES=ON" ndpid_gcrypt: "-DNDPI_WITH_GCRYPT=ON" ndpid_zlib: "-DENABLE_ZLIB=ON" sanitizer: "-DENABLE_SANITIZER=OFF -DENABLE_SANITIZER_THREAD=OFF" @@ -45,6 +51,8 @@ jobs: ndpi_min_version: "4.8" - compiler: "clang" os: "ubuntu-latest" + ndpi_build: "-DBUILD_NDPI=ON" + ndpid_examples: "-DBUILD_EXAMPLES=ON" ndpid_gcrypt: "-DNDPI_WITH_GCRYPT=OFF" ndpid_zlib: "-DENABLE_ZLIB=OFF" sanitizer: "-DENABLE_SANITIZER=OFF -DENABLE_SANITIZER_THREAD=OFF" @@ -55,6 +63,8 @@ jobs: ndpi_min_version: "4.8" - compiler: "gcc" os: "ubuntu-latest" + ndpi_build: "-DBUILD_NDPI=ON" + ndpid_examples: "-DBUILD_EXAMPLES=ON" ndpid_gcrypt: "-DNDPI_WITH_GCRYPT=OFF" ndpid_zlib: "-DENABLE_ZLIB=ON" sanitizer: "-DENABLE_SANITIZER=ON" @@ -64,24 +74,30 @@ jobs: ndpi_min_version: "4.8" - compiler: "clang" os: "ubuntu-latest" + ndpi_build: "-DBUILD_NDPI=ON" + ndpid_examples: "-DBUILD_EXAMPLES=ON" ndpid_gcrypt: "-DNDPI_WITH_GCRYPT=OFF" ndpid_zlib: "-DENABLE_ZLIB=ON" sanitizer: "-DENABLE_SANITIZER=ON" - coverage: "-DENABLE_COVERAGE=ON" + coverage: "-DENABLE_COVERAGE=OFF" poll: "-DFORCE_POLL=OFF" upload: false ndpi_min_version: "4.8" - compiler: "clang-12" os: "ubuntu-latest" + ndpi_build: "-DBUILD_NDPI=ON" + ndpid_examples: "-DBUILD_EXAMPLES=ON" ndpid_gcrypt: "-DNDPI_WITH_GCRYPT=OFF" ndpid_zlib: "-DENABLE_ZLIB=ON" sanitizer: "-DENABLE_SANITIZER_THREAD=ON" - coverage: "-DENABLE_COVERAGE=ON" - poll: "-DFORCE_POLL=OFF" + coverage: "-DENABLE_COVERAGE=OFF" + poll: upload: false ndpi_min_version: "4.8" - compiler: "gcc-10" os: "ubuntu-latest" + ndpi_build: "-DBUILD_NDPI=ON" + ndpid_examples: "-DBUILD_EXAMPLES=ON" ndpid_gcrypt: "-DNDPI_WITH_GCRYPT=OFF" ndpid_zlib: "-DENABLE_ZLIB=OFF" sanitizer: "-DENABLE_SANITIZER=ON" @@ -91,6 +107,8 @@ jobs: ndpi_min_version: "4.8" - compiler: "gcc-7" os: "ubuntu-20.04" + ndpi_build: "-DBUILD_NDPI=ON" + ndpid_examples: "-DBUILD_EXAMPLES=ON" ndpid_gcrypt: "-DNDPI_WITH_GCRYPT=OFF" ndpid_zlib: "-DENABLE_ZLIB=ON" sanitizer: "-DENABLE_SANITIZER=ON" @@ -98,6 +116,18 @@ jobs: poll: "-DFORCE_POLL=OFF" upload: false ndpi_min_version: "4.8" + - compiler: "cc" + os: "macOS-latest" + ndpi_build: "-DBUILD_NDPI=OFF" + ndpid_examples: "-DBUILD_EXAMPLES=OFF" + ndpid_gcrypt: "-DNDPI_WITH_GCRYPT=OFF" + ndpid_zlib: "-DENABLE_ZLIB=ON" + examples: "-DBUILD_EXAMPLES=OFF" + sanitizer: "-DENABLE_SANITIZER=OFF" + coverage: "-DENABLE_COVERAGE=OFF" + poll: + upload: false + ndpi_min_version: "4.8" steps: - name: Print Matrix @@ -105,9 +135,13 @@ jobs: echo '----------------------------------------' echo '| OS.......: ${{ matrix.os }}' echo '| CC.......: ${{ matrix.compiler }}' + echo "| CFLAGS...: $CMAKE_C_FLAGS" + echo "| LDFLAGS..: $CMAKE_C_EXE_LINKER_FLAGS" echo '|---------------------------------------' + echo '| nDPI min.: ${{ matrix.ndpi_min_version }}' echo '| GCRYPT...: ${{ matrix.ndpid_gcrypt }}' echo '| ZLIB.....: ${{ matrix.ndpid_zlib }}' + echo '| ForcePoll: ${{ matrix.poll }}' echo '|---------------------------------------' echo '| SANITIZER: ${{ matrix.sanitizer }}' echo '| COVERAGE.: ${{ matrix.coverage }}' @@ -118,6 +152,19 @@ jobs: with: submodules: false fetch-depth: 1 + - name: Install MacOS Prerequisites + if: startsWith(matrix.os, 'macOS') + run: | + brew install coreutils flock automake make unzip + wget 'https://www.tcpdump.org/release/libpcap-1.10.4.tar.gz' + tar -xzvf libpcap-1.10.4.tar.gz + cd libpcap-1.10.4 + ./configure && make install + cd .. + wget 'https://github.com/ntop/nDPI/archive/refs/heads/dev.zip' -O libndpi-dev.zip + unzip libndpi-dev.zip + cd nDPI-dev + ./autogen.sh --prefix=/usr/local --with-only-libndpi && make install - name: Install Ubuntu Prerequisites if: startsWith(matrix.os, 'ubuntu') run: | @@ -139,13 +186,15 @@ jobs: test ${C_VAL} = ${PY_VAL} - name: Configure nDPId run: | - mkdir build && cd build - cmake .. -DENABLE_SYSTEMD=ON -DBUILD_EXAMPLES=ON -DBUILD_NDPI=ON ${{ matrix.poll }} ${{ matrix.coverage }} ${{ matrix.sanitizer }} ${{ matrix.ndpid_zlib }} ${{ matrix.ndpid_gcrypt }} + cmake -S . -B build -DCMAKE_C_COMPILER="$CMAKE_C_COMPILER" -DCMAKE_C_FLAGS="$CMAKE_C_FLAGS" -DCMAKE_MODULE_LINKER_FLAGS="$CMAKE_MODULE_LINKER_FLAGS" -DCMAKE_C_EXE_LINKER_FLAGS="$CMAKE_C_EXE_LINKER_FLAGS" \ + -DENABLE_SYSTEMD=ON \ + ${{ matrix.poll }} ${{ matrix.coverage }} ${{ matrix.sanitizer }} ${{ matrix.ndpi_build }} \ + ${{ matrix.ndpid_examples }} ${{ matrix.ndpid_zlib }} ${{ matrix.ndpid_gcrypt }} - name: Build nDPId run: | - make -C build all VERBOSE=1 + cmake --build build --verbose - name: Build single nDPId executable (invoke CC directly) - if: startsWith(matrix.coverage, '-DENABLE_COVERAGE=OFF') && startsWith(matrix.sanitizer, '-DENABLE_SANITIZER=ON') && startsWith(matrix.ndpid_gcrypt, '-DNDPI_WITH_GCRYPT=OFF') && startsWith(matrix.ndpid_zlib, '-DENABLE_ZLIB=ON') + if: (endsWith(matrix.compiler, 'gcc') || endsWith(matrix.compiler, 'clang')) && startsWith(matrix.coverage, '-DENABLE_COVERAGE=OFF') && startsWith(matrix.sanitizer, '-DENABLE_SANITIZER=ON') && startsWith(matrix.ndpid_gcrypt, '-DNDPI_WITH_GCRYPT=OFF') && startsWith(matrix.ndpid_zlib, '-DENABLE_ZLIB=ON') run: | cc -fsanitize=address -fsanitize=undefined -fno-sanitize=alignment -fsanitize=enum -fsanitize=leak nDPId.c nio.c utils.c -I./build/libnDPI/include/ndpi -I. -I./dependencies -I./dependencies/jsmn -I./dependencies/uthash/include -o /tmp/a.out -lpcap ./build/libnDPI/lib/libndpi.a -pthread -lm -lz - name: Test EXEC @@ -154,10 +203,11 @@ jobs: ./build/nDPId -h || test $? -eq 1 ./build/nDPIsrvd -h || test $? -eq 1 - name: Test DIFF - if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.ndpid_gcrypt, '-DNDPI_WITH_GCRYPT=OFF') + if: startsWith(matrix.os, 'macOS') == false && startsWith(matrix.ndpid_gcrypt, '-DNDPI_WITH_GCRYPT=OFF') run: | ./test/run_tests.sh ./libnDPI ./build/nDPId-test - name: Daemon + if: endsWith(matrix.compiler, 'gcc') || endsWith(matrix.compiler, 'clang') run: | make -C ./build daemon VERBOSE=1 make -C ./build daemon VERBOSE=1 @@ -166,20 +216,21 @@ jobs: run: | make -C ./build coverage - name: Dist - if: matrix.upload == false + if: startsWith(matrix.os, 'macOS') == false && matrix.upload == false run: | make -C ./build dist - name: CPack DEB + if: startsWith(matrix.os, 'macOS') == false run: | cd ./build && cpack -G DEB && sudo dpkg -i nDPId-*.deb && cd .. - name: Upload DEB - if: matrix.upload + if: startsWith(matrix.os, 'macOS') == false && matrix.upload uses: actions/upload-artifact@v3 with: name: nDPId-debian-packages_${{ matrix.compiler }}${{ matrix.upload_suffix }} path: build/*.deb - - name: systemd test - if: startsWith(matrix.os, 'ubuntu-latest') && startsWith(matrix.compiler, 'gcc') + - name: Test systemd + if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.compiler, 'gcc') run: | ip -c address sudo systemctl daemon-reload @@ -190,14 +241,22 @@ jobs: sudo systemctl show ndpisrvd.service ndpid@lo.service -p SubState,ActiveState || true journalctl --no-tail --no-pager -u ndpisrvd.service -u ndpid@lo.service - name: Build against libnDPI-${{ matrix.ndpi_min_version }} - if: matrix.upload == false + if: matrix.upload == false && startsWith(matrix.os, 'ubuntu') run: | mkdir build-local-ndpi && cd build-local-ndpi WGET_RET=0 wget 'https://github.com/ntop/nDPI/archive/refs/tags/${{ matrix.ndpi_min_version }}.tar.gz' || { WGET_RET=$?; true; } echo "wget returned: ${WGET_RET}" test $WGET_RET -ne 8 || echo "::warning file=nDPId.c::New libnDPI release required to build against release tarball." - test $WGET_RET -ne 0 || { tar -xzvf ${{ matrix.ndpi_min_version }}.tar.gz && cd nDPI-${{ matrix.ndpi_min_version }} && ./autogen.sh --prefix=/usr --with-only-libndpi CC=${{ matrix.compiler }} CXX=false CFLAGS='-Werror' && sudo make install && cd .. ; } - test $WGET_RET -ne 0 || { echo "running cmake .."; cmake .. -DBUILD_EXAMPLES=ON -DBUILD_NDPI=OFF -DENABLE_SANITIZER=OFF ${{ matrix.poll }} ${{ matrix.coverage }} ${{ matrix.ndpi_min_version }} ; } - test $WGET_RET -ne 0 || { echo "running make .."; make all VERBOSE=1 ; } + test $WGET_RET -ne 0 || { tar -xzvf ${{ matrix.ndpi_min_version }}.tar.gz && \ + cd nDPI-${{ matrix.ndpi_min_version }} && \ + ./autogen.sh --prefix=/usr --with-only-libndpi CC="${{ matrix.compiler }}" CXX=false \ + CFLAGS="$CMAKE_C_FLAGS" && make && sudo make install; cd ..; } + test $WGET_RET -ne 0 || { echo "::info file=CMakeLists.txt::Running CMake.."; \ + cmake -S .. -DCMAKE_C_COMPILER="$CMAKE_C_COMPILER" -DCMAKE_C_FLAGS="$CMAKE_C_FLAGS" \ + -DCMAKE_C_EXE_LINKER_FLAGS="$CMAKE_C_EXE_LINKER_FLAGS" \ + -DBUILD_NDPI=OFF -DENABLE_SANITIZER=OFF \ + ${{ matrix.poll }} ${{ matrix.coverage }} \ + ${{ matrix.ndpid_examples }}; } + test $WGET_RET -ne 0 || { echo "::info file=CMakeLists.txt:Running Make.."; cmake --build . --verbose; } test $WGET_RET -eq 0 -o $WGET_RET -eq 8 diff --git a/CMakeLists.txt b/CMakeLists.txt index 73d659a5d..21020d5e7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,6 +31,7 @@ set(CPACK_PACKAGE_VERSION_PATCH 0) include(CPack) include(CheckFunctionExists) +include(CheckLibraryExists) include(CheckEpoll) check_epoll(HAS_EPOLL) @@ -49,14 +50,19 @@ if(NOT MATH_FUNCTION_EXISTS AND NOT NEED_LINKING_AGAINST_LIBM) CHECK_FUNCTION_EXISTS(log2f MATH_FUNCTION_EXISTS) if(NOT MATH_FUNCTION_EXISTS) unset(MATH_FUNCTION_EXISTS CACHE) - list(APPEND CMAKE_REQUIRED_LIBRARIES m) - CHECK_FUNCTION_EXISTS(log2f MATH_FUNCTION_EXISTS) - if(MATH_FUNCTION_EXISTS) - set(NEED_LINKING_AGAINST_LIBM TRUE CACHE BOOL "" FORCE) - else() - message(FATAL_ERROR "Failed making the log2f() function available") - endif() - endif() + list(APPEND CMAKE_REQUIRED_LIBRARIES m) + CHECK_FUNCTION_EXISTS(log2f MATH_FUNCTION_EXISTS) + if(MATH_FUNCTION_EXISTS) + set(NEED_LINKING_AGAINST_LIBM TRUE CACHE BOOL "" FORCE) + else() + check_library_exists(m sqrt "" NEED_LINKING_AGAINST_LIBM) + if(NOT NEED_LINKING_AGAINST_LIBM) + # Was not able to figure out if explicit linkage against libm is required. + # Forcing libm linkage. Good idea? + set(NEED_LINKING_AGAINST_LIBM TRUE CACHE BOOL "" FORCE) + endif() + endif() + endif() endif() if(NEED_LINKING_AGAINST_LIBM) diff --git a/dependencies/nDPIsrvd.h b/dependencies/nDPIsrvd.h index 77d91bd9d..11f651435 100644 --- a/dependencies/nDPIsrvd.h +++ b/dependencies/nDPIsrvd.h @@ -5,6 +5,7 @@ #include <ctype.h> #include <errno.h> #include <fcntl.h> +#include <netinet/in.h> #include <stdarg.h> #include <stdint.h> #include <stdio.h> diff --git a/nDPId-test.c b/nDPId-test.c index 48c0e2b70..0f3bd8539 100644 --- a/nDPId-test.c +++ b/nDPId-test.c @@ -923,7 +923,9 @@ static enum nDPIsrvd_callback_return distributor_json_printer(struct nDPIsrvd_so static void * distributor_client_mainloop_thread(void * const arg) { struct nio io; +#if !defined(__FreeBSD__) && !defined(__APPLE__) int signalfd = -1; +#endif struct distributor_return_value * const drv = (struct distributor_return_value *)arg; struct thread_return_value * const trv = &drv->thread_return_value; struct nDPIsrvd_socket * mock_sock = nDPIsrvd_socket_init(sizeof(struct distributor_global_user_data), @@ -960,12 +962,14 @@ static void * distributor_client_mainloop_thread(void * const arg) THREAD_ERROR_GOTO(trv); } +#if !defined(__FreeBSD__) && !defined(__APPLE__) signalfd = setup_signalfd(&io); if (signalfd < 0) { logger(1, "Distributor signal fd setup failed: %s", strerror(errno)); THREAD_ERROR_GOTO(trv); } +#endif if (thread_block_signals() != 0) { @@ -1159,6 +1163,7 @@ static void * distributor_client_mainloop_thread(void * const arg) * I am just here to trigger some IP code paths. */ } +#if !defined(__FreeBSD__) && !defined(__APPLE__) else if (fd == signalfd) { struct signalfd_siginfo fdsi; @@ -1178,6 +1183,7 @@ static void * distributor_client_mainloop_thread(void * const arg) THREAD_ERROR_GOTO(trv); } } +#endif else { logger(1, @@ -1251,7 +1257,9 @@ static void * distributor_client_mainloop_thread(void * const arg) } error: +#if !defined(__FreeBSD__) && !defined(__APPLE__) del_event(&io, signalfd); +#endif del_event(&io, mock_testfds[PIPE_TEST_READ]); del_event(&io, mock_bufffds[PIPE_BUFFER_READ]); del_event(&io, mock_nullfds[PIPE_NULL_READ]); @@ -1260,7 +1268,9 @@ error: close(mock_bufffds[PIPE_BUFFER_READ]); close(mock_nullfds[PIPE_NULL_READ]); close(mock_arpafds[PIPE_ARPA_READ]); +#if !defined(__FreeBSD__) && !defined(__APPLE__) close(signalfd); +#endif nio_free(&io); nDPIsrvd_socket_free(&mock_sock); @@ -1351,6 +1361,7 @@ static void usage(char const * const arg0) static int thread_wait_for_termination(pthread_t thread, time_t wait_time_secs, struct thread_return_value * const trv) { +#if !defined(__FreeBSD__) && !defined(__APPLE__) struct timespec ts; if (clock_gettime(CLOCK_REALTIME, &ts) == -1) @@ -1370,6 +1381,11 @@ static int thread_wait_for_termination(pthread_t thread, time_t wait_time_secs, } return 1; +#else + (void)wait_time_secs; + + return pthread_join(thread, (void **)&trv) != 0; +#endif } static int base64_selftest() @@ -1,3 +1,6 @@ +#if defined(__FreeBSD__) || defined(__APPLE__) +#include <sys/types.h> +#endif #include <arpa/inet.h> #include <errno.h> #include <fcntl.h> @@ -17,7 +20,9 @@ #include <stdio.h> #include <stdlib.h> #include <sys/ioctl.h> +#if !defined(__FreeBSD__) && !defined(__APPLE__) #include <sys/signalfd.h> +#endif #include <sys/un.h> #include <unistd.h> #ifdef ENABLE_ZLIB @@ -429,7 +434,6 @@ static struct nDPId_reader_thread reader_threads[nDPId_MAX_READER_THREADS] = {}; static struct nDPIsrvd_address collector_address; static MT_VALUE(nDPId_main_thread_shutdown, int) = MT_INIT(0); static MT_VALUE(global_flow_id, uint64_t) = MT_INIT(1); -static int ip4_interface_avail = 0, ip6_interface_avail = 0; #ifdef ENABLE_MEMORY_PROFILING static MT_VALUE(ndpi_memory_alloc_count, uint64_t) = MT_INIT(0); @@ -929,10 +933,17 @@ static void get_ip6_from_sockaddr(struct sockaddr_in6 const * const saddr, union switch (saddr->sin6_family) { case AF_INET6: +#if defined(__FreeBSD__) || defined(__APPLE__) + dest->v6.ip_u32[0] = saddr->sin6_addr.__u6_addr.__u6_addr32[0]; + dest->v6.ip_u32[1] = saddr->sin6_addr.__u6_addr.__u6_addr32[1]; + dest->v6.ip_u32[2] = saddr->sin6_addr.__u6_addr.__u6_addr32[2]; + dest->v6.ip_u32[3] = saddr->sin6_addr.__u6_addr.__u6_addr32[3]; +#else dest->v6.ip_u32[0] = saddr->sin6_addr.s6_addr32[0]; dest->v6.ip_u32[1] = saddr->sin6_addr.s6_addr32[1]; dest->v6.ip_u32[2] = saddr->sin6_addr.s6_addr32[2]; dest->v6.ip_u32[3] = saddr->sin6_addr.s6_addr32[3]; +#endif break; default: return; @@ -996,7 +1007,11 @@ static int get_ip6_address_and_netmask(char const * const ifa_name, size_t ifnam memset(&sap.sin6_addr.s6_addr, 0xFF, plen / 8); if (plen < 128 && (plen % 32) != 0) { +#if defined(__FreeBSD__) || defined(__APPLE__) + sap.sin6_addr.__u6_addr.__u6_addr32[plen / 32] = 0xFFFFFFFF << (32 - (plen % 32)); +#else sap.sin6_addr.s6_addr32[plen / 32] = 0xFFFFFFFF << (32 - (plen % 32)); +#endif } inet_ntop(AF_INET6, &sap.sin6_addr, netmask6, sizeof(netmask6)); sap.sin6_family = AF_INET6; @@ -1024,50 +1039,14 @@ error: return retval; } -static int get_ip4_address_and_netmask(char const * const ifa_name, size_t ifnamelen) +static void get_ip4_address_and_netmask(struct ifaddrs const * const ifaddr) { - int retval = 0; - int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); - struct ifreq ifr; - - if (sock < 0) - { - retval = 1; - goto error; - } - if (ifnamelen >= sizeof(ifr.ifr_name)) - { - retval = 1; - goto error; - } - - memset(&ifr, 0, sizeof(ifr)); - memcpy(ifr.ifr_name, ifa_name, ifnamelen); - ifr.ifr_name[ifnamelen] = '\0'; - ifr.ifr_netmask.sa_family = AF_INET; - if (ioctl(sock, SIOCGIFNETMASK, &ifr) == -1) - { - retval = 1; - goto error; - } - get_ip4_from_sockaddr((struct sockaddr_in *)&ifr.ifr_netmask, &nDPId_options.pcap_dev_netmask4); - - memset(&ifr, 0, sizeof(ifr)); - memcpy(ifr.ifr_name, ifa_name, ifnamelen); - ifr.ifr_name[ifnamelen] = '\0'; - ifr.ifr_addr.sa_family = AF_INET; - if (ioctl(sock, SIOCGIFADDR, &ifr) == -1) - { - retval = 1; - goto error; - } - get_ip4_from_sockaddr((struct sockaddr_in *)&ifr.ifr_netmask, &nDPId_options.pcap_dev_ip4); - + get_ip4_from_sockaddr((struct sockaddr_in *)ifaddr->ifa_netmask, &nDPId_options.pcap_dev_netmask4); + get_ip4_from_sockaddr((struct sockaddr_in *)ifaddr->ifa_addr, &nDPId_options.pcap_dev_ip4); ip_netmask_to_subnet(&nDPId_options.pcap_dev_ip4, &nDPId_options.pcap_dev_netmask4, &nDPId_options.pcap_dev_subnet4, L3_IP); - { char addr[INET_ADDRSTRLEN]; char netm[INET_ADDRSTRLEN]; @@ -1082,15 +1061,12 @@ static int get_ip4_address_and_netmask(char const * const ifa_name, size_t ifnam inet_ntop(AF_INET, snetm, netm, sizeof(netm)), inet_ntop(AF_INET, ssubn, subn, sizeof(subn))); } - -error: - close(sock); - return retval; } static int get_ip_netmask_from_pcap_dev(char const * const pcap_dev) { int retval = 0, found_dev = 0; + int ip4_interface_avail = 0, ip6_interface_avail = 0; struct ifaddrs * ifaddrs = NULL; struct ifaddrs * ifa; @@ -1113,10 +1089,7 @@ static int get_ip_netmask_from_pcap_dev(char const * const pcap_dev) switch (ifa->ifa_addr->sa_family) { case AF_INET: - if (ip4_interface_avail == 0 && get_ip4_address_and_netmask(ifa->ifa_name, ifnamelen) != 0) - { - retval = 1; - } + get_ip4_address_and_netmask(ifa); ip4_interface_avail = 1; break; case AF_INET6: @@ -1586,6 +1559,8 @@ static int setup_reader_threads(void) "Could not get netmask for pcap device %s: %s", get_cmdarg(&nDPId_options.pcap_file_or_interface), strerror(errno)); + } else { + logger_early(1, "Unexpected error while retrieving netmask for pcap device %s", get_cmdarg(&nDPId_options.pcap_file_or_interface)); } return 1; } @@ -2245,8 +2220,8 @@ static int connect_to_collector(struct nDPId_reader_thread * const reader_thread } int sock_type = (collector_address.raw.sa_family == AF_UNIX ? SOCK_STREAM : SOCK_DGRAM); - reader_thread->collector_sockfd = socket(collector_address.raw.sa_family, sock_type | SOCK_CLOEXEC, 0); - if (reader_thread->collector_sockfd < 0) + reader_thread->collector_sockfd = socket(collector_address.raw.sa_family, sock_type, 0); + if (reader_thread->collector_sockfd < 0 || set_fd_cloexec(reader_thread->collector_sockfd) < 0) { reader_thread->collector_sock_last_errno = errno; return 1; @@ -3458,7 +3433,7 @@ static int process_datalink_layer(struct nDPId_reader_thread * const reader_thre break; case ETHERTYPE_PAE: /* 802.1X Authentication */ return 1; - case ETH_P_ARP: /* ARP */ + case ETHERTYPE_ARP: /* ARP */ return 1; default: if (is_error_event_threshold(reader_thread->workflow) == 0) @@ -4274,6 +4249,7 @@ static void get_current_time(struct timeval * const tval) gettimeofday(tval, NULL); } +#if !defined(__FreeBSD__) && !defined(__APPLE__) static void ndpi_log_flow_walker(void const * const A, ndpi_VISIT which, int depth, void * const user_data) { struct nDPId_reader_thread const * const reader_thread = (struct nDPId_reader_thread *)user_data; @@ -4358,6 +4334,7 @@ static void log_all_flows(struct nDPId_reader_thread const * const reader_thread ndpi_twalk(workflow->ndpi_flows_active[scan_index], ndpi_log_flow_walker, (void *)reader_thread); } } +#endif static void run_pcap_loop(struct nDPId_reader_thread * const reader_thread) { @@ -4380,6 +4357,7 @@ static void run_pcap_loop(struct nDPId_reader_thread * const reader_thread) } else { +#if !defined(__FreeBSD__) && !defined(__APPLE__) sigset_t thread_signal_set, old_signal_set; sigfillset(&thread_signal_set); if (pthread_sigmask(SIG_BLOCK, &thread_signal_set, &old_signal_set) != 0) @@ -4392,13 +4370,14 @@ static void run_pcap_loop(struct nDPId_reader_thread * const reader_thread) sigaddset(&thread_signal_set, SIGINT); sigaddset(&thread_signal_set, SIGTERM); sigaddset(&thread_signal_set, SIGUSR1); - int signal_fd = signalfd(-1, &thread_signal_set, SFD_NONBLOCK | SFD_CLOEXEC); - if (signal_fd < 0) + int signal_fd = signalfd(-1, &thread_signal_set, SFD_NONBLOCK); + if (signal_fd < 0 || set_fd_cloexec(signal_fd) < 0) { logger(1, "signalfd: %s", strerror(errno)); MT_GET_AND_ADD(reader_thread->workflow->error_or_eof, 1); return; } +#endif int pcap_fd = pcap_get_selectable_fd(reader_thread->workflow->pcap_handle); if (pcap_fd < 0) @@ -4433,6 +4412,7 @@ static void run_pcap_loop(struct nDPId_reader_thread * const reader_thread) nio_free(&io); return; } +#if !defined(__FreeBSD__) && !defined(__APPLE__) errno = 0; if (nio_add_fd(&io, signal_fd, NIO_EVENT_INPUT, NULL) != NIO_SUCCESS) { @@ -4443,6 +4423,7 @@ static void run_pcap_loop(struct nDPId_reader_thread * const reader_thread) nio_free(&io); return; } +#endif int const timeout_ms = 1000; /* TODO: Configurable? */ struct timeval tval_before_epoll, tval_after_epoll; @@ -4482,6 +4463,7 @@ static void run_pcap_loop(struct nDPId_reader_thread * const reader_thread) int fd = nio_get_fd(&io, i); +#if !defined(__FreeBSD__) && !defined(__APPLE__) if (fd == signal_fd) { struct signalfd_siginfo fdsi; @@ -4513,7 +4495,9 @@ static void run_pcap_loop(struct nDPId_reader_thread * const reader_thread) logger(1, "Received signal %d (%s)", fdsi.ssi_signo, signame); } } - else if (fd == pcap_fd) + else +#endif + if (fd == pcap_fd) { switch (pcap_dispatch( reader_thread->workflow->pcap_handle, -1, ndpi_process_packet, (uint8_t *)reader_thread)) diff --git a/nDPIsrvd.c b/nDPIsrvd.c index a4d7457fe..37034751f 100644 --- a/nDPIsrvd.c +++ b/nDPIsrvd.c @@ -9,7 +9,9 @@ #include <stdlib.h> #include <stdint.h> #include <string.h> +#if !defined(__FreeBSD__) && !defined(__APPLE__) #include <sys/signalfd.h> +#endif #include <sys/socket.h> #include <sys/types.h> #include <unistd.h> @@ -43,15 +45,19 @@ struct remote_desc { struct sockaddr_un peer; unsigned long long int json_bytes; +#if !defined(__FreeBSD__) && !defined(__APPLE__) pid_t pid; +#endif struct nDPIsrvd_json_buffer main_read_buffer; } event_collector_un; struct { struct sockaddr_un peer; +#if !defined(__FreeBSD__) && !defined(__APPLE__) pid_t pid; char * user_name; +#endif struct nDPIsrvd_write_buffer main_write_buffer; UT_array * additional_write_buffers; @@ -79,7 +85,7 @@ static int collector_un_sockfd = -1; static int distributor_un_sockfd = -1; static int distributor_in_sockfd = -1; static struct nDPIsrvd_address distributor_in_address = { - .raw.sa_family = 0xFFFF, + .raw.sa_family = (sa_family_t)0xFFFF, }; static struct @@ -278,12 +284,16 @@ static void logger_nDPIsrvd(struct remote_desc const * const remote, switch (remote->sock_type) { case DISTRIBUTOR_UN: +#if !defined(__FreeBSD__) && !defined(__APPLE__) logger(1, "%s PID %d (User: %s) %s", prefix, remote->event_distributor_un.pid, remote->event_distributor_un.user_name, logbuf); +#else + logger(1, "%s %s", prefix, logbuf); +#endif break; case DISTRIBUTOR_IN: logger(1, @@ -295,7 +305,11 @@ static void logger_nDPIsrvd(struct remote_desc const * const remote, logbuf); break; case COLLECTOR_UN: +#if !defined(__FreeBSD__) && !defined(__APPLE__) logger(1, "%s PID %d %s", prefix, remote->event_collector_un.pid, logbuf); +#else + logger(1, "%s %s", prefix, logbuf); +#endif break; } @@ -435,9 +449,12 @@ static int handle_outgoing_data(struct nio * const io, struct remote_desc * cons { struct nDPIsrvd_write_buffer * const write_buffer = get_write_buffer(remote); - if (write_buffer->buf.used == 0) { + if (write_buffer->buf.used == 0) + { return set_in_event(io, remote); - } else { + } + else + { return drain_main_buffer(remote); } } @@ -473,7 +490,8 @@ static int create_listen_sockets(void) { collector_un_sockfd = socket(AF_UNIX, SOCK_STREAM, 0); distributor_un_sockfd = socket(AF_UNIX, SOCK_STREAM, 0); - if (collector_un_sockfd < 0 || distributor_un_sockfd < 0) + if (collector_un_sockfd < 0 || distributor_un_sockfd < 0 || set_fd_cloexec(collector_un_sockfd) < 0 || + set_fd_cloexec(distributor_un_sockfd) < 0) { logger(1, "Error creating UNIX socket: %s", strerror(errno)); return 1; @@ -482,7 +500,7 @@ static int create_listen_sockets(void) if (is_cmdarg_set(&nDPIsrvd_options.distributor_in_address) != 0) { distributor_in_sockfd = socket(distributor_in_address.raw.sa_family, SOCK_STREAM, 0); - if (distributor_in_sockfd < 0) + if (distributor_in_sockfd < 0 || set_fd_cloexec(distributor_in_sockfd) < 0) { logger(1, "Error creating TCP/IP socket: %s", strerror(errno)); return 1; @@ -716,7 +734,9 @@ static void free_remote(struct nio * const io, struct remote_desc * remote) utarray_free(remote->event_distributor_un.additional_write_buffers); } nDPIsrvd_buffer_free(&remote->event_distributor_un.main_write_buffer.buf); +#if !defined(__FreeBSD__) && !defined(__APPLE__) free(remote->event_distributor_un.user_name); +#endif break; case DISTRIBUTOR_IN: if (errno != 0) @@ -935,7 +955,7 @@ static struct remote_desc * accept_remote(int server_fd, int client_fd; while ((client_fd = accept(server_fd, sockaddr, addrlen)) < 0 && errno == EINTR) {} - if (client_fd < 0) + if (client_fd < 0 || set_fd_cloexec(client_fd) < 0) { logger(1, "Accept failed: %s", strerror(errno)); return NULL; @@ -1005,6 +1025,7 @@ static int new_connection(struct nio * const io, int eventfd) return 1; } +#if !defined(__FreeBSD__) && !defined(__APPLE__) struct ucred ucred = {}; socklen_t ucred_len = sizeof(ucred); if (getsockopt(current->fd, SOL_SOCKET, SO_PEERCRED, &ucred, &ucred_len) == -1) @@ -1012,8 +1033,8 @@ static int new_connection(struct nio * const io, int eventfd) logger(1, "Error getting credentials from UNIX socket: %s", strerror(errno)); return 1; } - current->event_collector_un.pid = ucred.pid; +#endif logger_nDPIsrvd(current, "New collector connection from", ""); break; @@ -1023,6 +1044,7 @@ static int new_connection(struct nio * const io, int eventfd) { current->event_distributor_un.peer = sockaddr.saddr_distributor_un; +#if !defined(__FreeBSD__) && !defined(__APPLE__) struct ucred ucred = {}; socklen_t ucred_len = sizeof(ucred); if (getsockopt(current->fd, SOL_SOCKET, SO_PEERCRED, &ucred, &ucred_len) == -1) @@ -1047,6 +1069,7 @@ static int new_connection(struct nio * const io, int eventfd) current->event_distributor_un.pid = ucred.pid; current->event_distributor_un.user_name = strdup(pwres->pw_name); +#endif } else { @@ -1351,6 +1374,7 @@ static int handle_data_event(struct nio * const io, int index) } } +#if !defined(__FreeBSD__) && !defined(__APPLE__) static int setup_signalfd(struct nio * const io) { sigset_t mask; @@ -1383,10 +1407,13 @@ static int setup_signalfd(struct nio * const io) return sfd; } +#endif static int mainloop(struct nio * const io) { +#if !defined(__FreeBSD__) && !defined(__APPLE__) int signalfd = setup_signalfd(io); +#endif while (nDPIsrvd_main_thread_shutdown == 0) { @@ -1433,6 +1460,7 @@ static int mainloop(struct nio * const io) continue; } } +#if !defined(__FreeBSD__) && !defined(__APPLE__) else if (fd == signalfd) { struct signalfd_siginfo fdsi; @@ -1441,10 +1469,18 @@ static int mainloop(struct nio * const io) s = read(signalfd, &fdsi, sizeof(struct signalfd_siginfo)); if (s != sizeof(struct signalfd_siginfo)) { - logger(1, - "Invalid signal fd read size. Got %zd, wanted %zu bytes.", - s, - sizeof(struct signalfd_siginfo)); + if (s < 0) + { + logger(1, "Read from signal fd returned: %s", strerror(errno)); + nDPIsrvd_main_thread_shutdown = 1; + } + else + { + logger(1, + "Invalid signal fd read size. Got %zd, wanted %zu bytes.", + s, + sizeof(struct signalfd_siginfo)); + } continue; } @@ -1454,6 +1490,7 @@ static int mainloop(struct nio * const io) continue; } } +#endif else { /* Incoming data / Outoing data ready to receive / send. */ @@ -1467,7 +1504,9 @@ static int mainloop(struct nio * const io) free_remotes(io); nio_free(io); +#if !defined(__FreeBSD__) && !defined(__APPLE__) close(signalfd); +#endif return 0; } @@ -1627,7 +1666,7 @@ int main(int argc, char ** argv) "everyone with access to the device/network. You've been warned!"); break; case AF_UNIX: - case 0xFFFF: + case (sa_family_t)0xFFFF: break; } diff --git a/scripts/daemon.sh b/scripts/daemon.sh index 74e9ffde0..30b3c5c00 100755 --- a/scripts/daemon.sh +++ b/scripts/daemon.sh @@ -27,7 +27,15 @@ if [ -r "${NROOT}/nDPId-${NSUFFIX}.pid" -o -r "${NROOT}/nDPIsrvd-${NSUFFIX}.pid" if [ x"${nDPId_PID}" != x ]; then sudo kill "${nDPId_PID}" 2>/dev/null || true - while ps -p "${nDPId_PID}" > /dev/null; do sleep 1; done + + MAX_TRIES=10 + while ps -p "${nDPId_PID}" > /dev/null; do + test ${MAX_TRIES} -gt 0 || break + sleep 1 + MAX_TRIES=$((MAX_TRIES - 1)) + done + test ${MAX_TRIES} -eq 0 && { RETVAL=1; printf '%s\n' 'Error: nDPId not started' >&2; } + rm -f "${NROOT}/nDPId-${NSUFFIX}.pid" else printf '%s\n' "${1} not started .." >&2 @@ -36,7 +44,15 @@ if [ -r "${NROOT}/nDPId-${NSUFFIX}.pid" -o -r "${NROOT}/nDPIsrvd-${NSUFFIX}.pid" if [ x"${nDPIsrvd_PID}" != x ]; then kill "${nDPIsrvd_PID}" 2>/dev/null || true - while ps -p "${nDPIsrvd_PID}" > /dev/null; do sleep 1; done + + MAX_TRIES=10 + while ps -p "${nDPIsrvd_PID}" > /dev/null; do + test ${MAX_TRIES} -gt 0 || break + sleep 1 + MAX_TRIES=$((MAX_TRIES - 1)) + done + test ${MAX_TRIES} -eq 0 && { RETVAL=1; printf '%s\n' 'Error: nDPIsrvd not started' >&2; } + rm -f "${NROOT}/nDPIsrvd-${NSUFFIX}.pid" "${NROOT}/nDPIsrvd-${NSUFFIX}-collector.sock" "${NROOT}/nDPIsrvd-${NSUFFIX}-distributor.sock" else printf '%s\n' "${2} not started .." >&2 @@ -54,14 +70,14 @@ else sleep 0.5 MAX_TRIES=$((MAX_TRIES - 1)) done - test ${MAX_TRIES} -eq 0 && RETVAL=1 + test ${MAX_TRIES} -eq 0 && { RETVAL=1; printf '%s\n' 'Error: nDPIsrvd collector socket not available' >&2; } MAX_TRIES=10 while [ ! -S "${NROOT}/nDPIsrvd-${NSUFFIX}-distributor.sock" -a ${MAX_TRIES} -gt 0 ]; do sleep 0.5 MAX_TRIES=$((MAX_TRIES - 1)) done - test ${MAX_TRIES} -eq 0 && RETVAL=1 + test ${MAX_TRIES} -eq 0 && { RETVAL=1; printf '%s\n' 'Error: nDPIsrvd distributor socket not available' >&2; } sudo chgrp "$(id -n -g "${NUSER}")" "${NROOT}/nDPIsrvd-${NSUFFIX}-collector.sock" test $? -eq 0 || RETVAL=1 diff --git a/scripts/get-and-build-libndpi.sh b/scripts/get-and-build-libndpi.sh index be17f7687..2d0939538 100755 --- a/scripts/get-and-build-libndpi.sh +++ b/scripts/get-and-build-libndpi.sh @@ -32,7 +32,9 @@ if [ ! -z "${CC}" ]; then fi if [ ! -z "${MAKEFLAGS}" ]; then - MAKEFLAGS="-${MAKEFLAGS}" + case "$(uname -s)" in + Linux*) MAKEFLAGS="-${MAKEFLAGS}" ;; + esac fi cat <<EOF @@ -102,7 +104,7 @@ MAKE_PROGRAM="${MAKE_PROGRAM:-make -j4}" HOST_ARG="--host=${HOST_TRIPLET}" ./autogen.sh --enable-option-checking=fatal \ --prefix="/" \ - --with-only-libndpi ${HOST_ARG} ${ADDITIONAL_ARGS} + --with-only-libndpi ${HOST_ARG} ${ADDITIONAL_ARGS} || { cat config.log | grep -v '^|'; false; } ${MAKE_PROGRAM} ${MAKEFLAGS} install DESTDIR="${DEST_INSTALL}" rm -f "${LOCKFILE}" @@ -141,6 +141,7 @@ int is_path_absolute(char const * const prefix, char const * const path) int daemonize_with_pidfile(char const * const pidfile) { pid_str ps = {}; + int nullfd; if (daemonize != 0) { @@ -156,12 +157,44 @@ int daemonize_with_pidfile(char const * const pidfile) return 1; } - if (daemon(0, 0) != 0) + nullfd = open("/dev/null", O_NONBLOCK, O_WRONLY); + if (nullfd < 0 || dup2(nullfd, STDIN_FILENO) < 0 || dup2(nullfd, STDOUT_FILENO) < 0 || + dup2(nullfd, STDERR_FILENO) < 0) { - logger_early(1, "daemon: %s", strerror(errno)); + logger_early(1, "Opening /dev/null or replacing stdin/stdout/stderr failed: %s", strerror(errno)); return 1; } + // For compatiblity reasons, we use the UNIX double fork() technique. + + switch (fork()) + { + case 0: + break; + case -1: + logger_early(1, "Could not fork (first time): %s", strerror(errno)); + return 1; + default: + exit(0); + } + + if (chdir("/") < 0 || setsid() < 0) + { + logger_early(1, "chdir() / setsid() failed: %s", strerror(errno)); + return 1; + } + + switch (fork()) + { + case 0: + break; + case -1: + logger_early(1, "Could not fork (second time): %s", strerror(errno)); + return 1; + default: + exit(0); + } + if (create_pidfile(pidfile) != 0) { return 1; @@ -401,6 +434,17 @@ __attribute__((format(printf, 2, 3))) void logger_early(int is_error, char const log_to_console = old_log_to_console; } +int set_fd_cloexec(int fd) +{ + int flags = fcntl(fd, F_GETFD, 0); + + if (flags < 0) + { + return -1; + } + return fcntl(fd, F_SETFD, FD_CLOEXEC); +} + char const * get_nDPId_version(void) { return "nDPId version " @@ -56,6 +56,8 @@ __attribute__((format(printf, 2, 3))) void logger(int is_error, char const * con __attribute__((format(printf, 2, 3))) void logger_early(int is_error, char const * const format, ...); +int set_fd_cloexec(int fd); + char const * get_nDPId_version(void); #endif |