- Minimum CMake version: 3.1.0

- Minimum G++ version: 4.8
- Minimum Visual Studio version: VS2012
- Added '-std=c++11' flag to G++
- Removed unused defines
- Removed checks for standard library headers
- Added CMake detections of '_vsnprintf' and '_snprintf' for Visual Studio 2015
- Removed bnpcap
- Force Travis CI to use CMake 3.1.3 and G++5
This commit is contained in:
xboi209 2015-08-23 23:02:11 -07:00
parent 98f7165e21
commit ae45207b29
11 changed files with 187 additions and 1065 deletions

View file

@ -1,15 +1,22 @@
sudo: required
branches:
only:
- master
language: cpp
os:
- linux
os: linux
compiler: gcc
before_install:
- sudo apt-get update --fix-missing
- sudo apt-get install build-essential zlib1g-dev libmysqlclient-dev liblua5.1-0-dev
- (cd /tmp && wget http://www.cmake.org/files/v3.1/cmake-3.1.3.tar.gz && tar zxf cmake-3.1.3.tar.gz)
- (cd /tmp/cmake-3.1.3 && cmake . && make && sudo make install) > /dev/null 2>&1
- sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
- sudo apt-get -qq update
- sudo apt-get -qq install g++-5
- export CXX="g++-5" CC="gcc-5"
- mkdir build
- cd build

View file

@ -1,9 +1,5 @@
# Required cmake version
cmake_minimum_required(VERSION 2.4.3)
if(COMMAND cmake_policy)
cmake_policy(SET CMP0003 NEW)
endif(COMMAND cmake_policy)
cmake_minimum_required(VERSION 3.1.0)
# Put the include dirs which are in the source or build tree
# before all other include dirs, so the headers in the sources
@ -11,18 +7,17 @@ endif(COMMAND cmake_policy)
# since cmake 2.4.1
set(CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE ON)
project(pvpgn)
project(pvpgn CXX)
option(WITH_BNETD "compile the bnetd target" ON)
option(WITH_D2CS "compile the d2cs target" ON)
option(WITH_D2DBS "compile the d2dbs target" ON)
option(WITH_ANSI "enforce strict ISO C++ conforming" ON)
option(WITH_LUA "enable Lua support" OFF)
if(WIN32)
option(WITH_WIN32_GUI "enable GUI building (default on)" ON)
endif(WIN32)
option(WITH_LUA "enable Lua support" OFF)
#storage backends flags
option(WITH_MYSQL "include MySQL user accounts support" OFF)
option(WITH_SQLITE3 "include SQLite3 user accounts support" OFF)
@ -32,29 +27,22 @@ include(ConfigureChecks.cmake)
if (CMAKE_COMPILER_IS_GNUCXX)
# Determine GCC version.
message("Determining GCC version.")
EXEC_PROGRAM(${CMAKE_CXX_COMPILER}
ARGS --version
OUTPUT_VARIABLE _GCC_VERSION)
STRING(REGEX REPLACE ".* ([0-9])\\.([0-9])\\.([0-9]) .*" "\\1\\2\\3"
_GCC_VERSION ${_GCC_VERSION})
message(" GCC version is ${_GCC_VERSION}")
# Minimum G++ version: 4.8
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.8)
message(FATAL_ERROR "G++ 4.8 or higher required")
endif()
# Add -Wno-longlong if the GCC version is < 4.0.0. Add -pedantic flag
# but disable warnings for variadic macros with GCC >= 4.0.0. Earlier
# versions warn because of anonymous variadic macros in pedantic mode
# but do not have a flag to disable these warnings.
if (400 GREATER _GCC_VERSION)
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-long-long")
else (400 GREATER _GCC_VERSION)
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic -Wno-variadic-macros")
endif (400 GREATER _GCC_VERSION)
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -pedantic -Wno-variadic-macros")
# Pass CXX flags to flags.
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSEQAN_CXX_FLAGS_=\"${CMAKE_CXX_FLAGS}\"")
endif (CMAKE_COMPILER_IS_GNUCXX)
endif ()
if (MSVC)
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 17.0)
message(FATAL_ERROR "Visual Studio 2012 or higher required")
endif()
endif ()
subdirs(src conf man files)
if(WITH_LUA)

View file

