void dowse_output(const char *descr, iaddr from, iaddr to, uint8_t proto, int isfrag, unsigned sport, unsigned dport, my_bpftimeval ts, const u_char *pkt_copy, unsigned olen, const u_char *dnspkt, unsigned dnslen) { /* dnspkt may be NULL if IP packet does not contain a valid DNS message */ char output[MAX_OUTPUT]; if (dnspkt) { ns_msg msg; int qdcount; ns_rr rr; int *val; char *sval; char *extracted; char *resolved; char *from; int res; char action = 'A'; char from_color[16]; ns_initparse(dnspkt, dnslen, &msg); if (!ns_msg_getflag(msg, ns_f_qr)) return; /* * -- flags -- * 0 1 5 6 7 8 11 15 * +----+----------------+----+----+----+-----------+----------------+ * | QR | Operation Code | AA | TC | RA | Zero | Recode | * +----+----------------+----+----+----+-----------+----------------+ * * Question/Response : ns_f_qr * Operation code : ns_f_opcode * Authoritative Answer : ns_f_aa * Truncation occurred : ns_f_tc * Recursion Desired : ns_f_rd * Recursion Available : ns_f_ra * MBZ : ns_f_z * Authentic Data (DNSSEC) : ns_f_ad * Checking Disabled (DNSSEC) : ns_f_cd * Response code : ns_f_rcode */ // logerr("msg: %p",msg); qdcount = ns_msg_count(msg, ns_s_qd); if (qdcount > 0 && 0 == ns_parserr(&msg, ns_s_qd, 0, &rr)) { // where the query comes from from = ia_resolv(to); // if its from ourselves omit it if(strncmp(from,hostname,MAX_DOMAIN)==0) return; if(own_ipv4) if(strncmp(from,own_ipv4,MAX_DOMAIN)==0) return; // not reverse resolved means not known by Dowse, code RED if(is_ip(from)) strcpy(from_color,"#FF0000"); resolved = ns_rr_name(rr); // what domain is being looked up extracted = extract_domain(resolved); res = hashmap_get(visited, extracted, (void**)(&val)); switch(res) { case MAP_MISSING : // never visited val = malloc(sizeof(int)); *val = 1; // just a placeholder for now res = hashmap_put(visited, strdup(extracted), val); break; case MAP_OK: // already visited action = 'M'; break; // TODO error checks case MAP_FULL: case MAP_OMEM: break; } // compose the path of the detected query // add category if listed if(listpath) { // add known domain list information res = hashmap_get(domainlist, extracted, (void**)(&sval)); switch(res) { case MAP_OK: /* render with the category in front of domain */ snprintf(output,MAX_OUTPUT,"%lu|%s|%c|%s/%s/%s", ts.tv_sec, from, action, tld, sval, extracted); break; default: /* render only the domain in root category */ snprintf(output,MAX_OUTPUT,"%lu|%s|%c|%s/%s", ts.tv_sec, from, action, tld, extracted); break; } } else /* render only the domain in root category */ snprintf(output,MAX_OUTPUT,"%lu|%s|%c|%s/%s", ts.tv_sec, from, action, tld, extracted); /* write to file */ if(fileout) { fputs(output, fileout); fputc('\n',fileout); if(fileout) fflush(fileout); } /* print fast on console for realtime */ if(console) { puts(output); fflush(stdout); } } } }
void dowse_output(const char *descr, iaddr from, iaddr to, uint8_t proto, int isfrag, unsigned sport, unsigned dport, my_bpftimeval ts, const u_char *pkt_copy, unsigned olen, const u_char *dnspkt, unsigned dnslen) { /* dnspkt may be NULL if IP packet does not contain a valid DNS message */ char output[MAX_OUTPUT]; if (dnspkt) { ns_msg msg; int qdcount; ns_rr rr; int *val; char *sval; char *extracted; char *resolved; char *from; int res; char action = 'A'; char from_color[16]; ns_initparse(dnspkt, dnslen, &msg); if (!ns_msg_getflag(msg, ns_f_qr)) return; /* * -- flags -- * 0 1 5 6 7 8 11 15 * +----+----------------+----+----+----+-----------+----------------+ * | QR | Operation Code | AA | TC | RA | Zero | Recode | * +----+----------------+----+----+----+-----------+----------------+ * * Question/Response : ns_f_qr * Operation code : ns_f_opcode * Authoritative Answer : ns_f_aa * Truncation occurred : ns_f_tc * Recursion Desired : ns_f_rd * Recursion Available : ns_f_ra * MBZ : ns_f_z * Authentic Data (DNSSEC) : ns_f_ad * Checking Disabled (DNSSEC) : ns_f_cd * Response code : ns_f_rcode */ // logerr("msg: %p",msg); qdcount = ns_msg_count(msg, ns_s_qd); if (qdcount > 0 && 0 == ns_parserr(&msg, ns_s_qd, 0, &rr)) { // where the query comes from from = ia_resolv(to); // if its from ourselves omit it if(strncmp(from,hostname,MAX_DOMAIN)==0) return; if(own_ipv4) if(strncmp(from,own_ipv4,MAX_DOMAIN)==0) return; // not reverse resolved means not known by Dowse, code RED if(is_ip(from)) strcpy(from_color,"#FF0000"); resolved = ns_rr_name(rr); // what domain is being looked up extracted = extract_domain(resolved); res = hashmap_get(visited, extracted, (void**)(&val)); switch(res) { // TODO: fix malloc and strdup here as they grow as a leak on long term case MAP_MISSING : // never visited /* ==13150== 992 bytes in 248 blocks are definitely lost in loss record 45 of 49 */ /* ==13150== at 0x4C28C20: malloc (vg_replace_malloc.c:296) */ /* ==13150== by 0x5C3D326: dowse_output (dowse.c:417) */ /* ==13150== by 0x404CAB: output (dnscap.c:2201) */ /* ==13150== by 0x406779: network_pkt (dnscap.c:2164) */ /* ==13150== by 0x407065: dl_pkt (dnscap.c:1608) */ /* ==13150== by 0x503F5E9: ??? (in /usr/lib/x86_64-linux-gnu/libpcap.so.1.6.2) */ /* ==13150== by 0x5043783: ??? (in /usr/lib/x86_64-linux-gnu/libpcap.so.1.6.2) */ /* ==13150== by 0x4037E0: poll_pcaps (dnscap.c:1344) */ /* ==13150== by 0x4037E0: main (dnscap.c:406) */ val = malloc(sizeof(int)); *val = 1; // just a placeholder for now /* ==13150== 3,069 bytes in 248 blocks are definitely lost in loss record 47 of 49 */ /* ==13150== at 0x4C28C20: malloc (vg_replace_malloc.c:296) */ /* ==13150== by 0x5511A69: strdup (strdup.c:42) */ /* ==13150== by 0x5C3D34D: dowse_output (dowse.c:419) */ /* ==13150== by 0x404CAB: output (dnscap.c:2201) */ /* ==13150== by 0x406779: network_pkt (dnscap.c:2164) */ /* ==13150== by 0x407065: dl_pkt (dnscap.c:1608) */ /* ==13150== by 0x503F5E9: ??? (in /usr/lib/x86_64-linux-gnu/libpcap.so.1.6.2) */ /* ==13150== by 0x5043783: ??? (in /usr/lib/x86_64-linux-gnu/libpcap.so.1.6.2) */ /* ==13150== by 0x4037E0: poll_pcaps (dnscap.c:1344) */ /* ==13150== by 0x4037E0: main (dnscap.c:406) */ res = hashmap_put(visited, strdup(extracted), val); break; case MAP_OK: // already visited action = 'M'; break; // TODO error checks case MAP_FULL: case MAP_OMEM: break; } // compose the path of the detected query // add category if listed if(listpath) { // add known domain list information res = hashmap_get(domainlist, extracted, (void**)(&sval)); switch(res) { case MAP_OK: /* render with the category in front of domain */ snprintf(output,MAX_OUTPUT,"%lu|%s|%c|%s/%s/%s", ts2epoch(&ts,NULL), // from our epoch.c from, action, tld, sval, extracted); break; default: /* render only the domain in root category */ snprintf(output,MAX_OUTPUT,"%lu|%s|%c|%s/%s", ts2epoch(&ts,NULL), // from our epoch.c from, action, tld, extracted); break; } } else /* render only the domain in root category */ snprintf(output,MAX_OUTPUT,"%lu|%s|%c|%s/%s", ts2epoch(&ts,NULL), // from our epoch.c from, action, tld, extracted); /* write to file */ if(fileout) { fputs(output, fileout); fputc('\n',fileout); if(fileout) fflush(fileout); } /* print fast on console for realtime */ if(console) { puts(output); fflush(stdout); } if(redis) { rreply = redisCommand(redis, "PUBLISH dns-query-channel %s", output); logerr("PUBLISH dns-query-channel: %s\n", rreply->str); freeReplyObject(rreply); } } } }