static void broadcast_check(void) { struct { int version; char const *str; uint32_t netmask; bool is_broadcast; } tests[] = { { 4, "1.0.0.0", 0xff000000U, false }, { 4, "127.0.0.1", 0xff000000U, false }, { 4, "128.10.5.255", 0xffff0000U, false }, { 4, "192.168.10.9", 0xffffff00U, false }, { 4, "10.255.255.255", 0xff000000U, true }, { 4, "127.0.255.255", 0xff000000U, false }, { 4, "128.0.255.255", 0xffff0000U, true }, { 4, "192.168.10.255", 0xffffff00U, true }, { 6, "ff02::1", 0, true }, { 6, "1:2:3:4::", 0, false }, }; for (unsigned t = 0; t < NB_ELEMS(tests); t++) { struct ip_addr addr; ip_addr_ctor_from_str(&addr, tests[t].str, strlen(tests[t].str), tests[t].version); if (addr.family == AF_INET) { assert(netmask_of_address(addr.u.v4) == tests[t].netmask); } assert(ip_addr_is_broadcast(&addr) == tests[t].is_broadcast); } }
static void all_fini(void) { // Make some effort to honnor any plugins destructor at exit doomer_stop(); // doomer_thread must not awake while we destroy parsers, plugins, and so on pkt_source_fini(); plugin_del_all(); // Since hook subscribers is not locked, we must kill sources before unregister plugins for (unsigned i = NB_ELEMS(initers); i > 0; ) { initers[--i].fini(); } # ifdef DELETE_ALL_AT_EXIT /* This is sometime usefull to clean all allocated ressources * at exit to help valgrind help us find memory leaks. */ ERR_free_strings(); # endif redim_array_fini(); hash_fini(); ref_fini(); mallocer_fini(); cli_fini(); ext_fini(); files_fini(); log_fini(); }
static void scm_conv_check(void) { scm_init_guile(); static struct { int version; char const *str; char const *num; sa_family_t exp_family; } tests[] = { { 4, "1.0.0.0", "(%d . 16777216)", AF_INET }, { 4, "127.0.0.1", "(%d . 2130706433)", AF_INET }, { 4, "128.10.5.255", "(%d . 2148140543)", AF_INET }, { 6, "ff02::1", "(%d . 338963523518870617245727861364146307073)", AF_INET6 }, { 6, "1:2:3:4::", "(%d . 5192455318486707403025865779445760)", AF_INET6 }, }; for (unsigned t = 0; t < NB_ELEMS(tests); t++) { struct ip_addr addr; ip_addr_ctor_from_str(&addr, tests[t].str, strlen(tests[t].str), tests[t].version); SCM ip = scm_from_ip_addr(&addr); SCM str = scm_simple_format(SCM_BOOL_F, scm_from_latin1_string("~a"), scm_cons(ip, SCM_EOL)); char buf[256]; size_t len = scm_to_locale_stringbuf(str, buf, sizeof(buf)); assert(len < sizeof(buf)); buf[len] = '\0'; char expected[256]; snprintf(expected, sizeof(expected), tests[t].num, tests[t].exp_family); printf("%s -> '%s' (expected '%s')\n", tests[t].str, buf, expected); assert(0 == strcmp(expected, buf)); } }
/* * Check if query is valid. * @param cursor to read * @param candidate Filled with potential sql size candidate * @return True if a correct query has been found and cursor is positioned at the begin of the query */ static bool lookup_query(struct cursor *cursor, struct query_candidate *candidate) { SLOG(LOG_DEBUG, "Start looking for query"); uint8_t current; uint8_t next; while (cursor->cap_len > QUERY_WITH_SIZE) { current = cursor_peek_u8(cursor, 0); next = cursor_peek_u8(cursor, 1); if (current == TTC_ROW_DATA && next > 0 && next <= 4) { SLOG(LOG_DEBUG, " Looks like start of a data query row"); return false; } if (current > 0 && current < 3 && next > MIN_QUERY_SIZE && candidate->num_candidate_size < NB_ELEMS(candidate->candidate_sizes)) { uint64_t buf = 0; // Copy cursor since we might have pattern like 0x01 Size Query struct cursor cursor_copy = *cursor; if (PROTO_OK == cursor_read_variable_int(&cursor_copy, &buf)) { SLOG(LOG_DEBUG, " Found a candidate size %"PRIu64, buf); insert_array_sorted(candidate, buf); } } if (candidate->num_candidate_size == 0 || current >= candidate->candidate_sizes[0]) { if (check_chuncked_query(cursor, current, next, candidate)) return true; if (check_fixed_query(cursor, current, next, candidate)) return true; } else { if (check_fixed_query(cursor, current, next, candidate)) return true; if (check_chuncked_query(cursor, current, next, candidate)) return true; } cursor_drop(cursor, 1); } return false; }
static enum mgcp_command mgcp_code_2_command(char const *code, size_t len) { # define COMMAND_LEN 4 static struct { char code[COMMAND_LEN+1]; enum mgcp_command command; } verbs[] = { { "EPCF", MGCP_EndpointConfiguration }, { "CRCX", MGCP_CreateConnection }, { "MDCX", MGCP_ModifyConnection }, { "DLCX", MGCP_DeleteConnection }, { "RQNT", MGCP_NotificationRequest }, { "NTFY", MGCP_Notify }, { "AUEP", MGCP_AuditEndpoint }, { "AUCX", MGCP_AuditConnection }, { "RSIP", MGCP_RestartInProgress }, }; if (len < COMMAND_LEN) return (enum mgcp_command)-1; for (unsigned v = 0; v < NB_ELEMS(verbs); v++) { if (0 == strncasecmp(code, verbs[v].code, COMMAND_LEN)) return verbs[v].command; } return (enum mgcp_command)-1; }
int sdper_parse(struct sdper const *sdper, size_t *head_sz, uint8_t const *packet, size_t packet_len, void *user_data) { // REVIEW: eols and spcs should be provided by liner. struct liner_delimiter eols[] = { { "\r\n", 2 }, { "\n", 1 } }, cols[] = { { "= ", 2}, { "=", 1 } }; struct liner_delimiter_set const lines = { NB_ELEMS(eols), eols, false }, eq = { NB_ELEMS(cols), cols, true }; struct liner liner, tokenizer; liner_init(&liner, &lines, (char const *)packet, packet_len); // Parse header fields while (true) { // Next line if (liner_eof(&liner)) break; // Otherwise tokenize the header line liner_init(&tokenizer, &eq, liner.start, liner_tok_length(&liner)); for (unsigned f = 0; f < sdper->nb_fields; f++) { struct sdper_field const *field = sdper->fields + f; size_t len = liner_tok_length(&tokenizer); if (len != field->length) continue; if (0 != strncasecmp(field->name, tokenizer.start, len)) continue; SLOG(LOG_DEBUG, "Found field %s", field->name); liner_next(&tokenizer); int ret = field->cb(f, &tokenizer, user_data); if (ret) return ret; break; } liner_next(&liner); } if (head_sz) *head_sz = liner_parsed(&liner); return 0; }
unsigned parse_events(struct liner *liner) { unsigned flags = 0; for (unsigned e = 0; e < NB_ELEMS(events); e++) { if ( (liner_tok_length(liner) >= 4 && 0 == strncasecmp(liner->start, events[e].code, 4)) || (events[e].from_line && (liner_tok_length(liner) >= 2 && 0 == strncasecmp(liner->start, events[e].code+2, 2))) ) { flags |= events[e].flag; } } return flags; }
void on_load(void) { log_category_duplicogram_init(); ext_param_bucket_width_init(); SLOG(LOG_INFO, "Duplicogram loaded"); term_init(&handle_key); cli_register("Duplicogram plugin", duplicogram_opts, NB_ELEMS(duplicogram_opts)); mutex_ctor(&dup_lock, "Duplicogram mutex"); ext_function_ctor(&sg_get_duplicogram, "get-duplicogram", 0, 0, 0, g_get_duplicogram, "(get-duplicogram): fetch duplicogram data and reset internal state. Not for the casual user"); hook_subscriber_ctor(&dup_hook, &dup_subscription, dup_callback); hook_subscriber_ctor(&proto_cap->hook, &cap_subscription, cap_callback); }
static void ip_addr_ctor_from_str_check(void) { static struct { char const *str; int mode; } const tests[] = { { "0.0.0.0", 4, }, { "1.2.3.4", 4, }, { "0.0.0.1", 4, }, { "128.2.1.255", 4, }, { "::ffff:1.2.3.4", 6, }, }; for (unsigned t = 0; t < NB_ELEMS(tests); t++) { struct ip_addr addr; ip_addr_ctor_from_str(&addr, tests[t].str, strlen(tests[t].str), tests[t].mode ); char const *str = ip_addr_2_str(&addr); SLOG(LOG_DEBUG, "Comparing '%s' with '%s'", tests[t].str, str); assert(0 == strcmp(str, tests[t].str)); } }
static void ip_addr_routable_check(void) { static struct { char const *str; int mode; bool routable; } const tests[] = { { "0.0.0.0", 4, true }, { "1.2.3.4", 4, true }, { "0.0.0.1", 4, true }, { "128.2.1.255", 4, true }, { "::ffff:1.2.3.4", 6, true }, { "127.0.0.1", 4, false }, { "172.24.5.4", 4, false }, { "192.168.10.9", 4, false }, }; for (unsigned t = 0; t < NB_ELEMS(tests); t++) { struct ip_addr addr; ip_addr_ctor_from_str(&addr, tests[t].str, strlen(tests[t].str), tests[t].mode); assert(ip_addr_is_routable(&addr) == tests[t].routable); } }
static void all_init(void) { log_init(); files_init(); ext_init(); cli_init(); mallocer_init(); // as all users do not init it... ref_init(); // as all users do not init it... hash_init(); // as all users do not init it... redim_array_init(); // if there are no users then some ext functions used by the www interface won't be defined os_detect_init(); // dummy function just to include os_detect in junkie (that does not use it, but plugins may want to) // Openssl don't like to be inited several times so let's do it once and for all SSL_load_error_strings(); SSL_library_init(); OpenSSL_add_all_algorithms(); for (unsigned i = 0; i < NB_ELEMS(initers); i++) { initers[i].init(); } ext_rebind(); }
[SIP_CMD_BYE] = { STRING_AND_LEN("BYE"), sip_set_command }, [SIP_CMD_BYE+1] = { STRING_AND_LEN("SIP/2.0"), sip_set_response }, }; static struct httper_field const fields[] = { { STRING_AND_LEN("content-length"), sip_extract_content_length }, { STRING_AND_LEN("content-type"), sip_extract_content_type }, { STRING_AND_LEN("cseq"), sip_extract_cseq }, { STRING_AND_LEN("call-id"), sip_extract_callid }, { STRING_AND_LEN("from"), sip_extract_from }, { STRING_AND_LEN("to"), sip_extract_to }, { STRING_AND_LEN("via"), sip_extract_via }, }; static struct httper const httper = { .nb_commands = NB_ELEMS(commands), .commands = commands, .nb_fields = NB_ELEMS(fields), .fields = fields }; SLOG(LOG_DEBUG, "Starting SIP analysis"); /* Parse */ struct sip_proto_info info; info.set_values = 0; size_t siphdr_len; enum proto_parse_status status = httper_parse(&httper, &siphdr_len, packet, cap_len, &info); if (status != PROTO_OK) return PROTO_PARSE_ERR; // TODO: handle short packets with the help of a streambuf ?
static ssize_t parse_next_option(struct tcp_proto_info *info, uint8_t const *options, size_t rem_len) { assert(rem_len > 0); if (rem_len < 1) return -1; uint8_t const kind = options[0]; // We only decode MSS and WSF but record all options if (info->nb_options < NB_ELEMS(info->options)) { info->options[info->nb_options++] = kind; } if (kind == 0) { // end of option list if (rem_len > 4) { SLOG(LOG_DEBUG, "Option list terminated while %zu bytes left", rem_len-1); return rem_len; // keep parsing payload } if ((intptr_t)(options+rem_len) & 0x3) { SLOG(LOG_DEBUG, "Option list ends in a non word boundary"); return -1; } // TODO: check that padding is composed of zeros return rem_len; } else if (kind == 1) { return 1; } if (rem_len < 2) { SLOG(LOG_DEBUG, "Invalid TCP options: can't read length"); return -1; } size_t const len = options[1]; // len includes what's read before if (len < 2) { SLOG(LOG_DEBUG, "Invalid TCP options: len field (%zu) < 2", len); return -1; } if (rem_len < len) { SLOG(LOG_DEBUG, "Invalid TCP options: length (%zu) > rem options bytes (%zu)", len, rem_len); return -1; } switch (kind) { case 2: // MSS if (len != 4) { SLOG(LOG_DEBUG, "MSS with length %zu", len); return -1; } info->set_values |= TCP_MSS_SET; info->mss = READ_U16N(options+2); break; case 3: // Window Scale Factor if (len != 3) { SLOG(LOG_DEBUG, "WSF with length %zu", len); return -1; } info->set_values |= TCP_WSF_SET; info->wsf = options[2]; break; } return len; }