static int parse_flags_option(struct isl_arg *decl, char **arg, struct isl_prefixes *prefixes, void *opt) { int has_argument; const char *flags; const char *comma; unsigned val; flags = skip_name(decl, arg[0], prefixes, 0, &has_argument); if (!flags) return 0; if (!has_argument && !arg[1]) return 0; if (!has_argument) flags = arg[1]; val = 0; while ((comma = strchr(flags, ',')) != NULL) { if (!set_flag(decl, &val, flags, comma - flags)) return 0; flags = comma + 1; } if (!set_flag(decl, &val, flags, strlen(flags))) return 0; *(unsigned *)(((char *)opt) + decl->offset) = val; return has_argument ? 1 : 2; }
static int parse_str_option(struct isl_arg *decl, char **arg, struct isl_prefixes *prefixes, void *opt) { int has_argument; const char *s; char **p = (char **)(((char *)opt) + decl->offset); s = skip_name(decl, arg[0], prefixes, 0, &has_argument); if (!s) return 0; if (has_argument) { free(*p); *p = strdup(s); return 1; } if (arg[1]) { free(*p); *p = strdup(arg[1]); return 2; } return 0; }
static int parse_ulong_option(struct isl_arg *decl, char **arg, struct isl_prefixes *prefixes, void *opt) { int has_argument; const char *val; char *endptr; unsigned long *p = (unsigned long *)(((char *)opt) + decl->offset); val = skip_name(decl, arg[0], prefixes, 0, &has_argument); if (!val) return 0; if (has_argument) { *p = strtoul(val, NULL, 0); return 1; } if (arg[1]) { unsigned long ul = strtoul(arg[1], &endptr, 0); if (*endptr == '\0') { *p = ul; return 2; } } return 0; }
static int parse_int_option(struct isl_arg *decl, char **arg, struct isl_prefixes *prefixes, void *opt) { int has_argument; const char *val; char *endptr; int *p = (int *)(((char *)opt) + decl->offset); val = skip_name(decl, arg[0], prefixes, 0, &has_argument); if (!val) return 0; if (has_argument) { *p = atoi(val); return 1; } if (arg[1]) { int i = strtol(arg[1], &endptr, 0); if (*endptr == '\0') { *p = i; return 2; } } return 0; }
static int parse_bool_option(struct isl_arg *decl, char **arg, struct isl_prefixes *prefixes, void *opt) { const char *name; unsigned *p = (unsigned *)(((char *)opt) + decl->offset); int next_prefix; if (skip_name(decl, arg[0], prefixes, 0, NULL)) { if ((decl->flags & ISL_ARG_BOOL_ARG) && arg[1]) { char *endptr; int val = strtol(arg[1], &endptr, 0); if (*endptr == '\0' && (val == 0 || val == 1)) { if (decl->offset != (size_t) -1) *p = val; if (decl->u.b.set) decl->u.b.set(opt, val); return 2; } } if (decl->offset != (size_t) -1) *p = 1; if (decl->u.b.set) decl->u.b.set(opt, 1); return 1; } if (!decl->long_name) return 0; name = skip_dash_dash(decl, arg[0]); if (!name) return 0; next_prefix = 0; name = skip_prefixes(name, prefixes, &next_prefix); if (strncmp(name, "no-", 3)) return 0; name += 3; name = skip_prefixes(name, prefixes, &next_prefix); if (match_long_name(decl, name, name + strlen(name))) { if (decl->offset != (size_t) -1) *p = 0; if (decl->u.b.set) decl->u.b.set(opt, 0); return 1; } return 0; }
static void mangle_line (const char * line, const char * prefix) { const char * scan = (skip_name (line)); scan = (skip_lws (scan)); scan = (skip_fixed (scan, '(')); scan = (skip_lws (scan)); scan = (skip_fixed (scan, '"')); write_string (prefix); write_string (scan); write_char ('\n'); fflush (stdout); }
int get_token(const char **ptr, const char *end) { if (*ptr >= end) return 0; char c = *(*ptr)++; if (c == '\\' && *ptr < end) { switch (**ptr) { default: *ptr += 1; break; case '(': case '[': skip_name(ptr, end); break; case '*': case 'f': *ptr += 1; skip_name(ptr, end); break; } } return 1; }
static bool skip_rr(u8 *dns, size_t len, size_t *offset) { u16 rdlength; if (skip_name(dns, len, offset) && ((*offset) + 6) <= len ){ rdlength = dns[(*offset) + 4] << 8 | dns[(*offset) + 5]; debug_dump_buf(dns, len, *offset, "skip_rr"); NFDEBUG("rdlength: %d\n", rdlength); if ((*offset) + 6 + rdlength < len) { (*offset) += 6 + rdlength; return true; } } pr_warn("Skipping RR failed. offset: %zu, len: %zu\n", *offset, len); return false; }
static int parse_long_option(struct isl_arg *decl, char **arg, struct isl_prefixes *prefixes, void *opt) { int has_argument; const char *val; char *endptr; long *p = (long *)(((char *)opt) + decl->offset); val = skip_name(decl, arg[0], prefixes, 0, &has_argument); if (!val) return 0; if (has_argument) { long l = strtol(val, NULL, 0); *p = l; if (decl->u.l.set) decl->u.l.set(opt, l); return 1; } if (arg[1]) { long l = strtol(arg[1], &endptr, 0); if (*endptr == '\0') { *p = l; if (decl->u.l.set) decl->u.l.set(opt, l); return 2; } } if (decl->u.l.default_value != decl->u.l.default_selected) { *p = decl->u.l.default_selected; if (decl->u.l.set) decl->u.l.set(opt, decl->u.l.default_selected); return 1; } return 0; }
static int parse_str_list_option(struct isl_arg *decl, char **arg, struct isl_prefixes *prefixes, void *opt) { int has_argument; const char *s; s = skip_name(decl, arg[0], prefixes, 0, &has_argument); if (!s) return 0; if (has_argument) { isl_arg_str_list_append(decl, opt, s); return 1; } if (arg[1]) { isl_arg_str_list_append(decl, opt, arg[1]); return 2; } return 0; }
static int parse_choice_option(struct isl_arg *decl, char **arg, struct isl_prefixes *prefixes, void *opt) { int i; int has_argument; const char *choice; choice = skip_name(decl, arg[0], prefixes, 0, &has_argument); if (!choice) return 0; if (!has_argument && (!arg[1] || arg[1][0] == '-')) { unsigned u = decl->u.choice.default_selected; *(unsigned *)(((char *)opt) + decl->offset) = u; if (decl->u.choice.set) decl->u.choice.set(opt, u); return 1; } if (!has_argument) choice = arg[1]; for (i = 0; decl->u.choice.choice[i].name; ++i) { unsigned u; if (strcmp(choice, decl->u.choice.choice[i].name)) continue; u = decl->u.choice.choice[i].value; *(unsigned *)(((char *)opt) + decl->offset) = u; if (decl->u.choice.set) decl->u.choice.set(opt, u); return has_argument ? 1 : 2; } return 0; }
static int parse_reply(char *response, size_t nbytes) { dns_header_t header; dns_query_t *q = NULL, *prev = NULL; dns_rr_t reply; char result[512] = ""; short rr; int r = -1; unsigned const char *eop = (unsigned char *) response + nbytes; unsigned char *ptr = (unsigned char *) response; egg_memcpy(&header, ptr, HEAD_SIZE); ptr += HEAD_SIZE; /* header.id is already in our order, echoed by the server */ header.flags = ntohs(header.flags); header.question_count = ntohs(header.question_count); header.answer_count = ntohs(header.answer_count); header.ar_count = ntohs(header.ar_count); header.ns_count = ntohs(header.ns_count); // print_header(header); /* Find our copy of the query before proceeding. */ for (q = query_head; q; q = q->next) { if (q->id == header.id) break; prev = q; } if (!q) return 0; // /* destroy our async timeout */ // timer_destroy(q->timer_id); /* Pass over the questions. */ for (rr = 0; rr < header.question_count; rr++) { ptr += skip_name(ptr); ptr += 4; } /* End of questions. */ // for (rr = 0; rr < header.answer_count + header.ar_count + header.ns_count; rr++) { q->answers += header.answer_count; for (rr = 0; rr < header.answer_count; rr++) { result[0] = 0; /* Read in the answer. */ ptr += skip_name(ptr); egg_memcpy(&reply, ptr, RR_SIZE); ptr += RR_SIZE; reply.type = ntohs(reply.type); reply.dclass = ntohs(reply.dclass); reply.rdlength = ntohs(reply.rdlength); reply.ttl = ntohl(reply.ttl); /* Save the lowest ttl */ if (reply.ttl && ((!q->answer.ttl) || (q->answer.ttl > reply.ttl))) q->answer.ttl = reply.ttl; // print_reply(reply); switch (reply.type) { case DNS_A: egg_inet_ntop(AF_INET, ptr, result, 512); answer_add(&q->answer, result); break; case DNS_AAAA: #ifdef USE_IPV6 egg_inet_ntop(AF_INET6, ptr, result, 512); answer_add(&q->answer, result); #endif /* USE_IPV6 */ break; case DNS_PTR: r = my_dn_expand((const unsigned char *) response, eop, ptr, result, sizeof(result)); if (r != -1 && result[0]) answer_add(&q->answer, result); break; default: sdprintf("Unhandled DNS reply type: %d", reply.type); break; } ptr += reply.rdlength; if ((size_t) (ptr - (unsigned char*) response) > nbytes) { sdprintf("MALFORMED/TRUNCATED DNS PACKET detected (need TCP)."); q->remaining = 0; break; } } /* Don't continue if we haven't gotten all expected replies. */ if (--q->remaining > 0) return 0; if (q->answer.len == 0) { sdprintf("Failed to get any answers for query"); if (prev) prev->next = q->next; else query_head = q->next; q->callback(q->id, q->client_data, q->query, NULL); free(q->query); if (q->ip) free(q->ip); free(q); return 1; /* get a new server */ } /* Ok, we have, so now issue the callback with the answers. */ if (prev) prev->next = q->next; else query_head = q->next; cache_add(q->query, &q->answer); q->callback(q->id, q->client_data, q->query, q->answer.list); answer_free(&q->answer); free(q->query); if (q->ip) free(q->ip); free(q); return(0); }
static void sort_rrset(struct dns_header *header, size_t plen, u16 *rr_desc, int rrsetidx, unsigned char **rrset, char *buff1, char *buff2) { int swap, quit, i; do { for (swap = 0, i = 0; i < rrsetidx-1; i++) { int rdlen1, rdlen2, left1, left2, len1, len2, len, rc; u16 *dp1, *dp2; unsigned char *end1, *end2; unsigned char *p1 = skip_name(rrset[i], header, plen, 10); unsigned char *p2 = skip_name(rrset[i+1], header, plen, 10); p1 += 8; /* skip class, type, ttl */ GETSHORT(rdlen1, p1); end1 = p1 + rdlen1; p2 += 8; /* skip class, type, ttl */ GETSHORT(rdlen2, p2); end2 = p2 + rdlen2; dp1 = dp2 = rr_desc; for (quit = 0, left1 = 0, left2 = 0, len1 = 0, len2 = 0; !quit;) { if (left1 != 0) memmove(buff1, buff1 + len1 - left1, left1); if ((len1 = get_rdata(header, plen, end1, buff1 + left1, &p1, &dp1)) == 0) { quit = 1; len1 = end1 - p1; memcpy(buff1 + left1, p1, len1); } len1 += left1; if (left2 != 0) memmove(buff2, buff2 + len2 - left2, left2); if ((len2 = get_rdata(header, plen, end2, buff2 + left2, &p2, &dp2)) == 0) { quit = 1; len2 = end2 - p2; memcpy(buff2 + left2, p2, len2); } len2 += left2; if (len1 > len2) left1 = len1 - len2, left2 = 0, len = len2; else left2 = len2 - len1, left1 = 0, len = len1; rc = memcmp(buff1, buff2, len); if (rc == 1 || (rc == 0 && quit && len1 > len2)) { unsigned char *tmp = rrset[i+1]; rrset[i+1] = rrset[i]; rrset[i] = tmp; swap = quit = 1; } } } } while (swap); }
//---------------------------------------------------------------------------- //Empfang der Antwort vom DNS Server void dns_get(void) { unsigned int byte_count; unsigned int id; unsigned int flags; unsigned int qdcount; unsigned int answ_cnt; unsigned int antype; unsigned int anclass; unsigned int rdlen; unsigned char ip[4]; DNS_DEBUG("** DNS DATA GET! **\r\n"); id = eth_buffer[UDP_DATA_START+ 0]*256; id += eth_buffer[UDP_DATA_START+ 1]; DNS_DEBUG("ID %4x\r\n", id); flags = eth_buffer[UDP_DATA_START+ 2]*256; flags += eth_buffer[UDP_DATA_START+ 3]; DNS_DEBUG("Flags %4x\r\n", flags); qdcount = eth_buffer[UDP_DATA_START+ 4]*256; qdcount += eth_buffer[UDP_DATA_START+ 5]; DNS_DEBUG("QDCOUNT %4x\r\n", qdcount); answ_cnt = eth_buffer[UDP_DATA_START+ 6]*256; answ_cnt += eth_buffer[UDP_DATA_START+ 7]; DNS_DEBUG("ANCOUNT %4x\r\n", answ_cnt); if ( (flags & 0x000f) != 0 ) //RCODE 0=no error { DNS_DEBUG("Err in flags: %4x\r\n", flags); dns_state = DNS_STATE_REC_ERR; return; } // nscount and arcount discarded. Jump to the questions and answers byte_count = 12; // Skip the question... byte_count += skip_name( (char *)ð_buffer[UDP_DATA_START + byte_count] ); byte_count += 4; //QTYPE + QCLASS // now the answer: while(answ_cnt > 0) { // first byte of the ARR determines a compressed record or a normal one. if( (eth_buffer[UDP_DATA_START + byte_count] & 0xc0) != 0 ) // Compressed name { // the remaining 14 bits byte_count += 2; // of the 2 bytes are the pointer // to the name... but ignored } else // Not compressed... { byte_count += skip_name( (char *)ð_buffer[UDP_DATA_START + byte_count] ); } antype = eth_buffer[UDP_DATA_START + byte_count++]*256; antype += eth_buffer[UDP_DATA_START + byte_count++]; //DNS_DEBUG("TYPE %4x\r\n",antype); anclass = eth_buffer[UDP_DATA_START + byte_count++]*256; anclass += eth_buffer[UDP_DATA_START + byte_count++]; //DNS_DEBUG("CLASS %4x\r\n",anclass); // skip TTL byte_count += 4; rdlen = eth_buffer[UDP_DATA_START + byte_count++]*256; rdlen += eth_buffer[UDP_DATA_START + byte_count++]; //DNS_DEBUG("RDLEN %4x\r\n",rdlen); // Check for IP address type and Internet class. Others are discarded. if(antype == 1 && anclass == 1 && rdlen == 4 ) { ip[0] = eth_buffer[UDP_DATA_START + byte_count++]; ip[1] = eth_buffer[UDP_DATA_START + byte_count++]; ip[2] = eth_buffer[UDP_DATA_START + byte_count++]; ip[3] = eth_buffer[UDP_DATA_START + byte_count++]; DNS_DEBUG("IP address %1i.%1i.%1i.%1i\r\n",ip[0], ip[1], ip[2], ip[3]); if ( dns_state != DNS_STATE_FINISHED ) { (*((unsigned long*)&dns_resolved_ip[0])) = (*((unsigned long*)&ip[0])); dns_state = DNS_STATE_FINISHED; } } else { byte_count += rdlen; } answ_cnt -= 1; } //while answ_cnt >0 }
/** * This is the main function of the DNS parser. * * This is where the each DNS 'answer' (or 'additional' or 'authoritative') * record is parsed. Mostly, we ignore the return code, though some functions * pay attention to and provide slightly different information depending * upon the opcode. */ static void dns_parse_resource_record(struct Ferret *ferret, struct NetFrame *frame, const unsigned char *px, unsigned length, struct DNSRECORD *rec, struct DNS *dns) { char name[512]; /* reserve a longer name than the max theoretical limit */ unsigned name_length; char name2[512]; /* reserve a longer name than the max theoretical limit */ unsigned name2_length; unsigned ip_address; unsigned offset = rec->rdata_offset; unsigned offset_max = MIN(rec->rdata_offset+rec->rdata_length, length); /* MULTICAST DNS (mDNS): handle the multicast DNS records differently * from normal DNS records. */ if (!dns->is_response && frame->dst_port == 5353) { bonjour_parse_resource_record(ferret, frame, px, length, rec, dns); return; } else if (dns->is_response && (frame->src_port == 5353 || (frame->dst_port == 5353 && frame->src_port != 53))) { bonjour_parse_resource_record(ferret, frame, px, length, rec, dns); return; } /* NETBIOS: handle NetBIOS records differently from normal DNS records */ if (!dns->is_response && frame->dst_port == 137) { netbios_parse_resource_record(ferret, frame, px, length, rec, dns); return; } else if (dns->is_response && frame->src_port == 137) { netbios_parse_resource_record(ferret, frame, px, length, rec, dns); return; } /* First, let's extract a pretty version of the name */ name_length = dns_extract_name(frame, px, length, rec->name_offset, name, sizeof(name)); if (rec->type == 0x8001) FRAMERR(frame, "TODO\n"); if (rec->clss == 0xfe) return; /* RFC2671 - Extension Mechanisms for DNS (EDNS0) */ if (rec->type == 41) { /* Regress: defcon2008/dump000.pca(12541) */ /* TODO: parse this */ return; } /* Haven't implemented dynamic update yet * TODO: */ if (dns->opcode == 21 || dns->opcode == 5) return; switch (rec->type<<16 | rec->clss) { case TYPECLASS(1,0x8001): /* type=A(IPv4 address), class=INTERNET(cache flush) */ bonjour_parse_resource_record(ferret, frame, px, length, rec, dns); break; case TYPECLASS(1,1): /* type=A(IPv4 address), class=INTERNET */ if (!is_valid_opcode(dns->opcode, 0x10, 5, -1)) { FRAMERR(frame, "%s: unknown opcode=%d\n", "DNS", dns->opcode); return; } ip_address = ex32be(px+rec->rdata_offset); if (rec->rdata_length != 4) FRAMERR(frame, "dns: data not 4-bytes long, was %d-bytes instead (class=%d, type=%d, name=%s)\n", rec->rdata_length, rec->clss, rec->type, name); JOTDOWN(ferret, JOT_PRINT("ID-DNS", name, name_length), JOT_IPv4("address", ip_address), 0); break; case TYPECLASS(2,1): /* type=NS, class=INTERNET */ if (!is_valid_opcode(dns->opcode, 0x10, -1)) { FRAMERR(frame, "%s: unknown opcode=%d\n", "DNS", dns->opcode); return; } name2_length = dns_extract_name(frame, px, length, rec->rdata_offset, name2, sizeof(name2)); ip_address = dns_resolve_alias(frame, px, length, dns, name2, 0); JOTDOWN(ferret, JOT_PRINT("ID-DNS", name, name_length), JOT_PRINT("Name-Server", name2, name2_length), JOT_IPv4("address", ip_address), 0); break; case TYPECLASS(5,1): /*type=CNAME(aliased canonical name), class=INTERNET */ if (!is_valid_opcode(dns->opcode, 0x10, 5, -1)) { FRAMERR(frame, "%s: unknown opcode=%d\n", "DNS", dns->opcode); return; } name2_length = dns_extract_name(frame, px, length, rec->rdata_offset, name2, sizeof(name2)); ip_address = dns_resolve_alias(frame, px, length, dns, name2, 0); if (ip_address != 0) { JOTDOWN(ferret, JOT_PRINT("ID-DNS", name, name_length), JOT_IPv4("alias",ip_address), 0); } JOTDOWN(ferret, JOT_PRINT("ID-DNS", name, name_length), JOT_PRINT("alias", name2, name2_length), 0); break; case TYPECLASS(6,1): /*type=SOA, class=INTERNET*/ if (!is_valid_opcode(dns->opcode, 0x10, -1)) { FRAMERR(frame, "%s: unknown opcode=%d\n", "DNS", dns->opcode); return; } /* * Authoritative Name Server */ name2_length = dns_extract_name(frame, px, length, offset, name2, sizeof(name2)); JOTDOWN(ferret, JOT_PRINT("ID-DNS", name, name_length), JOT_SZ("SOA", "Start of zone authority"), JOT_PRINT("Name-Server", name2, name2_length), 0); ip_address = dns_resolve_alias(frame, px, length, dns, name2, 0); if (ip_address) JOTDOWN(ferret, JOT_PRINT("ID-DNS", name, name_length), JOT_SZ("SOA", "Start of zone authority"), JOT_PRINT("Name-Server", name2, name2_length), JOT_IPv4("address", ip_address), 0); skip_name(px, length, &offset); /* Contact */ if (offset < offset_max) { name2_length = dns_extract_name(frame, px, length, offset, name2, sizeof(name2)); JOTDOWN(ferret, JOT_PRINT("ID-DNS", name, name_length), JOT_SZ("SOA", "Start of zone authority"), JOT_PRINT("Contact", name2, name2_length), 0); skip_name(px, length, &offset); } break; case TYPECLASS(10,1): /* type=NULL, class=INTERNET*/ /* Regress: defcon2008-dns2.pcap(100803): name=Vaaaaiaqaac.tunnel.fastcoder.net */ /* I'm not sure what this is, other than passing data as Null records. * This would be a good thing for an intrusion-detection system to trigger * on. */ break; case TYPECLASS(12,0x8001): /*type=PTR, class=INTERNET */ bonjour_parse_resource_record(ferret, frame, px, length, rec, dns); break; case TYPECLASS(12,1): /*type=PTR(pointer reverse lookup), class=INTERNET */ if (!is_valid_opcode(dns->opcode, 0x10, -1)) { FRAMERR(frame, "%s: unknown opcode=%d\n", "DNS", dns->opcode); return; } if (name_length > 6 && memcmp(name+name_length-6, ".local", 6) == 0) { JOTDOWN(ferret, JOT_SRC("ID-IP", frame), JOT_PRINT("Service", name,name_length), 0); /* Extract MAC address */ { const unsigned char *p_name; unsigned name_length; const unsigned char *p_mac = find_mac(px, MIN(length, rec->rdata_offset+rec->rdata_length), rec->rdata_offset, &p_name, &name_length); if (p_mac) { JOTDOWN(ferret, JOT_SRC("ID-IP", frame), JOT_PRINT("mac", p_mac, 19), 0); JOTDOWN(ferret, JOT_SRC("ID-IP", frame), JOT_PRINT("name", p_name, name_length), 0); } } } else if (endsWith(name, ".in-addr.arpa")) { /* Extract a 4-byte IPv4 address * Example: "18.0.0.10.in-addr.arpa"*/ unsigned ipv4=0; unsigned i; unsigned j=0; for (i=0; i<4; i++) { unsigned num = 0; for (; name[j] && name[j] != '.'; j++) { if ('0' <= name[j] && name[j] <= '9') num = num * 10 + name[j]-'0'; } while (name[j] == '.') j++; ipv4 |= num<<(i*8); } /* Now get the name it points to */ name2_length = dns_extract_name(frame, px, length, offset, name2, sizeof(name2)); JOTDOWN(ferret, JOT_PRINT("ID-DNS", name2, name2_length), JOT_IPv4("ID-IP", ipv4), JOT_SRC("dnssrv", frame), 0); } else ; //FRAMERR(frame, "dns: unknown PTR record\n"); break; case TYPECLASS(13,0x8001): /*type=HINFO, class=INTERNET */ bonjour_parse_resource_record(ferret, frame, px, length, rec, dns); break; case TYPECLASS(15,1): /*type=MX, class=INTERNET */ /* Regress: defcon2008-dns2.pcap(18661) */ break; case TYPECLASS(16,0x8001): /*type=TXT, class=INTERNET(cache flush)*/ bonjour_parse_resource_record(ferret, frame, px, length, rec, dns); break; case TYPECLASS(16,1): /*type=TXT, class=INTERNET */ if (!is_valid_opcode(dns->opcode, 0x10, 5, -1)) { FRAMERR(frame, "%s: unknown opcode=%d\n", "DNS", dns->opcode); return; } if (stricmp(name, "current.cvd.clamav.net") == 0) { /* This is a single string containing a version string, like: * 0.91.1:44:3855:1186270141:1 */ break; } else if (starts_with("_DM-NOTIFICATION.", name, strlen(name))) { /* Regress: defcon2008\dump001.pcap(87082) */ /* TODO */ break; } else if (endsWith(name, "._workstation._tcp.local")) { /* Regress: defcon2008-dns2.pcap(56127): "mike-desktop [00:0c:29:f6:58:ca]._workstation._tcp.local" */ break; } else if (endsWith(name, ".asn.cymru.com")) { /* Regress: defcon2008-dns2.pcap(98958) */ /* This is a system for mapping IP to ASN numbers: * http://www.team-cymru.org/Services/ip-to-asn.html */ break; } else if (endsWith(name, ".wrs.trendmicro.com")) { /* Regress: defcon2008-dns2.pcap(184904) */ /* Appears to check whether IP addresses are trustworthy */ break; } else { FRAMERR(frame, "%s: unknown TXT record %s", "DNS", name); } break; case TYPECLASS(0x1c,1): /*type=AAAA(IPv6 address), class=INTERNET*/ case TYPECLASS(0x1c,255): /*type=AAAA(IPv6 address), class=INTERNET*/ if (!is_valid_opcode(dns->opcode, 0x10, 5, -1)) { FRAMERR(frame, "%s: unknown opcode=%d\n", "DNS", dns->opcode); return; } switch (dns->opcode) { case 0x10: { const unsigned char *ipv6_address = px+rec->rdata_offset; if (rec->rdata_length != 16) FRAMERR(frame, "dns: data not 16-bytes long, was %d-bytes instead (class=%d, type=%d, name=%s)\n", rec->rdata_length, rec->clss, rec->type, name); JOTDOWN(ferret, JOT_SZ("proto","DNS"), JOT_SZ("op","lookup"), JOT_SRC("ip.src", frame), JOT_PRINT("name", name, name_length), JOT_IPv6("address", ipv6_address, 16), 0); } case 5: /* dynamic update*/ /* Regress: defcon2008-dns2.pcap(7958) */ break; default: FRAMERR(frame, "%s: unknown opcode=%d\n", "DNS", dns->opcode); } break; case TYPECLASS(33,1): /*type=SRV, class=INTERNET */ if (!is_valid_opcode(dns->opcode, 0x10, -1)) { FRAMERR(frame, "%s: unknown opcode=%d\n", "DNS", dns->opcode); return; } if (rec->rdata_length < 7) FRAMERR(frame, "dns: unknown type=%d (class=%d, name=%s)\n", rec->type, rec->clss, name); else { unsigned port = px[rec->rdata_offset+4]<<8 | px[rec->rdata_offset+5]; name2_length = dns_extract_name(frame, px, length, rec->rdata_offset+6, name2, sizeof(name2)); ip_address = dns_resolve_alias(frame, px, length, dns, name2, 0); if (ip_address != 0) { JOTDOWN(ferret, JOT_PRINT("ID-DNS", name, name_length), JOT_PRINT("Server", name2, name2_length), JOT_NUM("Port", port), JOT_IPv4("IPv4",ip_address), 0); } else JOTDOWN(ferret, JOT_PRINT("ID-DNS", name, name_length), JOT_PRINT("Server", name2, name2_length), JOT_NUM("Port", port), 0); } break; default: FRAMERR(frame, "dns: unknown type=%d (class=%d, name=%s)\n", rec->type, rec->clss, name); } }
static bool dns_mt(const struct sk_buff *skb, struct xt_action_param *par) #endif { const struct xt_dns_info *info = par->matchinfo; u8 *dns; size_t len, offset; bool is_match, invert; u16 counts[4]; /* qdcount, ancount, nscount, arcount */ u16 udpsize; int i; /* skip fragments */ if (par->fragoff) return false; NFDEBUG("skb->len: %d, skb->data_len: %d, par->thoff: %d\n", skb->len, skb->data_len, par->thoff); /* find UDP payload */ offset = par->thoff + sizeof(struct udphdr); len = skb->len - offset; if (len > sizeof(pktbuf)) { pr_warn(KBUILD_MODNAME": Packet too big. Increase MAX_MTU (size %d)\n", skb->len); return false; } dns = skb_header_pointer(skb, offset, len, pktbuf); if (dns == NULL) { pr_warn(KBUILD_MODNAME": skb_header_pointer failed!\n"); return false; } /* minimum DNS query payload is 17 bytes (for "." root zone) */ if (len < 17) return false; NFDEBUG("skb->len: %d, skb->data_len: %d, len: %zu\n", skb->len, skb->data_len, len); debug_dump_buf(dns, len, 0, "ipt_dns"); /* check if we are dealing with DNS query */ if (info->flags & XT_DNS_QUERY) { invert = ((info->invert_flags & XT_DNS_QUERY) != 0); is_match = ((dns[2] & NS_QR) == NS_QR_QUERY); if (is_match == invert) return false; } /* check if we are dealing with DNS response */ if (info->flags & XT_DNS_RESPONSE) { invert = ((info->invert_flags & XT_DNS_RESPONSE) != 0); is_match = ((dns[2] & NS_QR) == NS_QR_RESPONSE); if (is_match == invert) return false; } /* fill counts[] with data from dns header */ for (i=0; i<4; i++) { counts[i] = ntohs(((u16*)dns)[i+2]); } /* query type test */ if (info->flags & XT_DNS_QTYPE) { NFDEBUG("Entering qtype match\n"); invert = ((info->invert_flags & XT_DNS_QTYPE) != 0); is_match = counts[0] > 0; /* qdcount at least 1 */ if (!is_match) goto qtype_out; /* offset is set to the first question section */ offset = 12; is_match = skip_name(dns, len, &offset); if (!is_match) goto qtype_out; NFDEBUG("Matching qtype: %x %x %x %x\n", dns[offset-4], dns[offset-3], dns[offset-2], dns[offset-1]); /* match if type=info->type, class IN */ is_match = (dns[offset-4] == 0x00) && (dns[offset-3] == info->qtype) && (dns[offset-2] == 0x00) && (dns[offset-1] == 0x01); qtype_out: if (is_match == invert) return false; } /* check for EDNS0 */ if (info->flags & XT_DNS_EDNS0) { invert = ((info->invert_flags & XT_DNS_EDNS0) != 0); is_match = counts[3] > 0; /* arcount at least 1 */ offset = 12; /* skip query sections */ for (i=0; i<counts[0]; i++) { is_match &= skip_name(dns, len, &offset); if (!is_match) break; } if (!is_match) goto edns0_out; /* skip answer and authority sections */ for (i=0; i<(counts[1]+counts[2]); i++) { is_match &= skip_rr(dns, len, &offset); if (!is_match) break; } if (!is_match) goto edns0_out; /* try to find EDNS0 pseudo-RR */ for (i=0; i<counts[3]; i++) { if (dns[offset] == 0 && dns[offset+1] == 0 && dns[offset+2] == 41) break; is_match &= skip_rr(dns, len, &offset); if (!is_match) break; } if (!is_match || (i == counts[3])) { is_match = false; goto edns0_out; } /* EDNS0 found */ if (info->flags & XT_DNS_BUFSIZE) { /* TODO: XT_DNS_BUFSIZE inversion not implemented */ udpsize = dns[offset+3] << 8 | dns[offset+4]; if (udpsize < info->bufsize[0] || udpsize > info->bufsize[1]) { is_match = false; goto edns0_out; } } debug_dump_buf(dns, len, offset, "ipt_dns_edns0"); edns0_out: if (is_match == invert) return false; } /* Nothing stopped us so far, let's accept the packet */ return true; }
int xworker_do_crawl (struct xwork *xwork, struct dirjob *job) { DIR *dirp = NULL; int ret = -1; int boff; int plen; struct dirent *result; char dbuf[512]; char *path = NULL; struct dirjob *cjob = NULL; struct stat statbuf = {0,}; char gfid_path[4096] = {0,}; plen = strlen (job->dirname) + 256 + 2; path = alloca (plen); tdbg ("Entering: %s\n", job->dirname); dirp = sys_opendir (job->dirname); if (!dirp) { terr ("opendir failed on %s (%s)\n", job->dirname, strerror (errno)); goto out; } boff = sprintf (path, "%s/", job->dirname); for (;;) { ret = readdir_r (dirp, (struct dirent *)dbuf, &result); if (ret) { err ("readdir_r(%s): %s\n", job->dirname, strerror (errno)); goto out; } if (!result) /* EOF */ break; if (result->d_ino == 0) continue; if (skip_name (job->dirname, result->d_name)) continue; /* It is sure that, children and grandchildren of .glusterfs * are directories, just add them to global queue. */ if (skip_stat (job, result->d_name)) { strncpy (path + boff, result->d_name, (plen-boff)); cjob = dirjob_new (path, job); if (!cjob) { err ("dirjob_new(%s): %s\n", path, strerror (errno)); ret = -1; goto out; } xwork_addcrawl (xwork, cjob); continue; } strcpy (gfid_path, slavemnt); strcat (gfid_path, "/.gfid/"); strcat (gfid_path, result->d_name); ret = lstat (gfid_path, &statbuf); if (ret && errno == ENOENT) { out ("%s\n", result->d_name); BUMP (skipped_gfids); } if (ret && errno != ENOENT) { err ("stat on slave failed(%s): %s\n", gfid_path, strerror (errno)); goto out; } } ret = 0; out: if (dirp) sys_closedir (dirp); return ret; }
/* * Parse contacts in a Contact HF */ int parse_contacts(str* _s, contact_t** _c) { contact_t* c; contact_t* last; param_hooks_t hooks; last = NULL; while(1) { /* Allocate and clear contact structure */ c = (contact_t*)pkg_malloc(sizeof(contact_t)); if (c == 0) { LM_ERR("no pkg memory left\n"); goto error; } memset(c, 0, sizeof(contact_t)); c->name.s = _s->s; if (skip_name(_s) < 0) { LM_ERR("failed to skip name part\n"); goto error; } c->uri.s = _s->s; c->name.len = _s->s - c->name.s; trim_trailing(&c->name); /* Find the end of the URI */ if (skip_uri(_s) < 0) { LM_ERR("failed to skip URI\n"); goto error; } c->uri.len = _s->s - c->uri.s; /* Calculate URI length */ trim_trailing(&(c->uri)); /* Remove any trailing spaces from URI */ /* Remove <> if any */ if ((c->uri.len >= 2) && (c->uri.s[0] == '<') && (c->uri.s[c->uri.len - 1] == '>')) { c->uri.s++; c->uri.len -= 2; } trim(&c->uri); /* RFC3261 grammar enforces the existance of an URI */ if (c->uri.len==0) { LM_ERR("Empty URI found in contact body\n"); goto error; } if (_s->len == 0) goto ok; if (_s->s[0] == ';') { /* Contact parameter found */ _s->s++; _s->len--; trim_leading(_s); if (_s->len == 0) { LM_ERR("failed to parse params\n"); goto error; } if (parse_params(_s, CLASS_CONTACT, &hooks, &c->params) < 0) { LM_ERR("failed to parse contact parameters\n"); goto error; } c->q = hooks.contact.q; c->expires = hooks.contact.expires; c->received = hooks.contact.received; c->methods = hooks.contact.methods; c->instance = hooks.contact.instance; if (_s->len == 0) goto ok; } /* Next character is comma */ c->len = _s->s - c->name.s; _s->s++; _s->len--; trim_leading(_s); if (_s->len == 0) { LM_ERR("text after comma missing\n"); goto error; } if (last) {last->next=c;} else {*_c = c;} last = c; } error: if (c) pkg_free(c); free_contacts(_c); /* Free any contacts created so far */ return -1; ok: c->len = _s->s - c->name.s; if (last) {last->next=c;} else {*_c = c;} last = c; return 0; }