@ -9,11 +9,10 @@ set(CMAKE_MODULE_PATH
# include used modules
include(DefineInstallationPaths)
include(CheckIncludeFileCXX)
include(CheckIncludeFilesCXX)
include(CheckFunctionExists)
include(CheckSymbolExists)
include(CheckTypeSize)
include(CheckLibraryExists)
include(CheckTypeSizeCXX)
include(CheckCXXCompilerFlag)
include(CheckMkdirArgs)
@ -35,9 +34,9 @@ else(WIN32)
set(D2DBS_DEFAULT_CONF_FILE "${SYSCONFDIR}/d2dbs.conf")
endif(WIN32)
enable_language(C)
# library checks
find_package(ZLIB REQUIRED)
check_library_exists(pcap pcap_open_offline "" HAVE_LIBPCAP)
check_library_exists(nsl gethostbyname "" HAVE_LIBNSL)
check_library_exists(socket socket "" HAVE_LIBSOCKET)
check_library_exists(resolv inet_aton "" HAVE_LIBRESOLV)
@ -90,66 +89,74 @@ if(WIN32)
SET(NETWORK_LIBRARIES ${NETWORK_LIBRARIES} ws2_32)
endif(WIN32)
check_include_files_cxx("cassert;cctype;cerrno;cmath;climits;csignal;cstdarg;cstddef;cstdio;cstdlib;cstring;ctime;deque;exception;fstream;iomanip;iostream;limits;list;map;memory;sstream;stdexcept;string;utility;vector" HAVE_STD_HEADERS)
if(NOT HAVE_STD_HEADERS)
MESSAGE(FATAL_ERROR "Standard C90/C++98 header missing, you need a fully standard compliant compiler/enviroment.")
endif(NOT HAVE_STD_HEADERS)
check_include_file_cxx(fcntl.h HAVE_FCNTL_H)
check_include_file_cxx(sys/time.h HAVE_SYS_TIME_H)
check_include_file_cxx(sys/select.h HAVE_SYS_SELECT_H)
check_include_file_cxx(unistd.h HAVE_UNISTD_H)
check_include_file_cxx(sys/utsname.h HAVE_SYS_UTSNAME_H)
check_include_file_cxx(sys/timeb.h HAVE_SYS_TIMEB_H)
check_include_file_cxx(sys/socket.h HAVE_SYS_SOCKET_H)
check_include_file_cxx(sys/param.h HAVE_SYS_PARAM_H)
check_include_file_cxx(netinet/in.h HAVE_NETINET_IN_H)
message(STATUS "Checking POSIX headers")
check_include_file_cxx(arpa/inet.h HAVE_ARPA_INET_H)
check_include_file_cxx(netdb.h HAVE_NETDB_H)
check_include_file_cxx(termios.h HAVE_TERMIOS_H)
check_include_file_cxx(sys/types.h HAVE_SYS_TYPES_H)
check_include_file_cxx(sys/wait.h HAVE_SYS_WAIT_H)
check_include_file_cxx(sys/ioctl.h HAVE_SYS_IOCTL_H)
check_include_file_cxx(stdint.h HAVE_STDINT_H)
check_include_file_cxx(sys/file.h HAVE_SYS_FILE_H)
check_include_file_cxx(poll.h HAVE_POLL_H)
check_include_file_cxx(sys/poll.h HAVE_SYS_POLL_H)
check_include_file_cxx(sys/stropts.h HAVE_SYS_STROPTS_H)
check_include_file_cxx(sys/stat.h HAVE_SYS_STAT_H)
check_include_file_cxx(pwd.h HAVE_PWD_H)
check_include_file_cxx(grp.h HAVE_GRP_H)
check_include_file_cxx(dir.h HAVE_DIR_H)
check_include_file_cxx(dirent.h HAVE_DIRENT_H)
check_include_file_cxx(ndir.h HAVE_NDIR_H)
check_include_file_cxx(sys/ndir.h HAVE_SYS_NDIR_H)
check_include_file_cxx(sys/dir.h HAVE_SYS_DIR_H)
check_include_file_cxx(direct.h HAVE_DIRECT_H)
check_include_file_cxx(grp.h HAVE_GRP_H)
check_include_file_cxx(fcntl.h HAVE_FCNTL_H)
check_include_file_cxx(netdb.h HAVE_NETDB_H)
check_include_file_cxx(netinet/in.h HAVE_NETINET_IN_H)
check_include_file_cxx(poll.h HAVE_POLL_H)
check_include_file_cxx(pwd.h HAVE_PWD_H)
check_include_file_cxx(sys/mman.h HAVE_SYS_MMAN_H)
check_include_files_cxx("sys/types.h;sys/event.h" HAVE_SYS_EVENT_H)
check_include_file_cxx(sys/epoll.h HAVE_SYS_EPOLL_H)
check_include_file_cxx(sys/resource.h HAVE_SYS_RESOURCE_H)
check_include_file_cxx(pcap.h HAVE_PCAP_H)
check_include_file_cxx(sys/select.h HAVE_SYS_SELECT_H)
check_include_file_cxx(sys/socket.h HAVE_SYS_SOCKET_H)
check_include_file_cxx(sys/stat.h HAVE_SYS_STAT_H)
check_include_file_cxx(sys/time.h HAVE_SYS_TIME_H)
check_include_file_cxx(sys/types.h HAVE_SYS_TYPES_H)
check_include_file_cxx(sys/utsname.h HAVE_SYS_UTSNAME_H)
check_include_file_cxx(sys/wait.h HAVE_SYS_WAIT_H)
check_include_file_cxx(termios.h HAVE_TERMIOS_H)
check_include_file_cxx(unistd.h HAVE_UNISTD_H)
message(STATUS "Checking optional POSIX/required SUS headers")
check_include_file_cxx(sys/timeb.h HAVE_SYS_TIMEB_H)
message(STATUS "Checking FreeBSD-based headers")
if (HAVE_SYS_TYPES_H)
check_include_file_cxx(sys/event.h HAVE_SYS_EVENT_H)
endif()
check_include_file_cxx(sys/param.h HAVE_SYS_PARAM_H)
message(STATUS "Checking BSD headers")
check_include_file_cxx(sys/file.h HAVE_SYS_FILE_H)
message(STATUS "Checking Linux headers")
check_include_file_cxx(sys/epoll.h HAVE_SYS_EPOLL_H)
message(STATUS "Checking Win32 headers")
check_include_file_cxx(windows.h HAVE_WINDOWS_H)
check_include_file_cxx(winsock2.h HAVE_WINSOCK2_H)
check_include_file_cxx(process.h HAVE_PROCESS_H)
check_type_size_cxx("unsigned char" SIZEOF_UNSIGNED_CHAR)
check_type_size_cxx("unsigned short" SIZEOF_UNSIGNED_SHORT)
check_type_size_cxx("unsigned int" SIZEOF_UNSIGNED_INT)
check_type_size_cxx("unsigned long" SIZEOF_UNSIGNED_LONG)
check_type_size_cxx("unsigned long long" SIZEOF_UNSIGNED_LONG_LONG)
check_type_size_cxx("signed char" SIZEOF_SIGNED_CHAR)
check_type_size_cxx("signed short" SIZEOF_SIGNED_SHORT)
check_type_size_cxx("signed int" SIZEOF_SIGNED_INT)
check_type_size_cxx("signed long" SIZEOF_SIGNED_LONG)
check_type_size_cxx("signed long long" SIZEOF_SIGNED_LONG_LONG)
message(STATUS "Checking other headers")
check_include_file_cxx(dir.h HAVE_DIR_H)
check_include_file_cxx(direct.h HAVE_DIRECT_H)
check_include_file_cxx(ndir.h HAVE_NDIR_H)
check_include_file_cxx(sys/dir.h HAVE_SYS_DIR_H)
check_include_file_cxx(sys/ndir.h HAVE_SYS_NDIR_H)
check_include_file_cxx(sys/poll.h HAVE_SYS_POLL_H)
#Keep for now
check_include_file_cxx(stdint.h HAVE_STDINT_H)
check_type_size("unsigned char" SIZEOF_UNSIGNED_CHAR)
check_type_size("unsigned short" SIZEOF_UNSIGNED_SHORT)
check_type_size("unsigned int" SIZEOF_UNSIGNED_INT)
check_type_size("unsigned long" SIZEOF_UNSIGNED_LONG)
check_type_size("unsigned long long" SIZEOF_UNSIGNED_LONG_LONG)
check_type_size("signed char" SIZEOF_SIGNED_CHAR)
check_type_size("signed short" SIZEOF_SIGNED_SHORT)
check_type_size("signed int" SIZEOF_SIGNED_INT)
check_type_size("signed long" SIZEOF_SIGNED_LONG)
check_type_size("signed long long" SIZEOF_SIGNED_LONG_LONG)
check_function_exists(mmap HAVE_MMAP)
check_function_exists(gettimeofday HAVE_GETTIMEOFDAY)
check_function_exists(strdup HAVE_STRDUP)
check_function_exists(strtoul HAVE_STRTOUL)
check_function_exists(uname HAVE_UNAME)
check_function_exists(uname HAVE_UNAME)
check_function_exists(fork HAVE_FORK)
check_function_exists(getpid HAVE_GETPID)
check_function_exists(sigaction HAVE_SIGACTION)
@ -189,9 +196,9 @@ check_function_exists(setitimer HAVE_SETITIMER)
check_function_exists(epoll_create HAVE_EPOLL_CREATE)
check_function_exists(getrlimit HAVE_GETRLIMIT)
check_symbol_exists(vsnprintf "stdio.h" HAVE_VSNPRINTF)
check_function_exists(_vsnprintf HAVE__VSNPRINTF)
check_symbol_exists(_vsnprintf "stdio.h" HAVE__VSNPRINTF)
check_symbol_exists(snprintf "stdio.h" HAVE_SNPRINTF)
check_function_exists(_snprintf HAVE__SNPRINTF)
check_symbol_exists(_snprintf "stdio.h" HAVE__SNPRINTF)
check_function_exists(setpgrp HAVE_SETPGRP)
check_function_exists(inet_aton HAVE_INET_ATON)

View file

@ -1,59 +0,0 @@
# - Check if the files can be included
#
# CHECK_INCLUDE_FILES_CXX(INCLUDE VARIABLE)
#
# INCLUDE - list of files to include
# VARIABLE - variable to return result
#
# The following variables may be set before calling this macro to
# modify the way the check is run:
#
# CMAKE_REQUIRED_FLAGS = string of compile command line flags
# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar)
# CMAKE_REQUIRED_INCLUDES = list of include directories
MACRO(CHECK_INCLUDE_FILES_CXX INCLUDE VARIABLE)
IF("${VARIABLE}" MATCHES "^${VARIABLE}$")
SET(CMAKE_CONFIGURABLE_FILE_CONTENT "/* */\n")
IF(CMAKE_REQUIRED_INCLUDES)
SET(CHECK_INCLUDE_FILES_CXX_INCLUDE_DIRS "-DINCLUDE_DIRECTORIES=${CMAKE_REQUIRED_INCLUDES}")
ELSE(CMAKE_REQUIRED_INCLUDES)
SET(CHECK_INCLUDE_FILES_CXX_INCLUDE_DIRS)
ENDIF(CMAKE_REQUIRED_INCLUDES)
SET(CHECK_INCLUDE_FILES_CXX_CONTENT "/* */\n")
SET(MACRO_CHECK_INCLUDE_FILES_CXX_FLAGS ${CMAKE_REQUIRED_FLAGS})
FOREACH(FILE ${INCLUDE})
SET(CMAKE_CONFIGURABLE_FILE_CONTENT
"${CMAKE_CONFIGURABLE_FILE_CONTENT}#include <${FILE}>\n")
ENDFOREACH(FILE)
SET(CMAKE_CONFIGURABLE_FILE_CONTENT
"${CMAKE_CONFIGURABLE_FILE_CONTENT}\n\nint main(){return 0;}\n")
CONFIGURE_FILE("${CMAKE_ROOT}/Modules/CMakeConfigurableFile.in"
"${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckIncludeFiles.cxx" @ONLY IMMEDIATE)
MESSAGE(STATUS "Looking for include files ${VARIABLE}")
TRY_COMPILE(${VARIABLE}
${CMAKE_BINARY_DIR}
${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckIncludeFiles.cxx
COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
CMAKE_FLAGS
-DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_INCLUDE_FILES_CXX_FLAGS}
"${CHECK_INCLUDE_FILES_CXX_INCLUDE_DIRS}"
OUTPUT_VARIABLE OUTPUT)
IF(${VARIABLE})
MESSAGE(STATUS "Looking for include files ${VARIABLE} - found")
SET(${VARIABLE} 1 CACHE INTERNAL "Have include ${VARIABLE}")
FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
"Determining if files ${INCLUDE} "
"exist passed with the following output:\n"
"${OUTPUT}\n\n")
ELSE(${VARIABLE})
MESSAGE(STATUS "Looking for include files ${VARIABLE} - not found.")
SET(${VARIABLE} "" CACHE INTERNAL "Have includes ${VARIABLE}")
FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
"Determining if files ${INCLUDE} "
"exist failed with the following output:\n"
"${OUTPUT}\nSource:\n${CMAKE_CONFIGURABLE_FILE_CONTENT}\n")
ENDIF(${VARIABLE})
ENDIF("${VARIABLE}" MATCHES "^${VARIABLE}$")
ENDMACRO(CHECK_INCLUDE_FILES_CXX)

