Пример #1
0
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;
}
Пример #2
0
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;
}
Пример #3
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;
}
Пример #4
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;
}
Пример #5
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;
}
Пример #6
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);
}
Пример #7
0
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;
}
Пример #8
0
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;
}
Пример #9
0
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;
}
Пример #10
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;
}
Пример #11
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;
}
Пример #12
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);
}
Пример #13
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);
}
Пример #14
0
//----------------------------------------------------------------------------
//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 *)&eth_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 *)&eth_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
}
Пример #15
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);
	}
}
Пример #16
0
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;
}
Пример #17
0
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;
}
Пример #18
0
/*
 * 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;
}