static int SMB2Parse(Flow *f, void *smb2_state, AppLayerParserState *pstate, uint8_t *input, uint32_t input_len, void *local_data) { SCEnter(); SMB2State *sstate = (SMB2State *) smb2_state; uint32_t retval = 0; uint32_t parsed = 0; if (pstate == NULL) return -1; if (input == NULL && AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF)) { SCReturnInt(1); } else if (input == NULL || input_len == 0) { SCReturnInt(-1); } while (sstate->bytesprocessed < NBSS_HDR_LEN && input_len) { retval = NBSSParseHeader(smb2_state, pstate, input, input_len); if (retval <= input_len) { parsed += retval; input_len -= retval; } else { return -1; } SCLogDebug("NBSS Header (%u/%u) Type 0x%02x Length 0x%04x parsed %u input_len %u", sstate->bytesprocessed, NBSS_HDR_LEN, sstate->nbss.type, sstate->nbss.length, parsed, input_len); } switch(sstate->nbss.type) { case NBSS_SESSION_MESSAGE: while (input_len && (sstate->bytesprocessed >= NBSS_HDR_LEN && sstate->bytesprocessed < NBSS_HDR_LEN + SMB2_HDR_LEN)) { retval = SMB2ParseHeader(smb2_state, pstate, input + parsed, input_len); if (retval <= input_len) { parsed += retval; input_len -= retval; } else { return -1; } SCLogDebug("SMB2 Header (%u/%u) Command 0x%04x parsed %u input_len %u", sstate->bytesprocessed, NBSS_HDR_LEN + SMB2_HDR_LEN, sstate->smb2.Command, parsed, input_len); } break; default: break; } SCReturnInt(1); }
static int TFTPParseRequest(Flow *f, void *state, AppLayerParserState *pstate, uint8_t *input, uint32_t input_len, void *local_data, const uint8_t flags) { SCLogDebug("Parsing echo request: len=%"PRIu32, input_len); /* Likely connection closed, we can just return here. */ if ((input == NULL || input_len == 0) && AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF)) { return 0; } /* Probably don't want to create a transaction in this case * either. */ if (input == NULL || input_len == 0) { return 0; } return rs_tftp_request(state, input, input_len); }
static TmEcode OutputTxLog(ThreadVars *tv, Packet *p, void *thread_data) { BUG_ON(thread_data == NULL); if (list == NULL) { /* No child loggers registered. */ return TM_ECODE_OK; } OutputLoggerThreadData *op_thread_data = (OutputLoggerThreadData *)thread_data; OutputTxLogger *logger = list; OutputLoggerThreadStore *store = op_thread_data->store; BUG_ON(logger == NULL && store != NULL); BUG_ON(logger != NULL && store == NULL); BUG_ON(logger == NULL && store == NULL); if (p->flow == NULL) return TM_ECODE_OK; Flow * const f = p->flow; AppProto alproto = f->alproto; if (AppLayerParserProtocolIsTxAware(p->proto, alproto) == 0) goto end; if (AppLayerParserProtocolHasLogger(p->proto, alproto) == 0) goto end; void *alstate = f->alstate; if (alstate == NULL) { SCLogDebug("no alstate"); goto end; } uint64_t total_txs = AppLayerParserGetTxCnt(p->proto, alproto, alstate); uint64_t tx_id = AppLayerParserGetTransactionLogId(f->alparser); for (; tx_id < total_txs; tx_id++) { int logger_not_logged = 0; void *tx = AppLayerParserGetTx(p->proto, alproto, alstate, tx_id); if (tx == NULL) { SCLogDebug("tx is NULL not logging"); continue; } int tx_progress_ts = AppLayerParserGetStateProgress(p->proto, alproto, tx, FlowGetDisruptionFlags(f, STREAM_TOSERVER)); int tx_progress_tc = AppLayerParserGetStateProgress(p->proto, alproto, tx, FlowGetDisruptionFlags(f, STREAM_TOCLIENT)); SCLogDebug("tx_progress_ts %d tx_progress_tc %d", tx_progress_ts, tx_progress_tc); // call each logger here (pseudo code) logger = list; store = op_thread_data->store; while (logger && store) { BUG_ON(logger->LogFunc == NULL); SCLogDebug("logger %p, LogCondition %p, ts_log_progress %d " "tc_log_progress %d", logger, logger->LogCondition, logger->ts_log_progress, logger->tc_log_progress); if (logger->alproto == alproto) { SCLogDebug("alproto match, logging tx_id %"PRIu64, tx_id); if (AppLayerParserGetTxLogged(p->proto, alproto, alstate, tx, logger->id)) { SCLogDebug("logger has already logged this transaction"); goto next; } if (!(AppLayerParserStateIssetFlag(f->alparser, APP_LAYER_PARSER_EOF))) { if (logger->LogCondition) { int r = logger->LogCondition(tv, p, alstate, tx, tx_id); if (r == FALSE) { SCLogDebug("conditions not met, not logging"); logger_not_logged = 1; goto next; } } else { if (tx_progress_tc < logger->tc_log_progress) { SCLogDebug("progress not far enough, not logging"); logger_not_logged = 1; goto next; } if (tx_progress_ts < logger->ts_log_progress) { SCLogDebug("progress not far enough, not logging"); logger_not_logged = 1; goto next; } } } PACKET_PROFILING_LOGGER_START(p, logger->logger_id); logger->LogFunc(tv, store->thread_data, p, f, alstate, tx, tx_id); PACKET_PROFILING_LOGGER_END(p, logger->logger_id); AppLayerParserSetTxLogged(p->proto, alproto, alstate, tx, logger->id); } next: logger = logger->next; store = store->next; BUG_ON(logger == NULL && store != NULL); BUG_ON(logger != NULL && store == NULL); } if (!logger_not_logged) { SCLogDebug("updating log tx_id %"PRIu64, tx_id); AppLayerParserSetTransactionLogId(f->alparser); } } end: return TM_ECODE_OK; }
static TmEcode OutputTxLog(ThreadVars *tv, Packet *p, void *thread_data, PacketQueue *pq, PacketQueue *postpq) { BUG_ON(thread_data == NULL); BUG_ON(list == NULL); OutputLoggerThreadData *op_thread_data = (OutputLoggerThreadData *)thread_data; OutputTxLogger *logger = list; OutputLoggerThreadStore *store = op_thread_data->store; BUG_ON(logger == NULL && store != NULL); BUG_ON(logger != NULL && store == NULL); BUG_ON(logger == NULL && store == NULL); if (p->flow == NULL) return TM_ECODE_OK; Flow * const f = p->flow; FLOWLOCK_WRLOCK(f); /* WRITE lock before we updated flow logged id */ AppProto alproto = f->alproto; if (AppLayerParserProtocolIsTxAware(p->proto, alproto) == 0) goto end; if (AppLayerParserProtocolHasLogger(p->proto, alproto) == 0) goto end; void *alstate = f->alstate; if (alstate == NULL) { SCLogDebug("no alstate"); goto end; } uint64_t total_txs = AppLayerParserGetTxCnt(p->proto, alproto, alstate); uint64_t tx_id = AppLayerParserGetTransactionLogId(f->alparser); int tx_progress_done_value_ts = AppLayerParserGetStateProgressCompletionStatus(p->proto, alproto, STREAM_TOSERVER); int tx_progress_done_value_tc = AppLayerParserGetStateProgressCompletionStatus(p->proto, alproto, STREAM_TOCLIENT); for (; tx_id < total_txs; tx_id++) { int proto_logged = 0; void *tx = AppLayerParserGetTx(p->proto, alproto, alstate, tx_id); if (tx == NULL) { SCLogDebug("tx is NULL not logging"); continue; } if (!(AppLayerParserStateIssetFlag(f->alparser, APP_LAYER_PARSER_EOF))) { int tx_progress = AppLayerParserGetStateProgress(p->proto, alproto, tx, FlowGetDisruptionFlags(f, STREAM_TOSERVER)); if (tx_progress < tx_progress_done_value_ts) { SCLogDebug("progress not far enough, not logging"); break; } tx_progress = AppLayerParserGetStateProgress(p->proto, alproto, tx, FlowGetDisruptionFlags(f, STREAM_TOCLIENT)); if (tx_progress < tx_progress_done_value_tc) { SCLogDebug("progress not far enough, not logging"); break; } } // call each logger here (pseudo code) logger = list; store = op_thread_data->store; while (logger && store) { BUG_ON(logger->LogFunc == NULL); SCLogDebug("logger %p", logger); if (logger->alproto == alproto) { SCLogDebug("alproto match, logging tx_id %ju", tx_id); PACKET_PROFILING_TMM_START(p, logger->module_id); logger->LogFunc(tv, store->thread_data, p, f, alstate, tx, tx_id); PACKET_PROFILING_TMM_END(p, logger->module_id); proto_logged = 1; } logger = logger->next; store = store->next; BUG_ON(logger == NULL && store != NULL); BUG_ON(logger != NULL && store == NULL); } if (proto_logged) { SCLogDebug("updating log tx_id %ju", tx_id); AppLayerParserSetTransactionLogId(f->alparser); } } end: FLOWLOCK_UNLOCK(f); return TM_ECODE_OK; }
static TmEcode OutputTxLog(ThreadVars *tv, Packet *p, void *thread_data) { BUG_ON(thread_data == NULL); if (list == NULL) { /* No child loggers registered. */ return TM_ECODE_OK; } OutputLoggerThreadData *op_thread_data = (OutputLoggerThreadData *)thread_data; if (p->flow == NULL) return TM_ECODE_OK; Flow * const f = p->flow; const uint8_t ipproto = f->proto; const AppProto alproto = f->alproto; if (AppLayerParserProtocolIsTxAware(p->proto, alproto) == 0) goto end; if (AppLayerParserProtocolHasLogger(p->proto, alproto) == 0) goto end; const LoggerId logger_expectation = AppLayerParserProtocolGetLoggerBits(p->proto, alproto); if (logger_expectation == 0) goto end; void *alstate = f->alstate; if (alstate == NULL) { SCLogDebug("no alstate"); goto end; } const uint8_t ts_disrupt_flags = FlowGetDisruptionFlags(f, STREAM_TOSERVER); const uint8_t tc_disrupt_flags = FlowGetDisruptionFlags(f, STREAM_TOCLIENT); const uint64_t total_txs = AppLayerParserGetTxCnt(f, alstate); uint64_t tx_id = AppLayerParserGetTransactionLogId(f->alparser); uint64_t max_id = tx_id; int logged = 0; int gap = 0; AppLayerGetTxIteratorFunc IterFunc = AppLayerGetTxIterator(ipproto, alproto); AppLayerGetTxIterState state; memset(&state, 0, sizeof(state)); while (1) { AppLayerGetTxIterTuple ires = IterFunc(ipproto, alproto, alstate, tx_id, total_txs, &state); if (ires.tx_ptr == NULL) break; void * const tx = ires.tx_ptr; tx_id = ires.tx_id; LoggerId tx_logged = AppLayerParserGetTxLogged(f, alstate, tx); const LoggerId tx_logged_old = tx_logged; SCLogDebug("logger: expect %08x, have %08x", logger_expectation, tx_logged); if (tx_logged == logger_expectation) { /* tx already fully logged */ goto next_tx; } int tx_progress_ts = AppLayerParserGetStateProgress(p->proto, alproto, tx, ts_disrupt_flags); int tx_progress_tc = AppLayerParserGetStateProgress(p->proto, alproto, tx, tc_disrupt_flags); SCLogDebug("tx_progress_ts %d tx_progress_tc %d", tx_progress_ts, tx_progress_tc); const OutputTxLogger *logger = list; const OutputLoggerThreadStore *store = op_thread_data->store; #ifdef DEBUG_VALIDATION BUG_ON(logger == NULL && store != NULL); BUG_ON(logger != NULL && store == NULL); BUG_ON(logger == NULL && store == NULL); #endif while (logger && store) { BUG_ON(logger->LogFunc == NULL); SCLogDebug("logger %p, LogCondition %p, ts_log_progress %d " "tc_log_progress %d", logger, logger->LogCondition, logger->ts_log_progress, logger->tc_log_progress); if (logger->alproto == alproto && (tx_logged_old & (1<<logger->logger_id)) == 0) { SCLogDebug("alproto match, logging tx_id %"PRIu64, tx_id); if (!(AppLayerParserStateIssetFlag(f->alparser, APP_LAYER_PARSER_EOF))) { if (logger->LogCondition) { int r = logger->LogCondition(tv, p, alstate, tx, tx_id); if (r == FALSE) { SCLogDebug("conditions not met, not logging"); goto next_logger; } } else { if (tx_progress_tc < logger->tc_log_progress) { SCLogDebug("progress not far enough, not logging"); goto next_logger; } if (tx_progress_ts < logger->ts_log_progress) { SCLogDebug("progress not far enough, not logging"); goto next_logger; } } } SCLogDebug("Logging tx_id %"PRIu64" to logger %d", tx_id, logger->logger_id); PACKET_PROFILING_LOGGER_START(p, logger->logger_id); logger->LogFunc(tv, store->thread_data, p, f, alstate, tx, tx_id); PACKET_PROFILING_LOGGER_END(p, logger->logger_id); tx_logged |= (1<<logger->logger_id); } next_logger: logger = logger->next; store = store->next; #ifdef DEBUG_VALIDATION BUG_ON(logger == NULL && store != NULL); BUG_ON(logger != NULL && store == NULL); #endif } if (tx_logged != tx_logged_old) { SCLogDebug("logger: storing %08x (was %08x)", tx_logged, tx_logged_old); AppLayerParserSetTxLogged(p->proto, alproto, alstate, tx, tx_logged); } /* If all loggers logged set a flag and update the last tx_id * that was logged. * * If not all loggers were logged we flag that there was a gap * so any subsequent transactions in this loop don't increase * the maximum ID that was logged. */ if (!gap && tx_logged == logger_expectation) { logged = 1; max_id = tx_id; } else { gap = 1; } next_tx: if (!ires.has_next) break; tx_id++; } /* Update the the last ID that has been logged with all * transactions before it. */ if (logged) { SCLogDebug("updating log tx_id %"PRIu64, max_id); AppLayerParserSetTransactionLogId(f->alparser, max_id + 1); } end: return TM_ECODE_OK; }
static TmEcode OutputTxLog(ThreadVars *tv, Packet *p, void *thread_data) { BUG_ON(thread_data == NULL); if (list == NULL) { /* No child loggers registered. */ return TM_ECODE_OK; } OutputLoggerThreadData *op_thread_data = (OutputLoggerThreadData *)thread_data; if (p->flow == NULL) return TM_ECODE_OK; Flow * const f = p->flow; const AppProto alproto = f->alproto; if (AppLayerParserProtocolIsTxAware(p->proto, alproto) == 0) goto end; if (AppLayerParserProtocolHasLogger(p->proto, alproto) == 0) goto end; void *alstate = f->alstate; if (alstate == NULL) { SCLogDebug("no alstate"); goto end; } const uint8_t ts_disrupt_flags = FlowGetDisruptionFlags(f, STREAM_TOSERVER); const uint8_t tc_disrupt_flags = FlowGetDisruptionFlags(f, STREAM_TOCLIENT); const uint64_t total_txs = AppLayerParserGetTxCnt(f, alstate); uint64_t tx_id = AppLayerParserGetTransactionLogId(f->alparser); uint64_t max_id = tx_id; int logged = 0; int gap = 0; for (; tx_id < total_txs; tx_id++) { /* Track the number of loggers, of the eligible loggers that * actually logged this transaction. They all must have logged * before the transaction is considered logged. */ int number_of_loggers = 0; int loggers_that_logged = 0; void *tx = AppLayerParserGetTx(p->proto, alproto, alstate, tx_id); if (tx == NULL) { SCLogDebug("tx is NULL not logging"); continue; } int tx_progress_ts = AppLayerParserGetStateProgress(p->proto, alproto, tx, ts_disrupt_flags); int tx_progress_tc = AppLayerParserGetStateProgress(p->proto, alproto, tx, tc_disrupt_flags); SCLogDebug("tx_progress_ts %d tx_progress_tc %d", tx_progress_ts, tx_progress_tc); const OutputTxLogger *logger = list; const OutputLoggerThreadStore *store = op_thread_data->store; #ifdef DEBUG_VALIDATION BUG_ON(logger == NULL && store != NULL); BUG_ON(logger != NULL && store == NULL); BUG_ON(logger == NULL && store == NULL); #endif while (logger && store) { BUG_ON(logger->LogFunc == NULL); SCLogDebug("logger %p, LogCondition %p, ts_log_progress %d " "tc_log_progress %d", logger, logger->LogCondition, logger->ts_log_progress, logger->tc_log_progress); if (logger->alproto == alproto) { SCLogDebug("alproto match, logging tx_id %"PRIu64, tx_id); number_of_loggers++; if (AppLayerParserGetTxLogged(f, alstate, tx, logger->id)) { SCLogDebug("logger has already logged this transaction"); loggers_that_logged++; goto next; } if (!(AppLayerParserStateIssetFlag(f->alparser, APP_LAYER_PARSER_EOF))) { if (logger->LogCondition) { int r = logger->LogCondition(tv, p, alstate, tx, tx_id); if (r == FALSE) { SCLogDebug("conditions not met, not logging"); goto next; } } else { if (tx_progress_tc < logger->tc_log_progress) { SCLogDebug("progress not far enough, not logging"); goto next; } if (tx_progress_ts < logger->ts_log_progress) { SCLogDebug("progress not far enough, not logging"); goto next; } } } SCLogDebug("Logging tx_id %"PRIu64" to logger %d", tx_id, logger->logger_id); PACKET_PROFILING_LOGGER_START(p, logger->logger_id); logger->LogFunc(tv, store->thread_data, p, f, alstate, tx, tx_id); PACKET_PROFILING_LOGGER_END(p, logger->logger_id); AppLayerParserSetTxLogged(p->proto, alproto, alstate, tx, logger->id); loggers_that_logged++; } next: logger = logger->next; store = store->next; #ifdef DEBUG_VALIDATION BUG_ON(logger == NULL && store != NULL); BUG_ON(logger != NULL && store == NULL); #endif } /* If all loggers logged set a flag and update the last tx_id * that was logged. * * If not all loggers were logged we flag that there was a gap * so any subsequent transactions in this loop don't increase * the maximum ID that was logged. */ if (!gap && loggers_that_logged == number_of_loggers) { logged = 1; max_id = tx_id; } else { gap = 1; } } /* Update the the last ID that has been logged with all * transactions before it. */ if (logged) { SCLogDebug("updating log tx_id %"PRIu64, max_id); AppLayerParserSetTransactionLogId(f->alparser, max_id + 1); } end: return TM_ECODE_OK; }
/** \internal * \brief Parse DNS request packet */ static int DNSUDPRequestParse(Flow *f, void *dstate, AppLayerParserState *pstate, uint8_t *input, uint32_t input_len, void *local_data) { DNSState *dns_state = (DNSState *)dstate; SCLogDebug("starting %u", input_len); if (input == NULL && AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF)) { SCReturnInt(1); } /** \todo remove this when PP is fixed to enforce ipproto */ if (f != NULL && f->proto != IPPROTO_UDP) SCReturnInt(-1); if (input == NULL || input_len == 0 || input_len < sizeof(DNSHeader)) { SCLogDebug("ilen too small, hoped for at least %"PRIuMAX, (uintmax_t)sizeof(DNSHeader)); goto insufficient_data; } DNSHeader *dns_header = (DNSHeader *)input; SCLogDebug("DNS %p", dns_header); if (DNSValidateRequestHeader(dns_state, dns_header) < 0) goto bad_data; uint16_t q; const uint8_t *data = input + sizeof(DNSHeader); for (q = 0; q < ntohs(dns_header->questions); q++) { uint8_t fqdn[DNS_MAX_SIZE]; uint16_t fqdn_offset = 0; if (input + input_len < data + 1) { SCLogDebug("input buffer too small for len"); goto insufficient_data; } SCLogDebug("query length %u", *data); while (*data != 0) { if (*data > 63) { /** \todo set event?*/ goto insufficient_data; } uint8_t length = *data; data++; if (length == 0) { break; } if (input + input_len < data + length) { SCLogDebug("input buffer too small for domain of len %u", length); goto insufficient_data; } //PrintRawDataFp(stdout, data, qry->length); if ((size_t)(fqdn_offset + length + 1) < sizeof(fqdn)) { memcpy(fqdn + fqdn_offset, data, length); fqdn_offset += length; fqdn[fqdn_offset++] = '.'; } else { /** \todo set event? */ goto insufficient_data; } data += length; if (input + input_len < data + 1) { SCLogDebug("input buffer too small for len(2)"); goto insufficient_data; } SCLogDebug("qry length %u", *data); } if (fqdn_offset) { fqdn_offset--; } data++; if (input + input_len < data + sizeof(DNSQueryTrailer)) { SCLogDebug("input buffer too small for DNSQueryTrailer"); goto insufficient_data; } DNSQueryTrailer *trailer = (DNSQueryTrailer *)data; SCLogDebug("trailer type %04x class %04x", ntohs(trailer->type), ntohs(trailer->clazz)); data += sizeof(DNSQueryTrailer); /* store our data */ if (dns_state != NULL) { DNSStoreQueryInState(dns_state, fqdn, fqdn_offset, ntohs(trailer->type), ntohs(trailer->clazz), ntohs(dns_header->tx_id)); } } SCReturnInt(1); bad_data: insufficient_data: SCReturnInt(-1); }
/** \internal * \brief DNS UDP record parser, entry function * * Parses a DNS UDP record and fills the DNS state * */ static int DNSUDPResponseParse(Flow *f, void *dstate, AppLayerParserState *pstate, uint8_t *input, uint32_t input_len, void *local_data) { DNSState *dns_state = (DNSState *)dstate; SCLogDebug("starting %u", input_len); if (input == NULL && AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF)) { SCReturnInt(1); } /** \todo remove this when PP is fixed to enforce ipproto */ if (f != NULL && f->proto != IPPROTO_UDP) SCReturnInt(-1); if (input == NULL || input_len == 0 || input_len < sizeof(DNSHeader)) { SCLogDebug("ilen too small, hoped for at least %"PRIuMAX, (uintmax_t)sizeof(DNSHeader)); goto insufficient_data; } DNSHeader *dns_header = (DNSHeader *)input; SCLogDebug("DNS %p %04x %04x", dns_header, ntohs(dns_header->tx_id), dns_header->flags); DNSTransaction *tx = NULL; int found = 0; if ((tx = DNSTransactionFindByTxId(dns_state, ntohs(dns_header->tx_id))) != NULL) found = 1; if (!found) { SCLogDebug("DNS_DECODER_EVENT_UNSOLLICITED_RESPONSE"); DNSSetEvent(dns_state, DNS_DECODER_EVENT_UNSOLLICITED_RESPONSE); } if (DNSValidateResponseHeader(dns_state, dns_header) < 0) goto bad_data; SCLogDebug("queries %04x", ntohs(dns_header->questions)); uint16_t q; const uint8_t *data = input + sizeof(DNSHeader); for (q = 0; q < ntohs(dns_header->questions); q++) { uint8_t fqdn[DNS_MAX_SIZE]; uint16_t fqdn_offset = 0; if (input + input_len < data + 1) { SCLogDebug("input buffer too small for len"); goto insufficient_data; } SCLogDebug("qry length %u", *data); while (*data != 0) { uint8_t length = *data; data++; if (length == 0) break; if (input + input_len < data + length) { SCLogDebug("input buffer too small for domain of len %u", length); goto insufficient_data; } //PrintRawDataFp(stdout, data, length); if ((size_t)(fqdn_offset + length + 1) < sizeof(fqdn)) { memcpy(fqdn + fqdn_offset, data, length); fqdn_offset += length; fqdn[fqdn_offset++] = '.'; } data += length; if (input + input_len < data + 1) { SCLogDebug("input buffer too small for len"); goto insufficient_data; } SCLogDebug("length %u", *data); } if (fqdn_offset) { fqdn_offset--; } data++; if (input + input_len < data + sizeof(DNSQueryTrailer)) { SCLogDebug("input buffer too small for DNSQueryTrailer"); goto insufficient_data; } #if DEBUG DNSQueryTrailer *trailer = (DNSQueryTrailer *)data; SCLogDebug("trailer type %04x class %04x", ntohs(trailer->type), ntohs(trailer->clazz)); #endif data += sizeof(DNSQueryTrailer); } SCLogDebug("answer_rr %04x", ntohs(dns_header->answer_rr)); for (q = 0; q < ntohs(dns_header->answer_rr); q++) { data = DNSReponseParse(dns_state, dns_header, q, DNS_LIST_ANSWER, input, input_len, data); if (data == NULL) { goto insufficient_data; } } SCLogDebug("authority_rr %04x", ntohs(dns_header->authority_rr)); for (q = 0; q < ntohs(dns_header->authority_rr); q++) { data = DNSReponseParse(dns_state, dns_header, q, DNS_LIST_AUTHORITY, input, input_len, data); if (data == NULL) { goto insufficient_data; } } /* parse rcode, e.g. "noerror" or "nxdomain" */ uint8_t rcode = ntohs(dns_header->flags) & 0x0F; if (rcode <= DNS_RCODE_NOTZONE) { SCLogDebug("rcode %u", rcode); if (tx != NULL) tx->rcode = rcode; } else { /* this is not invalid, rcodes can be user defined */ SCLogDebug("unexpected DNS rcode %u", rcode); } if (ntohs(dns_header->flags) & 0x0080) { SCLogDebug("recursion desired"); if (tx != NULL) tx->recursion_desired = 1; } if (tx != NULL) { tx->replied = 1; } SCReturnInt(1); bad_data: insufficient_data: DNSSetEvent(dns_state, DNS_DECODER_EVENT_MALFORMED_DATA); SCReturnInt(-1); }