View file

@ -3,89 +3,63 @@ IF (NOT APPLICATION_NAME)
SET(APPLICATION_NAME ${PROJECT_NAME})
ENDIF (NOT APPLICATION_NAME)
# Suffix for Linux
SET(LIB_SUFFIX
CACHE STRING "Define suffix of directory name (32/64)"
)
SET(EXEC_INSTALL_PREFIX
"${CMAKE_INSTALL_PREFIX}"
CACHE PATH "Base directory for executables and libraries"
FORCE
)
SET(SHARE_INSTALL_PREFIX
"${CMAKE_INSTALL_PREFIX}/share"
CACHE PATH "Base directory for files which go to share/"
FORCE
)
SET(DATA_INSTALL_PREFIX
"${SHARE_INSTALL_PREFIX}/${APPLICATION_NAME}"
CACHE PATH "The parent directory where applications can install their data" FORCE)
# The following are directories where stuff will be installed to
CACHE PATH "The parent directory where applications can install their data"
FORCE
)
SET(BIN_INSTALL_DIR
"${EXEC_INSTALL_PREFIX}/bin"
CACHE PATH "The ${APPLICATION_NAME} binary install dir (default prefix/bin)"
FORCE
)
#***********************************#
if(WIN32)
SET(LOCALSTATE_INSTALL_DIR
"${EXEC_INSTALL_PREFIX}/var"
CACHE PATH "The ${APPLICATION_NAME} local state install dir (default prefix/var)"
FORCE
)
else()
SET(LOCALSTATE_INSTALL_DIR
"${EXEC_INSTALL_PREFIX}/var/${APPLICATION_NAME}"
CACHE PATH "The ${APPLICATION_NAME} local state install dir (default prefix/var)"
FORCE
)
endif()
SET(MAN_INSTALL_DIR
"${SHARE_INSTALL_PREFIX}/man"
CACHE PATH "The ${APPLICATION_NAME} man install dir (default prefix/man)"
FORCE
)
if(WIN32)
SET(SBIN_INSTALL_DIR
"${EXEC_INSTALL_PREFIX}"
CACHE PATH "The ${APPLICATION_NAME} sbin install dir (default prefix/sbin)"
FORCE
)
else(WIN32)
else()
SET(SBIN_INSTALL_DIR
"${EXEC_INSTALL_PREFIX}/sbin"
CACHE PATH "The ${APPLICATION_NAME} sbin install dir (default prefix/sbin)"
FORCE
)
endif(WIN32)
SET(LIB_INSTALL_DIR
"${EXEC_INSTALL_PREFIX}/lib${LIB_SUFFIX}"
CACHE PATH "The subdirectory relative to the install prefix where libraries will be installed (default is prefix/lib)"
FORCE
)
SET(LIBEXEC_INSTALL_DIR
"${EXEC_INSTALL_PREFIX}/libexec"
CACHE PATH "The subdirectory relative to the install prefix where libraries will be installed (default is prefix/libexec)"
FORCE
)
SET(PLUGIN_INSTALL_DIR
"${LIB_INSTALL_DIR}/${APPLICATION_NAME}"
CACHE PATH "The subdirectory relative to the install prefix where plugins will be installed (default is prefix/lib/${APPLICATION_NAME})"
FORCE
)
SET(INCLUDE_INSTALL_DIR
"${CMAKE_INSTALL_PREFIX}/include"
CACHE PATH "The subdirectory to the header prefix (default prefix/include)"
FORCE
)
endif()
SET(DATA_INSTALL_DIR
"${DATA_INSTALL_PREFIX}"
CACHE PATH "The parent directory where applications can install their data (default prefix/share/${APPLICATION_NAME})"
FORCE
)
SET(HTML_INSTALL_DIR
"${DATA_INSTALL_PREFIX}/doc/HTML"
CACHE PATH "The HTML install dir for documentation (default data/doc/html)"
FORCE
)
SET(ICON_INSTALL_DIR
"${DATA_INSTALL_PREFIX}/icons"
CACHE PATH "The icon install dir (default data/icons/)"
FORCE
)
SET(SOUND_INSTALL_DIR
"${DATA_INSTALL_PREFIX}/sounds"
CACHE PATH "The install dir for sound files (default data/sounds)"
FORCE
)
SET(LOCALE_INSTALL_DIR
"${SHARE_INSTALL_PREFIX}/locale"
CACHE PATH "The install dir for translations (default prefix/share/locale)"
SET(SHARE_INSTALL_PREFIX
"${CMAKE_INSTALL_PREFIX}/share"
CACHE PATH "Base directory for files which go to share/"
FORCE
)
@ -95,36 +69,10 @@ if(WIN32)
CACHE PATH "The ${APPLICATION_NAME} sysconfig install dir (default conf)"
FORCE
)
else(WIN32)
else()
SET(SYSCONF_INSTALL_DIR
"${EXEC_INSTALL_PREFIX}/etc/${APPLICATION_NAME}"
CACHE PATH "The ${APPLICATION_NAME} sysconfig install dir (default prefix/etc)"
FORCE
)
endif(WIN32)
SET(MAN_INSTALL_DIR
"${SHARE_INSTALL_PREFIX}/man"
CACHE PATH "The ${APPLICATION_NAME} man install dir (default prefix/man)"
FORCE
)
SET(INFO_INSTALL_DIR
"${SHARE_INSTALL_PREFIX}/info"
CACHE PATH "The ${APPLICATION_NAME} info install dir (default prefix/info)"
FORCE
)
if(WIN32)
SET(LOCALSTATE_INSTALL_DIR
"${EXEC_INSTALL_PREFIX}/var"
CACHE PATH "The ${APPLICATION_NAME} local state install dir (default prefix/var)"
FORCE
)
else(WIN32)
SET(LOCALSTATE_INSTALL_DIR
"${EXEC_INSTALL_PREFIX}/var/${APPLICATION_NAME}"
CACHE PATH "The ${APPLICATION_NAME} local state install dir (default prefix/var)"
FORCE
)
endif(WIN32)
endif()

