Skip to content

Instantly share code, notes, and snippets.

@jasonish
Created February 5, 2018 15:56
Show Gist options
  • Save jasonish/c84653483ebeea419f7562e0389f95c0 to your computer and use it in GitHub Desktop.
Save jasonish/c84653483ebeea419f7562e0389f95c0 to your computer and use it in GitHub Desktop.
diff --git a/src/app-layer-dns-udp.c b/src/app-layer-dns-udp.c
index 9f1ec9d09..747b441b3 100644
--- a/src/app-layer-dns-udp.c
+++ b/src/app-layer-dns-udp.c
@@ -387,6 +387,35 @@ static void DNSUDPConfigure(void)
DNSConfigSetGlobalMemcap(global_memcap);
}
+static void *DNSUDPGetTxIterator(const uint8_t ipproto, const AppProto alproto,
+ void *alstate, uint64_t min_tx_id, uint64_t max_tx_id,
+ uint64_t *ret_tx_id, AppLayerGetTxIterState *istate)
+{
+ DNSState *dns_state = alstate;
+ DNSTransaction *tx = NULL;
+
+ /* If we have istate, set tx to the next transaction. Otherwise
+ * set it to the the first transaction in the list. */
+ if (istate != NULL && istate->un.ptr != NULL) {
+ tx = TAILQ_NEXT(((DNSTransaction *)istate->un.ptr), next);
+ } else {
+ tx = TAILQ_FIRST(&dns_state->tx_list);
+ }
+
+ while (tx != NULL) {
+ if (tx->tx_num > max_tx_id) {
+ break;
+ }
+ if (tx->tx_num >= min_tx_id) {
+ *ret_tx_id = tx->tx_num + 1;
+ return tx;
+ }
+ tx = TAILQ_NEXT(tx, next);
+ }
+
+ return NULL;
+}
+
void RegisterDNSUDPParsers(void)
{
const char *proto_name = "dns";
@@ -461,6 +490,9 @@ void RegisterDNSUDPParsers(void)
DNSAppLayerRegisterGetEventInfo(IPPROTO_UDP, ALPROTO_DNS);
+ AppLayerParserRegisterGetTxIterator(IPPROTO_UDP, ALPROTO_DNS,
+ DNSUDPGetTxIterator);
+
DNSUDPConfigure();
} else {
SCLogInfo("Parsed disabled for %s protocol. Protocol detection"
@victorjulien
Copy link

victorjulien commented Feb 5, 2018

istate should never be null, I guess it would make sense to add a __attribute(nonnull). We pass this stuct to the iterator: https://github.com/OISF/suricata/pull/3214/files#diff-2f9c03681d2d9c60a050b9b472771473R169
As we first null it you can directly check the istate->un.ptr == NULL.

Also, the idea is that you're updating the 'istate' with the info to make sure the next call continues. Probably something like (pseudo code):

if istate->un.ptr == NULL {
  tx = get_first_tx
  istate->un.ptr = tx;
   return tx
} else {
  // return tx after the tx stored in 'istate'
  tx = get_next_from(istate->un.ptr)
  istate->un.ptr = tx;
  return tx
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment