diff options
| author | lijia <[email protected]> | 2024-10-18 16:47:51 +0800 |
|---|---|---|
| committer | lijia <[email protected]> | 2024-11-07 18:30:58 +0800 |
| commit | e734af76d81b07090c618b1c4af3b2fdd6b592f3 (patch) | |
| tree | c9b894fb0eaa9c56bd5f04bfab5628a97592091d /tools | |
| parent | 99a68d5c9efe500ab339165a2af515a0a7355ada (diff) | |
rebase onto develop-2.0
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | tools/monitor/CMakeLists.txt | 19 | ||||
| -rw-r--r-- | tools/monitor/monitor_cli.c | 557 | ||||
| -rwxr-xr-x | tools/monitor/stellar-dump-update.sh | 12 | ||||
| -rw-r--r-- | tools/monitor/stellar-dump.patch | 11400 |
5 files changed, 11989 insertions, 0 deletions
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt new file mode 100644 index 0000000..0b17171 --- /dev/null +++ b/tools/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(monitor) diff --git a/tools/monitor/CMakeLists.txt b/tools/monitor/CMakeLists.txt new file mode 100644 index 0000000..768dbff --- /dev/null +++ b/tools/monitor/CMakeLists.txt @@ -0,0 +1,19 @@ +#like redis-cli, use hyphen('-') not underscore('_') +add_executable(stellar-cli monitor_cli.c) +target_link_libraries(stellar-cli libevent-static cjson-static linenoise sds ringbuf monitor) +install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/stellar-cli DESTINATION ${CMAKE_INSTALL_PREFIX}/bin/ COMPONENT EXECUTABLE) + +# add_subdirectory(stellar-dump) + +#tcpdump patch +set (STELLAR-DUMP-PATCH-FILE ${CMAKE_SOURCE_DIR}/tools/monitor/stellar-dump.patch) +set (STELLAR-DUMP-PATCH-CMD ${CMAKE_SOURCE_DIR}/tools/monitor/stellar-dump-update.sh) +ExternalProject_Add(tcpdump PREFIX tcpdump + URL ${CMAKE_SOURCE_DIR}/vendors/tcpdump-4.99.4.tar.gz + URL_MD5 4f2d4a8a5fab017e5ebda156bfc86378 + PATCH_COMMAND sh -c "chmod +x ${STELLAR-DUMP-PATCH-CMD} && ${STELLAR-DUMP-PATCH-CMD} ${CMAKE_CURRENT_BINARY_DIR}/tcpdump/src/tcpdump ${STELLAR-DUMP-PATCH-FILE}" + CMAKE_ARGS -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DWITH_CRYPTO=OFF -DSTELLAR_SOURCE_DIR=${CMAKE_SOURCE_DIR} -DSTELLAR_BINARY_DIR=${CMAKE_BINARY_DIR} -DASAN_OPTION=${ASAN_OPTION} + ) +add_dependencies(tcpdump libevent) +ExternalProject_Get_Property(tcpdump INSTALL_DIR) +install(PROGRAMS ${INSTALL_DIR}/src/tcpdump-build/stellar-dump DESTINATION ${CMAKE_INSTALL_PREFIX}/bin/ COMPONENT EXECUTABLE) diff --git a/tools/monitor/monitor_cli.c b/tools/monitor/monitor_cli.c new file mode 100644 index 0000000..c16447b --- /dev/null +++ b/tools/monitor/monitor_cli.c @@ -0,0 +1,557 @@ +#include <arpa/inet.h> +#include <assert.h> +#include <evhttp.h> +#include <getopt.h> +#include <signal.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include "stellar/monitor.h" +#include "linenoise/linenoise.h" +#include "monitor_cmd_assistant.h" +#include "monitor_private.h" +#include "monitor/monitor_utils.h" + +static char g_stellar_cli_prompt[128]; /* prompt pattern: cli@ip:port> */ +static const char *g_stellar_monitor_history_file = ".stellar_cli_history.txt"; +static const char *g_stellar_monitor_version = "stellar-cli v1.0"; +static int g_stm_cli_noninteractive = 0; +static const char *g_stm_cli_noninteractive_cmd_line = NULL; +static const char *g_stm_cli_ipaddr_str = STM_SERVER_LISTEN_IP; +static unsigned short g_stm_cli_port_host = STM_SERVER_LISTEN_PORT; +static struct libevent_http_client *g_evh_client; +static struct stm_cmd_assistant *g_stm_cli_aide; +static int g_stm_cli_connect_timeout = STM_REQUEST_TIMEOUT; + +static struct monitor_cli_args g_cli_args[4] = { + {"-i", "--ip", 1, 0, NULL}, + {"-p", "--port", 1, 0, NULL}, + {"-t", "--timeout", 1, 0, NULL}, + {"-e", "--exec", 1, 1, NULL}, +}; + +struct stm_cmd_parser +{ + sds raw_cmd_line; // need be free + int argc; + sds *argv; +}; + +struct stm_builtin_cmd_compose +{ + const char *cmd_name; + monitor_cmd_cb *cmd_cb; + const char *description; +}; + +struct libevent_http_client +{ + struct event_base *base; + struct evhttp_connection *conn; + struct evhttp_request *req; + enum stm_http_response_code response_code; + char *response_cstr; +}; + +static int (*g_response_handler)(struct libevent_http_client *evh_client); + +static void cli_evhttp_free(void) +{ + evhttp_connection_free(g_evh_client->conn); + event_base_free(g_evh_client->base); + FREE(g_evh_client); +} + +static void stm_cli_args_free(struct stm_cmd_parser *cmd_args) +{ + if (NULL != cmd_args) + { + sdsfree(cmd_args->raw_cmd_line); + sdsfreesplitres(cmd_args->argv, cmd_args->argc); + FREE(cmd_args); + } +} + +static struct monitor_reply *stm_cli_builtin_exit(UNUSED struct stellar_monitor *monitor, UNUSED int argc, UNUSED char *argv[], void *arg) +{ + for (size_t i = 0; i < sizeof(g_cli_args) / sizeof(struct monitor_cli_args); i++) + { + sdsfree(g_cli_args[i].value); + } + stm_cli_args_free((struct stm_cmd_parser *)arg); + stm_cmd_assistant_free(g_stm_cli_aide); + cli_evhttp_free(); + exit(0); + return NULL; +} + +static void signal_handler(int signo) +{ + if (signo == SIGINT) + { + stm_cli_builtin_exit(NULL, 0, NULL, NULL); + } +} + +static struct monitor_reply *stm_cli_builtin_clear(UNUSED struct stellar_monitor *monitor, UNUSED int argc, UNUSED char *argv[], UNUSED void *arg) +{ + linenoiseClearScreen(); + return NULL; +} + +static struct stm_builtin_cmd_compose g_stm_cli_builtin_commands[] = { + {"q", stm_cli_builtin_exit, "cause the shell to exit"}, + {"quit", stm_cli_builtin_exit, "cause the shell to exit"}, + {"exit", stm_cli_builtin_exit, "cause the shell to exit"}, + {"clear", stm_cli_builtin_clear, "clear the terminal screen"}, + {NULL, NULL, NULL}}; + +static void evhttp_conn_close_cb(UNUSED struct evhttp_connection *conn, UNUSED void *arg) +{ + snprintf(g_stellar_cli_prompt, sizeof(g_stellar_cli_prompt), "not connected>"); +} + +static void evhttp_request_error_cb(enum evhttp_request_error errnum, void *arg) +{ + (void)arg; + switch (errnum) + { + case EVREQ_HTTP_TIMEOUT: + g_evh_client->response_code = STM_HTTP_408_REQUEST_TIMEOUT; + break; + case EVREQ_HTTP_INVALID_HEADER: + g_evh_client->response_code = STM_HTTP_403_FORBIDDEN; + break; + case EVREQ_HTTP_DATA_TOO_LONG: + g_evh_client->response_code = STM_HTTP_413_PAYLOAD_TOO_LARGE; + break; + case EVREQ_HTTP_EOF: + break; + default: + break; + } +} + +static void evhttp_response_cb(struct evhttp_request *req, void *arg) +{ + (void)arg; + if (req == NULL) + { + return; + } + struct evbuffer *input_buffer = evhttp_request_get_input_buffer(req); + size_t evbuf_len = evbuffer_get_length(input_buffer); + if (NULL == input_buffer || 0 == evbuf_len) + { + return; + } + g_evh_client->response_cstr = (char *)calloc(1, evbuf_len + 1); + evbuffer_remove(input_buffer, g_evh_client->response_cstr, evbuf_len); + g_evh_client->response_code = STM_HTTP_200_OK; + // terminate event_base_dispatch() + event_base_loopbreak(g_evh_client->base); +} + +static struct libevent_http_client *evhttp_client_new(const char *server_ip, unsigned short server_port) +{ + struct libevent_http_client *evh_client = + (struct libevent_http_client *)calloc(1, sizeof(struct libevent_http_client)); + + evh_client->base = event_base_new(); + evh_client->conn = evhttp_connection_base_new(evh_client->base, NULL, + server_ip, server_port); + evhttp_connection_set_timeout(evh_client->conn, g_stm_cli_connect_timeout); + return evh_client; +} + +static int evhttp_client_request_new(struct libevent_http_client *evh_client) +{ + evh_client->req = evhttp_request_new(evhttp_response_cb, evh_client); + evhttp_request_set_error_cb(evh_client->req, evhttp_request_error_cb); + evhttp_connection_set_closecb(evh_client->conn, evhttp_conn_close_cb, evh_client->req); + evh_client->response_cstr = NULL; + evh_client->response_code = STM_HTTP_204_NO_CONTENT; + return 0; +} + +static void evhttp_client_add_header(struct libevent_http_client *evh_client, const char *key, const char *value) +{ + struct evkeyvalq *output_headers = evhttp_request_get_output_headers(evh_client->req); + evhttp_add_header(output_headers, key, value); +} + +static void evhttp_client_add_uri(struct libevent_http_client *evh_client, + enum evhttp_cmd_type type, const char *uri) +{ + evhttp_make_request(evh_client->conn, evh_client->req, type, uri); +} + +static int default_response_handler(struct libevent_http_client *evh_client) +{ + if (evh_client->response_code != STM_HTTP_200_OK || evh_client->response_cstr == NULL) + { + snprintf(g_stellar_cli_prompt, sizeof(g_stellar_cli_prompt), "not connected>"); + fprintf(stderr, "ERR failed to connect to %s:%u\n", + g_stm_cli_ipaddr_str, g_stm_cli_port_host); + return -1; + } + + printf("%s", evh_client->response_cstr); + fflush(stdout); + FREE(evh_client->response_cstr); + snprintf(g_stellar_cli_prompt, sizeof(g_stellar_cli_prompt), + "cli@%s:%u>", g_stm_cli_ipaddr_str, g_stm_cli_port_host); + return 0; +} + +static int command_json_parse_handler(struct libevent_http_client *evh_client) +{ + if (evh_client->response_code != STM_HTTP_200_OK || evh_client->response_cstr == NULL) + { + snprintf(g_stellar_cli_prompt, sizeof(g_stellar_cli_prompt), "not connected>"); + fprintf(stderr, "ERR failed to connect to %s:%u\n", + g_stm_cli_ipaddr_str, g_stm_cli_port_host); + return -1; + } + if (stm_cmd_assistant_json_load(g_stm_cli_aide, evh_client->response_cstr) < 0) + { + fprintf(stderr, "ERR failed to synchronize command info with the monitor server\n"); + return -1; + } + FREE(evh_client->response_cstr); + return 0; +} + +static void stm_cli_usage(void) +{ + printf("%s\r\n", g_stellar_monitor_version); + printf("Usage:\r\n"); + printf(" %s [OPTIONS] [ -e command [arg [arg ...]]]\r\n", "stellar-cli"); + printf("\t%s %-6s %s\r\n", "-i", "--ip", "stellar monitor server ip address"); + printf("\t%s %-6s %s\r\n", "-p", "--port", "stellar monitor server port"); + printf("\t%s %-6s %s\r\n", "-e", "--exec", "non-interactive mode, exit after executing command"); + printf("\t%s %-6s %s\r\n", "-t", "--timeout", "maximum time(sec) allowed for connecting to server"); + exit(0); +} + +static int stm_cli_exec_builtin_cmd(struct stm_cmd_parser *cmd_args) +{ + const char *cli_cmd_name = cmd_args->argv[0]; + size_t raw_cmd_len = strlen(cli_cmd_name); + for (int i = 0; g_stm_cli_builtin_commands[i].cmd_name != NULL; i++) + { + if (stm_strncasecmp_exactly(g_stm_cli_builtin_commands[i].cmd_name, + cli_cmd_name, raw_cmd_len) == 0) + { + g_stm_cli_builtin_commands[i].cmd_cb(NULL, cmd_args->argc, cmd_args->argv, (void *)cmd_args); + return 1; + } + } + return 0; +} + +static sds stm_cli_build_RESTful_url(struct stm_cmd_parser *cmd_args) +{ + sds url; + char restful_path[256] = {0}; + snprintf(restful_path, sizeof(restful_path), "/%s/%s", STM_RESTFUL_VERSION, STM_RESTFUL_RESOURCE); + url = sdsempty(); + url = sdscatprintf(url, "%s?%s=", restful_path, STM_RESTFUL_URI_CMD_KEY); + for (int i = 0; i < cmd_args->argc; i++) + { + url = sdscat(url, cmd_args->argv[i]); + if (i < cmd_args->argc - 1) + { + url = sdscat(url, " "); // add blank space + } + } + char *encoded_url_str = stm_http_url_encode(url); + sds encoded_url = sdsnew(encoded_url_str); + sdsfree(url); + free(encoded_url_str); + return encoded_url; +} + +static int stm_cli_evhttp_run_cmd(struct stm_cmd_parser *cmd_args) +{ + evhttp_client_request_new(g_evh_client); + evhttp_client_add_header(g_evh_client, "Connection", "keep-alive"); + evhttp_client_add_header(g_evh_client, "Content-Length", "0"); + sds url = stm_cli_build_RESTful_url(cmd_args); + evhttp_client_add_uri(g_evh_client, EVHTTP_REQ_GET, url); + int ret = event_base_dispatch(g_evh_client->base); + sdsfree(url); + return ret; +} + +/* call remote command use RESTful */ +static int stm_cli_exec_rpc_cmd(UNUSED const char *raw_cmd_line, struct stm_cmd_parser *cmd_args) +{ + int ret = stm_cli_evhttp_run_cmd(cmd_args); + g_response_handler(g_evh_client); + return ret; +} + +static struct stm_cmd_parser *stm_cli_parse_cmd_line(const char *line) +{ + struct stm_cmd_parser *cmd_args = + (struct stm_cmd_parser *)calloc(1, sizeof(struct stm_cmd_parser)); + cmd_args->raw_cmd_line = sdsnew(line); + cmd_args->argv = sdssplitargs(line, &cmd_args->argc); + return cmd_args; +} + +static void stm_cli_exec_cmd(const char *raw_line) +{ + struct stm_cmd_parser *cmd_args = stm_cli_parse_cmd_line(raw_line); + if (stm_cli_exec_builtin_cmd(cmd_args)) + { + goto fun_exit; + } + stm_cli_exec_rpc_cmd(raw_line, cmd_args); + +fun_exit: + stm_cli_args_free(cmd_args); + return; +} + +static int stm_cli_builtin_help(const char *line) +{ + int argc = 0; + int is_help_cmd = 0; + sds *array = sdssplitargs(line, &argc); + + if (argc != 1) + { + sdsfreesplitres(array, argc); + return 0; + } + if ((strcasecmp(array[argc - 1], "help") == 0) || (strcasecmp(array[argc - 1], "--help") == 0) || (strcasecmp(array[argc - 1], "-h") == 0) || (strcasecmp(array[argc - 1], "/?") == 0) || (strcasecmp(array[argc - 1], "?") == 0)) + { + is_help_cmd = 1; + } + if (is_help_cmd == 1) + { + stm_cli_exec_cmd("show command brief"); + } + sdsfreesplitres(array, argc); + return is_help_cmd; +} + +static void stm_cli_register_builtin_cmd(void) +{ + for (int i = 0; g_stm_cli_builtin_commands[i].cmd_name != NULL; i++) + { + stm_cmd_assistant_register_cmd(g_stm_cli_aide, + g_stm_cli_builtin_commands[i].cmd_name, + g_stm_cli_builtin_commands[i].cmd_cb, + NULL, "readonly", "<cr>", + g_stm_cli_builtin_commands[i].description); + } +} + +static void stm_cli_run(void) +{ + char *line; + /* Load history from file. The history file is just a plain text file + * where entries are separated by newlines. */ + linenoiseHistoryLoad(g_stellar_monitor_history_file); /* Load the history at startup */ + /* Non-interactive mode */ + if (g_stm_cli_noninteractive) + { + stm_cli_exec_cmd(g_stm_cli_noninteractive_cmd_line); + exit(0); + } + + /* Synchronize with the monitor server on boot up */ + g_response_handler = command_json_parse_handler; + stm_cli_exec_cmd(STM_CLIENT_SERVER_SYNC_CMD); + g_response_handler = default_response_handler; + + /* register builtin command after synchronization */ + stm_cli_register_builtin_cmd(); + + /* Interactive mode */ + while (1) + { + line = linenoise(g_stellar_cli_prompt); + if (line && strlen(line) > 0) + { + if (stm_cli_builtin_help(line) == 0) + { + stm_cli_exec_cmd(line); + } + fflush(stdout); + linenoiseHistoryAdd(line); + } + FREE(line); + } +} + +static const char *stm_cli_short_options = "he:i:p:t:"; +static const struct option stm_cli_long_options[] = { + {"help", no_argument, NULL, 'h'}, + {"ip", required_argument, NULL, 'i'}, + {"port", required_argument, NULL, 'p'}, + {"exec", required_argument, NULL, 'e'}, + {"timeout", required_argument, NULL, 't'}, +}; + +static int stm_cli_check_args(int argc, char *_argv[]) +{ + int c, ret = 0; + char **argv_tmp = CALLOC(char *, argc + 1); + for (int i = 0; i < argc; i++) + { + argv_tmp[i] = _argv[i]; + } + while (1) + { + c = getopt_long(argc, argv_tmp, stm_cli_short_options, stm_cli_long_options, NULL); + if (c == -1) + { + ret = 0; + break; + } + switch (c) + { + case 'h': + stm_cli_usage(); + break; + case 'i': + case 'p': + case 'e': + case 't': + break; + case '?': /* invalid or unknown option */ + ret = -1; + break; + default: + ret = -1; + break; + } + } + FREE(argv_tmp); + return ret; +} + +static int stm_cli_evhttp_init(void) +{ + g_evh_client = evhttp_client_new(g_stm_cli_ipaddr_str, g_stm_cli_port_host); + assert(g_evh_client != NULL); + return 0; +} + +static void cli_linenoise_completion_cb(const char *line, linenoiseCompletions *lc) +{ + stm_cmd_assistant_input_line(g_stm_cli_aide, line, (void *)lc); +} + +static char *cli_linenoise_hints_cb(const char *line, int *color, int *bold) +{ + char *hints = (char *)stm_cmd_assistant_input_line_for_hints(g_stm_cli_aide, line); + if (NULL == hints) + { + return NULL; + } + sds tmp = sdsnew(" "); // add a blank space before hints, easy to input the next command + tmp = sdscat(tmp, hints); + *color = STM_CLI_CMD_HINTS_COLOR; + *bold = STM_CLI_CMD_HINTS_BOLD; + return tmp; +} + +static void cli_linenoise_free_hints_cb(void *arg) +{ + sdsfree((sds)arg); +} + +void cli_assistant_completion_cb(void *arg, const char *candidate_completion) +{ + linenoiseCompletions *lc = (linenoiseCompletions *)arg; + linenoiseAddCompletion(lc, candidate_completion); +} + +static int stm_assistant_init(void) +{ + g_stm_cli_aide = stm_cmd_assistant_new(); + if (NULL == g_stm_cli_aide) + { + return -1; + } + /* Set the completion callback. This will be called every time the + * user uses the <tab> key. */ + linenoiseSetCompletionCallback(cli_linenoise_completion_cb); + stm_cmd_assistant_set_completion_cb(g_stm_cli_aide, cli_assistant_completion_cb); + linenoiseSetHintsCallback(cli_linenoise_hints_cb); + linenoiseSetFreeHintsCallback(cli_linenoise_free_hints_cb); + return 0; +} + +static int stm_cli_parse_args(int argc, char *argv[]) +{ + if (stm_cli_check_args(argc, argv) < 0) + { + return -1; + } + if (monitor_util_parse_cmd_args(argc, (const char **)argv, g_cli_args, + sizeof(g_cli_args) / sizeof(struct monitor_cli_args)) < 0) + { + return -1; + } + if (g_cli_args[0].value != NULL) + { + g_stm_cli_ipaddr_str = g_cli_args[0].value; + } + int tmp_val; + if (g_cli_args[1].value != NULL) + { + tmp_val = atoi(g_cli_args[1].value); + if (tmp_val <= 0 || tmp_val > 65535) + { + fprintf(stderr, "invalid port: %s\n", g_cli_args[1].value); + return -1; + } + g_stm_cli_port_host = (unsigned short)tmp_val; + } + if (g_cli_args[2].value != NULL) + { + tmp_val = atoi(g_cli_args[2].value); + if (tmp_val <= 0) + { + fprintf(stderr, "invalid timeout: %s\n", g_cli_args[2].value); + return -1; + } + g_stm_cli_connect_timeout = tmp_val; + } + if (g_cli_args[3].value != NULL) + { + g_stm_cli_noninteractive = 1; + g_stm_cli_noninteractive_cmd_line = g_cli_args[3].value; + } + snprintf(g_stellar_cli_prompt, sizeof(g_stellar_cli_prompt), + "cli@%s:%u>", g_stm_cli_ipaddr_str, g_stm_cli_port_host); + return 0; +} + +int main(int argc, char *argv[]) +{ + if (stm_cli_parse_args(argc, argv) < 0) + { + return -1; + } + if (stm_assistant_init() < 0) + { + return -1; + } + if (stm_cli_evhttp_init() < 0) + { + return -1; + } + g_response_handler = default_response_handler; + signal(SIGINT, signal_handler); + stm_cli_run(); + return 0; +} diff --git a/tools/monitor/stellar-dump-update.sh b/tools/monitor/stellar-dump-update.sh new file mode 100755 index 0000000..13ff5b7 --- /dev/null +++ b/tools/monitor/stellar-dump-update.sh @@ -0,0 +1,12 @@ +#!/bin/bash +SOURCE_DIR=$1 +PATCH_FILE=$2 +PATCH_STATUS=`head $SOURCE_DIR/tcpdump.c | grep "PATCH FOR STELLAR-DUMP"` + +if [ -z "$PATCH_STATUS" ] +then + echo "starting patch tcpdump..." + patch -N -p1 -d $SOURCE_DIR -i $PATCH_FILE +else + echo "alread patched, skip... " +fi diff --git a/tools/monitor/stellar-dump.patch b/tools/monitor/stellar-dump.patch new file mode 100644 index 0000000..986149a --- /dev/null +++ b/tools/monitor/stellar-dump.patch @@ -0,0 +1,11400 @@ +diff -uNr tcpdump-tcpdump-4.99.4/addrtoname.c tcpdump-for-stellar/addrtoname.c +--- tcpdump-tcpdump-4.99.4/addrtoname.c 2023-04-08 02:30:58.000000000 +0800 ++++ tcpdump-for-stellar/addrtoname.c 2024-10-30 17:34:05.502498703 +0800 +@@ -1323,8 +1323,8 @@ + { + static char buf[128]; + snprintf(buf, sizeof(buf), "vlan %u, p %u%s", +- tci & 0xfff, +- tci >> 13, ++ (uint16_t)(tci & 0xfff), ++ (uint16_t)(tci >> 13), + (tci & 0x1000) ? ", DEI" : ""); + return buf; + } +diff -uNr tcpdump-tcpdump-4.99.4/addrtostr.c tcpdump-for-stellar/addrtostr.c +--- tcpdump-tcpdump-4.99.4/addrtostr.c 2023-04-08 02:30:58.000000000 +0800 ++++ tcpdump-for-stellar/addrtostr.c 2024-10-30 17:34:05.502498703 +0800 +@@ -51,52 +51,62 @@ + */ + + #ifndef IN6ADDRSZ +-#define IN6ADDRSZ 16 /* IPv6 T_AAAA */ ++#define IN6ADDRSZ 16 /* IPv6 T_AAAA */ + #endif + + #ifndef INT16SZ +-#define INT16SZ 2 /* word size */ ++#define INT16SZ 2 /* word size */ + #endif + ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wall" + const char * +-addrtostr (const void *src, char *dst, size_t size) ++addrtostr(const void *src, char *dst, size_t size) + { +- const u_char *srcaddr = (const u_char *)src; +- const char digits[] = "0123456789"; +- int i; +- const char *orig_dst = dst; +- +- if (size < INET_ADDRSTRLEN) { +- errno = ENOSPC; +- return NULL; +- } +- for (i = 0; i < 4; ++i) { +- int n = *srcaddr++; +- int non_zerop = 0; +- +- if (non_zerop || n / 100 > 0) { +- *dst++ = digits[n / 100]; +- n %= 100; +- non_zerop = 1; +- } +- if (non_zerop || n / 10 > 0) { +- *dst++ = digits[n / 10]; +- n %= 10; +- non_zerop = 1; +- } +- *dst++ = digits[n]; +- if (i != 3) +- *dst++ = '.'; ++ const u_char *srcaddr = (const u_char *)src; ++ const char digits[] = "0123456789"; ++ int i; ++ const char *orig_dst = dst; ++ ++ if (size < INET_ADDRSTRLEN) ++ { ++ errno = ENOSPC; ++ return NULL; ++ } ++ for (i = 0; i < 4; ++i) ++ { ++ int n = *srcaddr++; ++ int non_zerop = 0; ++#if 0 ++ if (non_zerop || n / 100 > 0) ++#else ++ if (n / 100 > 0) //for cppcheck ++#endif ++ { ++ *dst++ = digits[n / 100]; ++ n %= 100; ++ non_zerop = 1; + } +- *dst++ = '\0'; +- return orig_dst; ++ if (non_zerop || n / 10 > 0) ++ { ++ *dst++ = digits[n / 10]; ++ n %= 10; ++ non_zerop = 1; ++ } ++ *dst++ = digits[n]; ++ if (i != 3) ++ *dst++ = '.'; ++ } ++ *dst++ = '\0'; ++ return orig_dst; + } ++#pragma GCC diagnostic pop + + /* + * Convert IPv6 binary address into presentation (printable) format. + */ + const char * +-addrtostr6 (const void *src, char *dst, size_t size) ++addrtostr6(const void *src, char *dst, size_t size) + { + /* + * Note that int32_t and int16_t need only be "at least" large enough +@@ -109,57 +119,60 @@ + char *dp; + size_t space_left, added_space; + int snprintfed; +- struct { ++ struct ++ { + int base; + int len; + } best, cur; +- uint16_t words [IN6ADDRSZ / INT16SZ]; +- int i; ++ uint16_t words[IN6ADDRSZ / INT16SZ]; ++ int i; + + /* Preprocess: + * Copy the input (bytewise) array into a wordwise array. + * Find the longest run of 0x00's in src[] for :: shorthanding. + */ + for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) +- words[i] = (srcaddr[2*i] << 8) | srcaddr[2*i + 1]; ++ words[i] = (srcaddr[2 * i] << 8) | srcaddr[2 * i + 1]; + + best.len = 0; + best.base = -1; + cur.len = 0; +- cur.base = -1; ++ cur.base = -1; + for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) + { + if (words[i] == 0) + { + if (cur.base == -1) +- cur.base = i, cur.len = 1; +- else cur.len++; ++ cur.base = i, cur.len = 1; ++ else ++ cur.len++; + } + else if (cur.base != -1) + { + if (best.base == -1 || cur.len > best.len) +- best = cur; ++ best = cur; + cur.base = -1; + } + } + if ((cur.base != -1) && (best.base == -1 || cur.len > best.len)) +- best = cur; ++ best = cur; + if (best.base != -1 && best.len < 2) +- best.base = -1; ++ best.base = -1; + + /* Format the result. + */ + dp = dst; + space_left = size; +-#define APPEND_CHAR(c) \ +- { \ +- if (space_left == 0) { \ +- errno = ENOSPC; \ +- return (NULL); \ +- } \ +- *dp++ = c; \ +- space_left--; \ +- } ++#define APPEND_CHAR(c) \ ++ { \ ++ if (space_left == 0) \ ++ { \ ++ errno = ENOSPC; \ ++ return (NULL); \ ++ } \ ++ *dp++ = c; \ ++ space_left--; \ ++ } + for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) + { + /* Are we inside the best run of 0x00's? +@@ -167,21 +180,21 @@ + if (best.base != -1 && i >= best.base && i < (best.base + best.len)) + { + if (i == best.base) +- APPEND_CHAR(':'); ++ APPEND_CHAR(':'); + continue; + } + + /* Are we following an initial run of 0x00s or any real hex? + */ + if (i != 0) +- APPEND_CHAR(':'); ++ APPEND_CHAR(':'); + + /* Is this address an encapsulated IPv4? + */ + if (i == 6 && best.base == 0 && + (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) + { +- if (!addrtostr(srcaddr+12, dp, space_left)) ++ if (!addrtostr(srcaddr + 12, dp, space_left)) + { + errno = ENOSPC; + return (NULL); +@@ -191,13 +204,13 @@ + space_left -= added_space; + break; + } +- snprintfed = snprintf (dp, space_left, "%x", words[i]); ++ snprintfed = snprintf(dp, space_left, "%x", words[i]); + if (snprintfed < 0) +- return (NULL); +- if ((size_t) snprintfed >= space_left) ++ return (NULL); ++ if ((size_t)snprintfed >= space_left) + { +- errno = ENOSPC; +- return (NULL); ++ errno = ENOSPC; ++ return (NULL); + } + dp += snprintfed; + space_left -= snprintfed; +@@ -206,7 +219,7 @@ + /* Was it a trailing run of 0x00's? + */ + if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ)) +- APPEND_CHAR(':'); ++ APPEND_CHAR(':'); + APPEND_CHAR('\0'); + + return (dst); +diff -uNr tcpdump-tcpdump-4.99.4/checksum.c tcpdump-for-stellar/checksum.c +--- tcpdump-tcpdump-4.99.4/checksum.c 2023-04-08 02:30:58.000000000 +0800 ++++ tcpdump-for-stellar/checksum.c 2024-10-30 17:34:05.522498702 +0800 +@@ -37,75 +37,73 @@ + + crc_table = [] + for i in range(256): +- accum = i << 2 +- for j in range(8): +- accum <<= 1 +- if accum & 0x400: +- accum ^= 0x633 +- crc_table.append(accum) ++ accum = i << 2 ++ for j in range(8): ++ accum <<= 1 ++ if accum & 0x400: ++ accum ^= 0x633 ++ crc_table.append(accum) + + for i in range(len(crc_table)/8): +- for j in range(8): +- sys.stdout.write("0x%04x, " % crc_table[i*8+j]) +- sys.stdout.write("\n") ++ for j in range(8): ++ sys.stdout.write("0x%04x, " % crc_table[i*8+j]) ++ sys.stdout.write("\n") + + */ + static const uint16_t crc10_table[256] = +-{ +- 0x0000, 0x0233, 0x0255, 0x0066, 0x0299, 0x00aa, 0x00cc, 0x02ff, +- 0x0301, 0x0132, 0x0154, 0x0367, 0x0198, 0x03ab, 0x03cd, 0x01fe, +- 0x0031, 0x0202, 0x0264, 0x0057, 0x02a8, 0x009b, 0x00fd, 0x02ce, +- 0x0330, 0x0103, 0x0165, 0x0356, 0x01a9, 0x039a, 0x03fc, 0x01cf, +- 0x0062, 0x0251, 0x0237, 0x0004, 0x02fb, 0x00c8, 0x00ae, 0x029d, +- 0x0363, 0x0150, 0x0136, 0x0305, 0x01fa, 0x03c9, 0x03af, 0x019c, +- 0x0053, 0x0260, 0x0206, 0x0035, 0x02ca, 0x00f9, 0x009f, 0x02ac, +- 0x0352, 0x0161, 0x0107, 0x0334, 0x01cb, 0x03f8, 0x039e, 0x01ad, +- 0x00c4, 0x02f7, 0x0291, 0x00a2, 0x025d, 0x006e, 0x0008, 0x023b, +- 0x03c5, 0x01f6, 0x0190, 0x03a3, 0x015c, 0x036f, 0x0309, 0x013a, +- 0x00f5, 0x02c6, 0x02a0, 0x0093, 0x026c, 0x005f, 0x0039, 0x020a, +- 0x03f4, 0x01c7, 0x01a1, 0x0392, 0x016d, 0x035e, 0x0338, 0x010b, +- 0x00a6, 0x0295, 0x02f3, 0x00c0, 0x023f, 0x000c, 0x006a, 0x0259, +- 0x03a7, 0x0194, 0x01f2, 0x03c1, 0x013e, 0x030d, 0x036b, 0x0158, +- 0x0097, 0x02a4, 0x02c2, 0x00f1, 0x020e, 0x003d, 0x005b, 0x0268, +- 0x0396, 0x01a5, 0x01c3, 0x03f0, 0x010f, 0x033c, 0x035a, 0x0169, +- 0x0188, 0x03bb, 0x03dd, 0x01ee, 0x0311, 0x0122, 0x0144, 0x0377, +- 0x0289, 0x00ba, 0x00dc, 0x02ef, 0x0010, 0x0223, 0x0245, 0x0076, +- 0x01b9, 0x038a, 0x03ec, 0x01df, 0x0320, 0x0113, 0x0175, 0x0346, +- 0x02b8, 0x008b, 0x00ed, 0x02de, 0x0021, 0x0212, 0x0274, 0x0047, +- 0x01ea, 0x03d9, 0x03bf, 0x018c, 0x0373, 0x0140, 0x0126, 0x0315, +- 0x02eb, 0x00d8, 0x00be, 0x028d, 0x0072, 0x0241, 0x0227, 0x0014, +- 0x01db, 0x03e8, 0x038e, 0x01bd, 0x0342, 0x0171, 0x0117, 0x0324, +- 0x02da, 0x00e9, 0x008f, 0x02bc, 0x0043, 0x0270, 0x0216, 0x0025, +- 0x014c, 0x037f, 0x0319, 0x012a, 0x03d5, 0x01e6, 0x0180, 0x03b3, +- 0x024d, 0x007e, 0x0018, 0x022b, 0x00d4, 0x02e7, 0x0281, 0x00b2, +- 0x017d, 0x034e, 0x0328, 0x011b, 0x03e4, 0x01d7, 0x01b1, 0x0382, +- 0x027c, 0x004f, 0x0029, 0x021a, 0x00e5, 0x02d6, 0x02b0, 0x0083, +- 0x012e, 0x031d, 0x037b, 0x0148, 0x03b7, 0x0184, 0x01e2, 0x03d1, +- 0x022f, 0x001c, 0x007a, 0x0249, 0x00b6, 0x0285, 0x02e3, 0x00d0, +- 0x011f, 0x032c, 0x034a, 0x0179, 0x0386, 0x01b5, 0x01d3, 0x03e0, +- 0x021e, 0x002d, 0x004b, 0x0278, 0x0087, 0x02b4, 0x02d2, 0x00e1 +-}; ++ { ++ 0x0000, 0x0233, 0x0255, 0x0066, 0x0299, 0x00aa, 0x00cc, 0x02ff, ++ 0x0301, 0x0132, 0x0154, 0x0367, 0x0198, 0x03ab, 0x03cd, 0x01fe, ++ 0x0031, 0x0202, 0x0264, 0x0057, 0x02a8, 0x009b, 0x00fd, 0x02ce, ++ 0x0330, 0x0103, 0x0165, 0x0356, 0x01a9, 0x039a, 0x03fc, 0x01cf, ++ 0x0062, 0x0251, 0x0237, 0x0004, 0x02fb, 0x00c8, 0x00ae, 0x029d, ++ 0x0363, 0x0150, 0x0136, 0x0305, 0x01fa, 0x03c9, 0x03af, 0x019c, ++ 0x0053, 0x0260, 0x0206, 0x0035, 0x02ca, 0x00f9, 0x009f, 0x02ac, ++ 0x0352, 0x0161, 0x0107, 0x0334, 0x01cb, 0x03f8, 0x039e, 0x01ad, ++ 0x00c4, 0x02f7, 0x0291, 0x00a2, 0x025d, 0x006e, 0x0008, 0x023b, ++ 0x03c5, 0x01f6, 0x0190, 0x03a3, 0x015c, 0x036f, 0x0309, 0x013a, ++ 0x00f5, 0x02c6, 0x02a0, 0x0093, 0x026c, 0x005f, 0x0039, 0x020a, ++ 0x03f4, 0x01c7, 0x01a1, 0x0392, 0x016d, 0x035e, 0x0338, 0x010b, ++ 0x00a6, 0x0295, 0x02f3, 0x00c0, 0x023f, 0x000c, 0x006a, 0x0259, ++ 0x03a7, 0x0194, 0x01f2, 0x03c1, 0x013e, 0x030d, 0x036b, 0x0158, ++ 0x0097, 0x02a4, 0x02c2, 0x00f1, 0x020e, 0x003d, 0x005b, 0x0268, ++ 0x0396, 0x01a5, 0x01c3, 0x03f0, 0x010f, 0x033c, 0x035a, 0x0169, ++ 0x0188, 0x03bb, 0x03dd, 0x01ee, 0x0311, 0x0122, 0x0144, 0x0377, ++ 0x0289, 0x00ba, 0x00dc, 0x02ef, 0x0010, 0x0223, 0x0245, 0x0076, ++ 0x01b9, 0x038a, 0x03ec, 0x01df, 0x0320, 0x0113, 0x0175, 0x0346, ++ 0x02b8, 0x008b, 0x00ed, 0x02de, 0x0021, 0x0212, 0x0274, 0x0047, ++ 0x01ea, 0x03d9, 0x03bf, 0x018c, 0x0373, 0x0140, 0x0126, 0x0315, ++ 0x02eb, 0x00d8, 0x00be, 0x028d, 0x0072, 0x0241, 0x0227, 0x0014, ++ 0x01db, 0x03e8, 0x038e, 0x01bd, 0x0342, 0x0171, 0x0117, 0x0324, ++ 0x02da, 0x00e9, 0x008f, 0x02bc, 0x0043, 0x0270, 0x0216, 0x0025, ++ 0x014c, 0x037f, 0x0319, 0x012a, 0x03d5, 0x01e6, 0x0180, 0x03b3, ++ 0x024d, 0x007e, 0x0018, 0x022b, 0x00d4, 0x02e7, 0x0281, 0x00b2, ++ 0x017d, 0x034e, 0x0328, 0x011b, 0x03e4, 0x01d7, 0x01b1, 0x0382, ++ 0x027c, 0x004f, 0x0029, 0x021a, 0x00e5, 0x02d6, 0x02b0, 0x0083, ++ 0x012e, 0x031d, 0x037b, 0x0148, 0x03b7, 0x0184, 0x01e2, 0x03d1, ++ 0x022f, 0x001c, 0x007a, 0x0249, 0x00b6, 0x0285, 0x02e3, 0x00d0, ++ 0x011f, 0x032c, 0x034a, 0x0179, 0x0386, 0x01b5, 0x01d3, 0x03e0, ++ 0x021e, 0x002d, 0x004b, 0x0278, 0x0087, 0x02b4, 0x02d2, 0x00e1}; + +-static void +-init_crc10_table(void) ++static int init_crc10_table(void) + { + #define CRC10_POLYNOMIAL 0x633 + int i, j; + uint16_t accum; + uint16_t verify_crc10_table[256]; + +- for ( i = 0; i < 256; i++ ) ++ for (i = 0; i < 256; i++) + { +- accum = ((unsigned short) i << 2); +- for ( j = 0; j < 8; j++ ) ++ accum = ((unsigned short)i << 2); ++ for (j = 0; j < 8; j++) + { +- if ((accum <<= 1) & 0x400) accum ^= CRC10_POLYNOMIAL; ++ if ((accum <<= 1) & 0x400) ++ accum ^= CRC10_POLYNOMIAL; + } + verify_crc10_table[i] = accum; + } +- assert(memcmp(verify_crc10_table, +- crc10_table, +- sizeof(verify_crc10_table)) == 0); ++ assert(memcmp(verify_crc10_table, crc10_table, sizeof(verify_crc10_table)) == 0); ++ return memcmp(verify_crc10_table, crc10_table, sizeof(verify_crc10_table)); + #undef CRC10_POLYNOMIAL + } + +@@ -114,21 +112,18 @@ + { + int i; + +- for ( i = 0; i < length; i++ ) ++ for (i = 0; i < length; i++) + { +- accum = ((accum << 8) & 0x3ff) +- ^ crc10_table[( accum >> 2) & 0xff] +- ^ *p++; ++ accum = ((accum << 8) & 0x3ff) ^ crc10_table[(accum >> 2) & 0xff] ^ *p++; + } + return accum; + } + + /* precompute checksum tables */ +-void +-init_checksum(void) { ++void init_checksum(void) ++{ + + init_crc10_table(); +- + } + + /* +@@ -136,7 +131,7 @@ + * The checksum field of the passed PDU does not need to be reset to zero. + */ + uint16_t +-create_osi_cksum (const uint8_t *pptr, int checksum_offset, int length) ++create_osi_cksum(const uint8_t *pptr, int checksum_offset, int length) + { + + int x; +@@ -150,15 +145,19 @@ + c0 = 0; + c1 = 0; + +- for (idx = 0; idx < length; idx++) { ++ for (idx = 0; idx < length; idx++) ++ { + /* + * Ignore the contents of the checksum field. + */ + if (idx == checksum_offset || +- idx == checksum_offset+1) { ++ idx == checksum_offset + 1) ++ { + c1 += c0; + pptr++; +- } else { ++ } ++ else ++ { + c0 = c0 + *(pptr++); + c1 += c0; + } +@@ -167,20 +166,23 @@ + c0 = c0 % 255; + c1 = c1 % 255; + +- mul = (length - checksum_offset)*(c0); ++ mul = (length - checksum_offset) * (c0); + + x = mul - c0 - c1; + y = c1 - mul - 1; + +- if ( y >= 0 ) y++; +- if ( x < 0 ) x--; ++ if (y >= 0) ++ y++; ++ if (x < 0) ++ x--; + + x %= 255; + y %= 255; + +- +- if (x == 0) x = 255; +- if (y == 0) y = 255; ++ if (x == 0) ++ x = 255; ++ if (y == 0) ++ y = 255; + + y &= 0x00FF; + checksum = ((x << 8) | y); +diff -uNr tcpdump-tcpdump-4.99.4/CMakeLists.txt tcpdump-for-stellar/CMakeLists.txt +--- tcpdump-tcpdump-4.99.4/CMakeLists.txt 2023-04-08 02:30:58.000000000 +0800 ++++ tcpdump-for-stellar/CMakeLists.txt 2024-10-30 17:34:05.478498703 +0800 +@@ -82,7 +82,7 @@ + # + set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) + +-set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules) ++set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules) + + # + # OK, this is a royal pain. +@@ -206,11 +206,26 @@ + # Parameters + ################################################################### + +-option(WITH_SMI "Build with libsmi, if available" ON) +-option(WITH_CRYPTO "Build with OpenSSL/libressl libcrypto, if available" ON) ++option(WITH_SMI "Build with libsmi, if available" OFF) ++option(WITH_CRYPTO "Build with OpenSSL/libressl libcrypto, if available" OFF) + option(WITH_CAPSICUM "Build with Capsicum security functions, if available" ON) + option(WITH_CAP_NG "Use libcap-ng, if available" ON) + option(ENABLE_SMB "Build with the SMB dissector" OFF) ++option(STELLAR_SOURCE_DIR"stellar src root dir" "") ++option(STELLAR_BINARY_DIR "stellar build root dir" "") ++option(ASAN_OPTION "asan" OFF) ++ ++if(ASAN_OPTION MATCHES "ADDRESS") ++ set(CMAKE_C_FLAGS "${CMAKADDRESS} -g -DCMAKE_BUILD_TYPE=Debug -fsanitize=address -fno-omit-frame-pointer") ++ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -DCMAKE_BUILD_TYPE=Debug -fsanitize=address -fno-omit-frame-pointer") ++ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lasan") ++ set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lasan") ++elseif(ASAN_OPTION MATCHES "THREAD") ++ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -DCMAKE_BUILD_TYPE=Debug -fsanitize=thread -fno-omit-frame-pointer") ++ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -DCMAKE_BUILD_TYPE=Debug -fsanitize=thread -fno-omit-frame-pointer") ++ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lasan") ++ set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lasan") ++endif() + + # + # String parameters. Neither of them are set, initially; only if the +@@ -1235,6 +1250,15 @@ + set(TCPDUMP_SOURCE_LIST_C ${TCPDUMP_SOURCE_LIST_C} missing/dlnames.c) + endif((NOT HAVE_PCAP_DATALINK_NAME_TO_VAL) OR (NOT HAVE_PCAP_DATALINK_VAL_TO_DESCRIPTION)) + ++set(TCPDUMP_SOURCE_LIST_C ${TCPDUMP_SOURCE_LIST_C} stellar_dump_ctrl_link.c) ++set(TCPDUMP_SOURCE_LIST_C ${TCPDUMP_SOURCE_LIST_C} stellar_dump_data_link.c) ++include_directories(${STELLAR_SOURCE_DIR}/include/) ++include_directories(${STELLAR_SOURCE_DIR}/infra/) ++include_directories(${STELLAR_BINARY_DIR}/vendors/libevent/include/) ++ ++link_directories(${STELLAR_BINARY_DIR}/vendors/libevent/lib/) ++link_directories(${STELLAR_BINARY_DIR}/infra/packet_manager/) ++ + set(PROJECT_SOURCE_LIST_C ${NETDISSECT_SOURCE_LIST_C} ${TCPDUMP_SOURCE_LIST_C}) + + file(GLOB PROJECT_SOURCE_LIST_H +@@ -1297,11 +1321,17 @@ + # Register targets + ###################################### + +-add_executable(tcpdump ${TCPDUMP_SOURCE_LIST_C}) ++# add_executable(tcpdump ${TCPDUMP_SOURCE_LIST_C}) ++add_library(tcpdump_stellar ${TCPDUMP_SOURCE_LIST_C}) + if(NOT C_ADDITIONAL_FLAGS STREQUAL "") +- set_target_properties(tcpdump PROPERTIES COMPILE_FLAGS ${C_ADDITIONAL_FLAGS}) ++ set_target_properties(tcpdump_stellar PROPERTIES COMPILE_FLAGS ${C_ADDITIONAL_FLAGS}) + endif() +-target_link_libraries(tcpdump netdissect ${TCPDUMP_LINK_LIBRARIES}) ++target_link_libraries(tcpdump_stellar netdissect ${TCPDUMP_LINK_LIBRARIES}) ++ ++##like redis-cli, use hyphen('-') not underscore('_') to separate words ++add_executable(stellar-dump main.c) ++target_link_libraries(stellar-dump tcpdump_stellar pthread packet_manager) ++target_link_libraries(stellar-dump ${STELLAR_BINARY_DIR}/vendors/libevent/lib/libevent.a) + + ###################################### + # Write out the config.h file +@@ -1325,7 +1355,7 @@ + if(WIN32) + # XXX TODO where to install on Windows? + else(WIN32) +- install(TARGETS tcpdump DESTINATION bin) ++ install(TARGETS tcpdump_stellar DESTINATION bin) + endif(WIN32) + + # On UN*X, and on Windows when not using MSVC, process man pages and +@@ -1340,7 +1370,7 @@ + set(MAN1 "") + foreach(TEMPLATE_MANPAGE ${MAN1_EXPAND}) + string(REPLACE ".in" "" MANPAGE ${TEMPLATE_MANPAGE}) +- configure_file(${CMAKE_SOURCE_DIR}/${TEMPLATE_MANPAGE} ${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE} @ONLY) ++ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${TEMPLATE_MANPAGE} ${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE} @ONLY) + set(MAN1 ${MAN1} ${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE}) + endforeach(TEMPLATE_MANPAGE) + install(FILES ${MAN1} DESTINATION ${CMAKE_INSTALL_MANDIR}/man1) +@@ -1361,11 +1391,11 @@ + # rule run tests/TESTrun with it, because just trying to run the TESTrun + # script as a command won't work on Windows. + # +-find_program(PERL perl) +-if(PERL) +- message(STATUS "Found perl at ${PERL}") +- add_custom_target(check +- COMMAND ${PERL} ${CMAKE_SOURCE_DIR}/tests/TESTrun) +-else() +- message(STATUS "Didn't find perl") +-endif() ++# find_program(PERL perl) ++# if(PERL) ++# message(STATUS "Found perl at ${PERL}") ++# add_custom_target(check ++# COMMAND ${PERL} ${CMAKE_SOURCE_DIR}/tests/TESTrun) ++# else() ++# message(STATUS "Didn't find perl") ++# endif() +diff -uNr tcpdump-tcpdump-4.99.4/ftmacros.h tcpdump-for-stellar/ftmacros.h +--- tcpdump-tcpdump-4.99.4/ftmacros.h 2023-04-08 02:30:58.000000000 +0800 ++++ tcpdump-for-stellar/ftmacros.h 2024-10-30 17:34:05.573498702 +0800 +@@ -101,7 +101,9 @@ + * this might, for example, be GNU/HURD or one of Debian's kFreeBSD + * OSes ("GNU/FreeBSD"). + */ ++ #ifndef _GNU_SOURCE + #define _GNU_SOURCE ++ #endif + + /* + * We turn on both _DEFAULT_SOURCE and _BSD_SOURCE to try to get +diff -uNr tcpdump-tcpdump-4.99.4/.gitattributes tcpdump-for-stellar/.gitattributes +--- tcpdump-tcpdump-4.99.4/.gitattributes 2023-04-08 02:30:58.000000000 +0800 ++++ tcpdump-for-stellar/.gitattributes 1970-01-01 08:00:00.000000000 +0800 +@@ -1,9 +0,0 @@ +-# Auto detect text files and perform LF normalization +-* text=auto +- +-# Normalize line endings to LF on checkin and +-# prevents conversion to CRLF when the file is checked out +-tests/*.out text eol=lf +- +-# things that only make sense on github.com +-.github export-ignore +diff -uNr tcpdump-tcpdump-4.99.4/.gitignore tcpdump-for-stellar/.gitignore +--- tcpdump-tcpdump-4.99.4/.gitignore 2023-04-08 02:30:58.000000000 +0800 ++++ tcpdump-for-stellar/.gitignore 1970-01-01 08:00:00.000000000 +0800 +@@ -1,41 +0,0 @@ +-*.orig +-*.rej +-Makefile +-*~ +-*.o +-libnetdissect.a +-config.h +-config.log +-config.cache +-config.status +-.devel +-os-proto.h +-stamp-h +-stamp-h.in +-tcpdump +-tcpdump.1 +-tcpdump-*.tar.gz +-failure-outputs.txt +-autom4te.cache/ +-*.VC.db +-*.VC.opendb +-ALL_BUILD.vcxproj* +-ZERO_CHECK.vcxproj* +-check.vcxproj* +-netdissect.vcxproj* +-tcpdump.vcxproj* +-uninstall.vcxproj* +-CMakeCache.txt +-CMakeFiles/ +-Debug/ +-Release/ +-MinSizeRel/ +-RelWithDebInfo/ +-cmake_install.cmake +-cmake_uninstall.cmake +-netdissect.dir/ +-tcpdump.dir/ +-tcpdump.sln +-.vs/ +-.passed +-.failed +diff -uNr tcpdump-tcpdump-4.99.4/main.c tcpdump-for-stellar/main.c +--- tcpdump-tcpdump-4.99.4/main.c 1970-01-01 08:00:00.000000000 +0800 ++++ tcpdump-for-stellar/main.c 2024-10-30 17:34:06.260498697 +0800 +@@ -0,0 +1,10 @@ ++#include <stdio.h> ++#include <pcap/pcap.h> ++#include "netdissect.h" ++ ++extern int stellar_dump(int argc, char **argv); ++ ++int main(int argc, char const *argv[]) ++{ ++ return stellar_dump(argc, (char **)argv); ++} +diff -uNr tcpdump-tcpdump-4.99.4/netdissect.h tcpdump-for-stellar/netdissect.h +--- tcpdump-tcpdump-4.99.4/netdissect.h 2023-04-08 02:30:58.000000000 +0800 ++++ tcpdump-for-stellar/netdissect.h 2024-10-30 17:34:05.601498702 +0800 +@@ -21,17 +21,17 @@ + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ +- + #ifndef netdissect_h + #define netdissect_h + + #ifdef HAVE_OS_PROTO_H + #include "os-proto.h" + #endif ++#include <time.h> + #include <sys/types.h> + #include <setjmp.h> + #include "status-exit-codes.h" +-#include "funcattrs.h" /* for PRINTFLIKE_FUNCPTR() */ ++#include "funcattrs.h" /* for PRINTFLIKE_FUNCPTR() */ + #include "diag-control.h" /* for ND_UNREACHABLE */ + + /* +@@ -63,7 +63,7 @@ + typedef unsigned char nd_int32_t[4]; + typedef unsigned char nd_int64_t[8]; + +-#define FMAXINT (4294967296.0) /* floating point rep. of MAXINT */ ++#define FMAXINT (4294967296.0) /* floating point rep. of MAXINT */ + + /* + * Use this for IPv4 addresses and netmasks. +@@ -101,7 +101,7 @@ + /* + * Use this for MAC addresses. + */ +-#define MAC_ADDR_LEN 6U /* length of MAC addresses */ ++#define MAC_ADDR_LEN 6U /* length of MAC addresses */ + typedef unsigned char nd_mac_addr[MAC_ADDR_LEN]; + + /* +@@ -113,33 +113,34 @@ + * Round up x to a multiple of y; y must be a power of 2. + */ + #ifndef roundup2 +-#define roundup2(x, y) (((x)+((u_int)((y)-1)))&(~((u_int)((y)-1)))) ++#define roundup2(x, y) (((x) + ((u_int)((y) - 1))) & (~((u_int)((y) - 1)))) + #endif + + #include <stdarg.h> + #include <pcap.h> + +-#include "ip.h" /* struct ip for nextproto4_cksum() */ +-#include "ip6.h" /* struct ip6 for nextproto6_cksum() */ ++#include "tcpdump_ip.h" /* struct ip for nextproto4_cksum() */ ++#include "tcpdump_ip6.h" /* struct ip6 for nextproto6_cksum() */ + + #ifndef HAVE_STRLCAT +-extern size_t strlcat (char *, const char *, size_t); ++extern size_t strlcat(char *, const char *, size_t); + #endif + #ifndef HAVE_STRLCPY +-extern size_t strlcpy (char *, const char *, size_t); ++extern size_t strlcpy(char *, const char *, size_t); + #endif + + #ifndef HAVE_STRDUP +-extern char *strdup (const char *str); ++extern char *strdup(const char *str); + #endif + + #ifndef HAVE_STRSEP + extern char *strsep(char **, const char *); + #endif + +-struct tok { +- u_int v; /* value */ +- const char *s; /* string */ ++struct tok ++{ ++ u_int v; /* value */ ++ const char *s; /* string */ + }; + + /* tok2str is deprecated */ +@@ -165,7 +166,7 @@ + + #define IF_PRINTER_ARGS (netdissect_options *, const struct pcap_pkthdr *, const u_char *) + +-typedef void (*if_printer) IF_PRINTER_ARGS; ++typedef void(*if_printer) IF_PRINTER_ARGS; + + /* + * In case the data in a buffer needs to be processed by being decrypted, +@@ -186,52 +187,54 @@ + * on the stack with null buffer pointer, meaning there's nothing to + * free. + */ +-struct netdissect_saved_packet_info { +- u_char *ndspi_buffer; /* pointer to allocated buffer data */ +- const u_char *ndspi_packetp; /* saved beginning of data */ +- const u_char *ndspi_snapend; /* saved end of data */ +- struct netdissect_saved_packet_info *ndspi_prev; /* previous buffer on the stack */ ++struct netdissect_saved_packet_info ++{ ++ u_char *ndspi_buffer; /* pointer to allocated buffer data */ ++ const u_char *ndspi_packetp; /* saved beginning of data */ ++ const u_char *ndspi_snapend; /* saved end of data */ ++ struct netdissect_saved_packet_info *ndspi_prev; /* previous buffer on the stack */ + }; + + /* 'val' value(s) for longjmp */ + #define ND_TRUNCATED 1 + +-struct netdissect_options { +- int ndo_bflag; /* print 4 byte ASes in ASDOT notation */ +- int ndo_eflag; /* print ethernet header */ +- int ndo_fflag; /* don't translate "foreign" IP address */ +- int ndo_Kflag; /* don't check IP, TCP or UDP checksums */ +- int ndo_nflag; /* leave addresses as numbers */ +- int ndo_Nflag; /* remove domains from printed host names */ +- int ndo_qflag; /* quick (shorter) output */ +- int ndo_Sflag; /* print raw TCP sequence numbers */ +- int ndo_tflag; /* print packet arrival time */ +- int ndo_uflag; /* Print undecoded NFS handles */ +- int ndo_vflag; /* verbosity level */ +- int ndo_xflag; /* print packet in hex */ +- int ndo_Xflag; /* print packet in hex/ASCII */ +- int ndo_Aflag; /* print packet only in ASCII observing TAB, +- * LF, CR and SPACE as graphical chars +- */ +- int ndo_Hflag; /* dissect 802.11s draft mesh standard */ +- const char *ndo_protocol; /* protocol */ +- jmp_buf ndo_early_end; /* jmp_buf for setjmp()/longjmp() */ +- void *ndo_last_mem_p; /* pointer to the last allocated memory chunk */ +- int ndo_packet_number; /* print a packet number in the beginning of line */ ++struct netdissect_options ++{ ++ int ndo_bflag; /* print 4 byte ASes in ASDOT notation */ ++ int ndo_eflag; /* print ethernet header */ ++ int ndo_fflag; /* don't translate "foreign" IP address */ ++ int ndo_Kflag; /* don't check IP, TCP or UDP checksums */ ++ int ndo_nflag; /* leave addresses as numbers */ ++ int ndo_Nflag; /* remove domains from printed host names */ ++ int ndo_qflag; /* quick (shorter) output */ ++ int ndo_Sflag; /* print raw TCP sequence numbers */ ++ int ndo_tflag; /* print packet arrival time */ ++ int ndo_uflag; /* Print undecoded NFS handles */ ++ int ndo_vflag; /* verbosity level */ ++ int ndo_xflag; /* print packet in hex */ ++ int ndo_Xflag; /* print packet in hex/ASCII */ ++ int ndo_Aflag; /* print packet only in ASCII observing TAB, ++ * LF, CR and SPACE as graphical chars ++ */ ++ int ndo_Hflag; /* dissect 802.11s draft mesh standard */ ++ const char *ndo_protocol; /* protocol */ ++ jmp_buf ndo_early_end; /* jmp_buf for setjmp()/longjmp() */ ++ void *ndo_last_mem_p; /* pointer to the last allocated memory chunk */ ++ int ndo_packet_number; /* print a packet number in the beginning of line */ + int ndo_suppress_default_print; /* don't use default_print() for unknown packet types */ +- int ndo_tstamp_precision; /* requested time stamp precision */ +- const char *program_name; /* Name of the program using the library */ ++ int ndo_tstamp_precision; /* requested time stamp precision */ ++ const char *program_name; /* Name of the program using the library */ + + char *ndo_espsecret; +- struct sa_list *ndo_sa_list_head; /* used by print-esp.c */ ++ struct sa_list *ndo_sa_list_head; /* used by print-esp.c */ + struct sa_list *ndo_sa_default; + +- char *ndo_sigsecret; /* Signature verification secret key */ ++ char *ndo_sigsecret; /* Signature verification secret key */ + +- int ndo_packettype; /* as specified by -T */ ++ int ndo_packettype; /* as specified by -T */ + +- int ndo_snaplen; +- int ndo_ll_hdr_len; /* link-layer header length */ ++ int ndo_snaplen; ++ int ndo_ll_hdr_len; /* link-layer header length */ + + /*global pointers to beginning and end of current packet (during printing) */ + const u_char *ndo_packetp; +@@ -245,21 +248,21 @@ + + /* pointer to void function to output stuff */ + void (*ndo_default_print)(netdissect_options *, +- const u_char *bp, u_int length); ++ const u_char *bp, u_int length); + + /* pointer to function to do regular output */ +- int (*ndo_printf)(netdissect_options *, +- const char *fmt, ...) +- PRINTFLIKE_FUNCPTR(2, 3); ++ int (*ndo_printf)(netdissect_options *, ++ const char *fmt, ...) ++ PRINTFLIKE_FUNCPTR(2, 3); + /* pointer to function to output errors */ + void NORETURN_FUNCPTR (*ndo_error)(netdissect_options *, +- status_exit_codes_t status, +- const char *fmt, ...) +- PRINTFLIKE_FUNCPTR(3, 4); ++ status_exit_codes_t status, ++ const char *fmt, ...) ++ PRINTFLIKE_FUNCPTR(3, 4); + /* pointer to function to output warnings */ + void (*ndo_warning)(netdissect_options *, +- const char *fmt, ...) +- PRINTFLIKE_FUNCPTR(2, 3); ++ const char *fmt, ...) ++ PRINTFLIKE_FUNCPTR(2, 3); + }; + + extern WARN_UNUSED_RESULT int nd_push_buffer(netdissect_options *, u_char *, const u_char *, const u_int); +@@ -271,43 +274,40 @@ + static inline NORETURN void + nd_trunc_longjmp(netdissect_options *ndo) + { +- longjmp(ndo->ndo_early_end, ND_TRUNCATED); ++ longjmp(ndo->ndo_early_end, ND_TRUNCATED); + #ifdef _AIX +- /* +- * In AIX <setjmp.h> decorates longjmp() with "#pragma leaves", which tells +- * XL C that the function is noreturn, but GCC remains unaware of that and +- * yields a "'noreturn' function does return" warning. +- */ +- ND_UNREACHABLE ++ /* ++ * In AIX <setjmp.h> decorates longjmp() with "#pragma leaves", which tells ++ * XL C that the function is noreturn, but GCC remains unaware of that and ++ * yields a "'noreturn' function does return" warning. ++ */ ++ ND_UNREACHABLE + #endif /* _AIX */ + } + +-#define PT_VAT 1 /* Visual Audio Tool */ +-#define PT_WB 2 /* distributed White Board */ +-#define PT_RPC 3 /* Remote Procedure Call */ +-#define PT_RTP 4 /* Real-Time Applications protocol */ +-#define PT_RTCP 5 /* Real-Time Applications control protocol */ +-#define PT_SNMP 6 /* Simple Network Management Protocol */ +-#define PT_CNFP 7 /* Cisco NetFlow protocol */ +-#define PT_TFTP 8 /* trivial file transfer protocol */ +-#define PT_AODV 9 /* Ad-hoc On-demand Distance Vector Protocol */ +-#define PT_CARP 10 /* Common Address Redundancy Protocol */ +-#define PT_RADIUS 11 /* RADIUS authentication Protocol */ +-#define PT_ZMTP1 12 /* ZeroMQ Message Transport Protocol 1.0 */ +-#define PT_VXLAN 13 /* Virtual eXtensible Local Area Network */ +-#define PT_PGM 14 /* [UDP-encapsulated] Pragmatic General Multicast */ +-#define PT_PGM_ZMTP1 15 /* ZMTP/1.0 inside PGM (native or UDP-encapsulated) */ +-#define PT_LMP 16 /* Link Management Protocol */ +-#define PT_RESP 17 /* RESP */ +-#define PT_PTP 18 /* PTP */ +-#define PT_SOMEIP 19 /* Autosar SOME/IP Protocol */ +-#define PT_DOMAIN 20 /* Domain Name System (DNS) */ +- +-#define ND_MIN(a,b) ((a)>(b)?(b):(a)) +-#define ND_MAX(a,b) ((b)>(a)?(b):(a)) ++#define PT_VAT 1 /* Visual Audio Tool */ ++#define PT_WB 2 /* distributed White Board */ ++#define PT_RPC 3 /* Remote Procedure Call */ ++#define PT_RTP 4 /* Real-Time Applications protocol */ ++#define PT_RTCP 5 /* Real-Time Applications control protocol */ ++#define PT_SNMP 6 /* Simple Network Management Protocol */ ++#define PT_CNFP 7 /* Cisco NetFlow protocol */ ++#define PT_TFTP 8 /* trivial file transfer protocol */ ++#define PT_AODV 9 /* Ad-hoc On-demand Distance Vector Protocol */ ++#define PT_CARP 10 /* Common Address Redundancy Protocol */ ++#define PT_RADIUS 11 /* RADIUS authentication Protocol */ ++#define PT_ZMTP1 12 /* ZeroMQ Message Transport Protocol 1.0 */ ++#define PT_VXLAN 13 /* Virtual eXtensible Local Area Network */ ++#define PT_PGM 14 /* [UDP-encapsulated] Pragmatic General Multicast */ ++#define PT_PGM_ZMTP1 15 /* ZMTP/1.0 inside PGM (native or UDP-encapsulated) */ ++#define PT_LMP 16 /* Link Management Protocol */ ++#define PT_RESP 17 /* RESP */ ++#define PT_PTP 18 /* PTP */ ++#define PT_SOMEIP 19 /* Autosar SOME/IP Protocol */ ++#define PT_DOMAIN 20 /* Domain Name System (DNS) */ + +-/* For source or destination ports tests (UDP, TCP, ...) */ +-#define IS_SRC_OR_DST_PORT(p) (sport == (p) || dport == (p)) ++#define ND_MIN(a, b) ((a) > (b) ? (b) : (a)) ++#define ND_MAX(a, b) ((b) > (a) ? (b) : (a)) + + /* + * Maximum snapshot length. This should be enough to capture the full +@@ -336,7 +336,7 @@ + * let libpcap choose a snapshot length; newer versions may choose a bigger + * value than 262144 for D-Bus, for example. + */ +-#define MAXIMUM_SNAPLEN 262144 ++#define MAXIMUM_SNAPLEN 262144 + + /* + * True if "l" bytes from "p" were captured. +@@ -365,19 +365,23 @@ + */ + #define IS_NOT_NEGATIVE(x) (((x) > 0) || ((x) == 0)) + +-#define ND_TTEST_LEN(p, l) \ +- (IS_NOT_NEGATIVE(l) && \ +- ((uintptr_t)ndo->ndo_snapend - (l) <= (uintptr_t)ndo->ndo_snapend && \ +- (uintptr_t)(p) <= (uintptr_t)ndo->ndo_snapend - (l))) ++#define ND_TTEST_LEN(p, l) \ ++ (IS_NOT_NEGATIVE(l) && \ ++ ((uintptr_t)ndo->ndo_snapend - (l) <= (uintptr_t)ndo->ndo_snapend && \ ++ (uintptr_t)(p) <= (uintptr_t)ndo->ndo_snapend - (l))) + + /* True if "*(p)" was captured */ + #define ND_TTEST_SIZE(p) ND_TTEST_LEN(p, sizeof(*(p))) + + /* Bail out if "l" bytes from "p" were not captured */ + #ifdef ND_LONGJMP_FROM_TCHECK +-#define ND_TCHECK_LEN(p, l) if (!ND_TTEST_LEN(p, l)) nd_trunc_longjmp(ndo) ++#define ND_TCHECK_LEN(p, l) \ ++ if (!ND_TTEST_LEN(p, l)) \ ++ nd_trunc_longjmp(ndo) + #else +-#define ND_TCHECK_LEN(p, l) if (!ND_TTEST_LEN(p, l)) goto trunc ++#define ND_TCHECK_LEN(p, l) \ ++ if (!ND_TTEST_LEN(p, l)) \ ++ goto trunc + #endif + + /* Bail out if "*(p)" was not captured */ +@@ -395,26 +399,28 @@ + #define ND_BYTES_AVAILABLE_AFTER(p) ND_BYTES_BETWEEN(ndo->ndo_snapend, (p)) + + /* Check length < minimum for invalid packet with a custom message, format %u */ +-#define ND_LCHECKMSG_U(length, minimum, what) \ +-if ((length) < (minimum)) { \ +-ND_PRINT(" [%s %u < %u]", (what), (length), (minimum)); \ +-goto invalid; \ +-} ++#define ND_LCHECKMSG_U(length, minimum, what) \ ++ if ((length) < (minimum)) \ ++ { \ ++ ND_PRINT(" [%s %u < %u]", (what), (length), (minimum)); \ ++ goto invalid; \ ++ } + + /* Check length < minimum for invalid packet with #length message, format %u */ + #define ND_LCHECK_U(length, minimum) \ +-ND_LCHECKMSG_U((length), (minimum), (#length)) ++ ND_LCHECKMSG_U((length), (minimum), (#length)) + + /* Check length < minimum for invalid packet with a custom message, format %zu */ +-#define ND_LCHECKMSG_ZU(length, minimum, what) \ +-if ((length) < (minimum)) { \ +-ND_PRINT(" [%s %u < %zu]", (what), (length), (minimum)); \ +-goto invalid; \ +-} ++#define ND_LCHECKMSG_ZU(length, minimum, what) \ ++ if ((length) < (minimum)) \ ++ { \ ++ ND_PRINT(" [%s %u < %zu]", (what), (length), (minimum)); \ ++ goto invalid; \ ++ } + + /* Check length < minimum for invalid packet with #length message, format %zu */ + #define ND_LCHECK_ZU(length, minimum) \ +-ND_LCHECKMSG_ZU((length), (minimum), (#length)) ++ ND_LCHECKMSG_ZU((length), (minimum), (#length)) + + #define ND_PRINT(...) (ndo->ndo_printf)(ndo, __VA_ARGS__) + #define ND_DEFAULTPRINT(ap, length) (*ndo->ndo_default_print)(ndo, ap, length) +@@ -424,7 +430,7 @@ + extern void unsigned_relts_print(netdissect_options *, uint32_t); + + extern const char *nd_format_time(char *buf, size_t bufsize, +- const char *format, const struct tm *timeptr); ++ const char *format, const struct tm *timeptr); + + extern void fn_print_char(netdissect_options *, u_char); + extern void fn_print_str(netdissect_options *, const u_char *); +@@ -435,16 +441,16 @@ + /* + * Flags for txtproto_print(). + */ +-#define RESP_CODE_SECOND_TOKEN 0x00000001 /* response code is second token in response line */ ++#define RESP_CODE_SECOND_TOKEN 0x00000001 /* response code is second token in response line */ + + extern void txtproto_print(netdissect_options *, const u_char *, u_int, +- const char **, u_int); ++ const char **, u_int); + +-#if (defined(__i386__) || defined(_M_IX86) || defined(__X86__) || defined(__x86_64__) || defined(_M_X64)) || \ +- (defined(__arm__) || defined(_M_ARM) || defined(__aarch64__)) || \ +- (defined(__m68k__) && (!defined(__mc68000__) && !defined(__mc68010__))) || \ ++#if (defined(__i386__) || defined(_M_IX86) || defined(__X86__) || defined(__x86_64__) || defined(_M_X64)) || \ ++ (defined(__arm__) || defined(_M_ARM) || defined(__aarch64__)) || \ ++ (defined(__m68k__) && (!defined(__mc68000__) && !defined(__mc68010__))) || \ + (defined(__ppc__) || defined(__ppc64__) || defined(_M_PPC) || defined(_ARCH_PPC) || defined(_ARCH_PPC64)) || \ +- (defined(__s390__) || defined(__s390x__) || defined(__zarch__)) || \ ++ (defined(__s390__) || defined(__s390x__) || defined(__zarch__)) || \ + defined(__vax__) + /* + * The processor natively handles unaligned loads, so just use memcpy() +@@ -461,8 +467,8 @@ + * XXX - do we need to test for both 32-bit and 64-bit versions of those + * architectures in all cases? + */ +-#define UNALIGNED_MEMCPY(p, q, l) memcpy((p), (q), (l)) +-#define UNALIGNED_MEMCMP(p, q, l) memcmp((p), (q), (l)) ++#define UNALIGNED_MEMCPY(p, q, l) memcpy((p), (q), (l)) ++#define UNALIGNED_MEMCMP(p, q, l) memcmp((p), (q), (l)) + #else + /* + * The processor doesn't natively handle unaligned loads, +@@ -477,28 +483,32 @@ + */ + extern void unaligned_memcpy(void *, const void *, size_t); + extern int unaligned_memcmp(const void *, const void *, size_t); +-#define UNALIGNED_MEMCPY(p, q, l) unaligned_memcpy((p), (q), (l)) +-#define UNALIGNED_MEMCMP(p, q, l) unaligned_memcmp((p), (q), (l)) ++#define UNALIGNED_MEMCPY(p, q, l) unaligned_memcpy((p), (q), (l)) ++#define UNALIGNED_MEMCMP(p, q, l) unaligned_memcmp((p), (q), (l)) + #endif + + #define PLURAL_SUFFIX(n) \ +- (((n) != 1) ? "s" : "") ++ (((n) != 1) ? "s" : "") + + extern const char *tok2strary_internal(const char **, int, const char *, int); +-#define tok2strary(a,f,i) tok2strary_internal(a, sizeof(a)/sizeof(a[0]),f,i) ++#define tok2strary(a, f, i) tok2strary_internal(a, sizeof(a) / sizeof(a[0]), f, i) + + struct uint_tokary + { +- u_int uintval; +- const struct tok *tokary; ++ u_int uintval; ++ const struct tok *tokary; + }; + + extern const struct tok *uint2tokary_internal(const struct uint_tokary[], const size_t, const u_int); +-#define uint2tokary(a, i) uint2tokary_internal(a, sizeof(a)/sizeof(a[0]), i) ++#define uint2tokary(a, i) uint2tokary_internal(a, sizeof(a) / sizeof(a[0]), i) + + extern if_printer lookup_printer(int); + +-#define ND_DEBUG {printf(" [%s:%d %s] ", __FILE__, __LINE__, __func__); fflush(stdout);} ++#define ND_DEBUG \ ++ { \ ++ printf(" [%s:%d %s] ", __FILE__, __LINE__, __func__); \ ++ fflush(stdout); \ ++ } + + /* The DLT printer routines */ + +@@ -577,9 +587,10 @@ + * This contains a pointer to an address and a pointer to a routine + * to which we pass that pointer in order to get a string. + */ +-struct lladdr_info { +- const char *(*addr_string)(netdissect_options *, const u_char *); +- const u_char *addr; ++struct lladdr_info ++{ ++ const char *(*addr_string)(netdissect_options *, const u_char *); ++ const u_char *addr; + }; + + /* The printer routines. */ +@@ -589,7 +600,7 @@ + extern void ahcp_print(netdissect_options *, const u_char *, u_int); + extern void aodv_print(netdissect_options *, const u_char *, u_int, int); + extern void aoe_print(netdissect_options *, const u_char *, const u_int); +-extern int arista_ethertype_print(netdissect_options *,const u_char *, u_int); ++extern int arista_ethertype_print(netdissect_options *, const u_char *, u_int); + extern void arp_print(netdissect_options *, const u_char *, u_int, u_int); + extern void ascii_print(netdissect_options *, const u_char *, u_int); + extern void atalk_print(netdissect_options *, const u_char *, u_int); +@@ -668,8 +679,8 @@ + extern void lwres_print(netdissect_options *, const u_char *, u_int); + extern void m3ua_print(netdissect_options *, const u_char *, const u_int); + extern int macsec_print(netdissect_options *, const u_char **, +- u_int *, u_int *, u_int *, const struct lladdr_info *, +- const struct lladdr_info *); ++ u_int *, u_int *, u_int *, const struct lladdr_info *, ++ const struct lladdr_info *); + extern u_int mfr_print(netdissect_options *, const u_char *, u_int); + extern void mobile_print(netdissect_options *, const u_char *, u_int); + extern int mobility_print(netdissect_options *, const u_char *, const u_char *); +@@ -756,9 +767,10 @@ + extern uint16_t verify_crc10_cksum(uint16_t, const u_char *, int); + extern uint16_t create_osi_cksum(const uint8_t *, int, int); + +-struct cksum_vec { +- const uint8_t *ptr; +- int len; ++struct cksum_vec ++{ ++ const uint8_t *ptr; ++ int len; + }; + extern uint16_t in_cksum(const struct cksum_vec *, int); + extern uint16_t in_cksum_shouldbe(uint16_t, uint16_t); +@@ -766,10 +778,10 @@ + /* IP protocol demuxing routines */ + extern void ip_demux_print(netdissect_options *, const u_char *, u_int, u_int, int, u_int, uint8_t, const u_char *); + +-extern uint16_t nextproto4_cksum(netdissect_options *, const struct ip *, const uint8_t *, u_int, u_int, uint8_t); ++extern uint16_t nextproto4_cksum(netdissect_options *, const struct tcpdump_ip *, const uint8_t *, u_int, u_int, uint8_t); + + /* in print-ip6.c */ +-extern uint16_t nextproto6_cksum(netdissect_options *, const struct ip6_hdr *, const uint8_t *, u_int, u_int, uint8_t); ++extern uint16_t nextproto6_cksum(netdissect_options *, const struct tcpdump_ip6_hdr *, const uint8_t *, u_int, u_int, uint8_t); + + /* Utilities */ + extern void nd_print_trunc(netdissect_options *); +@@ -787,8 +799,8 @@ + + extern void esp_decodesecret_print(netdissect_options *); + extern int esp_decrypt_buffer_by_ikev2_print(netdissect_options *, int, +- const u_char spii[8], +- const u_char spir[8], +- const u_char *, const u_char *); ++ const u_char spii[8], ++ const u_char spir[8], ++ const u_char *, const u_char *); + + #endif /* netdissect_h */ +diff -uNr tcpdump-tcpdump-4.99.4/netdissect-stdinc.h tcpdump-for-stellar/netdissect-stdinc.h +--- tcpdump-tcpdump-4.99.4/netdissect-stdinc.h 2023-04-08 02:30:58.000000000 +0800 ++++ tcpdump-for-stellar/netdissect-stdinc.h 2024-10-30 17:34:05.601498702 +0800 +@@ -35,9 +35,9 @@ + * various items as needed, to isolate most of netdissect's platform + * differences to this one file. + */ +- +-#ifndef netdissect_stdinc_h +-#define netdissect_stdinc_h ++#pragma once ++// #ifndef netdissect_stdinc_h ++// #define netdissect_stdinc_h + + #include "ftmacros.h" + +@@ -379,4 +379,4 @@ + # define ND_FALL_THROUGH + #endif /* __has_attribute(fallthrough) */ + +-#endif /* netdissect_stdinc_h */ ++// #endif /* netdissect_stdinc_h */ +diff -uNr tcpdump-tcpdump-4.99.4/packet_parser.c tcpdump-for-stellar/packet_parser.c +--- tcpdump-tcpdump-4.99.4/packet_parser.c 1970-01-01 08:00:00.000000000 +0800 ++++ tcpdump-for-stellar/packet_parser.c 2024-10-30 17:34:06.264498697 +0800 +@@ -0,0 +1,980 @@ ++#include <string.h> ++#include <stdlib.h> ++#include <netinet/icmp6.h> ++#include <netinet/ip_icmp.h> ++#include <linux/ppp_defs.h> ++ ++#include "log_internal.h" ++#include "packet_helper.h" ++#include "packet_internal.h" ++#include "packet_parser.h" ++ ++#define PACKET_PARSE_LOG_DEBUG(format, ...) // STELLAR_LOG_DEBUG(__thread_local_logger, "packet parse", format, ##__VA_ARGS__) ++#define PACKET_PARSE_LOG_ERROR(format, ...) STELLAR_LOG_ERROR(__thread_local_logger, "packet parse", format, ##__VA_ARGS__) ++#define PACKET_PARSE_LOG_WARN(format, ...) STELLAR_LOG_WARN(__thread_local_logger, "packet parse", format, ##__VA_ARGS__) ++ ++#define PACKET_LOG_DATA_INSUFFICIENCY(pkt, layer) \ ++ { \ ++ PACKET_PARSE_LOG_WARN("pkt: %p, layer: %s, data insufficiency", \ ++ (pkt), layer_proto_to_str(layer)); \ ++ } ++ ++#define PACKET_LOG_UNSUPPORT_PROTO(pkt, layer, next_proto) \ ++ { \ ++ PACKET_PARSE_LOG_WARN("pkt: %p, layer: %s, unsupport next proto: %d", \ ++ (pkt), layer_proto_to_str(layer), (next_proto)); \ ++ } ++ ++#define PACKET_LOG_UNSUPPORT_ETHPROTO(pkt, next_proto) \ ++ { \ ++ PACKET_PARSE_LOG_WARN("pkt: %p, layer: L3, unsupport next proto: %d %s", \ ++ (pkt), (next_proto), eth_proto_to_str(next_proto)); \ ++ } ++ ++#define PACKET_LOG_UNSUPPORT_IPPROTO(pkt, next_proto) \ ++ { \ ++ PACKET_PARSE_LOG_WARN("pkt: %p, layer: L4, unsupport next proto: %d %s", \ ++ (pkt), (next_proto), ip_proto_to_str(next_proto)); \ ++ } ++ ++/****************************************************************************** ++ * Static API ++ ******************************************************************************/ ++ ++static inline struct layer_private *get_free_layer(struct packet *pkt); ++ ++// 数据链路层 ++static inline const char *parse_ether(struct packet *pkt, const char *data, uint16_t len); ++static inline const char *parse_pweth(struct packet *pkt, const char *data, uint16_t len); ++static inline const char *parse_ppp(struct packet *pkt, const char *data, uint16_t len); ++static inline const char *parse_l2tpv2_over_udp(struct packet *pkt, const char *data, uint16_t len); ++static inline const char *parse_l2tpv3_over_udp(struct packet *pkt, const char *data, uint16_t len); ++static inline const char *parse_l2tpv3_over_ip(struct packet *pkt, const char *data, uint16_t len); ++ ++// 数据链路层 -- 隧道 ++static inline const char *parse_vlan(struct packet *pkt, const char *data, uint16_t len); ++static inline const char *parse_pppoe_ses(struct packet *pkt, const char *data, uint16_t len); ++static inline const char *parse_mpls(struct packet *pkt, const char *data, uint16_t len); ++// 网络层 ++static inline const char *parse_ipv4(struct packet *pkt, const char *data, uint16_t len); ++static inline const char *parse_ipv6(struct packet *pkt, const char *data, uint16_t len); ++static inline const char *parse_auth(struct packet *pkt, const char *data, uint16_t len); ++// 网络层 -- 隧道 ++static inline const char *parse_gre(struct packet *pkt, const char *data, uint16_t len); ++// 传输层 ++static inline const char *parse_udp(struct packet *pkt, const char *data, uint16_t len); ++static inline const char *parse_tcp(struct packet *pkt, const char *data, uint16_t len); ++static inline const char *parse_icmp(struct packet *pkt, const char *data, uint16_t len); ++static inline const char *parse_icmp6(struct packet *pkt, const char *data, uint16_t len); ++// 传输层 -- 隧道 ++static inline const char *parse_vxlan(struct packet *pkt, const char *data, uint16_t len); ++static inline const char *parse_gtp_u(struct packet *pkt, const char *data, uint16_t len); ++static inline const char *parse_gtp_c(struct packet *pkt, const char *data, uint16_t len); ++// L3/L4 ++static inline const char *parse_l3(struct packet *pkt, uint16_t next_proto, const char *data, uint16_t len); ++static inline const char *parse_l4(struct packet *pkt, uint8_t next_proto, const char *data, uint16_t len); ++ ++/****************************************************************************** ++ * Private API -- Utils ++ ******************************************************************************/ ++ ++static inline struct layer_private *get_free_layer(struct packet *pkt) ++{ ++ if (pkt->layers_used >= pkt->layers_size) ++ { ++ return NULL; ++ } ++ ++ return &pkt->layers[pkt->layers_used]; ++} ++ ++#define SET_LAYER(_pkt, _layer, _proto, _hdr_len, _data, _len, _trim) \ ++ { \ ++ (_layer)->proto = (_proto); \ ++ (_layer)->hdr_offset = (_pkt)->data_len - (_pkt)->trim_len - (_len); \ ++ (_layer)->hdr_ptr = (_data); \ ++ (_layer)->hdr_len = (_hdr_len); \ ++ (_layer)->pld_ptr = (_data) + (_hdr_len); \ ++ (_layer)->pld_len = (_len) - (_hdr_len) - (_trim); \ ++ (_pkt)->trim_len += (_trim); \ ++ (_pkt)->layers_used++; \ ++ PACKET_PARSE_LOG_DEBUG("layer[%d/%d]: %s, header: {offset: %d, ptr: %p, len: %d}, payload: {ptr: %p, len: %d}", \ ++ (_pkt)->layers_used - 1, (_pkt)->layers_size, layer_proto_to_str((_proto)), \ ++ (_layer)->hdr_offset, (_layer)->hdr_ptr, (_layer)->hdr_len, (_layer)->pld_ptr, (_layer)->pld_len); \ ++ } ++ ++/****************************************************************************** ++ * Private API -- Parses ++ ******************************************************************************/ ++ ++static inline const char *parse_ether(struct packet *pkt, const char *data, uint16_t len) ++{ ++ if (unlikely(len < sizeof(struct ethhdr))) ++ { ++ PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_ETHER); ++ return data; ++ } ++ ++ struct layer_private *layer = get_free_layer(pkt); ++ if (unlikely(layer == NULL)) ++ { ++ return data; ++ } ++ uint16_t next_proto = eth_hdr_get_proto((const struct ethhdr *)data); ++ SET_LAYER(pkt, layer, LAYER_PROTO_ETHER, sizeof(struct ethhdr), data, len, 0); ++ ++ return parse_l3(pkt, next_proto, layer->pld_ptr, layer->pld_len); ++} ++ ++static inline const char *parse_pweth(struct packet *pkt, const char *data, uint16_t len) ++{ ++ /* ++ * PW Ethernet Control Word ++ * 0 1 2 3 ++ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 ++ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++ * |0 0 0 0| Reserved | Sequence Number | ++ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++ * Reference: https://tools.ietf.org/html/rfc4448 ++ */ ++ if (unlikely(len < 4)) ++ { ++ PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_PWETH); ++ return data; ++ } ++ ++ struct layer_private *layer = get_free_layer(pkt); ++ if (unlikely(layer == NULL)) ++ { ++ return data; ++ } ++ SET_LAYER(pkt, layer, LAYER_PROTO_PWETH, 4, data, len, 0); ++ ++ return parse_ether(pkt, layer->pld_ptr, layer->pld_len); ++} ++ ++static inline int is_ppp_proto(uint16_t proto) ++{ ++ // /usr/include/linux/ppp_defs.h.html ++ switch (proto) ++ { ++ case PPP_IP: /* Internet Protocol */ ++ case PPP_AT: /* AppleTalk Protocol */ ++ case PPP_IPX: /* IPX protocol */ ++ case PPP_VJC_COMP: /* VJ compressed TCP */ ++ case PPP_VJC_UNCOMP: /* VJ uncompressed TCP */ ++ case PPP_MP: /* Multilink protocol */ ++ case PPP_IPV6: /* Internet Protocol Version 6 */ ++ case PPP_COMPFRAG: /* fragment compressed below bundle */ ++ case PPP_COMP: /* compressed packet */ ++ case PPP_MPLS_UC: /* Multi Protocol Label Switching - Unicast */ ++ case PPP_MPLS_MC: /* Multi Protocol Label Switching - Multicast */ ++ case PPP_IPCP: /* IP Control Protocol */ ++ case PPP_ATCP: /* AppleTalk Control Protocol */ ++ case PPP_IPXCP: /* IPX Control Protocol */ ++ case PPP_IPV6CP: /* IPv6 Control Protocol */ ++ case PPP_CCPFRAG: /* CCP at link level (below MP bundle) */ ++ // case PPP_CCP: /* Compression Control Protocol */ (same as PPP_CCPFRAG) ++ case PPP_MPLSCP: /* MPLS Control Protocol */ ++ case PPP_LCP: /* Link Control Protocol */ ++ case PPP_PAP: /* Password Authentication Protocol */ ++ case PPP_LQR: /* Link Quality Report protocol */ ++ case PPP_CHAP: /* Cryptographic Handshake Auth. Protocol */ ++ case PPP_CBCP: /* Callback Control Protocol */ ++ return 1; ++ default: ++ return 0; ++ } ++} ++ ++static inline const char *parse_ppp(struct packet *pkt, const char *data, uint16_t len) ++{ ++ /* ++ * https://datatracker.ietf.org/doc/html/rfc1661#section-2 ++ * +----------+-------------+---------+ ++ * | Protocol | Information | Padding | ++ * | 8/16 bits| * | * | ++ * +----------+-------------+---------+ ++ * ++ * https://datatracker.ietf.org/doc/html/rfc1331#section-3.1 ++ * +----------+----------+----------+----------+------------ ++ * | Flag | Address | Control | Protocol | Information ++ * | 01111110 | 11111111 | 00000011 | 16 bits | * ++ * +----------+----------+----------+----------+------------ ++ * ---+----------+----------+----------------- ++ * | FCS | Flag | Inter-frame Fill ++ * | 16 bits | 01111110 | or next Address ++ * ---+----------+----------+----------------- ++ */ ++ if (unlikely(len < 4)) ++ { ++ PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_PPP); ++ return data; ++ } ++ ++ uint16_t hdr_len = 0; ++ uint16_t next_proto = 0; ++ struct layer_private *layer = NULL; ++ ++ // ppp header 1 byte ++ next_proto = *((uint8_t *)data); ++ if (is_ppp_proto(next_proto)) ++ { ++ hdr_len = 1; ++ goto success; ++ } ++ ++ // ppp header 2 bytes ++ next_proto = ntohs(*((uint16_t *)data)); ++ if (is_ppp_proto(next_proto)) ++ { ++ hdr_len = 2; ++ goto success; ++ } ++ ++ // ppp header 4 bytes ++ next_proto = ntohs(*((uint16_t *)data + 1)); ++ hdr_len = 4; ++ ++success: ++ layer = get_free_layer(pkt); ++ if (unlikely(layer == NULL)) ++ { ++ return data; ++ } ++ SET_LAYER(pkt, layer, LAYER_PROTO_PPP, hdr_len, data, len, 0); ++ switch (next_proto) ++ { ++ case PPP_IP: ++ return parse_ipv4(pkt, layer->pld_ptr, layer->pld_len); ++ case PPP_IPV6: ++ return parse_ipv6(pkt, layer->pld_ptr, layer->pld_len); ++ default: ++ PACKET_LOG_UNSUPPORT_PROTO(pkt, LAYER_PROTO_PPP, next_proto); ++ return layer->pld_ptr; ++ } ++} ++ ++static inline const char *parse_l2tpv2_over_udp(struct packet *pkt, const char *data, uint16_t len) ++{ ++ uint16_t hdr_len = calc_udp_l2tpv2_hdr_len(data, len); ++ if (unlikely(hdr_len == 0 || hdr_len > len)) ++ { ++ PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_L2TP); ++ return data; ++ } ++ ++ struct layer_private *layer = get_free_layer(pkt); ++ if (unlikely(layer == NULL)) ++ { ++ return data; ++ } ++ SET_LAYER(pkt, layer, LAYER_PROTO_L2TP, hdr_len, data, len, 0); ++ ++ // control message ++ if (l2tp_hdr_get_type((const struct l2tp_hdr *)data)) ++ { ++ return layer->pld_ptr; ++ } ++ // data message ++ else ++ { ++ return parse_ppp(pkt, layer->pld_ptr, layer->pld_len); ++ } ++} ++ ++static inline const char *parse_l2tpv3_over_udp(struct packet *pkt, const char *data, uint16_t len) ++{ ++ uint16_t hdr_len = calc_udp_l2tpv3_hdr_len(data, len); ++ if (unlikely(hdr_len == 0 || hdr_len > len)) ++ { ++ PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_L2TP); ++ return data; ++ } ++ ++ struct layer_private *layer = get_free_layer(pkt); ++ if (unlikely(layer == NULL)) ++ { ++ return data; ++ } ++ SET_LAYER(pkt, layer, LAYER_PROTO_L2TP, hdr_len, data, len, 0); ++ ++ // control message ++ if (l2tp_hdr_get_type((const struct l2tp_hdr *)data)) ++ { ++ return layer->pld_ptr; ++ } ++ // data message ++ else ++ { ++ // TOOD ++ return layer->pld_ptr; ++ } ++} ++ ++static inline const char *parse_l2tpv3_over_ip(struct packet *pkt, const char *data, uint16_t len) ++{ ++ uint16_t hdr_len = calc_ip_l2tpv3_hdr_len(data, len); ++ if (unlikely(hdr_len == 0 || hdr_len > len)) ++ { ++ PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_L2TP); ++ return data; ++ } ++ ++ struct layer_private *layer = get_free_layer(pkt); ++ if (unlikely(layer == NULL)) ++ { ++ return data; ++ } ++ SET_LAYER(pkt, layer, LAYER_PROTO_L2TP, hdr_len, data, len, 0); ++ ++ // data message ++ if (ntohl(*((uint32_t *)data))) ++ { ++ // TOOD ++ return layer->pld_ptr; ++ } ++ // control message ++ else ++ { ++ return layer->pld_ptr; ++ } ++} ++ ++static inline const char *parse_vlan(struct packet *pkt, const char *data, uint16_t len) ++{ ++ if (unlikely(len < sizeof(struct vlan_hdr))) ++ { ++ PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_VLAN); ++ return data; ++ } ++ ++ struct layer_private *layer = get_free_layer(pkt); ++ if (unlikely(layer == NULL)) ++ { ++ return data; ++ } ++ uint16_t next_proto = vlan_hdr_get_ethertype((const struct vlan_hdr *)data); ++ SET_LAYER(pkt, layer, LAYER_PROTO_VLAN, sizeof(struct vlan_hdr), data, len, 0); ++ ++ return parse_l3(pkt, next_proto, layer->pld_ptr, layer->pld_len); ++} ++ ++static inline const char *parse_pppoe_ses(struct packet *pkt, const char *data, uint16_t len) ++{ ++ if (unlikely(len < 6)) ++ { ++ PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_PPPOE); ++ return data; ++ } ++ ++ struct layer_private *layer = get_free_layer(pkt); ++ if (unlikely(layer == NULL)) ++ { ++ return data; ++ } ++ SET_LAYER(pkt, layer, LAYER_PROTO_PPPOE, 6, data, len, 0); ++ ++ return parse_ppp(pkt, layer->pld_ptr, layer->pld_len); ++} ++ ++static inline const char *parse_mpls(struct packet *pkt, const char *data, uint16_t len) ++{ ++ if (unlikely(len < 4)) ++ { ++ PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_MPLS); ++ return data; ++ } ++ ++ struct layer_private *layer = get_free_layer(pkt); ++ if (unlikely(layer == NULL)) ++ { ++ return data; ++ } ++ ++ if (mpls_label_get_bos((const struct mpls_label *)data)) ++ { ++ SET_LAYER(pkt, layer, LAYER_PROTO_MPLS, 4, data, len, 0); ++ if (layer->pld_len == 0) ++ { ++ return layer->pld_ptr; ++ } ++ uint8_t next_proto = layer->pld_ptr[0] >> 4; ++ switch (next_proto) ++ { ++ case 0: ++ // the first four digits of the PW Ethernet control word must be "00000", but the first four digits of Ethernet may also be "0000" ++ if (layer->pld_len >= sizeof(struct ethhdr) && is_eth_proto(eth_hdr_get_proto((const struct ethhdr *)layer->pld_ptr))) ++ { ++ return parse_ether(pkt, layer->pld_ptr, layer->pld_len); ++ } ++ else ++ { ++ return parse_pweth(pkt, layer->pld_ptr, layer->pld_len); ++ } ++ case 4: ++ return parse_ipv4(pkt, layer->pld_ptr, layer->pld_len); ++ case 6: ++ return parse_ipv6(pkt, layer->pld_ptr, layer->pld_len); ++ default: ++ return parse_ether(pkt, layer->pld_ptr, layer->pld_len); ++ } ++ } ++ else ++ { ++ SET_LAYER(pkt, layer, LAYER_PROTO_MPLS, 4, data, len, 0); ++ return parse_mpls(pkt, layer->pld_ptr, layer->pld_len); ++ } ++} ++ ++static inline const char *parse_ipv4(struct packet *pkt, const char *data, uint16_t len) ++{ ++ if (unlikely(len < sizeof(struct ip))) ++ { ++ PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_IPV4); ++ return data; ++ } ++ ++ struct layer_private *layer = get_free_layer(pkt); ++ if (unlikely(layer == NULL)) ++ { ++ return data; ++ } ++ ++ const struct ip *hdr = (const struct ip *)data; ++ uint8_t version = ip4_hdr_get_version(hdr); ++ if (unlikely(version != 4)) ++ { ++ PACKET_PARSE_LOG_ERROR("packet %p ipv4 version %d != 4", pkt, version); ++ return data; ++ } ++ ++ uint16_t hdr_len = ip4_hdr_get_hdr_len(hdr); ++ if (unlikely(hdr_len > len)) ++ { ++ PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_IPV4); ++ return data; ++ } ++ ++ uint16_t total_len = ip4_hdr_get_total_len(hdr); ++ if (unlikely(total_len > len)) ++ { ++ PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_IPV4); ++ return data; ++ } ++ if (unlikely(total_len < hdr_len)) ++ { ++ PACKET_PARSE_LOG_ERROR("packet %p ip total_len %d < hdr_len %d", pkt, total_len, hdr_len); ++ return data; ++ } ++ uint16_t trim_len = len - total_len; ++ SET_LAYER(pkt, layer, LAYER_PROTO_IPV4, hdr_len, data, len, trim_len); ++ ++ // ip fragmented ++ if (ip4_hdr_get_mf_flag(hdr) || ip4_hdr_get_frag_offset(hdr)) ++ { ++ PACKET_PARSE_LOG_DEBUG("packet %p ip layer %p is fragmented", pkt, layer); ++ pkt->frag_layer = layer; ++ return layer->pld_ptr; ++ } ++ ++ uint8_t next_proto = ip4_hdr_get_proto(hdr); ++ return parse_l4(pkt, next_proto, layer->pld_ptr, layer->pld_len); ++} ++ ++static inline const char *parse_ipv6(struct packet *pkt, const char *data, uint16_t len) ++{ ++ /* ++ * IP6 Extension Headers ++ * ++ * Internet Protocol, Version 6 (IPv6) : https://datatracker.ietf.org/doc/html/rfc2460 ++ * IP Encapsulating Security Payload (ESP) : https://datatracker.ietf.org/doc/html/rfc2406 ++ * IP Authentication Header : https://datatracker.ietf.org/doc/html/rfc4302 ++ * ++ * skip next header ++ * #define IPPROTO_HOPOPTS 0 // IP6 hop-by-hop options ++ * #define IPPROTO_ROUTING 43 // IP6 routing header ++ * #define IPPROTO_AH 51 // IP6 Auth Header ++ * #define IPPROTO_DSTOPTS 60 // IP6 destination option ++ * ++ * not skip next header ++ * #define IPPROTO_FRAGMENT 44 // IP6 fragmentation header ++ * #define IPPROTO_ESP 50 // IP6 Encap Sec. Payload ++ * #define IPPROTO_NONE 59 // IP6 no next header ++ */ ++ ++ if (unlikely(len < sizeof(struct ip6_hdr))) ++ { ++ PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_IPV6); ++ return data; ++ } ++ ++ struct layer_private *layer = get_free_layer(pkt); ++ if (unlikely(layer == NULL)) ++ { ++ return data; ++ } ++ const struct ip6_hdr *hdr = (const struct ip6_hdr *)data; ++ uint8_t version = ip6_hdr_get_version(hdr); ++ if (unlikely(version != 6)) ++ { ++ PACKET_PARSE_LOG_ERROR("packet %p ipv6 version %d != 6", pkt, version); ++ return data; ++ } ++ ++ uint16_t pld_len = ip6_hdr_get_payload_len(hdr); ++ if (unlikely(pld_len + sizeof(struct ip6_hdr) > len)) ++ { ++ PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_IPV6); ++ return data; ++ } ++ uint8_t next_proto = ip6_hdr_get_next_header(hdr); ++ uint16_t hdr_len = sizeof(struct ip6_hdr); ++ uint16_t trim_len = len - pld_len - sizeof(struct ip6_hdr); ++ const char *next_hdr_ptr = data + hdr_len; ++ while (next_proto == IPPROTO_HOPOPTS || next_proto == IPPROTO_ROUTING || next_proto == IPPROTO_AH || next_proto == IPPROTO_DSTOPTS) ++ { ++ if (unlikely(pld_len < 2)) ++ { ++ PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_IPV6); ++ return data; ++ } ++ struct ip6_ext *ext = (struct ip6_ext *)next_hdr_ptr; ++ uint16_t skip_len = 0; ++ if (next_proto == IPPROTO_AH) ++ { ++ /* ++ * https://datatracker.ietf.org/doc/html/rfc4302#section-2 ++ * For IPv6, the total length of the header must be a multiple of 8-octet units. ++ * (Note that although IPv6 [DH98] characterizes AH as an extension header, ++ * its length is measured in 32-bit words, not the 64-bit words used by other IPv6 extension headers.) ++ */ ++ skip_len = ext->ip6e_len * 4 + 8; ++ } ++ else ++ { ++ skip_len = ext->ip6e_len * 8 + 8; ++ } ++ if (unlikely(skip_len > pld_len)) ++ { ++ PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_IPV6); ++ return data; ++ } ++ hdr_len += skip_len; ++ pld_len -= skip_len; ++ next_hdr_ptr += skip_len; ++ next_proto = ext->ip6e_nxt; ++ } ++ SET_LAYER(pkt, layer, LAYER_PROTO_IPV6, hdr_len, data, len, trim_len); ++ ++ // ipv6 fragment ++ if (next_proto == IPPROTO_FRAGMENT) ++ { ++ PACKET_PARSE_LOG_DEBUG("packet %p ipv6 layer %p is fragmented", pkt, layer); ++ pkt->frag_layer = layer; ++ return layer->pld_ptr; ++ } ++ ++ return parse_l4(pkt, next_proto, layer->pld_ptr, layer->pld_len); ++} ++ ++static inline const char *parse_auth(struct packet *pkt, const char *data, uint16_t len) ++{ ++ /* ++ * https://datatracker.ietf.org/doc/html/rfc4302#section-2 ++ * For IPv4: AH not IPv4 option, as an single layer ++ * For IPv6: AH as IPv6 extension header ++ * ++ * AH Format ++ * ++ * 0 1 2 3 ++ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 ++ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++ * | Next Header | Payload Len | RESERVED | ++ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++ * | Security Parameters Index (SPI) | ++ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++ * | Sequence Number Field | ++ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++ * | | ++ * + Integrity Check Value-ICV (variable) | ++ * | | ++ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++ */ ++ ++ if (unlikely(len < 12)) ++ { ++ PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_IPAH); ++ return data; ++ } ++ /* ++ * https://datatracker.ietf.org/doc/html/rfc4302#section-2 ++ * For IPv4, This 8-bit field specifies the length of AH in 32-bit words (4-byte units), minus "2". ++ * Thus, for example, if an integrity algorithm yields a 96-bit authentication value, ++ * this length field will be "4" (3 32-bit word fixed fields plus 3 32-bit words for the ICV, minus 2). ++ */ ++ uint8_t next_proto = ((const uint8_t *)data)[0]; ++ uint16_t hdr_len = ((const uint8_t *)data)[1] * 4 + 8; ++ if (unlikely(len < hdr_len)) ++ { ++ PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_IPAH); ++ return data; ++ } ++ ++ struct layer_private *layer = get_free_layer(pkt); ++ if (unlikely(layer == NULL)) ++ { ++ return data; ++ } ++ SET_LAYER(pkt, layer, LAYER_PROTO_IPAH, hdr_len, data, len, 0); ++ ++ return parse_l4(pkt, next_proto, layer->pld_ptr, layer->pld_len); ++} ++ ++static inline const char *parse_gre(struct packet *pkt, const char *data, uint16_t len) ++{ ++ uint16_t hdr_len = calc_gre_hdr_len(data, len); ++ if (unlikely(hdr_len == 0 || hdr_len > len)) ++ { ++ PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_GRE); ++ return data; ++ } ++ ++ struct layer_private *layer = get_free_layer(pkt); ++ if (unlikely(layer == NULL)) ++ { ++ return data; ++ } ++ uint16_t next_proto = peek_gre_proto(data, len); ++ SET_LAYER(pkt, layer, LAYER_PROTO_GRE, hdr_len, data, len, 0); ++ ++ return parse_l3(pkt, next_proto, layer->pld_ptr, layer->pld_len); ++} ++ ++static inline const char *parse_udp(struct packet *pkt, const char *data, uint16_t len) ++{ ++ if (unlikely(len < sizeof(struct udphdr))) ++ { ++ PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_UDP); ++ return data; ++ } ++ ++ struct layer_private *layer = get_free_layer(pkt); ++ if (unlikely(layer == NULL)) ++ { ++ return data; ++ } ++ const struct udphdr *udp_hdr = (struct udphdr *)data; ++ SET_LAYER(pkt, layer, LAYER_PROTO_UDP, sizeof(struct udphdr), data, len, 0); ++ ++ uint16_t src_port = udp_hdr_get_src_port(udp_hdr); ++ uint16_t dst_port = udp_hdr_get_dst_port(udp_hdr); ++ ++ if (dst_port == 4789) ++ { ++ // VXLAN_DPORT 4789 ++ return parse_vxlan(pkt, layer->pld_ptr, layer->pld_len); ++ } ++ ++ if (dst_port == 2152 || src_port == 2152) ++ { ++ // only GTPv1-U, no GTPv2-U ++ return parse_gtp_u(pkt, layer->pld_ptr, layer->pld_len); ++ } ++ ++ if (dst_port == 2123 || src_port == 2123) ++ { ++ // GTPv1-C or GTPv2-C ++ return parse_gtp_c(pkt, layer->pld_ptr, layer->pld_len); ++ } ++ ++ if (dst_port == 1701 || src_port == 1701) ++ { ++ // L2TP_DPORT 1701 ++ if (unlikely(layer->pld_len < 8)) ++ { ++ return layer->pld_ptr; ++ } ++ ++ switch (l2tp_hdr_get_ver((const struct l2tp_hdr *)layer->pld_ptr)) ++ { ++ case 2: ++ return parse_l2tpv2_over_udp(pkt, layer->pld_ptr, layer->pld_len); ++ case 3: ++ return parse_l2tpv3_over_udp(pkt, layer->pld_ptr, layer->pld_len); ++ default: ++ return layer->pld_ptr; ++ } ++ } ++ ++ if (dst_port == 3544 || src_port == 3544) ++ { ++ // Teredo IPv6 tunneling 3544 ++ if (unlikely(layer->pld_len < sizeof(struct ip6_hdr))) ++ { ++ return layer->pld_ptr; ++ } ++ const struct ip6_hdr *ipv6_hdr = (const struct ip6_hdr *)layer->pld_ptr; ++ if (ip6_hdr_get_version(ipv6_hdr) != 6) ++ { ++ return layer->pld_ptr; ++ } ++ return parse_ipv6(pkt, layer->pld_ptr, layer->pld_len); ++ } ++ ++ return layer->pld_ptr; ++} ++ ++static inline const char *parse_tcp(struct packet *pkt, const char *data, uint16_t len) ++{ ++ if (unlikely(len < sizeof(struct tcphdr))) ++ { ++ PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_TCP); ++ return data; ++ } ++ ++ struct layer_private *layer = get_free_layer(pkt); ++ if (unlikely(layer == NULL)) ++ { ++ return data; ++ } ++ uint16_t hdr_len = tcp_hdr_get_hdr_len((const struct tcphdr *)data); ++ if (unlikely(hdr_len > len)) ++ { ++ PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_TCP); ++ return data; ++ } ++ SET_LAYER(pkt, layer, LAYER_PROTO_TCP, hdr_len, data, len, 0); ++ ++ return layer->pld_ptr; ++} ++ ++static inline const char *parse_icmp(struct packet *pkt, const char *data, uint16_t len) ++{ ++ if (unlikely(len < sizeof(struct icmphdr))) ++ { ++ PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_ICMP); ++ return data; ++ } ++ ++ struct layer_private *layer = get_free_layer(pkt); ++ if (unlikely(layer == NULL)) ++ { ++ return data; ++ } ++ SET_LAYER(pkt, layer, LAYER_PROTO_ICMP, sizeof(struct icmphdr), data, len, 0); ++ ++ return layer->pld_ptr; ++} ++ ++static inline const char *parse_icmp6(struct packet *pkt, const char *data, uint16_t len) ++{ ++ if (unlikely(len < sizeof(struct icmp6_hdr))) ++ { ++ PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_ICMP6); ++ return data; ++ } ++ ++ struct layer_private *layer = get_free_layer(pkt); ++ if (unlikely(layer == NULL)) ++ { ++ return data; ++ } ++ SET_LAYER(pkt, layer, LAYER_PROTO_ICMP6, sizeof(struct icmp6_hdr), data, len, 0); ++ ++ return layer->pld_ptr; ++} ++ ++static inline const char *parse_vxlan(struct packet *pkt, const char *data, uint16_t len) ++{ ++ if (unlikely(len < sizeof(struct vxlan_hdr))) ++ { ++ PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_VXLAN); ++ return data; ++ } ++ ++ struct layer_private *layer = get_free_layer(pkt); ++ if (unlikely(layer == NULL)) ++ { ++ return data; ++ } ++ SET_LAYER(pkt, layer, LAYER_PROTO_VXLAN, sizeof(struct vxlan_hdr), data, len, 0); ++ ++ return parse_ether(pkt, layer->pld_ptr, layer->pld_len); ++} ++ ++static inline const char *parse_gtp_u(struct packet *pkt, const char *data, uint16_t len) ++{ ++ // only GTPv1-U, no GTPv2-U ++ uint8_t version = peek_gtp_version(data, len); ++ if (unlikely(version != 1)) ++ { ++ return data; ++ } ++ ++ uint16_t hdr_len = calc_gtp_hdr_len(data, len); ++ if (unlikely(hdr_len == 0 || hdr_len > len)) ++ { ++ PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_GTP_U); ++ return data; ++ } ++ ++ uint8_t next_proto = (((const uint8_t *)(data + hdr_len))[0]) >> 4; ++ if (next_proto != 4 && next_proto != 6) ++ { ++ // next_proto is not IPv4 or IPv6, this is not a normal GTP-U packet, fallback to UDP ++ return data; ++ } ++ ++ struct layer_private *layer = get_free_layer(pkt); ++ if (unlikely(layer == NULL)) ++ { ++ return data; ++ } ++ SET_LAYER(pkt, layer, LAYER_PROTO_GTP_U, hdr_len, data, len, 0); ++ ++ switch (next_proto) ++ { ++ case 4: ++ return parse_ipv4(pkt, layer->pld_ptr, layer->pld_len); ++ case 6: ++ return parse_ipv6(pkt, layer->pld_ptr, layer->pld_len); ++ default: ++ PACKET_LOG_UNSUPPORT_PROTO(pkt, LAYER_PROTO_GTP_U, next_proto); ++ return layer->pld_ptr; ++ } ++} ++ ++static inline const char *parse_gtp_c(struct packet *pkt, const char *data, uint16_t len) ++{ ++ // GTPv1-C or GTPv2-C ++ uint16_t hdr_len = calc_gtp_hdr_len(data, len); ++ if (unlikely(hdr_len == 0 || hdr_len > len)) ++ { ++ PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_GTP_C); ++ return data; ++ } ++ ++ struct layer_private *layer = get_free_layer(pkt); ++ if (unlikely(layer == NULL)) ++ { ++ return data; ++ } ++ SET_LAYER(pkt, layer, LAYER_PROTO_GTP_C, hdr_len, data, len, 0); ++ ++ return layer->pld_ptr; ++} ++ ++static inline const char *parse_l3(struct packet *pkt, uint16_t next_proto, const char *data, uint16_t len) ++{ ++ switch (next_proto) ++ { ++ case ETH_P_8021Q: ++ case ETH_P_8021AD: ++ return parse_vlan(pkt, data, len); ++ case ETH_P_IP: ++ return parse_ipv4(pkt, data, len); ++ case ETH_P_IPV6: ++ return parse_ipv6(pkt, data, len); ++ case ETH_P_PPP_SES: ++ return parse_pppoe_ses(pkt, data, len); ++ case ETH_P_MPLS_UC: ++ return parse_mpls(pkt, data, len); ++ case 0x880b: ++ return parse_ppp(pkt, data, len); ++ default: ++ PACKET_LOG_UNSUPPORT_ETHPROTO(pkt, next_proto); ++ return data; ++ } ++} ++ ++static inline const char *parse_l4(struct packet *pkt, uint8_t next_proto, const char *data, uint16_t len) ++{ ++ switch (next_proto) ++ { ++ case IPPROTO_AH: ++ return parse_auth(pkt, data, len); ++ case IPPROTO_TCP: ++ return parse_tcp(pkt, data, len); ++ case IPPROTO_UDP: ++ return parse_udp(pkt, data, len); ++ case IPPROTO_IPIP: ++ return parse_ipv4(pkt, data, len); ++ case IPPROTO_IPV6: ++ return parse_ipv6(pkt, data, len); ++ case IPPROTO_GRE: ++ return parse_gre(pkt, data, len); ++ case IPPROTO_ICMP: ++ return parse_icmp(pkt, data, len); ++ case IPPROTO_ICMPV6: ++ return parse_icmp6(pkt, data, len); ++ case 115: ++ // L2TP ++ return parse_l2tpv3_over_ip(pkt, data, len); ++ default: ++ PACKET_LOG_UNSUPPORT_IPPROTO(pkt, next_proto); ++ return data; ++ } ++} ++ ++/****************************************************************************** ++ * Public API ++ ******************************************************************************/ ++ ++// return innermost payload ++const char *packet_parse(struct packet *pkt, const char *data, uint16_t len) ++{ ++ pkt->frag_layer = NULL; ++ pkt->layers_used = 0; ++ pkt->layers_size = PACKET_MAX_LAYERS; ++ pkt->data_ptr = data; ++ pkt->data_len = len; ++ pkt->trim_len = 0; ++ ++ return parse_ether(pkt, data, len); ++} ++ ++const char *layer_proto_to_str(enum layer_proto proto) ++{ ++ switch (proto) ++ { ++ case LAYER_PROTO_ETHER: ++ return "ETH"; ++ case LAYER_PROTO_PWETH: ++ return "PWETH"; ++ case LAYER_PROTO_PPP: ++ return "PPP"; ++ case LAYER_PROTO_L2TP: ++ return "L2TP"; ++ case LAYER_PROTO_VLAN: ++ return "VLAN"; ++ case LAYER_PROTO_PPPOE: ++ return "PPPOE"; ++ case LAYER_PROTO_MPLS: ++ return "MPLS"; ++ case LAYER_PROTO_IPV4: ++ return "IPV4"; ++ case LAYER_PROTO_IPV6: ++ return "IPV6"; ++ case LAYER_PROTO_IPAH: ++ return "IPAH"; ++ case LAYER_PROTO_GRE: ++ return "GRE"; ++ case LAYER_PROTO_UDP: ++ return "UDP"; ++ case LAYER_PROTO_TCP: ++ return "TCP"; ++ case LAYER_PROTO_ICMP: ++ return "ICMP"; ++ case LAYER_PROTO_ICMP6: ++ return "ICMP6"; ++ case LAYER_PROTO_VXLAN: ++ return "VXLAN"; ++ case LAYER_PROTO_GTP_C: ++ return "GTP-C"; ++ case LAYER_PROTO_GTP_U: ++ return "GTP-U"; ++ default: ++ return "UNKNOWN"; ++ } ++} +\ No newline at end of file +diff -uNr tcpdump-tcpdump-4.99.4/packet_utils.c tcpdump-for-stellar/packet_utils.c +--- tcpdump-tcpdump-4.99.4/packet_utils.c 1970-01-01 08:00:00.000000000 +0800 ++++ tcpdump-for-stellar/packet_utils.c 2024-10-30 17:34:06.265498697 +0800 +@@ -0,0 +1,966 @@ ++#include <assert.h> ++ ++#include "tuple.h" ++#include "uthash.h" ++#include "log_internal.h" ++#include "packet_helper.h" ++#include "packet_internal.h" ++#include "stellar/exdata.h" ++ ++#define PACKET_LOG_ERROR(format, ...) STELLAR_LOG_ERROR(__thread_local_logger, "packet", format, ##__VA_ARGS__) ++ ++/****************************************************************************** ++ * metadata utils ++ ******************************************************************************/ ++ ++void packet_set_route_ctx(struct packet *pkt, const struct route_ctx *ctx) ++{ ++ pkt->meta.route_ctx = *ctx; ++} ++ ++const struct route_ctx *packet_get_route_ctx(const struct packet *pkt) ++{ ++ return &pkt->meta.route_ctx; ++} ++ ++void packet_set_origin_ctx(struct packet *pkt, void *ctx) ++{ ++ pkt->meta.origin_ctx = ctx; ++} ++ ++const void *packet_get_origin_ctx(const struct packet *pkt) ++{ ++ return pkt->meta.origin_ctx; ++} ++ ++void packet_set_sids(struct packet *pkt, const struct sids *sids) ++{ ++ pkt->meta.sids = *sids; ++} ++ ++const struct sids *packet_get_sids(const struct packet *pkt) ++{ ++ return &pkt->meta.sids; ++} ++ ++void packet_prepend_sids(struct packet *pkt, const struct sids *sids) ++{ ++ if (pkt->meta.sids.used + sids->used > MAX_SIDS) ++ { ++ PACKET_LOG_ERROR("sids overflow"); ++ return; ++ } ++ else ++ { ++ for (int i = pkt->meta.sids.used - 1; i >= 0; i--) ++ { ++ pkt->meta.sids.sid[i + sids->used] = pkt->meta.sids.sid[i]; ++ } ++ for (int i = 0; i < sids->used; i++) ++ { ++ pkt->meta.sids.sid[i] = sids->sid[i]; ++ } ++ pkt->meta.sids.used += sids->used; ++ } ++} ++ ++void packet_set_session_id(struct packet *pkt, uint64_t id) ++{ ++ pkt->meta.session_id = id; ++} ++ ++uint64_t packet_get_session_id(const struct packet *pkt) ++{ ++ return pkt->meta.session_id; ++} ++ ++void packet_set_domain(struct packet *pkt, uint64_t domain) ++{ ++ pkt->meta.domain = domain; ++} ++ ++uint64_t packet_get_domain(const struct packet *pkt) ++{ ++ return pkt->meta.domain; ++} ++ ++void packet_set_link_id(struct packet *pkt, uint16_t id) ++{ ++ pkt->meta.link_id = id; ++} ++ ++uint16_t packet_get_link_id(const struct packet *pkt) ++{ ++ return pkt->meta.link_id; ++} ++ ++void packet_set_ctrl(struct packet *pkt, bool ctrl) ++{ ++ pkt->meta.is_ctrl = ctrl; ++} ++ ++bool packet_is_ctrl(const struct packet *pkt) ++{ ++ return pkt->meta.is_ctrl; ++} ++ ++void packet_set_claim(struct packet *pkt, bool claim) ++{ ++ pkt->meta.is_claim = claim; ++} ++ ++bool packet_is_claim(const struct packet *pkt) ++{ ++ return pkt->meta.is_claim; ++} ++ ++void packet_set_direction(struct packet *pkt, enum packet_direction dir) ++{ ++ pkt->meta.direction = dir; ++} ++ ++enum packet_direction packet_get_direction(const struct packet *pkt) ++{ ++ return pkt->meta.direction; ++} ++ ++void packet_set_action(struct packet *pkt, enum packet_action action) ++{ ++ pkt->meta.action = action; ++} ++ ++enum packet_action packet_get_action(const struct packet *pkt) ++{ ++ return pkt->meta.action; ++} ++ ++void packet_set_timeval(struct packet *pkt, const struct timeval *tv) ++{ ++ pkt->meta.tv = *tv; ++} ++ ++const struct timeval *packet_get_timeval(const struct packet *pkt) ++{ ++ return &pkt->meta.tv; ++} ++ ++void packet_set_user_data(struct packet *pkt, void *data) ++{ ++ pkt->user_data = data; ++} ++ ++void *packet_get_user_data(struct packet *pkt) ++{ ++ return pkt->user_data; ++} ++ ++/****************************************************************************** ++ * tuple uitls ++ ******************************************************************************/ ++ ++// return 0 : found ++// return -1 : not found ++int packet_get_innermost_tuple2(const struct packet *pkt, struct tuple2 *tuple) ++{ ++ memset(tuple, 0, sizeof(struct tuple2)); ++ const struct layer_private *layer = NULL; ++ ++ for (int8_t i = pkt->layers_used - 1; i >= 0; i--) ++ { ++ layer = &pkt->layers[i]; ++ ++ if (layer->proto == LAYER_PROTO_IPV4) ++ { ++ const struct ip *ip4_hdr = (const struct ip *)layer->hdr_ptr; ++ tuple->addr_family = AF_INET; ++ tuple->src_addr.v4 = ip4_hdr_get_src_in_addr(ip4_hdr); ++ tuple->dst_addr.v4 = ip4_hdr_get_dst_in_addr(ip4_hdr); ++ return 0; ++ } ++ if (layer->proto == LAYER_PROTO_IPV6) ++ { ++ const struct ip6_hdr *ip6_hdr = (const struct ip6_hdr *)layer->hdr_ptr; ++ tuple->addr_family = AF_INET6; ++ tuple->src_addr.v6 = ip6_hdr_get_src_in6_addr(ip6_hdr); ++ tuple->dst_addr.v6 = ip6_hdr_get_dst_in6_addr(ip6_hdr); ++ return 0; ++ } ++ } ++ ++ return -1; ++} ++ ++// return 0 : found ++// return -1 : not found ++int packet_get_outermost_tuple2(const struct packet *pkt, struct tuple2 *tuple) ++{ ++ memset(tuple, 0, sizeof(struct tuple2)); ++ const struct layer_private *layer = NULL; ++ ++ for (int8_t i = 0; i < pkt->layers_used; i++) ++ { ++ layer = &pkt->layers[i]; ++ ++ if (layer->proto == LAYER_PROTO_IPV4) ++ { ++ const struct ip *ip4_hdr = (const struct ip *)layer->hdr_ptr; ++ tuple->addr_family = AF_INET; ++ tuple->src_addr.v4 = ip4_hdr_get_src_in_addr(ip4_hdr); ++ tuple->dst_addr.v4 = ip4_hdr_get_dst_in_addr(ip4_hdr); ++ return 0; ++ } ++ if (layer->proto == LAYER_PROTO_IPV6) ++ { ++ const struct ip6_hdr *ip6_hdr = (const struct ip6_hdr *)layer->hdr_ptr; ++ tuple->addr_family = AF_INET6; ++ tuple->src_addr.v6 = ip6_hdr_get_src_in6_addr(ip6_hdr); ++ tuple->dst_addr.v6 = ip6_hdr_get_dst_in6_addr(ip6_hdr); ++ return 0; ++ } ++ } ++ ++ return -1; ++} ++ ++// return 0 : found ++// return -1 : not found ++int packet_get_innermost_tuple4(const struct packet *pkt, struct tuple4 *tuple) ++{ ++ memset(tuple, 0, sizeof(struct tuple4)); ++ const struct layer_private *layer_l3 = NULL; ++ const struct layer_private *layer_l4 = NULL; ++ const struct layer_private *layer = NULL; ++ ++ for (int8_t i = pkt->layers_used - 1; i >= 0; i--) ++ { ++ layer = &pkt->layers[i]; ++ ++ // first get L4 layer ++ if (layer->proto == LAYER_PROTO_UDP) ++ { ++ const struct udphdr *udp_hdr = (const struct udphdr *)layer->hdr_ptr; ++ tuple->src_port = udp_hdr->uh_sport; ++ tuple->dst_port = udp_hdr->uh_dport; ++ layer_l4 = layer; ++ continue; ++ } ++ if (layer->proto == LAYER_PROTO_TCP) ++ { ++ const struct tcphdr *tcp_hdr = (const struct tcphdr *)layer->hdr_ptr; ++ tuple->src_port = tcp_hdr->th_sport; ++ tuple->dst_port = tcp_hdr->th_dport; ++ layer_l4 = layer; ++ continue; ++ } ++ ++ // second get L3 layer ++ if (layer->proto == LAYER_PROTO_IPV4) ++ { ++ const struct ip *ip4_hdr = (const struct ip *)layer->hdr_ptr; ++ tuple->addr_family = AF_INET; ++ tuple->src_addr.v4 = ip4_hdr_get_src_in_addr(ip4_hdr); ++ tuple->dst_addr.v4 = ip4_hdr_get_dst_in_addr(ip4_hdr); ++ layer_l3 = layer; ++ break; ++ } ++ if (layer->proto == LAYER_PROTO_IPV6) ++ { ++ const struct ip6_hdr *ip6_hdr = (const struct ip6_hdr *)layer->hdr_ptr; ++ tuple->addr_family = AF_INET6; ++ tuple->src_addr.v6 = ip6_hdr_get_src_in6_addr(ip6_hdr); ++ tuple->dst_addr.v6 = ip6_hdr_get_dst_in6_addr(ip6_hdr); ++ layer_l3 = layer; ++ break; ++ } ++ } ++ ++ if (layer_l3 && layer_l4 && layer_l4 - layer_l3 == 1) ++ { ++ return 0; ++ } ++ else ++ { ++ return -1; ++ } ++} ++ ++// return 0 : found ++// return -1 : not found ++int packet_get_outermost_tuple4(const struct packet *pkt, struct tuple4 *tuple) ++{ ++ memset(tuple, 0, sizeof(struct tuple4)); ++ const struct layer_private *layer_l3 = NULL; ++ const struct layer_private *layer_l4 = NULL; ++ const struct layer_private *layer = NULL; ++ ++ for (int8_t i = 0; i < pkt->layers_used; i++) ++ { ++ layer = &pkt->layers[i]; ++ ++ // first get L3 layer ++ if (layer->proto == LAYER_PROTO_IPV4) ++ { ++ const struct ip *ip4_hdr = (const struct ip *)layer->hdr_ptr; ++ tuple->addr_family = AF_INET; ++ tuple->src_addr.v4 = ip4_hdr_get_src_in_addr(ip4_hdr); ++ tuple->dst_addr.v4 = ip4_hdr_get_dst_in_addr(ip4_hdr); ++ layer_l3 = layer; ++ continue; ++ } ++ if (layer->proto == LAYER_PROTO_IPV6) ++ { ++ const struct ip6_hdr *ip6_hdr = (const struct ip6_hdr *)layer->hdr_ptr; ++ tuple->addr_family = AF_INET6; ++ tuple->src_addr.v6 = ip6_hdr_get_src_in6_addr(ip6_hdr); ++ tuple->dst_addr.v6 = ip6_hdr_get_dst_in6_addr(ip6_hdr); ++ layer_l3 = layer; ++ continue; ++ } ++ ++ // second get L4 layer ++ if (layer->proto == LAYER_PROTO_UDP) ++ { ++ const struct udphdr *udp_hdr = (const struct udphdr *)layer->hdr_ptr; ++ tuple->src_port = udp_hdr->uh_sport; ++ tuple->dst_port = udp_hdr->uh_dport; ++ layer_l4 = layer; ++ break; ++ } ++ if (layer->proto == LAYER_PROTO_TCP) ++ { ++ const struct tcphdr *tcp_hdr = (const struct tcphdr *)layer->hdr_ptr; ++ tuple->src_port = tcp_hdr->th_sport; ++ tuple->dst_port = tcp_hdr->th_dport; ++ layer_l4 = layer; ++ break; ++ } ++ } ++ ++ if (layer_l3 && layer_l4 && layer_l4 - layer_l3 == 1) ++ { ++ return 0; ++ } ++ else ++ { ++ return -1; ++ } ++} ++ ++// return 0 : found ++// return -1 : not found ++int packet_get_innermost_tuple6(const struct packet *pkt, struct tuple6 *tuple) ++{ ++ memset(tuple, 0, sizeof(struct tuple6)); ++ const struct layer_private *layer_l3 = NULL; ++ const struct layer_private *layer_l4 = NULL; ++ const struct layer_private *layer = NULL; ++ ++ for (int8_t i = pkt->layers_used - 1; i >= 0; i--) ++ { ++ layer = &pkt->layers[i]; ++ ++ // first get L4 layer ++ if (layer->proto == LAYER_PROTO_UDP) ++ { ++ const struct udphdr *udp_hdr = (const struct udphdr *)layer->hdr_ptr; ++ tuple->ip_proto = IPPROTO_UDP; ++ tuple->src_port = udp_hdr->uh_sport; ++ tuple->dst_port = udp_hdr->uh_dport; ++ layer_l4 = layer; ++ continue; ++ } ++ if (layer->proto == LAYER_PROTO_TCP) ++ { ++ const struct tcphdr *tcp_hdr = (const struct tcphdr *)layer->hdr_ptr; ++ tuple->ip_proto = IPPROTO_TCP; ++ tuple->src_port = tcp_hdr->th_sport; ++ tuple->dst_port = tcp_hdr->th_dport; ++ layer_l4 = layer; ++ continue; ++ } ++ ++ // second get L3 layer ++ if (layer->proto == LAYER_PROTO_IPV4) ++ { ++ const struct ip *ip4_hdr = (const struct ip *)layer->hdr_ptr; ++ tuple->addr_family = AF_INET; ++ tuple->src_addr.v4 = ip4_hdr_get_src_in_addr(ip4_hdr); ++ tuple->dst_addr.v4 = ip4_hdr_get_dst_in_addr(ip4_hdr); ++ layer_l3 = layer; ++ break; ++ } ++ if (layer->proto == LAYER_PROTO_IPV6) ++ { ++ const struct ip6_hdr *ip6_hdr = (const struct ip6_hdr *)layer->hdr_ptr; ++ tuple->addr_family = AF_INET6; ++ tuple->src_addr.v6 = ip6_hdr_get_src_in6_addr(ip6_hdr); ++ tuple->dst_addr.v6 = ip6_hdr_get_dst_in6_addr(ip6_hdr); ++ layer_l3 = layer; ++ break; ++ } ++ } ++ ++ if (layer_l3 && layer_l4 && layer_l4 - layer_l3 == 1) ++ { ++ tuple->domain = packet_get_domain(pkt); ++ return 0; ++ } ++ else ++ { ++ return -1; ++ } ++} ++ ++// return 0 : found ++// return -1 : not found ++int packet_get_outermost_tuple6(const struct packet *pkt, struct tuple6 *tuple) ++{ ++ memset(tuple, 0, sizeof(struct tuple6)); ++ const struct layer_private *layer_l3 = NULL; ++ const struct layer_private *layer_l4 = NULL; ++ const struct layer_private *layer = NULL; ++ ++ for (int8_t i = 0; i < pkt->layers_used; i++) ++ { ++ layer = &pkt->layers[i]; ++ ++ // first get L3 layer ++ if (layer->proto == LAYER_PROTO_IPV4) ++ { ++ const struct ip *ip4_hdr = (const struct ip *)layer->hdr_ptr; ++ tuple->addr_family = AF_INET; ++ tuple->src_addr.v4 = ip4_hdr_get_src_in_addr(ip4_hdr); ++ tuple->dst_addr.v4 = ip4_hdr_get_dst_in_addr(ip4_hdr); ++ layer_l3 = layer; ++ continue; ++ } ++ if (layer->proto == LAYER_PROTO_IPV6) ++ { ++ const struct ip6_hdr *ip6_hdr = (const struct ip6_hdr *)layer->hdr_ptr; ++ tuple->addr_family = AF_INET6; ++ tuple->src_addr.v6 = ip6_hdr_get_src_in6_addr(ip6_hdr); ++ tuple->dst_addr.v6 = ip6_hdr_get_dst_in6_addr(ip6_hdr); ++ layer_l3 = layer; ++ continue; ++ } ++ ++ // second get L4 layer ++ if (layer->proto == LAYER_PROTO_UDP) ++ { ++ const struct udphdr *udp_hdr = (const struct udphdr *)layer->hdr_ptr; ++ tuple->ip_proto = IPPROTO_UDP; ++ tuple->src_port = udp_hdr->uh_sport; ++ tuple->dst_port = udp_hdr->uh_dport; ++ layer_l4 = layer; ++ break; ++ } ++ if (layer->proto == LAYER_PROTO_TCP) ++ { ++ const struct tcphdr *tcp_hdr = (const struct tcphdr *)layer->hdr_ptr; ++ tuple->ip_proto = IPPROTO_TCP; ++ tuple->src_port = tcp_hdr->th_sport; ++ tuple->dst_port = tcp_hdr->th_dport; ++ layer_l4 = layer; ++ break; ++ } ++ } ++ ++ if (layer_l3 && layer_l4 && layer_l4 - layer_l3 == 1) ++ { ++ tuple->domain = packet_get_domain(pkt); ++ return 0; ++ } ++ else ++ { ++ return -1; ++ } ++} ++ ++/****************************************************************************** ++ * layer uitls ++ ******************************************************************************/ ++ ++int packet_get_layer_count(const struct packet *pkt) ++{ ++ return pkt->layers_used; ++} ++ ++const struct layer *packet_get_layer_by_idx(const struct packet *pkt, int idx) ++{ ++ const struct layer_private *layer = packet_get_layer(pkt, idx); ++ if (layer == NULL) ++ { ++ return NULL; ++ } ++ else ++ { ++ return (const struct layer *)layer; ++ } ++} ++ ++const struct layer_private *packet_get_layer(const struct packet *pkt, int idx) ++{ ++ if (idx < 0 || idx >= pkt->layers_used) ++ { ++ return NULL; ++ } ++ return &pkt->layers[idx]; ++} ++ ++const struct layer_private *packet_get_innermost_layer(const struct packet *pkt, enum layer_proto proto) ++{ ++ const struct layer_private *layer = NULL; ++ ++ for (int8_t i = pkt->layers_used - 1; i >= 0; i--) ++ { ++ layer = &pkt->layers[i]; ++ if (layer->proto == proto) ++ { ++ return layer; ++ } ++ } ++ ++ return NULL; ++} ++ ++const struct layer_private *packet_get_outermost_layer(const struct packet *pkt, enum layer_proto proto) ++{ ++ const struct layer_private *layer = NULL; ++ ++ for (int8_t i = 0; i < pkt->layers_used; i++) ++ { ++ layer = &pkt->layers[i]; ++ if (layer->proto == proto) ++ { ++ return layer; ++ } ++ } ++ ++ return NULL; ++} ++ ++/****************************************************************************** ++ * tunnel uitls ++ ******************************************************************************/ ++ ++struct tunnel_detector ++{ ++ enum tunnel_type type; ++ int contain_layers; ++ int (*identify_func)(const struct layer_private *curr, const struct layer_private *next1, const struct layer_private *next2); ++}; ++ ++static int is_ipv4_tunnel(const struct layer_private *curr, const struct layer_private *next1, const struct layer_private *next2 __attribute__((unused))) ++{ ++ if (curr && curr->proto == LAYER_PROTO_IPV4 && ++ next1 && (next1->proto == LAYER_PROTO_IPV4 || next1->proto == LAYER_PROTO_IPV6)) ++ { ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static int is_ipv6_tunnel(const struct layer_private *curr, const struct layer_private *next1, const struct layer_private *next2 __attribute__((unused))) ++{ ++ if (curr && curr->proto == LAYER_PROTO_IPV6 && ++ next1 && (next1->proto == LAYER_PROTO_IPV4 || next1->proto == LAYER_PROTO_IPV6)) ++ { ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static int is_gre_tunnel(const struct layer_private *curr, const struct layer_private *next1, const struct layer_private *next2 __attribute__((unused))) ++{ ++ if (curr && (curr->proto == LAYER_PROTO_IPV4 || curr->proto == LAYER_PROTO_IPV6) && ++ next1 && next1->proto == LAYER_PROTO_GRE) ++ { ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static int is_gtp_tunnel(const struct layer_private *curr, const struct layer_private *next1, const struct layer_private *next2) ++{ ++ if (curr && (curr->proto == LAYER_PROTO_IPV4 || curr->proto == LAYER_PROTO_IPV6) && ++ next1 && next1->proto == LAYER_PROTO_UDP && ++ next2 && next2->proto == LAYER_PROTO_GTP_U) ++ { ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static int is_vxlan_tunnel(const struct layer_private *curr, const struct layer_private *next1, const struct layer_private *next2) ++{ ++ if (curr && (curr->proto == LAYER_PROTO_IPV4 || curr->proto == LAYER_PROTO_IPV6) && ++ next1 && next1->proto == LAYER_PROTO_UDP && ++ next2 && next2->proto == LAYER_PROTO_VXLAN) ++ { ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static int is_l2tp_tunnel(const struct layer_private *curr, const struct layer_private *next1, const struct layer_private *next2) ++{ ++ if (curr && (curr->proto == LAYER_PROTO_IPV4 || curr->proto == LAYER_PROTO_IPV6) && ++ next1 && next1->proto == LAYER_PROTO_UDP && ++ next2 && next2->proto == LAYER_PROTO_L2TP) ++ { ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static int is_teredo_tunnel(const struct layer_private *curr, const struct layer_private *next1, const struct layer_private *next2) ++{ ++ if (curr && curr->proto == LAYER_PROTO_IPV4 && ++ next1 && next1->proto == LAYER_PROTO_UDP && ++ next2 && next2->proto == LAYER_PROTO_IPV6) ++ { ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static struct tunnel_detector detectors[] = { ++ {TUNNEL_IPV4, 1, is_ipv4_tunnel}, ++ {TUNNEL_IPV6, 1, is_ipv6_tunnel}, ++ {TUNNEL_GRE, 2, is_gre_tunnel}, ++ {TUNNEL_GTP, 3, is_gtp_tunnel}, ++ {TUNNEL_VXLAN, 3, is_vxlan_tunnel}, ++ {TUNNEL_L2TP, 3, is_l2tp_tunnel}, ++ {TUNNEL_TEREDO, 2, is_teredo_tunnel}, ++}; ++ ++// return index of detectors ++static int detect_tunnel(const struct layer_private *curr, const struct layer_private *next1, const struct layer_private *next2) ++{ ++ for (int i = 0; i < (int)(sizeof(detectors) / sizeof(detectors[0])); i++) ++ { ++ if (detectors[i].identify_func(curr, next1, next2)) ++ { ++ return i; ++ } ++ } ++ ++ return -1; ++} ++ ++int packet_get_tunnel_count(const struct packet *pkt) ++{ ++ int count = 0; ++ int used = packet_get_layer_count(pkt); ++ const struct layer_private *curr = NULL; ++ const struct layer_private *next1 = NULL; ++ const struct layer_private *next2 = NULL; ++ ++ for (int i = 0; i < used; i++) ++ { ++ curr = packet_get_layer(pkt, i); ++ next1 = packet_get_layer(pkt, i + 1); ++ next2 = packet_get_layer(pkt, i + 2); ++ if (detect_tunnel(curr, next1, next2) >= 0) ++ { ++ count++; ++ } ++ } ++ ++ return count; ++} ++ ++// return 0: success ++// return -1: failed ++int packet_get_tunnel_by_idx(const struct packet *pkt, int idx, struct tunnel *out) ++{ ++ int ret = -1; ++ int count = 0; ++ int used = packet_get_layer_count(pkt); ++ const struct layer_private *curr = NULL; ++ const struct layer_private *next1 = NULL; ++ const struct layer_private *next2 = NULL; ++ memset(out, 0, sizeof(struct tunnel)); ++ ++ for (int i = 0; i < used; i++) ++ { ++ curr = packet_get_layer(pkt, i); ++ next1 = packet_get_layer(pkt, i + 1); ++ next2 = packet_get_layer(pkt, i + 2); ++ ret = detect_tunnel(curr, next1, next2); ++ if (ret >= 0 && count++ == idx) ++ { ++ struct tunnel_detector *hit = &detectors[ret]; ++ out->type = hit->type; ++ out->layer_count = hit->contain_layers; ++ if (out->layer_count >= 1) ++ out->layers[0] = (const struct layer *)curr; ++ if (out->layer_count >= 2) ++ out->layers[1] = (const struct layer *)next1; ++ if (out->layer_count >= 3) ++ out->layers[2] = (const struct layer *)next2; ++ return 0; ++ } ++ } ++ ++ return -1; ++} ++ ++/****************************************************************************** ++ * load balance uitls ++ ******************************************************************************/ ++ ++uint64_t packet_ldbc_hash(const struct packet *pkt, enum packet_load_balance_method method, enum packet_direction direction) ++{ ++ uint64_t temp = 0; ++ uint64_t hash_value = 1; ++ ++ int inner_addr_len = 0; ++ int outer_addr_len = 0; ++ const char *inner_src_addr = NULL; ++ const char *inner_dst_addr = NULL; ++ const char *outer_src_addr = NULL; ++ const char *outer_dst_addr = NULL; ++ ++ struct tuple2 inner_addr; ++ struct tuple2 outer_addr; ++ ++ if (pkt == NULL) ++ { ++ return hash_value; ++ } ++ ++ if (packet_get_innermost_tuple2(pkt, &inner_addr) == -1) ++ { ++ return hash_value; ++ } ++ ++ if (packet_get_outermost_tuple2(pkt, &outer_addr) == -1) ++ { ++ return hash_value; ++ } ++ ++ if (inner_addr.addr_family == AF_INET) ++ { ++ inner_src_addr = (const char *)&inner_addr.src_addr.v4; ++ inner_dst_addr = (const char *)&inner_addr.dst_addr.v4; ++ inner_addr_len = sizeof(struct in_addr); ++ } ++ else ++ { ++ inner_src_addr = (const char *)&inner_addr.src_addr.v6; ++ inner_dst_addr = (const char *)&inner_addr.dst_addr.v6; ++ inner_addr_len = sizeof(struct in6_addr); ++ } ++ ++ if (outer_addr.addr_family == AF_INET) ++ { ++ outer_src_addr = (const char *)&outer_addr.src_addr.v4; ++ outer_dst_addr = (const char *)&outer_addr.dst_addr.v4; ++ outer_addr_len = sizeof(struct in_addr); ++ } ++ else ++ { ++ outer_src_addr = (const char *)&outer_addr.src_addr.v6; ++ outer_dst_addr = (const char *)&outer_addr.dst_addr.v6; ++ outer_addr_len = sizeof(struct in6_addr); ++ } ++ ++ switch (method) ++ { ++ case PKT_LDBC_METH_OUTERMOST_INT_IP: ++ if (direction == PACKET_DIRECTION_INCOMING) ++ { ++ // direction 1: E2I ++ HASH_VALUE(outer_dst_addr, outer_addr_len, hash_value); ++ } ++ else ++ { ++ // direction 0: I2E ++ HASH_VALUE(outer_src_addr, outer_addr_len, hash_value); ++ } ++ break; ++ case PKT_LDBC_METH_OUTERMOST_EXT_IP: ++ if (direction == PACKET_DIRECTION_INCOMING) ++ { ++ // direction 1: E2I ++ HASH_VALUE(outer_src_addr, outer_addr_len, hash_value); ++ } ++ else ++ { ++ // direction 0: I2E ++ HASH_VALUE(outer_dst_addr, outer_addr_len, hash_value); ++ } ++ break; ++ case PKT_LDBC_METH_OUTERMOST_INT_EXT_IP: ++ HASH_VALUE(outer_src_addr, outer_addr_len, hash_value); ++ HASH_VALUE(outer_dst_addr, outer_addr_len, temp); ++ hash_value = hash_value ^ temp; ++ break; ++ case PKT_LDBC_METH_INNERMOST_INT_IP: ++ if (direction == PACKET_DIRECTION_INCOMING) ++ { ++ // direction 1: E2I ++ HASH_VALUE(inner_dst_addr, inner_addr_len, hash_value); ++ } ++ else ++ { ++ // direction 0: I2E ++ HASH_VALUE(inner_src_addr, inner_addr_len, hash_value); ++ } ++ break; ++ case PKT_LDBC_METH_INNERMOST_EXT_IP: ++ if (direction == PACKET_DIRECTION_INCOMING) ++ { ++ // direction 1: E2I ++ HASH_VALUE(inner_src_addr, inner_addr_len, hash_value); ++ } ++ else ++ { ++ // direction 0: I2E ++ HASH_VALUE(inner_dst_addr, inner_addr_len, hash_value); ++ } ++ break; ++ default: ++ return hash_value; ++ } ++ ++ return hash_value; ++} ++ ++/****************************************************************************** ++ * other uitls ++ ******************************************************************************/ ++ ++const char *packet_get_raw_data(const struct packet *pkt) ++{ ++ return pkt->data_ptr; ++} ++ ++uint16_t packet_get_raw_len(const struct packet *pkt) ++{ ++ return pkt->data_len; ++} ++ ++const char *packet_get_payload(const struct packet *pkt) ++{ ++ if (pkt == NULL || pkt->layers_used == 0) ++ { ++ return NULL; ++ } ++ ++ if (pkt->layers[pkt->layers_used - 1].pld_len) ++ { ++ return pkt->layers[pkt->layers_used - 1].pld_ptr; ++ } ++ else ++ { ++ return NULL; ++ } ++} ++ ++uint16_t packet_get_payload_len(const struct packet *pkt) ++{ ++ if (pkt == NULL || pkt->layers_used == 0) ++ { ++ return 0; ++ } ++ return pkt->layers[pkt->layers_used - 1].pld_len; ++} ++ ++struct packet *packet_new(uint16_t pkt_len) ++{ ++ struct packet *pkt = (struct packet *)calloc(1, sizeof(struct packet) + pkt_len); ++ if (pkt == NULL) ++ { ++ return NULL; ++ } ++ pkt->data_len = pkt_len; ++ pkt->data_ptr = (const char *)pkt + sizeof(struct packet); ++ pkt->need_free = 1; ++ ++ return pkt; ++} ++ ++struct packet *packet_dup(const struct packet *pkt) ++{ ++ if (pkt == NULL) ++ { ++ return NULL; ++ } ++ ++ struct packet *dup_pkt = packet_new(pkt->data_len); ++ if (dup_pkt == NULL) ++ { ++ return NULL; ++ } ++ ++ dup_pkt->layers_used = pkt->layers_used; ++ dup_pkt->layers_size = pkt->layers_size; ++ ++ memcpy((char *)dup_pkt->data_ptr, pkt->data_ptr, pkt->data_len); ++ dup_pkt->data_len = pkt->data_len; ++ packet_set_action(dup_pkt, PACKET_ACTION_DROP); ++ ++ for (int8_t i = 0; i < pkt->layers_used; i++) ++ { ++ dup_pkt->layers[i].proto = pkt->layers[i].proto; ++ dup_pkt->layers[i].hdr_ptr = dup_pkt->data_ptr + pkt->layers[i].hdr_offset; ++ dup_pkt->layers[i].pld_ptr = dup_pkt->data_ptr + pkt->layers[i].hdr_offset + pkt->layers[i].hdr_len; ++ dup_pkt->layers[i].hdr_offset = pkt->layers[i].hdr_offset; ++ dup_pkt->layers[i].hdr_len = pkt->layers[i].hdr_len; ++ dup_pkt->layers[i].pld_len = pkt->layers[i].pld_len; ++ } ++ ++ // update frag_layer ++ if (pkt->frag_layer) ++ { ++ dup_pkt->frag_layer = &dup_pkt->layers[pkt->frag_layer - pkt->layers]; ++ } ++ memcpy(&dup_pkt->meta, &pkt->meta, sizeof(struct metadata)); ++ packet_set_origin_ctx(dup_pkt, (void *)NULL); ++ ++ return dup_pkt; ++} ++ ++void packet_free(struct packet *pkt) ++{ ++ if (pkt) ++ { ++ if (packet_is_claim(pkt)) ++ { ++ PACKET_LOG_ERROR("packet has been claimed and cannot be released, please check the module arrangement order"); ++ assert(0); ++ return; ++ } ++ ++ if (pkt->need_free) ++ { ++ free((void *)pkt); ++ } ++ } ++} ++ ++int packet_is_fragment(const struct packet *pkt) ++{ ++ return (pkt->frag_layer) ? 1 : 0; ++} ++ ++void packet_set_exdata(struct packet *pkt, int idx, void *ex_ptr) ++{ ++ struct exdata_runtime *exdata_rt = (struct exdata_runtime *)packet_get_user_data(pkt); ++ exdata_set(exdata_rt, idx, ex_ptr); ++} ++ ++void *packet_get_exdata(struct packet *pkt, int idx) ++{ ++ struct exdata_runtime *exdata_rt = (struct exdata_runtime *)packet_get_user_data(pkt); ++ return exdata_get(exdata_rt, idx); ++} +diff -uNr tcpdump-tcpdump-4.99.4/print-bfd.c tcpdump-for-stellar/print-bfd.c +--- tcpdump-tcpdump-4.99.4/print-bfd.c 2023-04-08 02:30:58.000000000 +0800 ++++ tcpdump-for-stellar/print-bfd.c 2024-10-30 17:34:05.612498702 +0800 +@@ -30,7 +30,7 @@ + #include "netdissect.h" + #include "extract.h" + +-#include "udp.h" ++#include "print-udp.h" + + /* + * Control packet, BFDv0, draft-ietf-bfd-base-01 +@@ -144,9 +144,9 @@ + }; + + static const struct tok bfd_port_values[] = { +- { BFD_CONTROL_PORT, "Control" }, +- { BFD_MULTIHOP_PORT, "Multihop" }, +- { BFD_LAG_PORT, "Lag" }, ++ { TCPDUMP_BFD_CONTROL_PORT, "Control" }, ++ { TCPDUMP_BFD_MULTIHOP_PORT, "Multihop" }, ++ { TCPDUMP_BFD_LAG_PORT, "Lag" }, + { 0, NULL } + }; + +@@ -292,9 +292,9 @@ + u_int len, u_int port) + { + ndo->ndo_protocol = "bfd"; +- if (port == BFD_CONTROL_PORT || +- port == BFD_MULTIHOP_PORT || +- port == BFD_LAG_PORT) { ++ if (port == TCPDUMP_BFD_CONTROL_PORT || ++ port == TCPDUMP_BFD_MULTIHOP_PORT || ++ port == TCPDUMP_BFD_LAG_PORT) { + /* + * Control packet. + */ +@@ -401,7 +401,7 @@ + } + break; + } +- } else if (port == BFD_ECHO_PORT) { ++ } else if (port == TCPDUMP_BFD_ECHO_PORT) { + /* + * Echo packet. + */ +diff -uNr tcpdump-tcpdump-4.99.4/print-cnfp.c tcpdump-for-stellar/print-cnfp.c +--- tcpdump-tcpdump-4.99.4/print-cnfp.c 2023-04-08 02:30:58.000000000 +0800 ++++ tcpdump-for-stellar/print-cnfp.c 2024-10-30 17:34:05.613498702 +0800 +@@ -52,7 +52,7 @@ + #include "addrtoname.h" + #include "extract.h" + +-#include "tcp.h" ++#include "print-tcp.h" + #include "ipproto.h" + + struct nfhdr_v1 { +diff -uNr tcpdump-tcpdump-4.99.4/print-dccp.c tcpdump-for-stellar/print-dccp.c +--- tcpdump-tcpdump-4.99.4/print-dccp.c 2023-04-08 02:30:58.000000000 +0800 ++++ tcpdump-for-stellar/print-dccp.c 2024-10-30 17:34:05.614498702 +0800 +@@ -20,8 +20,8 @@ + #include "netdissect.h" + #include "addrtoname.h" + #include "extract.h" +-#include "ip.h" +-#include "ip6.h" ++#include "tcpdump_ip.h" ++#include "tcpdump_ip6.h" + #include "ipproto.h" + + /* RFC4340: Datagram Congestion Control Protocol (DCCP) */ +@@ -199,14 +199,14 @@ + return (cov > len)? len : cov; + } + +-static uint16_t dccp_cksum(netdissect_options *ndo, const struct ip *ip, ++static uint16_t dccp_cksum(netdissect_options *ndo, const struct tcpdump_ip *ip, + const struct dccp_hdr *dh, u_int len) + { + return nextproto4_cksum(ndo, ip, (const uint8_t *)(const void *)dh, len, + dccp_csum_coverage(ndo, dh, len), IPPROTO_DCCP); + } + +-static uint16_t dccp6_cksum(netdissect_options *ndo, const struct ip6_hdr *ip6, ++static uint16_t dccp6_cksum(netdissect_options *ndo, const struct tcpdump_ip6_hdr *ip6, + const struct dccp_hdr *dh, u_int len) + { + return nextproto6_cksum(ndo, ip6, (const uint8_t *)(const void *)dh, len, +@@ -270,8 +270,8 @@ + u_int len) + { + const struct dccp_hdr *dh; +- const struct ip *ip; +- const struct ip6_hdr *ip6; ++ const struct tcpdump_ip *ip; ++ const struct tcpdump_ip6_hdr *ip6; + const u_char *cp; + u_short sport, dport; + u_int hlen; +@@ -281,9 +281,9 @@ + ndo->ndo_protocol = "dccp"; + dh = (const struct dccp_hdr *)bp; + +- ip = (const struct ip *)data2; ++ ip = (const struct tcpdump_ip *)data2; + if (IP_V(ip) == 6) +- ip6 = (const struct ip6_hdr *)data2; ++ ip6 = (const struct tcpdump_ip6_hdr *)data2; + else + ip6 = NULL; + +diff -uNr tcpdump-tcpdump-4.99.4/print-esp.c tcpdump-for-stellar/print-esp.c +--- tcpdump-tcpdump-4.99.4/print-esp.c 2023-04-08 02:30:58.000000000 +0800 ++++ tcpdump-for-stellar/print-esp.c 2024-10-30 17:34:05.615498702 +0800 +@@ -54,8 +54,8 @@ + #include "ascii_strcasecmp.h" + #endif + +-#include "ip.h" +-#include "ip6.h" ++#include "tcpdump_ip.h" ++#include "tcpdump_ip6.h" + + /* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. +@@ -737,7 +737,7 @@ + #ifdef HAVE_LIBCRYPTO + const struct ip *ip; + struct sa_list *sa = NULL; +- const struct ip6_hdr *ip6 = NULL; ++ const struct tcpdump_ip6_hdr *ip6 = NULL; + const u_char *iv; + u_int ivlen; + u_int payloadlen; +@@ -776,7 +776,7 @@ + ip = (const struct ip *)bp2; + switch (ver) { + case 6: +- ip6 = (const struct ip6_hdr *)bp2; ++ ip6 = (const struct tcpdump_ip6_hdr *)bp2; + /* we do not attempt to decrypt jumbograms */ + if (!GET_BE_U_2(ip6->ip6_plen)) + return; +diff -uNr tcpdump-tcpdump-4.99.4/print-frag6.c tcpdump-for-stellar/print-frag6.c +--- tcpdump-tcpdump-4.99.4/print-frag6.c 2023-04-08 02:30:58.000000000 +0800 ++++ tcpdump-for-stellar/print-frag6.c 2024-10-30 17:34:05.616498702 +0800 +@@ -30,29 +30,29 @@ + #include "netdissect.h" + #include "extract.h" + +-#include "ip6.h" ++#include "tcpdump_ip6.h" + + int + frag6_print(netdissect_options *ndo, const u_char *bp, const u_char *bp2) + { +- const struct ip6_frag *dp; +- const struct ip6_hdr *ip6; ++ const struct tcpdump_ip6_frag *dp; ++ const struct tcpdump_ip6_hdr *ip6; + + ndo->ndo_protocol = "frag6"; +- dp = (const struct ip6_frag *)bp; +- ip6 = (const struct ip6_hdr *)bp2; ++ dp = (const struct tcpdump_ip6_frag *)bp; ++ ip6 = (const struct tcpdump_ip6_hdr *)bp2; + + if (ndo->ndo_vflag) { + ND_PRINT("frag (0x%08x:%u|%zu)", + GET_BE_U_4(dp->ip6f_ident), + GET_BE_U_2(dp->ip6f_offlg) & IP6F_OFF_MASK, +- sizeof(struct ip6_hdr) + GET_BE_U_2(ip6->ip6_plen) - +- (bp - bp2) - sizeof(struct ip6_frag)); ++ sizeof(struct tcpdump_ip6_hdr) + GET_BE_U_2(ip6->ip6_plen) - ++ (bp - bp2) - sizeof(struct tcpdump_ip6_frag)); + } else { + ND_PRINT("frag (%u|%zu)", + GET_BE_U_2(dp->ip6f_offlg) & IP6F_OFF_MASK, +- sizeof(struct ip6_hdr) + GET_BE_U_2(ip6->ip6_plen) - +- (bp - bp2) - sizeof(struct ip6_frag)); ++ sizeof(struct tcpdump_ip6_hdr) + GET_BE_U_2(ip6->ip6_plen) - ++ (bp - bp2) - sizeof(struct tcpdump_ip6_frag)); + } + + /* it is meaningless to decode non-first fragment */ +@@ -61,6 +61,6 @@ + else + { + ND_PRINT(" "); +- return sizeof(struct ip6_frag); ++ return sizeof(struct tcpdump_ip6_frag); + } + } +diff -uNr tcpdump-tcpdump-4.99.4/print-icmp6.c tcpdump-for-stellar/print-icmp6.c +--- tcpdump-tcpdump-4.99.4/print-icmp6.c 2023-04-08 02:30:58.000000000 +0800 ++++ tcpdump-for-stellar/print-icmp6.c 2024-10-30 17:34:05.617498702 +0800 +@@ -35,10 +35,10 @@ + #include "addrtostr.h" + #include "extract.h" + +-#include "ip6.h" ++#include "tcpdump_ip6.h" + #include "ipproto.h" + +-#include "udp.h" ++#include "print-udp.h" + #include "ah.h" + + /* NetBSD: icmp6.h,v 1.13 2000/08/03 16:30:37 itojun Exp */ +@@ -769,7 +769,7 @@ + } + } + +-static uint16_t icmp6_cksum(netdissect_options *ndo, const struct ip6_hdr *ip6, ++static uint16_t icmp6_cksum(netdissect_options *ndo, const struct tcpdump_ip6_hdr *ip6, + const struct icmp6_hdr *icp, u_int len) + { + return nextproto6_cksum(ndo, ip6, (const uint8_t *)(const void *)icp, len, len, +@@ -1011,8 +1011,8 @@ + { + const struct icmp6_hdr *dp; + uint8_t icmp6_type, icmp6_code; +- const struct ip6_hdr *ip; +- const struct ip6_hdr *oip; ++ const struct tcpdump_ip6_hdr *ip; ++ const struct tcpdump_ip6_hdr *oip; + const struct udphdr *ouh; + uint16_t dport; + const u_char *ep; +@@ -1020,8 +1020,8 @@ + + ndo->ndo_protocol = "icmp6"; + dp = (const struct icmp6_hdr *)bp; +- ip = (const struct ip6_hdr *)bp2; +- oip = (const struct ip6_hdr *)(dp + 1); ++ ip = (const struct tcpdump_ip6_hdr *)bp2; ++ oip = (const struct tcpdump_ip6_hdr *)(dp + 1); + /* 'ep' points to the end of available data. */ + ep = ndo->ndo_snapend; + if (length == 0) { +@@ -1319,10 +1319,10 @@ + get_upperlayer(netdissect_options *ndo, const u_char *bp, u_int *prot) + { + const u_char *ep; +- const struct ip6_hdr *ip6 = (const struct ip6_hdr *)bp; ++ const struct tcpdump_ip6_hdr *ip6 = (const struct tcpdump_ip6_hdr *)bp; + const struct udphdr *uh; +- const struct ip6_hbh *hbh; +- const struct ip6_frag *fragh; ++ const struct tcpdump_ip6_hbh *hbh; ++ const struct tcpdump_ip6_frag *fragh; + const struct ah *ah; + u_int nh; + int hlen; +@@ -1334,7 +1334,7 @@ + return NULL; + + nh = GET_U_1(ip6->ip6_nxt); +- hlen = sizeof(struct ip6_hdr); ++ hlen = sizeof(struct tcpdump_ip6_hdr); + + while (bp < ep) { + bp += hlen; +@@ -1354,7 +1354,7 @@ + case IPPROTO_HOPOPTS: + case IPPROTO_DSTOPTS: + case IPPROTO_ROUTING: +- hbh = (const struct ip6_hbh *)bp; ++ hbh = (const struct tcpdump_ip6_hbh *)bp; + if (!ND_TTEST_1(hbh->ip6h_len)) + return(NULL); + nh = GET_U_1(hbh->ip6h_nxt); +@@ -1362,14 +1362,14 @@ + break; + + case IPPROTO_FRAGMENT: /* this should be odd, but try anyway */ +- fragh = (const struct ip6_frag *)bp; ++ fragh = (const struct tcpdump_ip6_frag *)bp; + if (!ND_TTEST_2(fragh->ip6f_offlg)) + return(NULL); + /* fragments with non-zero offset are meaningless */ + if ((GET_BE_U_2(fragh->ip6f_offlg) & IP6F_OFF_MASK) != 0) + return(NULL); + nh = GET_U_1(fragh->ip6f_nxt); +- hlen = sizeof(struct ip6_frag); ++ hlen = sizeof(struct tcpdump_ip6_frag); + break; + + case IPPROTO_AH: +diff -uNr tcpdump-tcpdump-4.99.4/print-icmp.c tcpdump-for-stellar/print-icmp.c +--- tcpdump-tcpdump-4.99.4/print-icmp.c 2023-04-08 02:30:58.000000000 +0800 ++++ tcpdump-for-stellar/print-icmp.c 2024-10-30 17:34:05.617498702 +0800 +@@ -34,8 +34,8 @@ + #include "addrtoname.h" + #include "extract.h" + +-#include "ip.h" +-#include "udp.h" ++#include "tcpdump_ip.h" ++#include "print-udp.h" + #include "ipproto.h" + #include "mpls.h" + +@@ -72,7 +72,7 @@ + nd_uint32_t its_ttime; + } id_ts; + struct id_ip { +- struct ip idi_ip; ++ struct tcpdump_ip idi_ip; + /* options and then 64 bits of data */ + } id_ip; + nd_uint32_t id_mask; +@@ -95,10 +95,10 @@ + * ip header length. + */ + #define ICMP_MINLEN 8 /* abs minimum */ +-#define ICMP_EXTD_MINLEN (156 - sizeof (struct ip)) /* draft-bonica-internet-icmp-08 */ ++#define ICMP_EXTD_MINLEN (156 - sizeof (struct tcpdump_ip)) /* draft-bonica-internet-icmp-08 */ + #define ICMP_TSLEN (8 + 3 * sizeof (uint32_t)) /* timestamp */ + #define ICMP_MASKLEN 12 /* address mask */ +-#define ICMP_ADVLENMIN (8 + sizeof (struct ip) + 8) /* min */ ++#define ICMP_ADVLENMIN (8 + sizeof (struct tcpdump_ip) + 8) /* min */ + #define ICMP_ADVLEN(p) (8 + (IP_HL(&(p)->icmp_ip) << 2) + 8) + /* N.B.: must separately check that ip_hl >= 5 */ + +@@ -318,9 +318,9 @@ + const struct icmp *dp; + uint8_t icmp_type, icmp_code; + const struct icmp_ext_t *ext_dp; +- const struct ip *ip; ++ const struct tcpdump_ip *ip; + const char *str; +- const struct ip *oip; ++ const struct tcpdump_ip *oip; + uint8_t ip_proto; + const struct udphdr *ouh; + const uint8_t *obj_tptr; +@@ -334,7 +334,7 @@ + ndo->ndo_protocol = "icmp"; + dp = (const struct icmp *)bp; + ext_dp = (const struct icmp_ext_t *)bp; +- ip = (const struct ip *)bp2; ++ ip = (const struct tcpdump_ip *)bp2; + str = buf; + + icmp_type = GET_U_1(dp->icmp_type); +@@ -674,7 +674,7 @@ + + bp += 8; + ND_PRINT("\n\t"); +- ip = (const struct ip *)bp; ++ ip = (const struct tcpdump_ip *)bp; + snapend_save = ndo->ndo_snapend; + /* + * Update the snapend because extensions (MPLS, ...) may be +diff -uNr tcpdump-tcpdump-4.99.4/print-ip6.c tcpdump-for-stellar/print-ip6.c +--- tcpdump-tcpdump-4.99.4/print-ip6.c 2023-04-08 02:30:58.000000000 +0800 ++++ tcpdump-for-stellar/print-ip6.c 2024-10-30 17:34:05.618498702 +0800 +@@ -33,7 +33,7 @@ + #include "addrtoname.h" + #include "extract.h" + +-#include "ip6.h" ++#include "tcpdump_ip6.h" + #include "ipproto.h" + + /* +@@ -45,20 +45,20 @@ + */ + static void + ip6_finddst(netdissect_options *ndo, nd_ipv6 *dst, +- const struct ip6_hdr *ip6) ++ const struct tcpdump_ip6_hdr *ip6) + { + const u_char *cp; + u_int advance; + u_int nh; + const void *dst_addr; +- const struct ip6_rthdr *dp; +- const struct ip6_rthdr0 *dp0; +- const struct ip6_srh *srh; ++ const struct tcpdump_ip6_rthdr *dp; ++ const struct tcpdump_ip6_rthdr0 *dp0; ++ const struct tcpdump_ip6_srh *srh; + const u_char *p; + int i, len; + + cp = (const u_char *)ip6; +- advance = sizeof(struct ip6_hdr); ++ advance = sizeof(struct tcpdump_ip6_hdr); + nh = GET_U_1(ip6->ip6_nxt); + dst_addr = (const void *)ip6->ip6_dst; + +@@ -87,7 +87,7 @@ + * marked as reserved, and the header is always + * the same size. + */ +- advance = sizeof(struct ip6_frag); ++ advance = sizeof(struct tcpdump_ip6_frag); + nh = GET_U_1(cp); + break; + +@@ -95,14 +95,14 @@ + /* + * OK, we found it. + */ +- dp = (const struct ip6_rthdr *)cp; ++ dp = (const struct tcpdump_ip6_rthdr *)cp; + ND_TCHECK_SIZE(dp); + len = GET_U_1(dp->ip6r_len); + switch (GET_U_1(dp->ip6r_type)) { + + case IPV6_RTHDR_TYPE_0: + case IPV6_RTHDR_TYPE_2: /* Mobile IPv6 ID-20 */ +- dp0 = (const struct ip6_rthdr0 *)dp; ++ dp0 = (const struct tcpdump_ip6_rthdr0 *)dp; + if (len % 2 == 1) + goto trunc; + len >>= 1; +@@ -115,7 +115,7 @@ + break; + case IPV6_RTHDR_TYPE_4: + /* IPv6 Segment Routing Header (SRH) */ +- srh = (const struct ip6_srh *)dp; ++ srh = (const struct tcpdump_ip6_srh *)dp; + if (len % 2 == 1) + goto trunc; + p = (const u_char *) srh->srh_segments; +@@ -171,7 +171,7 @@ + */ + uint16_t + nextproto6_cksum(netdissect_options *ndo, +- const struct ip6_hdr *ip6, const uint8_t *data, ++ const struct tcpdump_ip6_hdr *ip6, const uint8_t *data, + u_int len, u_int covlen, uint8_t next_proto) + { + struct { +@@ -225,7 +225,7 @@ + void + ip6_print(netdissect_options *ndo, const u_char *bp, u_int length) + { +- const struct ip6_hdr *ip6; ++ const struct tcpdump_ip6_hdr *ip6; + int advance; + u_int len; + u_int total_advance; +@@ -239,10 +239,10 @@ + int found_hbh; + + ndo->ndo_protocol = "ip6"; +- ip6 = (const struct ip6_hdr *)bp; ++ ip6 = (const struct tcpdump_ip6_hdr *)bp; + + ND_TCHECK_SIZE(ip6); +- if (length < sizeof (struct ip6_hdr)) { ++ if (length < sizeof (struct tcpdump_ip6_hdr)) { + ND_PRINT("truncated-ip6 %u", length); + return; + } +@@ -279,12 +279,12 @@ + * a Jumbo Payload option, and fail if we haven't. + */ + if (payload_len != 0) { +- len = payload_len + sizeof(struct ip6_hdr); ++ len = payload_len + sizeof(struct tcpdump_ip6_hdr); + if (length < len) + ND_PRINT("truncated-ip6 - %u bytes missing!", + len - length); + } else +- len = length + sizeof(struct ip6_hdr); ++ len = length + sizeof(struct tcpdump_ip6_hdr); + + ph = 255; + nh = GET_U_1(ip6->ip6_nxt); +@@ -313,7 +313,7 @@ + } + + cp = (const u_char *)ip6; +- advance = sizeof(struct ip6_hdr); ++ advance = sizeof(struct tcpdump_ip6_hdr); + total_advance = 0; + /* Process extension headers */ + found_extension_header = 0; +@@ -433,7 +433,7 @@ + * the total number of bytes we've + * processed so far. + */ +- len = payload_len + sizeof(struct ip6_hdr); ++ len = payload_len + sizeof(struct tcpdump_ip6_hdr); + if (len < total_advance) + goto trunc; + if (length < len) +@@ -471,7 +471,7 @@ + * and change the snapshot length + * accordingly. + */ +- len = sizeof(struct ip6_hdr); ++ len = sizeof(struct tcpdump_ip6_hdr); + nd_change_snaplen(ndo, bp, len); + + /* +diff -uNr tcpdump-tcpdump-4.99.4/print-ip6opts.c tcpdump-for-stellar/print-ip6opts.c +--- tcpdump-tcpdump-4.99.4/print-ip6opts.c 2023-04-08 02:30:58.000000000 +0800 ++++ tcpdump-for-stellar/print-ip6opts.c 2024-10-30 17:34:05.618498702 +0800 +@@ -39,7 +39,7 @@ + #include "addrtoname.h" + #include "extract.h" + +-#include "ip6.h" ++#include "tcpdump_ip6.h" + + static int + ip6_sopt_print(netdissect_options *ndo, const u_char *bp, int len) +@@ -219,7 +219,7 @@ + hbhopt_process(netdissect_options *ndo, const u_char *bp, int *found_jumbo, + uint32_t *jumbolen) + { +- const struct ip6_hbh *dp = (const struct ip6_hbh *)bp; ++ const struct tcpdump_ip6_hbh *dp = (const struct tcpdump_ip6_hbh *)bp; + u_int hbhlen = 0; + + ndo->ndo_protocol = "hbhopt"; +@@ -239,7 +239,7 @@ + int + dstopt_process(netdissect_options *ndo, const u_char *bp) + { +- const struct ip6_dest *dp = (const struct ip6_dest *)bp; ++ const struct tcpdump_ip6_dest *dp = (const struct tcpdump_ip6_dest *)bp; + u_int dstoptlen = 0; + + ndo->ndo_protocol = "dstopt"; +diff -uNr tcpdump-tcpdump-4.99.4/print-ip.c tcpdump-for-stellar/print-ip.c +--- tcpdump-tcpdump-4.99.4/print-ip.c 2023-04-08 02:30:58.000000000 +0800 ++++ tcpdump-for-stellar/print-ip.c 2024-10-30 17:34:05.618498702 +0800 +@@ -31,7 +31,7 @@ + #include "addrtoname.h" + #include "extract.h" + +-#include "ip.h" ++#include "tcpdump_ip.h" + #include "ipproto.h" + + +@@ -89,7 +89,7 @@ + */ + static uint32_t + ip_finddst(netdissect_options *ndo, +- const struct ip *ip) ++ const struct tcpdump_ip *ip) + { + u_int length; + u_int len; +@@ -97,9 +97,9 @@ + + cp = (const u_char *)(ip + 1); + length = IP_HL(ip) * 4; +- if (length < sizeof(struct ip)) ++ if (length < sizeof(struct tcpdump_ip)) + goto trunc; +- length -= sizeof(struct ip); ++ length -= sizeof(struct tcpdump_ip); + + for (; length != 0; cp += len, length -= len) { + int tt; +@@ -135,7 +135,7 @@ + */ + uint16_t + nextproto4_cksum(netdissect_options *ndo, +- const struct ip *ip, const uint8_t *data, ++ const struct tcpdump_ip *ip, const uint8_t *data, + u_int len, u_int covlen, uint8_t next_proto) + { + struct phdr { +@@ -320,7 +320,7 @@ + const u_char *bp, + u_int length) + { +- const struct ip *ip; ++ const struct tcpdump_ip *ip; + u_int off; + u_int hlen; + u_int len; +@@ -331,7 +331,7 @@ + int truncated = 0; + + ndo->ndo_protocol = "ip"; +- ip = (const struct ip *)bp; ++ ip = (const struct tcpdump_ip *)bp; + if (IP_V(ip) != 4) { /* print version and fail if != 4 */ + if (IP_V(ip) == 6) + ND_PRINT("IP6, wrong link-layer encapsulation"); +@@ -344,12 +344,12 @@ + ND_PRINT("IP "); + + ND_TCHECK_SIZE(ip); +- if (length < sizeof (struct ip)) { ++ if (length < sizeof (struct tcpdump_ip)) { + ND_PRINT("truncated-ip %u", length); + return; + } + hlen = IP_HL(ip) * 4; +- if (hlen < sizeof (struct ip)) { ++ if (hlen < sizeof (struct tcpdump_ip)) { + ND_PRINT("bad-hlen %u", hlen); + return; + } +@@ -428,10 +428,10 @@ + + ND_PRINT(", length %u", GET_BE_U_2(ip->ip_len)); + +- if ((hlen - sizeof(struct ip)) > 0) { ++ if ((hlen - sizeof(struct tcpdump_ip)) > 0) { + ND_PRINT(", options ("); + if (ip_optprint(ndo, (const u_char *)(ip + 1), +- hlen - sizeof(struct ip)) == -1) { ++ hlen - sizeof(struct tcpdump_ip)) == -1) { + ND_PRINT(" [truncated-option]"); + truncated = 1; + } +diff -uNr tcpdump-tcpdump-4.99.4/print-ip-demux.c tcpdump-for-stellar/print-ip-demux.c +--- tcpdump-tcpdump-4.99.4/print-ip-demux.c 2023-04-08 02:30:58.000000000 +0800 ++++ tcpdump-for-stellar/print-ip-demux.c 2024-10-30 17:34:05.618498702 +0800 +@@ -31,7 +31,7 @@ + #include "addrtoname.h" + #include "extract.h" + +-#include "ip.h" ++#include "tcpdump_ip.h" + #include "ipproto.h" + + void +diff -uNr tcpdump-tcpdump-4.99.4/print-isakmp.c tcpdump-for-stellar/print-isakmp.c +--- tcpdump-tcpdump-4.99.4/print-isakmp.c 2023-04-08 02:30:58.000000000 +0800 ++++ tcpdump-for-stellar/print-isakmp.c 2024-10-30 17:34:05.619498702 +0800 +@@ -53,8 +53,8 @@ + #include "addrtoname.h" + #include "extract.h" + +-#include "ip.h" +-#include "ip6.h" ++#include "tcpdump_ip.h" ++#include "tcpdump_ip6.h" + #include "ipproto.h" + + typedef nd_byte cookie_t[8]; +@@ -771,8 +771,8 @@ + cookie_record(netdissect_options *ndo, const cookie_t *in, const u_char *bp2) + { + int i; +- const struct ip *ip; +- const struct ip6_hdr *ip6; ++ const struct tcpdump_ip *ip; ++ const struct tcpdump_ip6_hdr *ip6; + + i = cookie_find(in); + if (0 <= i) { +@@ -780,7 +780,7 @@ + return; + } + +- ip = (const struct ip *)bp2; ++ ip = (const struct tcpdump_ip *)bp2; + switch (IP_V(ip)) { + case 4: + cookiecache[ninitiator].version = 4; +@@ -790,7 +790,7 @@ + ip->ip_dst, sizeof(nd_ipv4)); + break; + case 6: +- ip6 = (const struct ip6_hdr *)bp2; ++ ip6 = (const struct tcpdump_ip6_hdr *)bp2; + cookiecache[ninitiator].version = 6; + UNALIGNED_MEMCPY(&cookiecache[ninitiator].iaddr.in6, + ip6->ip6_src, sizeof(nd_ipv6)); +@@ -809,10 +809,10 @@ + static int + cookie_sidecheck(netdissect_options *ndo, int i, const u_char *bp2, int initiator) + { +- const struct ip *ip; +- const struct ip6_hdr *ip6; ++ const struct tcpdump_ip *ip; ++ const struct tcpdump_ip6_hdr *ip6; + +- ip = (const struct ip *)bp2; ++ ip = (const struct tcpdump_ip *)bp2; + switch (IP_V(ip)) { + case 4: + if (cookiecache[i].version != 4) +@@ -828,7 +828,7 @@ + case 6: + if (cookiecache[i].version != 6) + return 0; +- ip6 = (const struct ip6_hdr *)bp2; ++ ip6 = (const struct tcpdump_ip6_hdr *)bp2; + if (initiator) { + if (UNALIGNED_MEMCMP(ip6->ip6_src, &cookiecache[i].iaddr.in6, sizeof(nd_ipv6)) == 0) + return 1; +diff -uNr tcpdump-tcpdump-4.99.4/print-lisp.c tcpdump-for-stellar/print-lisp.c +--- tcpdump-tcpdump-4.99.4/print-lisp.c 2023-04-08 02:30:58.000000000 +0800 ++++ tcpdump-for-stellar/print-lisp.c 2024-10-30 17:34:05.620498702 +0800 +@@ -101,8 +101,8 @@ + #include "netdissect-stdinc.h" + #include "netdissect.h" + +-#include "ip.h" +-#include "ip6.h" ++#include "tcpdump_ip.h" ++#include "tcpdump_ip6.h" + + #include "extract.h" + #include "addrtoname.h" +diff -uNr tcpdump-tcpdump-4.99.4/print-lldp.c tcpdump-for-stellar/print-lldp.c +--- tcpdump-tcpdump-4.99.4/print-lldp.c 2023-04-08 02:30:58.000000000 +0800 ++++ tcpdump-for-stellar/print-lldp.c 2024-10-30 17:34:05.620498702 +0800 +@@ -41,9 +41,9 @@ + */ + #define LLDP_END_TLV 0 + #define LLDP_CHASSIS_ID_TLV 1 +-#define LLDP_PORT_ID_TLV 2 ++#define LTCPDUMP_LDP_PORT_ID_TLV 2 + #define LLDP_TTL_TLV 3 +-#define LLDP_PORT_DESCR_TLV 4 ++#define LTCPDUMP_LDP_PORT_DESCR_TLV 4 + #define LLDP_SYSTEM_NAME_TLV 5 + #define LLDP_SYSTEM_DESCR_TLV 6 + #define LLDP_SYSTEM_CAP_TLV 7 +@@ -53,9 +53,9 @@ + static const struct tok lldp_tlv_values[] = { + { LLDP_END_TLV, "End" }, + { LLDP_CHASSIS_ID_TLV, "Chassis ID" }, +- { LLDP_PORT_ID_TLV, "Port ID" }, ++ { LTCPDUMP_LDP_PORT_ID_TLV, "Port ID" }, + { LLDP_TTL_TLV, "Time to Live" }, +- { LLDP_PORT_DESCR_TLV, "Port Description" }, ++ { LTCPDUMP_LDP_PORT_DESCR_TLV, "Port Description" }, + { LLDP_SYSTEM_NAME_TLV, "System Name" }, + { LLDP_SYSTEM_DESCR_TLV, "System Description" }, + { LLDP_SYSTEM_CAP_TLV, "System Capabilities" }, +@@ -89,22 +89,22 @@ + /* + * Port ID subtypes + */ +-#define LLDP_PORT_INTF_ALIAS_SUBTYPE 1 +-#define LLDP_PORT_PORT_COMP_SUBTYPE 2 +-#define LLDP_PORT_MAC_ADDR_SUBTYPE 3 +-#define LLDP_PORT_NETWORK_ADDR_SUBTYPE 4 +-#define LLDP_PORT_INTF_NAME_SUBTYPE 5 +-#define LLDP_PORT_AGENT_CIRC_ID_SUBTYPE 6 +-#define LLDP_PORT_LOCAL_SUBTYPE 7 ++#define LTCPDUMP_LDP_PORT_INTF_ALIAS_SUBTYPE 1 ++#define LTCPDUMP_LDP_PORT_PORT_COMP_SUBTYPE 2 ++#define LTCPDUMP_LDP_PORT_MAC_ADDR_SUBTYPE 3 ++#define LTCPDUMP_LDP_PORT_NETWORK_ADDR_SUBTYPE 4 ++#define LTCPDUMP_LDP_PORT_INTF_NAME_SUBTYPE 5 ++#define LTCPDUMP_LDP_PORT_AGENT_CIRC_ID_SUBTYPE 6 ++#define LTCPDUMP_LDP_PORT_LOCAL_SUBTYPE 7 + + static const struct tok lldp_port_subtype_values[] = { +- { LLDP_PORT_INTF_ALIAS_SUBTYPE, "Interface alias"}, +- { LLDP_PORT_PORT_COMP_SUBTYPE, "Port component"}, +- { LLDP_PORT_MAC_ADDR_SUBTYPE, "MAC address"}, +- { LLDP_PORT_NETWORK_ADDR_SUBTYPE, "Network Address"}, +- { LLDP_PORT_INTF_NAME_SUBTYPE, "Interface Name"}, +- { LLDP_PORT_AGENT_CIRC_ID_SUBTYPE, "Agent circuit ID"}, +- { LLDP_PORT_LOCAL_SUBTYPE, "Local"}, ++ { LTCPDUMP_LDP_PORT_INTF_ALIAS_SUBTYPE, "Interface alias"}, ++ { LTCPDUMP_LDP_PORT_PORT_COMP_SUBTYPE, "Port component"}, ++ { LTCPDUMP_LDP_PORT_MAC_ADDR_SUBTYPE, "MAC address"}, ++ { LTCPDUMP_LDP_PORT_NETWORK_ADDR_SUBTYPE, "Network Address"}, ++ { LTCPDUMP_LDP_PORT_INTF_NAME_SUBTYPE, "Interface Name"}, ++ { LTCPDUMP_LDP_PORT_AGENT_CIRC_ID_SUBTYPE, "Agent circuit ID"}, ++ { LTCPDUMP_LDP_PORT_LOCAL_SUBTYPE, "Local"}, + { 0, NULL} + }; + +@@ -1531,7 +1531,7 @@ + } + break; + +- case LLDP_PORT_ID_TLV: ++ case LTCPDUMP_LDP_PORT_ID_TLV: + if (ndo->ndo_vflag) { + if (tlv_len < 2) { + goto trunc; +@@ -1542,22 +1542,22 @@ + subtype); + + switch (subtype) { +- case LLDP_PORT_MAC_ADDR_SUBTYPE: ++ case LTCPDUMP_LDP_PORT_MAC_ADDR_SUBTYPE: + if (tlv_len < 1+6) { + goto trunc; + } + ND_PRINT("%s", GET_ETHERADDR_STRING(tptr + 1)); + break; + +- case LLDP_PORT_INTF_NAME_SUBTYPE: /* fall through */ +- case LLDP_PORT_LOCAL_SUBTYPE: +- case LLDP_PORT_AGENT_CIRC_ID_SUBTYPE: +- case LLDP_PORT_INTF_ALIAS_SUBTYPE: +- case LLDP_PORT_PORT_COMP_SUBTYPE: ++ case LTCPDUMP_LDP_PORT_INTF_NAME_SUBTYPE: /* fall through */ ++ case LTCPDUMP_LDP_PORT_LOCAL_SUBTYPE: ++ case LTCPDUMP_LDP_PORT_AGENT_CIRC_ID_SUBTYPE: ++ case LTCPDUMP_LDP_PORT_INTF_ALIAS_SUBTYPE: ++ case LTCPDUMP_LDP_PORT_PORT_COMP_SUBTYPE: + nd_printjnp(ndo, tptr + 1, tlv_len - 1); + break; + +- case LLDP_PORT_NETWORK_ADDR_SUBTYPE: ++ case LTCPDUMP_LDP_PORT_NETWORK_ADDR_SUBTYPE: + network_addr = lldp_network_addr_print(ndo, tptr+1, tlv_len-1); + if (network_addr == NULL) { + goto trunc; +@@ -1581,7 +1581,7 @@ + } + break; + +- case LLDP_PORT_DESCR_TLV: ++ case LTCPDUMP_LDP_PORT_DESCR_TLV: + if (ndo->ndo_vflag) { + ND_PRINT(": "); + nd_printjnp(ndo, tptr, tlv_len); +diff -uNr tcpdump-tcpdump-4.99.4/print-mobility.c tcpdump-for-stellar/print-mobility.c +--- tcpdump-tcpdump-4.99.4/print-mobility.c 2023-04-08 02:30:58.000000000 +0800 ++++ tcpdump-for-stellar/print-mobility.c 2024-10-30 17:34:05.622498702 +0800 +@@ -40,7 +40,7 @@ + #include "addrtoname.h" + #include "extract.h" + +-#include "ip6.h" ++#include "tcpdump_ip6.h" + + + /* Mobility header */ +diff -uNr tcpdump-tcpdump-4.99.4/print-mptcp.c tcpdump-for-stellar/print-mptcp.c +--- tcpdump-tcpdump-4.99.4/print-mptcp.c 2023-04-08 02:30:58.000000000 +0800 ++++ tcpdump-for-stellar/print-mptcp.c 2024-10-30 17:34:05.622498702 +0800 +@@ -46,7 +46,7 @@ + #include "extract.h" + #include "addrtoname.h" + +-#include "tcp.h" ++#include "print-tcp.h" + + #define MPTCP_SUB_CAPABLE 0x0 + #define MPTCP_SUB_JOIN 0x1 +diff -uNr tcpdump-tcpdump-4.99.4/print-nfs.c tcpdump-for-stellar/print-nfs.c +--- tcpdump-tcpdump-4.99.4/print-nfs.c 2023-04-08 02:30:58.000000000 +0800 ++++ tcpdump-for-stellar/print-nfs.c 2024-10-30 17:34:05.623498702 +0800 +@@ -38,8 +38,8 @@ + #include "nfs.h" + #include "nfsfh.h" + +-#include "ip.h" +-#include "ip6.h" ++#include "tcpdump_ip.h" ++#include "tcpdump_ip6.h" + #include "rpc_auth.h" + #include "rpc_msg.h" + +@@ -201,19 +201,19 @@ + print_nfsaddr(netdissect_options *ndo, + const u_char *bp, const char *s, const char *d) + { +- const struct ip *ip; +- const struct ip6_hdr *ip6; ++ const struct tcpdump_ip *ip; ++ const struct tcpdump_ip6_hdr *ip6; + char srcaddr[INET6_ADDRSTRLEN], dstaddr[INET6_ADDRSTRLEN]; + + srcaddr[0] = dstaddr[0] = '\0'; +- switch (IP_V((const struct ip *)bp)) { ++ switch (IP_V((const struct tcpdump_ip *)bp)) { + case 4: +- ip = (const struct ip *)bp; ++ ip = (const struct tcpdump_ip *)bp; + strlcpy(srcaddr, GET_IPADDR_STRING(ip->ip_src), sizeof(srcaddr)); + strlcpy(dstaddr, GET_IPADDR_STRING(ip->ip_dst), sizeof(dstaddr)); + break; + case 6: +- ip6 = (const struct ip6_hdr *)bp; ++ ip6 = (const struct tcpdump_ip6_hdr *)bp; + strlcpy(srcaddr, GET_IP6ADDR_STRING(ip6->ip6_src), + sizeof(srcaddr)); + strlcpy(dstaddr, GET_IP6ADDR_STRING(ip6->ip6_dst), +@@ -941,18 +941,18 @@ + xid_map_enter(netdissect_options *ndo, + const struct sunrpc_msg *rp, const u_char *bp) + { +- const struct ip *ip = NULL; +- const struct ip6_hdr *ip6 = NULL; ++ const struct tcpdump_ip *ip = NULL; ++ const struct tcpdump_ip6_hdr *ip6 = NULL; + struct xid_map_entry *xmep; + + if (!ND_TTEST_4(rp->rm_call.cb_proc)) + return (0); +- switch (IP_V((const struct ip *)bp)) { ++ switch (IP_V((const struct tcpdump_ip *)bp)) { + case 4: +- ip = (const struct ip *)bp; ++ ip = (const struct tcpdump_ip *)bp; + break; + case 6: +- ip6 = (const struct ip6_hdr *)bp; ++ ip6 = (const struct tcpdump_ip6_hdr *)bp; + break; + default: + return (1); +@@ -994,8 +994,8 @@ + int i; + struct xid_map_entry *xmep; + uint32_t xid; +- const struct ip *ip = (const struct ip *)bp; +- const struct ip6_hdr *ip6 = (const struct ip6_hdr *)bp; ++ const struct tcpdump_ip *ip = (const struct tcpdump_ip *)bp; ++ const struct tcpdump_ip6_hdr *ip6 = (const struct tcpdump_ip6_hdr *)bp; + int cmp; + + UNALIGNED_MEMCPY(&xid, &rp->rm_xid, sizeof(xmep->xid)); +diff -uNr tcpdump-tcpdump-4.99.4/print-pgm.c tcpdump-for-stellar/print-pgm.c +--- tcpdump-tcpdump-4.99.4/print-pgm.c 2023-04-08 02:30:58.000000000 +0800 ++++ tcpdump-for-stellar/print-pgm.c 2024-10-30 17:34:05.625498702 +0800 +@@ -26,8 +26,8 @@ + #include "addrtoname.h" + #include "addrtostr.h" + +-#include "ip.h" +-#include "ip6.h" ++#include "tcpdump_ip.h" ++#include "tcpdump_ip6.h" + #include "ipproto.h" + #include "af.h" + +@@ -148,20 +148,20 @@ + const u_char *bp2) + { + const struct pgm_header *pgm; +- const struct ip *ip; ++ const struct tcpdump_ip *ip; + uint8_t pgm_type_val; + uint16_t sport, dport; + u_int nla_afnum; + char nla_buf[INET6_ADDRSTRLEN]; +- const struct ip6_hdr *ip6; ++ const struct tcpdump_ip6_hdr *ip6; + uint8_t opt_type, opt_len; + uint32_t seq, opts_len, len, offset; + + ndo->ndo_protocol = "pgm"; + pgm = (const struct pgm_header *)bp; +- ip = (const struct ip *)bp2; ++ ip = (const struct tcpdump_ip *)bp2; + if (IP_V(ip) == 6) +- ip6 = (const struct ip6_hdr *)bp2; ++ ip6 = (const struct tcpdump_ip6_hdr *)bp2; + else + ip6 = NULL; + if (!ND_TTEST_2(pgm->pgm_dport)) { +diff -uNr tcpdump-tcpdump-4.99.4/print-pim.c tcpdump-for-stellar/print-pim.c +--- tcpdump-tcpdump-4.99.4/print-pim.c 2023-04-08 02:30:58.000000000 +0800 ++++ tcpdump-for-stellar/print-pim.c 2024-10-30 17:34:05.625498702 +0800 +@@ -31,8 +31,8 @@ + #include "addrtoname.h" + #include "extract.h" + +-#include "ip.h" +-#include "ip6.h" ++#include "tcpdump_ip.h" ++#include "tcpdump_ip6.h" + #include "ipproto.h" + + #define PIMV1_TYPE_QUERY 0 +@@ -657,14 +657,14 @@ + pimv2_check_checksum(netdissect_options *ndo, const u_char *bp, + const u_char *bp2, u_int len) + { +- const struct ip *ip; ++ const struct tcpdump_ip *ip; + u_int cksum; + + if (!ND_TTEST_LEN(bp, len)) { + /* We don't have all the data. */ + return (UNVERIFIED); + } +- ip = (const struct ip *)bp2; ++ ip = (const struct tcpdump_ip *)bp2; + if (IP_V(ip) == 4) { + struct cksum_vec vec[1]; + +@@ -673,9 +673,9 @@ + cksum = in_cksum(vec, 1); + return (cksum ? INCORRECT : CORRECT); + } else if (IP_V(ip) == 6) { +- const struct ip6_hdr *ip6; ++ const struct tcpdump_ip6_hdr *ip6; + +- ip6 = (const struct ip6_hdr *)bp2; ++ ip6 = (const struct tcpdump_ip6_hdr *)bp2; + cksum = nextproto6_cksum(ndo, ip6, bp, len, len, IPPROTO_PIM); + return (cksum ? INCORRECT : CORRECT); + } else { +@@ -882,7 +882,7 @@ + + case PIMV2_TYPE_REGISTER: + { +- const struct ip *ip; ++ const struct tcpdump_ip *ip; + + if (len < 4) + goto trunc; +@@ -897,7 +897,7 @@ + /* encapsulated multicast packet */ + if (len == 0) + goto trunc; +- ip = (const struct ip *)bp; ++ ip = (const struct tcpdump_ip *)bp; + switch (IP_V(ip)) { + case 0: /* Null header */ + ND_PRINT("IP-Null-header %s > %s", +diff -uNr tcpdump-tcpdump-4.99.4/print-rt6.c tcpdump-for-stellar/print-rt6.c +--- tcpdump-tcpdump-4.99.4/print-rt6.c 2023-04-08 02:30:58.000000000 +0800 ++++ tcpdump-for-stellar/print-rt6.c 2024-10-30 17:34:05.627498702 +0800 +@@ -31,21 +31,21 @@ + #include "addrtoname.h" + #include "extract.h" + +-#include "ip6.h" ++#include "tcpdump_ip6.h" + + int + rt6_print(netdissect_options *ndo, const u_char *bp, const u_char *bp2 _U_) + { +- const struct ip6_rthdr *dp; +- const struct ip6_rthdr0 *dp0; +- const struct ip6_srh *srh; ++ const struct tcpdump_ip6_rthdr *dp; ++ const struct tcpdump_ip6_rthdr0 *dp0; ++ const struct tcpdump_ip6_srh *srh; + u_int i, len, type; + const u_char *p; + + ndo->ndo_protocol = "rt6"; + + nd_print_protocol_caps(ndo); +- dp = (const struct ip6_rthdr *)bp; ++ dp = (const struct tcpdump_ip6_rthdr *)bp; + + len = GET_U_1(dp->ip6r_len); + ND_PRINT(" (len=%u", len); /*)*/ +@@ -58,7 +58,7 @@ + switch (type) { + case IPV6_RTHDR_TYPE_0: + case IPV6_RTHDR_TYPE_2: /* Mobile IPv6 ID-20 */ +- dp0 = (const struct ip6_rthdr0 *)dp; ++ dp0 = (const struct tcpdump_ip6_rthdr0 *)dp; + + if (GET_BE_U_4(dp0->ip6r0_reserved) || ndo->ndo_vflag) { + ND_PRINT(", rsv=0x%0x", +@@ -80,7 +80,7 @@ + return((GET_U_1(dp0->ip6r0_len) + 1) << 3); + break; + case IPV6_RTHDR_TYPE_4: +- srh = (const struct ip6_srh *)dp; ++ srh = (const struct tcpdump_ip6_srh *)dp; + ND_PRINT(", last-entry=%u", GET_U_1(srh->srh_last_ent)); + + if (GET_U_1(srh->srh_flags) || ndo->ndo_vflag) { +diff -uNr tcpdump-tcpdump-4.99.4/print-rx.c tcpdump-for-stellar/print-rx.c +--- tcpdump-tcpdump-4.99.4/print-rx.c 2023-04-08 02:30:58.000000000 +0800 ++++ tcpdump-for-stellar/print-rx.c 2024-10-30 17:34:05.628498702 +0800 +@@ -47,7 +47,7 @@ + #include "addrtoname.h" + #include "extract.h" + +-#include "ip.h" ++#include "tcpdump_ip.h" + + #define FS_RX_PORT 7000 + #define CB_RX_PORT 7001 +@@ -493,9 +493,9 @@ + + static uint32_t rx_cache_next = 0; + static uint32_t rx_cache_hint = 0; +-static void rx_cache_insert(netdissect_options *, const u_char *, const struct ip *, uint16_t); ++static void rx_cache_insert(netdissect_options *, const u_char *, const struct tcpdump_ip *, uint16_t); + static int rx_cache_find(netdissect_options *, const struct rx_header *, +- const struct ip *, uint16_t, uint32_t *); ++ const struct tcpdump_ip *, uint16_t, uint32_t *); + + static void fs_print(netdissect_options *, const u_char *, u_int); + static void fs_reply_print(netdissect_options *, const u_char *, u_int, uint32_t); +@@ -597,7 +597,7 @@ + * have a chance to print out replies + */ + +- rx_cache_insert(ndo, bp, (const struct ip *) bp2, dport); ++ rx_cache_insert(ndo, bp, (const struct tcpdump_ip *) bp2, dport); + + switch (dport) { + case FS_RX_PORT: /* AFS file service */ +@@ -636,7 +636,7 @@ + GET_BE_U_4(rxh->seq) == 1) || + type == RX_PACKET_TYPE_ABORT) && + (flags & RX_CLIENT_INITIATED) == 0 && +- rx_cache_find(ndo, rxh, (const struct ip *) bp2, ++ rx_cache_find(ndo, rxh, (const struct tcpdump_ip *) bp2, + sport, &opcode)) { + + switch (sport) { +@@ -684,7 +684,7 @@ + + static void + rx_cache_insert(netdissect_options *ndo, +- const u_char *bp, const struct ip *ip, uint16_t dport) ++ const u_char *bp, const struct tcpdump_ip *ip, uint16_t dport) + { + struct rx_cache_entry *rxent; + const struct rx_header *rxh = (const struct rx_header *) bp; +@@ -714,7 +714,7 @@ + + static int + rx_cache_find(netdissect_options *ndo, const struct rx_header *rxh, +- const struct ip *ip, uint16_t sport, uint32_t *opcode) ++ const struct tcpdump_ip *ip, uint16_t sport, uint32_t *opcode) + { + uint32_t i; + struct rx_cache_entry *rxent; +diff -uNr tcpdump-tcpdump-4.99.4/print-sctp.c tcpdump-for-stellar/print-sctp.c +--- tcpdump-tcpdump-4.99.4/print-sctp.c 2023-04-08 02:30:58.000000000 +0800 ++++ tcpdump-for-stellar/print-sctp.c 2024-10-30 17:34:05.628498702 +0800 +@@ -44,8 +44,8 @@ + #include "netdissect.h" + #include "addrtoname.h" + #include "extract.h" +-#include "ip.h" +-#include "ip6.h" ++#include "tcpdump_ip.h" ++#include "tcpdump_ip6.h" + + /* Definitions from: + * +@@ -455,8 +455,8 @@ + { + u_int sctpPacketLengthRemaining; + const struct sctpHeader *sctpPktHdr; +- const struct ip *ip; +- const struct ip6_hdr *ip6; ++ const struct tcpdump_ip *ip; ++ const struct tcpdump_ip6_hdr *ip6; + uint8_t chunkID; + u_short sourcePort, destPort; + u_int chunkCount; +@@ -478,9 +478,9 @@ + sourcePort = GET_BE_U_2(sctpPktHdr->source); + destPort = GET_BE_U_2(sctpPktHdr->destination); + +- ip = (const struct ip *)bp2; ++ ip = (const struct tcpdump_ip *)bp2; + if (IP_V(ip) == 6) +- ip6 = (const struct ip6_hdr *)bp2; ++ ip6 = (const struct tcpdump_ip6_hdr *)bp2; + else + ip6 = NULL; + +diff -uNr tcpdump-tcpdump-4.99.4/print-sl.c tcpdump-for-stellar/print-sl.c +--- tcpdump-tcpdump-4.99.4/print-sl.c 2023-04-08 02:30:58.000000000 +0800 ++++ tcpdump-for-stellar/print-sl.c 2024-10-30 17:34:05.628498702 +0800 +@@ -31,8 +31,8 @@ + #include "netdissect.h" + #include "extract.h" + +-#include "ip.h" +-#include "tcp.h" ++#include "tcpdump_ip.h" ++#include "print-tcp.h" + #include "slcompress.h" + + /* +@@ -51,15 +51,15 @@ + static u_int lastlen[2][256]; + static u_int lastconn = 255; + +-static void sliplink_print(netdissect_options *, const u_char *, const struct ip *, u_int); +-static void compressed_sl_print(netdissect_options *, const u_char *, const struct ip *, u_int, int); ++static void sliplink_print(netdissect_options *, const u_char *, const struct tcpdump_ip *, u_int); ++static void compressed_sl_print(netdissect_options *, const u_char *, const struct tcpdump_ip *, u_int, int); + + void + sl_if_print(netdissect_options *ndo, + const struct pcap_pkthdr *h, const u_char *p) + { + u_int length = h->len; +- const struct ip *ip; ++ const struct tcpdump_ip *ip; + + ndo->ndo_protocol = "slip"; + ND_TCHECK_LEN(p, SLIP_HDRLEN); +@@ -67,7 +67,7 @@ + + length -= SLIP_HDRLEN; + +- ip = (const struct ip *)(p + SLIP_HDRLEN); ++ ip = (const struct tcpdump_ip *)(p + SLIP_HDRLEN); + + if (ndo->ndo_eflag) + sliplink_print(ndo, p, ip, length); +@@ -89,7 +89,7 @@ + const struct pcap_pkthdr *h, const u_char *p) + { + u_int length = h->len; +- const struct ip *ip; ++ const struct tcpdump_ip *ip; + + ndo->ndo_protocol = "slip_bsdos"; + ND_TCHECK_LEN(p, SLIP_HDRLEN); +@@ -97,7 +97,7 @@ + + length -= SLIP_HDRLEN; + +- ip = (const struct ip *)(p + SLIP_HDRLEN); ++ ip = (const struct tcpdump_ip *)(p + SLIP_HDRLEN); + + #ifdef notdef + if (ndo->ndo_eflag) +@@ -109,7 +109,7 @@ + + static void + sliplink_print(netdissect_options *ndo, +- const u_char *p, const struct ip *ip, ++ const u_char *p, const struct tcpdump_ip *ip, + u_int length) + { + int dir; +@@ -143,7 +143,7 @@ + * Get it from the link layer since sl_uncompress_tcp() + * has restored the IP header copy to IPPROTO_TCP. + */ +- lastconn = GET_U_1(((const struct ip *)(p + SLX_CHDR))->ip_p); ++ lastconn = GET_U_1(((const struct tcpdump_ip *)(p + SLX_CHDR))->ip_p); + ND_PRINT("utcp %u: ", lastconn); + if (dir == -1) { + /* Direction is bogus, don't use it */ +@@ -204,7 +204,7 @@ + + static void + compressed_sl_print(netdissect_options *ndo, +- const u_char *chdr, const struct ip *ip, ++ const u_char *chdr, const struct tcpdump_ip *ip, + u_int length, int dir) + { + const u_char *cp = chdr; +diff -uNr tcpdump-tcpdump-4.99.4/print-someip.c tcpdump-for-stellar/print-someip.c +--- tcpdump-tcpdump-4.99.4/print-someip.c 2023-04-08 02:30:58.000000000 +0800 ++++ tcpdump-for-stellar/print-someip.c 2024-10-30 17:34:05.631498702 +0800 +@@ -22,7 +22,7 @@ + #include "netdissect-stdinc.h" + #include "netdissect.h" + #include "extract.h" +-#include "udp.h" ++#include "print-udp.h" + + /* + * SOMEIP Header (R19-11) +diff -uNr tcpdump-tcpdump-4.99.4/print-sunrpc.c tcpdump-for-stellar/print-sunrpc.c +--- tcpdump-tcpdump-4.99.4/print-sunrpc.c 2023-04-08 02:30:58.000000000 +0800 ++++ tcpdump-for-stellar/print-sunrpc.c 2024-10-30 17:34:05.631498702 +0800 +@@ -57,8 +57,8 @@ + #include "addrtoname.h" + #include "extract.h" + +-#include "ip.h" +-#include "ip6.h" ++#include "tcpdump_ip.h" ++#include "tcpdump_ip6.h" + + #include "rpc_auth.h" + #include "rpc_msg.h" +@@ -159,8 +159,8 @@ + u_int length, const u_char *bp2) + { + const struct sunrpc_msg *rp; +- const struct ip *ip; +- const struct ip6_hdr *ip6; ++ const struct tcpdump_ip *ip; ++ const struct tcpdump_ip6_hdr *ip6; + uint32_t x; + char srcid[20], dstid[20]; /*fits 32bit*/ + +@@ -178,15 +178,15 @@ + snprintf(dstid, sizeof(dstid), "0x%x", SUNRPC_PMAPPORT); + } + +- switch (IP_V((const struct ip *)bp2)) { ++ switch (IP_V((const struct tcpdump_ip *)bp2)) { + case 4: +- ip = (const struct ip *)bp2; ++ ip = (const struct tcpdump_ip *)bp2; + ND_PRINT("%s.%s > %s.%s: %u", + GET_IPADDR_STRING(ip->ip_src), srcid, + GET_IPADDR_STRING(ip->ip_dst), dstid, length); + break; + case 6: +- ip6 = (const struct ip6_hdr *)bp2; ++ ip6 = (const struct tcpdump_ip6_hdr *)bp2; + ND_PRINT("%s.%s > %s.%s: %u", + GET_IP6ADDR_STRING(ip6->ip6_src), srcid, + GET_IP6ADDR_STRING(ip6->ip6_dst), dstid, length); +diff -uNr tcpdump-tcpdump-4.99.4/print-tcp.c tcpdump-for-stellar/print-tcp.c +--- tcpdump-tcpdump-4.99.4/print-tcp.c 2023-04-08 02:30:58.000000000 +0800 ++++ tcpdump-for-stellar/print-tcp.c 2024-10-30 17:34:05.631498702 +0800 +@@ -25,6 +25,12 @@ + + /* \summary: TCP printer */ + ++#if defined(__clang__) ++#pragma clang diagnostic ignored "-Wall" ++#elif defined(__GNUC__) ++#pragma GCC diagnostic ignored "-Wall" ++#endif ++ + #ifndef lint + #else + __RCSID("$NetBSD: print-tcp.c,v 1.8 2007/07/24 11:53:48 drochner Exp $"); +@@ -45,10 +51,10 @@ + + #include "diag-control.h" + +-#include "tcp.h" ++#include "print-tcp.h" + +-#include "ip.h" +-#include "ip6.h" ++#include "tcpdump_ip.h" ++#include "tcpdump_ip6.h" + #include "ipproto.h" + #include "rpc_auth.h" + #include "rpc_msg.h" +@@ -56,9 +62,8 @@ + #ifdef HAVE_LIBCRYPTO + #include <openssl/md5.h> + #include "signature.h" +- + static int tcp_verify_signature(netdissect_options *ndo, +- const struct ip *ip, const struct tcphdr *tp, ++ const struct tcpdump_ip *ip, const struct tcphdr *tp, + const u_char *data, u_int length, const u_char *rcvsig); + #endif + +@@ -66,29 +71,35 @@ + static void print_tcp_fastopen_option(netdissect_options *ndo, const u_char *cp, + u_int datalen, int exp); + +-#define MAX_RST_DATA_LEN 30 ++#define MAX_RST_DATA_LEN 30 + ++/* For source or destination ports tests (UDP, TCP, ...) */ ++#define IS_SRC_OR_DST_TCPPORT(p) (sport == (p) || dport == (p)) + +-struct tha { ++struct tha ++{ + nd_ipv4 src; + nd_ipv4 dst; + u_int port; + }; + +-struct tcp_seq_hash { ++struct tcp_seq_hash ++{ + struct tcp_seq_hash *nxt; + struct tha addr; + uint32_t seq; + uint32_t ack; + }; + +-struct tha6 { ++struct tha6 ++{ + nd_ipv6 src; + nd_ipv6 dst; + u_int port; + }; + +-struct tcp_seq_hash6 { ++struct tcp_seq_hash6 ++{ + struct tcp_seq_hash6 *nxt; + struct tha6 addr; + uint32_t seq; +@@ -104,43 +115,41 @@ + static struct tcp_seq_hash6 tcp_seq_hash6[TSEQ_HASHSIZE]; + + static const struct tok tcp_flag_values[] = { +- { TH_FIN, "F" }, +- { TH_SYN, "S" }, +- { TH_RST, "R" }, +- { TH_PUSH, "P" }, +- { TH_ACK, "." }, +- { TH_URG, "U" }, +- { TH_ECNECHO, "E" }, +- { TH_CWR, "W" }, +- { 0, NULL } +-}; ++ {TH_FIN, "F"}, ++ {TH_SYN, "S"}, ++ {TH_RST, "R"}, ++ {TH_PUSH, "P"}, ++ {TH_ACK, "."}, ++ {TH_URG, "U"}, ++ {TH_ECNECHO, "E"}, ++ {TH_CWR, "W"}, ++ {0, NULL}}; + + static const struct tok tcp_option_values[] = { +- { TCPOPT_EOL, "eol" }, +- { TCPOPT_NOP, "nop" }, +- { TCPOPT_MAXSEG, "mss" }, +- { TCPOPT_WSCALE, "wscale" }, +- { TCPOPT_SACKOK, "sackOK" }, +- { TCPOPT_SACK, "sack" }, +- { TCPOPT_ECHO, "echo" }, +- { TCPOPT_ECHOREPLY, "echoreply" }, +- { TCPOPT_TIMESTAMP, "TS" }, +- { TCPOPT_CC, "cc" }, +- { TCPOPT_CCNEW, "ccnew" }, +- { TCPOPT_CCECHO, "" }, +- { TCPOPT_SIGNATURE, "md5" }, +- { TCPOPT_SCPS, "scps" }, +- { TCPOPT_UTO, "uto" }, +- { TCPOPT_TCPAO, "tcp-ao" }, +- { TCPOPT_MPTCP, "mptcp" }, +- { TCPOPT_FASTOPEN, "tfo" }, +- { TCPOPT_EXPERIMENT2, "exp" }, +- { 0, NULL } +-}; ++ {TCPOPT_EOL, "eol"}, ++ {TCPOPT_NOP, "nop"}, ++ {TCPOPT_MAXSEG, "mss"}, ++ {TCPOPT_WSCALE, "wscale"}, ++ {TCPOPT_SACKOK, "sackOK"}, ++ {TCPOPT_SACK, "sack"}, ++ {TCPOPT_ECHO, "echo"}, ++ {TCPOPT_ECHOREPLY, "echoreply"}, ++ {TCPOPT_TIMESTAMP, "TS"}, ++ {TCPOPT_CC, "cc"}, ++ {TCPOPT_CCNEW, "ccnew"}, ++ {TCPOPT_CCECHO, ""}, ++ {TCPOPT_SIGNATURE, "md5"}, ++ {TCPOPT_SCPS, "scps"}, ++ {TCPOPT_UTO, "uto"}, ++ {TCPOPT_TCPAO, "tcp-ao"}, ++ {TCPOPT_MPTCP, "mptcp"}, ++ {TCPOPT_FASTOPEN, "tfo"}, ++ {TCPOPT_EXPERIMENT2, "exp"}, ++ {0, NULL}}; + + static uint16_t + tcp_cksum(netdissect_options *ndo, +- const struct ip *ip, ++ const struct tcpdump_ip *ip, + const struct tcphdr *tp, + u_int len) + { +@@ -150,7 +159,7 @@ + + static uint16_t + tcp6_cksum(netdissect_options *ndo, +- const struct ip6_hdr *ip6, ++ const struct tcpdump_ip6_hdr *ip6, + const struct tcphdr *tp, + u_int len) + { +@@ -158,13 +167,12 @@ + IPPROTO_TCP); + } + +-void +-tcp_print(netdissect_options *ndo, +- const u_char *bp, u_int length, +- const u_char *bp2, int fragmented) ++void tcp_print(netdissect_options *ndo, ++ const u_char *bp, u_int length, ++ const u_char *bp2, int fragmented) + { + const struct tcphdr *tp; +- const struct ip *ip; ++ const struct tcpdump_ip *ip; + u_char flags; + u_int hlen; + char ch; +@@ -173,23 +181,27 @@ + u_int utoval; + uint16_t magic; + int rev; +- const struct ip6_hdr *ip6; +- u_int header_len; /* Header length in bytes */ ++ const struct tcpdump_ip6_hdr *ip6; ++ u_int header_len; /* Header length in bytes */ + + ndo->ndo_protocol = "tcp"; + tp = (const struct tcphdr *)bp; +- ip = (const struct ip *)bp2; ++ ip = (const struct tcpdump_ip *)bp2; + if (IP_V(ip) == 6) +- ip6 = (const struct ip6_hdr *)bp2; ++ ip6 = (const struct tcpdump_ip6_hdr *)bp2; + else + ip6 = NULL; + ch = '\0'; +- if (!ND_TTEST_2(tp->th_dport)) { +- if (ip6) { ++ if (!ND_TTEST_2(tp->th_dport)) ++ { ++ if (ip6) ++ { + ND_PRINT("%s > %s:", + GET_IP6ADDR_STRING(ip6->ip6_src), + GET_IP6ADDR_STRING(ip6->ip6_dst)); +- } else { ++ } ++ else ++ { + ND_PRINT("%s > %s:", + GET_IPADDR_STRING(ip->ip_src), + GET_IPADDR_STRING(ip->ip_dst)); +@@ -201,25 +213,34 @@ + sport = GET_BE_U_2(tp->th_sport); + dport = GET_BE_U_2(tp->th_dport); + +- if (ip6) { +- if (GET_U_1(ip6->ip6_nxt) == IPPROTO_TCP) { ++ if (ip6) ++ { ++ if (GET_U_1(ip6->ip6_nxt) == IPPROTO_TCP) ++ { + ND_PRINT("%s.%s > %s.%s: ", + GET_IP6ADDR_STRING(ip6->ip6_src), + tcpport_string(ndo, sport), + GET_IP6ADDR_STRING(ip6->ip6_dst), + tcpport_string(ndo, dport)); +- } else { ++ } ++ else ++ { + ND_PRINT("%s > %s: ", + tcpport_string(ndo, sport), tcpport_string(ndo, dport)); + } +- } else { +- if (GET_U_1(ip->ip_p) == IPPROTO_TCP) { ++ } ++ else ++ { ++ if (GET_U_1(ip->ip_p) == IPPROTO_TCP) ++ { + ND_PRINT("%s.%s > %s.%s: ", + GET_IPADDR_STRING(ip->ip_src), + tcpport_string(ndo, sport), + GET_IPADDR_STRING(ip->ip_dst), + tcpport_string(ndo, dport)); +- } else { ++ } ++ else ++ { + ND_PRINT("%s > %s: ", + tcpport_string(ndo, sport), tcpport_string(ndo, dport)); + } +@@ -229,7 +250,8 @@ + + hlen = TH_OFF(tp) * 4; + +- if (hlen < sizeof(*tp)) { ++ if (hlen < sizeof(*tp)) ++ { + ND_PRINT(" tcp %u [bad hdr length %u - too short, < %zu]", + length - hlen, hlen, sizeof(*tp)); + return; +@@ -240,9 +262,11 @@ + win = GET_BE_U_2(tp->th_win); + urp = GET_BE_U_2(tp->th_urp); + +- if (ndo->ndo_qflag) { ++ if (ndo->ndo_qflag) ++ { + ND_PRINT("tcp %u", length - hlen); +- if (hlen > length) { ++ if (hlen > length) ++ { + ND_PRINT(" [bad hdr length %u - too long, > %u]", + hlen, length); + } +@@ -252,7 +276,8 @@ + flags = GET_U_1(tp->th_flags); + ND_PRINT("Flags [%s]", bittok2str_nosep(tcp_flag_values, "none", flags)); + +- if (!ndo->ndo_Sflag && (flags & TH_ACK)) { ++ if (!ndo->ndo_Sflag && (flags & TH_ACK)) ++ { + /* + * Find (or record) the initial sequence numbers for + * this conversation. (we pick an arbitrary +@@ -260,7 +285,8 @@ + * both directions). + */ + rev = 0; +- if (ip6) { ++ if (ip6) ++ { + struct tcp_seq_hash6 *th; + struct tcp_seq_hash6 *tcp_seq_hash; + const void *src, *dst; +@@ -271,15 +297,19 @@ + dst = (const void *)ip6->ip6_dst; + if (sport > dport) + rev = 1; +- else if (sport == dport) { ++ else if (sport == dport) ++ { + if (UNALIGNED_MEMCMP(src, dst, sizeof(ip6->ip6_dst)) > 0) + rev = 1; + } +- if (rev) { ++ if (rev) ++ { + UNALIGNED_MEMCPY(&tha.src, dst, sizeof(ip6->ip6_dst)); + UNALIGNED_MEMCPY(&tha.dst, src, sizeof(ip6->ip6_src)); + tha.port = ((u_int)dport) << 16 | sport; +- } else { ++ } ++ else ++ { + UNALIGNED_MEMCPY(&tha.dst, dst, sizeof(ip6->ip6_dst)); + UNALIGNED_MEMCPY(&tha.src, src, sizeof(ip6->ip6_src)); + tha.port = ((u_int)sport) << 16 | dport; +@@ -291,24 +321,28 @@ + sizeof(th->addr)) == 0) + break; + +- if (!th->nxt || (flags & TH_SYN)) { ++ if (!th->nxt || (flags & TH_SYN)) ++ { + /* didn't find it or new conversation */ + /* calloc() return used by the 'tcp_seq_hash6' + hash table: do not free() */ +- if (th->nxt == NULL) { ++ if (th->nxt == NULL) ++ { + th->nxt = (struct tcp_seq_hash6 *) +- calloc(1, sizeof(*th)); ++ calloc(1, sizeof(*th)); + if (th->nxt == NULL) + (*ndo->ndo_error)(ndo, +- S_ERR_ND_MEM_ALLOC, +- "%s: calloc", __func__); ++ S_ERR_ND_MEM_ALLOC, ++ "%s: calloc", __func__); + } + th->addr = tha; + if (rev) + th->ack = seq, th->seq = ack - 1; + else + th->seq = seq, th->ack = ack - 1; +- } else { ++ } ++ else ++ { + if (rev) + seq -= th->ack, ack -= th->seq; + else +@@ -317,7 +351,9 @@ + + thseq = th->seq; + thack = th->ack; +- } else { ++ } ++ else ++ { + struct tcp_seq_hash *th; + struct tcp_seq_hash *tcp_seq_hash; + struct tha tha; +@@ -325,17 +361,21 @@ + tcp_seq_hash = tcp_seq_hash4; + if (sport > dport) + rev = 1; +- else if (sport == dport) { ++ else if (sport == dport) ++ { + if (UNALIGNED_MEMCMP(ip->ip_src, ip->ip_dst, sizeof(ip->ip_dst)) > 0) + rev = 1; + } +- if (rev) { ++ if (rev) ++ { + UNALIGNED_MEMCPY(&tha.src, ip->ip_dst, + sizeof(ip->ip_dst)); + UNALIGNED_MEMCPY(&tha.dst, ip->ip_src, + sizeof(ip->ip_src)); + tha.port = ((u_int)dport) << 16 | sport; +- } else { ++ } ++ else ++ { + UNALIGNED_MEMCPY(&tha.dst, ip->ip_dst, + sizeof(ip->ip_dst)); + UNALIGNED_MEMCPY(&tha.src, ip->ip_src, +@@ -349,24 +389,28 @@ + sizeof(th->addr)) == 0) + break; + +- if (!th->nxt || (flags & TH_SYN)) { ++ if (!th->nxt || (flags & TH_SYN)) ++ { + /* didn't find it or new conversation */ + /* calloc() return used by the 'tcp_seq_hash4' + hash table: do not free() */ +- if (th->nxt == NULL) { ++ if (th->nxt == NULL) ++ { + th->nxt = (struct tcp_seq_hash *) +- calloc(1, sizeof(*th)); ++ calloc(1, sizeof(*th)); + if (th->nxt == NULL) + (*ndo->ndo_error)(ndo, +- S_ERR_ND_MEM_ALLOC, +- "%s: calloc", __func__); ++ S_ERR_ND_MEM_ALLOC, ++ "%s: calloc", __func__); + } + th->addr = tha; + if (rev) + th->ack = seq, th->seq = ack - 1; + else + th->seq = seq, th->ack = ack - 1; +- } else { ++ } ++ else ++ { + if (rev) + seq -= th->ack, ack -= th->seq; + else +@@ -376,58 +420,69 @@ + thseq = th->seq; + thack = th->ack; + } +- } else { ++ } ++ else ++ { + /*fool gcc*/ + thseq = thack = rev = 0; + } +- if (hlen > length) { ++ if (hlen > length) ++ { + ND_PRINT(" [bad hdr length %u - too long, > %u]", + hlen, length); + return; + } + +- if (ndo->ndo_vflag && !ndo->ndo_Kflag && !fragmented) { ++ if (ndo->ndo_vflag && !ndo->ndo_Kflag && !fragmented) ++ { + /* Check the checksum, if possible. */ + uint16_t sum, tcp_sum; + +- if (IP_V(ip) == 4) { +- if (ND_TTEST_LEN(tp->th_sport, length)) { ++ if (IP_V(ip) == 4) ++ { ++ if (ND_TTEST_LEN(tp->th_sport, length)) ++ { + sum = tcp_cksum(ndo, ip, tp, length); + tcp_sum = GET_BE_U_2(tp->th_sum); + + ND_PRINT(", cksum 0x%04x", tcp_sum); + if (sum != 0) + ND_PRINT(" (incorrect -> 0x%04x)", +- in_cksum_shouldbe(tcp_sum, sum)); ++ in_cksum_shouldbe(tcp_sum, sum)); + else + ND_PRINT(" (correct)"); + } +- } else if (IP_V(ip) == 6) { +- if (ND_TTEST_LEN(tp->th_sport, length)) { ++ } ++ else if (IP_V(ip) == 6) ++ { ++ if (ND_TTEST_LEN(tp->th_sport, length)) ++ { + sum = tcp6_cksum(ndo, ip6, tp, length); + tcp_sum = GET_BE_U_2(tp->th_sum); + + ND_PRINT(", cksum 0x%04x", tcp_sum); + if (sum != 0) + ND_PRINT(" (incorrect -> 0x%04x)", +- in_cksum_shouldbe(tcp_sum, sum)); ++ in_cksum_shouldbe(tcp_sum, sum)); + else + ND_PRINT(" (correct)"); +- + } + } + } + + length -= hlen; +- if (ndo->ndo_vflag > 1 || length > 0 || flags & (TH_SYN | TH_FIN | TH_RST)) { ++ if (ndo->ndo_vflag > 1 || length > 0 || flags & (TH_SYN | TH_FIN | TH_RST)) ++ { + ND_PRINT(", seq %u", seq); + +- if (length > 0) { ++ if (length > 0) ++ { + ND_PRINT(":%u", seq + length); + } + } + +- if (flags & TH_ACK) { ++ if (flags & TH_ACK) ++ { + ND_PRINT(", ack %u", ack); + } + +@@ -438,7 +493,8 @@ + /* + * Handle any options. + */ +- if (hlen > sizeof(*tp)) { ++ if (hlen > sizeof(*tp)) ++ { + const u_char *cp; + u_int i, opt, datalen; + u_int len; +@@ -446,30 +502,37 @@ + hlen -= sizeof(*tp); + cp = (const u_char *)tp + sizeof(*tp); + ND_PRINT(", options ["); +- while (hlen > 0) { ++ while (hlen > 0) ++ { + if (ch != '\0') + ND_PRINT("%c", ch); + opt = GET_U_1(cp); + cp++; + if (ZEROLENOPT(opt)) + len = 1; +- else { ++ else ++ { + len = GET_U_1(cp); +- cp++; /* total including type, len */ ++ cp++; /* total including type, len */ + if (len < 2 || len > hlen) + goto bad; +- --hlen; /* account for length byte */ ++ --hlen; /* account for length byte */ + } +- --hlen; /* account for type byte */ ++ --hlen; /* account for type byte */ + datalen = 0; + + /* Bail if "l" bytes of data are not left or were not captured */ +-#define LENCHECK(l) { if ((l) > hlen) goto bad; ND_TCHECK_LEN(cp, l); } +- ++#define LENCHECK(l) \ ++ { \ ++ if ((l) > hlen) \ ++ goto bad; \ ++ ND_TCHECK_LEN(cp, l); \ ++ } + + ND_PRINT("%s", tok2str(tcp_option_values, "unknown-%u", opt)); + +- switch (opt) { ++ switch (opt) ++ { + + case TCPOPT_MAXSEG: + datalen = 2; +@@ -485,21 +548,28 @@ + + case TCPOPT_SACK: + datalen = len - 2; +- if (datalen % 8 != 0) { ++ if (datalen % 8 != 0) ++ { + ND_PRINT(" invalid sack"); +- } else { ++ } ++ else ++ { + uint32_t s, e; + + ND_PRINT(" %u ", datalen / 8); +- for (i = 0; i < datalen; i += 8) { ++ for (i = 0; i < datalen; i += 8) ++ { + LENCHECK(i + 4); + s = GET_BE_U_4(cp + i); + LENCHECK(i + 8); + e = GET_BE_U_4(cp + i + 4); +- if (rev) { ++ if (rev) ++ { + s -= thseq; + e -= thseq; +- } else { ++ } ++ else ++ { + s -= thack; + e -= thack; + } +@@ -527,8 +597,8 @@ + datalen = 8; + LENCHECK(datalen); + ND_PRINT(" val %u ecr %u", +- GET_BE_U_4(cp), +- GET_BE_U_4(cp + 4)); ++ GET_BE_U_4(cp), ++ GET_BE_U_4(cp + 4)); + break; + + case TCPOPT_SIGNATURE: +@@ -537,7 +607,8 @@ + ND_PRINT(" "); + #ifdef HAVE_LIBCRYPTO + switch (tcp_verify_signature(ndo, ip, tp, +- bp + TH_OFF(tp) * 4, length, cp)) { ++ bp + TH_OFF(tp) * 4, length, cp)) ++ { + + case SIGNATURE_VALID: + ND_PRINT("valid"); +@@ -574,17 +645,22 @@ + * (This includes the Kind and Length fields already processed + * at this point.) + */ +- if (datalen < 2) { ++ if (datalen < 2) ++ { + nd_print_invalid(ndo); +- } else { ++ } ++ else ++ { + LENCHECK(1); + ND_PRINT(" keyid %u", GET_U_1(cp)); + LENCHECK(2); + ND_PRINT(" rnextkeyid %u", + GET_U_1(cp + 1)); +- if (datalen > 2) { ++ if (datalen > 2) ++ { + ND_PRINT(" mac 0x"); +- for (i = 2; i < datalen; i++) { ++ for (i = 2; i < datalen; i++) ++ { + LENCHECK(i + 1); + ND_PRINT("%02x", + GET_U_1(cp + i)); +@@ -615,7 +691,7 @@ + break; + + case TCPOPT_MPTCP: +- { ++ { + const u_char *snapend_save; + int ret; + +@@ -636,7 +712,7 @@ + if (!ret) + goto bad; + break; +- } ++ } + + case TCPOPT_FASTOPEN: + datalen = len - 2; +@@ -654,7 +730,8 @@ + magic = GET_BE_U_2(cp); + ND_PRINT("-"); + +- switch(magic) { ++ switch (magic) ++ { + + case 0xf989: /* TCP Fast Open RFC 7413 */ + print_tcp_fastopen_option(ndo, cp + 2, datalen - 2, TRUE); +@@ -671,7 +748,8 @@ + datalen = len - 2; + if (datalen) + ND_PRINT(" 0x"); +- for (i = 0; i < datalen; ++i) { ++ for (i = 0; i < datalen; ++i) ++ { + LENCHECK(i + 1); + ND_PRINT("%02x", GET_U_1(cp + i)); + } +@@ -683,9 +761,9 @@ + hlen -= datalen; + + /* Check specification against observed length */ +- ++datalen; /* option octet */ ++ ++datalen; /* option octet */ + if (!ZEROLENOPT(opt)) +- ++datalen; /* size octet */ ++ ++datalen; /* size octet */ + if (datalen != len) + ND_PRINT("[len %u]", len); + ch = ','; +@@ -711,19 +789,23 @@ + * Do a bounds check before decoding the payload. + * At least the header data is required. + */ +- if (!ND_TTEST_LEN(bp, header_len)) { ++ if (!ND_TTEST_LEN(bp, header_len)) ++ { + ND_PRINT(" [remaining caplen(%u) < header length(%u)]", + ND_BYTES_AVAILABLE_AFTER(bp), header_len); + nd_trunc_longjmp(ndo); + } + bp += header_len; +- if ((flags & TH_RST) && ndo->ndo_vflag) { ++ if ((flags & TH_RST) && ndo->ndo_vflag) ++ { + print_tcp_rst_data(ndo, bp, length); + return; + } + +- if (ndo->ndo_packettype) { +- switch (ndo->ndo_packettype) { ++ if (ndo->ndo_packettype) ++ { ++ switch (ndo->ndo_packettype) ++ { + case PT_ZMTP1: + zmtp1_print(ndo, bp, length); + break; +@@ -738,52 +820,107 @@ + return; + } + +- if (IS_SRC_OR_DST_PORT(TELNET_PORT)) { ++ if (IS_SRC_OR_DST_TCPPORT(TELNET_PORT)) ++ { + telnet_print(ndo, bp, length); +- } else if (IS_SRC_OR_DST_PORT(SMTP_PORT)) { ++ return; ++ } ++ if (IS_SRC_OR_DST_TCPPORT(SMTP_PORT)) ++ { + ND_PRINT(": "); + smtp_print(ndo, bp, length); +- } else if (IS_SRC_OR_DST_PORT(WHOIS_PORT)) { ++ return; ++ } ++ if (IS_SRC_OR_DST_TCPPORT(WHOIS_PORT)) ++ { + ND_PRINT(": "); + whois_print(ndo, bp, length); +- } else if (IS_SRC_OR_DST_PORT(BGP_PORT)) ++ return; ++ } ++ if (IS_SRC_OR_DST_TCPPORT(BGP_PORT)) ++ { + bgp_print(ndo, bp, length); +- else if (IS_SRC_OR_DST_PORT(PPTP_PORT)) ++ return; ++ } ++ if (IS_SRC_OR_DST_TCPPORT(PPTP_PORT)) ++ { + pptp_print(ndo, bp); +- else if (IS_SRC_OR_DST_PORT(REDIS_PORT)) ++ return; ++ } ++ if (IS_SRC_OR_DST_TCPPORT(REDIS_PORT)) ++ { + resp_print(ndo, bp, length); +- else if (IS_SRC_OR_DST_PORT(SSH_PORT)) ++ return; ++ } ++ if (IS_SRC_OR_DST_TCPPORT(SSH_PORT)) ++ { + ssh_print(ndo, bp, length); ++ return; ++ } + #ifdef ENABLE_SMB +- else if (IS_SRC_OR_DST_PORT(NETBIOS_SSN_PORT)) ++ if (IS_SRC_OR_DST_TCPPORT(NETBIOS_SSN_PORT)) ++ { + nbt_tcp_print(ndo, bp, length); +- else if (IS_SRC_OR_DST_PORT(SMB_PORT)) ++ return; ++ } ++ if (IS_SRC_OR_DST_TCPPORT(SMB_PORT)) ++ { + smb_tcp_print(ndo, bp, length); ++ return; ++ } + #endif +- else if (IS_SRC_OR_DST_PORT(BEEP_PORT)) ++ if (IS_SRC_OR_DST_TCPPORT(BEEP_PORT)) ++ { + beep_print(ndo, bp, length); +- else if (IS_SRC_OR_DST_PORT(OPENFLOW_PORT_OLD) || IS_SRC_OR_DST_PORT(OPENFLOW_PORT_IANA)) ++ return; ++ } ++ if (IS_SRC_OR_DST_TCPPORT(OPENFLOW_PORT_OLD) || IS_SRC_OR_DST_TCPPORT(OPENFLOW_PORT_IANA)) ++ { + openflow_print(ndo, bp, length); +- else if (IS_SRC_OR_DST_PORT(FTP_PORT)) { ++ return; ++ } ++ if (IS_SRC_OR_DST_TCPPORT(FTP_PORT)) ++ { + ND_PRINT(": "); + ftp_print(ndo, bp, length); +- } else if (IS_SRC_OR_DST_PORT(HTTP_PORT) || IS_SRC_OR_DST_PORT(HTTP_PORT_ALT)) { ++ return; ++ } ++ if (IS_SRC_OR_DST_TCPPORT(HTTP_PORT) || IS_SRC_OR_DST_TCPPORT(HTTP_PORT_ALT)) ++ { + ND_PRINT(": "); + http_print(ndo, bp, length); +- } else if (IS_SRC_OR_DST_PORT(RTSP_PORT) || IS_SRC_OR_DST_PORT(RTSP_PORT_ALT)) { ++ return; ++ } ++ if (IS_SRC_OR_DST_TCPPORT(RTSP_PORT) || IS_SRC_OR_DST_TCPPORT(RTSP_PORT_ALT)) ++ { + ND_PRINT(": "); + rtsp_print(ndo, bp, length); +- } else if (IS_SRC_OR_DST_PORT(NAMESERVER_PORT)) { ++ return; ++ } ++ if (IS_SRC_OR_DST_TCPPORT(TCPDUMP_NAMESERVER_TCP_PORT)) ++ { + /* over_tcp: TRUE, is_mdns: FALSE */ + domain_print(ndo, bp, length, TRUE, FALSE); +- } else if (IS_SRC_OR_DST_PORT(MSDP_PORT)) { ++ return; ++ } ++ if (IS_SRC_OR_DST_TCPPORT(MSDP_PORT)) ++ { + msdp_print(ndo, bp, length); +- } else if (IS_SRC_OR_DST_PORT(RPKI_RTR_PORT)) { ++ return; ++ } ++ if (IS_SRC_OR_DST_TCPPORT(RPKI_RTR_PORT)) ++ { + rpki_rtr_print(ndo, bp, length); +- } else if (IS_SRC_OR_DST_PORT(LDP_PORT)) { ++ return; ++ } ++ if (IS_SRC_OR_DST_TCPPORT(TCPDUMP_LDP_PORT)) ++ { + ldp_print(ndo, bp, length); +- } else if ((IS_SRC_OR_DST_PORT(NFS_PORT)) && +- length >= 4 && ND_TTEST_4(bp)) { ++ return; ++ } ++ if ((IS_SRC_OR_DST_TCPPORT(NFS_PORT)) && ++ length >= 4 && ND_TTEST_4(bp)) ++ { + /* + * If data present, header length valid, and NFS port used, + * assume NFS. +@@ -795,24 +932,28 @@ + enum sunrpc_msg_type direction; + + fraglen = GET_BE_U_4(bp) & 0x7FFFFFFF; +- if (fraglen > (length) - 4) +- fraglen = (length) - 4; ++ if (fraglen > (length)-4) ++ fraglen = (length)-4; + rp = (const struct sunrpc_msg *)(bp + 4); +- if (ND_TTEST_4(rp->rm_direction)) { +- direction = (enum sunrpc_msg_type) GET_BE_U_4(rp->rm_direction); +- if (dport == NFS_PORT && direction == SUNRPC_CALL) { ++ if (ND_TTEST_4(rp->rm_direction)) ++ { ++ direction = (enum sunrpc_msg_type)GET_BE_U_4(rp->rm_direction); ++ if (dport == NFS_PORT && direction == SUNRPC_CALL) ++ { + ND_PRINT(": NFS request xid %u ", + GET_BE_U_4(rp->rm_xid)); + nfsreq_noaddr_print(ndo, (const u_char *)rp, fraglen, (const u_char *)ip); + return; + } +- if (sport == NFS_PORT && direction == SUNRPC_REPLY) { ++ if (sport == NFS_PORT && direction == SUNRPC_REPLY) ++ { + ND_PRINT(": NFS reply xid %u ", + GET_BE_U_4(rp->rm_xid)); + nfsreply_noaddr_print(ndo, (const u_char *)rp, fraglen, (const u_char *)ip); + return; + } + } ++ return; + } + + return; +@@ -849,12 +990,14 @@ + u_char c; + + ND_PRINT(ND_TTEST_LEN(sp, length) ? " [RST" : " [!RST"); +- if (length > MAX_RST_DATA_LEN) { +- length = MAX_RST_DATA_LEN; /* can use -X for longer */ +- ND_PRINT("+"); /* indicate we truncate */ ++ if (length > MAX_RST_DATA_LEN) ++ { ++ length = MAX_RST_DATA_LEN; /* can use -X for longer */ ++ ND_PRINT("+"); /* indicate we truncate */ + } + ND_PRINT(" "); +- while (length && sp < ndo->ndo_snapend) { ++ while (length && sp < ndo->ndo_snapend) ++ { + c = GET_U_1(sp); + sp++; + fn_print_char(ndo, c); +@@ -872,14 +1015,20 @@ + if (exp) + ND_PRINT("tfo"); + +- if (datalen == 0) { ++ if (datalen == 0) ++ { + /* Fast Open Cookie Request */ + ND_PRINT(" cookiereq"); +- } else { ++ } ++ else ++ { + /* Fast Open Cookie */ +- if (datalen % 2 != 0 || datalen < 4 || datalen > 16) { ++ if (datalen % 2 != 0 || datalen < 4 || datalen > 16) ++ { + nd_print_invalid(ndo); +- } else { ++ } ++ else ++ { + ND_PRINT(" cookie "); + for (i = 0; i < datalen; ++i) + ND_PRINT("%02x", GET_U_1(cp + i)); +@@ -891,7 +1040,7 @@ + DIAG_OFF_DEPRECATION + static int + tcp_verify_signature(netdissect_options *ndo, +- const struct ip *ip, const struct tcphdr *tp, ++ const struct tcpdump_ip *ip, const struct tcphdr *tp, + const u_char *data, u_int length, const u_char *rcvsig) + { + struct tcphdr tp1; +@@ -899,18 +1048,20 @@ + char zero_proto = 0; + MD5_CTX ctx; + uint16_t savecsum, tlen; +- const struct ip6_hdr *ip6; ++ const struct tcpdump_ip6_hdr *ip6; + uint32_t len32; + uint8_t nxt; + +- if (data + length > ndo->ndo_snapend) { ++ if (data + length > ndo->ndo_snapend) ++ { + ND_PRINT("snaplen too short, "); + return (CANT_CHECK_SIGNATURE); + } + + tp1 = *tp; + +- if (ndo->ndo_sigsecret == NULL) { ++ if (ndo->ndo_sigsecret == NULL) ++ { + ND_PRINT("shared secret not supplied with -M, "); + return (CANT_CHECK_SIGNATURE); + } +@@ -919,7 +1070,8 @@ + /* + * Step 1: Update MD5 hash with IP pseudo-header. + */ +- if (IP_V(ip) == 4) { ++ if (IP_V(ip) == 4) ++ { + MD5_Update(&ctx, (const char *)&ip->ip_src, sizeof(ip->ip_src)); + MD5_Update(&ctx, (const char *)&ip->ip_dst, sizeof(ip->ip_dst)); + MD5_Update(&ctx, (const char *)&zero_proto, sizeof(zero_proto)); +@@ -927,8 +1079,10 @@ + tlen = GET_BE_U_2(ip->ip_len) - IP_HL(ip) * 4; + tlen = htons(tlen); + MD5_Update(&ctx, (const char *)&tlen, sizeof(tlen)); +- } else if (IP_V(ip) == 6) { +- ip6 = (const struct ip6_hdr *)ip; ++ } ++ else if (IP_V(ip) == 6) ++ { ++ ip6 = (const struct tcpdump_ip6_hdr *)ip; + MD5_Update(&ctx, (const char *)&ip6->ip6_src, sizeof(ip6->ip6_src)); + MD5_Update(&ctx, (const char *)&ip6->ip6_dst, sizeof(ip6->ip6_dst)); + len32 = htonl(GET_BE_U_2(ip6->ip6_plen)); +@@ -939,7 +1093,9 @@ + MD5_Update(&ctx, (const char *)&nxt, sizeof(nxt)); + nxt = IPPROTO_TCP; + MD5_Update(&ctx, (const char *)&nxt, sizeof(nxt)); +- } else { ++ } ++ else ++ { + ND_PRINT("IP version not 4 or 6, "); + return (CANT_CHECK_SIGNATURE); + } +diff -uNr tcpdump-tcpdump-4.99.4/print-tcp.h tcpdump-for-stellar/print-tcp.h +--- tcpdump-tcpdump-4.99.4/print-tcp.h 1970-01-01 08:00:00.000000000 +0800 ++++ tcpdump-for-stellar/print-tcp.h 2024-10-30 17:34:06.265498697 +0800 +@@ -0,0 +1,159 @@ ++/* ++ * Copyright (c) 1982, 1986, 1993 ++ * The Regents of the University of California. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by the University of ++ * California, Berkeley and its contributors. ++ * 4. Neither the name of the University nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ * @(#)tcp.h 8.1 (Berkeley) 6/10/93 ++ */ ++#pragma once ++/* ++ * TCP header. ++ * Per RFC 793, September, 1981. ++ */ ++struct tcphdr ++{ ++ nd_uint16_t th_sport; /* source port */ ++ nd_uint16_t th_dport; /* destination port */ ++ nd_uint32_t th_seq; /* sequence number */ ++ nd_uint32_t th_ack; /* acknowledgement number */ ++ nd_uint8_t th_offx2; /* data offset, rsvd */ ++ nd_uint8_t th_flags; ++ nd_uint16_t th_win; /* window */ ++ nd_uint16_t th_sum; /* checksum */ ++ nd_uint16_t th_urp; /* urgent pointer */ ++}; ++ ++#define TH_OFF(th) ((GET_U_1((th)->th_offx2) & 0xf0) >> 4) ++ ++/* TCP flags */ ++#define TH_FIN 0x01 ++#define TH_SYN 0x02 ++#define TH_RST 0x04 ++#define TH_PUSH 0x08 ++#define TH_ACK 0x10 ++#define TH_URG 0x20 ++#define TH_ECNECHO 0x40 /* ECN Echo */ ++#define TH_CWR 0x80 /* ECN Cwnd Reduced */ ++ ++#define TCPOPT_EOL 0 ++#define TCPOPT_NOP 1 ++#define TCPOPT_MAXSEG 2 ++#define TCPOLEN_MAXSEG 4 ++#define TCPOPT_WSCALE 3 /* window scale factor (rfc1323) */ ++#define TCPOPT_SACKOK 4 /* selective ack ok (rfc2018) */ ++#define TCPOPT_SACK 5 /* selective ack (rfc2018) */ ++#define TCPOPT_ECHO 6 /* echo (rfc1072) */ ++#define TCPOPT_ECHOREPLY 7 /* echo (rfc1072) */ ++#define TCPOPT_TIMESTAMP 8 /* timestamp (rfc1323) */ ++#define TCPOLEN_TIMESTAMP 10 ++#define TCPOLEN_TSTAMP_APPA (TCPOLEN_TIMESTAMP + 2) /* appendix A */ ++#define TCPOPT_CC 11 /* T/TCP CC options (rfc1644) */ ++#define TCPOPT_CCNEW 12 /* T/TCP CC options (rfc1644) */ ++#define TCPOPT_CCECHO 13 /* T/TCP CC options (rfc1644) */ ++#define TCPOPT_SIGNATURE 19 /* Keyed MD5 (rfc2385) */ ++#define TCPOLEN_SIGNATURE 18 ++#define TCP_SIGLEN 16 /* length of an option 19 digest */ ++#define TCPOPT_SCPS 20 /* SCPS-TP (CCSDS 714.0-B-2) */ ++#define TCPOPT_UTO 28 /* tcp user timeout (rfc5482) */ ++#define TCPOLEN_UTO 4 ++#define TCPOPT_TCPAO 29 /* TCP authentication option (rfc5925) */ ++#define TCPOPT_MPTCP 30 /* MPTCP options */ ++#define TCPOPT_FASTOPEN 34 /* TCP Fast Open (rfc7413) */ ++#define TCPOPT_EXPERIMENT2 254 /* experimental headers (rfc4727) */ ++ ++#define TCPOPT_TSTAMP_HDR \ ++ (TCPOPT_NOP << 24 | TCPOPT_NOP << 16 | TCPOPT_TIMESTAMP << 8 | TCPOLEN_TIMESTAMP) ++ ++#ifndef FTP_PORT ++#define FTP_PORT 21 ++#endif ++#ifndef SSH_PORT ++#define SSH_PORT 22 ++#endif ++#ifndef TELNET_PORT ++#define TELNET_PORT 23 ++#endif ++#ifndef SMTP_PORT ++#define SMTP_PORT 25 ++#endif ++#ifndef WHOIS_PORT ++#define WHOIS_PORT 43 ++#endif ++ ++#define TCPDUMP_NAMESERVER_TCP_PORT 53 ++ ++#ifndef HTTP_PORT ++#define HTTP_PORT 80 ++#endif ++#ifndef NETBIOS_SSN_PORT ++#define NETBIOS_SSN_PORT 139 /* RFC 1001, RFC 1002 */ ++#endif ++#ifndef BGP_PORT ++#define BGP_PORT 179 ++#endif ++#ifndef RPKI_RTR_PORT ++#define RPKI_RTR_PORT 323 ++#endif ++#ifndef SMB_PORT ++#define SMB_PORT 445 ++#endif ++#ifndef RTSP_PORT ++#define RTSP_PORT 554 ++#endif ++#ifndef MSDP_PORT ++#define MSDP_PORT 639 ++#endif ++#ifndef TCPDUMP_LDP_PORT ++#define TCPDUMP_LDP_PORT 646 ++#endif ++#ifndef PPTP_PORT ++#define PPTP_PORT 1723 ++#endif ++#ifndef NFS_PORT ++#define NFS_PORT 2049 ++#endif ++#ifndef OPENFLOW_PORT_OLD ++#define OPENFLOW_PORT_OLD 6633 ++#endif ++#ifndef OPENFLOW_PORT_IANA ++#define OPENFLOW_PORT_IANA 6653 ++#endif ++#ifndef HTTP_PORT_ALT ++#define HTTP_PORT_ALT 8080 ++#endif ++#ifndef RTSP_PORT_ALT ++#define RTSP_PORT_ALT 8554 ++#endif ++#ifndef BEEP_PORT ++#define BEEP_PORT 10288 ++#endif ++#ifndef REDIS_PORT ++#define REDIS_PORT 6379 ++#endif +diff -uNr tcpdump-tcpdump-4.99.4/print-udp.c tcpdump-for-stellar/print-udp.c +--- tcpdump-tcpdump-4.99.4/print-udp.c 2023-04-08 02:30:58.000000000 +0800 ++++ tcpdump-for-stellar/print-udp.c 2024-10-30 17:34:05.631498702 +0800 +@@ -20,109 +20,118 @@ + */ + + /* \summary: UDP printer */ +- + #ifdef HAVE_CONFIG_H + #include <config.h> + #endif +- + #include "netdissect-stdinc.h" +- + #include "netdissect.h" + #include "addrtoname.h" + #include "extract.h" + #include "appletalk.h" +- +-#include "udp.h" +- +-#include "ip.h" +-#include "ip6.h" ++#include "tcpdump_ip.h" ++#include "tcpdump_ip6.h" + #include "ipproto.h" + #include "rpc_auth.h" + #include "rpc_msg.h" +- + #include "nfs.h" ++#include "print-udp.h" + +- +-struct rtcphdr { +- nd_uint16_t rh_flags; /* T:2 P:1 CNT:5 PT:8 */ +- nd_uint16_t rh_len; /* length of message (in words) */ +- nd_uint32_t rh_ssrc; /* synchronization src id */ ++struct rtcphdr ++{ ++ nd_uint16_t rh_flags; /* T:2 P:1 CNT:5 PT:8 */ ++ nd_uint16_t rh_len; /* length of message (in words) */ ++ nd_uint32_t rh_ssrc; /* synchronization src id */ + }; + +-typedef struct { +- nd_uint32_t upper; /* more significant 32 bits */ +- nd_uint32_t lower; /* less significant 32 bits */ ++typedef struct ++{ ++ nd_uint32_t upper; /* more significant 32 bits */ ++ nd_uint32_t lower; /* less significant 32 bits */ + } ntp64; + + /* + * Sender report. + */ +-struct rtcp_sr { +- ntp64 sr_ntp; /* 64-bit ntp timestamp */ +- nd_uint32_t sr_ts; /* reference media timestamp */ +- nd_uint32_t sr_np; /* no. packets sent */ +- nd_uint32_t sr_nb; /* no. bytes sent */ ++struct rtcp_sr ++{ ++ ntp64 sr_ntp; /* 64-bit ntp timestamp */ ++ nd_uint32_t sr_ts; /* reference media timestamp */ ++ nd_uint32_t sr_np; /* no. packets sent */ ++ nd_uint32_t sr_nb; /* no. bytes sent */ + }; + + /* + * Receiver report. + * Time stamps are middle 32-bits of ntp timestamp. + */ +-struct rtcp_rr { +- nd_uint32_t rr_srcid; /* sender being reported */ +- nd_uint32_t rr_nl; /* no. packets lost */ +- nd_uint32_t rr_ls; /* extended last seq number received */ +- nd_uint32_t rr_dv; /* jitter (delay variance) */ +- nd_uint32_t rr_lsr; /* orig. ts from last rr from this src */ +- nd_uint32_t rr_dlsr; /* time from recpt of last rr to xmit time */ ++struct rtcp_rr ++{ ++ nd_uint32_t rr_srcid; /* sender being reported */ ++ nd_uint32_t rr_nl; /* no. packets lost */ ++ nd_uint32_t rr_ls; /* extended last seq number received */ ++ nd_uint32_t rr_dv; /* jitter (delay variance) */ ++ nd_uint32_t rr_lsr; /* orig. ts from last rr from this src */ ++ nd_uint32_t rr_dlsr; /* time from recpt of last rr to xmit time */ + }; + + /*XXX*/ +-#define RTCP_PT_SR 200 +-#define RTCP_PT_RR 201 +-#define RTCP_PT_SDES 202 +-#define RTCP_SDES_CNAME 1 +-#define RTCP_SDES_NAME 2 +-#define RTCP_SDES_EMAIL 3 +-#define RTCP_SDES_PHONE 4 +-#define RTCP_SDES_LOC 5 +-#define RTCP_SDES_TOOL 6 +-#define RTCP_SDES_NOTE 7 +-#define RTCP_SDES_PRIV 8 +-#define RTCP_PT_BYE 203 +-#define RTCP_PT_APP 204 ++#define RTCP_PT_SR 200 ++#define RTCP_PT_RR 201 ++#define RTCP_PT_SDES 202 ++#define RTCP_SDES_CNAME 1 ++#define RTCP_SDES_NAME 2 ++#define RTCP_SDES_EMAIL 3 ++#define RTCP_SDES_PHONE 4 ++#define RTCP_SDES_LOC 5 ++#define RTCP_SDES_TOOL 6 ++#define RTCP_SDES_NOTE 7 ++#define RTCP_SDES_PRIV 8 ++#define RTCP_PT_BYE 203 ++#define RTCP_PT_APP 204 ++ ++#define IS_SRC_OR_DST_UDPPORT(p) (sport == (p) || dport == (p)) ++ ++static inline int CHECK_IS_SRC_OR_DST_PORT(unsigned short p, unsigned short sport, unsigned short dport) ++{ ++ return (sport == (p) || dport == (p)); ++} + +-static void +-vat_print(netdissect_options *ndo, const u_char *hdr, u_int length) ++// cppcheck-suppress ++static void vat_print(netdissect_options *ndo, const u_char *hdr, u_int length) + { + /* vat/vt audio */ + u_int ts; + + ndo->ndo_protocol = "vat"; +- if (length < 2) { ++ if (length < 2) ++ { + ND_PRINT("udp/va/vat, length %u < 2", length); + return; + } + ts = GET_BE_U_2(hdr); +- if ((ts & 0xf060) != 0) { ++ if ((ts & 0xf060) != 0) ++ { + /* probably vt */ + ND_PRINT("udp/vt %u %u / %u", +- length, +- ts & 0x3ff, ts >> 10); +- } else { ++ length, ++ ts & 0x3ff, ts >> 10); ++ } ++ else ++ { + /* probably vat */ + uint32_t i0, i1; + +- if (length < 8) { ++ if (length < 8) ++ { + ND_PRINT("udp/vat, length %u < 8", length); + return; + } + i0 = GET_BE_U_4(&((const u_int *)hdr)[0]); + i1 = GET_BE_U_4(&((const u_int *)hdr)[1]); + ND_PRINT("udp/vat %u c%u %u%s", +- length - 8, +- i0 & 0xffff, +- i1, i0 & 0x800000? "*" : ""); ++ length - 8, ++ i0 & 0xffff, ++ i1, i0 & 0x800000 ? "*" : ""); + /* audio format */ + if (i0 & 0x1f0000) + ND_PRINT(" f%u", (i0 >> 16) & 0x1f); +@@ -131,17 +140,18 @@ + } + } + +-static void +-rtp_print(netdissect_options *ndo, const u_char *hdr, u_int len) ++// cppcheck-suppress ++static void rtp_print(netdissect_options *ndo, const u_char *hdr, u_int len) + { + /* rtp v1 or v2 */ + const u_int *ip = (const u_int *)hdr; + u_int hasopt, hasext, contype, hasmarker, dlen; + uint32_t i0, i1; +- const char * ptype; ++ const char *ptype; + + ndo->ndo_protocol = "rtp"; +- if (len < 8) { ++ if (len < 8) ++ { + ND_PRINT("udp/rtp, length %u < 8", len); + return; + } +@@ -153,15 +163,19 @@ + len -= 2; + hasopt = 0; + hasext = 0; +- if ((i0 >> 30) == 1) { ++ if ((i0 >> 30) == 1) ++ { + /* rtp v1 - draft-ietf-avt-rtp-04 */ + hasopt = i0 & 0x800000; + contype = (i0 >> 16) & 0x3f; + hasmarker = i0 & 0x400000; + ptype = "rtpv1"; +- } else { ++ } ++ else ++ { + /* rtp v2 - RFC 3550 */ +- if (dlen < 4) { ++ if (dlen < 4) ++ { + ND_PRINT("udp/rtp, length %u < 12", dlen + 8); + return; + } +@@ -174,21 +188,25 @@ + len -= 1; + } + ND_PRINT("udp/%s %u c%u %s%s %u %u", +- ptype, +- dlen, +- contype, +- (hasopt || hasext)? "+" : "", +- hasmarker? "*" : "", +- i0 & 0xffff, +- i1); +- if (ndo->ndo_vflag) { ++ ptype, ++ dlen, ++ contype, ++ (hasopt || hasext) ? "+" : "", ++ hasmarker ? "*" : "", ++ i0 & 0xffff, ++ i1); ++ if (ndo->ndo_vflag) ++ { + ND_PRINT(" %u", GET_BE_U_4(&((const u_int *)hdr)[2])); +- if (hasopt) { ++ if (hasopt) ++ { + u_int i2, optlen; +- do { ++ do ++ { + i2 = GET_BE_U_4(ip); + optlen = (i2 >> 16) & 0xff; +- if (optlen == 0 || optlen > len) { ++ if (optlen == 0 || optlen > len) ++ { + ND_PRINT(" !opt"); + return; + } +@@ -196,11 +214,13 @@ + len -= optlen; + } while ((int)i2 >= 0); + } +- if (hasext) { ++ if (hasext) ++ { + u_int i2, extlen; + i2 = GET_BE_U_4(ip); + extlen = (i2 & 0xffff) + 1; +- if (extlen > len) { ++ if (extlen > len) ++ { + ND_PRINT(" !ext"); + return; + } +@@ -211,8 +231,8 @@ + } + } + +-static const u_char * +-rtcp_print(netdissect_options *ndo, const u_char *hdr, const u_char *ep) ++// cppcheck-suppress ++static const u_char *rtcp_print(netdissect_options *ndo, const u_char *hdr, const u_char *ep) + { + /* rtp v2 control (rtcp) */ + const struct rtcp_rr *rr = 0; +@@ -230,7 +250,8 @@ + len = (GET_BE_U_2(rh->rh_len) + 1) * 4; + flags = GET_BE_U_2(rh->rh_flags); + cnt = (flags >> 8) & 0x1f; +- switch (flags & 0xff) { ++ switch (flags & 0xff) ++ { + case RTCP_PT_SR: + sr = (const struct rtcp_sr *)(rh + 1); + ND_PRINT(" sr"); +@@ -242,10 +263,10 @@ + goto trunc; + ND_TCHECK_SIZE(sr); + ts = (double)(GET_BE_U_4(sr->sr_ntp.upper)) + +- ((double)(GET_BE_U_4(sr->sr_ntp.lower)) / +- FMAXINT); ++ ((double)(GET_BE_U_4(sr->sr_ntp.lower)) / ++ FMAXINT); + ND_PRINT(" @%.2f %u %up %ub", ts, GET_BE_U_4(sr->sr_ts), +- GET_BE_U_4(sr->sr_np), GET_BE_U_4(sr->sr_nb)); ++ GET_BE_U_4(sr->sr_np), GET_BE_U_4(sr->sr_nb)); + rr = (const struct rtcp_rr *)(sr + 1); + break; + case RTCP_PT_RR: +@@ -275,7 +296,8 @@ + } + if (cnt > 1) + ND_PRINT(" c%u", cnt); +- while (cnt != 0) { ++ while (cnt != 0) ++ { + if ((const u_char *)(rr + 1) > ep) + goto trunc; + ND_TCHECK_SIZE(rr); +@@ -284,9 +306,9 @@ + ts = (double)(GET_BE_U_4(rr->rr_lsr)) / 65536.; + dts = (double)(GET_BE_U_4(rr->rr_dlsr)) / 65536.; + ND_PRINT(" %ul %us %uj @%.2f+%.2f", +- GET_BE_U_4(rr->rr_nl) & 0x00ffffff, +- GET_BE_U_4(rr->rr_ls), +- GET_BE_U_4(rr->rr_dv), ts, dts); ++ GET_BE_U_4(rr->rr_nl) & 0x00ffffff, ++ GET_BE_U_4(rr->rr_ls), ++ GET_BE_U_4(rr->rr_dv), ts, dts); + cnt--; + } + return (hdr + len); +@@ -296,94 +318,112 @@ + return ep; + } + +-static uint16_t udp_cksum(netdissect_options *ndo, const struct ip *ip, +- const struct udphdr *up, +- u_int len) ++// cppcheck-suppress ++static uint16_t udp_cksum(netdissect_options *ndo, const struct tcpdump_ip *ip, ++ const struct udphdr *up, ++ u_int len) + { + return nextproto4_cksum(ndo, ip, (const uint8_t *)(const void *)up, len, len, +- IPPROTO_UDP); ++ IPPROTO_UDP); + } +- +-static uint16_t udp6_cksum(netdissect_options *ndo, const struct ip6_hdr *ip6, +- const struct udphdr *up, u_int len) ++// cppcheck-suppress ++static uint16_t udp6_cksum(netdissect_options *ndo, const struct tcpdump_ip6_hdr *ip6, ++ const struct udphdr *up, u_int len) + { + return nextproto6_cksum(ndo, ip6, (const uint8_t *)(const void *)up, len, len, +- IPPROTO_UDP); ++ IPPROTO_UDP); + } + +-static void +-udpipaddr_print(netdissect_options *ndo, const struct ip *ip, int sport, int dport) ++// cppcheck-suppress ++static void udpipaddr_print(netdissect_options *ndo, const struct tcpdump_ip *ip, int sport, int dport) + { +- const struct ip6_hdr *ip6; ++ const struct tcpdump_ip6_hdr *ip6; + + if (IP_V(ip) == 6) +- ip6 = (const struct ip6_hdr *)ip; ++ ip6 = (const struct tcpdump_ip6_hdr *)ip; + else + ip6 = NULL; + +- if (ip6) { +- if (GET_U_1(ip6->ip6_nxt) == IPPROTO_UDP) { +- if (sport == -1) { ++ if (ip6) ++ { ++ if (GET_U_1(ip6->ip6_nxt) == IPPROTO_UDP) ++ { ++ if (sport == -1) ++ { + ND_PRINT("%s > %s: ", +- GET_IP6ADDR_STRING(ip6->ip6_src), +- GET_IP6ADDR_STRING(ip6->ip6_dst)); +- } else { ++ GET_IP6ADDR_STRING(ip6->ip6_src), ++ GET_IP6ADDR_STRING(ip6->ip6_dst)); ++ } ++ else ++ { + ND_PRINT("%s.%s > %s.%s: ", +- GET_IP6ADDR_STRING(ip6->ip6_src), +- udpport_string(ndo, (uint16_t)sport), +- GET_IP6ADDR_STRING(ip6->ip6_dst), +- udpport_string(ndo, (uint16_t)dport)); ++ GET_IP6ADDR_STRING(ip6->ip6_src), ++ udpport_string(ndo, (uint16_t)sport), ++ GET_IP6ADDR_STRING(ip6->ip6_dst), ++ udpport_string(ndo, (uint16_t)dport)); + } +- } else { +- if (sport != -1) { ++ } ++ else ++ { ++ if (sport != -1) ++ { + ND_PRINT("%s > %s: ", +- udpport_string(ndo, (uint16_t)sport), +- udpport_string(ndo, (uint16_t)dport)); ++ udpport_string(ndo, (uint16_t)sport), ++ udpport_string(ndo, (uint16_t)dport)); + } + } +- } else { +- if (GET_U_1(ip->ip_p) == IPPROTO_UDP) { +- if (sport == -1) { ++ } ++ else ++ { ++ if (GET_U_1(ip->ip_p) == IPPROTO_UDP) ++ { ++ if (sport == -1) ++ { + ND_PRINT("%s > %s: ", +- GET_IPADDR_STRING(ip->ip_src), +- GET_IPADDR_STRING(ip->ip_dst)); +- } else { ++ GET_IPADDR_STRING(ip->ip_src), ++ GET_IPADDR_STRING(ip->ip_dst)); ++ } ++ else ++ { + ND_PRINT("%s.%s > %s.%s: ", +- GET_IPADDR_STRING(ip->ip_src), +- udpport_string(ndo, (uint16_t)sport), +- GET_IPADDR_STRING(ip->ip_dst), +- udpport_string(ndo, (uint16_t)dport)); ++ GET_IPADDR_STRING(ip->ip_src), ++ udpport_string(ndo, (uint16_t)sport), ++ GET_IPADDR_STRING(ip->ip_dst), ++ udpport_string(ndo, (uint16_t)dport)); + } +- } else { +- if (sport != -1) { ++ } ++ else ++ { ++ if (sport != -1) ++ { + ND_PRINT("%s > %s: ", +- udpport_string(ndo, (uint16_t)sport), +- udpport_string(ndo, (uint16_t)dport)); ++ udpport_string(ndo, (uint16_t)sport), ++ udpport_string(ndo, (uint16_t)dport)); + } + } + } + } + +-void +-udp_print(netdissect_options *ndo, const u_char *bp, u_int length, +- const u_char *bp2, int fragmented, u_int ttl_hl) ++// cppcheck-suppress ++void udp_print(netdissect_options *ndo, const u_char *bp, u_int length, const u_char *bp2, int fragmented, u_int ttl_hl) + { + const struct udphdr *up; +- const struct ip *ip; ++ const struct tcpdump_ip *ip; + const u_char *cp; + const u_char *ep = ndo->ndo_snapend; + uint16_t sport, dport; + u_int ulen; +- const struct ip6_hdr *ip6; ++ const struct tcpdump_ip6_hdr *ip6; + + ndo->ndo_protocol = "udp"; + up = (const struct udphdr *)bp; +- ip = (const struct ip *)bp2; ++ ip = (const struct tcpdump_ip *)bp2; + if (IP_V(ip) == 6) +- ip6 = (const struct ip6_hdr *)bp2; ++ ip6 = (const struct tcpdump_ip6_hdr *)bp2; + else + ip6 = NULL; +- if (!ND_TTEST_2(up->uh_dport)) { ++ if (!ND_TTEST_2(up->uh_dport)) ++ { + udpipaddr_print(ndo, ip, -1, -1); + goto trunc; + } +@@ -391,12 +431,14 @@ + sport = GET_BE_U_2(up->uh_sport); + dport = GET_BE_U_2(up->uh_dport); + +- if (length < sizeof(struct udphdr)) { ++ if (length < sizeof(struct udphdr)) ++ { + udpipaddr_print(ndo, ip, sport, dport); + ND_PRINT("truncated-udp %u", length); + return; + } +- if (!ND_TTEST_2(up->uh_ulen)) { ++ if (!ND_TTEST_2(up->uh_ulen)) ++ { + udpipaddr_print(ndo, ip, sport, dport); + goto trunc; + } +@@ -408,7 +450,8 @@ + */ + if (ulen == 0 && length > 65535) + ulen = length; +- if (ulen < sizeof(struct udphdr)) { ++ if (ulen < sizeof(struct udphdr)) ++ { + udpipaddr_print(ndo, ip, sport, dport); + ND_PRINT("truncated-udplength %u", ulen); + return; +@@ -419,16 +462,19 @@ + length = ulen; + + cp = (const u_char *)(up + 1); +- if (cp > ndo->ndo_snapend) { ++ if (cp > ndo->ndo_snapend) ++ { + udpipaddr_print(ndo, ip, sport, dport); + goto trunc; + } + +- if (ndo->ndo_packettype) { ++ if (ndo->ndo_packettype) ++ { + const struct sunrpc_msg *rp; + enum sunrpc_msg_type direction; + +- switch (ndo->ndo_packettype) { ++ switch (ndo->ndo_packettype) ++ { + + case PT_VAT: + udpipaddr_print(ndo, ip, sport, dport); +@@ -442,13 +488,13 @@ + + case PT_RPC: + rp = (const struct sunrpc_msg *)cp; +- direction = (enum sunrpc_msg_type) GET_BE_U_4(rp->rm_direction); ++ direction = (enum sunrpc_msg_type)GET_BE_U_4(rp->rm_direction); + if (direction == SUNRPC_CALL) + sunrpc_print(ndo, (const u_char *)rp, length, +- (const u_char *)ip); ++ (const u_char *)ip); + else + nfsreply_print(ndo, (const u_char *)rp, length, +- (const u_char *)ip); /*XXX*/ ++ (const u_char *)ip); /*XXX*/ + break; + + case PT_RTP: +@@ -480,7 +526,7 @@ + case PT_AODV: + udpipaddr_print(ndo, ip, sport, dport); + aodv_print(ndo, cp, length, +- ip6 != NULL); ++ ip6 != NULL); + break; + + case PT_RADIUS: +@@ -520,29 +566,34 @@ + } + + udpipaddr_print(ndo, ip, sport, dport); +- if (!ndo->ndo_qflag) { ++ if (!ndo->ndo_qflag) ++ { + const struct sunrpc_msg *rp; + enum sunrpc_msg_type direction; + + rp = (const struct sunrpc_msg *)cp; +- if (ND_TTEST_4(rp->rm_direction)) { +- direction = (enum sunrpc_msg_type) GET_BE_U_4(rp->rm_direction); +- if (dport == NFS_PORT && direction == SUNRPC_CALL) { ++ if (ND_TTEST_4(rp->rm_direction)) ++ { ++ direction = (enum sunrpc_msg_type)GET_BE_U_4(rp->rm_direction); ++ if (dport == NFS_PORT && direction == SUNRPC_CALL) ++ { + ND_PRINT("NFS request xid %u ", +- GET_BE_U_4(rp->rm_xid)); ++ GET_BE_U_4(rp->rm_xid)); + nfsreq_noaddr_print(ndo, (const u_char *)rp, length, +- (const u_char *)ip); ++ (const u_char *)ip); + return; + } +- if (sport == NFS_PORT && direction == SUNRPC_REPLY) { ++ if (sport == NFS_PORT && direction == SUNRPC_REPLY) ++ { + ND_PRINT("NFS reply xid %u ", +- GET_BE_U_4(rp->rm_xid)); ++ GET_BE_U_4(rp->rm_xid)); + nfsreply_noaddr_print(ndo, (const u_char *)rp, length, +- (const u_char *)ip); ++ (const u_char *)ip); + return; + } + #ifdef notdef +- if (dport == SUNRPC_PORT && direction == SUNRPC_CALL) { ++ if (dport == 111 /*TCPDUMP_SUNRPC_PORT*/ && direction == SUNRPC_CALL) ++ { + sunrpc_print((const u_char *)rp, length, (const u_char *)ip); + return; + } +@@ -550,7 +601,8 @@ + } + } + +- if (ndo->ndo_vflag && !ndo->ndo_Kflag && !fragmented) { ++ if (ndo->ndo_vflag && !ndo->ndo_Kflag && !fragmented) ++ { + /* Check the checksum, if possible. */ + uint16_t sum, udp_sum; + +@@ -558,181 +610,353 @@ + * XXX - do this even if vflag == 1? + * TCP does, and we do so for UDP-over-IPv6. + */ +- if (IP_V(ip) == 4 && (ndo->ndo_vflag > 1)) { ++ if (IP_V(ip) == 4 && (ndo->ndo_vflag > 1)) ++ { + udp_sum = GET_BE_U_2(up->uh_sum); +- if (udp_sum == 0) { ++ if (udp_sum == 0) ++ { + ND_PRINT("[no cksum] "); +- } else if (ND_TTEST_LEN(cp, length)) { ++ } ++ else if (ND_TTEST_LEN(cp, length)) ++ { + sum = udp_cksum(ndo, ip, up, length + sizeof(struct udphdr)); + +- if (sum != 0) { ++ if (sum != 0) ++ { + ND_PRINT("[bad udp cksum 0x%04x -> 0x%04x!] ", +- udp_sum, +- in_cksum_shouldbe(udp_sum, sum)); +- } else ++ udp_sum, ++ in_cksum_shouldbe(udp_sum, sum)); ++ } ++ else + ND_PRINT("[udp sum ok] "); + } + } +- else if (IP_V(ip) == 6) { ++ else if (IP_V(ip) == 6) ++ { + /* for IPv6, UDP checksum is mandatory */ +- if (ND_TTEST_LEN(cp, length)) { ++ if (ND_TTEST_LEN(cp, length)) ++ { + sum = udp6_cksum(ndo, ip6, up, length + sizeof(struct udphdr)); + udp_sum = GET_BE_U_2(up->uh_sum); + +- if (sum != 0) { ++ if (sum != 0) ++ { + ND_PRINT("[bad udp cksum 0x%04x -> 0x%04x!] ", +- udp_sum, +- in_cksum_shouldbe(udp_sum, sum)); +- } else ++ udp_sum, ++ in_cksum_shouldbe(udp_sum, sum)); ++ } ++ else + ND_PRINT("[udp sum ok] "); + } + } + } + +- if (!ndo->ndo_qflag) { +- if (IS_SRC_OR_DST_PORT(NAMESERVER_PORT)) ++ if (!ndo->ndo_qflag) ++ { ++ if (CHECK_IS_SRC_OR_DST_PORT(53 /*TCPDUMP_NAMESERVER_PORT*/, sport, dport)) ++ { + /* over_tcp: FALSE, is_mdns: FALSE */ + domain_print(ndo, cp, length, FALSE, FALSE); +- else if (IS_SRC_OR_DST_PORT(MULTICASTDNS_PORT)) ++ return; ++ } ++ ++ if (CHECK_IS_SRC_OR_DST_PORT(5353 /*TCPDUMP_MULTICASTDNS_PORT*/, sport, dport)) ++ { + /* over_tcp: FALSE, is_mdns: TRUE */ + domain_print(ndo, cp, length, FALSE, TRUE); +- else if (IS_SRC_OR_DST_PORT(TIMED_PORT)) ++ return; ++ } ++ ++ if (CHECK_IS_SRC_OR_DST_PORT(525 /*TCPDUMP_TIMED_PORT*/, sport, dport)) ++ { + timed_print(ndo, (const u_char *)cp); +- else if (IS_SRC_OR_DST_PORT(TFTP_PORT)) ++ return; ++ } ++ if (CHECK_IS_SRC_OR_DST_PORT(69 /*TCPDUMP_TFTP_PORT*/, sport, dport)) ++ { + tftp_print(ndo, cp, length); +- else if (IS_SRC_OR_DST_PORT(BOOTPC_PORT) || IS_SRC_OR_DST_PORT(BOOTPS_PORT)) ++ return; ++ } ++ if (CHECK_IS_SRC_OR_DST_PORT(68 /*TCPDUMP_BOOTPC_PORT*/, sport, dport) || CHECK_IS_SRC_OR_DST_PORT(67 /*TCPDUMP_BOOTPS_PORT*/, sport, dport)) ++ { + bootp_print(ndo, cp, length); +- else if (IS_SRC_OR_DST_PORT(RIP_PORT)) ++ return; ++ } ++ if (CHECK_IS_SRC_OR_DST_PORT(520 /*TCPDUMP_RIP_PORT*/, sport, dport)) ++ { + rip_print(ndo, cp, length); +- else if (IS_SRC_OR_DST_PORT(AODV_PORT)) +- aodv_print(ndo, cp, length, +- ip6 != NULL); +- else if (IS_SRC_OR_DST_PORT(ISAKMP_PORT)) +- isakmp_print(ndo, cp, length, bp2); +- else if (IS_SRC_OR_DST_PORT(ISAKMP_PORT_NATT)) +- isakmp_rfc3948_print(ndo, cp, length, bp2, IP_V(ip), fragmented, ttl_hl); +- else if (IS_SRC_OR_DST_PORT(ISAKMP_PORT_USER1) || IS_SRC_OR_DST_PORT(ISAKMP_PORT_USER2)) ++ return; ++ } ++ if (CHECK_IS_SRC_OR_DST_PORT(654 /*AODV_PORT*/, sport, dport)) ++ { ++ aodv_print(ndo, cp, length, ip6 != NULL); ++ return; ++ } ++ ++ if (CHECK_IS_SRC_OR_DST_PORT(500 /*TCPDUMP_ISAKMP_PORT*/, sport, dport)) ++ { ++ isakmp_print(ndo, cp, length, bp2); ++ return; ++ } ++ if (CHECK_IS_SRC_OR_DST_PORT(4500 /*TCPDUMP_ISAKMP_PORT_NATT*/, sport, dport)) ++ { ++ isakmp_rfc3948_print(ndo, cp, length, bp2, IP_V(ip), fragmented, ttl_hl); ++ return; ++ } ++ if (CHECK_IS_SRC_OR_DST_PORT(7500 /*TCPDUMP_ISAKMP_PORT_USER1*/, sport, dport) || CHECK_IS_SRC_OR_DST_PORT(8500 /*TCPDUMP_ISAKMP_PORT_USER2*/, sport, dport)) ++ { + isakmp_print(ndo, cp, length, bp2); +- else if (IS_SRC_OR_DST_PORT(SNMP_PORT) || IS_SRC_OR_DST_PORT(SNMPTRAP_PORT)) ++ return; ++ } ++ if (CHECK_IS_SRC_OR_DST_PORT(161 /*TCPDUMP_SNMP_PORT*/, sport, dport) || CHECK_IS_SRC_OR_DST_PORT(162 /*TCPDUMP_SNMPTRAP_PORT*/, sport, dport)) ++ { + snmp_print(ndo, cp, length); +- else if (IS_SRC_OR_DST_PORT(NTP_PORT)) ++ return; ++ } ++ if (CHECK_IS_SRC_OR_DST_PORT(123 /*TCPDUMP_NTP_PORT*/, sport, dport)) ++ { + ntp_print(ndo, cp, length); +- else if (IS_SRC_OR_DST_PORT(KERBEROS_PORT) || IS_SRC_OR_DST_PORT(KERBEROS_SEC_PORT)) ++ return; ++ } ++ if (IS_SRC_OR_DST_UDPPORT(88 /*TCPDUMP_KERBEROS_PORT*/) || CHECK_IS_SRC_OR_DST_PORT(750 /*TCPDUMP_KERBEROS_SEC_PORT*/, sport, dport)) ++ { + krb_print(ndo, (const u_char *)cp); +- else if (IS_SRC_OR_DST_PORT(L2TP_PORT)) ++ return; ++ } ++ if (IS_SRC_OR_DST_UDPPORT(1701 /*TCPDUMP_L2TP_PORT*/)) ++ { + l2tp_print(ndo, cp, length); ++ return; ++ } + #ifdef ENABLE_SMB +- else if (IS_SRC_OR_DST_PORT(NETBIOS_NS_PORT)) ++ if (IS_SRC_OR_DST_UDPPORT(137 /*TCPDUMP_NETBIOS_NS_PORT*/)) ++ { + nbt_udp137_print(ndo, cp, length); +- else if (IS_SRC_OR_DST_PORT(NETBIOS_DGRAM_PORT)) ++ return; ++ } ++ if (IS_SRC_OR_DST_UDPPORT(138 /*TCPDUMP_NETBIOS_DGRAM_PORT*/)) ++ { + nbt_udp138_print(ndo, cp, length); ++ return; ++ } + #endif +- else if (dport == VAT_PORT) ++ ++ if (dport == 3456 /*TCPDUMP_VAT_PORT*/) ++ { + vat_print(ndo, cp, length); +- else if (IS_SRC_OR_DST_PORT(ZEPHYR_SRV_PORT) || IS_SRC_OR_DST_PORT(ZEPHYR_CLT_PORT)) ++ return; ++ } ++ if (IS_SRC_OR_DST_UDPPORT(2103 /*TCPDUMP_ZEPHYR_SRV_PORT*/) || IS_SRC_OR_DST_UDPPORT(2104 /*ZEPHYR_CLT_PORT*/)) ++ { + zephyr_print(ndo, cp, length); ++ return; ++ } + /* + * Since there are 10 possible ports to check, I think + * a <> test would be more efficient + */ +- else if ((sport >= RX_PORT_LOW && sport <= RX_PORT_HIGH) || +- (dport >= RX_PORT_LOW && dport <= RX_PORT_HIGH)) +- rx_print(ndo, cp, length, sport, dport, +- (const u_char *) ip); +- else if (IS_SRC_OR_DST_PORT(RIPNG_PORT)) ++ if ((sport >= 7000 /*TCPDUMP_RX_PORT_LOW*/ && sport <= 7009 /*TCPDUMP_RX_PORT_HIGH*/) || ++ (dport >= 7000 /*TCPDUMP_RX_PORT_LOW*/ && dport <= 7009 /*TCPDUMP_RX_PORT_HIGH*/)) ++ { ++ rx_print(ndo, cp, length, sport, dport, (const u_char *)ip); ++ return; ++ } ++ if (IS_SRC_OR_DST_UDPPORT(521 /*TCPDUMP_RIPNG_PORT*/)) ++ { + ripng_print(ndo, cp, length); +- else if (IS_SRC_OR_DST_PORT(DHCP6_SERV_PORT) || IS_SRC_OR_DST_PORT(DHCP6_CLI_PORT)) ++ return; ++ } ++ ++ if (IS_SRC_OR_DST_UDPPORT(546 /*TCPDUMP_DHCP6_SERV_PORT*/) || IS_SRC_OR_DST_UDPPORT(547 /*TCPDUMP_DHCP6_CLI_PORT*/)) ++ { + dhcp6_print(ndo, cp, length); +- else if (IS_SRC_OR_DST_PORT(AHCP_PORT)) ++ return; ++ } ++ if (IS_SRC_OR_DST_UDPPORT(5359 /*TCPDUMP_AHCP_PORT*/)) ++ { + ahcp_print(ndo, cp, length); +- else if (IS_SRC_OR_DST_PORT(BABEL_PORT) || IS_SRC_OR_DST_PORT(BABEL_PORT_OLD)) ++ return; ++ } ++ if (IS_SRC_OR_DST_UDPPORT(6696 /*TCPDUMP_BABEL_PORT*/) || IS_SRC_OR_DST_UDPPORT(6697 /*TCPDUMP_BABEL_PORT_OLD*/)) ++ { + babel_print(ndo, cp, length); +- else if (IS_SRC_OR_DST_PORT(HNCP_PORT)) ++ return; ++ } ++ if (IS_SRC_OR_DST_UDPPORT(8231 /*TCPDUMP_HNCP_PORT*/)) ++ { + hncp_print(ndo, cp, length); ++ return; ++ } + /* + * Kludge in test for whiteboard packets. + */ +- else if (dport == WB_PORT) ++ if (dport == 4567 /*TCPDUMP_WB_PORT*/) ++ { + wb_print(ndo, cp, length); +- else if (IS_SRC_OR_DST_PORT(CISCO_AUTORP_PORT)) ++ return; ++ } ++ if (IS_SRC_OR_DST_UDPPORT(496 /*TCPDUMP_CISCO_AUTORP_PORT*/)) ++ { + cisco_autorp_print(ndo, cp, length); +- else if (IS_SRC_OR_DST_PORT(RADIUS_PORT) || +- IS_SRC_OR_DST_PORT(RADIUS_NEW_PORT) || +- IS_SRC_OR_DST_PORT(RADIUS_ACCOUNTING_PORT) || +- IS_SRC_OR_DST_PORT(RADIUS_NEW_ACCOUNTING_PORT) || +- IS_SRC_OR_DST_PORT(RADIUS_CISCO_COA_PORT) || +- IS_SRC_OR_DST_PORT(RADIUS_COA_PORT) ) ++ return; ++ } ++ if (IS_SRC_OR_DST_UDPPORT(1645 /*TCPDUMP_RADIUS_PORT*/) || ++ IS_SRC_OR_DST_UDPPORT(1812 /*TCPDUMP_RADIUS_NEW_PORT*/) || ++ IS_SRC_OR_DST_UDPPORT(1646 /*TCPDUMP_RADIUS_ACCOUNTING_PORT*/) || ++ IS_SRC_OR_DST_UDPPORT(1813 /*TCPDUMP_RADIUS_NEW_ACCOUNTING_PORT*/) || ++ IS_SRC_OR_DST_UDPPORT(1700 /*TCPDUMP_RADIUS_CISCO_COA_PORT*/) || ++ IS_SRC_OR_DST_UDPPORT(3799 /*TCPDUMP_RADIUS_COA_PORT*/)) ++ { + radius_print(ndo, cp, length); +- else if (dport == HSRP_PORT) ++ return; ++ } ++ if (dport == 1985 /*TCPDUMP_HSRP_PORT*/) ++ { + hsrp_print(ndo, cp, length); +- else if (IS_SRC_OR_DST_PORT(LWRES_PORT)) ++ return; ++ } ++ if (IS_SRC_OR_DST_UDPPORT(921 /*TCPDUMP_LWRES_PORT*/)) ++ { + lwres_print(ndo, cp, length); +- else if (IS_SRC_OR_DST_PORT(LDP_PORT)) ++ return; ++ } ++ if (IS_SRC_OR_DST_UDPPORT(646 /*TCPDUMP_LDP_PORT*/)) ++ { + ldp_print(ndo, cp, length); +- else if (IS_SRC_OR_DST_PORT(OLSR_PORT)) +- olsr_print(ndo, cp, length, +- (IP_V(ip) == 6) ? 1 : 0); +- else if (IS_SRC_OR_DST_PORT(MPLS_LSP_PING_PORT)) ++ return; ++ } ++ if (IS_SRC_OR_DST_UDPPORT(698 /*TCPDUMP_OLSR_PORT*/)) ++ { ++ olsr_print(ndo, cp, length, (IP_V(ip) == 6) ? 1 : 0); ++ return; ++ } ++ if (IS_SRC_OR_DST_UDPPORT(3503 /*TCPDUMP_MPLS_LSP_PING_PORT*/)) ++ { + lspping_print(ndo, cp, length); +- else if (sport == BCM_LI_PORT) ++ return; ++ } ++ if (sport == 49152 /*TCPDUMP_BCM_LI_PORT*/) ++ { + bcm_li_print(ndo, cp, length); +- else if (dport == BFD_CONTROL_PORT || +- dport == BFD_MULTIHOP_PORT || +- dport == BFD_LAG_PORT || +- dport == BFD_ECHO_PORT ) ++ return; ++ } ++ ++ if (dport == 3784 /*TCPDUMP_BFD_CONTROL_PORT*/ || ++ dport == 4784 /*TCPDUMP_BFD_MULTIHOP_PORT*/ || ++ dport == 6784 /*TCPDUMP_BFD_LAG_PORT*/ || ++ dport == 3785 /*TCPDUMP_BFD_ECHO_PORT*/) ++ { + bfd_print(ndo, cp, length, dport); +- else if (IS_SRC_OR_DST_PORT(LMP_PORT)) ++ return; ++ } ++ if (IS_SRC_OR_DST_UDPPORT(701 /*TCPDUMP_LMP_PORT*/)) ++ { + lmp_print(ndo, cp, length); +- else if (IS_SRC_OR_DST_PORT(VQP_PORT)) ++ return; ++ } ++ if (IS_SRC_OR_DST_UDPPORT(1589 /*TCPDUMP_VQP_PORT*/)) ++ { + vqp_print(ndo, cp, length); +- else if (IS_SRC_OR_DST_PORT(SFLOW_PORT)) ++ return; ++ } ++ if (IS_SRC_OR_DST_UDPPORT(6343 /*TCPDUMP_SFLOW_PORT*/)) ++ { + sflow_print(ndo, cp, length); +- else if (dport == LWAPP_CONTROL_PORT) ++ return; ++ } ++ if (dport == 12223 /*TCPDUMP_LWAPP_CONTROL_PORT*/) ++ { + lwapp_control_print(ndo, cp, length, 1); +- else if (sport == LWAPP_CONTROL_PORT) ++ return; ++ } ++ if (sport == 12223 /*TCPDUMP_LWAPP_CONTROL_PORT*/) ++ { + lwapp_control_print(ndo, cp, length, 0); +- else if (IS_SRC_OR_DST_PORT(LWAPP_DATA_PORT)) ++ return; ++ } ++ if (IS_SRC_OR_DST_UDPPORT(12222 /*TCPDUMP_LWAPP_DATA_PORT*/)) ++ { + lwapp_data_print(ndo, cp, length); +- else if (IS_SRC_OR_DST_PORT(SIP_PORT)) ++ return; ++ } ++ if (IS_SRC_OR_DST_UDPPORT(5060 /*TCPDUMP_SIP_PORT*/)) ++ { + sip_print(ndo, cp, length); +- else if (IS_SRC_OR_DST_PORT(SYSLOG_PORT)) ++ return; ++ } ++ if (IS_SRC_OR_DST_UDPPORT(514 /*TCPDUMP_SYSLOG_PORT*/)) ++ { + syslog_print(ndo, cp, length); +- else if (IS_SRC_OR_DST_PORT(OTV_PORT)) ++ return; ++ } ++ if (IS_SRC_OR_DST_UDPPORT(8472 /*TCPDUMP_OTV_PORT*/)) ++ { + otv_print(ndo, cp, length); +- else if (IS_SRC_OR_DST_PORT(VXLAN_PORT)) ++ return; ++ } ++ if (IS_SRC_OR_DST_UDPPORT(4789 /*TCPDUMP_VXLAN_PORT*/)) ++ { + vxlan_print(ndo, cp, length); +- else if (dport == GENEVE_PORT) ++ return; ++ } ++ if (dport == 6081 /*TCPDUMP_GENEVE_PORT*/) ++ { + geneve_print(ndo, cp, length); +- else if (IS_SRC_OR_DST_PORT(LISP_CONTROL_PORT)) ++ return; ++ } ++ if (IS_SRC_OR_DST_UDPPORT(4342 /*TCPDUMP_LISP_CONTROL_PORT*/)) ++ { + lisp_print(ndo, cp, length); +- else if (IS_SRC_OR_DST_PORT(VXLAN_GPE_PORT)) ++ return; ++ } ++ if (IS_SRC_OR_DST_UDPPORT(4790 /*TCPDUMP_VXLAN_GPE_PORT*/)) ++ { + vxlan_gpe_print(ndo, cp, length); +- else if (IS_SRC_OR_DST_PORT(ZEP_PORT)) ++ return; ++ } ++ if (IS_SRC_OR_DST_UDPPORT(17754 /*TCPDUMP_ZEP_PORT*/)) ++ { + zep_print(ndo, cp, length); +- else if (IS_SRC_OR_DST_PORT(MPLS_PORT)) ++ return; ++ } ++ if (IS_SRC_OR_DST_UDPPORT(6635 /*TCPDUMP_MPLS_PORT*/)) ++ { + mpls_print(ndo, cp, length); +- else if (ND_TTEST_1(((const struct LAP *)cp)->type) && +- GET_U_1(((const struct LAP *)cp)->type) == lapDDP && +- (atalk_port(sport) || atalk_port(dport))) { ++ return; ++ } ++ if (ND_TTEST_1(((const struct LAP *)cp)->type) && ++ GET_U_1(((const struct LAP *)cp)->type) == lapDDP && ++ (atalk_port(sport) || atalk_port(dport))) ++ { + if (ndo->ndo_vflag) + ND_PRINT("kip "); + llap_print(ndo, cp, length); +- } else if (IS_SRC_OR_DST_PORT(PTP_EVENT_PORT) || +- IS_SRC_OR_DST_PORT(PTP_GENERAL_PORT)) { ++ return; ++ } ++ if (IS_SRC_OR_DST_UDPPORT(319 /*TCPDUMP_PTP_EVENT_PORT*/) || ++ IS_SRC_OR_DST_UDPPORT(320 /*TCPDUMP_PTP_GENERAL_PORT*/)) ++ ++ { + ptp_print(ndo, cp, length); +- } else if (IS_SRC_OR_DST_PORT(SOMEIP_PORT)) ++ return; ++ } ++ if (IS_SRC_OR_DST_UDPPORT(30490 /*TCPDUMP_SOMEIP_PORT*/)) + someip_print(ndo, cp, length); +- else { ++ else ++ { + if (ulen > length && !fragmented) + ND_PRINT("UDP, bad length %u > %u", +- ulen, length); ++ ulen, length); + else + ND_PRINT("UDP, length %u", ulen); + } +- } else { ++ } ++ ++ else ++ { + if (ulen > length && !fragmented) + ND_PRINT("UDP, bad length %u > %u", +- ulen, length); ++ ulen, length); + else + ND_PRINT("UDP, length %u", ulen); + } +diff -uNr tcpdump-tcpdump-4.99.4/print-udp.h tcpdump-for-stellar/print-udp.h +--- tcpdump-tcpdump-4.99.4/print-udp.h 1970-01-01 08:00:00.000000000 +0800 ++++ tcpdump-for-stellar/print-udp.h 2024-10-30 17:34:06.265498697 +0800 +@@ -0,0 +1,184 @@ ++/* ++ * Copyright (c) 1982, 1986, 1993 ++ * The Regents of the University of California. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by the University of ++ * California, Berkeley and its contributors. ++ * 4. Neither the name of the University nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ * @(#)udp.h 8.1 (Berkeley) 6/10/93 ++ */ ++ ++#pragma once ++#include "netdissect.h" ++/* ++ * Udp protocol header. ++ * Per RFC 768, September, 1981. ++ */ ++struct udphdr ++{ ++ nd_uint16_t uh_sport; /* source port */ ++ nd_uint16_t uh_dport; /* destination port */ ++ nd_uint16_t uh_ulen; /* udp length */ ++ nd_uint16_t uh_sum; /* udp checksum */ ++}; ++ ++// #define TCPDUMP_NAMESERVER_PORT 53 ++ ++// #define TCPDUMP_BOOTPS_PORT 67 /* RFC951 */ ++ ++// #define TCPDUMP_BOOTPC_PORT 68 /* RFC951 */ ++ ++// #define TCPDUMP_TFTP_PORT 69 /*XXX*/ ++ ++// #define TCPDUMP_KERBEROS_PORT 88 /*XXX*/ ++ ++// #define TCPDUMP_SUNRPC_PORT 111 /*XXX*/ ++ ++// #define TCPDUMP_NTP_PORT 123 /*XXX*/ ++ ++// #define TCPDUMP_NETBIOS_NS_PORT 137 /* RFC 1001, RFC 1002 */ ++ ++// #define TCPDUMP_NETBIOS_DGRAM_PORT 138 /* RFC 1001, RFC 1002 */ ++ ++// #define TCPDUMP_SNMP_PORT 161 /*XXX*/ ++ ++// #define TCPDUMP_SNMPTRAP_PORT 162 /*XXX*/ ++ ++// #define TCPDUMP_PTP_EVENT_PORT 319 /* IANA */ ++ ++// #define TCPDUMP_PTP_GENERAL_PORT 320 /* IANA */ ++ ++// #define TCPDUMP_CISCO_AUTORP_PORT 496 /*XXX*/ ++ ++// #define TCPDUMP_ISAKMP_PORT 500 /*XXX*/ ++ ++// #define TCPDUMP_SYSLOG_PORT 514 /* rfc3164 */ ++ ++// #define TCPDUMP_RIP_PORT 520 /*XXX*/ ++ ++// #define TCPDUMP_RIPNG_PORT 521 /* RFC 2080 */ ++ ++// #define TCPDUMP_TIMED_PORT 525 /*XXX*/ ++ ++// #define TCPDUMP_DHCP6_SERV_PORT 546 /*XXX*/ ++ ++// #define TCPDUMP_DHCP6_CLI_PORT 547 /*XXX*/ ++ ++// #define TCPDUMP_LDP_PORT 646 ++ ++// #define TCPDUMP_AQDV_PORT 654 /*XXX*/ ++ ++// #define TCPDUMP_OLSR_PORT 698 /* rfc3626 */ ++ ++// #define TCPDUMP_LMP_PORT 701 /* rfc4204 */ ++ ++// #define TCPDUMP_KERBEROS_SEC_PORT 750 /*XXX - Kerberos v4 */ ++ ++// #define TCPDUMP_LWRES_PORT 921 /*XXX*/ ++ ++// #define TCPDUMP_VQP_PORT 1589 /*XXX*/ ++ ++// #define TCPDUMP_RADIUS_PORT 1645 /*XXX*/ ++ ++// #define TCPDUMP_RADIUS_ACCOUNTING_PORT 1646 ++ ++// #define TCPDUMP_RADIUS_CISCO_COA_PORT 1700 ++ ++// #define TCPDUMP_L2TP_PORT 1701 /*XXX*/ ++ ++// #define TCPDUMP_RADIUS_NEW_PORT 1812 /*XXX*/ ++ ++// #define TCPDUMP_RADIUS_NEW_ACCOUNTING_PORT 1813 ++ ++// #define TCPDUMP_HSRP_PORT 1985 /*XXX*/ ++ ++// #define TCPDUMP_ZEPHYR_SRV_PORT 2103 /*XXX*/ ++ ++// #define TCPDUMP_ZEPHYR_CLI_PORT 2104 /*XXX*/ ++ ++// #define TCPDUMP_VAT_PORT 3456 /*XXX*/ ++ ++// #define TCPDUMP_MPLS_LSP_PING_PORT 3503 /* draft-ietf-mpls-lsp-ping-02.txt */ ++ ++// #define TCPDUMP_BCM_LI_PORT 49152 /* SDK default */ ++ ++#define TCPDUMP_BFD_CONTROL_PORT 3784 /* RFC 5881 */ ++ ++#define TCPDUMP_BFD_ECHO_PORT 3785 /* RFC 5881 */ ++ ++// #define TCPDUMP_RADIUS_COA_PORT 3799 /* RFC 5176 */ ++ ++// #define TCPDUMP_LISP_CONTROL_PORT 4342 /* RFC 6830 */ ++ ++// #define TCPDUMP_ISAKMP_PORT_NATT 4500 /* rfc3948 */ ++ ++// #define TCPDUMP_WB_PORT 4567 ++ ++#define TCPDUMP_BFD_MULTIHOP_PORT 4784 /* RFC 5883 */ ++ ++// #define TCPDUMP_VXLAN_PORT 4789 /* RFC 7348 */ ++ ++// #define TCPDUMP_VXLAN_GPE_PORT 4790 /* draft-ietf-nvo3-vxlan-gpe-01 */ ++ ++// #define TCPDUMP_SIP_PORT 5060 ++ ++// #define TCPDUMP_MULTICASTDNS_PORT 5353 /* RFC 6762 */ ++ ++// #define TCPDUMP_AHCP_PORT 5359 /* draft-chroboczek-ahcp-00 */ ++ ++// #define TCPDUMP_GENEVE_PORT 6081 /* draft-gross-geneve-02 */ ++ ++// #define TCPDUMP_SFLOW_PORT 6343 /* https://sflow.org/developers/specifications.php */ ++ ++// #define TCPDUMP_MPLS_PORT 6635 /* RFC 7510 */ ++ ++// #define TCPDUMP_BABEL_PORT 6696 /* RFC 6126 errata */ ++ ++// #define TCPDUMP_BABEL_PORT_OLD 6697 /* RFC 6126 */ ++ ++#define TCPDUMP_BFD_LAG_PORT 6784 /* RFC 7310 */ ++ ++// #define TCPDUMP_RX_PORT_LOW 7000 /*XXX*/ ++ ++// #define TCPDUMP_RX_PORT_HIGH 7009 /*XXX*/ ++ ++// #define TCPDUMP_ISAKMP_PORT_USER1 7500 /*XXX - nonstandard*/ ++ ++// #define TCPDUMP_HNCP_PORT 8231 /* RFC 7788 */ ++ ++// #define TCPDUMP_OTV_PORT 8472 /* draft-hasmit-otv-04 */ ++ ++// #define TCPDUMP_ISAKMP_PORT_USER2 8500 /*XXX - nonstandard*/ ++ ++// #define TCPDUMP_LWAPP_DATA_PORT 12222 /* RFC 5412 */ ++ ++// #define TCPDUMP_LWAPP_CONTROL_PORT 12223 /* RFC 5412 */ ++ ++// #define TCPDUMP_ZEP_PORT 17754 /* XXX */ ++ ++// #define TCPDUMP_SOMEIP_PORT 30490 /* https://www.autosar.org/standards/foundation */ +diff -uNr tcpdump-tcpdump-4.99.4/print-vrrp.c tcpdump-for-stellar/print-vrrp.c +--- tcpdump-tcpdump-4.99.4/print-vrrp.c 2023-04-08 02:30:58.000000000 +0800 ++++ tcpdump-for-stellar/print-vrrp.c 2024-10-30 17:34:05.631498702 +0800 +@@ -35,7 +35,7 @@ + #include "extract.h" + #include "addrtoname.h" + +-#include "ip.h" ++#include "tcpdump_ip.h" + #include "ipproto.h" + /* + * RFC 2338 (VRRP v2): +@@ -151,10 +151,10 @@ + uint16_t cksum; + + if (ver == 4) +- cksum = nextproto4_cksum(ndo, (const struct ip *)bp2, bp, ++ cksum = nextproto4_cksum(ndo, (const struct tcpdump_ip *)bp2, bp, + len, len, IPPROTO_VRRP); + else +- cksum = nextproto6_cksum(ndo, (const struct ip6_hdr *)bp2, bp, ++ cksum = nextproto6_cksum(ndo, (const struct tcpdump_ip6_hdr *)bp2, bp, + len, len, IPPROTO_VRRP); + if (cksum) + ND_PRINT(", (bad vrrp cksum %x)", +diff -uNr tcpdump-tcpdump-4.99.4/stellar_dump_ctrl_link.c tcpdump-for-stellar/stellar_dump_ctrl_link.c +--- tcpdump-tcpdump-4.99.4/stellar_dump_ctrl_link.c 1970-01-01 08:00:00.000000000 +0800 ++++ tcpdump-for-stellar/stellar_dump_ctrl_link.c 2024-10-30 17:34:06.265498697 +0800 +@@ -0,0 +1,266 @@ ++#include "stellar_dump.h" ++#include <stdio.h> ++#include <stdlib.h> ++#include <string.h> ++#include <unistd.h> ++#include <pthread.h> ++#include <pcap/pcap.h> ++#include <sys/types.h> /* See NOTES */ ++#include <sys/socket.h> ++#include <netinet/in.h> ++#include <event2/event.h> ++#include <event2/listener.h> ++#include <event2/bufferevent.h> ++#include <event2/buffer.h> ++#include <event2/thread.h> ++#include <event2/http.h> ++ ++struct libevent_http_client ++{ ++ struct event_base *base; ++ struct evhttp_connection *conn; ++ struct evhttp_request *req; ++ uint32_t response_code; ++ char *response_cstr; ++}; ++ ++static struct libevent_http_client *g_ctrllink_http_client = NULL; ++static pthread_t keepalive_thread_id; ++static volatile int keepalive_running = 0; ++ ++static struct libevent_http_client *evhttp_client_new(const char *server_ip, unsigned short server_port_host) ++{ ++ struct libevent_http_client *evh_client = (struct libevent_http_client *)calloc(1, sizeof(struct libevent_http_client)); ++ evh_client->base = event_base_new(); ++ evh_client->conn = evhttp_connection_base_new(evh_client->base, NULL, server_ip, server_port_host); ++ evhttp_connection_set_timeout(evh_client->conn, CTRLLINK_CONNECT_TIMEOUT); ++ return evh_client; ++} ++ ++static void evhttp_response_cb(struct evhttp_request *req, void *arg) ++{ ++ struct libevent_http_client *evh_client = (struct libevent_http_client *)arg; ++ if (req == NULL) ++ { ++ return; ++ } ++ ++ struct evbuffer *input_buffer = evhttp_request_get_input_buffer(req); ++ size_t evbuf_len = evbuffer_get_length(input_buffer); ++ if (NULL == input_buffer || 0 == evbuf_len) ++ { ++ return; ++ } ++ evh_client->response_cstr = (char *)calloc(1, evbuf_len + 1); ++ evbuffer_remove(input_buffer, evh_client->response_cstr, evbuf_len); ++ evh_client->response_code = evhttp_request_get_response_code(req); ++ // terminate event_base_dispatch() ++ event_base_loopbreak(evh_client->base); ++} ++ ++static void evhttp_request_error_cb(enum evhttp_request_error errnum, void *arg) ++{ ++ (void)arg; ++ (void)errnum; ++ // fprintf(stderr, "ERR monitor connection error: %d\n", errnum); ++ exit(1); ++} ++ ++static void evhttp_conn_close_cb(struct evhttp_connection *conn, void *arg) ++{ ++ (void)conn; ++ event_base_loopexit((struct event_base *)arg, NULL); ++ static volatile int barrier = 0; ++ if (__sync_bool_compare_and_swap(&barrier, 0, 1)) ++ { ++ fprintf(stderr, "monitor connection closed.\n"); ++ exit(1); ++ } ++} ++ ++static int evhttp_client_request_new(struct libevent_http_client *evh_client) ++{ ++ evh_client->req = evhttp_request_new(evhttp_response_cb, evh_client); ++ evhttp_request_set_error_cb(evh_client->req, evhttp_request_error_cb); ++ evhttp_connection_set_closecb(evh_client->conn, evhttp_conn_close_cb, evh_client->base); ++ evh_client->response_cstr = NULL; ++ evh_client->response_code = 204; ++ return 0; ++} ++static void evhttp_client_add_header(struct libevent_http_client *evh_client, ++ const char *key, const char *value) ++{ ++ struct evkeyvalq *output_headers = evhttp_request_get_output_headers(evh_client->req); ++ evhttp_add_header(output_headers, key, value); ++} ++ ++static unsigned int evhttp_run_cmd(struct libevent_http_client *evh_client, const char *cmd_uri) ++{ ++ evhttp_client_request_new(evh_client); ++ evhttp_client_add_header(evh_client, "Connection", "keep-alive"); ++ evhttp_client_add_header(evh_client, "Content-Length", "0"); ++ evhttp_make_request(evh_client->conn, evh_client->req, EVHTTP_REQ_GET, cmd_uri); ++ ++ int ret = event_base_dispatch(evh_client->base); ++ if (ret < 0) ++ { ++ fprintf(stderr, "event_base_dispatch failed!\n"); ++ exit(1); ++ } ++ // here we receive the response from monitor server. ++ return evh_client->response_code; ++} ++ ++static void *stellar_dump_ctrllink_keepalive(void *arg) ++{ ++ (void)arg; ++ struct libevent_http_client *evh_client = g_ctrllink_http_client; ++ char keepalive_cmd[256] = {0}; ++ snprintf(keepalive_cmd, sizeof(keepalive_cmd), "%s%s", CTRLLINK_CMD_URI_PREFIX, "ping%20stellar-dump-keepalive"); ++ int cmd_ret; ++ while (keepalive_running) ++ { ++ cmd_ret = evhttp_run_cmd(evh_client, keepalive_cmd); ++ if (cmd_ret != 200) ++ { ++ fprintf(stderr, "ERR connection failed!\n"); ++ exit(1); ++ } ++ if (evh_client->response_cstr) ++ { ++ free(evh_client->response_cstr); ++ evh_client->response_cstr = NULL; ++ } ++ if (keepalive_running) ++ { ++ sleep(1); ++ } ++ } ++ return NULL; ++} ++ ++static char *http_url_encode(const char *originalText) ++{ ++ // allocate memory for the worst possible case (all characters need to be encoded) ++ char *encodedText = (char *)malloc(sizeof(char) * strlen(originalText) * 3 + 1); ++ const char *hex = "0123456789abcdef"; ++ int pos = 0; ++ for (size_t i = 0; i < strlen(originalText); i++) ++ { ++ if (('a' <= originalText[i] && originalText[i] <= 'z') || ('A' <= originalText[i] && originalText[i] <= 'Z') || ('0' <= originalText[i] && originalText[i] <= '9')) ++ { ++ encodedText[pos++] = originalText[i]; ++ } ++ else if (originalText[i] == ' ') ++ { ++ encodedText[pos++] = '%'; ++ encodedText[pos++] = hex[originalText[i] >> 4]; ++ encodedText[pos++] = hex[originalText[i] & 15]; ++ } ++ else ++ { ++ encodedText[pos++] = originalText[i]; ++ } ++ } ++ encodedText[pos] = '\0'; ++ return encodedText; ++} ++ ++int stellar_dump_ctrllink_init(const struct stellar_dump_args *st_dump_arg) ++{ ++ g_ctrllink_http_client = evhttp_client_new(st_dump_arg->stellar_server_ip, st_dump_arg->stellar_server_port_host_order); ++ char probe_cmd[256] = {}; ++ snprintf(probe_cmd, sizeof(probe_cmd), "%s%s", CTRLLINK_CMD_URI_PREFIX, "ping stellar-dump-start"); ++ char *encoded_url = http_url_encode(probe_cmd); ++ evhttp_run_cmd(g_ctrllink_http_client, encoded_url); ++ free(encoded_url); ++ if (g_ctrllink_http_client->response_code != 200) ++ { ++ fprintf(stderr, "Could not connect to stellar monitor server %s:%u\n", st_dump_arg->stellar_server_ip, st_dump_arg->stellar_server_port_host_order); ++ exit(1); ++ } ++ if (g_ctrllink_http_client->response_cstr) ++ { ++ free(g_ctrllink_http_client->response_cstr); ++ g_ctrllink_http_client->response_cstr = NULL; ++ } ++ return 0; ++} ++ ++void stellar_dump_ctrllink_free(void) ++{ ++ if (g_ctrllink_http_client) ++ { ++ evhttp_connection_free(g_ctrllink_http_client->conn); ++ event_base_loopbreak(g_ctrllink_http_client->base); ++ event_base_free(g_ctrllink_http_client->base); ++ if (g_ctrllink_http_client->response_cstr) ++ { ++ free(g_ctrllink_http_client->response_cstr); ++ g_ctrllink_http_client->response_cstr = NULL; ++ } ++ free(g_ctrllink_http_client); ++ g_ctrllink_http_client = NULL; ++ } ++} ++ ++int stellar_dump_start(const struct stellar_dump_args *st_dump_arg) ++{ ++ char dump_cmd[4096] = {}; ++ strcat(dump_cmd, CTRLLINK_CMD_URI_PREFIX); ++ strcat(dump_cmd, "tcpdump "); ++ ++ /* necessary arg */ ++ sprintf(dump_cmd, "%s%s%s%u ", CTRLLINK_CMD_URI_PREFIX, "tcpdump ", "datalinkport ", st_dump_arg->datalink_recv_port_host_order); ++ ++ /* optional args */ ++ if (st_dump_arg->greedy_seek) ++ { ++ strcat(dump_cmd, "greedy "); ++ } ++ if (st_dump_arg->thread_enable_expression) ++ { ++ strcat(dump_cmd, "threads "); ++ strcat(dump_cmd, st_dump_arg->thread_enable_expression); ++ strcat(dump_cmd, " "); ++ } ++ if (st_dump_arg->bpf) ++ { ++ strcat(dump_cmd, "bpf "); ++ strcat(dump_cmd, st_dump_arg->bpf); ++ strcat(dump_cmd, " "); ++ } ++ char *encoded_url = http_url_encode(dump_cmd); ++ evhttp_run_cmd(g_ctrllink_http_client, encoded_url); ++ free(encoded_url); ++ if (g_ctrllink_http_client->response_code != 200) ++ { ++ fprintf(stderr, "Starting packet dump from server %s:%u : %s\r\n", ++ st_dump_arg->stellar_server_ip, st_dump_arg->stellar_server_port_host_order, g_ctrllink_http_client->response_cstr); ++ exit(1); ++ } ++ if (g_ctrllink_http_client->response_cstr) ++ { ++ free(g_ctrllink_http_client->response_cstr); ++ g_ctrllink_http_client->response_cstr = NULL; ++ } ++ return 0; ++} ++ ++int stellar_dump_ctrllink_keepalive_start(const struct stellar_dump_args *st_dump_arg) ++{ ++ keepalive_running = 1; ++ pthread_create(&keepalive_thread_id, NULL, stellar_dump_ctrllink_keepalive, (void *)st_dump_arg); ++ return 0; ++} ++ ++void stellar_dump_ctrllink_keepalive_stop(void) ++{ ++ keepalive_running = 0; ++ if (keepalive_thread_id != 0) ++ { ++ pthread_cancel(keepalive_thread_id); ++ pthread_join(keepalive_thread_id, NULL); ++ keepalive_thread_id = 0; ++ } ++} +diff -uNr tcpdump-tcpdump-4.99.4/stellar_dump_data_link.c tcpdump-for-stellar/stellar_dump_data_link.c +--- tcpdump-tcpdump-4.99.4/stellar_dump_data_link.c 1970-01-01 08:00:00.000000000 +0800 ++++ tcpdump-for-stellar/stellar_dump_data_link.c 2024-10-30 17:34:06.265498697 +0800 +@@ -0,0 +1,69 @@ ++#include "stellar_dump.h" ++#include <stdio.h> ++#include <stdlib.h> ++#include <string.h> ++#include <unistd.h> ++#include <pcap/pcap.h> ++#include <sys/types.h> /* See NOTES */ ++#include <sys/socket.h> ++#include <netinet/in.h> ++#include <errno.h> ++static int sockfd; ++ ++int stellar_dump_datalink_init(struct stellar_dump_args *out_arg) ++{ ++ uint16_t port; ++ struct sockaddr_in datalink_addr = {}; ++ datalink_addr.sin_family = AF_INET; ++ datalink_addr.sin_addr.s_addr = htonl(INADDR_ANY); ++ ++ sockfd = socket(AF_INET, SOCK_DGRAM, 0); ++ if (sockfd < 0) ++ { ++ perror("socket"); ++ return -1; ++ } ++ // int opt = 1; ++ // if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int)) == -1) ++ // { ++ // perror("setsockopt SO_REUSEADDR"); ++ // return -1; ++ // } ++ ++ struct timeval tv = {}; ++ tv.tv_sec = 1; ++ tv.tv_usec = 0; ++ setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char *)&tv, sizeof(tv)); ++ ++ /* find an available port */ ++ for (port = 60000; port < 65535; port++) ++ { ++ datalink_addr.sin_port = htons(port); ++ if (bind(sockfd, (struct sockaddr *)&datalink_addr, sizeof(datalink_addr)) != -1) ++ { ++ break; ++ } ++ } ++ if (port >= 65535) ++ { ++ fprintf(stderr, "no available data link port found\n"); ++ return -1; ++ } ++ out_arg->datalink_recv_port_host_order = port; ++ return port; ++} ++ ++ssize_t stellar_dump_datalink_recv(void *buf, size_t len, char **raw_pkt_start_ptr, struct pcap_pkthdr *phdr) ++{ ++ ssize_t n; ++ n = recv(sockfd, buf, len, 0); ++ if (n < TZSP_HDR_LEN) ++ { ++ return -1; ++ } ++ gettimeofday(&phdr->ts, NULL); ++ phdr->caplen = n - TZSP_HDR_LEN; ++ phdr->len = n - TZSP_HDR_LEN; ++ *raw_pkt_start_ptr = (char *)buf + TZSP_HDR_LEN; ++ return n; ++} +\ No newline at end of file +diff -uNr tcpdump-tcpdump-4.99.4/stellar_dump.h tcpdump-for-stellar/stellar_dump.h +--- tcpdump-tcpdump-4.99.4/stellar_dump.h 1970-01-01 08:00:00.000000000 +0800 ++++ tcpdump-for-stellar/stellar_dump.h 2024-10-30 17:34:06.265498697 +0800 +@@ -0,0 +1,42 @@ ++#pragma once ++#ifndef __FAVOR_BSD ++#define __FAVOR_BSD 1 ++#endif ++#include <stdio.h> ++#include <stdint.h> ++#include <pcap/pcap.h> ++ ++#define STELLAR_DUMP (1) ++#define PROGRAM_NAME "stellar_dump" ++ ++#define CTRLLINK_DEFAULT_IP "127.0.0.1" ++#define CTRLLINK_DEFAULT_PORT 80 ++ ++#define TZSP_UDP_PORT 37008 /* default port of TZSP protocol: https://en.wikipedia.org/wiki/TZSP# */ ++#define TZSP_HDR_LEN 5 /* length of TZSP header */ ++ ++#define CTRLLINK_CONNECT_TIMEOUT 3 /* seconds */ ++ ++#define DATALINK_RECV_BUF_SIZE 4096 ++ ++#define CTRLLINK_CMD_URI_PREFIX "/v1/stellar_monitor?raw_cmd=" ++ ++struct stellar_dump_args ++{ ++ char *stellar_server_ip; ++ unsigned short stellar_server_port_host_order; ++ unsigned short datalink_recv_port_host_order; ++ int greedy_seek; ++ char *thread_enable_expression; ++ char *bpf; ++ int expect_packet_count; // arg -c ++}; ++ ++int stellar_dump_ctrllink_init(const struct stellar_dump_args *st_dump_arg); ++void stellar_dump_ctrllink_free(void); ++int stellar_dump_ctrllink_keepalive_start(const struct stellar_dump_args *st_dump_arg); ++void stellar_dump_ctrllink_keepalive_stop(void); ++ ++int stellar_dump_datalink_init(struct stellar_dump_args *out_arg); ++int stellar_dump_start(const struct stellar_dump_args *st_dump_arg); ++ssize_t stellar_dump_datalink_recv(void *buf, size_t len, char **raw_pkt_start_ptr, struct pcap_pkthdr *phdr); +\ No newline at end of file +diff -uNr tcpdump-tcpdump-4.99.4/tcpdump.c tcpdump-for-stellar/tcpdump.c +--- tcpdump-tcpdump-4.99.4/tcpdump.c 2023-04-08 02:30:58.000000000 +0800 ++++ tcpdump-for-stellar/tcpdump.c 2024-10-30 17:34:05.655498702 +0800 +@@ -1,4 +1,4 @@ +-/* ++/* PATCH FOR STELLAR-DUMP + * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000 + * The Regents of the University of California. All rights reserved. + * +@@ -33,6 +33,24 @@ + * combined efforts of Van, Steve McCanne and Craig Leres of LBL. + */ + ++#if defined(__clang__) ++#pragma clang diagnostic ignored "-Wunused-function" ++#pragma clang diagnostic ignored "-Wunused-parameter" ++#pragma clang diagnostic ignored "-Wunused-label" ++#pragma clang diagnostic ignored "-Wunused-macros" ++#pragma clang diagnostic ignored "-Wunused-variable" ++#pragma clang diagnostic ignored "-Wunused-parameter" ++#elif defined(__GNUC__) ++#pragma GCC diagnostic ignored "-Wunused-function" ++#pragma GCC diagnostic ignored "-Wunused-parameter" ++#pragma GCC diagnostic ignored "-Wunused-label" ++#pragma GCC diagnostic ignored "-Wunused-macros" ++#pragma GCC diagnostic ignored "-Wunused-variable" ++#pragma GCC diagnostic ignored "-Wunused-parameter" ++#endif ++ ++#include "stellar_dump.h" ++ + #ifdef HAVE_CONFIG_H + #include <config.h> + #endif +@@ -57,7 +75,7 @@ + */ + #ifndef lint + static const char copyright[] _U_ = +- "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\ ++ "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\ + The Regents of the University of California. All rights reserved.\n"; + #endif + +@@ -91,8 +109,8 @@ + #include <libcasper.h> + #include <casper/cap_dns.h> + #include <sys/nv.h> +-#endif /* HAVE_CASPER */ +-#endif /* HAVE_CAPSICUM */ ++#endif /* HAVE_CASPER */ ++#endif /* HAVE_CAPSICUM */ + #ifdef HAVE_PCAP_OPEN + /* + * We found pcap_open() in the capture library, so we'll be using +@@ -116,6 +134,7 @@ + #include <stdlib.h> + #include <string.h> + #include <limits.h> ++#include <ctype.h> + #ifdef _WIN32 + #include <windows.h> + #else +@@ -131,9 +150,9 @@ + * Use this in pathnames, but do *not* use it in URLs. + */ + #ifdef _WIN32 +-#define PATH_SEPARATOR '\\' ++#define PATH_SEPARATOR '\\' + #else +-#define PATH_SEPARATOR '/' ++#define PATH_SEPARATOR '/' + #endif + + /* capabilities convenience library */ +@@ -182,19 +201,19 @@ + #endif + + #if defined(HAVE_PCAP_CREATE) || defined(_WIN32) +-static int Bflag; /* buffer size */ ++static int Bflag; /* buffer size */ + #endif + #ifdef HAVE_PCAP_DUMP_FTELL64 +-static int64_t Cflag; /* rotate dump files after this many bytes */ ++static int64_t Cflag; /* rotate dump files after this many bytes */ + #else +-static long Cflag; /* rotate dump files after this many bytes */ ++static long Cflag; /* rotate dump files after this many bytes */ + #endif +-static int Cflag_count; /* Keep track of which file number we're writing */ ++static int Cflag_count; /* Keep track of which file number we're writing */ + #ifdef HAVE_PCAP_FINDALLDEVS +-static int Dflag; /* list available devices and exit */ ++static int Dflag; /* list available devices and exit */ + #endif + #ifdef HAVE_PCAP_FINDALLDEVS_EX +-static char *remote_interfaces_source; /* list available devices from this source and exit */ ++static char *remote_interfaces_source; /* list available devices from this source and exit */ + #endif + + /* +@@ -210,28 +229,28 @@ + * *export* a routine to set that flag. + */ + extern int dflag; +-int dflag; /* print filter code */ +-static int Gflag; /* rotate dump files after this many seconds */ +-static int Gflag_count; /* number of files created with Gflag rotation */ +-static time_t Gflag_time; /* The last time_t the dump file was rotated. */ +-static int Lflag; /* list available data link types and exit */ +-static int Iflag; /* rfmon (monitor) mode */ ++int dflag; /* print filter code */ ++static int Gflag; /* rotate dump files after this many seconds */ ++static int Gflag_count; /* number of files created with Gflag rotation */ ++static time_t Gflag_time; /* The last time_t the dump file was rotated. */ ++static int Lflag; /* list available data link types and exit */ ++static int Iflag; /* rfmon (monitor) mode */ + #ifdef HAVE_PCAP_SET_TSTAMP_TYPE +-static int Jflag; /* list available time stamp types */ +-static int jflag = -1; /* packet time stamp source */ ++static int Jflag; /* list available time stamp types */ ++static int jflag = -1; /* packet time stamp source */ + #endif +-static int lflag; /* line-buffered output */ +-static int pflag; /* don't go promiscuous */ ++static int lflag; /* line-buffered output */ ++static int pflag; /* don't go promiscuous */ + #ifdef HAVE_PCAP_SETDIRECTION +-static int Qflag = -1; /* restrict captured packet by send/receive direction */ ++static int Qflag = -1; /* restrict captured packet by send/receive direction */ + #endif + #ifdef HAVE_PCAP_DUMP_FLUSH +-static int Uflag; /* "unbuffered" output of dump files */ ++static int Uflag; /* "unbuffered" output of dump files */ + #endif +-static int Wflag; /* recycle output files after this number of files */ ++static int Wflag; /* recycle output files after this number of files */ + static int WflagChars; +-static char *zflag = NULL; /* compress each savefile using a specified command (like gzip or bzip2) */ +-static int timeout = 1000; /* default timeout = 1000 ms = 1 s */ ++static char *zflag = NULL; /* compress each savefile using a specified command (like gzip or bzip2) */ ++static int timeout = 1000; /* default timeout = 1000 ms = 1 s */ + #ifdef HAVE_PCAP_SET_IMMEDIATE_MODE + static int immediate_mode; + #endif +@@ -246,7 +265,7 @@ + static NORETURN void error(FORMAT_STRING(const char *), ...) PRINTFLIKE(1, 2); + static void warning(FORMAT_STRING(const char *), ...) PRINTFLIKE(1, 2); + static NORETURN void exit_tcpdump(int); +-static void (*setsignal (int sig, void (*func)(int)))(int); ++static void (*setsignal(int sig, void (*func)(int)))(int); + static void cleanup(int); + static void child_cleanup(int); + static void print_version(FILE *); +@@ -262,9 +281,9 @@ + static NORETURN void show_remote_devices_and_exit(void); + #endif + +-static void print_packet(u_char *, const struct pcap_pkthdr *, const u_char *); ++void print_packet(u_char *, const struct pcap_pkthdr *, const u_char *); + static void dump_packet_and_trunc(u_char *, const struct pcap_pkthdr *, const u_char *); +-static void dump_packet(u_char *, const struct pcap_pkthdr *, const u_char *); ++void dump_packet(u_char *, const struct pcap_pkthdr *, const u_char *); + static void droproot(const char *, const char *); + + #ifdef SIGNAL_REQ_INFO +@@ -276,10 +295,10 @@ + #endif + + #ifdef _WIN32 +- static HANDLE timer_handle = INVALID_HANDLE_VALUE; +- static void CALLBACK verbose_stats_dump(PVOID param, BOOLEAN timer_fired); +-#else /* _WIN32 */ +- static void verbose_stats_dump(int sig); ++static HANDLE timer_handle = INVALID_HANDLE_VALUE; ++static void CALLBACK verbose_stats_dump(PVOID param, BOOLEAN timer_fired); ++#else /* _WIN32 */ ++static void verbose_stats_dump(int sig); + #endif /* _WIN32 */ + + static void info(int); +@@ -288,38 +307,82 @@ + #ifdef HAVE_PCAP_FINDALLDEVS + static const struct tok status_flags[] = { + #ifdef PCAP_IF_UP +- { PCAP_IF_UP, "Up" }, ++ {PCAP_IF_UP, "Up"}, + #endif + #ifdef PCAP_IF_RUNNING +- { PCAP_IF_RUNNING, "Running" }, ++ {PCAP_IF_RUNNING, "Running"}, + #endif +- { PCAP_IF_LOOPBACK, "Loopback" }, ++ {PCAP_IF_LOOPBACK, "Loopback"}, + #ifdef PCAP_IF_WIRELESS +- { PCAP_IF_WIRELESS, "Wireless" }, ++ {PCAP_IF_WIRELESS, "Wireless"}, + #endif +- { 0, NULL } +-}; ++ {0, NULL}}; + #endif + + static pcap_t *pd; + static pcap_dumper_t *pdd = NULL; + + static int supports_monitor_mode; +- + extern int optind; + extern int opterr; + extern char *optarg; + +-struct dump_info { +- char *WFileName; +- char *CurrentFileName; +- pcap_t *pd; ++static netdissect_options Ndo; ++static netdissect_options *ndo = &Ndo; ++u_char *pcap_userdata; ++static char *cp, *infile, *cmdbuf, *device, *RFileName, *VFileName, *WFileName; ++pcap_handler callback; ++static int print = 0; ++static FILE *VFile; ++static char VFileLine[PATH_MAX + 1]; ++static char ebuf[PCAP_ERRBUF_SIZE]; ++int dlt, i; ++static char *endp; ++static int cnt = -1, op; ++static bpf_u_int32 localnet = 0, netmask = 0; ++ ++static int Oflag = 1; /* run filter code optimizer */ ++static int yflag_dlt = -1; ++static const char *yflag_dlt_name = NULL; ++ ++static const char *dlt_name; ++static struct bpf_program fcode; ++#ifndef _WIN32 ++static void (*oldhandler)(int); ++#endif ++ ++static const char *username = NULL; ++#ifndef _WIN32 ++static const char *chroot_dir = NULL; ++#endif ++// static char *ret = NULL; ++static char *end; ++#ifdef HAVE_PCAP_FINDALLDEVS ++static pcap_if_t *devlist; ++static long devnum; ++#endif ++static int status; ++ ++#ifdef HAVE_CAPSICUM ++static cap_rights_t rights; ++#endif /* HAVE_CAPSICUM */ ++static int cansandbox; ++ ++static int argc; ++static char **argv; ++ ++struct dump_info ++{ ++ char *WFileName; ++ char *CurrentFileName; ++ pcap_t *pd; + pcap_dumper_t *pdd; + netdissect_options *ndo; + #ifdef HAVE_CAPSICUM +- int dirfd; ++ int dirfd; + #endif + }; ++static struct dump_info dumpinfo; + + #if defined(HAVE_PCAP_SET_PARSER_DEBUG) + /* +@@ -330,10 +393,11 @@ + */ + #ifdef _WIN32 + __declspec(dllimport) +-#else /* _WIN32 */ ++#else /* _WIN32 */ + extern + #endif /* _WIN32 */ +-void pcap_set_parser_debug(int); ++void ++pcap_set_parser_debug(int); + #elif defined(HAVE_PCAP_DEBUG) || defined(HAVE_YYDEBUG) + /* + * We don't have pcap_set_parser_debug() in libpcap, but we do have +@@ -347,7 +411,7 @@ + extern int pcap_debug; + + pcap_debug = value; +-#else /* HAVE_PCAP_DEBUG */ ++#else /* HAVE_PCAP_DEBUG */ + extern int yydebug; + + yydebug = value; +@@ -366,10 +430,11 @@ + */ + #ifdef _WIN32 + __declspec(dllimport) +-#else /* _WIN32 */ ++#else /* _WIN32 */ + extern + #endif /* _WIN32 */ +-void pcap_set_optimizer_debug(int); ++void ++pcap_set_optimizer_debug(int); + #endif + + /* VARARGS */ +@@ -382,7 +447,8 @@ + va_start(ap, fmt); + (void)vfprintf(stderr, fmt, ap); + va_end(ap); +- if (*fmt) { ++ if (*fmt) ++ { + fmt += strlen(fmt); + if (fmt[-1] != '\n') + (void)fputc('\n', stderr); +@@ -401,15 +467,15 @@ + va_start(ap, fmt); + (void)vfprintf(stderr, fmt, ap); + va_end(ap); +- if (*fmt) { ++ if (*fmt) ++ { + fmt += strlen(fmt); + if (fmt[-1] != '\n') + (void)fputc('\n', stderr); + } + } + +-static void +-exit_tcpdump(int status) ++static void exit_tcpdump(int status) + { + nd_cleanup(); + exit(status); +@@ -428,20 +494,25 @@ + if (n_tstamp_types < 0) + error("%s", pcap_geterr(pc)); + +- if (n_tstamp_types == 0) { ++ if (n_tstamp_types == 0) ++ { + fprintf(stderr, "Time stamp type cannot be set for %s\n", +- device); ++ device); + exit_tcpdump(S_SUCCESS); + } + fprintf(stderr, "Time stamp types for %s (use option -j to set):\n", +- device); +- for (i = 0; i < n_tstamp_types; i++) { ++ device); ++ for (i = 0; i < n_tstamp_types; i++) ++ { + tstamp_type_name = pcap_tstamp_type_val_to_name(tstamp_types[i]); +- if (tstamp_type_name != NULL) { +- (void) fprintf(stderr, " %s (%s)\n", tstamp_type_name, +- pcap_tstamp_type_val_to_description(tstamp_types[i])); +- } else { +- (void) fprintf(stderr, " %d\n", tstamp_types[i]); ++ if (tstamp_type_name != NULL) ++ { ++ (void)fprintf(stderr, " %s (%s)\n", tstamp_type_name, ++ pcap_tstamp_type_val_to_description(tstamp_types[i])); ++ } ++ else ++ { ++ (void)fprintf(stderr, " %d\n", tstamp_types[i]); + } + } + pcap_free_tstamp_types(tstamp_types); +@@ -471,28 +542,32 @@ + * not in monitor mode). + */ + if (supports_monitor_mode) +- (void) fprintf(stderr, "Data link types for %s %s (use option -y to set):\n", +- device, +- Iflag ? "when in monitor mode" : "when not in monitor mode"); ++ (void)fprintf(stderr, "Data link types for %s %s (use option -y to set):\n", ++ device, ++ Iflag ? "when in monitor mode" : "when not in monitor mode"); + else +- (void) fprintf(stderr, "Data link types for %s (use option -y to set):\n", +- device); ++ (void)fprintf(stderr, "Data link types for %s (use option -y to set):\n", ++ device); + +- for (i = 0; i < n_dlts; i++) { ++ for (i = 0; i < n_dlts; i++) ++ { + dlt_name = pcap_datalink_val_to_name(dlts[i]); +- if (dlt_name != NULL) { +- (void) fprintf(stderr, " %s (%s)", dlt_name, +- pcap_datalink_val_to_description(dlts[i])); ++ if (dlt_name != NULL) ++ { ++ (void)fprintf(stderr, " %s (%s)", dlt_name, ++ pcap_datalink_val_to_description(dlts[i])); + + /* + * OK, does tcpdump handle that type? + */ + if (!has_printer(dlts[i])) +- (void) fprintf(stderr, " (printing not supported)"); ++ (void)fprintf(stderr, " (printing not supported)"); + fprintf(stderr, "\n"); +- } else { +- (void) fprintf(stderr, " DLT %d (printing not supported)\n", +- dlts[i]); ++ } ++ else ++ { ++ (void)fprintf(stderr, " DLT %d (printing not supported)\n", ++ dlts[i]); + } + } + #ifdef HAVE_PCAP_FREE_DATALINKS +@@ -511,16 +586,20 @@ + + if (pcap_findalldevs(&devlist, ebuf) < 0) + error("%s", ebuf); +- for (i = 0, dev = devlist; dev != NULL; i++, dev = dev->next) { +- printf("%d.%s", i+1, dev->name); ++ for (i = 0, dev = devlist; dev != NULL; i++, dev = dev->next) ++ { ++ printf("%d.%s", i + 1, dev->name); + if (dev->description != NULL) + printf(" (%s)", dev->description); +- if (dev->flags != 0) { ++ if (dev->flags != 0) ++ { + printf(" ["); + printf("%s", bittok2str(status_flags, "none", dev->flags)); + #ifdef PCAP_IF_WIRELESS +- if (dev->flags & PCAP_IF_WIRELESS) { +- switch (dev->flags & PCAP_IF_CONNECTION_STATUS) { ++ if (dev->flags & PCAP_IF_WIRELESS) ++ { ++ switch (dev->flags & PCAP_IF_CONNECTION_STATUS) ++ { + + case PCAP_IF_CONNECTION_STATUS_UNKNOWN: + printf(", Association status unknown"); +@@ -537,8 +616,11 @@ + case PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE: + break; + } +- } else { +- switch (dev->flags & PCAP_IF_CONNECTION_STATUS) { ++ } ++ else ++ { ++ switch (dev->flags & PCAP_IF_CONNECTION_STATUS) ++ { + + case PCAP_IF_CONNECTION_STATUS_UNKNOWN: + printf(", Connection status unknown"); +@@ -575,10 +657,11 @@ + int i; + + if (pcap_findalldevs_ex(remote_interfaces_source, NULL, &devlist, +- ebuf) < 0) ++ ebuf) < 0) + error("%s", ebuf); +- for (i = 0, dev = devlist; dev != NULL; i++, dev = dev->next) { +- printf("%d.%s", i+1, dev->name); ++ for (i = 0, dev = devlist; dev != NULL; i++, dev = dev->next) ++ { ++ printf("%d.%s", i + 1, dev->name); + if (dev->description != NULL) + printf(" (%s)", dev->description); + if (dev->flags != 0) +@@ -625,29 +708,29 @@ + * version of libpcap we're using. + */ + #if defined(HAVE_PCAP_CREATE) || defined(_WIN32) +-#define B_FLAG "B:" +-#define B_FLAG_USAGE " [ -B size ]" ++#define B_FLAG "B:" ++#define B_FLAG_USAGE " [ -B size ]" + #else /* defined(HAVE_PCAP_CREATE) || defined(_WIN32) */ + #define B_FLAG + #define B_FLAG_USAGE + #endif /* defined(HAVE_PCAP_CREATE) || defined(_WIN32) */ + + #ifdef HAVE_PCAP_FINDALLDEVS +-#define D_FLAG "D" ++#define D_FLAG "D" + #else + #define D_FLAG + #endif + + #ifdef HAVE_PCAP_CREATE +-#define I_FLAG "I" ++#define I_FLAG "I" + #else /* HAVE_PCAP_CREATE */ + #define I_FLAG + #endif /* HAVE_PCAP_CREATE */ + + #ifdef HAVE_PCAP_SET_TSTAMP_TYPE +-#define j_FLAG "j:" +-#define j_FLAG_USAGE " [ -j tstamptype ]" +-#define J_FLAG "J" ++#define j_FLAG "j:" ++#define j_FLAG_USAGE " [ -j tstamptype ]" ++#define J_FLAG "J" + #else /* PCAP_ERROR_TSTAMP_TYPE_NOTSUP */ + #define j_FLAG + #define j_FLAG_USAGE +@@ -667,12 +750,18 @@ + #endif + + #ifdef HAVE_PCAP_DUMP_FLUSH +-#define U_FLAG "U" ++#define U_FLAG "U" + #else + #define U_FLAG + #endif + ++#if STELLAR_DUMP ++#define SHORTOPTS "aAb" B_FLAG "c:C:d" D_FLAG "eE:fF:G:hHi:" I_FLAG j_FLAG J_FLAG "KlLm:M:nNOpq" Q_FLAG "r:s:StT:u" U_FLAG "vV:w:W:xXy:Yz:Z:P:k:g#" ++static struct stellar_dump_args g_stellar_dump_arg = {}; ++static volatile int g_stellar_dump_run = 1; ++#else + #define SHORTOPTS "aAb" B_FLAG "c:C:d" D_FLAG "eE:fF:G:hHi:" I_FLAG j_FLAG J_FLAG "KlLm:M:nNOpq" Q_FLAG "r:s:StT:u" U_FLAG "vV:w:W:xXy:Yz:Z:#" ++#endif + + /* + * Long options. +@@ -694,65 +783,70 @@ + * component of the entry for the long option, and have a case for that + * option in the switch statement. + */ +-#define OPTION_VERSION 128 +-#define OPTION_TSTAMP_PRECISION 129 +-#define OPTION_IMMEDIATE_MODE 130 +-#define OPTION_PRINT 131 +-#define OPTION_LIST_REMOTE_INTERFACES 132 +-#define OPTION_TSTAMP_MICRO 133 +-#define OPTION_TSTAMP_NANO 134 +-#define OPTION_FP_TYPE 135 +-#define OPTION_COUNT 136 ++#define OPTION_VERSION 128 ++#define OPTION_TSTAMP_PRECISION 129 ++#define OPTION_IMMEDIATE_MODE 130 ++#define OPTION_PRINT 131 ++#define OPTION_LIST_REMOTE_INTERFACES 132 ++#define OPTION_TSTAMP_MICRO 133 ++#define OPTION_TSTAMP_NANO 134 ++#define OPTION_FP_TYPE 135 ++#define OPTION_COUNT 136 + + static const struct option longopts[] = { + #if defined(HAVE_PCAP_CREATE) || defined(_WIN32) +- { "buffer-size", required_argument, NULL, 'B' }, ++ {"buffer-size", required_argument, NULL, 'B'}, + #endif +- { "list-interfaces", no_argument, NULL, 'D' }, ++ {"list-interfaces", no_argument, NULL, 'D'}, + #ifdef HAVE_PCAP_FINDALLDEVS_EX +- { "list-remote-interfaces", required_argument, NULL, OPTION_LIST_REMOTE_INTERFACES }, ++ {"list-remote-interfaces", required_argument, NULL, OPTION_LIST_REMOTE_INTERFACES}, + #endif +- { "help", no_argument, NULL, 'h' }, +- { "interface", required_argument, NULL, 'i' }, ++ {"help", no_argument, NULL, 'h'}, ++ {"serverip", required_argument, NULL, 'i'}, + #ifdef HAVE_PCAP_CREATE +- { "monitor-mode", no_argument, NULL, 'I' }, ++ {"monitor-mode", no_argument, NULL, 'I'}, + #endif + #ifdef HAVE_PCAP_SET_TSTAMP_TYPE +- { "time-stamp-type", required_argument, NULL, 'j' }, +- { "list-time-stamp-types", no_argument, NULL, 'J' }, ++ {"time-stamp-type", required_argument, NULL, 'j'}, ++ {"list-time-stamp-types", no_argument, NULL, 'J'}, + #endif + #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION +- { "micro", no_argument, NULL, OPTION_TSTAMP_MICRO}, +- { "nano", no_argument, NULL, OPTION_TSTAMP_NANO}, +- { "time-stamp-precision", required_argument, NULL, OPTION_TSTAMP_PRECISION}, +-#endif +- { "dont-verify-checksums", no_argument, NULL, 'K' }, +- { "list-data-link-types", no_argument, NULL, 'L' }, +- { "no-optimize", no_argument, NULL, 'O' }, +- { "no-promiscuous-mode", no_argument, NULL, 'p' }, ++ {"micro", no_argument, NULL, OPTION_TSTAMP_MICRO}, ++ {"nano", no_argument, NULL, OPTION_TSTAMP_NANO}, ++ {"time-stamp-precision", required_argument, NULL, OPTION_TSTAMP_PRECISION}, ++#endif ++ {"dont-verify-checksums", no_argument, NULL, 'K'}, ++ {"list-data-link-types", no_argument, NULL, 'L'}, ++ {"no-optimize", no_argument, NULL, 'O'}, ++ {"no-promiscuous-mode", no_argument, NULL, 'p'}, + #ifdef HAVE_PCAP_SETDIRECTION +- { "direction", required_argument, NULL, 'Q' }, ++ {"direction", required_argument, NULL, 'Q'}, + #endif +- { "snapshot-length", required_argument, NULL, 's' }, +- { "absolute-tcp-sequence-numbers", no_argument, NULL, 'S' }, ++ {"snapshot-length", required_argument, NULL, 's'}, ++ {"absolute-tcp-sequence-numbers", no_argument, NULL, 'S'}, + #ifdef HAVE_PCAP_DUMP_FLUSH +- { "packet-buffered", no_argument, NULL, 'U' }, ++ {"packet-buffered", no_argument, NULL, 'U'}, + #endif +- { "linktype", required_argument, NULL, 'y' }, ++ {"linktype", required_argument, NULL, 'y'}, + #ifdef HAVE_PCAP_SET_IMMEDIATE_MODE +- { "immediate-mode", no_argument, NULL, OPTION_IMMEDIATE_MODE }, ++ {"immediate-mode", no_argument, NULL, OPTION_IMMEDIATE_MODE}, + #endif + #ifdef HAVE_PCAP_SET_PARSER_DEBUG +- { "debug-filter-parser", no_argument, NULL, 'Y' }, ++ {"debug-filter-parser", no_argument, NULL, 'Y'}, + #endif +- { "relinquish-privileges", required_argument, NULL, 'Z' }, +- { "count", no_argument, NULL, OPTION_COUNT }, +- { "fp-type", no_argument, NULL, OPTION_FP_TYPE }, +- { "number", no_argument, NULL, '#' }, +- { "print", no_argument, NULL, OPTION_PRINT }, +- { "version", no_argument, NULL, OPTION_VERSION }, +- { NULL, 0, NULL, 0 } +-}; ++ {"relinquish-privileges", required_argument, NULL, 'Z'}, ++ {"count", no_argument, NULL, OPTION_COUNT}, ++ {"fp-type", no_argument, NULL, OPTION_FP_TYPE}, ++ {"number", no_argument, NULL, '#'}, ++ {"print", no_argument, NULL, OPTION_PRINT}, ++ {"version", no_argument, NULL, OPTION_VERSION}, ++#if STELLAR_DUMP ++ {"greedy", no_argument, NULL, 'g'}, ++ {"threads", required_argument, NULL, 'k'}, ++ {"serverport", required_argument, NULL, 'P'}, ++// {"classify", required_argument, NULL, 255}, ++#endif ++ {NULL, 0, NULL, 0}}; + + #ifdef HAVE_PCAP_FINDALLDEVS_EX + #define LIST_REMOTE_INTERFACES_USAGE "[ --list-remote-interfaces remote-source ]" +@@ -777,11 +871,13 @@ + error("Chroot without dropping root is insecure"); + + pw = getpwnam(username); +- if (pw) { +- if (chroot_dir) { +- if (chroot(chroot_dir) != 0 || chdir ("/") != 0) ++ if (pw) ++ { ++ if (chroot_dir) ++ { ++ if (chroot(chroot_dir) != 0 || chdir("/") != 0) + error("Couldn't chroot/chdir to '%.64s': %s", +- chroot_dir, pcap_strerror(errno)); ++ chroot_dir, pcap_strerror(errno)); + } + #ifdef HAVE_LIBCAP_NG + { +@@ -793,21 +889,23 @@ + } + #else + if (initgroups(pw->pw_name, pw->pw_gid) != 0 || +- setgid(pw->pw_gid) != 0 || setuid(pw->pw_uid) != 0) ++ setgid(pw->pw_gid) != 0 || setuid(pw->pw_uid) != 0) + error("Couldn't change to '%.32s' uid=%lu gid=%lu: %s", +- username, +- (unsigned long)pw->pw_uid, +- (unsigned long)pw->pw_gid, +- pcap_strerror(errno)); +- else { ++ username, ++ (unsigned long)pw->pw_uid, ++ (unsigned long)pw->pw_gid, ++ pcap_strerror(errno)); ++ else ++ { + fprintf(stderr, "dropped privs to %s\n", username); + } + #endif /* HAVE_LIBCAP_NG */ +- } else ++ } ++ else + error("Couldn't find user '%.32s'", username); + #ifdef HAVE_LIBCAP_NG + /* We don't need CAP_SETUID, CAP_SETGID and CAP_SYS_CHROOT any more. */ +-DIAG_OFF_ASSIGN_ENUM ++ DIAG_OFF_ASSIGN_ENUM + capng_updatev( + CAPNG_DROP, + CAPNG_EFFECTIVE | CAPNG_PERMITTED, +@@ -815,10 +913,9 @@ + CAP_SETGID, + CAP_SYS_CHROOT, + -1); +-DIAG_ON_ASSIGN_ENUM ++ DIAG_ON_ASSIGN_ENUM + capng_apply(CAPNG_SELECT_BOTH); + #endif /* HAVE_LIBCAP_NG */ +- + } + #endif /* _WIN32 */ + +@@ -828,7 +925,8 @@ + int c = 0; + + x -= 1; +- while (x > 0) { ++ while (x > 0) ++ { + c += 1; + x /= 10; + } +@@ -836,56 +934,61 @@ + return c; + } + +- + static void + MakeFilename(char *buffer, char *orig_name, int cnt, int max_chars) + { +- char *filename = malloc(PATH_MAX + 1); +- if (filename == NULL) +- error("%s: malloc", __func__); +- if (strlen(orig_name) == 0) +- error("an empty string is not a valid file name"); +- +- /* Process with strftime if Gflag is set. */ +- if (Gflag != 0) { +- struct tm *local_tm; +- +- /* Convert Gflag_time to a usable format */ +- if ((local_tm = localtime(&Gflag_time)) == NULL) { +- error("%s: localtime", __func__); +- } +- +- /* There's no good way to detect an error in strftime since a return +- * value of 0 isn't necessarily failure; if orig_name is an empty +- * string, the formatted string will be empty. +- * +- * However, the C90 standard says that, if there *is* a +- * buffer overflow, the content of the buffer is undefined, +- * so we must check for a buffer overflow. +- * +- * So we check above for an empty orig_name, and only call +- * strftime() if it's non-empty, in which case the return +- * value will only be 0 if the formatted date doesn't fit +- * in the buffer. +- * +- * (We check above because, even if we don't use -G, we +- * want a better error message than "tcpdump: : No such +- * file or directory" for this case.) +- */ +- if (strftime(filename, PATH_MAX, orig_name, local_tm) == 0) { +- error("%s: strftime", __func__); +- } +- } else { +- strncpy(filename, orig_name, PATH_MAX); +- } ++ char *filename = malloc(PATH_MAX + 1); ++ if (filename == NULL) ++ error("%s: malloc", __func__); ++ if (strlen(orig_name) == 0) ++ error("an empty string is not a valid file name"); ++ ++ /* Process with strftime if Gflag is set. */ ++ if (Gflag != 0) ++ { ++ struct tm *local_tm; ++ ++ /* Convert Gflag_time to a usable format */ ++ if ((local_tm = localtime(&Gflag_time)) == NULL) ++ { ++ error("%s: localtime", __func__); ++ return; ++ } ++ ++ /* There's no good way to detect an error in strftime since a return ++ * value of 0 isn't necessarily failure; if orig_name is an empty ++ * string, the formatted string will be empty. ++ * ++ * However, the C90 standard says that, if there *is* a ++ * buffer overflow, the content of the buffer is undefined, ++ * so we must check for a buffer overflow. ++ * ++ * So we check above for an empty orig_name, and only call ++ * strftime() if it's non-empty, in which case the return ++ * value will only be 0 if the formatted date doesn't fit ++ * in the buffer. ++ * ++ * (We check above because, even if we don't use -G, we ++ * want a better error message than "tcpdump: : No such ++ * file or directory" for this case.) ++ */ ++ if (strftime(filename, PATH_MAX, orig_name, local_tm) == 0) ++ { ++ error("%s: strftime", __func__); ++ return; ++ } ++ } ++ else ++ { ++ strncpy(filename, orig_name, PATH_MAX); ++ } + + if (cnt == 0 && max_chars == 0) + strncpy(buffer, filename, PATH_MAX + 1); +- else +- if (snprintf(buffer, PATH_MAX + 1, "%s%0*d", filename, max_chars, cnt) > PATH_MAX) +- /* Report an error if the filename is too large */ +- error("too many output files or filename is too long (> %d)", PATH_MAX); +- free(filename); ++ else if (snprintf(buffer, PATH_MAX + 1, "%s%0*d", filename, max_chars, cnt) > PATH_MAX) ++ /* Report an error if the filename is too large */ ++ error("too many output files or filename is too long (> %d)", PATH_MAX); ++ free(filename); + } + + static char * +@@ -898,7 +1001,7 @@ + if (!ret) + return NULL; + +- len = strlen (ptr); ++ len = strlen(ptr); + if (len > 0 && ptr[len - 1] == '\n') + ptr[len - 1] = '\0'; + +@@ -932,7 +1035,7 @@ + + return (capdnsloc); + } +-#endif /* HAVE_CASPER */ ++#endif /* HAVE_CASPER */ + + #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION + static int +@@ -950,7 +1053,8 @@ + static const char * + tstamp_precision_to_string(int precision) + { +- switch (precision) { ++ switch (precision) ++ { + + case PCAP_TSTAMP_PRECISION_MICRO: + return "micro"; +@@ -962,6 +1066,7 @@ + return "unknown"; + } + } ++ + #endif + + #ifdef HAVE_CAPSICUM +@@ -1025,10 +1130,12 @@ + cap_rights_t rights; + + cap_rights_init(&rights, CAP_SEEK, CAP_WRITE, CAP_FCNTL); +- if (cap_rights_limit(fd, &rights) < 0 && errno != ENOSYS) { ++ if (cap_rights_limit(fd, &rights) < 0 && errno != ENOSYS) ++ { + error("unable to limit dump descriptor"); + } +- if (cap_fcntls_limit(fd, CAP_FCNTL_GETFL) < 0 && errno != ENOSYS) { ++ if (cap_fcntls_limit(fd, CAP_FCNTL_GETFL) < 0 && errno != ENOSYS) ++ { + error("unable to limit dump descriptor fcntls"); + } + } +@@ -1037,8 +1144,7 @@ + /* + * Copy arg vector into a new buffer, concatenating arguments with spaces. + */ +-static char * +-copy_argv(char **argv) ++static char *copy_argv(char **argv) + { + char **p; + size_t len = 0; +@@ -1058,7 +1164,8 @@ + + p = argv; + dst = buf; +- while ((src = *p++) != NULL) { ++ while ((src = *p++) != NULL) ++ { + while ((*dst++ = *src++) != '\0') + ; + dst[-1] = ' '; +@@ -1075,7 +1182,7 @@ + * we define it as 0 if it's not defined, so it does nothing. + */ + #ifndef O_BINARY +-#define O_BINARY 0 ++#define O_BINARY 0 + #endif + + static char * +@@ -1086,7 +1193,7 @@ + char *cp; + our_statb buf; + +- fd = open(fname, O_RDONLY|O_BINARY); ++ fd = open(fname, O_RDONLY | O_BINARY); + if (fd < 0) + error("can't open %s: %s", fname, pcap_strerror(errno)); + +@@ -1103,17 +1210,18 @@ + cp = malloc((u_int)buf.st_size + 1); + if (cp == NULL) + error("malloc(%d) for %s: %s", (u_int)buf.st_size + 1, +- fname, pcap_strerror(errno)); ++ fname, pcap_strerror(errno)); + cc = read(fd, cp, (u_int)buf.st_size); + if (cc < 0) + error("read %s: %s", fname, pcap_strerror(errno)); + if (cc != buf.st_size) +- error("short read %s (%d != %d)", fname, (int) cc, +- (int)buf.st_size); ++ error("short read %s (%d != %d)", fname, (int)cc, ++ (int)buf.st_size); + + close(fd); + /* replace "# comment" with spaces */ +- for (i = 0; i < cc; i++) { ++ for (i = 0; i < cc; i++) ++ { + if (cp[i] == '#') + while (i < cc && cp[i] != '\n') + cp[i++] = ' '; +@@ -1135,19 +1243,22 @@ + * of the device. + */ + p = strchr(device, ':'); +- if (p != NULL) { ++ if (p != NULL) ++ { + /* + * We found it. Is it followed by "//"? + */ +- p++; /* skip the : */ +- if (strncmp(p, "//", 2) == 0) { ++ 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 += 2; /* skip the // */ + p = strchr(p, '/'); +- if (p != NULL) { ++ if (p != NULL) ++ { + /* + * OK, past the / is the path. + */ +@@ -1156,18 +1267,22 @@ + } + } + devnum = strtol(device, &end, 10); +- if (device != end && *end == '\0') { ++ if (device != end && *end == '\0') ++ { + /* + * It's all-numeric, but is it a valid number? + */ +- if (devnum <= 0) { ++ if (devnum <= 0) ++ { + /* + * No, it's not an ordinal. + */ + error("Invalid adapter index"); + } + return (devnum); +- } else { ++ } ++ else ++ { + /* + * It's not all-numeric; return -1, so our caller + * knows that. +@@ -1175,13 +1290,15 @@ + return (-1); + } + } ++#endif + + static char * + find_interface_by_number(const char *url + #ifndef HAVE_PCAP_FINDALLDEVS_EX +-_U_ ++ _U_ + #endif +-, long devnum) ++ , ++ long devnum) + { + pcap_if_t *dev, *devlist; + long i; +@@ -1199,27 +1316,31 @@ + * of the URL. + */ + endp = strchr(url, ':'); +- if (endp != NULL) { ++ if (endp != NULL) ++ { + /* + * We found it. Is it followed by "//"? + */ +- endp++; /* skip the : */ +- if (strncmp(endp, "//", 2) == 0) { ++ 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 += 2; /* skip the // */ + endp = strchr(endp, '/'); +- } else ++ } ++ else + endp = NULL; + } +- if (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 */ ++ endp++; /* Include the trailing / in the URL; pcap_findalldevs_ex() requires it */ + host_url = malloc(endp - url + 1); + if (host_url == NULL && (endp - url + 1) > 0) + error("Invalid allocation for host"); +@@ -1228,24 +1349,30 @@ + host_url[endp - url] = '\0'; + status = pcap_findalldevs_ex(host_url, NULL, &devlist, ebuf); + free(host_url); +- } else ++ } ++ else + #endif +- status = pcap_findalldevs(&devlist, ebuf); ++ status = pcap_findalldevs(&devlist, ebuf); + if (status < 0) ++ { + error("%s", ebuf); ++ return NULL; ++ } + /* + * Look for the devnum-th entry in the list of devices (1-based). + */ +- for (i = 0, dev = devlist; i < devnum-1 && dev != NULL; +- i++, dev = dev->next) ++ for (i = 0, dev = devlist; i < devnum - 1 && dev != NULL; ++ i++, dev = dev->next) + ; + if (dev == NULL) ++ { + error("Invalid adapter index"); ++ return NULL; ++ } + device = strdup(dev->name); + pcap_freealldevs(devlist); + return (device); + } +-#endif + + #ifdef HAVE_PCAP_OPEN + /* +@@ -1269,15 +1396,17 @@ + * Is this an rpcap URL? + */ + if (strncmp(device, rpcap_prefix, sizeof(rpcap_prefix) - 1) == 0 || +- strncmp(device, rpcap_ssl_prefix, sizeof(rpcap_ssl_prefix) - 1) == 0) { ++ strncmp(device, rpcap_ssl_prefix, sizeof(rpcap_ssl_prefix) - 1) == 0) ++ { + /* + * Yes. Open it with pcap_open(). + */ + *ebuf = '\0'; + pc = pcap_open(device, ndo->ndo_snaplen, +- pflag ? 0 : PCAP_OPENFLAG_PROMISCUOUS, timeout, NULL, +- ebuf); +- if (pc == NULL) { ++ pflag ? 0 : PCAP_OPENFLAG_PROMISCUOUS, timeout, NULL, ++ ebuf); ++ if (pc == NULL) ++ { + /* + * If this failed with "No such device" or "The system + * cannot find the device specified", that means +@@ -1286,7 +1415,7 @@ + * actually an interface index. + */ + if (strstr(ebuf, "No such device") != NULL || +- strstr(ebuf, "The system cannot find the device specified") != NULL) ++ strstr(ebuf, "The system cannot find the device specified") != NULL) + return (NULL); + error("%s", ebuf); + } +@@ -1298,7 +1427,8 @@ + + #ifdef HAVE_PCAP_CREATE + pc = pcap_create(device, ebuf); +- if (pc == NULL) { ++ if (pc == NULL) ++ { + /* + * If this failed with "No such device", that means + * the interface doesn't exist; return NULL, so that +@@ -1317,17 +1447,18 @@ + status = pcap_set_tstamp_precision(pc, ndo->ndo_tstamp_precision); + if (status != 0) + error("%s: Can't set %ssecond time stamp precision: %s", +- device, +- tstamp_precision_to_string(ndo->ndo_tstamp_precision), +- pcap_statustostr(status)); ++ device, ++ tstamp_precision_to_string(ndo->ndo_tstamp_precision), ++ pcap_statustostr(status)); + #endif + + #ifdef HAVE_PCAP_SET_IMMEDIATE_MODE +- if (immediate_mode) { ++ if (immediate_mode) ++ { + status = pcap_set_immediate_mode(pc, 1); + if (status != 0) + error("%s: Can't set immediate mode: %s", +- device, pcap_statustostr(status)); ++ device, pcap_statustostr(status)); + } + #endif + /* +@@ -1337,7 +1468,8 @@ + supports_monitor_mode = 1; + else + supports_monitor_mode = 0; +- if (ndo->ndo_snaplen != 0) { ++ if (ndo->ndo_snaplen != 0) ++ { + /* + * A snapshot length was explicitly specified; + * use it. +@@ -1345,66 +1477,73 @@ + status = pcap_set_snaplen(pc, ndo->ndo_snaplen); + if (status != 0) + error("%s: Can't set snapshot length: %s", +- device, pcap_statustostr(status)); ++ device, pcap_statustostr(status)); + } + status = pcap_set_promisc(pc, !pflag); + if (status != 0) + error("%s: Can't set promiscuous mode: %s", +- device, pcap_statustostr(status)); +- if (Iflag) { ++ device, pcap_statustostr(status)); ++ if (Iflag) ++ { + status = pcap_set_rfmon(pc, 1); + if (status != 0) + error("%s: Can't set monitor mode: %s", +- device, pcap_statustostr(status)); ++ device, pcap_statustostr(status)); + } + status = pcap_set_timeout(pc, timeout); + if (status != 0) + error("%s: pcap_set_timeout failed: %s", +- device, pcap_statustostr(status)); +- if (Bflag != 0) { ++ device, pcap_statustostr(status)); ++ if (Bflag != 0) ++ { + status = pcap_set_buffer_size(pc, Bflag); + if (status != 0) + error("%s: Can't set buffer size: %s", +- device, pcap_statustostr(status)); ++ device, pcap_statustostr(status)); + } + #ifdef HAVE_PCAP_SET_TSTAMP_TYPE +- if (jflag != -1) { ++ if (jflag != -1) ++ { + status = pcap_set_tstamp_type(pc, jflag); + if (status < 0) + error("%s: Can't set time stamp type: %s", +- device, pcap_statustostr(status)); ++ device, pcap_statustostr(status)); + else if (status > 0) + warning("When trying to set timestamp type '%s' on %s: %s", +- pcap_tstamp_type_val_to_name(jflag), device, +- pcap_statustostr(status)); ++ pcap_tstamp_type_val_to_name(jflag), device, ++ pcap_statustostr(status)); + } + #endif + status = pcap_activate(pc); +- if (status < 0) { ++ if (status < 0) ++ { + /* + * pcap_activate() failed. + */ + cp = pcap_geterr(pc); + if (status == PCAP_ERROR) + error("%s", cp); +- else if (status == PCAP_ERROR_NO_SUCH_DEVICE) { ++ else if (status == PCAP_ERROR_NO_SUCH_DEVICE) ++ { + /* + * Return an error for our caller to handle. + */ + snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s: %s\n(%s)", +- device, pcap_statustostr(status), cp); +- } else if (status == PCAP_ERROR_PERM_DENIED && *cp != '\0') ++ device, pcap_statustostr(status), cp); ++ } ++ else if (status == PCAP_ERROR_PERM_DENIED && *cp != '\0') + error("%s: %s\n(%s)", device, +- pcap_statustostr(status), cp); ++ pcap_statustostr(status), cp); + #ifdef __FreeBSD__ + else if (status == PCAP_ERROR_RFMON_NOTSUP && +- strncmp(device, "wlan", 4) == 0) { ++ strncmp(device, "wlan", 4) == 0) ++ { + char parent[8], newdev[8]; + char sysctl[32]; + size_t s = sizeof(parent); + + snprintf(sysctl, sizeof(sysctl), +- "net.wlan.%d.%%parent", atoi(device + 4)); ++ "net.wlan.%d.%%parent", atoi(device + 4)); + sysctlbyname(sysctl, parent, &s, NULL, 0); + strlcpy(newdev, device, sizeof(newdev)); + /* Suggest a new wlan device. */ +@@ -1412,20 +1551,22 @@ + * when the index is 9 or greater but the only consequence in this + * specific case would be an error message that looks a bit odd. + */ +- newdev[strlen(newdev)-1]++; ++ newdev[strlen(newdev) - 1]++; + error("%s is not a monitor mode VAP\n" +- "To create a new monitor mode VAP use:\n" +- " ifconfig %s create wlandev %s wlanmode monitor\n" +- "and use %s as the tcpdump interface", +- device, newdev, parent, newdev); ++ "To create a new monitor mode VAP use:\n" ++ " ifconfig %s create wlandev %s wlanmode monitor\n" ++ "and use %s as the tcpdump interface", ++ device, newdev, parent, newdev); + } + #endif + else + error("%s: %s", device, +- pcap_statustostr(status)); ++ pcap_statustostr(status)); + pcap_close(pc); + return (NULL); +- } else if (status > 0) { ++ } ++ else if (status > 0) ++ { + /* + * pcap_activate() succeeded, but it's warning us + * of a problem it had. +@@ -1434,22 +1575,23 @@ + if (status == PCAP_WARNING) + warning("%s", cp); + else if (status == PCAP_WARNING_PROMISC_NOTSUP && +- *cp != '\0') ++ *cp != '\0') + warning("%s: %s\n(%s)", device, +- pcap_statustostr(status), cp); ++ pcap_statustostr(status), cp); + else + warning("%s: %s", device, +- pcap_statustostr(status)); ++ pcap_statustostr(status)); + } + #ifdef HAVE_PCAP_SETDIRECTION +- if (Qflag != -1) { ++ if (Qflag != -1) ++ { + status = pcap_setdirection(pc, Qflag); + if (status != 0) + error("%s: pcap_setdirection() failed: %s", +- device, pcap_geterr(pc)); +- } ++ device, pcap_geterr(pc)); ++ } + #endif /* HAVE_PCAP_SETDIRECTION */ +-#else /* HAVE_PCAP_CREATE */ ++#else /* HAVE_PCAP_CREATE */ + *ebuf = '\0'; + /* + * If no snapshot length was specified, or a length of 0 was +@@ -1458,7 +1600,8 @@ + if (ndo->ndo_snaplen == 0) + ndo->ndo_snaplen = MAXIMUM_SNAPLEN; + pc = pcap_open_live(device, ndo->ndo_snaplen, !pflag, timeout, ebuf); +- if (pc == NULL) { ++ if (pc == NULL) ++ { + /* + * If this failed with "No such device", that means + * the interface doesn't exist; return NULL, so that +@@ -1476,48 +1619,743 @@ + return (pc); + } + +-int +-main(int argc, char **argv) ++/* ++ * Catch a signal. ++ */ ++static void (*setsignal(int sig, void (*func)(int)))(int) + { +- int cnt, op, i; +- bpf_u_int32 localnet = 0, netmask = 0; +- char *cp, *infile, *cmdbuf, *device, *RFileName, *VFileName, *WFileName; +- char *endp; +- pcap_handler callback; +- int dlt; +- const char *dlt_name; +- struct bpf_program fcode; +-#ifndef _WIN32 +- void (*oldhandler)(int); ++#ifdef _WIN32 ++ return (signal(sig, func)); ++#else ++ struct sigaction old, new; ++ ++ memset(&new, 0, sizeof(new)); ++ new.sa_handler = func; ++ if ((sig == SIGCHLD) ++#ifdef SIGNAL_REQ_INFO ++ || (sig == SIGNAL_REQ_INFO) + #endif +- struct dump_info dumpinfo; +- u_char *pcap_userdata; +- char ebuf[PCAP_ERRBUF_SIZE]; +- char VFileLine[PATH_MAX + 1]; +- const char *username = NULL; +-#ifndef _WIN32 +- const char *chroot_dir = NULL; ++#ifdef SIGNAL_FLUSH_PCAP ++ || (sig == SIGNAL_FLUSH_PCAP) + #endif +- char *ret = NULL; +- char *end; +-#ifdef HAVE_PCAP_FINDALLDEVS +- pcap_if_t *devlist; +- long devnum; ++ ) ++ new.sa_flags = SA_RESTART; ++ if (sigaction(sig, &new, &old) < 0) ++ return (SIG_ERR); ++ return (old.sa_handler); + #endif +- int status; +- FILE *VFile; ++} ++ ++/* make a clean exit on interrupts */ ++static void cleanup(int signo _U_) ++{ ++#ifdef _WIN32 ++ if (timer_handle != INVALID_HANDLE_VALUE) ++ { ++ DeleteTimerQueueTimer(NULL, timer_handle, NULL); ++ CloseHandle(timer_handle); ++ timer_handle = INVALID_HANDLE_VALUE; ++ } ++#else /* _WIN32 */ ++ struct itimerval timer; ++ ++ timer.it_interval.tv_sec = 0; ++ timer.it_interval.tv_usec = 0; ++ timer.it_value.tv_sec = 0; ++ timer.it_value.tv_usec = 0; ++ setitimer(ITIMER_REAL, &timer, NULL); ++#endif /* _WIN32 */ ++ ++#ifdef HAVE_PCAP_BREAKLOOP ++ /* ++ * We have "pcap_breakloop()"; use it, so that we do as little ++ * as possible in the signal handler (it's probably not safe ++ * to do anything with standard I/O streams in a signal handler - ++ * the ANSI C standard doesn't say it is). ++ */ ++ if (pd) ++ { ++ pcap_breakloop(pd); ++ pcap_close(pd); ++#ifdef HAVE_PCAP_DUMP_FLUSH ++ if (WFileName != NULL) ++ { ++ pcap_dump_flush(dumpinfo.pdd); ++ } ++#endif ++ pd = NULL; ++ } ++#else ++ /* ++ * We don't have "pcap_breakloop()"; this isn't safe, but ++ * it's the best we can do. Print the summary if we're ++ * not reading from a savefile - i.e., if we're doing a ++ * live capture - and exit. ++ */ ++ if (pd != NULL && pcap_file(pd) == NULL) ++ { ++ /* ++ * We got interrupted, so perhaps we didn't ++ * manage to finish a line we were printing. ++ * Print an extra newline, just in case. ++ */ ++ putchar('\n'); ++ (void)fflush(stdout); ++ info(1); ++ } ++ exit_tcpdump(S_SUCCESS); ++#endif ++ ++#if STELLAR_DUMP ++ if (fcode.bf_len != 0) ++ { ++ pcap_freecode(&fcode); ++ memset(&fcode, 0, sizeof(fcode)); ++ } ++ g_stellar_dump_run = 0; ++ if (device != NULL) // for memleak check ++ { ++ free(device); ++ device = NULL; ++ } ++ if (RFileName == NULL && VFileName == NULL) ++ { ++ stellar_dump_ctrllink_keepalive_stop(); ++ stellar_dump_ctrllink_free(); ++ } ++ exit_tcpdump(S_SUCCESS); ++#endif ++} ++ ++/* ++ On windows, we do not use a fork, so we do not care less about ++ waiting a child processes to die ++ */ ++#if defined(HAVE_FORK) || defined(HAVE_VFORK) ++static void ++child_cleanup(int signo _U_) ++{ ++ wait(NULL); ++} ++#endif /* HAVE_FORK && HAVE_VFORK */ ++ ++static void ++info(int verbose) ++{ ++ struct pcap_stat stats; ++ ++ /* ++ * Older versions of libpcap didn't set ps_ifdrop on some ++ * platforms; initialize it to 0 to handle that. ++ */ ++ stats.ps_ifdrop = 0; ++ if (pcap_stats(pd, &stats) < 0) ++ { ++ (void)fprintf(stderr, "pcap_stats: %s\n", pcap_geterr(pd)); ++ infoprint = 0; ++ return; ++ } ++ ++ if (!verbose) ++ fprintf(stderr, "%s: ", program_name); ++ ++ (void)fprintf(stderr, "%u packet%s captured", packets_captured, ++ PLURAL_SUFFIX(packets_captured)); ++ if (!verbose) ++ fputs(", ", stderr); ++ else ++ putc('\n', stderr); ++ (void)fprintf(stderr, "%u packet%s received by filter", stats.ps_recv, ++ PLURAL_SUFFIX(stats.ps_recv)); ++ if (!verbose) ++ fputs(", ", stderr); ++ else ++ putc('\n', stderr); ++ (void)fprintf(stderr, "%u packet%s dropped by kernel", stats.ps_drop, ++ PLURAL_SUFFIX(stats.ps_drop)); ++ if (stats.ps_ifdrop != 0) ++ { ++ if (!verbose) ++ fputs(", ", stderr); ++ else ++ putc('\n', stderr); ++ (void)fprintf(stderr, "%u packet%s dropped by interface\n", ++ stats.ps_ifdrop, PLURAL_SUFFIX(stats.ps_ifdrop)); ++ } ++ else ++ putc('\n', stderr); ++ infoprint = 0; ++} ++ ++#if defined(HAVE_FORK) || defined(HAVE_VFORK) ++#ifdef HAVE_FORK ++#define fork_subprocess() fork() ++#else ++#define fork_subprocess() vfork() ++#endif ++static void ++compress_savefile(const char *filename) ++{ ++ pid_t child; ++ ++ child = fork_subprocess(); ++ if (child == -1) ++ { ++ fprintf(stderr, ++ "compress_savefile: fork failed: %s\n", ++ pcap_strerror(errno)); ++ return; ++ } ++ if (child != 0) ++ { ++ /* Parent process. */ ++ return; ++ } ++ ++ /* ++ * Child process. ++ * Set to lowest priority so that this doesn't disturb the capture. ++ */ ++#ifdef NZERO ++ setpriority(PRIO_PROCESS, 0, NZERO - 1); ++#else ++ setpriority(PRIO_PROCESS, 0, 19); ++#endif ++ if (execlp(zflag, zflag, filename, (char *)NULL) == -1) ++ fprintf(stderr, ++ "compress_savefile: execlp(%s, %s) failed: %s\n", ++ zflag, ++ filename, ++ pcap_strerror(errno)); ++#ifdef HAVE_FORK ++ exit(S_ERR_HOST_PROGRAM); ++#else ++ _exit(S_ERR_HOST_PROGRAM); ++#endif ++} ++#else /* HAVE_FORK && HAVE_VFORK */ ++static void ++compress_savefile(const char *filename) ++{ ++ fprintf(stderr, ++ "compress_savefile failed. Functionality not implemented under your system\n"); ++} ++#endif /* HAVE_FORK && HAVE_VFORK */ ++ ++static void ++dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) ++{ ++ struct dump_info *dump_info; ++ ++ ++packets_captured; ++ ++ ++infodelay; ++ ++ dump_info = (struct dump_info *)user; ++ ++ /* ++ * XXX - this won't force the file to rotate on the specified time ++ * boundary, but it will rotate on the first packet received after the ++ * specified Gflag number of seconds. Note: if a Gflag time boundary ++ * and a Cflag size boundary coincide, the time rotation will occur ++ * first thereby cancelling the Cflag boundary (since the file should ++ * be 0). ++ */ ++ if (Gflag != 0) ++ { ++ /* Check if it is time to rotate */ ++ time_t t; ++ ++ /* Get the current time */ ++ if ((t = time(NULL)) == (time_t)-1) ++ { ++ error("%s: can't get current_time: %s", ++ __func__, pcap_strerror(errno)); ++ } ++ ++ /* If the time is greater than the specified window, rotate */ ++ if (t - Gflag_time >= Gflag) ++ { + #ifdef HAVE_CAPSICUM +- cap_rights_t rights; +- int cansandbox; +-#endif /* HAVE_CAPSICUM */ +- int Oflag = 1; /* run filter code optimizer */ +- int yflag_dlt = -1; +- const char *yflag_dlt_name = NULL; +- int print = 0; ++ FILE *fp; ++ int fd; ++#endif ++ ++ /* Update the Gflag_time */ ++ Gflag_time = t; ++ /* Update Gflag_count */ ++ Gflag_count++; ++ /* ++ * Close the current file and open a new one. ++ */ ++ pcap_dump_close(dump_info->pdd); ++ ++ /* ++ * Compress the file we just closed, if the user asked for it ++ */ ++ if (zflag != NULL) ++ compress_savefile(dump_info->CurrentFileName); ++ ++ /* ++ * Check to see if we've exceeded the Wflag (when ++ * not using Cflag). ++ */ ++ if (Cflag == 0 && Wflag > 0 && Gflag_count >= Wflag) ++ { ++ (void)fprintf(stderr, "Maximum file limit reached: %d\n", ++ Wflag); ++ info(1); ++ exit_tcpdump(S_SUCCESS); ++ /* NOTREACHED */ ++ } ++ if (dump_info->CurrentFileName != NULL) ++ free(dump_info->CurrentFileName); ++ /* Allocate space for max filename + \0. */ ++ dump_info->CurrentFileName = (char *)malloc(PATH_MAX + 1); ++ if (dump_info->CurrentFileName == NULL) ++ error("dump_packet_and_trunc: malloc"); ++ /* ++ * Gflag was set otherwise we wouldn't be here. Reset the count ++ * so multiple files would end with 1,2,3 in the filename. ++ * The counting is handled with the -C flow after this. ++ */ ++ Cflag_count = 0; ++ ++ /* ++ * This is always the first file in the Cflag ++ * rotation: e.g. 0 ++ * We also don't need numbering if Cflag is not set. ++ */ ++ if (Cflag != 0) ++ MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, 0, ++ WflagChars); ++ else ++ MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, 0, 0); ++ ++#ifdef HAVE_LIBCAP_NG ++ capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE); ++ capng_apply(CAPNG_SELECT_BOTH); ++#endif /* HAVE_LIBCAP_NG */ ++#ifdef HAVE_CAPSICUM ++ fd = openat(dump_info->dirfd, ++ dump_info->CurrentFileName, ++ O_CREAT | O_WRONLY | O_TRUNC, 0644); ++ if (fd < 0) ++ { ++ error("unable to open file %s", ++ dump_info->CurrentFileName); ++ } ++ fp = fdopen(fd, "w"); ++ if (fp == NULL) ++ { ++ error("unable to fdopen file %s", ++ dump_info->CurrentFileName); ++ } ++ dump_info->pdd = pcap_dump_fopen(dump_info->pd, fp); ++#else /* !HAVE_CAPSICUM */ ++ dump_info->pdd = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName); ++#endif ++#ifdef HAVE_LIBCAP_NG ++ capng_update(CAPNG_DROP, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE); ++ capng_apply(CAPNG_SELECT_BOTH); ++#endif /* HAVE_LIBCAP_NG */ ++ if (dump_info->pdd == NULL) ++ error("%s", pcap_geterr(pd)); ++#ifdef HAVE_CAPSICUM ++ set_dumper_capsicum_rights(dump_info->pdd); ++#endif ++ } ++ } ++ ++ /* ++ * XXX - this won't prevent capture files from getting ++ * larger than Cflag - the last packet written to the ++ * file could put it over Cflag. ++ */ ++ if (Cflag != 0) ++ { ++#ifdef HAVE_PCAP_DUMP_FTELL64 ++ int64_t size = pcap_dump_ftell64(dump_info->pdd); ++#else ++ /* ++ * XXX - this only handles a Cflag value > 2^31-1 on ++ * LP64 platforms; to handle ILP32 (32-bit UN*X and ++ * Windows) or LLP64 (64-bit Windows) would require ++ * a version of libpcap with pcap_dump_ftell64(). ++ */ ++ long size = pcap_dump_ftell(dump_info->pdd); ++#endif ++ ++ if (size == -1) ++ error("ftell fails on output file"); ++ if (size > Cflag) ++ { ++#ifdef HAVE_CAPSICUM ++ FILE *fp; ++ int fd; ++#endif ++ ++ /* ++ * Close the current file and open a new one. ++ */ ++ pcap_dump_close(dump_info->pdd); ++ ++ /* ++ * Compress the file we just closed, if the user ++ * asked for it. ++ */ ++ if (zflag != NULL) ++ compress_savefile(dump_info->CurrentFileName); ++ ++ Cflag_count++; ++ if (Wflag > 0) ++ { ++ if (Cflag_count >= Wflag) ++ Cflag_count = 0; ++ } ++ if (dump_info->CurrentFileName != NULL) ++ free(dump_info->CurrentFileName); ++ dump_info->CurrentFileName = (char *)malloc(PATH_MAX + 1); ++ if (dump_info->CurrentFileName == NULL) ++ error("%s: malloc", __func__); ++ MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, Cflag_count, WflagChars); ++#ifdef HAVE_LIBCAP_NG ++ capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE); ++ capng_apply(CAPNG_SELECT_BOTH); ++#endif /* HAVE_LIBCAP_NG */ ++#ifdef HAVE_CAPSICUM ++ fd = openat(dump_info->dirfd, dump_info->CurrentFileName, ++ O_CREAT | O_WRONLY | O_TRUNC, 0644); ++ if (fd < 0) ++ { ++ error("unable to open file %s", ++ dump_info->CurrentFileName); ++ } ++ fp = fdopen(fd, "w"); ++ if (fp == NULL) ++ { ++ error("unable to fdopen file %s", ++ dump_info->CurrentFileName); ++ } ++ dump_info->pdd = pcap_dump_fopen(dump_info->pd, fp); ++#else /* !HAVE_CAPSICUM */ ++ dump_info->pdd = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName); ++#endif ++#ifdef HAVE_LIBCAP_NG ++ capng_update(CAPNG_DROP, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE); ++ capng_apply(CAPNG_SELECT_BOTH); ++#endif /* HAVE_LIBCAP_NG */ ++ if (dump_info->pdd == NULL) ++ error("%s", pcap_geterr(pd)); ++#ifdef HAVE_CAPSICUM ++ set_dumper_capsicum_rights(dump_info->pdd); ++#endif ++ } ++ } ++ ++ pcap_dump((u_char *)dump_info->pdd, h, sp); ++#ifdef HAVE_PCAP_DUMP_FLUSH ++ if (Uflag) ++ pcap_dump_flush(dump_info->pdd); ++#endif ++ ++ if (dump_info->ndo != NULL) ++ pretty_print_packet(dump_info->ndo, h, sp, packets_captured); ++ ++ --infodelay; ++ if (infoprint) ++ info(0); ++} ++ ++//#include "stellar/packet_manager.h" ++#include "packet_manager/packet_internal.h" ++#include "packet_manager/packet_parser.h" ++#include "stellar/log.h" ++#include "stellar/exdata.h" ++ ++// fake variable and function ++__thread struct logger *__thread_local_logger = NULL; ++int exdata_set(struct exdata_runtime *rt, int idx, void *ex_ptr) ++{ ++ return 0; ++} ++void *exdata_get(struct exdata_runtime *rt, int idx) ++{ ++ return NULL; ++} ++int log_check_level(struct logger *logger, enum log_level level) ++{ ++ return 0; ++} ++void log_print(struct logger *logger, enum log_level level, const char *module, const char *fmt, ...) ++{ ++ return; ++} ++/* ++ * 0: not match ++ * not 0: match ++ */ ++static int packet_filter_greedy(const struct pcap_pkthdr *h, const u_char *sp) ++{ ++ if (NULL == cmdbuf || fcode.bf_len == 0) ++ { ++ return 1; ++ } ++ ++ struct packet _pkt = {}; ++ if (NULL == packet_parse(&_pkt, (char *)sp, h->caplen)) ++ { ++ return 0; ++ } ++ struct packet *pkt = &_pkt; ++ const char *raw_pkt_hdr = packet_get_raw_data(pkt); ++ int raw_pkt_len = (int)packet_get_raw_len(pkt); ++ int pkt_layer = packet_get_layer_count(pkt); ++ int match = 0; ++ for (int i = 0; i < pkt_layer; i++) ++ { ++ const struct layer *layer = packet_get_layer_by_idx(pkt, i); ++ if (layer->proto == LAYER_PROTO_IPV4 || layer->proto == LAYER_PROTO_IPV6) ++ { ++ int remain_len = raw_pkt_len - (layer->hdr.raw - raw_pkt_hdr); ++ if (remain_len <= 0) ++ { ++ continue; ++ } ++ match = bpf_filter(fcode.bf_insns, (unsigned char *)layer->hdr.raw, remain_len, remain_len); ++ if (match) ++ { ++ break; ++ } ++ } ++ } ++ return match; ++} ++ ++void dump_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) ++{ ++ struct dump_info *dump_info; ++ if ((g_stellar_dump_arg.greedy_seek != 0) && packet_filter_greedy(h, sp) == 0) ++ { ++ return; ++ } ++ ++ ++packets_captured; ++ ++ ++infodelay; ++ ++ dump_info = (struct dump_info *)user; ++ ++ pcap_dump((u_char *)dump_info->pdd, h, sp); ++#ifdef HAVE_PCAP_DUMP_FLUSH ++ if (Uflag) ++ pcap_dump_flush(dump_info->pdd); ++#endif ++ ++ if (dump_info->ndo != NULL) ++ pretty_print_packet(dump_info->ndo, h, sp, packets_captured); ++ ++ --infodelay; ++ if (infoprint) ++ info(0); ++} ++ ++void print_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) ++{ ++ if ((g_stellar_dump_arg.greedy_seek != 0) && packet_filter_greedy(h, sp) == 0) ++ { ++ return; ++ } ++ ++packets_captured; ++ ++ ++infodelay; ++ ++ if (!count_mode) ++ pretty_print_packet((netdissect_options *)user, h, sp, packets_captured); ++ ++ --infodelay; ++ if (infoprint) ++ info(0); ++} ++ ++#ifdef SIGNAL_REQ_INFO ++static void ++requestinfo(int signo _U_) ++{ ++ if (infodelay) ++ ++infoprint; ++ else ++ info(0); ++} ++#endif ++ ++#ifdef SIGNAL_FLUSH_PCAP ++static void ++flushpcap(int signo _U_) ++{ ++ if (pdd != NULL) ++ pcap_dump_flush(pdd); ++} ++#endif ++ ++static void ++print_packets_captured(void) ++{ ++ static u_int prev_packets_captured, first = 1; ++ ++ if (infodelay == 0 && (first || packets_captured != prev_packets_captured)) ++ { ++ fprintf(stderr, "Got %u\r", packets_captured); ++ first = 0; ++ prev_packets_captured = packets_captured; ++ } ++} ++ ++/* ++ * Called once each second in verbose mode while dumping to file ++ */ ++#ifdef _WIN32 ++static void CALLBACK verbose_stats_dump(PVOID param _U_, ++ BOOLEAN timer_fired _U_) ++{ ++ print_packets_captured(); ++} ++#else /* _WIN32 */ ++static void verbose_stats_dump(int sig _U_) ++{ ++ print_packets_captured(); ++} ++#endif /* _WIN32 */ ++ ++DIAG_OFF_DEPRECATION ++static void ++print_version(FILE *f) ++{ ++#ifndef HAVE_PCAP_LIB_VERSION ++#ifdef HAVE_PCAP_VERSION ++ extern char pcap_version[]; ++#else /* HAVE_PCAP_VERSION */ ++ static char pcap_version[] = "unknown"; ++#endif /* HAVE_PCAP_VERSION */ ++#endif /* HAVE_PCAP_LIB_VERSION */ ++ const char *smi_version_string; ++ ++ (void)fprintf(f, "%s version " PACKAGE_VERSION "\n", program_name); ++#ifdef HAVE_PCAP_LIB_VERSION ++ (void)fprintf(f, "%s\n", pcap_lib_version()); ++#else /* HAVE_PCAP_LIB_VERSION */ ++ (void)fprintf(f, "libpcap version %s\n", pcap_version); ++#endif /* HAVE_PCAP_LIB_VERSION */ ++ ++#if defined(HAVE_LIBCRYPTO) && defined(SSLEAY_VERSION) ++ (void)fprintf(f, "%s\n", SSLeay_version(SSLEAY_VERSION)); ++#endif ++ ++ smi_version_string = nd_smi_version_string(); ++ if (smi_version_string != NULL) ++ (void)fprintf(f, "SMI-library: %s\n", smi_version_string); ++ ++#if defined(__SANITIZE_ADDRESS__) ++ (void)fprintf(f, "Compiled with AddressSanitizer/GCC.\n"); ++#elif defined(__has_feature) ++#if __has_feature(address_sanitizer) ++ (void)fprintf(f, "Compiled with AddressSanitizer/Clang.\n"); ++#elif __has_feature(memory_sanitizer) ++ (void)fprintf(f, "Compiled with MemorySanitizer/Clang.\n"); ++#endif ++#endif /* __SANITIZE_ADDRESS__ or __has_feature */ ++} ++DIAG_ON_DEPRECATION ++ ++static void ++print_usage(FILE *f) ++{ ++ print_version(f); ++ (void)fprintf(f, ++ "Usage: %s [-Abd" D_FLAG "efhH" I_FLAG J_FLAG "KlLnNOpqStu" U_FLAG "vxX#]" B_FLAG_USAGE " [ -c count ] [--count]\n", program_name); ++ (void)fprintf(f, ++ "\t\t[ -C file_size ] [ -E algo:secret ] [ -F file ] [ -G seconds ]\n"); ++#if STELLAR_DUMP == 0 ++ (void)fprintf(f, "\t\t[ -i interface ]" IMMEDIATE_MODE_USAGE j_FLAG_USAGE "\n"); ++#endif ++#ifdef HAVE_PCAP_FINDALLDEVS_EX ++ (void)fprintf(f, ++ "\t\t" LIST_REMOTE_INTERFACES_USAGE "\n"); ++#endif ++#ifdef USE_LIBSMI ++ (void)fprintf(f, ++ "\t\t" m_FLAG_USAGE "\n"); ++#endif ++ ++ (void)fprintf(f, "\t\t[ -M secret ] [ --number ] [ --print ]" Q_FLAG_USAGE "\n"); ++ (void)fprintf(f, ++ "\t\t[ -r file ] [ -s snaplen ] [ -T type ] [ --version ]\n"); ++ (void)fprintf(f, ++ "\t\t[ -V file ] [ -w file ] [ -W filecount ] [ -y datalinktype ]\n"); ++#ifdef HAVE_PCAP_SET_TSTAMP_PRECISION ++ (void)fprintf(f, ++ "\t\t[ --time-stamp-precision precision ] [ --micro ] [ --nano ]\n"); ++#endif ++ (void)fprintf(f, ++ "\t\t[ -z postrotate-command ] [ -Z user ] [ expression ]\n"); ++#if STELLAR_DUMP ++ (void)fprintf(f, "\n --- \033[1m%s %s ---\033[0m\n", "The following options are customized for", PROGRAM_NAME); ++ (void)fprintf(f, "\t\t[ -i ] not interface, is stellar monitor ip (default: 127.0.0.1)\n"); ++ (void)fprintf(f, "\t\t[ -P ] stellar monitor port (default: 80)\n"); ++ (void)fprintf(f, "\t\t[ -g ] enable greedy seek to most inner IP layer for tunnel protocol (default: disable)\n"); ++ (void)fprintf(f, "\t\t[ -k ] which threads enable packet dump, support comma-separated values, for example: 1,3,5 (default: all threads)\n"); ++#endif ++} + +- netdissect_options Ndo; +- netdissect_options *ndo = &Ndo; ++// static netdissect_options Ndo; ++// static netdissect_options *ndo = &Ndo; ++// static struct dump_info dumpinfo; ++// u_char *pcap_userdata; ++// static char *cp, *infile, *cmdbuf, *device, *RFileName, *VFileName, *WFileName; ++// pcap_handler callback; ++// static int print = 0; ++// static FILE *VFile; ++// static char VFileLine[PATH_MAX + 1]; ++// static char ebuf[PCAP_ERRBUF_SIZE]; ++// int dlt, i; ++// static char *endp; ++// static int cnt, op; ++// static bpf_u_int32 localnet = 0, netmask = 0; ++ ++// static int Oflag = 1; /* run filter code optimizer */ ++// static int yflag_dlt = -1; ++// static const char *yflag_dlt_name = NULL; ++ ++// static const char *dlt_name; ++// static struct bpf_program fcode; ++// #ifndef _WIN32 ++// static void (*oldhandler)(int); ++// #endif ++ ++// static const char *username = NULL; ++// #ifndef _WIN32 ++// static const char *chroot_dir = NULL; ++// #endif ++// static char *ret = NULL; ++// static char *end; ++// #ifdef HAVE_PCAP_FINDALLDEVS ++// static pcap_if_t *devlist; ++// static long devnum; ++// #endif ++// static int status; ++ ++// #ifdef HAVE_CAPSICUM ++// static cap_rights_t rights; ++// static int cansandbox; ++// #endif /* HAVE_CAPSICUM */ + ++// static int argc; ++// static char **argv; ++ ++int tcpdump_parse_args(int f_argc, char **f_argv) ++{ ++ argc = f_argc; ++ argv = f_argv; + /* + * Initialize the netdissect code. + */ +@@ -1558,9 +2396,9 @@ + if (abort_on_misalignment(ebuf, sizeof(ebuf)) < 0) + error("%s", ebuf); + +- while ( +- (op = getopt_long(argc, argv, SHORTOPTS, longopts, NULL)) != -1) +- switch (op) { ++ while ((op = getopt_long(argc, argv, SHORTOPTS, longopts, NULL)) != -1) ++ switch (op) ++ { + + case 'a': + /* compatibility for old -a */ +@@ -1576,7 +2414,7 @@ + + #if defined(HAVE_PCAP_CREATE) || defined(_WIN32) + case 'B': +- Bflag = atoi(optarg)*1024; ++ Bflag = atoi(optarg) * 1024; + if (Bflag <= 0) + error("invalid packet buffer size %s", optarg); + break; +@@ -1586,6 +2424,7 @@ + cnt = atoi(optarg); + if (cnt <= 0) + error("invalid packet count %s", optarg); ++ g_stellar_dump_arg.expect_packet_count = cnt; + break; + + case 'C': +@@ -1595,12 +2434,11 @@ + #else + Cflag = strtol(optarg, &endp, 10); + #endif +- if (endp == optarg || *endp != '\0' || errno != 0 +- || Cflag <= 0) ++ if (endp == optarg || *endp != '\0' || errno != 0 || Cflag <= 0) + error("invalid file size %s", optarg); +- /* +- * Will multiplying it by 1000000 overflow? +- */ ++ /* ++ * Will multiplying it by 1000000 overflow? ++ */ + #ifdef HAVE_PCAP_DUMP_FTELL64 + if (Cflag > INT64_T_CONSTANT(0x7fffffffffffffff) / 1000000) + #else +@@ -1649,18 +2487,24 @@ + infile = optarg; + break; + ++#if STELLAR_DUMP ++ case 'g': ++ g_stellar_dump_arg.greedy_seek = 1; ++ break; ++#endif + case 'G': + Gflag = atoi(optarg); + if (Gflag < 0) + error("invalid number of seconds %s", optarg); + +- /* We will create one file initially. */ +- Gflag_count = 0; ++ /* We will create one file initially. */ ++ Gflag_count = 0; + + /* Grab the current time for rotation use. */ +- if ((Gflag_time = time(NULL)) == (time_t)-1) { ++ if ((Gflag_time = time(NULL)) == (time_t)-1) ++ { + error("%s: can't get current time: %s", +- __func__, pcap_strerror(errno)); ++ __func__, pcap_strerror(errno)); + } + break; + +@@ -1674,8 +2518,20 @@ + break; + + case 'i': ++ { ++#if STELLAR_DUMP ++ uint32_t tmp_ip; ++ g_stellar_dump_arg.stellar_server_ip = optarg; ++ if (inet_pton(AF_INET, g_stellar_dump_arg.stellar_server_ip, &tmp_ip) != 1) ++ { ++ printf("invalid ip address %s\n", g_stellar_dump_arg.stellar_server_ip); ++ exit(1); ++ } ++#else + device = optarg; +- break; ++#endif ++ } ++ break; + + #ifdef HAVE_PCAP_CREATE + case 'I': +@@ -1717,17 +2573,38 @@ + lflag = 1; + break; + ++#if STELLAR_DUMP ++ case 'k': ++ { ++ const char *ptr = optarg; ++ size_t len = strlen(optarg); ++ for (i = 0; i < (int)len; i++) ++ { ++ if (isxdigit(ptr[i]) == 0 && ptr[i] != ',') ++ { ++ printf("invalid threads expression: %s\n", optarg); ++ exit(1); ++ } ++ } ++ g_stellar_dump_arg.thread_enable_expression = optarg; ++ } ++ break; ++#endif ++ + case 'K': + ++ndo->ndo_Kflag; + break; + + case 'm': +- if (nd_have_smi_support()) { ++ if (nd_have_smi_support()) ++ { + if (nd_load_smi_module(optarg, ebuf, sizeof(ebuf)) == -1) + error("%s", ebuf); +- } else { ++ } ++ else ++ { + (void)fprintf(stderr, "%s: ignoring option `-m %s' ", +- program_name, optarg); ++ program_name, optarg); + (void)fprintf(stderr, "(no libsmi support)\n"); + } + break; +@@ -1756,6 +2633,19 @@ + ++pflag; + break; + ++#if STELLAR_DUMP ++ case 'P': ++ { ++ int tmp_port = atoi(optarg); ++ if (tmp_port <= 0 || tmp_port > 65535) ++ { ++ printf("invalid port %s\n", optarg); ++ exit(1); ++ } ++ g_stellar_dump_arg.stellar_server_port_host_order = (unsigned short)tmp_port; ++ } ++ break; ++#endif + case 'q': + ++ndo->ndo_qflag; + ++ndo->ndo_suppress_default_print; +@@ -1763,6 +2653,7 @@ + + #ifdef HAVE_PCAP_SETDIRECTION + case 'Q': ++#if STELLAR_DUMP == 0 + if (ascii_strcasecmp(optarg, "in") == 0) + Qflag = PCAP_D_IN; + else if (ascii_strcasecmp(optarg, "out") == 0) +@@ -1771,6 +2662,10 @@ + Qflag = PCAP_D_INOUT; + else + error("unknown capture direction `%s'", optarg); ++#else ++ fprintf(stderr, "unsupport '-Q' option for %s\n", PROGRAM_NAME); ++ return -1; ++#endif + break; + #endif /* HAVE_PCAP_SETDIRECTION */ + +@@ -1780,10 +2675,9 @@ + + case 's': + ndo->ndo_snaplen = (int)strtol(optarg, &end, 0); +- if (optarg == end || *end != '\0' +- || ndo->ndo_snaplen < 0 || ndo->ndo_snaplen > MAXIMUM_SNAPLEN) ++ if (optarg == end || *end != '\0' || ndo->ndo_snaplen < 0 || ndo->ndo_snaplen > MAXIMUM_SNAPLEN) + error("invalid snaplen %s (must be >= 0 and <= %d)", +- optarg, MAXIMUM_SNAPLEN); ++ optarg, MAXIMUM_SNAPLEN); + break; + + case 'S': +@@ -1888,11 +2782,11 @@ + + #ifdef HAVE_PCAP_SET_PARSER_DEBUG + case 'Y': +- { ++ { + /* Undocumented flag */ + pcap_set_parser_debug(1); +- } +- break; ++ } ++ break; + #endif + case 'z': + zflag = optarg; +@@ -1970,15 +2864,31 @@ + #endif + + #if defined(DLT_LINUX_SLL2) && defined(HAVE_PCAP_SET_DATALINK) +-/* Set default linktype DLT_LINUX_SLL2 when capturing on the "any" device */ +- if (device != NULL && +- strncmp (device, "any", strlen("any")) == 0 +- && yflag_dlt == -1) +- yflag_dlt = DLT_LINUX_SLL2; ++ /* Set default linktype DLT_LINUX_SLL2 when capturing on the "any" device */ ++ if (device != NULL && ++ strncmp(device, "any", strlen("any")) == 0 && yflag_dlt == -1) ++ yflag_dlt = DLT_LINUX_SLL2; + #endif + +- switch (ndo->ndo_tflag) { ++#if STELLAR_DUMP ++ /* set default value */ ++ if (g_stellar_dump_arg.stellar_server_ip == NULL) ++ { ++ g_stellar_dump_arg.stellar_server_ip = CTRLLINK_DEFAULT_IP; ++ } ++ if (g_stellar_dump_arg.stellar_server_port_host_order == 0) ++ { ++ g_stellar_dump_arg.stellar_server_port_host_order = CTRLLINK_DEFAULT_PORT; ++ } ++#endif ++ return 0; ++} + ++int tcpdump_prepare(void) ++{ ++ char *ret; ++ switch (ndo->ndo_tflag) ++ { + case 0: /* Default */ + case 1: /* No time stamp */ + case 2: /* Unix timeval style */ +@@ -2013,7 +2923,8 @@ + + #ifdef WITH_CHROOT + /* if run as root, prepare for chrooting */ +- if (getuid() == 0 || geteuid() == 0) { ++ if (getuid() == 0 || geteuid() == 0) ++ { + /* future extensibility for cmd-line arguments */ + if (!chroot_dir) + chroot_dir = WITH_CHROOT; +@@ -2022,14 +2933,16 @@ + + #ifdef WITH_USER + /* if run as root, prepare for dropping root privileges */ +- if (getuid() == 0 || geteuid() == 0) { ++ if (getuid() == 0 || geteuid() == 0) ++ { + /* Run with '-Z root' to restore old behaviour */ + if (!username) + username = WITH_USER; + } + #endif + +- if (RFileName != NULL || VFileName != NULL) { ++ if (RFileName != NULL || VFileName != NULL) ++ { + /* + * If RFileName is non-null, it's the pathname of a + * savefile to read. If VFileName is non-null, it's +@@ -2049,10 +2962,11 @@ + * people's trace files (especially if we're set-UID + * root). + */ +- if (setgid(getgid()) != 0 || setuid(getuid()) != 0 ) ++ if (setgid(getgid()) != 0 || setuid(getuid()) != 0) + fprintf(stderr, "Warning: setgid/setuid failed !\n"); + #endif /* _WIN32 */ +- if (VFileName != NULL) { ++ if (VFileName != NULL) ++ { + if (VFileName[0] == '-' && VFileName[1] == '\0') + VFile = stdin; + else +@@ -2069,7 +2983,7 @@ + + #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION + pd = pcap_open_offline_with_tstamp_precision(RFileName, +- ndo->ndo_tstamp_precision, ebuf); ++ ndo->ndo_tstamp_precision, ebuf); + #else + pd = pcap_open_offline(RFileName, ebuf); + #endif +@@ -2079,25 +2993,31 @@ + #ifdef HAVE_CAPSICUM + cap_rights_init(&rights, CAP_READ); + if (cap_rights_limit(fileno(pcap_file(pd)), &rights) < 0 && +- errno != ENOSYS) { ++ errno != ENOSYS) ++ { + error("unable to limit pcap descriptor"); + } + #endif + dlt = pcap_datalink(pd); + dlt_name = pcap_datalink_val_to_name(dlt); + fprintf(stderr, "reading from file %s", RFileName); +- if (dlt_name == NULL) { +- fprintf(stderr, ", link-type %u", dlt); +- } else { ++ if (dlt_name == NULL) ++ { ++ fprintf(stderr, ", link-type %d", dlt); ++ } ++ else ++ { + fprintf(stderr, ", link-type %s (%s)", dlt_name, +- pcap_datalink_val_to_description(dlt)); ++ pcap_datalink_val_to_description(dlt)); + } + fprintf(stderr, ", snapshot length %d\n", pcap_snapshot(pd)); + #ifdef DLT_LINUX_SLL2 + if (dlt == DLT_LINUX_SLL2) + fprintf(stderr, "Warning: interface names might be incorrect\n"); + #endif +- } else if (dflag && !device) { ++ } ++ else if (dflag && !device) ++ { + int dump_dlt = DLT_EN10MB; + /* + * We're dumping the compiled code without an explicit +@@ -2119,12 +3039,16 @@ + dump_dlt = yflag_dlt; + else + fprintf(stderr, "Warning: assuming Ethernet\n"); +- pd = pcap_open_dead(dump_dlt, ndo->ndo_snaplen); +- } else { ++ pd = pcap_open_dead(dump_dlt, ndo->ndo_snaplen); ++ } ++ else ++ { + /* + * We're doing a live capture. + */ +- if (device == NULL) { ++ if (device == NULL) ++ { ++#if STELLAR_DUMP == 0 + /* + * No interface was specified. Pick one. + */ +@@ -2148,13 +3072,21 @@ + if (device == NULL) + error("%s", ebuf); + #endif ++#else ++ device = strdup("lo"); ++#endif + } + + /* + * Try to open the interface with the specified name. + */ ++#if STELLAR_DUMP == 0 + pd = open_interface(device, ndo, ebuf); +- if (pd == NULL) { ++#else ++ pd = pcap_open_dead(DLT_EN10MB, 65535); ++#endif ++ if (pd == NULL) ++ { + /* + * That failed. If we can get a list of + * interfaces, and the interface name +@@ -2164,7 +3096,8 @@ + */ + #ifdef HAVE_PCAP_FINDALLDEVS + devnum = parse_interface_number(device); +- if (devnum == -1) { ++ if (devnum == -1) ++ { + /* + * It's not a number; just report + * the open error and fail. +@@ -2184,7 +3117,7 @@ + pd = open_interface(device, ndo, ebuf); + if (pd == NULL) + error("%s", ebuf); +-#else /* HAVE_PCAP_FINDALLDEVS */ ++#else /* HAVE_PCAP_FINDALLDEVS */ + /* + * We can't get a list of interfaces; just + * fail. +@@ -2202,14 +3135,16 @@ + fprintf(stderr, "Warning: setgid/setuid failed !\n"); + #endif /* _WIN32 */ + #if !defined(HAVE_PCAP_CREATE) && defined(_WIN32) +- if(Bflag != 0) +- if(pcap_setbuff(pd, Bflag)==-1){ ++ if (Bflag != 0) ++ if (pcap_setbuff(pd, Bflag) == -1) ++ { + error("%s", pcap_geterr(pd)); + } + #endif /* !defined(HAVE_PCAP_CREATE) && defined(_WIN32) */ + if (Lflag) + show_dlts_and_exit(pd, device); +- if (yflag_dlt >= 0) { ++ if (yflag_dlt >= 0) ++ { + #ifdef HAVE_PCAP_SET_DATALINK + if (pcap_set_datalink(pd, yflag_dlt) < 0) + error("%s", pcap_geterr(pd)); +@@ -2219,31 +3154,36 @@ + * data link type, so we only let them + * set it to what it already is. + */ +- if (yflag_dlt != pcap_datalink(pd)) { ++ if (yflag_dlt != pcap_datalink(pd)) ++ { + error("%s is not one of the DLTs supported by this device\n", +- yflag_dlt_name); ++ yflag_dlt_name); + } + #endif + (void)fprintf(stderr, "%s: data link type %s\n", +- program_name, +- pcap_datalink_val_to_name(yflag_dlt)); ++ program_name, ++ pcap_datalink_val_to_name(yflag_dlt)); + (void)fflush(stderr); + } + i = pcap_snapshot(pd); +- if (ndo->ndo_snaplen < i) { ++ if (ndo->ndo_snaplen < i) ++ { + if (ndo->ndo_snaplen != 0) + warning("snaplen raised from %d to %d", ndo->ndo_snaplen, i); + ndo->ndo_snaplen = i; +- } else if (ndo->ndo_snaplen > i) { ++ } ++ else if (ndo->ndo_snaplen > i) ++ { + warning("snaplen lowered from %d to %d", ndo->ndo_snaplen, i); + ndo->ndo_snaplen = i; + } +- if(ndo->ndo_fflag != 0) { +- if (pcap_lookupnet(device, &localnet, &netmask, ebuf) < 0) { +- warning("foreign (-f) flag used but: %s", ebuf); +- } +- } +- ++ if (ndo->ndo_fflag != 0) ++ { ++ if (pcap_lookupnet(device, &localnet, &netmask, ebuf) < 0) ++ { ++ warning("foreign (-f) flag used but: %s", ebuf); ++ } ++ } + } + if (infile) + cmdbuf = read_infile(infile); +@@ -2253,9 +3193,32 @@ + #ifdef HAVE_PCAP_SET_OPTIMIZER_DEBUG + pcap_set_optimizer_debug(dflag); + #endif +- if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0) +- error("%s", pcap_geterr(pd)); +- if (dflag) { ++ ++ if (cmdbuf != NULL) ++ { ++ int compile_ret; ++ if (RFileName != NULL) ++ { ++ if (g_stellar_dump_arg.greedy_seek == 0) ++ { ++ compile_ret = pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask); ++ } ++ else ++ { ++ compile_ret = pcap_compile_nopcap(65535, DLT_RAW, &fcode, cmdbuf, Oflag, netmask); ++ } ++ } ++ else ++ { ++ compile_ret = pcap_compile_nopcap(65535, DLT_RAW, &fcode, cmdbuf, Oflag, netmask); ++ } ++ if (compile_ret < 0) ++ { ++ error("pcap_compile: %s", pcap_geterr(pd)); ++ } ++ } ++ if (dflag) ++ { + bpf_dump(&fcode, dflag); + pcap_close(pd); + free(cmdbuf); +@@ -2263,10 +3226,14 @@ + exit_tcpdump(S_SUCCESS); + } + ++#if STELLAR_DUMP ++ g_stellar_dump_arg.bpf = cmdbuf; ++#endif ++ + #ifdef HAVE_CASPER + if (!ndo->ndo_nflag) + capdns = capdns_setup(); +-#endif /* HAVE_CASPER */ ++#endif /* HAVE_CASPER */ + + init_print(ndo, localnet, netmask); + +@@ -2303,52 +3270,60 @@ + * savefile doesn't handle the general case. + */ + +- if (getuid() == 0 || geteuid() == 0) { ++ if (getuid() == 0 || geteuid() == 0) ++ { + #ifdef HAVE_LIBCAP_NG + /* Initialize capng */ + capng_clear(CAPNG_SELECT_BOTH); +- if (username) { +-DIAG_OFF_ASSIGN_ENUM ++ if (username) ++ { ++ DIAG_OFF_ASSIGN_ENUM + capng_updatev( + CAPNG_ADD, + CAPNG_PERMITTED | CAPNG_EFFECTIVE, + CAP_SETUID, + CAP_SETGID, + -1); +-DIAG_ON_ASSIGN_ENUM ++ DIAG_ON_ASSIGN_ENUM + } +- if (chroot_dir) { +-DIAG_OFF_ASSIGN_ENUM ++ if (chroot_dir) ++ { ++ DIAG_OFF_ASSIGN_ENUM + capng_update( + CAPNG_ADD, + CAPNG_PERMITTED | CAPNG_EFFECTIVE, +- CAP_SYS_CHROOT +- ); +-DIAG_ON_ASSIGN_ENUM ++ CAP_SYS_CHROOT); ++ DIAG_ON_ASSIGN_ENUM + } + +- if (WFileName) { +-DIAG_OFF_ASSIGN_ENUM ++ if (WFileName) ++ { ++ DIAG_OFF_ASSIGN_ENUM + capng_update( + CAPNG_ADD, + CAPNG_PERMITTED | CAPNG_EFFECTIVE, +- CAP_DAC_OVERRIDE +- ); +-DIAG_ON_ASSIGN_ENUM ++ CAP_DAC_OVERRIDE); ++ DIAG_ON_ASSIGN_ENUM + } + capng_apply(CAPNG_SELECT_BOTH); + #endif /* HAVE_LIBCAP_NG */ + if (username || chroot_dir) + droproot(username, chroot_dir); +- + } + #endif /* _WIN32 */ + +- if (pcap_setfilter(pd, &fcode) < 0) +- error("%s", pcap_geterr(pd)); ++ if (RFileName) ++ { ++ if ((pd != NULL) && (cmdbuf != NULL) && (0 == g_stellar_dump_arg.greedy_seek) && pcap_setfilter(pd, &fcode) < 0) ++ { ++ error("%s", pcap_geterr(pd)); ++ return -1; ++ } ++ } + #ifdef HAVE_CAPSICUM +- if (RFileName == NULL && VFileName == NULL && pcap_fileno(pd) != -1) { +- static const unsigned long cmds[] = { BIOCGSTATS, BIOCROTZBUF }; ++ if (RFileName == NULL && VFileName == NULL && pcap_fileno(pd) != -1) ++ { ++ static const unsigned long cmds[] = {BIOCGSTATS, BIOCROTZBUF}; + + /* + * The various libpcap devices use a combination of +@@ -2357,16 +3332,20 @@ + */ + cap_rights_init(&rights, CAP_IOCTL, CAP_READ, CAP_EVENT); + if (cap_rights_limit(pcap_fileno(pd), &rights) < 0 && +- errno != ENOSYS) { ++ errno != ENOSYS) ++ { + error("unable to limit pcap descriptor"); + } + if (cap_ioctls_limit(pcap_fileno(pd), cmds, +- sizeof(cmds) / sizeof(cmds[0])) < 0 && errno != ENOSYS) { ++ sizeof(cmds) / sizeof(cmds[0])) < 0 && ++ errno != ENOSYS) ++ { + error("unable to limit ioctls on pcap descriptor"); + } + } + #endif +- if (WFileName) { ++ if (WFileName) ++ { + /* Do not exceed the default PATH_MAX for files. */ + dumpinfo.CurrentFileName = (char *)malloc(PATH_MAX + 1); + +@@ -2375,9 +3354,9 @@ + + /* We do not need numbering for dumpfiles if Cflag isn't set. */ + if (Cflag != 0) +- MakeFilename(dumpinfo.CurrentFileName, WFileName, 0, WflagChars); ++ MakeFilename(dumpinfo.CurrentFileName, WFileName, 0, WflagChars); + else +- MakeFilename(dumpinfo.CurrentFileName, WFileName, 0, 0); ++ MakeFilename(dumpinfo.CurrentFileName, WFileName, 0, 0); + + pdd = pcap_dump_open(pd, dumpinfo.CurrentFileName); + #ifdef HAVE_LIBCAP_NG +@@ -2387,10 +3366,8 @@ + */ + capng_update( + CAPNG_DROP, +- (Cflag || Gflag ? 0 : CAPNG_PERMITTED) +- | CAPNG_EFFECTIVE, +- CAP_DAC_OVERRIDE +- ); ++ (Cflag || Gflag ? 0 : CAPNG_PERMITTED) | CAPNG_EFFECTIVE, ++ CAP_DAC_OVERRIDE); + capng_apply(CAPNG_SELECT_BOTH); + #endif /* HAVE_LIBCAP_NG */ + if (pdd == NULL) +@@ -2398,7 +3375,8 @@ + #ifdef HAVE_CAPSICUM + set_dumper_capsicum_rights(pdd); + #endif +- if (Cflag != 0 || Gflag != 0) { ++ if (Cflag != 0 || Gflag != 0) ++ { + #ifdef HAVE_CAPSICUM + /* + * basename() and dirname() may modify their input buffer +@@ -2409,71 +3387,83 @@ + */ + char *WFileName_copy; + +- if ((WFileName_copy = strdup(WFileName)) == NULL) { ++ if ((WFileName_copy = strdup(WFileName)) == NULL) ++ { + error("Unable to allocate memory for file %s", +- WFileName); ++ WFileName); + } + DIAG_OFF_C11_EXTENSIONS + dumpinfo.WFileName = strdup(basename(WFileName_copy)); + DIAG_ON_C11_EXTENSIONS +- if (dumpinfo.WFileName == NULL) { ++ if (dumpinfo.WFileName == NULL) ++ { + error("Unable to allocate memory for file %s", +- WFileName); ++ WFileName); + } + free(WFileName_copy); + +- if ((WFileName_copy = strdup(WFileName)) == NULL) { ++ if ((WFileName_copy = strdup(WFileName)) == NULL) ++ { + error("Unable to allocate memory for file %s", +- WFileName); ++ WFileName); + } + DIAG_OFF_C11_EXTENSIONS + char *WFileName_dirname = dirname(WFileName_copy); + DIAG_ON_C11_EXTENSIONS + dumpinfo.dirfd = open(WFileName_dirname, +- O_DIRECTORY | O_RDONLY); +- if (dumpinfo.dirfd < 0) { ++ O_DIRECTORY | O_RDONLY); ++ if (dumpinfo.dirfd < 0) ++ { + error("unable to open directory %s", +- WFileName_dirname); ++ WFileName_dirname); + } + free(WFileName_dirname); + free(WFileName_copy); + + cap_rights_init(&rights, CAP_CREATE, CAP_FCNTL, +- CAP_FTRUNCATE, CAP_LOOKUP, CAP_SEEK, CAP_WRITE); ++ CAP_FTRUNCATE, CAP_LOOKUP, CAP_SEEK, CAP_WRITE); + if (cap_rights_limit(dumpinfo.dirfd, &rights) < 0 && +- errno != ENOSYS) { ++ errno != ENOSYS) ++ { + error("unable to limit directory rights"); + } + if (cap_fcntls_limit(dumpinfo.dirfd, CAP_FCNTL_GETFL) < 0 && +- errno != ENOSYS) { ++ errno != ENOSYS) ++ { + error("unable to limit dump descriptor fcntls"); + } +-#else /* !HAVE_CAPSICUM */ ++#else /* !HAVE_CAPSICUM */ + dumpinfo.WFileName = WFileName; + #endif + callback = dump_packet_and_trunc; + dumpinfo.pd = pd; + dumpinfo.pdd = pdd; + pcap_userdata = (u_char *)&dumpinfo; +- } else { ++ } ++ else ++ { + callback = dump_packet; + dumpinfo.WFileName = WFileName; + dumpinfo.pd = pd; + dumpinfo.pdd = pdd; + pcap_userdata = (u_char *)&dumpinfo; + } +- if (print) { ++ if (print) ++ { + dlt = pcap_datalink(pd); + ndo->ndo_if_printer = get_if_printer(dlt); + dumpinfo.ndo = ndo; +- } else ++ } ++ else + dumpinfo.ndo = NULL; + + #ifdef HAVE_PCAP_DUMP_FLUSH + if (Uflag) + pcap_dump_flush(pdd); + #endif +- } else { ++ } ++ else ++ { + dlt = pcap_datalink(pd); + ndo->ndo_if_printer = get_if_printer(dlt); + callback = print_packet; +@@ -2492,7 +3482,8 @@ + (void)setsignal(SIGNAL_FLUSH_PCAP, flushpcap); + #endif + +- if (ndo->ndo_vflag > 0 && WFileName && RFileName == NULL && !print) { ++ if (ndo->ndo_vflag > 0 && WFileName && RFileName == NULL && !print) ++ { + /* + * When capturing to a file, if "--print" wasn't specified, + *"-v" means tcpdump should, once per second, +@@ -2511,10 +3502,10 @@ + * that printing the stats could be a "long wait". + */ + CreateTimerQueueTimer(&timer_handle, NULL, +- verbose_stats_dump, NULL, 1000, 1000, +- WT_EXECUTEDEFAULT|WT_EXECUTELONGFUNCTION); ++ verbose_stats_dump, NULL, 1000, 1000, ++ WT_EXECUTEDEFAULT | WT_EXECUTELONGFUNCTION); + setvbuf(stderr, NULL, _IONBF, 0); +-#else /* _WIN32 */ ++#else /* _WIN32 */ + /* + * Assume this is UN*X, and that it has setitimer(); that + * dates back to UNIX 95. +@@ -2529,30 +3520,38 @@ + #endif /* _WIN32 */ + } + +- if (RFileName == NULL) { ++#if 0 == STELLAR_DUMP ++ if (RFileName == NULL) ++ { + /* + * Live capture (if -V was specified, we set RFileName + * to a file from the -V file). Print a message to + * the standard error on UN*X. + */ +- if (!ndo->ndo_vflag && !WFileName) { ++ if (!ndo->ndo_vflag && !WFileName) ++ { + (void)fprintf(stderr, +- "%s: verbose output suppressed, use -v[v]... for full protocol decode\n", +- program_name); +- } else ++ "%s: verbose output suppressed, use -v[v]... for full protocol decode\n", ++ program_name); ++ } ++ else + (void)fprintf(stderr, "%s: ", program_name); + dlt = pcap_datalink(pd); + dlt_name = pcap_datalink_val_to_name(dlt); + (void)fprintf(stderr, "listening on %s", device); +- if (dlt_name == NULL) { ++ if (dlt_name == NULL) ++ { + (void)fprintf(stderr, ", link-type %u", dlt); +- } else { ++ } ++ else ++ { + (void)fprintf(stderr, ", link-type %s (%s)", dlt_name, +- pcap_datalink_val_to_description(dlt)); ++ pcap_datalink_val_to_description(dlt)); + } + (void)fprintf(stderr, ", snapshot length %d bytes\n", ndo->ndo_snaplen); + (void)fflush(stderr); + } ++#endif + + #ifdef HAVE_CAPSICUM + cansandbox = (VFileName == NULL && zflag == NULL); +@@ -2563,16 +3562,24 @@ + #endif /* HAVE_CASPER */ + if (cansandbox && cap_enter() < 0 && errno != ENOSYS) + error("unable to enter the capability mode"); +-#endif /* HAVE_CAPSICUM */ ++#endif /* HAVE_CAPSICUM */ ++ return 0; ++} + +- do { ++void tcpdump_run(void) ++{ ++ char *ret = NULL; ++ do ++ { + status = pcap_loop(pd, cnt, callback, pcap_userdata); +- if (WFileName == NULL) { ++ if (WFileName == NULL) ++ { + /* + * We're printing packets. Flush the printed output, + * so it doesn't get intermingled with error output. + */ +- if (status == -2) { ++ if (status == -2) ++ { + /* + * We got interrupted, so perhaps we didn't + * manage to finish a line we were printing. +@@ -2582,7 +3589,8 @@ + } + (void)fflush(stdout); + } +- if (status == -2) { ++ if (status == -2) ++ { + /* + * We got interrupted. If we are reading multiple + * files (via -V) set these so that we stop. +@@ -2590,24 +3598,32 @@ + VFileName = NULL; + ret = NULL; + } +- if (status == -1) { ++ if (status == -1) ++ { + /* + * Error. Report it. + */ + (void)fprintf(stderr, "%s: pcap_loop: %s\n", +- program_name, pcap_geterr(pd)); ++ program_name, pcap_geterr(pd)); + } +- if (RFileName == NULL) { ++ if (RFileName == NULL) ++ { + /* + * We're doing a live capture. Report the capture + * statistics. + */ + info(1); + } +- pcap_close(pd); +- if (VFileName != NULL) { ++ if (pd) ++ { ++ pcap_close(pd); ++ pd = NULL; ++ } ++ if (VFileName != NULL) ++ { + ret = get_next_file(VFile, VFileLine); +- if (ret) { ++ if (ret) ++ { + int new_dlt; + + RFileName = VFileLine; +@@ -2617,18 +3633,22 @@ + #ifdef HAVE_CAPSICUM + cap_rights_init(&rights, CAP_READ); + if (cap_rights_limit(fileno(pcap_file(pd)), +- &rights) < 0 && errno != ENOSYS) { ++ &rights) < 0 && ++ errno != ENOSYS) ++ { + error("unable to limit pcap descriptor"); + } + #endif + new_dlt = pcap_datalink(pd); +- if (new_dlt != dlt) { ++ if (new_dlt != dlt) ++ { + /* + * The new file has a different + * link-layer header type from the + * previous one. + */ +- if (WFileName != NULL) { ++ if (WFileName != NULL) ++ { + /* + * We're writing raw packets + * that match the filter to +@@ -2667,586 +3687,86 @@ + */ + dlt_name = pcap_datalink_val_to_name(dlt); + fprintf(stderr, "reading from file %s", RFileName); +- if (dlt_name == NULL) { +- fprintf(stderr, ", link-type %u", dlt); +- } else { ++ if (dlt_name == NULL) ++ { ++ fprintf(stderr, ", link-type %d", dlt); ++ } ++ else ++ { + fprintf(stderr, ", link-type %s (%s)", +- dlt_name, +- pcap_datalink_val_to_description(dlt)); ++ dlt_name, ++ pcap_datalink_val_to_description(dlt)); + } + fprintf(stderr, ", snapshot length %d\n", pcap_snapshot(pd)); + } + } +- } +- while (ret != NULL); ++ } while (ret != NULL); + + if (count_mode && RFileName != NULL) + fprintf(stdout, "%u packet%s\n", packets_captured, +- PLURAL_SUFFIX(packets_captured)); ++ PLURAL_SUFFIX(packets_captured)); + + free(cmdbuf); + pcap_freecode(&fcode); + exit_tcpdump(status == -1 ? S_ERR_HOST_PROGRAM : S_SUCCESS); + } + +-/* +- * Catch a signal. +- */ +-static void +-(*setsignal (int sig, void (*func)(int)))(int) +-{ +-#ifdef _WIN32 +- return (signal(sig, func)); +-#else +- struct sigaction old, new; +- +- memset(&new, 0, sizeof(new)); +- new.sa_handler = func; +- if ((sig == SIGCHLD) +-# ifdef SIGNAL_REQ_INFO +- || (sig == SIGNAL_REQ_INFO) +-# endif +-# ifdef SIGNAL_FLUSH_PCAP +- || (sig == SIGNAL_FLUSH_PCAP) +-# endif +- ) +- new.sa_flags = SA_RESTART; +- if (sigaction(sig, &new, &old) < 0) +- return (SIG_ERR); +- return (old.sa_handler); +-#endif +-} +- +-/* make a clean exit on interrupts */ +-static void +-cleanup(int signo _U_) ++static void stellar_dump_run(void) + { +-#ifdef _WIN32 +- if (timer_handle != INVALID_HANDLE_VALUE) { +- DeleteTimerQueueTimer(NULL, timer_handle, NULL); +- CloseHandle(timer_handle); +- timer_handle = INVALID_HANDLE_VALUE; +- } +-#else /* _WIN32 */ +- struct itimerval timer; +- +- timer.it_interval.tv_sec = 0; +- timer.it_interval.tv_usec = 0; +- timer.it_value.tv_sec = 0; +- timer.it_value.tv_usec = 0; +- setitimer(ITIMER_REAL, &timer, NULL); +-#endif /* _WIN32 */ +- +-#ifdef HAVE_PCAP_BREAKLOOP +- /* +- * We have "pcap_breakloop()"; use it, so that we do as little +- * as possible in the signal handler (it's probably not safe +- * to do anything with standard I/O streams in a signal handler - +- * the ANSI C standard doesn't say it is). +- */ +- pcap_breakloop(pd); +-#else +- /* +- * We don't have "pcap_breakloop()"; this isn't safe, but +- * it's the best we can do. Print the summary if we're +- * not reading from a savefile - i.e., if we're doing a +- * live capture - and exit. +- */ +- if (pd != NULL && pcap_file(pd) == NULL) { ++ if (stellar_dump_datalink_init(&g_stellar_dump_arg) < 0) ++ { ++ exit(1); ++ } ++ if (stellar_dump_ctrllink_init(&g_stellar_dump_arg) < 0) ++ { ++ exit(1); ++ } ++ if (stellar_dump_start(&g_stellar_dump_arg) < 0) ++ { ++ exit(1); ++ } ++ stellar_dump_ctrllink_keepalive_start(&g_stellar_dump_arg); ++ char recv_buf[DATALINK_RECV_BUF_SIZE]; ++ struct pcap_pkthdr pcaphdr = {}; ++ char *pkt_ptr; ++ int total_recv_pkt_num = 0; ++ while (g_stellar_dump_run) ++ { ++ if (stellar_dump_datalink_recv(recv_buf, DATALINK_RECV_BUF_SIZE, &pkt_ptr, &pcaphdr) < 0) ++ { ++ continue; ++ } + /* +- * We got interrupted, so perhaps we didn't +- * manage to finish a line we were printing. +- * Print an extra newline, just in case. +- */ +- putchar('\n'); +- (void)fflush(stdout); +- info(1); +- } +- exit_tcpdump(S_SUCCESS); +-#endif +-} +- +-/* +- On windows, we do not use a fork, so we do not care less about +- waiting a child processes to die +- */ +-#if defined(HAVE_FORK) || defined(HAVE_VFORK) +-static void +-child_cleanup(int signo _U_) +-{ +- wait(NULL); +-} +-#endif /* HAVE_FORK && HAVE_VFORK */ +- +-static void +-info(int verbose) +-{ +- struct pcap_stat stats; +- +- /* +- * Older versions of libpcap didn't set ps_ifdrop on some +- * platforms; initialize it to 0 to handle that. +- */ +- stats.ps_ifdrop = 0; +- if (pcap_stats(pd, &stats) < 0) { +- (void)fprintf(stderr, "pcap_stats: %s\n", pcap_geterr(pd)); +- infoprint = 0; +- return; ++ dump_packet: if set -w option, write packet to file ++ print_packet: print packet to stdout ++ */ ++ callback(pcap_userdata, &pcaphdr, (u_char *)pkt_ptr); ++ if (g_stellar_dump_arg.expect_packet_count > 0 && ++total_recv_pkt_num >= g_stellar_dump_arg.expect_packet_count) ++ { ++ break; ++ } + } +- +- if (!verbose) +- fprintf(stderr, "%s: ", program_name); +- +- (void)fprintf(stderr, "%u packet%s captured", packets_captured, +- PLURAL_SUFFIX(packets_captured)); +- if (!verbose) +- fputs(", ", stderr); +- else +- putc('\n', stderr); +- (void)fprintf(stderr, "%u packet%s received by filter", stats.ps_recv, +- PLURAL_SUFFIX(stats.ps_recv)); +- if (!verbose) +- fputs(", ", stderr); +- else +- putc('\n', stderr); +- (void)fprintf(stderr, "%u packet%s dropped by kernel", stats.ps_drop, +- PLURAL_SUFFIX(stats.ps_drop)); +- if (stats.ps_ifdrop != 0) { +- if (!verbose) +- fputs(", ", stderr); +- else +- putc('\n', stderr); +- (void)fprintf(stderr, "%u packet%s dropped by interface\n", +- stats.ps_ifdrop, PLURAL_SUFFIX(stats.ps_ifdrop)); +- } else +- putc('\n', stderr); +- infoprint = 0; ++ exit(0); + } + +-#if defined(HAVE_FORK) || defined(HAVE_VFORK) +-#ifdef HAVE_FORK +-#define fork_subprocess() fork() +-#else +-#define fork_subprocess() vfork() +-#endif +-static void +-compress_savefile(const char *filename) ++int stellar_dump(int argc, char **argv) + { +- pid_t child; +- +- child = fork_subprocess(); +- if (child == -1) { +- fprintf(stderr, +- "compress_savefile: fork failed: %s\n", +- pcap_strerror(errno)); +- return; ++ atexit((void (*)(void))cleanup); ++ if (tcpdump_parse_args(argc, argv) < 0) ++ { ++ return -1; + } +- if (child != 0) { +- /* Parent process. */ +- return; +- } +- +- /* +- * Child process. +- * Set to lowest priority so that this doesn't disturb the capture. +- */ +-#ifdef NZERO +- setpriority(PRIO_PROCESS, 0, NZERO - 1); +-#else +- setpriority(PRIO_PROCESS, 0, 19); +-#endif +- if (execlp(zflag, zflag, filename, (char *)NULL) == -1) +- fprintf(stderr, +- "compress_savefile: execlp(%s, %s) failed: %s\n", +- zflag, +- filename, +- pcap_strerror(errno)); +-#ifdef HAVE_FORK +- exit(S_ERR_HOST_PROGRAM); +-#else +- _exit(S_ERR_HOST_PROGRAM); +-#endif +-} +-#else /* HAVE_FORK && HAVE_VFORK */ +-static void +-compress_savefile(const char *filename) +-{ +- fprintf(stderr, +- "compress_savefile failed. Functionality not implemented under your system\n"); +-} +-#endif /* HAVE_FORK && HAVE_VFORK */ +- +-static void +-dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) +-{ +- struct dump_info *dump_info; +- +- ++packets_captured; +- +- ++infodelay; +- +- dump_info = (struct dump_info *)user; +- +- /* +- * XXX - this won't force the file to rotate on the specified time +- * boundary, but it will rotate on the first packet received after the +- * specified Gflag number of seconds. Note: if a Gflag time boundary +- * and a Cflag size boundary coincide, the time rotation will occur +- * first thereby cancelling the Cflag boundary (since the file should +- * be 0). +- */ +- if (Gflag != 0) { +- /* Check if it is time to rotate */ +- time_t t; +- +- /* Get the current time */ +- if ((t = time(NULL)) == (time_t)-1) { +- error("%s: can't get current_time: %s", +- __func__, pcap_strerror(errno)); +- } +- +- +- /* If the time is greater than the specified window, rotate */ +- if (t - Gflag_time >= Gflag) { +-#ifdef HAVE_CAPSICUM +- FILE *fp; +- int fd; +-#endif +- +- /* Update the Gflag_time */ +- Gflag_time = t; +- /* Update Gflag_count */ +- Gflag_count++; +- /* +- * Close the current file and open a new one. +- */ +- pcap_dump_close(dump_info->pdd); +- +- /* +- * Compress the file we just closed, if the user asked for it +- */ +- if (zflag != NULL) +- compress_savefile(dump_info->CurrentFileName); +- +- /* +- * Check to see if we've exceeded the Wflag (when +- * not using Cflag). +- */ +- if (Cflag == 0 && Wflag > 0 && Gflag_count >= Wflag) { +- (void)fprintf(stderr, "Maximum file limit reached: %d\n", +- Wflag); +- info(1); +- exit_tcpdump(S_SUCCESS); +- /* NOTREACHED */ +- } +- if (dump_info->CurrentFileName != NULL) +- free(dump_info->CurrentFileName); +- /* Allocate space for max filename + \0. */ +- dump_info->CurrentFileName = (char *)malloc(PATH_MAX + 1); +- if (dump_info->CurrentFileName == NULL) +- error("dump_packet_and_trunc: malloc"); +- /* +- * Gflag was set otherwise we wouldn't be here. Reset the count +- * so multiple files would end with 1,2,3 in the filename. +- * The counting is handled with the -C flow after this. +- */ +- Cflag_count = 0; +- +- /* +- * This is always the first file in the Cflag +- * rotation: e.g. 0 +- * We also don't need numbering if Cflag is not set. +- */ +- if (Cflag != 0) +- MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, 0, +- WflagChars); +- else +- MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, 0, 0); +- +-#ifdef HAVE_LIBCAP_NG +- capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE); +- capng_apply(CAPNG_SELECT_BOTH); +-#endif /* HAVE_LIBCAP_NG */ +-#ifdef HAVE_CAPSICUM +- fd = openat(dump_info->dirfd, +- dump_info->CurrentFileName, +- O_CREAT | O_WRONLY | O_TRUNC, 0644); +- if (fd < 0) { +- error("unable to open file %s", +- dump_info->CurrentFileName); +- } +- fp = fdopen(fd, "w"); +- if (fp == NULL) { +- error("unable to fdopen file %s", +- dump_info->CurrentFileName); +- } +- dump_info->pdd = pcap_dump_fopen(dump_info->pd, fp); +-#else /* !HAVE_CAPSICUM */ +- dump_info->pdd = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName); +-#endif +-#ifdef HAVE_LIBCAP_NG +- capng_update(CAPNG_DROP, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE); +- capng_apply(CAPNG_SELECT_BOTH); +-#endif /* HAVE_LIBCAP_NG */ +- if (dump_info->pdd == NULL) +- error("%s", pcap_geterr(pd)); +-#ifdef HAVE_CAPSICUM +- set_dumper_capsicum_rights(dump_info->pdd); +-#endif +- } ++ if (tcpdump_prepare() < 0) ++ { ++ return -1; + } +- +- /* +- * XXX - this won't prevent capture files from getting +- * larger than Cflag - the last packet written to the +- * file could put it over Cflag. +- */ +- if (Cflag != 0) { +-#ifdef HAVE_PCAP_DUMP_FTELL64 +- int64_t size = pcap_dump_ftell64(dump_info->pdd); +-#else +- /* +- * XXX - this only handles a Cflag value > 2^31-1 on +- * LP64 platforms; to handle ILP32 (32-bit UN*X and +- * Windows) or LLP64 (64-bit Windows) would require +- * a version of libpcap with pcap_dump_ftell64(). +- */ +- long size = pcap_dump_ftell(dump_info->pdd); +-#endif +- +- if (size == -1) +- error("ftell fails on output file"); +- if (size > Cflag) { +-#ifdef HAVE_CAPSICUM +- FILE *fp; +- int fd; +-#endif +- +- /* +- * Close the current file and open a new one. +- */ +- pcap_dump_close(dump_info->pdd); +- +- /* +- * Compress the file we just closed, if the user +- * asked for it. +- */ +- if (zflag != NULL) +- compress_savefile(dump_info->CurrentFileName); +- +- Cflag_count++; +- if (Wflag > 0) { +- if (Cflag_count >= Wflag) +- Cflag_count = 0; +- } +- if (dump_info->CurrentFileName != NULL) +- free(dump_info->CurrentFileName); +- dump_info->CurrentFileName = (char *)malloc(PATH_MAX + 1); +- if (dump_info->CurrentFileName == NULL) +- error("%s: malloc", __func__); +- MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, Cflag_count, WflagChars); +-#ifdef HAVE_LIBCAP_NG +- capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE); +- capng_apply(CAPNG_SELECT_BOTH); +-#endif /* HAVE_LIBCAP_NG */ +-#ifdef HAVE_CAPSICUM +- fd = openat(dump_info->dirfd, dump_info->CurrentFileName, +- O_CREAT | O_WRONLY | O_TRUNC, 0644); +- if (fd < 0) { +- error("unable to open file %s", +- dump_info->CurrentFileName); +- } +- fp = fdopen(fd, "w"); +- if (fp == NULL) { +- error("unable to fdopen file %s", +- dump_info->CurrentFileName); +- } +- dump_info->pdd = pcap_dump_fopen(dump_info->pd, fp); +-#else /* !HAVE_CAPSICUM */ +- dump_info->pdd = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName); +-#endif +-#ifdef HAVE_LIBCAP_NG +- capng_update(CAPNG_DROP, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE); +- capng_apply(CAPNG_SELECT_BOTH); +-#endif /* HAVE_LIBCAP_NG */ +- if (dump_info->pdd == NULL) +- error("%s", pcap_geterr(pd)); +-#ifdef HAVE_CAPSICUM +- set_dumper_capsicum_rights(dump_info->pdd); +-#endif +- } ++ if (RFileName != NULL || VFileName != NULL) ++ { ++ tcpdump_run(); + } +- +- pcap_dump((u_char *)dump_info->pdd, h, sp); +-#ifdef HAVE_PCAP_DUMP_FLUSH +- if (Uflag) +- pcap_dump_flush(dump_info->pdd); +-#endif +- +- if (dump_info->ndo != NULL) +- pretty_print_packet(dump_info->ndo, h, sp, packets_captured); +- +- --infodelay; +- if (infoprint) +- info(0); +-} +- +-static void +-dump_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) +-{ +- struct dump_info *dump_info; +- +- ++packets_captured; +- +- ++infodelay; +- +- dump_info = (struct dump_info *)user; +- +- pcap_dump((u_char *)dump_info->pdd, h, sp); +-#ifdef HAVE_PCAP_DUMP_FLUSH +- if (Uflag) +- pcap_dump_flush(dump_info->pdd); +-#endif +- +- if (dump_info->ndo != NULL) +- pretty_print_packet(dump_info->ndo, h, sp, packets_captured); +- +- --infodelay; +- if (infoprint) +- info(0); +-} +- +-static void +-print_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) +-{ +- ++packets_captured; +- +- ++infodelay; +- +- if (!count_mode) +- pretty_print_packet((netdissect_options *)user, h, sp, packets_captured); +- +- --infodelay; +- if (infoprint) +- info(0); +-} +- +-#ifdef SIGNAL_REQ_INFO +-static void +-requestinfo(int signo _U_) +-{ +- if (infodelay) +- ++infoprint; + else +- info(0); +-} +-#endif +- +-#ifdef SIGNAL_FLUSH_PCAP +-static void +-flushpcap(int signo _U_) +-{ +- if (pdd != NULL) +- pcap_dump_flush(pdd); +-} +-#endif +- +-static void +-print_packets_captured (void) +-{ +- static u_int prev_packets_captured, first = 1; +- +- if (infodelay == 0 && (first || packets_captured != prev_packets_captured)) { +- fprintf(stderr, "Got %u\r", packets_captured); +- first = 0; +- prev_packets_captured = packets_captured; ++ { ++ stellar_dump_run(); + } +-} +- +-/* +- * Called once each second in verbose mode while dumping to file +- */ +-#ifdef _WIN32 +-static void CALLBACK verbose_stats_dump(PVOID param _U_, +- BOOLEAN timer_fired _U_) +-{ +- print_packets_captured(); +-} +-#else /* _WIN32 */ +-static void verbose_stats_dump(int sig _U_) +-{ +- print_packets_captured(); +-} +-#endif /* _WIN32 */ +- +-DIAG_OFF_DEPRECATION +-static void +-print_version(FILE *f) +-{ +-#ifndef HAVE_PCAP_LIB_VERSION +- #ifdef HAVE_PCAP_VERSION +- extern char pcap_version[]; +- #else /* HAVE_PCAP_VERSION */ +- static char pcap_version[] = "unknown"; +- #endif /* HAVE_PCAP_VERSION */ +-#endif /* HAVE_PCAP_LIB_VERSION */ +- const char *smi_version_string; +- +- (void)fprintf(f, "%s version " PACKAGE_VERSION "\n", program_name); +-#ifdef HAVE_PCAP_LIB_VERSION +- (void)fprintf(f, "%s\n", pcap_lib_version()); +-#else /* HAVE_PCAP_LIB_VERSION */ +- (void)fprintf(f, "libpcap version %s\n", pcap_version); +-#endif /* HAVE_PCAP_LIB_VERSION */ +- +-#if defined(HAVE_LIBCRYPTO) && defined(SSLEAY_VERSION) +- (void)fprintf (f, "%s\n", SSLeay_version(SSLEAY_VERSION)); +-#endif +- +- smi_version_string = nd_smi_version_string(); +- if (smi_version_string != NULL) +- (void)fprintf (f, "SMI-library: %s\n", smi_version_string); +- +-#if defined(__SANITIZE_ADDRESS__) +- (void)fprintf (f, "Compiled with AddressSanitizer/GCC.\n"); +-#elif defined(__has_feature) +-# if __has_feature(address_sanitizer) +- (void)fprintf (f, "Compiled with AddressSanitizer/Clang.\n"); +-# elif __has_feature(memory_sanitizer) +- (void)fprintf (f, "Compiled with MemorySanitizer/Clang.\n"); +-# endif +-#endif /* __SANITIZE_ADDRESS__ or __has_feature */ +-} +-DIAG_ON_DEPRECATION +- +-static void +-print_usage(FILE *f) +-{ +- print_version(f); +- (void)fprintf(f, +-"Usage: %s [-Abd" D_FLAG "efhH" I_FLAG J_FLAG "KlLnNOpqStu" U_FLAG "vxX#]" B_FLAG_USAGE " [ -c count ] [--count]\n", program_name); +- (void)fprintf(f, +-"\t\t[ -C file_size ] [ -E algo:secret ] [ -F file ] [ -G seconds ]\n"); +- (void)fprintf(f, +-"\t\t[ -i interface ]" IMMEDIATE_MODE_USAGE j_FLAG_USAGE "\n"); +-#ifdef HAVE_PCAP_FINDALLDEVS_EX +- (void)fprintf(f, +-"\t\t" LIST_REMOTE_INTERFACES_USAGE "\n"); +-#endif +-#ifdef USE_LIBSMI +- (void)fprintf(f, +-"\t\t" m_FLAG_USAGE "\n"); +-#endif +- (void)fprintf(f, +-"\t\t[ -M secret ] [ --number ] [ --print ]" Q_FLAG_USAGE "\n"); +- (void)fprintf(f, +-"\t\t[ -r file ] [ -s snaplen ] [ -T type ] [ --version ]\n"); +- (void)fprintf(f, +-"\t\t[ -V file ] [ -w file ] [ -W filecount ] [ -y datalinktype ]\n"); +-#ifdef HAVE_PCAP_SET_TSTAMP_PRECISION +- (void)fprintf(f, +-"\t\t[ --time-stamp-precision precision ] [ --micro ] [ --nano ]\n"); +-#endif +- (void)fprintf(f, +-"\t\t[ -z postrotate-command ] [ -Z user ] [ expression ]\n"); ++ return 0; + } +diff -uNr tcpdump-tcpdump-4.99.4/tcpdump_ip6.h tcpdump-for-stellar/tcpdump_ip6.h +--- tcpdump-tcpdump-4.99.4/tcpdump_ip6.h 1970-01-01 08:00:00.000000000 +0800 ++++ tcpdump-for-stellar/tcpdump_ip6.h 2024-10-30 17:34:06.265498697 +0800 +@@ -0,0 +1,231 @@ ++/* NetBSD: ip6.h,v 1.9 2000/07/13 05:34:21 itojun Exp */ ++/* $KAME: ip6.h,v 1.9 2000/07/02 21:01:32 itojun Exp $ */ ++ ++/* ++ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. Neither the name of the project nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ */ ++ ++/* ++ * Copyright (c) 1982, 1986, 1993 ++ * The Regents of the University of California. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by the University of ++ * California, Berkeley and its contributors. ++ * 4. Neither the name of the University nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ * @(#)ip.h 8.1 (Berkeley) 6/10/93 ++ */ ++ ++#ifndef ND_IP6_H_ ++#define ND_IP6_H_ ++ ++/* ++ * Definition for internet protocol version 6. ++ * RFC 2460 ++ */ ++ ++// struct ip6_hdr ++struct tcpdump_ip6_hdr ++{ ++ union ++ { ++ // struct ip6_hdrctl ++ struct tcpdump_ip6_hdrctl ++ { ++ nd_uint32_t ip6_un1_flow; /* 20 bits of flow-ID */ ++ nd_uint16_t ip6_un1_plen; /* payload length */ ++ nd_uint8_t ip6_un1_nxt; /* next header */ ++ nd_uint8_t ip6_un1_hlim; /* hop limit */ ++ } ip6_un1; ++ nd_uint8_t ip6_un2_vfc; /* 4 bits version, top 4 bits class */ ++ } ip6_ctlun; ++ nd_ipv6 ip6_src; /* source address */ ++ nd_ipv6 ip6_dst; /* destination address */ ++}; ++ ++#define ip6_vfc ip6_ctlun.ip6_un2_vfc ++#define IP6_VERSION(ip6_hdr) ((GET_U_1((ip6_hdr)->ip6_vfc) & 0xf0) >> 4) ++#define ip6_flow ip6_ctlun.ip6_un1.ip6_un1_flow ++#define ip6_plen ip6_ctlun.ip6_un1.ip6_un1_plen ++#define ip6_nxt ip6_ctlun.ip6_un1.ip6_un1_nxt ++#define ip6_hlim ip6_ctlun.ip6_un1.ip6_un1_hlim ++#define ip6_hops ip6_ctlun.ip6_un1.ip6_un1_hlim ++ ++/* in network endian */ ++#define IPV6_FLOWINFO_MASK ((uint32_t)htonl(0x0fffffff)) /* flow info (28 bits) */ ++#define IPV6_FLOWLABEL_MASK ((uint32_t)htonl(0x000fffff)) /* flow label (20 bits) */ ++ ++/* ++ * Extension Headers ++ */ ++ ++// struct ip6_ext ++struct tcpdump_ip6_ext ++{ ++ nd_uint8_t ip6e_nxt; ++ nd_uint8_t ip6e_len; ++}; ++ ++/* Hop-by-Hop options header */ ++// struct ip6_hbh ++struct tcpdump_ip6_hbh ++{ ++ nd_uint8_t ip6h_nxt; /* next header */ ++ nd_uint8_t ip6h_len; /* length in units of 8 octets */ ++ /* followed by options */ ++}; ++ ++/* Destination options header */ ++// struct ip6_dest ++struct tcpdump_ip6_dest ++{ ++ nd_uint8_t ip6d_nxt; /* next header */ ++ nd_uint8_t ip6d_len; /* length in units of 8 octets */ ++ /* followed by options */ ++}; ++ ++/* https://www.iana.org/assignments/ipv6-parameters/ipv6-parameters.xhtml */ ++ ++/* Option types and related macros */ ++#define IP6OPT_PAD1 0x00 /* 00 0 00000 */ ++#define IP6OPT_PADN 0x01 /* 00 0 00001 */ ++#define IP6OPT_JUMBO 0xC2 /* 11 0 00010 = 194 */ ++#define IP6OPT_JUMBO_LEN 6 ++#define IP6OPT_RPL 0x63 /* 01 1 00011 */ ++#define IP6OPT_TUN_ENC_LIMIT 0x04 /* 00 0 00100 */ ++#define IP6OPT_ROUTER_ALERT 0x05 /* 00 0 00101 */ ++ ++#define IP6OPT_RTALERT_LEN 4 ++#define IP6OPT_RTALERT_MLD 0 /* Datagram contains an MLD message */ ++#define IP6OPT_RTALERT_RSVP 1 /* Datagram contains an RSVP message */ ++#define IP6OPT_RTALERT_ACTNET 2 /* contains an Active Networks msg */ ++#define IP6OPT_MINLEN 2 ++ ++#define IP6OPT_QUICK_START 0x26 /* 00 1 00110 */ ++#define IP6OPT_CALIPSO 0x07 /* 00 0 00111 */ ++#define IP6OPT_SMF_DPD 0x08 /* 00 0 01000 */ ++#define IP6OPT_HOME_ADDRESS 0xc9 /* 11 0 01001 */ ++#define IP6OPT_HOMEADDR_MINLEN 18 ++#define IP6OPT_EID 0x8a /* 10 0 01010 */ ++#define IP6OPT_ILNP_NOTICE 0x8b /* 10 0 01011 */ ++#define IP6OPT_LINE_ID 0x8c /* 10 0 01100 */ ++#define IP6OPT_MPL 0x6d /* 01 1 01101 */ ++#define IP6OPT_IP_DFF 0xee /* 11 1 01110 */ ++ ++#define IP6OPT_TYPE(o) ((o) & 0xC0) ++#define IP6OPT_TYPE_SKIP 0x00 ++#define IP6OPT_TYPE_DISCARD 0x40 ++#define IP6OPT_TYPE_FORCEICMP 0x80 ++#define IP6OPT_TYPE_ICMP 0xC0 ++ ++#define IP6OPT_MUTABLE 0x20 ++ ++/* Routing header */ ++// struct ip6_rthdr ++struct tcpdump_ip6_rthdr ++{ ++ nd_uint8_t ip6r_nxt; /* next header */ ++ nd_uint8_t ip6r_len; /* length in units of 8 octets */ ++ nd_uint8_t ip6r_type; /* routing type */ ++ nd_uint8_t ip6r_segleft; /* segments left */ ++ /* followed by routing type specific data */ ++}; ++ ++#define IPV6_RTHDR_TYPE_0 0 ++#define IPV6_RTHDR_TYPE_2 2 ++#define IPV6_RTHDR_TYPE_4 4 ++ ++/* Type 0 Routing header */ ++/* Also used for Type 2 */ ++// struct ip6_rthdr0 ++struct tcpdump_ip6_rthdr0 ++{ ++ nd_uint8_t ip6r0_nxt; /* next header */ ++ nd_uint8_t ip6r0_len; /* length in units of 8 octets */ ++ nd_uint8_t ip6r0_type; /* always zero */ ++ nd_uint8_t ip6r0_segleft; /* segments left */ ++ nd_uint32_t ip6r0_reserved; /* reserved field */ ++ nd_ipv6 ip6r0_addr[1]; /* up to 23 addresses */ ++}; ++ ++/** ++ * Type 4 Routing header ++ * known as Segment Routing Header 'SRH' ++ */ ++// struct ip6_srh ++struct tcpdump_ip6_srh ++{ ++ nd_uint8_t srh_nxt; /* next header */ ++ nd_uint8_t srh_len; /* length in units of 8 octets */ ++ nd_uint8_t srh_type; /* Routing Type 4 */ ++ nd_uint8_t srh_segleft; /* segments left */ ++ nd_uint8_t srh_last_ent; /* Last Entry*/ ++ nd_uint8_t srh_flags; /* Flags */ ++ nd_uint16_t srh_tag; /* Tag */ ++ nd_ipv6 srh_segments[1]; /* SRH segments list*/ ++}; ++ ++/* Fragment header */ ++// struct ip6_frag ++struct tcpdump_ip6_frag ++{ ++ nd_uint8_t ip6f_nxt; /* next header */ ++ nd_uint8_t ip6f_reserved; /* reserved field */ ++ nd_uint16_t ip6f_offlg; /* offset, reserved, and flag */ ++ nd_uint32_t ip6f_ident; /* identification */ ++}; ++ ++#define IP6F_OFF_MASK 0xfff8 /* mask out offset from ip6f_offlg */ ++#define IP6F_RESERVED_MASK 0x0006 /* reserved bits in ip6f_offlg */ ++#define IP6F_MORE_FRAG 0x0001 /* more-fragments flag */ ++ ++#endif /* not ND_IP6_H_ */ +diff -uNr tcpdump-tcpdump-4.99.4/tcpdump_ip.h tcpdump-for-stellar/tcpdump_ip.h +--- tcpdump-tcpdump-4.99.4/tcpdump_ip.h 1970-01-01 08:00:00.000000000 +0800 ++++ tcpdump-for-stellar/tcpdump_ip.h 2024-10-30 17:34:06.265498697 +0800 +@@ -0,0 +1,169 @@ ++/* ++ * Copyright (c) 1982, 1986, 1993 ++ * The Regents of the University of California. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by the University of ++ * California, Berkeley and its contributors. ++ * 4. Neither the name of the University nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ * @(#)ip.h 8.2 (Berkeley) 6/1/94 ++ */ ++ ++#ifndef netdissect_ip_h ++#define netdissect_ip_h ++/* ++ * Definitions for internet protocol version 4. ++ * Per RFC 791, September 1981. ++ */ ++#define IPVERSION 4 ++ ++/* ++ * Structure of an internet header, naked of options. ++ * ++ * We declare ip_len and ip_off to be short, rather than u_short ++ * pragmatically since otherwise unsigned comparisons can result ++ * against negative integers quite easily, and fail in subtle ways. ++ */ ++// struct ip ++struct tcpdump_ip ++{ ++ nd_uint8_t ip_vhl; /* header length, version */ ++#define IP_V(ip) ((GET_U_1((ip)->ip_vhl) & 0xf0) >> 4) ++#define IP_HL(ip) (GET_U_1((ip)->ip_vhl) & 0x0f) ++ nd_uint8_t ip_tos; /* type of service */ ++ nd_uint16_t ip_len; /* total length */ ++ nd_uint16_t ip_id; /* identification */ ++ nd_uint16_t ip_off; /* fragment offset field */ ++#define IP_DF 0x4000 /* don't fragment flag */ ++#define IP_MF 0x2000 /* more fragments flag */ ++#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */ ++ nd_uint8_t ip_ttl; /* time to live */ ++ nd_uint8_t ip_p; /* protocol */ ++ nd_uint16_t ip_sum; /* checksum */ ++ nd_ipv4 ip_src, ip_dst; /* source and dest address */ ++}; ++ ++#define IP_MAXPACKET 65535 /* maximum packet size */ ++ ++/* ++ * Definitions for IP type of service (ip_tos) ++ */ ++#define IPTOS_LOWDELAY 0x10 ++#define IPTOS_THROUGHPUT 0x08 ++#define IPTOS_RELIABILITY 0x04 ++ ++/* ++ * Definitions for IP precedence (also in ip_tos) (hopefully unused) ++ */ ++#define IPTOS_PREC_NETCONTROL 0xe0 ++#define IPTOS_PREC_INTERNETCONTROL 0xc0 ++#define IPTOS_PREC_CRITIC_ECP 0xa0 ++#define IPTOS_PREC_FLASHOVERRIDE 0x80 ++#define IPTOS_PREC_FLASH 0x60 ++#define IPTOS_PREC_IMMEDIATE 0x40 ++#define IPTOS_PREC_PRIORITY 0x20 ++#define IPTOS_PREC_ROUTINE 0x00 ++ ++/* ++ * Definitions for options. ++ */ ++#define IPOPT_COPIED(o) ((o) & 0x80) ++#define IPOPT_CLASS(o) ((o) & 0x60) ++#define IPOPT_NUMBER(o) ((o) & 0x1f) ++ ++#define IPOPT_CONTROL 0x00 ++#define IPOPT_RESERVED1 0x20 ++#define IPOPT_DEBMEAS 0x40 ++#define IPOPT_RESERVED2 0x60 ++ ++#define IPOPT_EOL 0 /* end of option list */ ++#define IPOPT_NOP 1 /* no operation */ ++ ++#define IPOPT_RR 7 /* record packet route */ ++#define IPOPT_TS 68 /* timestamp */ ++#define IPOPT_RFC1393 82 /* traceroute RFC 1393 */ ++#define IPOPT_SECURITY 130 /* provide s,c,h,tcc */ ++#define IPOPT_LSRR 131 /* loose source route */ ++#define IPOPT_SATID 136 /* satnet id */ ++#define IPOPT_SSRR 137 /* strict source route */ ++#define IPOPT_RA 148 /* router-alert, rfc2113 */ ++ ++/* ++ * Offsets to fields in options other than EOL and NOP. ++ */ ++#define IPOPT_OPTVAL 0 /* option ID */ ++#define IPOPT_OLEN 1 /* option length */ ++#define IPOPT_OFFSET 2 /* offset within option */ ++#define IPOPT_MINOFF 4 /* min value of above */ ++ ++/* ++ * Time stamp option structure. ++ */ ++// struct ip_timestamp ++struct tcpdump_ip_timestamp ++{ ++ nd_uint8_t ipt_code; /* IPOPT_TS */ ++ nd_uint8_t ipt_len; /* size of structure (variable) */ ++ nd_uint8_t ipt_ptr; /* index of current entry */ ++ nd_uint8_t ipt_oflwflg; /* flags, overflow counter */ ++#define IPTS_OFLW(ip) (((ipt)->ipt_oflwflg & 0xf0) >> 4) ++#define IPTS_FLG(ip) ((ipt)->ipt_oflwflg & 0x0f) ++ union ipt_timestamp ++ { ++ nd_uint32_t ipt_time[1]; ++ struct ipt_ta ++ { ++ nd_ipv4 ipt_addr; ++ nd_uint32_t ipt_time; ++ } ipt_ta[1]; ++ } ipt_timestamp; ++}; ++ ++/* flag bits for ipt_flg */ ++#define IPOPT_TS_TSONLY 0 /* timestamps only */ ++#define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */ ++#define IPOPT_TS_PRESPEC 3 /* specified modules only */ ++ ++/* bits for security (not byte swapped) */ ++#define IPOPT_SECUR_UNCLASS 0x0000 ++#define IPOPT_SECUR_CONFID 0xf135 ++#define IPOPT_SECUR_EFTO 0x789a ++#define IPOPT_SECUR_MMMM 0xbc4d ++#define IPOPT_SECUR_RESTR 0xaf13 ++#define IPOPT_SECUR_SECRET 0xd788 ++#define IPOPT_SECUR_TOPSECRET 0x6bc5 ++ ++/* ++ * Internet implementation parameters. ++ */ ++#define MAXTTL 255 /* maximum time to live (seconds) */ ++#define IPDEFTTL 64 /* default ttl, from RFC 1340 */ ++#define IPFRAGTTL 60 /* time to live for frags, slowhz */ ++#define IPTTLDEC 1 /* subtracted when forwarding */ ++ ++#define IP_MSS 576 /* default maximum segment size */ ++#endif /* netdissect_ip_h */ +\ No newline at end of file |