View file

@ -15,12 +15,10 @@
#cmakedefine HAVE_TERMIOS_H
#cmakedefine HAVE_SYS_TYPES_H
#cmakedefine HAVE_SYS_WAIT_H
#cmakedefine HAVE_SYS_IOCTL_H
#cmakedefine HAVE_STDINT_H
#cmakedefine HAVE_SYS_FILE_H
#cmakedefine HAVE_POLL_H
#cmakedefine HAVE_SYS_POLL_H
#cmakedefine HAVE_SYS_STROPTS_H
#cmakedefine HAVE_SYS_STAT_H
#cmakedefine HAVE_PWD_H
#cmakedefine HAVE_GRP_H
@ -34,7 +32,6 @@
#cmakedefine HAVE_SYS_EVENT_H
#cmakedefine HAVE_SYS_EPOLL_H
#cmakedefine HAVE_SYS_RESOURCE_H
#cmakedefine HAVE_PCAP_H
#cmakedefine HAVE_WINDOWS_H
#cmakedefine HAVE_WINSOCK2_H
#cmakedefine HAVE_PROCESS_H

View file

@ -54,10 +54,6 @@ if(WITH_D2DBS)
add_subdirectory(d2dbs)
endif(WITH_D2DBS)
if(HAVE_PCAP_H AND HAVE_LIBPCAP)
add_subdirectory(bnpcap)
endif(HAVE_PCAP_H AND HAVE_LIBPCAP)
if(CMAKE_TESTING_ENABLED)
add_subdirectory(test)
endif(CMAKE_TESTING_ENABLED)

View file

@ -465,12 +465,29 @@ namespace pvpgn
*/
#ifndef REGION_CONVERT_RUSSIAN
typedef struct ConvLetter {
typedef struct ConvLetter
{
char win1251;
int unicode;
} Letter;
static Letter g_letters[] = { { 0x82, 0x201A }, { 0x83, 0x0453 }, { 0x84, 0x201E }, { 0x85, 0x2026 }, { 0x86, 0x2020 }, { 0x87, 0x2021 }, { 0x88, 0x20AC }, { 0x89, 0x2030 }, { 0x8A, 0x0409 }, { 0x8B, 0x2039 }, { 0x8C, 0x040A }, { 0x8D, 0x040C }, { 0x8E, 0x040B }, { 0x8F, 0x040F }, { 0x90, 0x0452 }, { 0x91, 0x2018 }, { 0x92, 0x2019 }, { 0x93, 0x201C }, { 0x94, 0x201D }, { 0x95, 0x2022 }, { 0x96, 0x2013 }, { 0x97, 0x2014 }, { 0x99, 0x2122 }, { 0x9A, 0x0459 }, { 0x9B, 0x203A }, { 0x9C, 0x045A }, { 0x9D, 0x045C }, { 0x9E, 0x045B }, { 0x9F, 0x045F }, { 0xA0, 0x00A0 }, { 0xA1, 0x040E }, { 0xA2, 0x045E }, { 0xA3, 0x0408 }, { 0xA4, 0x00A4 }, { 0xA5, 0x0490 }, { 0xA6, 0x00A6 }, { 0xA7, 0x00A7 }, { 0xA8, 0x0401 }, { 0xA9, 0x00A9 }, { 0xAA, 0x0404 }, { 0xAB, 0x00AB }, { 0xAC, 0x00AC }, { 0xAD, 0x00AD }, { 0xAE, 0x00AE }, { 0xAF, 0x0407 }, { 0xB0, 0x00B0 }, { 0xB1, 0x00B1 }, { 0xB2, 0x0406 }, { 0xB3, 0x0456 }, { 0xB4, 0x0491 }, { 0xB5, 0x00B5 }, { 0xB6, 0x00B6 }, { 0xB7, 0x00B7 }, { 0xB8, 0x0451 }, { 0xB9, 0x2116 }, { 0xBA, 0x0454 }, { 0xBB, 0x00BB }, { 0xBC, 0x0458 }, { 0xBD, 0x0405 }, { 0xBE, 0x0455 }, { 0xBF, 0x0457 } };
static Letter g_letters[] = {
{ static_cast<char>(0x82), 0x201A }, { static_cast<char>(0x83), 0x0453 }, { static_cast<char>(0x84), 0x201E }, { static_cast<char>(0x85), 0x2026 },
{ static_cast<char>(0x86), 0x2020 }, { static_cast<char>(0x87), 0x2021 }, { static_cast<char>(0x88), 0x20AC }, { static_cast<char>(0x89), 0x2030 },
{ static_cast<char>(0x8A), 0x0409 }, { static_cast<char>(0x8B), 0x2039 }, { static_cast<char>(0x8C), 0x040A }, { static_cast<char>(0x8D), 0x040C },
{ static_cast<char>(0x8E), 0x040B }, { static_cast<char>(0x8F), 0x040F }, { static_cast<char>(0x90), 0x0452 }, { static_cast<char>(0x91), 0x2018 },
{ static_cast<char>(0x92), 0x2019 }, { static_cast<char>(0x93), 0x201C }, { static_cast<char>(0x94), 0x201D }, { static_cast<char>(0x95), 0x2022 },
{ static_cast<char>(0x96), 0x2013 }, { static_cast<char>(0x97), 0x2014 }, { static_cast<char>(0x99), 0x2122 }, { static_cast<char>(0x9A), 0x0459 },
{ static_cast<char>(0x9B), 0x203A }, { static_cast<char>(0x9C), 0x045A }, { static_cast<char>(0x9D), 0x045C }, { static_cast<char>(0x9E), 0x045B },
{ static_cast<char>(0x9F), 0x045F }, { static_cast<char>(0xA0), 0x00A0 }, { static_cast<char>(0xA1), 0x040E }, { static_cast<char>(0xA2), 0x045E },
{ static_cast<char>(0xA3), 0x0408 }, { static_cast<char>(0xA4), 0x00A4 }, { static_cast<char>(0xA5), 0x0490 }, { static_cast<char>(0xA6), 0x00A6 },
{ static_cast<char>(0xA7), 0x00A7 }, { static_cast<char>(0xA8), 0x0401 }, { static_cast<char>(0xA9), 0x00A9 }, { static_cast<char>(0xAA), 0x0404 },
{ static_cast<char>(0xAB), 0x00AB }, { static_cast<char>(0xAC), 0x00AC }, { static_cast<char>(0xAD), 0x00AD }, { static_cast<char>(0xAE), 0x00AE },
{ static_cast<char>(0xAF), 0x0407 }, { static_cast<char>(0xB0), 0x00B0 }, { static_cast<char>(0xB1), 0x00B1 }, { static_cast<char>(0xB2), 0x0406 },
{ static_cast<char>(0xB3), 0x0456 }, { static_cast<char>(0xB4), 0x0491 }, { static_cast<char>(0xB5), 0x00B5 }, { static_cast<char>(0xB6), 0x00B6 },
{ static_cast<char>(0xB7), 0x00B7 }, { static_cast<char>(0xB8), 0x0451 }, { static_cast<char>(0xB9), 0x2116 }, { static_cast<char>(0xBA), 0x0454 },
{ static_cast<char>(0xBB), 0x00BB }, { static_cast<char>(0xBC), 0x0458 }, { static_cast<char>(0xBD), 0x0405 }, { static_cast<char>(0xBE), 0x0455 },
{ static_cast<char>(0xBF), 0x0457 } };
// https://code.google.com/p/convert-utf8-to-cp1251/
int convert_utf8_to_windows1251(const char* utf8, char* windows1251, size_t n)

View file

@ -1,4 +0,0 @@
add_executable(bnpcap bnpcap.cpp)
target_link_libraries(bnpcap common pcap)
install(TARGETS bnpcap DESTINATION ${BINDIR})

View file

@ -1,769 +0,0 @@
/*
* Copyright (C) 2001 Marco Ziech (mmz@gmx.net)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "common/setup_before.h"
#include <cstring>
#include <cerrno>
#include <pcap.h>
#include "compat/pgetopt.h"
#include "compat/psock.h"
#include "common/init_protocol.h"
#include "common/bnet_protocol.h"
#include "common/udp_protocol.h"
#include "common/packet.h"
#include "common/eventlog.h"
#include "common/hexdump.h"
#include "common/list.h"
#include "common/version.h"
#include "common/util.h"
#include "common/xalloc.h"
#include "common/setup_after.h"
using namespace pvpgn;
/* FIXME: everywhere: add checks for NULL pointers */
char *filename = NULL;
pcap_t *pc;
char ebuf[PCAP_ERRBUF_SIZE];
int bnpcap_dodebug = 0;
int bnpcap_beverbose = 0;
unsigned int listen_port = 6112;
/********************* CONNECTIONS ********************/
typedef enum {
tcp_state_none,
tcp_state_syn,
tcp_state_ack,
tcp_state_ok
} t_tcp_state;
typedef struct {
/* It's IPV4 */
unsigned int ip;
unsigned short port;
} t_bnpcap_addr;
/* To track connections ... */
typedef struct {
t_bnpcap_addr client;
t_bnpcap_addr server;
t_packet_class cclass;
t_tcp_state tcpstate;
int incomplete;
int clientoff;
t_packet *clientpkt;
int serveroff;
t_packet *serverpkt;
t_list * packets;
} t_bnpcap_conn;
typedef struct {
t_packet_dir dir;
struct timeval tv;
unsigned int id;
t_packet *p;
} t_bnpcap_packet;
t_list * conns;
t_list * udppackets;
struct timeval packettime;
static unsigned int current_packet_id = 1;
/*********************** HEADERS **********************/
/* FIXME: don't assume that's always true */
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
/************************** TCP ***********************/
typedef struct {
u16 sport;
u16 dport;
u32 seqno;
u32 ackno;
u16 stuff; /* Data offset, various flags */
u16 window;
u16 checksum;
u16 urgp; /* Urgent Pointer (if URG flag set) */
/* options */
} t_tcp_header_raw;
typedef struct {
unsigned short sport;
unsigned short dport;
unsigned int seqno;
unsigned int ackno;
unsigned char doffset;
unsigned short flags;
#define TCP_URG 0x20 /* Urgent pointer field significant */
#define TCP_ACK 0x10 /* Acknowlegdement field significant */
#define TCP_PSH 0x08 /* Push function */
#define TCP_RST 0x04 /* Reset connection */
#define TCP_SYN 0x02 /* Synchronize sequence numbers */
#define TCP_FIN 0x01 /* No more data from sender (finish) */
unsigned short window;
unsigned short checksum;
unsigned short urgp;
/* options */
} t_tcp_header;
/******************************** UDP ************************/
typedef struct {
u16 sport;
u16 dport;
u16 len;
u16 checksum;
} t_ip_udp_header_raw;
typedef struct {
unsigned short sport;
unsigned short dport;
unsigned short len;
unsigned short checksum;
} t_ip_udp_header;
/******************************** IP *************************/
typedef struct {
u8 versionihl;
u8 tos;
u16 len;
u16 id;
u16 flagsoffset;
u8 ttl;
u8 protocol;
u16 checksum;
u32 src;
u32 dst;
/* options */
} t_ip_header_raw;
typedef struct {
unsigned char version;
unsigned char ihl;
unsigned char tos;
unsigned short len;
unsigned short id;
unsigned char flags;
#define IP_DF 0x02 /* 1 == Don't fragment */
#define IP_MF 0x01 /* 1 == More fragments */
unsigned short offset;
unsigned char ttl;
unsigned char protocol;
unsigned short checksum;
unsigned int src;
unsigned int dst;
/* options */
} t_ip_header;
/******************************* ETHERNET *****************************/
typedef struct {
u8 dst[6]; /* Ethernet hardware address */
u8 src[6]; /* Ethernet hardware address */
u16 type; /* Ethernet_II: protocol type */
/* FIXME: Ethernet [802.2|802.3|SNAP]: maybe something else (eg. length) */
} t_ether_raw;
/************************************************************************/
/************************* CONNECTION FUNCTIONS *************************/
static t_bnpcap_conn * bnpcap_conn_new(t_bnpcap_addr const *s, t_bnpcap_addr const *d)
{
t_bnpcap_conn * c;
c = (t_bnpcap_conn *)xmalloc(sizeof(t_bnpcap_conn)); /* avoid warning */
if (!c) {
eventlog(eventlog_level_error, __FUNCTION__, "xalloc failed: %s", std::strerror(errno));
return NULL;
}
if (d->port == listen_port || d->port == 6200) { /* FIXME: That's dirty: We assume the server is on port 6112 */
std::memcpy(&c->client, s, sizeof(t_bnpcap_addr));
std::memcpy(&c->server, d, sizeof(t_bnpcap_addr));
}
else {
std::memcpy(&c->client, d, sizeof(t_bnpcap_addr));
std::memcpy(&c->server, s, sizeof(t_bnpcap_addr));
}
c->cclass = packet_class_init;
c->packets = list_create();
c->incomplete = 0;
c->tcpstate = tcp_state_none;
c->clientoff = 0;
c->clientpkt = NULL;
c->serveroff = 0;
c->serverpkt = NULL;
return c;
}
static void bnpcap_conn_set_class(t_bnpcap_conn *c, t_packet_class cclass)
{
c->cclass = cclass;
}
static t_packet_class bnpcap_conn_get_class(t_bnpcap_conn *c)
{
return c->cclass;
}
static t_bnpcap_conn * bnpcap_conn_find(t_bnpcap_addr const *s, t_bnpcap_addr const *d)
{
t_elem * curr;
LIST_TRAVERSE(conns, curr) {
t_bnpcap_conn *c;
c = (t_bnpcap_conn*)elem_get_data(curr);
if (((c->client.ip == s->ip) && (c->client.port == s->port)) &&
((c->server.ip == d->ip) && (c->server.port == d->port))) {
return c;
}
else if (((c->client.ip == d->ip) && (c->client.port == d->port)) &&
((c->server.ip == s->ip) && (c->server.port == s->port))) {
return c;
}
}
return NULL;
}
static t_packet_dir bnpcap_conn_get_dir(t_bnpcap_conn const * c, t_bnpcap_addr const *s, t_bnpcap_addr const *d)
{
if (((c->client.ip == s->ip) && (c->client.port == s->port)) &&
((c->server.ip == d->ip) && (c->server.port == d->port)))
return packet_dir_from_client;
else
return packet_dir_from_server;
}
static int bnpcap_conn_add_packet(t_bnpcap_conn *c, t_bnpcap_packet *bp) {
eventlog(eventlog_level_debug, __FUNCTION__, "id=%u ", bp->id);
list_append_data(c->packets, bp);
packet_add_ref(bp->p);
return 0;
}
static int bnpcap_conn_packet(unsigned int sip, unsigned short sport, unsigned int dip, unsigned short dport, unsigned char const * data, unsigned int len)
{
t_bnpcap_addr s;
t_bnpcap_addr d;
t_bnpcap_conn *c;
t_bnpcap_packet *bp;
s.ip = sip;
s.port = sport;
d.ip = dip;
d.port = dport;
if ((c = bnpcap_conn_find(&s, &d))) {
eventlog(eventlog_level_debug, __FUNCTION__, "adding packet to existing connection");
if (c->tcpstate == tcp_state_ack) {
c->tcpstate = tcp_state_ok;
}
else if (c->tcpstate == tcp_state_syn) {
c->incomplete = 1; /* ACK missing */
c->tcpstate = tcp_state_ok;
}
}
else {
eventlog(eventlog_level_debug, __FUNCTION__, "adding packet to incomplete connection");
c = bnpcap_conn_new(&s, &d);
bnpcap_conn_set_class(c, packet_class_raw); /* we don't know the init sequence */
c->incomplete = 1;
c->tcpstate = tcp_state_ok;
list_append_data(conns, c);
}
if (c->tcpstate != tcp_state_ok) {
eventlog(eventlog_level_warn, __FUNCTION__, "connection got packet in wrong state!");
}
if (bnpcap_conn_get_class(c) == packet_class_init) {
if (len > 1) {
eventlog(eventlog_level_warn, __FUNCTION__, "init packet larger than 1 byte");
}
switch (data[0]) {
case CLIENT_INITCONN_CLASS_BNET:
bnpcap_conn_set_class(c, packet_class_bnet);
break;
case CLIENT_INITCONN_CLASS_FILE:
bnpcap_conn_set_class(c, packet_class_file);
break;
case 0xf7: // W3 matchmaking hack
eventlog(eventlog_level_info, __FUNCTION__, "matchmaking packet");
bnpcap_conn_set_class(c, packet_class_bnet);
break;
default:
bnpcap_conn_set_class(c, packet_class_raw);
}
}
else {
t_packet *p;
unsigned int off;
unsigned char const *datap = data;
int always_complete = 0;
if (bnpcap_conn_get_class(c) == packet_class_raw)
always_complete = 1; /* There is no size field */
if (bnpcap_conn_get_class(c) == packet_class_file)
always_complete = 1; /* Size field isn't always there */
if (always_complete) {
/* packet is always complete */
eventlog(eventlog_level_debug, __FUNCTION__, "packet is always complete (class=%d)", bnpcap_conn_get_class(c));
bp = (t_bnpcap_packet *)xmalloc(sizeof(t_bnpcap_packet)); /* avoid warning */
if (!bp) {
eventlog(eventlog_level_error, __FUNCTION__, "xalloc failed: %s", std::strerror(errno));
return -1;
}
bp->dir = bnpcap_conn_get_dir(c, &s, &d);
bp->p = packet_create(bnpcap_conn_get_class(c));
bp->id = current_packet_id++;
if (!bp->p) {
eventlog(eventlog_level_error, __FUNCTION__, "packet_create failed");
return -1;
}
std::memcpy(&bp->tv, &packettime, sizeof(struct timeval));
packet_set_size(bp->p, len);
std::memcpy(packet_get_raw_data(bp->p, 0), data, len);
bnpcap_conn_add_packet(c, bp);
if ((packet_get_class(bp->p) == packet_class_file) && (packet_get_type(bp->p) == SERVER_FILE_REPLY)) {
eventlog(eventlog_level_debug, __FUNCTION__, "file transfer initiated (setting to raw)");
bnpcap_conn_set_class(c, packet_class_raw);
}
}
else {
/* read out saved state */
if (bnpcap_conn_get_dir(c, &s, &d) == packet_dir_from_client) {
p = c->clientpkt;
off = c->clientoff;
}
else {
p = c->serverpkt;
off = c->serveroff;
}
while ((datap - data) < (signed)len) {
if (!p) {
eventlog(eventlog_level_debug, __FUNCTION__, "creating new packet");
p = packet_create(bnpcap_conn_get_class(c));
if (!p) {
eventlog(eventlog_level_error, __FUNCTION__, "packet_create failed");
return -1;
}
packet_set_size(p, packet_get_header_size(p)); /* set it to the minimum for now */
off = 0;
}
if (off < packet_get_header_size(p)) {
unsigned int l = (packet_get_header_size(p) - off);
/* (len-(datap-data)) : remaining bytes in buffer */
if ((len - (datap - data)) < l)
l = (len - (datap - data));
eventlog(eventlog_level_debug, __FUNCTION__, "filling up header (adding %d to %d to get %d)", l, off, packet_get_header_size(p));
std::memcpy(packet_get_raw_data(p, off), datap, l);
datap = datap + l;
off = off + l;
}
else {
unsigned int l = (packet_get_size(p) - off);
if ((len - (datap - data)) < l)
l = (len - (datap - data));
eventlog(eventlog_level_debug, __FUNCTION__, "filling up packet (0x%04x:%s) (adding %d to %d to get %d)", packet_get_type(p), packet_get_type_str(p, bnpcap_conn_get_dir(c, &s, &d)), l, off, packet_get_size(p));
std::memcpy(packet_get_raw_data(p, off), datap, l);
datap = datap + l;
off = off + l;
}
if ((off >= packet_get_header_size(p)) && (off >= packet_get_size(p))) {
/* packet is complete */
eventlog(eventlog_level_debug, __FUNCTION__, "packet is complete");
bp = (t_bnpcap_packet *)xmalloc(sizeof(t_bnpcap_packet)); /* avoid warning */
if (!bp) {
eventlog(eventlog_level_error, __FUNCTION__, "xalloc failed: %s", std::strerror(errno));
return -1;
}
if ((off != packet_get_size(p)) && (bnpcap_dodebug)) {
eventlog(eventlog_level_warn, __FUNCTION__, "packet size differs (%d != %d) (offset=0x%04lx)", off, packet_get_size(p), datap - data);
hexdump(stderr, data, len);
/* std::memcpy(packet_get_raw_data(p,0),data,packet_get_size(p)); */
}
bp->dir = bnpcap_conn_get_dir(c, &s, &d);
bp->p = p;
bp->id = current_packet_id++;
std::memcpy(&bp->tv, &packettime, sizeof(struct timeval));
bnpcap_conn_add_packet(c, bp);
if (packet_get_size(p) == 0)
datap = data + len; /* if size is invalid, drop the rest of the stream packet */
p = NULL;
off = 0;
}
} /* while */
/* write back saved state */
if ((off > 0) && (bnpcap_dodebug)) {
eventlog(eventlog_level_debug, __FUNCTION__, "saving %d bytes in packet buffer (p=0x%08lx)", off, (long)p);
}
if (bnpcap_conn_get_dir(c, &s, &d) == packet_dir_from_client) {
c->clientpkt = p;
c->clientoff = off;
}
else {
c->serverpkt = p;
c->serveroff = off;
}
} /* !always_complete */
return 0;
}
return 0;
}
/************************************************************************/
/******************************** LAYERS ********************************/
/********************************* TCP **********************************/
static int bnpcap_tcp2tcp(t_tcp_header * d, t_tcp_header_raw const * s)
{
d->sport = htons(s->sport);
d->dport = htons(s->dport);
d->seqno = htonl(s->seqno);
d->ackno = htonl(s->ackno);
d->doffset = (htons(s->stuff) & 0xF000) >> 12;
d->flags = (htons(s->stuff) & 0x0FFF);
d->window = htons(s->window);
d->checksum = htons(s->checksum);
d->urgp = htons(s->urgp);
return 0;
}
static int bnpcap_process_tcp(t_ip_header const * ip, unsigned char const *data, unsigned int len)
{
t_tcp_header_raw const *raw;
t_tcp_header h;
raw = (t_tcp_header_raw const *)data; /* avoid warning */
bnpcap_tcp2tcp(&h, raw);
if (h.doffset < 5) {
eventlog(eventlog_level_warn, __FUNCTION__, "tcp header too small (%u 32-bit words)", h.doffset);
return 1;
}
else {
char fstr[32] = "";
if (h.flags & TCP_URG)
std::strcat(fstr, "U");
if (h.flags & TCP_ACK)
std::strcat(fstr, "A");
if (h.flags & TCP_PSH)
std::strcat(fstr, "P");
if (h.flags & TCP_RST)
std::strcat(fstr, "R");
if (h.flags & TCP_SYN)
std::strcat(fstr, "S");
if (h.flags & TCP_FIN)
std::strcat(fstr, "F");
eventlog(eventlog_level_debug, __FUNCTION__, "tcp: sport=%u dport=%u seqno=0x%08x ackno=0x%08x window=0x%08x len=%d (%s)", h.sport, h.dport, h.seqno, h.ackno, h.window, ((signed)len - (h.doffset * 4)), fstr);
if (((signed)len - (h.doffset * 4)) <= 0) {
eventlog(eventlog_level_info, __FUNCTION__, "empty packet (%d)", ((signed)len - (h.doffset * 4)));
/* handle sync packets */
if (h.flags & TCP_SYN) {
t_bnpcap_addr s, d;
s.ip = ip->src; s.port = h.sport;
d.ip = ip->dst; d.port = h.dport;
if (h.flags & TCP_ACK) {
t_bnpcap_conn *c = bnpcap_conn_find(&s, &d);
if (c) {
if (c->tcpstate == tcp_state_syn)
c->tcpstate = tcp_state_ack;
}
}
else {
if (!bnpcap_conn_find(&s, &d)) {
t_bnpcap_conn *c;
c = bnpcap_conn_new(&s, &d);
c->tcpstate = tcp_state_syn;
list_append_data(conns, c);
eventlog(eventlog_level_debug, __FUNCTION__, "created new connection with SYN");
}
else {
eventlog(eventlog_level_debug, __FUNCTION__, "got SYN in connection");
}
}
}
}
else if (((h.sport != listen_port) && (h.dport != listen_port)) && ((h.sport != 6200) && (h.dport != 6200))) {
eventlog(eventlog_level_info, __FUNCTION__, "other packet (%d)", ((signed)len - (h.doffset * 4)));
}
else {
eventlog(eventlog_level_info, __FUNCTION__, "valid packet (%d)", ((signed)len - (h.doffset * 4)));
bnpcap_conn_packet(ip->src, h.sport, ip->dst, h.dport, data + (h.doffset * 4), len - (h.doffset * 4));
}
return 0;
}
}
/************************************ UDP ********************************/
static int bnpcap_udp2udp(t_ip_udp_header *d, t_ip_udp_header_raw const *s)
{
d->sport = ntohs(s->sport);
d->dport = ntohs(s->dport);
d->len = ntohs(s->len);
d->checksum = ntohs(s->checksum);
return 0;
}
static int bnpcap_process_udp(unsigned char const *data, unsigned int len)
{
t_ip_udp_header_raw const *raw;
t_ip_udp_header h;
t_bnpcap_packet *bp;
raw = (t_ip_udp_header_raw const *)data; /* avoid warning */
bnpcap_udp2udp(&h, raw);
bp = (t_bnpcap_packet *)xmalloc(sizeof(t_bnpcap_packet)); /* avoid warning */
if (!bp) {
eventlog(eventlog_level_error, __FUNCTION__, "xalloc failed: %s", std::strerror(errno));
return -1;
}
if (h.dport == listen_port || h.dport == 6200) {
bp->dir = packet_dir_from_client;
}
else {
bp->dir = packet_dir_from_server;
}
eventlog(eventlog_level_debug, __FUNCTION__, "sport=%u dport=%u len=%u(%d)", h.sport, h.dport, h.len, len);
bp->id = current_packet_id++;
std::memcpy(&bp->tv, &packettime, sizeof(struct timeval));
bp->p = packet_create(packet_class_udp);
if (!bp->p) {
eventlog(eventlog_level_error, __FUNCTION__, "packet_create failed");
return -1;
}
packet_set_size(bp->p, h.len - sizeof(t_ip_udp_header_raw));
std::memcpy(packet_get_raw_data(bp->p, 0), data + sizeof(t_ip_udp_header_raw), h.len - sizeof(t_ip_udp_header_raw));
eventlog(eventlog_level_error, __FUNCTION__, "id=%u ", bp->id);
list_append_data(udppackets, bp);
return 0;
}
/************************************ IP *********************************/
static int bnpcap_ip2ip(t_ip_header * d, t_ip_header_raw const * s)
{
d->version = ((s->versionihl & 0xf0) >> 4);
d->ihl = s->versionihl & 0x0f;
d->tos = s->tos;
d->len = ntohs(s->len);
d->id = ntohs(s->id);
d->offset = ntohl(s->flagsoffset);
d->flags = ((d->offset & 0xE000) >> 13);
d->offset = ((d->offset & 0x1FFF));
d->ttl = s->ttl;
d->protocol = s->protocol;
d->checksum = ntohs(s->checksum);
d->src = ntohl(s->src);
d->dst = ntohl(s->dst);
return 0;
}
static int bnpcap_process_ip(unsigned char const *data, unsigned int len)
{
/* FIXME: handle IP fragmentation */
/* FIXME: use identification field to pass the datagram in the right order */
t_ip_header_raw const *raw;
t_ip_header h;
raw = (t_ip_header_raw const *)data; /* avoid warning */
bnpcap_ip2ip(&h, raw);
if (h.version != 4) {
eventlog(eventlog_level_warn, __FUNCTION__, "ip version %u not supported (ihl=%u, raw=0x%02x)", h.version, h.ihl, raw->versionihl);
return 1;
}
else if (h.ihl < 5) {
/* an IP header must be at least 5 words */
eventlog(eventlog_level_warn, __FUNCTION__, "ip header to small (%u 32-bit words)", h.ihl);
return 1;
}
else if (h.len > len) {
eventlog(eventlog_level_warn, __FUNCTION__, "ip len larger than packet (%d > %d)", h.len, len);
return 1;
}
else {
char fstr[32] = "";
if (h.flags & IP_DF)
std::strcat(fstr, "D");
if (h.flags & IP_MF)
std::strcat(fstr, "M");
eventlog(eventlog_level_debug, __FUNCTION__, "ip: len=%u(%u) src=%08x dst=%08x protocol=%u offset=0x%08x id=0x%08x (%s)", h.len, len, h.src, h.dst, h.protocol, h.offset, h.id, fstr);
if (h.protocol == 6) {
/* This is TCP */
return bnpcap_process_tcp(&h, data + (h.ihl * 4), h.len - (h.ihl * 4));
}
else if (h.protocol == 17) {
/* This is UDP */
return bnpcap_process_udp(data + (h.ihl * 4), h.len - (h.ihl * 4));
}
}
return 0;
}
/************************************* ETHERNET ******************************/
static int bnpcap_process_ether(unsigned char const *data, unsigned int len)
{ /* Well, first parse the ethernet header (I hope you use Ethernet_II :) ... */
t_ether_raw const *raw;
raw = (t_ether_raw const *)data; /* avoid warning */
if (ntohs(raw->type) == 0x0800) {
/* This is IP */
return bnpcap_process_ip(data + sizeof(t_ether_raw), len - sizeof(t_ether_raw));
}
else {
eventlog(eventlog_level_warn, __FUNCTION__, "unsupported protocol 0x%04x", ntohs(raw->type));
return 1;
}
}
/* If you want to use other hardware protocols like PPP add them here ... */
/**************************** PACKET/PCAP *********************************/
static void bnpcap_process_packet(u_char * private_, const struct pcap_pkthdr * p, u_char const * data)
{
unsigned int pl = p->len;
if (private_) private_ = NULL; // hack to eliminate compiler warning
std::memcpy(&packettime, &p->ts, sizeof(struct timeval));
eventlog(eventlog_level_debug, __FUNCTION__, "packet: len=%d caplen=%d", p->len, p->caplen);
/* FIXME: check if it's ethernet */
bnpcap_process_ether(data, pl);
}
/**************************************************************************/
static void bnpcap_usage(void) {
std::printf("BNPCAP - A tool to convert pcap battle.net dumps to a human-readable format.\n");
std::printf("Version " PVPGN_VERSION " --- Copyright (c) 2001 Marco Ziech (mmz@gmx.net)\n");
std::printf("This software makes use of libpcap.\n\n");
std::printf("Usage: bnpcap [-d] [-v] [-p PORT] <pcap-filename>\n");
std::printf(" -d Print out debugging information\n");
std::printf(" -v Be more verbose\n");
std::printf(" -p PORT Specify port to process (Default: 6112)\n\n");
}
/******************************* MAIN *************************************/
int main(int argc, char **argv) {
t_elem * currconn;
t_elem * currudp;
int c;
while ((c = getopt(argc, argv, "dvp:")) != -1) {
switch (c) {
case 'p':
str_to_uint(optarg, &listen_port);
break;
case 'd':
bnpcap_dodebug = 1;
break;
case 'v':
bnpcap_beverbose = 1;
break;
case '?':
std::printf("unrecognized option '%c'\n", optopt);
break;
default:
std::printf("getopt returned \'%c\'\n", c);
}
}
if (optind < argc) {
filename = argv[optind];
}
else {
bnpcap_usage();
return 1;
}
pc = pcap_open_offline(filename, ebuf);
if (!pc) {
std::fprintf(stderr, "pcap_open_offline: %s\n", ebuf);
return -1;
}
eventlog_set(stderr);
eventlog_clear_level();
if (bnpcap_dodebug)
eventlog_add_level("debug");
if (bnpcap_beverbose || bnpcap_dodebug)
eventlog_add_level("info");
eventlog_add_level("warn");
eventlog_add_level("error");
eventlog_add_level("fatal");
conns = list_create();
udppackets = list_create();
pcap_dispatch(pc, 0, bnpcap_process_packet, NULL);
std::printf("### This packet dump was created by bnpcap.\n");
LIST_TRAVERSE(conns, currconn) {
t_bnpcap_conn *c;
char cstr[64];
char sstr[64];
t_elem * currpacket;
c = (t_bnpcap_conn*)elem_get_data(currconn);
snprintf(cstr, 64, "%u.%u.%u.%u:%u", ((c->client.ip & 0xFF000000) >> 24), ((c->client.ip & 0x00FF0000) >> 16), ((c->client.ip & 0x0000FF00) >> 8), ((c->client.ip & 0x000000FF)), c->client.port);
snprintf(sstr, 64, "%u.%u.%u.%u:%u", ((c->server.ip & 0xFF000000) >> 24), ((c->server.ip & 0x00FF0000) >> 16), ((c->server.ip & 0x0000FF00) >> 8), ((c->server.ip & 0x000000FF)), c->server.port);
std::printf("## %s connection: client=%s server=%s\n", (c->incomplete ? "incomplete" : "complete"), cstr, sstr);
LIST_TRAVERSE(c->packets, currpacket) {
t_bnpcap_packet * bp;
bp = (t_bnpcap_packet*)elem_get_data(currpacket);
std::printf("# %u packet from %s: type=0x%04x(%s) length=%d class=%s\n", bp->id/*bp->tv.tv_sec*/, (bp->dir == packet_dir_from_client ? "client" : "server"), packet_get_type(bp->p), packet_get_type_str(bp->p, bp->dir), packet_get_size(bp->p), packet_get_class_str(bp->p));
hexdump(stdout, packet_get_raw_data(bp->p, 0), packet_get_size(bp->p));
std::printf("\n");
}
}
std::printf("## udp packets\n");
LIST_TRAVERSE(udppackets, currudp) {
t_bnpcap_packet *bp;
bp = (t_bnpcap_packet*)elem_get_data(currudp);
std::printf("# %u packet from %s: type=0x%04x(%s) length=%d class=%s\n", bp->id/*bp->tv.tv_sec*/, (bp->dir == packet_dir_from_client ? "client" : "server"), packet_get_type(bp->p), packet_get_type_str(bp->p, bp->dir), packet_get_size(bp->p), packet_get_class_str(bp->p));
hexdump(stdout, packet_get_raw_data(bp->p, 0), packet_get_size(bp->p));
std::printf("\n");
}
pcap_close(pc);
return 0;
}

View file

@ -416,9 +416,6 @@
# define HAVE_SYS_FILE_H 1
#endif
/* Define if you have the <sys/ioctl.h> header file. */
/* #undef HAVE_SYS_IOCTL_H */
/* Define if you have the <sys/mman.h> header file. */
/* #undef HAVE_SYS_MMAN_H */
@ -445,9 +442,6 @@
/* Define if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define if you have the <sys/stropts.h> header file. */
/* #undef HAVE_SYS_STROPTS_H */
/* Define if you have the <sys/time.h> header file. */
/* #undef HAVE_SYS_TIME_H */ /* MinGW has this header, but confilcts with compat/gettimeofday.h */