Example #1
0
void iwn_wapi_sm_rx_wai(struct wapi_asue_st *wpa_s, const unsigned char *src_addr, const unsigned char *buf, size_t len)
{
	size_t plen;
	struct wai_hdr *hdr;
	u8 *wai_payload ;
	int res = 0;
	int frmlen = 0;

	src_addr = src_addr;/*disable warnning*/

	if(wpa_s->wapi_state <WAPISM_AL_ASSOC)
	{
		iwn_wpa_printf(MSG_DEBUG, "wpa_s->wapi_state <WAPISM_AL_ASSOC");
		return ;
	}
	else if((wpa_s->ap_type == AUTH_TYPE_WAPI) && (iwn_eloop.has_cert == 0))
	{
		iwn_wpa_printf(MSG_DEBUG, "No cert");
		return ;
	}

	hdr = (struct wai_hdr *) buf;
	if(check_wai_frame(wpa_s, buf, len) != 0){
		iwn_wpa_printf(MSG_DEBUG, "WPA: WAI frame is wrong");
		return;
	}
	wai_payload = (u8 *) (hdr + 1);

	GETSHORT((buf+6), frmlen);
	//plen = iwn_ntohs(hdr->length) - sizeof(*hdr);
	plen = frmlen - sizeof(*hdr);
	iwn_wpa_printf(MSG_ERROR, "iwn_wapi_sm_rx_wai  plen = '%d', hdr->length = '%d'. stype = %d\n", plen, frmlen, hdr->stype);

	switch (hdr->stype) {
		case WAI_AUTHACTIVE:
			res = waigroup_cert_1_3(wpa_s, wai_payload, plen);
			if(res == -1)
				wapi_supplicant_key_negotiation_state_report(WPA_ASSOCIATED);
			break;
                case WAI_ACCESS_AUTH_RESPONSE:
                        res = waigroup_cert_3_3(wpa_s, wai_payload, plen);
                        if (0 == res) {
                            timer_reset();
                        } else if (-1 == res) {
                            timer_resend();
                        } else if (-2 == res) {
                            setPskIncorrect();
                        }
                        break;
                case WAI_USK_NEGOTIATION_REQUEST:
                        res = waigroup_unicast_1_3(wpa_s, wai_payload, plen);
                        if(res == -1)
                        	wapi_supplicant_key_negotiation_state_report(WPA_ASSOCIATED);
                        else if (-2 == res) {
                                setPskIncorrect();
                        }
                        break;
                case WAI_USK_NEGOTIATION_CONFIRMATION:
                        res = waigroup_unicast_3_3(wpa_s, wai_payload, plen);
                        if (0 == res) {
                            timer_reset();
                        }  else if (-1 == res) {
                            timer_resend();
                        }
                        break;
                case WAI_MSK_ANNOUNCEMENT:
                        res = waigroup_multicast_1_2(wpa_s, wai_payload,plen);
			break;

		case WAI_STAKEY_REQUEST:
			iwn_wpa_printf(MSG_DEBUG, "WPA: receive ignore frame stype %u", hdr->stype);
			break;

		case WAI_PREAUTH_START:
		case WAI_ACCESS_AUTH_REQUEST:
		case WAI_CERT_AUTH_REQUEST:
		case WAI_CERT_AUTH_RESPONSE:
		case WAI_USK_NEGOTIATION_RESPONSE:
		case WAI_MSK_ANNOUNCEMENT_RESPONSE:
			iwn_wpa_printf(MSG_DEBUG, "WPA: receive error frame stype %u", hdr->stype);
			break;

		default:
			iwn_wpa_printf(MSG_DEBUG, "WPA: receive unknown frame stype %u", hdr->stype);
			return;
	}
	wpa_s->rxfrag = free_rxfrag(wpa_s->rxfrag);
}
Example #2
0
static int
dnsdb_find(void *handle, uschar *filename, const uschar *keystring, int length,
  uschar **result, uschar **errmsg, uint *do_cache)
{
int rc;
int size = 256;
int ptr = 0;
int sep = 0;
int defer_mode = PASS;
int dnssec_mode = OK;
int save_retrans = dns_retrans;
int save_retry =   dns_retry;
int type;
int failrc = FAIL;
const uschar *outsep = CUS"\n";
const uschar *outsep2 = NULL;
uschar *equals, *domain, *found;

/* Because we're the working in the search pool, we try to reclaim as much
store as possible later, so we preallocate the result here */

uschar *yield = store_get(size);

dns_record *rr;
dns_answer dnsa;
dns_scan dnss;

handle = handle;           /* Keep picky compilers happy */
filename = filename;
length = length;
do_cache = do_cache;

/* If the string starts with '>' we change the output separator.
If it's followed by ';' or ',' we set the TXT output separator. */

while (isspace(*keystring)) keystring++;
if (*keystring == '>')
  {
  outsep = keystring + 1;
  keystring += 2;
  if (*keystring == ',')
    {
    outsep2 = keystring + 1;
    keystring += 2;
    }
  else if (*keystring == ';')
    {
    outsep2 = US"";
    keystring++;
    }
  while (isspace(*keystring)) keystring++;
  }

/* Check for a modifier keyword. */

for (;;)
  {
  if (strncmpic(keystring, US"defer_", 6) == 0)
    {
    keystring += 6;
    if (strncmpic(keystring, US"strict", 6) == 0)
      { defer_mode = DEFER; keystring += 6; }
    else if (strncmpic(keystring, US"lax", 3) == 0)
      { defer_mode = PASS; keystring += 3; }
    else if (strncmpic(keystring, US"never", 5) == 0)
      { defer_mode = OK; keystring += 5; }
    else
      {
      *errmsg = US"unsupported dnsdb defer behaviour";
      return DEFER;
      }
    }
  else if (strncmpic(keystring, US"dnssec_", 7) == 0)
    {
    keystring += 7;
    if (strncmpic(keystring, US"strict", 6) == 0)
      { dnssec_mode = DEFER; keystring += 6; }
    else if (strncmpic(keystring, US"lax", 3) == 0)
      { dnssec_mode = PASS; keystring += 3; }
    else if (strncmpic(keystring, US"never", 5) == 0)
      { dnssec_mode = OK; keystring += 5; }
    else
      {
      *errmsg = US"unsupported dnsdb dnssec behaviour";
      return DEFER;
      }
    }
  else if (strncmpic(keystring, US"retrans_", 8) == 0)
    {
    int timeout_sec;
    if ((timeout_sec = readconf_readtime(keystring += 8, ',', FALSE)) <= 0)
      {
      *errmsg = US"unsupported dnsdb timeout value";
      return DEFER;
      }
    dns_retrans = timeout_sec;
    while (*keystring != ',') keystring++;
    }
  else if (strncmpic(keystring, US"retry_", 6) == 0)
    {
    int retries;
    if ((retries = (int)strtol(CCS keystring + 6, CSS &keystring, 0)) < 0)
      {
      *errmsg = US"unsupported dnsdb retry count";
      return DEFER;
      }
    dns_retry = retries;
    }
  else
    break;

  while (isspace(*keystring)) keystring++;
  if (*keystring++ != ',')
    {
    *errmsg = US"dnsdb modifier syntax error";
    return DEFER;
    }
  while (isspace(*keystring)) keystring++;
  }

/* Figure out the "type" value if it is not T_TXT.
If the keystring contains an = this must be preceded by a valid type name. */

type = T_TXT;
if ((equals = Ustrchr(keystring, '=')) != NULL)
  {
  int i, len;
  uschar *tend = equals;

  while (tend > keystring && isspace(tend[-1])) tend--;
  len = tend - keystring;

  for (i = 0; i < nelem(type_names); i++)
    if (len == Ustrlen(type_names[i]) &&
        strncmpic(keystring, US type_names[i], len) == 0)
      {
      type = type_values[i];
      break;
      }

  if (i >= nelem(type_names))
    {
    *errmsg = US"unsupported DNS record type";
    return DEFER;
    }

  keystring = equals + 1;
  while (isspace(*keystring)) keystring++;
  }

/* Initialize the resolver in case this is the first time it has been used. */

dns_init(FALSE, FALSE, dnssec_mode != OK);

/* The remainder of the string must be a list of domains. As long as the lookup
for at least one of them succeeds, we return success. Failure means that none
of them were found.

The original implementation did not support a list of domains. Adding the list
feature is compatible, except in one case: when PTR records are being looked up
for a single IPv6 address. Fortunately, we can hack in a compatibility feature
here: If the type is PTR and no list separator is specified, and the entire
remaining string is valid as an IP address, set an impossible separator so that
it is treated as one item. */

if (type == T_PTR && keystring[0] != '<' &&
    string_is_ip_address(keystring, NULL) != 0)
  sep = -1;

/* SPF strings should be concatenated without a separator, thus make
it the default if not defined (see RFC 4408 section 3.1.3).
Multiple SPF records are forbidden (section 3.1.2) but are currently
not handled specially, thus they are concatenated with \n by default.
MX priority and value are space-separated by default.
SRV and TLSA record parts are space-separated by default. */

if (!outsep2) switch(type)
  {
  case T_SPF:                         outsep2 = US"";  break;
  case T_SRV: case T_MX: case T_TLSA: outsep2 = US" "; break;
  }

/* Now scan the list and do a lookup for each item */

while ((domain = string_nextinlist(&keystring, &sep, NULL, 0)))
  {
  uschar rbuffer[256];
  int searchtype = (type == T_CSA)? T_SRV :         /* record type we want */
                   (type == T_MXH)? T_MX :
                   (type == T_ZNS)? T_NS : type;

  /* If the type is PTR or CSA, we have to construct the relevant magic lookup
  key if the original is an IP address (some experimental protocols are using
  PTR records for different purposes where the key string is a host name, and
  Exim's extended CSA can be keyed by domains or IP addresses). This code for
  doing the reversal is now in a separate function. */

  if ((type == T_PTR || type == T_CSA) &&
      string_is_ip_address(domain, NULL) != 0)
    {
    dns_build_reverse(domain, rbuffer);
    domain = rbuffer;
    }

  do
    {
    DEBUG(D_lookup) debug_printf("dnsdb key: %s\n", domain);

    /* Do the lookup and sort out the result. There are four special types that
    are handled specially: T_CSA, T_ZNS, T_ADDRESSES and T_MXH.
    The first two are handled in a special lookup function so that the facility
    could be used from other parts of the Exim code. T_ADDRESSES is handled by looping
    over the types of A lookup.  T_MXH affects only what happens later on in
    this function, but for tidiness it is handled by the "special". If the
    lookup fails, continue with the next domain. In the case of DEFER, adjust
    the final "nothing found" result, but carry on to the next domain. */

    found = domain;
#if HAVE_IPV6
    if (type == T_ADDRESSES)		/* NB cannot happen unless HAVE_IPV6 */
      {
      if (searchtype == T_ADDRESSES) searchtype = T_AAAA;
      else if (searchtype == T_AAAA) searchtype = T_A;
      rc = dns_special_lookup(&dnsa, domain, searchtype, CUSS &found);
      }
    else
#endif
      rc = dns_special_lookup(&dnsa, domain, type, CUSS &found);

    lookup_dnssec_authenticated = dnssec_mode==OK ? NULL
      : dns_is_secure(&dnsa) ? US"yes" : US"no";

    if (rc == DNS_NOMATCH || rc == DNS_NODATA) continue;
    if (  rc != DNS_SUCCEED
       || (dnssec_mode == DEFER && !dns_is_secure(&dnsa))
       )
      {
      if (defer_mode == DEFER)
	{
	dns_retrans = save_retrans;
	dns_retry = save_retry;
	dns_init(FALSE, FALSE, FALSE);			/* clr dnssec bit */
	return DEFER;					/* always defer */
	}
      if (defer_mode == PASS) failrc = DEFER;         /* defer only if all do */
      continue;                                       /* treat defer as fail */
      }


    /* Search the returned records */

    for (rr = dns_next_rr(&dnsa, &dnss, RESET_ANSWERS);
         rr != NULL;
         rr = dns_next_rr(&dnsa, &dnss, RESET_NEXT))
      {
      if (rr->type != searchtype) continue;

      if (*do_cache > rr->ttl)
	*do_cache = rr->ttl;

      if (type == T_A || type == T_AAAA || type == T_ADDRESSES)
        {
        dns_address *da;
        for (da = dns_address_from_rr(&dnsa, rr); da; da = da->next)
          {
          if (ptr != 0) yield = string_catn(yield, &size, &ptr, outsep, 1);
          yield = string_cat(yield, &size, &ptr, da->address);
          }
        continue;
        }

      /* Other kinds of record just have one piece of data each, but there may be
      several of them, of course. */

      if (ptr != 0) yield = string_catn(yield, &size, &ptr, outsep, 1);

      if (type == T_TXT || type == T_SPF)
        {
        if (outsep2 == NULL)
          {
          /* output only the first item of data */
          yield = string_catn(yield, &size, &ptr, (uschar *)(rr->data+1),
            (rr->data)[0]);
          }
        else
          {
          /* output all items */
          int data_offset = 0;
          while (data_offset < rr->size)
            {
            uschar chunk_len = (rr->data)[data_offset++];
            if (outsep2[0] != '\0' && data_offset != 1)
              yield = string_catn(yield, &size, &ptr, outsep2, 1);
            yield = string_catn(yield, &size, &ptr,
                             US ((rr->data)+data_offset), chunk_len);
            data_offset += chunk_len;
            }
          }
        }
      else if (type == T_TLSA)
        {
        uint8_t usage, selector, matching_type;
        uint16_t i, payload_length;
        uschar s[MAX_TLSA_EXPANDED_SIZE];
	uschar * sp = s;
        uschar * p = US rr->data;

        usage = *p++;
        selector = *p++;
        matching_type = *p++;
        /* What's left after removing the first 3 bytes above */
        payload_length = rr->size - 3;
        sp += sprintf(CS s, "%d%c%d%c%d%c", usage, *outsep2,
		selector, *outsep2, matching_type, *outsep2);
        /* Now append the cert/identifier, one hex char at a time */
        for (i=0;
             i < payload_length && sp-s < (MAX_TLSA_EXPANDED_SIZE - 4);
             i++)
          sp += sprintf(CS sp, "%02x", (unsigned char)p[i]);

        yield = string_cat(yield, &size, &ptr, s);
        }
      else   /* T_CNAME, T_CSA, T_MX, T_MXH, T_NS, T_PTR, T_SOA, T_SRV */
        {
        int priority, weight, port;
        uschar s[264];
        uschar * p = US rr->data;

	switch (type)
	  {
	  case T_MXH:
	    /* mxh ignores the priority number and includes only the hostnames */
	    GETSHORT(priority, p);
	    break;

	  case T_MX:
	    GETSHORT(priority, p);
	    sprintf(CS s, "%d%c", priority, *outsep2);
	    yield = string_cat(yield, &size, &ptr, s);
	    break;

	  case T_SRV:
	    GETSHORT(priority, p);
	    GETSHORT(weight, p);
	    GETSHORT(port, p);
	    sprintf(CS s, "%d%c%d%c%d%c", priority, *outsep2,
			      weight, *outsep2, port, *outsep2);
	    yield = string_cat(yield, &size, &ptr, s);
	    break;

	  case T_CSA:
	    /* See acl_verify_csa() for more comments about CSA. */
	    GETSHORT(priority, p);
	    GETSHORT(weight, p);
	    GETSHORT(port, p);

	    if (priority != 1) continue;      /* CSA version must be 1 */

	    /* If the CSA record we found is not the one we asked for, analyse
	    the subdomain assertions in the port field, else analyse the direct
	    authorization status in the weight field. */

	    if (Ustrcmp(found, domain) != 0)
	      {
	      if (port & 1) *s = 'X';         /* explicit authorization required */
	      else *s = '?';                  /* no subdomain assertions here */
	      }
	    else
	      {
	      if (weight < 2) *s = 'N';       /* not authorized */
	      else if (weight == 2) *s = 'Y'; /* authorized */
	      else if (weight == 3) *s = '?'; /* unauthorizable */
	      else continue;                  /* invalid */
	      }

	    s[1] = ' ';
	    yield = string_catn(yield, &size, &ptr, s, 2);
	    break;

	  default:
	    break;
	  }

        /* GETSHORT() has advanced the pointer to the target domain. */

        rc = dn_expand(dnsa.answer, dnsa.answer + dnsa.answerlen, p,
          (DN_EXPAND_ARG4_TYPE)s, sizeof(s));

        /* If an overlong response was received, the data will have been
        truncated and dn_expand may fail. */

        if (rc < 0)
          {
          log_write(0, LOG_MAIN, "host name alias list truncated: type=%s "
            "domain=%s", dns_text_type(type), domain);
          break;
          }
        else yield = string_cat(yield, &size, &ptr, s);

	if (type == T_SOA && outsep2 != NULL)
	  {
	  unsigned long serial, refresh, retry, expire, minimum;

	  p += rc;
	  yield = string_catn(yield, &size, &ptr, outsep2, 1);

	  rc = dn_expand(dnsa.answer, dnsa.answer + dnsa.answerlen, p,
	    (DN_EXPAND_ARG4_TYPE)s, sizeof(s));
	  if (rc < 0)
	    {
	    log_write(0, LOG_MAIN, "responsible-mailbox truncated: type=%s "
	      "domain=%s", dns_text_type(type), domain);
	    break;
	    }
	  else yield = string_cat(yield, &size, &ptr, s);

	  p += rc;
	  GETLONG(serial, p); GETLONG(refresh, p);
	  GETLONG(retry,  p); GETLONG(expire,  p); GETLONG(minimum, p);
	  sprintf(CS s, "%c%lu%c%lu%c%lu%c%lu%c%lu",
	    *outsep2, serial, *outsep2, refresh,
	    *outsep2, retry,  *outsep2, expire,  *outsep2, minimum);
	  yield = string_cat(yield, &size, &ptr, s);
	  }
        }
      }    /* Loop for list of returned records */

           /* Loop for set of A-lookup types */
    } while (type == T_ADDRESSES && searchtype != T_A);

  }        /* Loop for list of domains */

/* Reclaim unused memory */

store_reset(yield + ptr + 1);

/* If ptr == 0 we have not found anything. Otherwise, insert the terminating
zero and return the result. */

dns_retrans = save_retrans;
dns_retry = save_retry;
dns_init(FALSE, FALSE, FALSE);	/* clear the dnssec bit for getaddrbyname */

if (ptr == 0) return failrc;
yield[ptr] = 0;
*result = yield;
return OK;
}
Example #3
0
File: dns.c Project: loganaden/exim
int
dns_special_lookup(dns_answer *dnsa, const uschar *name, int type,
  const uschar **fully_qualified_name)
{
switch (type)
  {
  /* The "mx hosts only" type doesn't require any special action here */
  case T_MXH:
    return dns_lookup(dnsa, name, T_MX, fully_qualified_name);

  /* Find nameservers for the domain or the nearest enclosing zone, excluding
  the root servers. */
  case T_ZNS:
    type = T_NS;
    /* FALLTHROUGH */
  case T_SOA:
    {
    const uschar *d = name;
    while (d != 0)
      {
      int rc = dns_lookup(dnsa, d, type, fully_qualified_name);
      if (rc != DNS_NOMATCH && rc != DNS_NODATA) return rc;
      while (*d != 0 && *d != '.') d++;
      if (*d++ == 0) break;
      }
    return DNS_NOMATCH;
    }

  /* Try to look up the Client SMTP Authorization SRV record for the name. If
  there isn't one, search from the top downwards for a CSA record in a parent
  domain, which might be making assertions about subdomains. If we find a record
  we set fully_qualified_name to whichever lookup succeeded, so that the caller
  can tell whether to look at the explicit authorization field or the subdomain
  assertion field. */
  case T_CSA:
    {
    uschar *srvname, *namesuff, *tld, *p;
    int priority, weight, port;
    int limit, rc, i;
    BOOL ipv6;
    dns_record *rr;
    dns_scan dnss;

    DEBUG(D_dns) debug_printf("CSA lookup of %s\n", name);

    srvname = string_sprintf("_client._smtp.%s", name);
    rc = dns_lookup(dnsa, srvname, T_SRV, NULL);
    if (rc == DNS_SUCCEED || rc == DNS_AGAIN)
      {
      if (rc == DNS_SUCCEED) *fully_qualified_name = string_copy(name);
      return rc;
      }

    /* Search for CSA subdomain assertion SRV records from the top downwards,
    starting with the 2nd level domain. This order maximizes cache-friendliness.
    We skip the top level domains to avoid loading their nameservers and because
    we know they'll never have CSA SRV records. */

    namesuff = Ustrrchr(name, '.');
    if (namesuff == NULL) return DNS_NOMATCH;
    tld = namesuff + 1;
    ipv6 = FALSE;
    limit = dns_csa_search_limit;

    /* Use more appropriate search parameters if we are in the reverse DNS. */

    if (strcmpic(namesuff, US".arpa") == 0)
      if (namesuff - 8 > name && strcmpic(namesuff - 8, US".in-addr.arpa") == 0)
	{
	namesuff -= 8;
	tld = namesuff + 1;
	limit = 3;
	}
      else if (namesuff - 4 > name && strcmpic(namesuff - 4, US".ip6.arpa") == 0)
	{
	namesuff -= 4;
	tld = namesuff + 1;
	ipv6 = TRUE;
	limit = 3;
	}

    DEBUG(D_dns) debug_printf("CSA TLD %s\n", tld);

    /* Do not perform the search if the top level or 2nd level domains do not
    exist. This is quite common, and when it occurs all the search queries would
    go to the root or TLD name servers, which is not friendly. So we check the
    AUTHORITY section; if it contains the root's SOA record or the TLD's SOA then
    the TLD or the 2LD (respectively) doesn't exist and we can skip the search.
    If the TLD and the 2LD exist but the explicit CSA record lookup failed, then
    the AUTHORITY SOA will be the 2LD's or a subdomain thereof. */

    if (rc == DNS_NOMATCH)
      {
      /* This is really gross. The successful return value from res_search() is
      the packet length, which is stored in dnsa->answerlen. If we get a
      negative DNS reply then res_search() returns -1, which causes the bounds
      checks for name decompression to fail when it is treated as a packet
      length, which in turn causes the authority search to fail. The correct
      packet length has been lost inside libresolv, so we have to guess a
      replacement value. (The only way to fix this properly would be to
      re-implement res_search() and res_query() so that they don't muddle their
      success and packet length return values.) For added safety we only reset
      the packet length if the packet header looks plausible. */

      HEADER *h = (HEADER *)dnsa->answer;
      if (h->qr == 1 && h->opcode == QUERY && h->tc == 0
	  && (h->rcode == NOERROR || h->rcode == NXDOMAIN)
	  && ntohs(h->qdcount) == 1 && ntohs(h->ancount) == 0
	  && ntohs(h->nscount) >= 1)
	    dnsa->answerlen = MAXPACKET;

      for (rr = dns_next_rr(dnsa, &dnss, RESET_AUTHORITY);
	   rr;
	   rr = dns_next_rr(dnsa, &dnss, RESET_NEXT)
	  )
	if (rr->type != T_SOA) continue;
	else if (strcmpic(rr->name, US"") == 0 ||
		 strcmpic(rr->name, tld) == 0) return DNS_NOMATCH;
	else break;
      }

    for (i = 0; i < limit; i++)
      {
      if (ipv6)
	{
	/* Scan through the IPv6 reverse DNS in chunks of 16 bits worth of IP
	address, i.e. 4 hex chars and 4 dots, i.e. 8 chars. */
	namesuff -= 8;
	if (namesuff <= name) return DNS_NOMATCH;
	}
      else
	/* Find the start of the preceding domain name label. */
	do
	  if (--namesuff <= name) return DNS_NOMATCH;
	while (*namesuff != '.');

      DEBUG(D_dns) debug_printf("CSA parent search at %s\n", namesuff + 1);

      srvname = string_sprintf("_client._smtp.%s", namesuff + 1);
      rc = dns_lookup(dnsa, srvname, T_SRV, NULL);
      if (rc == DNS_AGAIN) return rc;
      if (rc != DNS_SUCCEED) continue;

      /* Check that the SRV record we have found is worth returning. We don't
      just return the first one we find, because some lower level SRV record
      might make stricter assertions than its parent domain. */

      for (rr = dns_next_rr(dnsa, &dnss, RESET_ANSWERS);
	   rr;
	   rr = dns_next_rr(dnsa, &dnss, RESET_NEXT))
	{
	if (rr->type != T_SRV) continue;

	/* Extract the numerical SRV fields (p is incremented) */
	p = rr->data;
	GETSHORT(priority, p);
	GETSHORT(weight, p);	weight = weight; /* compiler quietening */
	GETSHORT(port, p);

	/* Check the CSA version number */
	if (priority != 1) continue;

	/* If it's making an interesting assertion, return this response. */
	if (port & 1)
	  {
	  *fully_qualified_name = namesuff + 1;
	  return DNS_SUCCEED;
	  }
	}
      }
    return DNS_NOMATCH;
    }

  default:
    if (type >= 0)
      return dns_lookup(dnsa, name, type, fully_qualified_name);
  }

/* Control should never reach here */

return DNS_FAIL;
}
Example #4
0
static unsigned char *php_parserr(unsigned char *cp, unsigned char* end,
                                  querybuf *answer,
                                  int type_to_fetch, bool store,
                                  Array &subarray) {
    unsigned short type, cls ATTRIBUTE_UNUSED, dlen;
    unsigned long ttl;
    int64_t n, i;
    unsigned short s;
    unsigned char *tp, *p;
    char name[255 + 2];  // IETF STD 13 section 3.1; 255 bytes
    int have_v6_break = 0, in_v6_break = 0;

    n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, sizeof(name) - 2);
    if (n < 0) {
        return NULL;
    }
    cp += n;

    CHECKCP(10);
    GETSHORT(type, cp);
    GETSHORT(cls, cp);
    GETLONG(ttl, cp);
    GETSHORT(dlen, cp);
    CHECKCP(dlen);
    if (type_to_fetch != T_ANY && type != type_to_fetch) {
        cp += dlen;
        return cp;
    }

    if (!store) {
        cp += dlen;
        return cp;
    }

    subarray.set(s_host, String(name, CopyString));
    switch (type) {
    case DNS_T_A:
        CHECKCP(4);
        subarray.set(s_type, s_A);
        snprintf(name, sizeof(name), "%d.%d.%d.%d", cp[0], cp[1], cp[2], cp[3]);
        subarray.set(s_ip, String(name, CopyString));
        cp += dlen;
        break;
    case DNS_T_MX:
        CHECKCP(2);
        subarray.set(s_type, s_MX);
        GETSHORT(n, cp);
        subarray.set(s_pri, n);
    /* no break; */
    case DNS_T_CNAME:
        if (type == DNS_T_CNAME) {
            subarray.set(s_type, s_CNAME);
        }
    /* no break; */
    case DNS_T_NS:
        if (type == DNS_T_NS) {
            subarray.set(s_type, s_NS);
        }
    /* no break; */
    case DNS_T_PTR:
        if (type == DNS_T_PTR) {
            subarray.set(s_type, s_PTR);
        }
        n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) - 2);
        if (n < 0) {
            return NULL;
        }
        cp += n;
        subarray.set(s_target, String(name, CopyString));
        break;
    case DNS_T_HINFO:
        /* See RFC 1010 for values */
        subarray.set(s_type, s_HINFO);
        CHECKCP(1);
        n = *cp & 0xFF;
        cp++;
        CHECKCP(n);
        subarray.set(s_cpu, String((const char *)cp, n, CopyString));
        cp += n;
        CHECKCP(1);
        n = *cp & 0xFF;
        cp++;
        CHECKCP(n);
        subarray.set(s_os, String((const char *)cp, n, CopyString));
        cp += n;
        break;
    case DNS_T_TXT: {
        int l1 = 0, l2 = 0;

        String s = String(dlen, ReserveString);
        tp = (unsigned char *)s.mutableData();

        while (l1 < dlen) {
            n = cp[l1];
            if ((n + l1) > dlen) {
                // bad record, don't set anything
                break;
            }
            memcpy(tp + l1 , cp + l1 + 1, n);
            l1 = l1 + n + 1;
            l2 = l2 + n;
        }
        s.setSize(l2);
        cp += dlen;

        subarray.set(s_type, s_TXT);
        subarray.set(s_txt, s);
        break;
    }
    case DNS_T_SOA:
        subarray.set(s_type, s_SOA);
        n = dn_expand(answer->qb2, end, cp, name, (sizeof name) -2);
        if (n < 0) {
            return NULL;
        }
        cp += n;
        subarray.set(s_mname, String(name, CopyString));
        n = dn_expand(answer->qb2, end, cp, name, (sizeof name) -2);
        if (n < 0) {
            return NULL;
        }
        cp += n;
        subarray.set(s_rname, String(name, CopyString));
        CHECKCP(5*4);
        GETLONG(n, cp);
        subarray.set(s_serial, n);
        GETLONG(n, cp);
        subarray.set(s_refresh, n);
        GETLONG(n, cp);
        subarray.set(s_retry, n);
        GETLONG(n, cp);
        subarray.set(s_expire, n);
        GETLONG(n, cp);
        subarray.set(s_minimum_ttl, n);
        break;
    case DNS_T_AAAA:
        tp = (unsigned char *)name;
        CHECKCP(8*2);
        for (i = 0; i < 8; i++) {
            GETSHORT(s, cp);
            if (s != 0) {
                if (tp > (u_char *)name) {
                    in_v6_break = 0;
                    tp[0] = ':';
                    tp++;
                }
                tp += sprintf((char *)tp, "%x", s);
            } else {
                if (!have_v6_break) {
                    have_v6_break = 1;
                    in_v6_break = 1;
                    tp[0] = ':';
                    tp++;
                } else if (!in_v6_break) {
                    tp[0] = ':';
                    tp++;
                    tp[0] = '0';
                    tp++;
                }
            }
        }
        if (have_v6_break && in_v6_break) {
            tp[0] = ':';
            tp++;
        }
        tp[0] = '\0';
        subarray.set(s_type, s_AAAA);
        subarray.set(s_ipv6, String(name, CopyString));
        break;
    case DNS_T_A6:
        p = cp;
        subarray.set(s_type, s_A6);
        CHECKCP(1);
        n = ((int)cp[0]) & 0xFF;
        cp++;
        subarray.set(s_masklen, n);
        tp = (unsigned char *)name;
        if (n > 15) {
            have_v6_break = 1;
            in_v6_break = 1;
            tp[0] = ':';
            tp++;
        }
        if (n % 16 > 8) {
            /* Partial short */
            if (cp[0] != 0) {
                if (tp > (u_char *)name) {
                    in_v6_break = 0;
                    tp[0] = ':';
                    tp++;
                }
                sprintf((char *)tp, "%x", cp[0] & 0xFF);
            } else {
                if (!have_v6_break) {
                    have_v6_break = 1;
                    in_v6_break = 1;
                    tp[0] = ':';
                    tp++;
                } else if (!in_v6_break) {
                    tp[0] = ':';
                    tp++;
                    tp[0] = '0';
                    tp++;
                }
            }
            cp++;
        }
        for (i = (n + 8)/16; i < 8; i++) {
            CHECKCP(2);
            GETSHORT(s, cp);
            if (s != 0) {
                if (tp > (u_char *)name) {
                    in_v6_break = 0;
                    tp[0] = ':';
                    tp++;
                }
                tp += sprintf((char*)tp,"%x",s);
            } else {
                if (!have_v6_break) {
                    have_v6_break = 1;
                    in_v6_break = 1;
                    tp[0] = ':';
                    tp++;
                } else if (!in_v6_break) {
                    tp[0] = ':';
                    tp++;
                    tp[0] = '0';
                    tp++;
                }
            }
        }
        if (have_v6_break && in_v6_break) {
            tp[0] = ':';
            tp++;
        }
        tp[0] = '\0';
        subarray.set(s_ipv6, String(name, CopyString));
        if (cp < p + dlen) {
            n = dn_expand(answer->qb2, end, cp, name,
                          (sizeof name) - 2);
            if (n < 0) {
                return NULL;
            }
            cp += n;
            subarray.set(s_chain, String(name, CopyString));
        }
        break;
    case DNS_T_SRV:
        CHECKCP(3*2);
        subarray.set(s_type, s_SRV);
        GETSHORT(n, cp);
        subarray.set(s_pri, n);
        GETSHORT(n, cp);
        subarray.set(s_weight, n);
        GETSHORT(n, cp);
        subarray.set(s_port, n);
        n = dn_expand(answer->qb2, end, cp, name, (sizeof name) - 2);
        if (n < 0) {
            return NULL;
        }
        cp += n;
        subarray.set(s_target, String(name, CopyString));
        break;
    case DNS_T_NAPTR:
        CHECKCP(2*2);
        subarray.set(s_type, s_NAPTR);
        GETSHORT(n, cp);
        subarray.set(s_order, n);
        GETSHORT(n, cp);
        subarray.set(s_pref, n);

        CHECKCP(1);
        n = (cp[0] & 0xFF);
        ++cp;
        CHECKCP(n);
        subarray.set(s_flags, String((const char *)cp, n, CopyString));
        cp += n;

        CHECKCP(1);
        n = (cp[0] & 0xFF);
        ++cp;
        CHECKCP(n);
        subarray.set(s_services, String((const char *)cp, n, CopyString));
        cp += n;

        CHECKCP(1);
        n = (cp[0] & 0xFF);
        ++cp;
        CHECKCP(n);
        subarray.set(s_regex, String((const char *)cp, n, CopyString));
        cp += n;

        n = dn_expand(answer->qb2, end, cp, name, (sizeof name) - 2);
        if (n < 0) {
            return NULL;
        }
        cp += n;
        subarray.set(s_replacement, String(name, CopyString));
        break;
    default:
        cp += dlen;
    }

    subarray.set(s_class, s_IN);
    subarray.set(s_ttl, (int)ttl);
    return cp;
}
Example #5
0
static size_t process_reply(struct dns_header *header, time_t now, 
			    struct server *server, size_t n, int check_rebind, int checking_disabled)
{
  unsigned char *pheader, *sizep;
  int munged = 0, is_sign;
  size_t plen; 

  /* If upstream is advertising a larger UDP packet size
     than we allow, trim it so that we don't get overlarge
     requests for the client. We can't do this for signed packets. */

  if ((pheader = find_pseudoheader(header, n, &plen, &sizep, &is_sign)) && !is_sign)
    {
      unsigned short udpsz;
      unsigned char *psave = sizep;
      
      GETSHORT(udpsz, sizep);
      if (udpsz > daemon->edns_pktsz)
	PUTSHORT(daemon->edns_pktsz, psave);
    }

  /* RFC 4035 sect 4.6 para 3 */
  if (!is_sign && !option_bool(OPT_DNSSEC))
     header->hb4 &= ~HB4_AD;

  if (OPCODE(header) != QUERY || (RCODE(header) != NOERROR && RCODE(header) != NXDOMAIN))
    return n;
  
  /* Complain loudly if the upstream server is non-recursive. */
  if (!(header->hb4 & HB4_RA) && RCODE(header) == NOERROR && ntohs(header->ancount) == 0 &&
      server && !(server->flags & SERV_WARNED_RECURSIVE))
    {
      prettyprint_addr(&server->addr, daemon->namebuff);
      my_syslog(LOG_WARNING, _("nameserver %s refused to do a recursive query"), daemon->namebuff);
      if (!option_bool(OPT_LOG))
	server->flags |= SERV_WARNED_RECURSIVE;
    }  
    
  if (daemon->bogus_addr && RCODE(header) != NXDOMAIN &&
      check_for_bogus_wildcard(header, n, daemon->namebuff, daemon->bogus_addr, now))
    {
      munged = 1;
      SET_RCODE(header, NXDOMAIN);
      header->hb3 &= ~HB3_AA;
    }
  else 
    {
      if (RCODE(header) == NXDOMAIN && 
	  extract_request(header, n, daemon->namebuff, NULL) &&
	  check_for_local_domain(daemon->namebuff, now))
	{
	  /* if we forwarded a query for a locally known name (because it was for 
	     an unknown type) and the answer is NXDOMAIN, convert that to NODATA,
	     since we know that the domain exists, even if upstream doesn't */
	  munged = 1;
	  header->hb3 |= HB3_AA;
	  SET_RCODE(header, NOERROR);
	}
      
      if (extract_addresses(header, n, daemon->namebuff, now, is_sign, check_rebind, checking_disabled))
	{
	  my_syslog(LOG_WARNING, _("possible DNS-rebind attack detected: %s"), daemon->namebuff);
	  munged = 1;
	}
    }
  
  /* do this after extract_addresses. Ensure NODATA reply and remove
     nameserver info. */
  
  if (munged)
    {
      header->ancount = htons(0);
      header->nscount = htons(0);
      header->arcount = htons(0);
    }
  
  /* the bogus-nxdomain stuff, doctor and NXDOMAIN->NODATA munging can all elide
     sections of the packet. Find the new length here and put back pseudoheader
     if it was removed. */
  return resize_packet(header, n, pheader, plen);
}
Example #6
0
static bool ProcessDNSRecords(
        const unsigned char * reply,
        const unsigned char * replyEnd,
              unsigned char * cp,
            size_t anCount,
            size_t nsCount,
            size_t arCount,
     DNS_RECORD * results)
{
  DNS_RECORD lastRecord = 0;

  size_t rrCount = anCount + nsCount + arCount;
  nsCount += anCount;
  arCount += nsCount;

  size_t i;
  for (i = 0; i < rrCount; i++) {

    int section;
    if (i < anCount)
      section = DnsSectionAnswer;
    else if (i < nsCount)
      section = DnsSectionAuthority;
    else // if (i < arCount)
      section = DnsSectionAddtional;

    // get the name
    char pName[MAXDNAME];
    if (!GetDN(reply, replyEnd, cp, pName))
      return false;

    // get other common parts of the record
    unsigned short  type;
    unsigned short  dnsClass;
    unsigned long ttl;
    unsigned short  dlen;

    GETSHORT(type,     cp);
    GETSHORT(dnsClass, cp);
    GETLONG (ttl,      cp);
    GETSHORT(dlen,     cp);
    
    //
    // Avoid unused compiler warning
    //
    (void)dnsClass;
    (void)ttl;

    unsigned char * data = cp;
    cp += dlen;

    DNS_RECORD newRecord  = 0;

    switch (type) {
      default:
        newRecord = (DNS_RECORD)malloc(sizeof(DnsRecord) + sizeof(unsigned long) + dlen);
        newRecord->Data.Null.dwByteCount = dlen;
        memcpy(&newRecord->Data, data, dlen);
        break;

      case T_SRV:
        newRecord = (DNS_RECORD)malloc(sizeof(DnsRecord));
        memset(newRecord, 0, sizeof(DnsRecord));
        GETSHORT(newRecord->Data.SRV.wPriority, data);
        GETSHORT(newRecord->Data.SRV.wWeight, data);
        GETSHORT(newRecord->Data.SRV.wPort, data);
        if (!GetDN(reply, replyEnd, data, newRecord->Data.SRV.pNameTarget)) {
          free(newRecord);
          return false;
        }
        break;

      case T_MX:
        newRecord = (DNS_RECORD)malloc(sizeof(DnsRecord));
        memset(newRecord, 0, sizeof(DnsRecord));
        GETSHORT(newRecord->Data.MX.wPreference,  data);
        if (!GetDN(reply, replyEnd, data, newRecord->Data.MX.pNameExchange)) {
          free(newRecord);
          return false;
        }
        break;

      case T_A:
        newRecord = (DNS_RECORD)malloc(sizeof(DnsRecord));
        memset(newRecord, 0, sizeof(DnsRecord));
        GETLONG(newRecord->Data.A.IpAddress, data);
        break;

      case T_NS:
        newRecord = (DNS_RECORD)malloc(sizeof(DnsRecord));
        memset(newRecord, 0, sizeof(DnsRecord));
        if (!GetDN(reply, replyEnd, data, newRecord->Data.NS.pNameHost)) {
          free (newRecord);
          return false;
        }
        break;
    }

    // initialise the new record
    if (newRecord != 0) {
      newRecord->wType = type;
      newRecord->Flags.S.Section = section;
      newRecord->pNext = 0;
      strcpy(newRecord->pName, pName);

      bool hasPlaceHolder = false;
      if (*results == 0)
      {
        *results = newRecord;
        hasPlaceHolder = true;
      }
      else if (lastRecord != 0)
      {
        lastRecord->pNext = newRecord;
        hasPlaceHolder = true;
      }

      if (hasPlaceHolder)
      {
        lastRecord = newRecord;
        newRecord = 0;
      }
      else
      {
        //
        // This can never happen but we need to satisfy coverity scan.
        //
        free(newRecord);
        newRecord = 0;
      }
    }
  }

  return true;
}
Example #7
0
/*
 * get_input - called when incoming data is available.
 */
static void
get_input(void)
{
    int len, i;
    u_char *p;
    u_short protocol;
    struct protent *protp;

    p = inpacket_buf;	/* point to beginning of packet buffer */

    len = read_packet(inpacket_buf);
    if (len < 0)
	return;

    if (len == 0) {
	etime = time(NULL);
	minutes = (etime-stime)/60;
	syslog(LOG_NOTICE, "Modem hangup, connected for %d minutes", (minutes >1) ? minutes : 1);
	hungup = 1;
	lcp_lowerdown(0);	/* serial link is no longer available */
	link_terminated(0);
	return;
    }

    if (debug /*&& (debugflags & DBG_INPACKET)*/)
	log_packet(p, len, "rcvd ", LOG_DEBUG);

    if (len < PPP_HDRLEN) {
	MAINDEBUG((LOG_INFO, "io(): Received short packet."));
	return;
    }

    p += 2;				/* Skip address and control */
    GETSHORT(protocol, p);
    len -= PPP_HDRLEN;

    /*
     * Toss all non-LCP packets unless LCP is OPEN.
     */
    if (protocol != PPP_LCP && lcp_fsm[0].state != OPENED) {
	MAINDEBUG((LOG_INFO,
		   "get_input: Received non-LCP packet when LCP not open."));
	return;
    }

    /*
     * Until we get past the authentication phase, toss all packets
     * except LCP, LQR and authentication packets.
     */
    if (phase <= PHASE_AUTHENTICATE
	&& !(protocol == PPP_LCP || protocol == PPP_LQR
	     || protocol == PPP_PAP || protocol == PPP_CHAP)) {
	MAINDEBUG((LOG_INFO, "get_input: discarding proto 0x%x in phase %d",
		   protocol, phase));
	return;
    }

    /*
     * Upcall the proper protocol input routine.
     */
    for (i = 0; (protp = protocols[i]) != NULL; ++i) {
	if (protp->protocol == protocol && protp->enabled_flag) {
	    (*protp->input)(0, p, len);
	    return;
	}
        if (protocol == (protp->protocol & ~0x8000) && protp->enabled_flag
	    && protp->datainput != NULL) {
	    (*protp->datainput)(0, p, len);
	    return;
	}
    }

    if (debug)
    	syslog(LOG_WARNING, "Unsupported protocol (0x%x) received", protocol);
    lcp_sprotrej(0, p - PPP_HDRLEN, len + PPP_HDRLEN);
}
Example #8
0
static int
printZone(ns_type xfr, const char *zone, const struct sockaddr_in *sin,
	  ns_tsig_key *key)
{
	static u_char *answer = NULL;
	static int answerLen = 0;

	querybuf buf;
	int msglen, amtToRead, numRead, result, sockFD, len;
	int count, type, rlen, done, n;
	int numAnswers, numRecords, soacnt;
	u_char *cp, tmp[NS_INT16SZ];
	char dname[2][NS_MAXDNAME];
	enum { NO_ERRORS, ERR_READING_LEN, ERR_READING_MSG, ERR_PRINTING }
		error;
	pid_t zpid = -1;
	u_char *newmsg;
	int newmsglen;
	ns_tcp_tsig_state tsig_state;
	int tsig_ret, tsig_required, tsig_present;

	switch (xfr) {
	case ns_t_axfr:
	case ns_t_zxfr:
		break;
	default:
		fprintf(stderr, ";; %s - transfer type not supported\n",
			p_type(xfr));
		return (ERROR);
	}

	/*
	 *  Create a query packet for the requested zone name.
	 */
	msglen = res_nmkquery(&res, ns_o_query, zone,
			      queryClass, ns_t_axfr, NULL,
			      0, 0, buf.qb2, sizeof buf);
	if (msglen < 0) {
		if (res.options & RES_DEBUG)
			fprintf(stderr, ";; res_nmkquery failed\n");
		return (ERROR);
	}

	/*
	 * Sign the message if a key was sent
	 */
	if (key == NULL) {
		newmsg = (u_char *)&buf;
		newmsglen = msglen;
	} else {
		DST_KEY *dstkey;
		int bufsize, siglen;
		u_char sig[64];
		int ret;
		
		/* ns_sign() also calls dst_init(), but there is no harm
		 * doing it twice
		 */
		dst_init();
		
		bufsize = msglen + 1024;
		newmsg = (u_char *) malloc(bufsize);
		if (newmsg == NULL) {
			errno = ENOMEM;
			return (-1);
		}
		memcpy(newmsg, (u_char *)&buf, msglen);
		newmsglen = msglen;
		
		if (strcmp(key->alg, NS_TSIG_ALG_HMAC_MD5) != 0)
			dstkey = NULL;
		else
			dstkey = dst_buffer_to_key(key->name, KEY_HMAC_MD5,
							NS_KEY_TYPE_AUTH_ONLY,
							NS_KEY_PROT_ANY,
							key->data, key->len);
		if (dstkey == NULL) {
			errno = EINVAL;
			if (key)
				free(newmsg);
			return (-1);
		}
		
		siglen = sizeof(sig);
/* newmsglen++; */
		ret = ns_sign(newmsg, &newmsglen, bufsize, NOERROR, dstkey, NULL, 0,
		      sig, &siglen, 0);
		if (ret < 0) {
			if (key)
				free (newmsg);
			if (ret == NS_TSIG_ERROR_NO_SPACE)
				errno  = EMSGSIZE;
			else if (ret == -1)
				errno  = EINVAL;
			return (ret);
		}
		ns_verify_tcp_init(dstkey, sig, siglen, &tsig_state);
	}

	/*
	 *  Set up a virtual circuit to the server.
	 */
	if ((sockFD = socket(sin->sin_family, SOCK_STREAM, 0)) < 0) {
		int e = errno;

		perror(";; socket");
		return (e);
	}
	
	switch (sin->sin_family) {
	case AF_INET:
		if (bind(sockFD, (struct sockaddr *)&myaddress,
			 sizeof myaddress) < 0){
			int e = errno;

			fprintf(stderr, ";; bind(%s port %u): %s\n",
				inet_ntoa(myaddress.sin_addr),
				ntohs(myaddress.sin_port),
				strerror(e));
			(void) close(sockFD);
			sockFD = -1;
			return (e);
		}
		if (connect(sockFD, (const struct sockaddr *)sin,
			    sizeof *sin) < 0) {
			int e = errno;

			perror(";; connect");
			(void) close(sockFD);
			sockFD = -1;
			return (e);
		}
		break;
	case AF_INET6:
		if (bind(sockFD, (struct sockaddr *)&myaddress6,
			 sizeof myaddress6) < 0){
			int e = errno;
			char buf[80];

			fprintf(stderr, ";; bind(%s port %u): %s\n",
				inet_ntop(AF_INET6, &myaddress6.sin6_addr,
					  buf, sizeof(buf)),
				ntohs(myaddress6.sin6_port),
				strerror(e));
			(void) close(sockFD);
			sockFD = -1;
			return (e);
		}
		if (connect(sockFD, (const struct sockaddr *)sin,
			    sizeof(struct sockaddr_in6)) < 0) {
			int e = errno;

			perror(";; connect");
			(void) close(sockFD);
			sockFD = -1;
			return (e);
		}
		break;
	}

	/*
	 * Send length & message for zone transfer
	 */

	ns_put16(newmsglen, tmp);
        if (write(sockFD, (char *)tmp, NS_INT16SZ) != NS_INT16SZ ||
            write(sockFD, (char *)newmsg, newmsglen) != newmsglen) {
		int e = errno;
		if (key)
			free (newmsg);
		perror(";; write");
		(void) close(sockFD);
		sockFD = -1;
		return (e);
	} else if (key)
		free (newmsg);

	/*
	 * If we're compressing, push a gzip into the pipeline.
	 */
	if (xfr == ns_t_zxfr) {
		enum { rd = 0, wr = 1 };
		int z[2];

		if (pipe(z) < 0) {
			int e = errno;

			perror(";; pipe");
			(void) close(sockFD);
			sockFD = -1;
			return (e);
		}
		zpid = vfork();
		if (zpid < 0) {
			int e = errno;

			perror(";; fork");
			(void) close(sockFD);
			sockFD = -1;
			return (e);
		} else if (zpid == 0) {
			/* Child. */
			(void) close(z[rd]);
			(void) dup2(sockFD, STDIN_FILENO);
			(void) close(sockFD);
			(void) dup2(z[wr], STDOUT_FILENO);
			(void) close(z[wr]);
			execlp("gzip", "gzip", "-d", "-v", NULL);
			perror(";; child: execlp(gunzip)");
			_exit(1);
		}
		/* Parent. */
		(void) close(z[wr]);
		(void) dup2(z[rd], sockFD);
		(void) close(z[rd]);
	}
	result = 0;
	numAnswers = 0;
	numRecords = 0;
	soacnt = 0;
	error = NO_ERRORS;
	numRead = 0;

	dname[0][0] = '\0';
	for (done = 0; !done; (void)NULL) {
		/*
		 * Read the length of the response.
		 */

		cp = tmp;
		amtToRead = INT16SZ;
		while (amtToRead > 0 &&
		   (numRead = read(sockFD, cp, amtToRead)) > 0) {
			cp += numRead;
			amtToRead -= numRead;
		}
		if (numRead <= 0) {
			error = ERR_READING_LEN;
			break;
		}

		len = ns_get16(tmp);
		if (len == 0)
			break;	/* nothing left to read */

		/*
		 * The server sent too much data to fit the existing buffer --
		 * allocate a new one.
		 */
		if (len > answerLen) {
			if (answerLen != 0)
				free(answer);
			answerLen = len;
			answer = (u_char *)malloc(answerLen);
		}

		/*
		 * Read the response.
		 */

		amtToRead = len;
		cp = answer;
		while (amtToRead > 0 &&
		       (numRead = read(sockFD, cp, amtToRead)) > 0) {
			cp += numRead;
			amtToRead -= numRead;
		}
		if (numRead <= 0) {
			error = ERR_READING_MSG;
			break;
		}

		result = print_axfr(stdout, answer, len);
		if (result != 0) {
			error = ERR_PRINTING;
			break;
		}
		numRecords += htons(((HEADER *)answer)->ancount);
		numAnswers++;

		/* Header. */
		cp = answer + HFIXEDSZ;
		/* Question. */
		for (count = ntohs(((HEADER *)answer)->qdcount);	
		     count > 0;
		     count--) {
			n = dn_skipname(cp, answer + len);
			if (n < 0) {
				error = ERR_PRINTING;
				done++;
				break;
			}
			cp += n + QFIXEDSZ;
			if (cp > answer + len) {
				error = ERR_PRINTING;
				done++;
				break;
			}
		}
		/* Answer. */
		for (count = ntohs(((HEADER *)answer)->ancount);
		     count > 0 && !done;
		     count--) {
			n = dn_expand(answer, answer + len, cp,
				      dname[soacnt], sizeof dname[0]);
			if (n < 0) {
				error = ERR_PRINTING;
				done++;
				break;
			}
			cp += n;
			if (cp + 3 * INT16SZ + INT32SZ > answer + len) {
				error = ERR_PRINTING;
				done++;
				break;
			}
			GETSHORT(type, cp);
			cp += INT16SZ;
			cp += INT32SZ;	/* ttl */
			GETSHORT(rlen, cp);
			cp += rlen;
			if (cp > answer + len) {
				error = ERR_PRINTING;
				done++;
				break;
			}
			if (type == T_SOA && soacnt++ &&
			    ns_samename(dname[0], dname[1]) == 1) {
				done++;
				break;
			}
		}

		/*
		 * Verify the TSIG
		 */

		if (key) {
			if (ns_find_tsig(answer, answer + len) != NULL)
				tsig_present = 1;
			else
				tsig_present = 0;
			if (numAnswers == 1 || soacnt > 1)
				tsig_required = 1;
			else
				tsig_required = 0;
			tsig_ret = ns_verify_tcp(answer, &len, &tsig_state,
						 tsig_required);
			if (tsig_ret == 0) {
				if (tsig_present)
					printf("; TSIG ok\n");
			}
			else
				printf("; TSIG invalid\n");
		}

	}

	printf(";; Received %d answer%s (%d record%s).\n",
	       numAnswers, (numAnswers != 1) ? "s" : "",
	       numRecords, (numRecords != 1) ? "s" : "");

	(void) close(sockFD);
	sockFD = -1;

	/*
	 * If we were uncompressing, reap the uncompressor.
	 */
	if (xfr == ns_t_zxfr) {
		pid_t pid;
		int status = 0;

		pid = wait(&status);
		if (pid < 0) {
			int e = errno;

			perror(";; wait");
			return (e);
		}
		if (pid != zpid) {
			fprintf(stderr, ";; wrong pid (%lu != %lu)\n",
				(u_long)pid, (u_long)zpid);
			return (ERROR);
		}
		printf(";; pid %lu: exit %d, signal %d, core %c\n",
		       (u_long)pid, WEXITSTATUS(status),
		       WIFSIGNALED(status) ? WTERMSIG(status) : 0,
		       WCOREDUMP(status) ? 't' : 'f');
	}

	switch (error) {
	case NO_ERRORS:
		return (0);

	case ERR_READING_LEN:
		return (EMSGSIZE);

	case ERR_PRINTING:
		return (result);

	case ERR_READING_MSG:
		return (EMSGSIZE);

	default:
		return (EFAULT);
	}
}
Example #9
0
main ()
{
 int i, j, hl, rc, qc, ac, p, a;
 int op, class, type, datalen, buflen, msgl;
 u_short qtype, qclass, rtype, rclass, l, l2;
 u_long rttl;
 u_char buf[100], *cp;
 char dn[100], *dname, *z, ping[50];
 struct rrec newrr, *rec;
 union {
	char cdat[4];
	unsigned long ldat;
	struct in_addr adat;
 } dat;
 union {
	u_char data[DATALEN];
	HEADER head;
 } data;

  hl = sizeof (HEADER);
  signal (SIGALRM, tfunc);
  res_init();
  printf ("Inhalt von resolv.conf\n");
  printf ("domain: %s\n", _res.defdname);
 /* printf ("MAXDNSRCH = %d\n", MAXDNSRCH);
  for (i=0; i<MAXDNSRCH; i++)
	printf ("%s\n", _res.dnsrch[i]);
*/
  printf ("%d Name-Server\n", MAXNS);
  for (i=0; i<MAXNS; i++)
  	printf ("%s\n", inet_ntoa(_res.nsaddr_list[i].sin_addr));
/*  printf ("number of addresses: %d \n", _res.ascount);
  printf ("number of name servers: %d \n", _res.nscount);
*/
  /*printf ("%d %s\n", _res.ascount, inet_ntoa(_res.sort_list[0]));*/
 
/*  strcpy (dn, "zeus.rz.htwk-leipzig.de");  */
/*  strcpy (dn, "caramba.cs.tu-berlin.de"); */ 
/*  strcpy (dn, "ftp.cs.tu-berlin.de");  */
/*  strcpy (dn, "moses.imn.htwk-leipzig.de"); */
/*  strcpy (dn, "moses"); */

 do {
  printf ("\nSuche nach IP-Adresse von\n");
  printf ("Hostname: ");
  z = gets (dn); 
  printf ("\n");
 if (z) {
  dname = dn;
  strcpy (data.data, dn);
  datalen = strlen(dn)+1;
  op = QUERY;
  buflen = sizeof(buf);
/*  _res.options |= RES_DEBUG; */
  _res.retrans = 10;
  _res.retry = 2; 
  class = C_IN; 
  type = T_A; 
  rc=res_mkquery (op, dname, class, type, data.data, datalen, &newrr, buf, buflen);

  buflen = rc;
  alarm (10);
  msgl=res_send (buf, buflen, data.data, DATALEN);
  if (msgl>0) {

/*  printf ("\nsend: %d\n", msgl); */
/* for (i=0; i< msgl; i++) {
	for (j=0; j<4; j++) dat.cdat[j] = data.data[i+j];
*/
/*	printf ("%x ", dat.ldat); 
	if (dat.ldat==x) printf ("\n%d %x\n", i, dat.ldat); 
  }
  printf ("\n");
*/
/*  for (i=0; i< msgl;i++) {
	j = data.data[i] & 0xff; printf ("%2x ", j); 
  } 
  printf ("\n");
  for (i=0; i< msgl;i++) if (data.data[i]>31) printf ("%c ", data.data[i]);
  printf ("\n");
*/
/*  printf ("%x \n", x); 
*/
  ac = data.head.ancount;
  qc = data.head.qdcount;
  p = hl;
  printf ("Query\n");
  while (qc) {
    l = data.data[p];
    while (l > 0 && l < 64) {
/*	printf ("%d \n", p); */
	for (i=1; i<=l; i++) putchar (data.data[p+i]);	       	
	p = p + l + 1;
	l = data.data[p];
	if (l) putchar ('.');
    } 
    putchar ('\n');
    p++;
    cp = data.data+p; /* GETSHORT verlangt Pointervariable !! */
/* einfache Zuweisung (auch mit cast) ergibt falsche Werte
   evtl. Probleme mit integralen Grenzen ?? */
    GETSHORT (qtype, cp); 
/* oder: qtype = _getshort(data.data+p);*/
    p = p + sizeof(u_short);
    cp = data.data+p;
    GETSHORT (qclass, cp); 
    p = p + sizeof(u_short);
    cp = data.data+p;
    printf ("QTYPE=%d, QCLASS=%d", qtype, qclass);
    qc--;
    putchar ('\n');
  }
  printf ("\n%d Answers\n", ac);
  a=1;
  while (ac) {
    printf ("%d.\n", a);
    l = data.data[p];
    while (l > 0 && l < 64) {
/*	printf ("%d \n", p); */
	for (i=1; i<=l; i++) putchar (data.data[p+i]);	       	
	p = p + l + 1;
	l = data.data[p];
	if (l) putchar ('.');
	else putchar ('\n');
    }
    if (l>63) {
	rc=dn_expand (data.data, data.data+msgl, cp, buf, buflen);
	printf ("%s\n", buf);
	p += 2;
    }  else p++;
    cp = data.data+p;
    GETSHORT (rtype, cp); 
    p = p + sizeof(u_short);
    cp = data.data+p;
    GETSHORT (rclass, cp); 
    p = p + sizeof(u_short);
    cp = data.data+p;
    GETLONG (rttl, cp);
    p = p + sizeof(u_long);
    printf ("RRTYPE=%d, RRCLASS=%d RRTTL=%d\n", rtype, rclass, rttl);
    cp = data.data+p;
    GETSHORT (l, cp);
    p = p + sizeof(u_short);
    if (rtype == 1) {
    	for (j = 0; j< l; j++) dat.cdat[j] = data.data[p+j];
/*	printf ("IP-Adresse: %x \n", dat.ldat); */
    	printf ("IP-Adresse: %s \n", inet_ntoa (dat.adat));
    	sprintf (buf, "%s", inet_ntoa (dat.adat));
	strcpy (ping, "ping ");
	strcat (ping, buf);
	strcat (ping, " 10");
	printf ("%s\n", ping);
	system (ping);
	p += l;
    } 
    if (rtype == 5) {
	l2 = l;
	l = data.data[p];
	while (l > 0 && l < 64) {
/*		printf ("%d \n", p); */
		for (i=1; i<=l; i++) putchar (data.data[p+i]);	       	
		p = p + l + 1;
		l = data.data[p];
		if (l) putchar ('.');
		else putchar('\n');
    	}
    	if (l>63) {
		rc=dn_expand (data.data, data.data+msgl, cp, buf, buflen);
		printf ("%s\n", buf);
		p += 2;
    	}  else p++;
	l = l2;
    }
    putchar ('\n');
    ac--; a++;
    }
   } else printf ("not found\n");
 } } while (z);
}
Example #10
0
static int waigroup_cert_3_3(struct wapi_asue_st* wpa_s, u8* payload, int len)
{
	u8 flag = 0 ;
	u8 *Nasue = NULL, *Nae = NULL, *acc_res = NULL;
	u8 *asue_key_data = NULL,*ae_key_data = NULL;
	u8 *ae_id = NULL, *asue_id = NULL, *cert_res = NULL;
	u8 *ae_sign = NULL;
	int request_len = 0;
	const struct cert_obj_st_t  *cert_obj = NULL;
	
	iwn_wpa_printf(MSG_DEBUG, "WPA: in %s:%d", __func__, __LINE__);

	if (wpa_s->wapi_state != WAPISM_CNT_REQ)
	{
		return -1;
	}

	wapi_supplicant_key_negotiation_state_report(WPA_4WAY_HANDSHAKE);

	/*flag*/
	flag = payload[0];
	iwn_wpa_printf(MSG_DEBUG, "WPA: in %s:%d,flag=%d", __func__, __LINE__,flag);
	iwn_wpa_printf(MSG_DEBUG, "WPA: in %s:%d,wpa_s->flag=%d,(flag & BIT(0) )=%d", __func__, __LINE__,flag,(flag & BIT(0) ));
	iwn_wpa_printf(MSG_DEBUG, "WPA: in %s:%d,wpa_s->flag=%d,(flag & BIT(0) )=%d", __func__, __LINE__,flag,(wpa_s->flag& BIT(0) ));
	iwn_wpa_printf(MSG_DEBUG, "WPA: in %s:%d,wpa_s->flag=%d,(flag & BIT(1) )=%d", __func__, __LINE__,flag,(flag & BIT(1) ));
	iwn_wpa_printf(MSG_DEBUG, "WPA: in %s:%d,wpa_s->flag=%d,(flag & BIT(1) )=%d", __func__, __LINE__,flag,(wpa_s->flag & BIT(1) ));

	if((flag &0x03)!= (wpa_s->flag & 0x03))
	{
		iwn_wpa_printf(MSG_ERROR, "WPA: not same flag bit 0,1!\n");
		return -1;
	}
	request_len +=1;
	Nasue = payload+1;
	if(Nasue == NULL) return -1;
	if(memcmp(Nasue, wpa_s->Nasue , 32)!=0)
	{
		iwn_wpa_printf(MSG_ERROR, "WPA: not same Nasue!\n");
		return -1;
	}
	request_len +=32;
	Nae = Nasue + 32;
	if(Nae== NULL) return -1;
	memcpy(wpa_s->Nae, Nae, 32);
	request_len +=32;
	acc_res = Nae + 32;
	if(acc_res == NULL) return -1;
	if(acc_res[0] != 0) return -2;
	request_len +=1;
	asue_key_data = acc_res + 1;
	if(asue_key_data == NULL) return -1;
	if((asue_key_data[0]!=wpa_s->asue_key_data.length)
		||memcmp((char *)asue_key_data+1, &(wpa_s->asue_key_data.data), wpa_s->asue_key_data.length )!=0)
	{
		iwn_wpa_printf(MSG_ERROR, "WPA: not same asue key data!,asue_len =%d,wpa_s->asue_key_data.length=%d\n",asue_key_data[0],wpa_s->asue_key_data.length);

		return -1;
	}
	request_len +=wpa_s->asue_key_data.length + 1;
	ae_key_data = asue_key_data + 	wpa_s->asue_key_data.length + 1;
	if(ae_key_data == NULL) return -1;
	memcpy(wpa_s->ae_key_data.data, ae_key_data+1,ae_key_data[0]);
	wpa_s->ae_key_data.length = ae_key_data[0];
	request_len +=ae_key_data[0] + 1;
	ae_id = ae_key_data + ae_key_data[0] + 1;
	if(ae_id == NULL) return -1;
	if (cmp_var_struct(ae_id, &(wpa_s->ae_id), wpa_s->ae_id.id_len))
	{
		iwn_wpa_printf(MSG_ERROR, "WPA: not same ae id!\n");
		iwn_wpa_hexdump(MSG_ERROR, "ae_id", ae_id,wpa_s->ae_id.id_len+ 4);
		iwn_wpa_hexdump(MSG_ERROR, "wpa_s->ae_id", (unsigned char *)&(wpa_s->ae_id),wpa_s->ae_id.id_len+ 4);
		return -1;
	}
	request_len +=wpa_s->ae_id.id_len+ 4;
	iwn_wpa_printf(MSG_DEBUG, "WPA: in %s:%d,request_len=%d,wpa_s->ae_id.id_len=%d", __func__, __LINE__,request_len,wpa_s->ae_id.id_len);
	asue_id = ae_id + wpa_s->ae_id.id_len+ 4;
	if(asue_id == NULL) return -1;
	if (cmp_var_struct(asue_id, &(iwn_eloop.asue_id), iwn_eloop.asue_id.id_len))
	{
		iwn_wpa_printf(MSG_ERROR, "WPA: not same asue id!\n");
		return -1;
	}
	request_len +=iwn_eloop.asue_id.id_len+ 4;
	iwn_wpa_printf(MSG_DEBUG, "WPA: in %s:%d,request_len=%d,wpa_s->asue_id.id_len=%d", __func__, __LINE__,request_len,iwn_eloop.asue_id.id_len);


	if(flag & BIT(3))
	{
		u8 *cert_pos = NULL, *asu_sign = NULL;
		u16 fix_data_len=0, sign_len=0; 
		tkey *pubkey = NULL;
		iwn_wpa_printf(MSG_DEBUG, "WPA: in %s:%d,iwn_eloop.asue_id.id_len=%d", __func__, __LINE__,iwn_eloop.asue_id.id_len);

		cert_res = asue_id +iwn_eloop.asue_id.id_len+ 4;
		if(cert_res[0] != 2)
		{
			iwn_wpa_printf(MSG_ERROR, "cert result flag is not 2!\n");
			return -1;
		}
		cert_pos = cert_res + 1 +2 + 32 + 32 + 1 + 2 ;
		GETSHORT((cert_pos), fix_data_len);
		cert_pos = cert_pos + fix_data_len + 2;
		if(cert_pos[0] != 0)
		{
			iwn_wpa_printf(MSG_ERROR, "cert result  is not ok!\n");
			return -2;
		}
		GETSHORT((cert_pos + 1 + 2), fix_data_len);
		asu_sign = cert_pos + fix_data_len + 1 + 2 + 2;
		GETSHORT((asu_sign + 1), sign_len);
		iwn_wpa_printf(MSG_DEBUG, "WPA: in %s:%d", __func__, __LINE__);

		GETSHORT((cert_res + 1), fix_data_len);
		cert_obj = get_cert_obj(iwn_eloop.cert_info.config.used_cert);
		pubkey = cert_obj->asu_pubkey;
		if(!(*cert_obj->verify)(pubkey->data, pubkey->length,
								cert_res,fix_data_len + 3,
								asu_sign + 1 + 2 + sign_len - 48,
								48))
		{
			iwn_wpa_hexdump(MSG_ERROR, "pubkey->data", pubkey->data,pubkey->length);
			iwn_wpa_hexdump(MSG_ERROR, "cert_res", cert_res,fix_data_len + 3);
			iwn_wpa_hexdump(MSG_ERROR, "asu_sign", asu_sign + 1 + 2 + sign_len - 48,48);
			return -1;
		}
		request_len +=fix_data_len + 3+sign_len+3 ;
		iwn_wpa_printf(MSG_DEBUG, "WPA: in %s:%d,request_len=%d,len=%d", __func__, __LINE__,request_len,len);

	}
	{
		tkey *pubkey = NULL;
		u16 fix_data_len = 0;
		u16 cert_flag = wpa_s->ae_cert.cert_flag;//iwn_ntohs(wpa_s->ae_cert.cert_flag);

		ae_sign = payload + len - 48;
		cert_obj = get_cert_obj(cert_flag);
		iwn_wpa_printf(MSG_DEBUG, "WPA: in %s:%d,wpa_s->ae_cert.len=%d", __func__, __LINE__,wpa_s->ae_cert.length);
		pubkey = (*cert_obj->get_public_key)((void *)&wpa_s->ae_cert);
		if(!(*cert_obj->verify)(pubkey->data, pubkey->length,
							payload,request_len,
							ae_sign,
							48))
		{
			pubkey = iwn_free_buffer(pubkey, sizeof(tkey));
			printf("AE sign error!!!\n");
			return -1;
		}
		iwn_wpa_printf(MSG_DEBUG, "WPA: in %s:%d", __func__, __LINE__);
		pubkey = iwn_free_buffer(pubkey, sizeof(tkey));
		iwn_wpa_printf(MSG_DEBUG, "WPA: in %s:%d", __func__, __LINE__);
		GETSHORT((payload+request_len+1), fix_data_len);
		request_len += fix_data_len + 3;
	}
	if(len != request_len)
	{
		iwn_wpa_printf(MSG_DEBUG, "WPA: in %s:%d,request_len=%d,len=%d", __func__, __LINE__,request_len,len);
		return -1;
	}

	iwn_wpa_printf(MSG_DEBUG, "WPA: in %s:%d", __func__, __LINE__);
	asue_certauthbk_derivation(wpa_s);

	wpa_s->wapi_state = WAPISM_CNT_RESP;

	return 0;
}
Example #11
0
//******************************************************************************
//	 			Parse DNS address from ipconfig options
//******************************************************************************
Boolean Capi2ReadDnsSrv( PCHProtConfig_t *ipcnfg,
						   u_long* primaryDns1,
						   u_long* secDns1,
						   u_long* primaryDns2,
						   u_long* secDns2)        
{                                                                         
	u_char *input;                                                          
	u_char code, id, len_pid;
	u_short protocol;
	int len, t_len;               				  
	int i=0;
    int type, templ;							 
	u_long DNSsrvr;				
	u_long l;
	
	*primaryDns1 = 0;
	*secDns1 = 0;
	*primaryDns2 = 0;
	*secDns2 = 0;

	IPCPDEBUG(("ReadDnsSrv, read dns_servers"));
	/* if option length == 2, no option data */
	if (ipcnfg->length ==  0)                                 
    {                                                                     
		IPCPDEBUG(("Network ignored protocol options"));                  
		/* (Not an error, network does not want to bother) */
		return TRUE;                                                           
    }                                                                     
                                                                          
	len = 0;                                                              
	if (( ipcnfg->options[len++] & 0x83 ) == 0x81)	  	                  
    {                                                                     
		IPCPDEBUG(("Bad protocol config option"));                        
		return FALSE;                                                           
    }                                                                     
                                                                          
	t_len = len;                                                          
	while ( t_len < (ipcnfg->length) )                      
    {                                                                     
		input = (u_char *) &ipcnfg->options[t_len];  	                  
        GETSHORT(protocol, input);
        GETCHAR(len_pid, input);
        GETCHAR(code, input);
        GETCHAR(id, input);
        GETSHORT(len, input);
		switch (protocol)				                                  
    	{									                              
			/* Check LCP option from the Network */
			case PPP_LCP:			   
				break;                                                      

			/* Check IPCP option from the Network */
			case PPP_IPCP:
				if ( code == CONFREQ )
                {
                	IPCPDEBUG((" ReadOptions: CONFREQ"));
					i=0;
					while (i<(len-4))
                    {
   						GETCHAR(type, input);     			//RFC 1661, this is option type
   						GETCHAR(templ, input);		  		//RFC 1661, next byte is length
      					GETLONG(l, input);					//read but don't use
						i += templ;
					}
				}
				else if ( code == CONFACK || code == CONFNAK )													
                {	
                	IPCPDEBUG((" ReadOptions: CONFACK or CONFNAK"));
					
					i=0;
					while (i<(len-4))
                    {
   						GETCHAR(type, input);     //RFC 1661, this is option type
   						GETCHAR(templ, input);		  //RFC 1661, next byte is length
						switch (type)
                        {
							case CI_ADDR:
      							GETLONG(l, input);
								IPCPDEBUG(("CI_ADDR"));
								break;
							case CI_DNSADDR_PRI:
      							GETLONG(l, input);
								DNSsrvr = htonl(l);
								*primaryDns1 = DNSsrvr;
   								IPCPDEBUG(("CI_DNSADDR_PRI =%x", DNSsrvr));
								break;
						
							case (CI_DNSADDR_PRI+1):
      							GETLONG(l, input);
								DNSsrvr = htonl(l);
								*primaryDns2 = DNSsrvr;
   								IPCPDEBUG(("CI_DNSADDR_PRI =%x", DNSsrvr));
								break;
						
							case CI_DNSADDR_SEC:
      							GETLONG(l, input);
								DNSsrvr = htonl(l);
								*secDns1 = DNSsrvr;
   								IPCPDEBUG(("CI_DNSADDR_SEC"));
								break;
						
							case (CI_DNSADDR_SEC+1):
      							GETLONG(l, input);
								DNSsrvr = htonl(l);
								*secDns2 = DNSsrvr;
   								IPCPDEBUG(("CI_DNSADDR_SEC"));
								break;	  
							default:
								break;
                        }
						i += templ;

                    }
                }	
				else	/* Network had rejected */
                {
					while(i<(len-4))
                    {
   						GETCHAR(type, input);
   						GETCHAR(templ, input);								 
						switch (type)
                        {
							case CI_DNSADDR_PRI:
								IPCPDEBUG(("CI_DNSADDR_PRI rejected"));
								break;
						
							case (CI_DNSADDR_PRI+1):
								IPCPDEBUG(("CI_DNSADDR_PRI+1 rejected"));
								break;
						
							case CI_DNSADDR_SEC:
								IPCPDEBUG(("CI_DNSADDR_SEC rejected"));
								break;
						
							case (CI_DNSADDR_SEC+1):			 // Not supported
								IPCPDEBUG(("CI_DNSADDR_SEC+1 rejected"));
								break;	  
							default:
								break;
                        }
						i += templ;
                    }
					IPCPDEBUG((" ReadOptions: IPCP REJed"));	
                }	
				break;
			default:
				break;
    	}
	   	t_len += (len + 3);
     }                                                                                                            

	return TRUE;                                                           
}
Example #12
0
struct wapi_rxfrag *iwn_wpa_defrag(struct wapi_asue_st *wpa_s, struct wapi_rxfrag *rxbuf)
{
	u8 *buf =(u8 *)rxbuf->data;
	int len = rxbuf->data_len;

	struct wai_hdr *hdr = (struct wai_hdr *)buf;
	u16 rxseq=0, last_rxseq=0;
	u8 fragno, last_fragno;
	u8 more_frag = hdr->more_frag;

	struct wapi_rxfrag *wai_frame = NULL;
	GETSHORT(hdr->rxseq, rxseq);
	fragno = hdr->frag_sc;

	/* Quick way out, if there's nothing to defragment */
	if ((!more_frag) && (fragno == 0) && (wpa_s->rxfrag== NULL))
	{
		iwn_wpa_printf(MSG_DEBUG, "WPA: in %s:%d", __func__, __LINE__);
		return rxbuf;
	}

	/*
	 * Update the time stamp.  As a side effect, it
	 * also makes sure that the timer will not change
	 * ni->ni_rxfrag[0] for at least 1 second, or in
	 * other words, for the remaining of this function.
	 */
	/*
	 * Validate that fragment is in order and
	 * related to the previous ones.
	 */
	if (wpa_s->rxfrag) {
		struct wai_hdr *hdr1;
		iwn_wpa_printf(MSG_DEBUG, "WPA: in %s:%d", __func__, __LINE__);

		hdr1 = (struct wai_hdr *) wpa_s->rxfrag->data;
		GETSHORT(hdr1->rxseq, last_rxseq);
		last_fragno = hdr1->frag_sc;
		if (rxseq != last_rxseq
		    || fragno != last_fragno + 1
			||(wpa_s->rxfrag->maxlen - wpa_s->rxfrag->data_len< len)
			/*||(time(NULL) - wpa_s->rxfragstamp >1)*/
			)
		{
			/*
			 * Unrelated fragment or no space for it,
			 * clear current fragments
			 */
			wpa_s->rxfrag = free_rxfrag(wpa_s->rxfrag); 
		}
		iwn_wpa_printf(MSG_DEBUG, "WPA: in %s:%d", __func__, __LINE__);
	}
	/* If this is the first fragment */
 	if (wpa_s->rxfrag == NULL && fragno == 0) {
		/*ni->ni_rxfrag[0] = skb;*/
		wpa_s->rxfrag = malloc_rxfrag(PAGE_LEN);
		/* If more frags are coming */
		if (more_frag) {
			wpa_put_frag(wpa_s->rxfrag, buf, len);
			iwn_wpa_printf(MSG_DEBUG, "WPA: in %s:%d", __func__, __LINE__);
		
		}
	}
	else {
			if (wpa_s->rxfrag) {
			struct wai_hdr *lhdr = (struct wai_hdr *)wpa_s->rxfrag->data;

			/*
			 * We know we have enough space to copy,
			 * we've verified that before
			 */
			/* Copy current fragment at end of previous one */
			/* Update tail and length */
			wpa_put_frag(wpa_s->rxfrag , buf + WAI_HDR, len - WAI_HDR);
			
			/* Keep a copy of last sequence and fragno */
			*(u16 *)lhdr->rxseq = *(u16*)hdr->rxseq;
			lhdr->frag_sc = hdr->frag_sc;
		}
	}
		
	if (more_frag) {
		/* More to come */
		wai_frame = NULL;
	} else {
		/* Last fragment received, we're done! */
		wai_frame = wpa_s->rxfrag;
	}
/*	wpa_s->rxfragstamp = time(0);*/
	return wai_frame;
}
Example #13
0
static int waigroup_cert_1_3(struct wapi_asue_st* wpa_s, u8* payload, int len)
{
	u8 flag = 0;
	u8 *ae_auth_flag = NULL;
	u8 *asu_id = NULL;
	u8 *ae_cer = NULL;
	u8 *ecdh = NULL;
	int ret = -1;
	

	u8 auth_act_len = WAI_FLAG_LEN  
		+32
		+2/*ASU ID Identifier*/
		+2/*ASU ID Length*/
		+2/*AE Cert type*/
		+2/*AE Cert length*/
		+1/*ECDH Parameter Identifier*/
		+2/*ECDH Parameter Length */;

	iwn_wpa_printf(MSG_DEBUG, "WPA: in %s:%d", __func__, __LINE__);

	wapi_supplicant_key_negotiation_state_report(WPA_4WAY_HANDSHAKE);
	
	if(len < auth_act_len)
	{
		iwn_wpa_printf(MSG_ERROR, "WPA: WAI frame payload too short");
		return -1;
	}
	

	flag = payload[0];
	ae_auth_flag = payload+1;
	asu_id = payload+1 + 32;
	
	len -= auth_act_len;
	
	if (AUTH_TYPE_WAPI != wpa_s->ap_type)
	{
		return -1;
	}
	else
	{
		int bk_up = flag & BIT(0);
		wapi_states require = bk_up ? WAPISM_FINISH : WAPISM_AL_ASSOC;
		
		if (wpa_s->wapi_state != require)
		{
		       /* skip the usk update check */
		       if (wpa_s->usk_updated && bk_up && wpa_s->wapi_state == WAPISM_UNI_ACK)
			   	;
			else
				return -1;
		}
	}

	if(flag &BIT(0)){
		if(memcmp(ae_auth_flag, wpa_s->ae_auth_flag, 32) !=0)
		{
			iwn_wpa_printf(MSG_ERROR, "WPA: ae_auth_flag not same!\n");
			return -1;
		}
	}else{
	
		memcpy(wpa_s->ae_auth_flag, ae_auth_flag, 32);
	}
	
	/*get ASU ID*/	
	GETSHORT(asu_id, wpa_s->ae_asu_id.id_flag); 
	GETSHORT((asu_id+2), wpa_s->ae_asu_id.id_len);

	if(len <wpa_s->ae_asu_id.id_len){
		
		iwn_wpa_printf(MSG_ERROR, "WPA: WAI frame payload too short");
		return -1;
	}
	else{
		memcpy(wpa_s->ae_asu_id.id_data, asu_id+4, wpa_s->ae_asu_id.id_len);
	}
	
	len -= wpa_s->ae_asu_id.id_len; 

	/*get AE Certificate*/
	ae_cer = asu_id + 2 + 2 + wpa_s->ae_asu_id.id_len;
	
	GETSHORT(ae_cer, wpa_s->ae_cert.cert_flag); 
	GETSHORT((ae_cer+2), wpa_s->ae_cert.length); 
	
	if(len <wpa_s->ae_cert.length){
		
		iwn_wpa_printf(MSG_ERROR, "WPA: WAI frame payload too short");
		return -1;
	}
	else{
		memcpy(wpa_s->ae_cert.data, ae_cer+4, wpa_s->ae_cert.length);
	}
	len -= wpa_s->ae_cert.length;

	/*get AE ID*/
	iwn_wai_fixdata_id_by_ident(&wpa_s->ae_cert, &(wpa_s->ae_id), wpa_s->ae_cert.cert_flag);
	iwn_wpa_hexdump(MSG_DEBUG, "AE ID: ", wpa_s->ae_id.id_data, wpa_s->ae_id.id_len);

	/*get ECDH Parameter*/
	ecdh = ae_cer + 2 + 2 + wpa_s->ae_cert.length;

	wpa_s->ecdh.para_flag = ecdh[0];
	GETSHORT((ecdh + 1), wpa_s->ecdh.para_len);

	if(len <wpa_s->ecdh.para_len){
		
		iwn_wpa_printf(MSG_ERROR, "WPA: WAI frame payload too short");
		return -1;
	}
	else{
		memcpy(wpa_s->ecdh.para_data, ecdh+3, wpa_s->ecdh.para_len);
	}
	len -= wpa_s->ecdh.para_len;

	
	if(len != 0) 
	{
		iwn_wpa_printf(MSG_DEBUG, "WPA: in %s:%d", __func__, __LINE__);
		return -1;
	}
	
	asue_initialize_alg(wpa_s);
	ret = asue_x_x_p_derivation(wpa_s);
	if(ret == -1)
		return -1;

	get_random(wpa_s->Nasue, 32);

	if (waigroup_cert_2_3_send(wpa_s, payload, len))
	{
		iwn_wpa_printf(MSG_DEBUG, "WPA: in %s:%d", __func__, __LINE__);
		return -1;
	}
	return 0;
}
Example #14
0
static int waigroup_cert_1_3_old(struct wapi_asue_st* wpa_s, u8* payload, int len)
{
	u8 flag = 0;
	u8 *ae_auth_flag = NULL;
	u8 *asu_id = NULL;
	u8 *ae_cer = NULL;
	u8 *ecdh = NULL;
	u16 fix_data_len = 0;
	int  request_len = 0;
	int ret = -1;
	
	iwn_wpa_printf(MSG_DEBUG, "WPA: in %s:%d", __func__, __LINE__);
	/*flag*/
	wpa_s->flag = 0;
	flag = payload[0];
	wpa_s->flag = flag;
	request_len +=1;

	{
		if (AUTH_TYPE_WAPI != wpa_s->ap_type)
		{
			return -1;
		}
		else
		{
			int bk_up = flag & BIT(0);
			wapi_states require = bk_up ? WAPISM_FINISH : WAPISM_AL_ASSOC;
			
			if (wpa_s->wapi_state != require)
			{
			       /* skip the usk update check */
			       if (wpa_s->usk_updated && bk_up && wpa_s->wapi_state == WAPISM_UNI_ACK)
				   	;
				else
					return -1;
			}
		}
	}

	ae_auth_flag = payload+1; 
	if(ae_auth_flag == NULL) 
	{
		iwn_wpa_printf(MSG_DEBUG, "WPA: in %s:%d", __func__, __LINE__);
		return -1;
	}
	if(flag &BIT(0)){
		if(memcmp(ae_auth_flag, wpa_s->ae_auth_flag, 32) !=0)
		{
			iwn_wpa_printf(MSG_ERROR, "WPA: ae_auth_flag not same!\n");
			return -1;
		}
	}else 
		memcpy(wpa_s->ae_auth_flag, ae_auth_flag, 32);
	request_len +=32;
	
	asu_id = ae_auth_flag + 32;
	if(asu_id == NULL) 
	{
		iwn_wpa_printf(MSG_DEBUG, "WPA: in %s:%d", __func__, __LINE__);
		return -1;
	}
	GETSHORT((asu_id + 2), fix_data_len);
	/*iwn_wpa_hexdump(MSG_DEBUG, "asu_id ", asu_id, fix_data_len+4);*/
	memcpy(&(wpa_s->ae_asu_id), asu_id ,fix_data_len + 4) ;
	request_len +=2 + 2 +fix_data_len;
	ae_cer = asu_id + 2 + 2 + fix_data_len;
	if(ae_cer == NULL) 
	{
		iwn_wpa_printf(MSG_DEBUG, "WPA: in %s:%d", __func__, __LINE__);
		return -1;
	}

	GETSHORT(ae_cer, wpa_s->ae_cert.cert_flag); ae_cer +=2;
	GETSHORT(ae_cer, wpa_s->ae_cert.length); ae_cer +=2;
	memcpy(wpa_s->ae_cert.data, ae_cer, wpa_s->ae_cert.length);
	ae_cer -= 4;
	fix_data_len = wpa_s->ae_cert.length;
	
	/*iwn_wpa_hexdump(MSG_DEBUG, "ae_cer ", ae_cer+2+2, fix_data_len);*/
	request_len +=2 + 2 +fix_data_len;
	{
          	u16 cert_flag = 0;

		/* get ae cert type */
		GETSHORT(ae_cer , cert_flag);
		((cert_id  *)ae_cer)->length = fix_data_len; 
		iwn_wai_fixdata_id_by_ident(ae_cer, &(wpa_s->ae_id), cert_flag);
		iwn_wpa_hexdump(MSG_DEBUG, "AE ID: ", wpa_s->ae_id.id_data, wpa_s->ae_id.id_len);

	}
	ecdh = ae_cer + 2 + 2 + fix_data_len;
	if(ecdh == NULL) return -1;
	wpa_s->ecdh.para_flag = ecdh[0];
	GETSHORT((ecdh + 1), fix_data_len);
	wpa_s->ecdh.para_len = fix_data_len;
	request_len +=1 + 2 +fix_data_len;
	memcpy(&(wpa_s->ecdh.para_data), ecdh+3, fix_data_len);
	if(len != request_len) 
	{
		iwn_wpa_printf(MSG_DEBUG, "WPA: in %s:%d", __func__, __LINE__);
		return -1;
	}
	asue_initialize_alg(wpa_s);
	ret = asue_x_x_p_derivation(wpa_s);
	if(ret == -1)
		return -1;

	get_random(wpa_s->Nasue, 32);

	if (waigroup_cert_2_3_send(wpa_s, payload, len))
	{
		iwn_wpa_printf(MSG_DEBUG, "WPA: in %s:%d", __func__, __LINE__);
		return -1;
	}
	return 0;
}
Example #15
0
File: net.c Project: zabbix/zabbix
static int	dns_query(AGENT_REQUEST *request, AGENT_RESULT *result, int short_answer)
{
#if defined(HAVE_RES_QUERY) || defined(_WINDOWS)

	size_t			offset = 0;
	int			res, type, retrans, retry, use_tcp, i, ret = SYSINFO_RET_FAIL, ip_type = AF_INET;
	char			*ip, zone[MAX_STRING_LEN], buffer[MAX_STRING_LEN], *zone_str, *param,
				tmp[MAX_STRING_LEN];
	struct in_addr		inaddr;
	struct in6_addr		in6addr;
#ifndef _WINDOWS
#if defined(HAVE_RES_NINIT) && !defined(_AIX)
	/* It seems that on some AIX systems with no updates installed res_ninit() can */
	/* corrupt stack (see ZBX-14559). Use res_init() on AIX. */
	struct __res_state	res_state_local;
#else	/* thread-unsafe resolver API */
	int			saved_retrans, saved_retry, saved_nscount = 0;
	unsigned long		saved_options;
	struct sockaddr_in	saved_ns;
#	if defined(HAVE_RES_U_EXT)		/* thread-unsafe resolver API /Linux/ */
	int			save_nssocks, saved_nscount6;
#	endif
#endif

#if defined(HAVE_RES_EXT_EXT)		/* AIX */
	union res_sockaddr_union	saved_ns6;
#elif defined(HAVE_RES_U_EXT_EXT)	/* BSD */
	struct sockaddr_in6		saved_ns6;
#else
	struct sockaddr_in6		*saved_ns6;
#endif
	struct sockaddr_in6	sockaddrin6;
	struct addrinfo		hint, *hres = NULL;
#endif
	typedef struct
	{
		const char	*name;
		int		type;
	}
	resolv_querytype_t;

	static const resolv_querytype_t	qt[] =
	{
		{"ANY",		T_ANY},
		{"A",		T_A},
		{"AAAA",	T_AAAA},
		{"NS",		T_NS},
		{"MD",		T_MD},
		{"MF",		T_MF},
		{"CNAME",	T_CNAME},
		{"SOA",		T_SOA},
		{"MB",		T_MB},
		{"MG",		T_MG},
		{"MR",		T_MR},
		{"NULL",	T_NULL},
#ifndef _WINDOWS
		{"WKS",		T_WKS},
#endif
		{"PTR",		T_PTR},
		{"HINFO",	T_HINFO},
		{"MINFO",	T_MINFO},
		{"MX",		T_MX},
		{"TXT",		T_TXT},
		{"SRV",		T_SRV},
		{NULL}
	};

#ifdef _WINDOWS
	PDNS_RECORD	pQueryResults, pDnsRecord;
	wchar_t		*wzone;
	char		tmp2[MAX_STRING_LEN];
	DWORD		options;
#else
	char		*name;
	unsigned char	*msg_end, *msg_ptr, *p;
	int		num_answers, num_query, q_type, q_class, q_len, value, c, n;
	struct servent	*s;
	HEADER		*hp;
	struct protoent	*pr;
#if PACKETSZ > 1024
	unsigned char	buf[PACKETSZ];
#else
	unsigned char	buf[1024];
#endif

	typedef union
	{
		HEADER		h;
#if defined(NS_PACKETSZ)
		unsigned char	buffer[NS_PACKETSZ];
#elif defined(PACKETSZ)
		unsigned char	buffer[PACKETSZ];
#else
		unsigned char	buffer[512];
#endif
	}
	answer_t;

	answer_t	answer;
#endif	/* _WINDOWS */
	zbx_vector_str_t	answers;

	*buffer = '\0';

	if (6 < request->nparam)
	{
		SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
		return SYSINFO_RET_FAIL;
	}

	ip = get_rparam(request, 0);
	zone_str = get_rparam(request, 1);

#ifndef _WINDOWS
	memset(&hint, '\0', sizeof(hint));
	hint.ai_family = PF_UNSPEC;
	hint.ai_flags = AI_NUMERICHOST;

	if (NULL != ip && '\0' != *ip && 0 == getaddrinfo(ip, NULL, &hint, &hres) && AF_INET6 == hres->ai_family)
		ip_type = hres->ai_family;

	if (NULL != hres)
		freeaddrinfo(hres);
#endif
	if (NULL == zone_str || '\0' == *zone_str)
		strscpy(zone, "zabbix.com");
	else
		strscpy(zone, zone_str);

	param = get_rparam(request, 2);

	if (NULL == param || '\0' == *param)
		type = T_SOA;
	else
	{
		for (i = 0; NULL != qt[i].name; i++)
		{
			if (0 == strcasecmp(qt[i].name, param))
			{
				type = qt[i].type;
				break;
			}
		}

		if (NULL == qt[i].name)
		{
			SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid third parameter."));
			return SYSINFO_RET_FAIL;
		}
	}

	param = get_rparam(request, 3);

	if (NULL == param || '\0' == *param)
		retrans = 1;
	else if (SUCCEED != is_uint31(param, &retrans) || 0 == retrans)
	{
		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid fourth parameter."));
		return SYSINFO_RET_FAIL;
	}

	param = get_rparam(request, 4);

	if (NULL == param || '\0' == *param)
		retry = 2;
	else if (SUCCEED != is_uint31(param, &retry) || 0 == retry)
	{
		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid fifth parameter."));
		return SYSINFO_RET_FAIL;
	}

	param = get_rparam(request, 5);

	if (NULL == param || '\0' == *param || 0 == strcmp(param, "udp"))
		use_tcp = 0;
	else if (0 == strcmp(param, "tcp"))
		use_tcp = 1;
	else
	{
		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid sixth parameter."));
		return SYSINFO_RET_FAIL;
	}

#ifdef _WINDOWS
	options = DNS_QUERY_STANDARD | DNS_QUERY_BYPASS_CACHE;
	if (0 != use_tcp)
		options |= DNS_QUERY_USE_TCP_ONLY;

	wzone = zbx_utf8_to_unicode(zone);
	res = DnsQuery(wzone, type, options, NULL, &pQueryResults, NULL);
	zbx_free(wzone);

	if (1 == short_answer)
	{
		SET_UI64_RESULT(result, DNS_RCODE_NOERROR != res ? 0 : 1);
		ret = SYSINFO_RET_OK;
		goto clean_dns;
	}

	if (DNS_RCODE_NOERROR != res)
	{
		SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot perform DNS query: [%d]", res));
		return SYSINFO_RET_FAIL;
	}

	pDnsRecord = pQueryResults;
	zbx_vector_str_create(&answers);

	while (NULL != pDnsRecord)
	{
		if (DnsSectionAnswer != pDnsRecord->Flags.S.Section)
		{
			pDnsRecord = pDnsRecord->pNext;
			continue;
		}

		if (NULL == pDnsRecord->pName)
			goto clean;

		offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "%-20s",
				zbx_unicode_to_utf8_static(pDnsRecord->pName, tmp, sizeof(tmp)));
		offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %-8s",
				decode_type(pDnsRecord->wType));

		switch (pDnsRecord->wType)
		{
			case T_A:
				inaddr.s_addr = pDnsRecord->Data.A.IpAddress;
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s",
						inet_ntoa(inaddr));
				break;
			case T_AAAA:
				memcpy(&in6addr.s6_addr, &(pDnsRecord->Data.AAAA.Ip6Address), sizeof(in6addr.s6_addr));
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s",
						zbx_inet_ntop(AF_INET6, &in6addr, tmp, sizeof(tmp)));
				break;
			case T_NS:
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s",
						zbx_unicode_to_utf8_static(pDnsRecord->Data.NS.pNameHost, tmp, sizeof(tmp)));
				break;
			case T_MD:
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s",
						zbx_unicode_to_utf8_static(pDnsRecord->Data.MD.pNameHost, tmp, sizeof(tmp)));
				break;
			case T_MF:
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s",
						zbx_unicode_to_utf8_static(pDnsRecord->Data.MF.pNameHost, tmp, sizeof(tmp)));
				break;
			case T_CNAME:
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s",
						zbx_unicode_to_utf8_static(pDnsRecord->Data.CNAME.pNameHost, tmp, sizeof(tmp)));
				break;
			case T_SOA:
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s %s %lu %lu %lu %lu %lu",
						zbx_unicode_to_utf8_static(pDnsRecord->Data.SOA.pNamePrimaryServer, tmp, sizeof(tmp)),
						zbx_unicode_to_utf8_static(pDnsRecord->Data.SOA.pNameAdministrator, tmp2, sizeof(tmp2)),
						pDnsRecord->Data.SOA.dwSerialNo,
						pDnsRecord->Data.SOA.dwRefresh,
						pDnsRecord->Data.SOA.dwRetry,
						pDnsRecord->Data.SOA.dwExpire,
						pDnsRecord->Data.SOA.dwDefaultTtl);
				break;
			case T_MB:
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s",
						zbx_unicode_to_utf8_static(pDnsRecord->Data.MB.pNameHost, tmp, sizeof(tmp)));
				break;
			case T_MG:
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s",
						zbx_unicode_to_utf8_static(pDnsRecord->Data.MG.pNameHost, tmp, sizeof(tmp)));
				break;
			case T_MR:
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s",
						zbx_unicode_to_utf8_static(pDnsRecord->Data.MR.pNameHost, tmp, sizeof(tmp)));
				break;
			case T_NULL:
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " len:%lu",
						pDnsRecord->Data.Null.dwByteCount);
				break;
			case T_PTR:
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s",
						zbx_unicode_to_utf8_static(pDnsRecord->Data.PTR.pNameHost, tmp, sizeof(tmp)));
				break;
			case T_HINFO:
				for (i = 0; i < (int)(pDnsRecord->Data.HINFO.dwStringCount); i++)
					offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " \"%s\"",
							zbx_unicode_to_utf8_static(pDnsRecord->Data.HINFO.pStringArray[i], tmp, sizeof(tmp)));
				break;
			case T_MINFO:
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s %s",
						zbx_unicode_to_utf8_static(pDnsRecord->Data.MINFO.pNameMailbox, tmp, sizeof(tmp)),
						zbx_unicode_to_utf8_static(pDnsRecord->Data.MINFO.pNameErrorsMailbox, tmp2, sizeof(tmp2)));
				break;
			case T_MX:
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %hu %s",
						pDnsRecord->Data.MX.wPreference,
						zbx_unicode_to_utf8_static(pDnsRecord->Data.MX.pNameExchange, tmp, sizeof(tmp)));
				break;
			case T_TXT:
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " \"");

				for (i = 0; i < (int)(pDnsRecord->Data.TXT.dwStringCount); i++)
					offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "%s ",
							zbx_unicode_to_utf8_static(pDnsRecord->Data.TXT.pStringArray[i], tmp, sizeof(tmp)));

				if (0 < i)
					offset -= 1;	/* remove the trailing space */

				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "\"");

				break;
			case T_SRV:
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %hu %hu %hu %s",
						pDnsRecord->Data.SRV.wPriority,
						pDnsRecord->Data.SRV.wWeight,
						pDnsRecord->Data.SRV.wPort,
						zbx_unicode_to_utf8_static(pDnsRecord->Data.SRV.pNameTarget, tmp, sizeof(tmp)));
				break;
			default:
				break;
		}

		zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "\n");

		pDnsRecord = pDnsRecord->pNext;
		zbx_vector_str_append(&answers, zbx_strdup(NULL, buffer));
		offset = 0;
		*buffer = '\0';
	}
#else	/* not _WINDOWS */
#if defined(HAVE_RES_NINIT) && !defined(_AIX)
	memset(&res_state_local, 0, sizeof(res_state_local));
	if (-1 == res_ninit(&res_state_local))	/* initialize always, settings might have changed */
#else
	if (-1 == res_init())	/* initialize always, settings might have changed */
#endif
	{
		SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot initialize DNS subsystem: %s", zbx_strerror(errno)));
		return SYSINFO_RET_FAIL;
	}

#if defined(HAVE_RES_NINIT) && !defined(_AIX)
	if (-1 == (res = res_nmkquery(&res_state_local, QUERY, zone, C_IN, type, NULL, 0, NULL, buf, sizeof(buf))))
#else
	if (-1 == (res = res_mkquery(QUERY, zone, C_IN, type, NULL, 0, NULL, buf, sizeof(buf))))
#endif
	{
		SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot create DNS query: %s", zbx_strerror(errno)));
		return SYSINFO_RET_FAIL;
	}

	if (NULL != ip && '\0' != *ip && AF_INET == ip_type)
	{
		if (0 == inet_aton(ip, &inaddr))
		{
			SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid IP address."));
			return SYSINFO_RET_FAIL;
		}

#if defined(HAVE_RES_NINIT) && !defined(_AIX)
		res_state_local.nsaddr_list[0].sin_addr = inaddr;
		res_state_local.nsaddr_list[0].sin_family = AF_INET;
		res_state_local.nsaddr_list[0].sin_port = htons(ZBX_DEFAULT_DNS_PORT);
		res_state_local.nscount = 1;
#else	/* thread-unsafe resolver API */
		memcpy(&saved_ns, &(_res.nsaddr_list[0]), sizeof(struct sockaddr_in));
		saved_nscount = _res.nscount;

		_res.nsaddr_list[0].sin_addr = inaddr;
		_res.nsaddr_list[0].sin_family = AF_INET;
		_res.nsaddr_list[0].sin_port = htons(ZBX_DEFAULT_DNS_PORT);
		_res.nscount = 1;
#endif
	}
	else if (NULL != ip && '\0' != *ip && AF_INET6 == ip_type)
	{
		if (0 == inet_pton(ip_type, ip, &in6addr))
		{
			SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid IPv6 address."));
			return SYSINFO_RET_FAIL;
		}

		memset(&sockaddrin6, '\0', sizeof(sockaddrin6));
#if defined(HAVE_RES_SIN6_LEN)
		sockaddrin6.sin6_len = sizeof(sockaddrin6);
#endif
		sockaddrin6.sin6_family = AF_INET6;
		sockaddrin6.sin6_addr = in6addr;
		sockaddrin6.sin6_port = htons(ZBX_DEFAULT_DNS_PORT);
#if defined(HAVE_RES_NINIT) && !defined(_AIX) && (defined(HAVE_RES_U_EXT) || defined(HAVE_RES_U_EXT_EXT))
		memset(&res_state_local.nsaddr_list[0], '\0', sizeof(res_state_local.nsaddr_list[0]));
#		ifdef HAVE_RES_U_EXT			/* Linux */
		saved_ns6 = res_state_local._u._ext.nsaddrs[0];
		res_state_local._u._ext.nsaddrs[0] = &sockaddrin6;
		res_state_local._u._ext.nssocks[0] = -1;
		res_state_local._u._ext.nscount6 = 1;	/* CentOS */
#		elif HAVE_RES_U_EXT_EXT			/* BSD */
		if (NULL != res_state_local._u._ext.ext)
			memcpy(res_state_local._u._ext.ext, &sockaddrin6, sizeof(sockaddrin6));

		res_state_local.nsaddr_list[0].sin_port = htons(ZBX_DEFAULT_DNS_PORT);
#		endif
		res_state_local.nscount = 1;
#else
		memcpy(&saved_ns, &(_res.nsaddr_list[0]), sizeof(struct sockaddr_in));
		saved_nscount = _res.nscount;
#		if defined(HAVE_RES_U_EXT) || defined(HAVE_RES_U_EXT_EXT) || defined(HAVE_RES_EXT_EXT)
		memset(&_res.nsaddr_list[0], '\0', sizeof(_res.nsaddr_list[0]));
		_res.nscount = 1;
#		endif
#		if defined(HAVE_RES_U_EXT)		/* thread-unsafe resolver API /Linux/ */
		saved_nscount6 = _res._u._ext.nscount6;
		saved_ns6 = _res._u._ext.nsaddrs[0];
		save_nssocks = _res._u._ext.nssocks[0];
		_res._u._ext.nsaddrs[0] = &sockaddrin6;
		_res._u._ext.nssocks[0] = -1;
		_res._u._ext.nscount6 = 1;
#		elif defined(HAVE_RES_U_EXT_EXT)	/* thread-unsafe resolver API /BSD/ */
		memcpy(&saved_ns6, _res._u._ext.ext, sizeof(saved_ns6));
		_res.nsaddr_list[0].sin_port = htons(ZBX_DEFAULT_DNS_PORT);

		if (NULL != _res._u._ext.ext)
			memcpy(_res._u._ext.ext, &sockaddrin6, sizeof(sockaddrin6));
#		elif defined(HAVE_RES_EXT_EXT)		/* thread-unsafe resolver API /AIX/ */
		memcpy(&saved_ns6, &(_res._ext.ext.nsaddrs[0]), sizeof(saved_ns6));
		memcpy(&_res._ext.ext.nsaddrs[0], &sockaddrin6, sizeof(sockaddrin6));
#		endif /* #if defined(HAVE_RES_U_EXT) */
#endif /* #if defined(HAVE_RES_NINIT) && !defined(_AIX) && (defined(HAVE_RES_U_EXT) || defined(HAVE_RES_U_EXT_EXT)) */
	}

#if defined(HAVE_RES_NINIT) && !defined(_AIX) && (defined(HAVE_RES_U_EXT) || defined(HAVE_RES_U_EXT_EXT))
	if (0 != use_tcp)
		res_state_local.options |= RES_USEVC;

	res_state_local.retrans = retrans;
	res_state_local.retry = retry;

	res = res_nsend(&res_state_local, buf, res, answer.buffer, sizeof(answer.buffer));

#	ifdef HAVE_RES_U_EXT	/* Linux */
	if (NULL != ip && '\0' != *ip && AF_INET6 == ip_type)
		res_state_local._u._ext.nsaddrs[0] = saved_ns6;
#	endif
#	ifdef HAVE_RES_NDESTROY
	res_ndestroy(&res_state_local);
#	else
	res_nclose(&res_state_local);
#	endif
#else	/* thread-unsafe resolver API */
	saved_options = _res.options;
	saved_retrans = _res.retrans;
	saved_retry = _res.retry;

	if (0 != use_tcp)
		_res.options |= RES_USEVC;

	_res.retrans = retrans;
	_res.retry = retry;

	res = res_send(buf, res, answer.buffer, sizeof(answer.buffer));

	_res.options = saved_options;
	_res.retrans = saved_retrans;
	_res.retry = saved_retry;

	if (NULL != ip && '\0' != *ip)
	{
		if (AF_INET6 == ip_type)
		{
#			if defined(HAVE_RES_U_EXT)		/* Linux */
			_res._u._ext.nsaddrs[0] = saved_ns6;
			_res._u._ext.nssocks[0] = save_nssocks;
			_res._u._ext.nscount6 = saved_nscount6;
#			elif defined(HAVE_RES_U_EXT_EXT)	/* BSD */
			if (NULL != _res._u._ext.ext)
				memcpy(_res._u._ext.ext, &saved_ns6, sizeof(saved_ns6));
#			elif defined(HAVE_RES_EXT_EXT)		/* AIX */
			memcpy(&_res._ext.ext.nsaddrs[0], &saved_ns6, sizeof(saved_ns6));
#			endif
		}

		memcpy(&(_res.nsaddr_list[0]), &saved_ns, sizeof(struct sockaddr_in));
		_res.nscount = saved_nscount;
	}
#endif
	hp = (HEADER *)answer.buffer;

	if (1 == short_answer)
	{
		SET_UI64_RESULT(result, NOERROR != hp->rcode || 0 == ntohs(hp->ancount) || -1 == res ? 0 : 1);
		return SYSINFO_RET_OK;
	}

	if (NOERROR != hp->rcode || 0 == ntohs(hp->ancount) || -1 == res)
	{
		SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot perform DNS query."));
		return SYSINFO_RET_FAIL;
	}

	msg_end = answer.buffer + res;

	num_answers = ntohs(answer.h.ancount);
	num_query = ntohs(answer.h.qdcount);

	msg_ptr = answer.buffer + HFIXEDSZ;
	zbx_vector_str_create(&answers);

	/* skipping query records */
	for (; 0 < num_query && msg_ptr < msg_end; num_query--)
		msg_ptr += dn_skipname(msg_ptr, msg_end) + QFIXEDSZ;

	for (; 0 < num_answers && msg_ptr < msg_end; num_answers--)
	{
		if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr)))
		{
			SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response."));
			ret = SYSINFO_RET_FAIL;
			goto clean;
		}

		offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "%-20s", name);

		GETSHORT(q_type, msg_ptr);
		GETSHORT(q_class, msg_ptr);
		msg_ptr += INT32SZ;		/* skipping TTL */
		GETSHORT(q_len, msg_ptr);
		offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %-8s", decode_type(q_type));

		switch (q_type)
		{
			case T_A:
				switch (q_class)
				{
					case C_IN:
					case C_HS:
						memcpy(&inaddr, msg_ptr, INADDRSZ);
						offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s",
								inet_ntoa(inaddr));
						break;
					default:
						;
				}

				msg_ptr += q_len;

				break;
			case T_AAAA:
				switch (q_class)
				{
					case C_IN:
					case C_HS:
						memcpy(&in6addr, msg_ptr, IN6ADDRSZ);
						offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s",
								inet_ntop(AF_INET6, &in6addr, tmp, sizeof(tmp)));
						break;
					default:
						;
				}

				msg_ptr += q_len;

				break;
			case T_NS:
			case T_CNAME:
			case T_MB:
			case T_MD:
			case T_MF:
			case T_MG:
			case T_MR:
			case T_PTR:
				if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr)))
				{
					SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response."));
					return SYSINFO_RET_FAIL;
				}
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name);
				break;
			case T_MX:
				GETSHORT(value, msg_ptr);	/* preference */
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value);

				if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr)))	/* exchange */
				{
					SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response."));
					return SYSINFO_RET_FAIL;
				}
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name);

				break;
			case T_SOA:
				if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr)))	/* source host */
				{
					SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response."));
					return SYSINFO_RET_FAIL;
				}
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name);

				if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr)))	/* administrator */
				{
					SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response."));
					return SYSINFO_RET_FAIL;
				}
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name);

				GETLONG(value, msg_ptr);	/* serial number */
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value);

				GETLONG(value, msg_ptr);	/* refresh time */
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value);

				GETLONG(value, msg_ptr);	/* retry time */
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value);

				GETLONG(value, msg_ptr);	/* expire time */
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value);

				GETLONG(value, msg_ptr);	/* minimum TTL */
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value);

				break;
			case T_NULL:
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " len:%d", q_len);
				msg_ptr += q_len;
				break;
			case T_WKS:
				if (INT32SZ + 1 > q_len)
				{
					SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response."));
					return SYSINFO_RET_FAIL;
				}

				p = msg_ptr + q_len;

				memcpy(&inaddr, msg_ptr, INADDRSZ);
				msg_ptr += INT32SZ;

				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", inet_ntoa(inaddr));

				if (NULL != (pr = getprotobynumber(*msg_ptr)))
					offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", pr->p_name);
				else
					offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", (int)*msg_ptr);

				msg_ptr++;
				n = 0;

				while (msg_ptr < p)
				{
					c = *msg_ptr++;

					do
					{
						if (0 != (c & 0200))
						{
							s = getservbyport((int)htons(n), pr ? pr->p_name : NULL);

							if (NULL != s)
								offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", s->s_name);
							else
								offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " #%d", n);
						}

						c <<= 1;
					}
					while (0 != (++n & 07));
				}

				break;
			case T_HINFO:
				p = msg_ptr + q_len;
				c = *msg_ptr++;

				if (0 != c)
				{
					offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " \"%.*s\"", c, msg_ptr);
					msg_ptr += c;
				}

				if (msg_ptr < p)
				{
					c = *msg_ptr++;

					if (0 != c)
					{
						offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " \"%.*s\"", c, msg_ptr);
						msg_ptr += c;
					}
				}

				break;
			case T_MINFO:
				if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr)))	/* mailbox responsible for mailing lists */
				{
					SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response."));
					return SYSINFO_RET_FAIL;
				}
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name);

				if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr)))	/* mailbox for error messages */
				{
					SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response."));
					return SYSINFO_RET_FAIL;
				}
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name);

				break;
			case T_TXT:
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " \"");
				p = msg_ptr + q_len;

				while (msg_ptr < p)
				{
					for (c = *msg_ptr++; 0 < c && msg_ptr < p; c--)
						offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "%c", *msg_ptr++);
				}

				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "\"");

				break;
			case T_SRV:
				GETSHORT(value, msg_ptr);       /* priority */
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value);

				GETSHORT(value, msg_ptr);       /* weight */
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value);

				GETSHORT(value, msg_ptr);       /* port */
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value);

				if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr)))	/* target */
				{
					SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response."));
					return SYSINFO_RET_FAIL;
				}
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name);

				break;
			default:
				msg_ptr += q_len;
				break;
		}

		zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "\n");

		zbx_vector_str_append(&answers, zbx_strdup(NULL, buffer));
		offset = 0;
		*buffer = '\0';
	}
#endif	/* _WINDOWS */

	zbx_vector_str_sort(&answers, ZBX_DEFAULT_STR_COMPARE_FUNC);

	for (i = 0; i < answers.values_num; i++)
		offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "%s", answers.values[i]);

	if (0 != offset)
		buffer[--offset] = '\0';

	SET_TEXT_RESULT(result, zbx_strdup(NULL, buffer));
	ret = SYSINFO_RET_OK;

clean:
	zbx_vector_str_clear_ext(&answers, zbx_str_free);
	zbx_vector_str_destroy(&answers);
#ifdef _WINDOWS
clean_dns:
	if (DNS_RCODE_NOERROR == res)
		DnsRecordListFree(pQueryResults, DnsFreeRecordList);
#endif

	return ret;

#else	/* both HAVE_RES_QUERY and _WINDOWS not defined */

	return SYSINFO_RET_FAIL;

#endif	/* defined(HAVE_RES_QUERY) || defined(_WINDOWS) */
}
Example #16
0
/* Modified version of req_action */
static enum req_action
req_iquery(HEADER *hp, u_char **cpp, u_char *eom, int *buflenp, u_char *msg)
{
	int dlen, alen, n, type, class, count;
	char anbuf[2], *data, *fname;

	/*
	 * Skip domain name, get class, and type.
	 */
	if ((n = dn_skipname(*cpp, eom)) < 0) {
	  printf("FORMERR IQuery packet name problem\n");
	  hp->rcode = FORMERR;
	  return (Finish);
	}
	*cpp += n;
	GETSHORT(type, *cpp);
	GETSHORT(class, *cpp);
	*cpp += INT32SZ;	/* ttl */
	GETSHORT(dlen, *cpp);
	*cpp += dlen;
	if (*cpp != eom) {
	  printf("FORMERR IQuery message length off\n");
	  hp->rcode = FORMERR;
	  return (Finish);
	}

	/*
	 * not all inverse queries are handled.
	 * this is a meaningless switch statement to preserve original program's structure 
	 */

	switch (type) {
	case T_A:
	  if (something == 0) 
	    return (Refuse);
	  break;
	default:
	  return (Refuse);
	}
	printf("req: IQuery class %d type %d\n", class, type);

	fname = (char *)msg + HFIXEDSZ;
	alen = (char *)*cpp - fname;
	
	

	/* Check to see if anbuf is large enough to store alen bytes*/
	if ((size_t)alen > sizeof anbuf){
	  printf("BUFFER OVERFLOW DETECTED!\n");
	  return (Refuse);
	}
	printf("Copying %d bytes from fname to anbuf which can store %d bytes\n", alen, sizeof(anbuf)); 

	/*OK*/
	memcpy(anbuf, fname, alen);
	data = anbuf + alen - dlen;
	*cpp = (u_char *)fname;
	*buflenp -= HFIXEDSZ;
	count = 0;


	/* ..... do some other stuff */

	return (Finish);
}
Example #17
0
int main(int argc, char *argv[]) {
    asyncns_t* asyncns = NULL;
    asyncns_query_t *q1, *q2, *q3;
    int r = 1, ret;
    struct addrinfo *ai, hints;
    struct sockaddr_in sa;
    char host[NI_MAXHOST] = "", serv[NI_MAXSERV] = "";
    unsigned char *srv;

    signal(SIGCHLD, SIG_IGN);

    if (!(asyncns = asyncns_new(2))) {
        fprintf(stderr, "asyncns_new() failed\n");
        goto fail;
    }

    /* Make a name -> address query */
    memset(&hints, 0, sizeof(hints));
    hints.ai_family = PF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;

    q1 = asyncns_getaddrinfo(asyncns, argc >= 2 ? argv[1] : "www.heise.de", NULL, &hints);

    if (!q1)
        fprintf(stderr, "asyncns_getaddrinfo(): %s\n", strerror(errno));

    /* Make an address -> name query */
    memset(&sa, 0, sizeof(sa));
    sa.sin_family = AF_INET;
    sa.sin_addr.s_addr = inet_addr(argc >= 3 ? argv[2] : "193.99.144.71");
    sa.sin_port = htons(80);

    q2 = asyncns_getnameinfo(asyncns, (struct sockaddr*) &sa, sizeof(sa), 0, 1, 1);

    if (!q2)
        fprintf(stderr, "asyncns_getnameinfo(): %s\n", strerror(errno));

    /* Make a res_query() call */
    q3 = asyncns_res_query(asyncns, "_xmpp-client._tcp.gmail.com", C_IN, T_SRV);

    if (!q3)
        fprintf(stderr, "asyncns_res_query(): %s\n", strerror(errno));

    /* Wait until the three queries are completed */
    while (!asyncns_isdone(asyncns, q1)
           || !asyncns_isdone(asyncns, q2)
           || !asyncns_isdone(asyncns, q3)) {
        if (asyncns_wait(asyncns, 1) < 0) {
            fprintf(stderr, "asyncns_wait(): %s\n", strerror(errno));
            goto fail;
        }
    }

    /* Interpret the result of the name -> addr query */
    if ((ret = asyncns_getaddrinfo_done(asyncns, q1, &ai)))
        fprintf(stderr, "error: %s %i\n", gai_strerror(ret), ret);
    else {
        struct addrinfo *i;

        for (i = ai; i; i = i->ai_next) {
            char t[256];
            const char *p = NULL;

            if (i->ai_family == PF_INET)
                p = inet_ntop(AF_INET, &((struct sockaddr_in*) i->ai_addr)->sin_addr, t, sizeof(t));
            else if (i->ai_family == PF_INET6)
                p = inet_ntop(AF_INET6, &((struct sockaddr_in6*) i->ai_addr)->sin6_addr, t, sizeof(t));

            printf("%s\n", p);
        }

        asyncns_freeaddrinfo(ai);
    }

    /* Interpret the result of the addr -> name query */
    if ((ret = asyncns_getnameinfo_done(asyncns, q2, host, sizeof(host), serv, sizeof(serv))))
        fprintf(stderr, "error: %s %i\n", gai_strerror(ret), ret);
    else
        printf("%s -- %s\n", host, serv);

    /* Interpret the result of the SRV lookup */
    if ((ret = asyncns_res_done(asyncns, q3, &srv)) < 0) {
        fprintf(stderr, "error: %s %i\n", strerror(errno), ret);
    } else if (ret == 0) {
        fprintf(stderr, "No reply for SRV lookup\n");
    } else {
        int qdcount;
        int ancount;
        int len;
        const unsigned char *pos = srv + sizeof(HEADER);
        unsigned char *end = srv + ret;
        HEADER *head = (HEADER *)srv;
        char name[256];

        qdcount = ntohs(head->qdcount);
        ancount = ntohs(head->ancount);

        printf("%d answers for srv lookup:\n", ancount);

        /* Ignore the questions */
        while (qdcount-- > 0 && (len = dn_expand(srv, end, pos, name, 255)) >= 0) {
            assert(len >= 0);
            pos += len + QFIXEDSZ;
        }

        /* Parse the answers */
        while (ancount-- > 0 && (len = dn_expand(srv, end, pos, name, 255)) >= 0) {
            /* Ignore the initial string */
            uint16_t pref, weight, port;
            assert(len >= 0);
            pos += len;
            /* Ignore type, ttl, class and dlen */
            pos += 10;

            GETSHORT(pref, pos);
            GETSHORT(weight, pos);
            GETSHORT(port, pos);
            len = dn_expand(srv, end, pos, name, 255);
            printf("\tpreference: %2d weight: %2d port: %d host: %s\n",
                   pref, weight, port, name);

            pos += len;
        }

        asyncns_freeanswer(srv);
    }

    r = 0;

fail:

    if (asyncns)
        asyncns_free(asyncns);

    return r;
}
Example #18
0
File: asn.c Project: RichiH/mtr
char *ipinfo_lookup(const char *domain) {
    unsigned char answer[PACKETSZ],  *pt;
    char host[128];
    char *txt;
    int len, exp, size, txtlen, type;


    if(res_init() < 0) {
        fprintf(stderr,"@res_init failed\n");
        return NULL;
    }

    memset(answer, 0, PACKETSZ);
    if((len = res_query(domain, C_IN, T_TXT, answer, PACKETSZ)) < 0) {
#ifdef IIDEBUG
        if (iihash)
            syslog(LOG_INFO, "Malloc-txt: %s", UNKN);
#endif
        return (iihash)?strdup(UNKN):UNKN;
    }

    pt = answer + sizeof(HEADER);

    if((exp = dn_expand(answer, answer + len, pt, host, sizeof(host))) < 0) {
        printf("@dn_expand failed\n"); return NULL;
    }

    pt += exp;

    GETSHORT(type, pt);
    if(type != T_TXT) {
        printf("@Broken DNS reply.\n"); return NULL;
    }

    pt += INT16SZ; /* class */

    if((exp = dn_expand(answer, answer + len, pt, host, sizeof(host))) < 0) {
        printf("@second dn_expand failed\n"); return NULL;
    }

    pt += exp;
    GETSHORT(type, pt);
    if(type != T_TXT) {
        printf("@Not a TXT record\n"); return NULL;
    }

    pt += INT16SZ; /* class */
    pt += INT32SZ; /* ttl */
    GETSHORT(size, pt);
    txtlen = *pt;


    if(txtlen >= size || !txtlen) {
        printf("@Broken TXT record (txtlen = %d, size = %d)\n", txtlen, size); return NULL;
    }

    if (txtlen > NAMELEN)
        txtlen = NAMELEN;

    if (iihash) {
        if (!(txt = malloc(txtlen + 1)))
            return NULL;
    } else
        txt = (char*)txtrec;

    pt++;
    strncpy(txt, (char*) pt, txtlen);
    txt[txtlen] = 0;

#ifdef IIDEBUG
    if (iihash)
        syslog(LOG_INFO, "Malloc-txt(%p): %s", txt, txt);
#endif

    return txt;
}
Example #19
0
static void
do_section(const res_state statp,
	   ns_msg *handle, ns_sect section,
	   int pflag, FILE *file)
{
	int n, sflag, rrnum;
	static int buflen = 2048;
	char *buf;
	ns_opcode opcode;
	ns_rr rr;

	/*
	 * Print answer records.
	 */
	sflag = (statp->pfcode & pflag);
	if (statp->pfcode && !sflag)
		return;

	buf = malloc(buflen);
	if (buf == NULL) {
		fprintf(file, ";; memory allocation failure\n");
		return;
	}

	opcode = (ns_opcode) ns_msg_getflag(*handle, ns_f_opcode);
	rrnum = 0;
	for (;;) {
		if (ns_parserr(handle, section, rrnum, &rr)) {
			if (errno != ENODEV)
				fprintf(file, ";; ns_parserr: %s\n",
					strerror(errno));
			else if (rrnum > 0 && sflag != 0 &&
				 (statp->pfcode & RES_PRF_HEAD1))
				putc('\n', file);
			goto cleanup;
		}
		if (rrnum == 0 && sflag != 0 && (statp->pfcode & RES_PRF_HEAD1))
			fprintf(file, ";; %s SECTION:\n",
				p_section(section, opcode));
		if (section == ns_s_qd)
			fprintf(file, ";;\t%s, type = %s, class = %s\n",
				ns_rr_name(rr),
				p_type(ns_rr_type(rr)),
				p_class(ns_rr_class(rr)));
		else if (section == ns_s_ar && ns_rr_type(rr) == ns_t_opt) {
			u_int16_t optcode, optlen, rdatalen = ns_rr_rdlen(rr);
			u_int32_t ttl = ns_rr_ttl(rr);

			fprintf(file,
				"; EDNS: version: %u, udp=%u, flags=%04x\n",
				(ttl>>16)&0xff, ns_rr_class(rr), ttl&0xffff);

			while (rdatalen >= 4) {
				const u_char *cp = ns_rr_rdata(rr);
				int i;

				GETSHORT(optcode, cp);
				GETSHORT(optlen, cp);

				if (optcode == NS_OPT_NSID) {
					fputs("; NSID: ", file);
					if (optlen == 0) {
						fputs("; NSID\n", file);
					} else {
						fputs("; NSID: ", file);
						for (i = 0; i < optlen; i++)
							fprintf(file, "%02x ",
								cp[i]);
						fputs(" (",file);
						for (i = 0; i < optlen; i++)
							fprintf(file, "%c",
								isprint(cp[i])?
								cp[i] : '.');
						fputs(")\n", file);
					}
				} else {
					if (optlen == 0) {
						fprintf(file, "; OPT=%u\n",
							optcode);
					} else {
						fprintf(file, "; OPT=%u: ",
							optcode);
						for (i = 0; i < optlen; i++)
							fprintf(file, "%02x ",
								cp[i]);
						fputs(" (",file);
						for (i = 0; i < optlen; i++)
							fprintf(file, "%c",
								isprint(cp[i]) ?
									cp[i] : '.');
						fputs(")\n", file);
					}
				}
				rdatalen -= 4 + optlen;
			}
		} else {
Example #20
0
static GList *
g_resolver_records_from_res_query (const gchar      *rrname,
                                   gint              rrtype,
                                   guchar           *answer,
                                   gint              len,
                                   gint              herr,
                                   GError          **error)
{
  gint count;
  gchar namebuf[1024];
  guchar *end, *p;
  guint16 type, qclass, rdlength;
  guint32 ttl;
  HEADER *header;
  GList *records;
  GVariant *record;

  if (len <= 0)
    {
      if (len == 0 || herr == HOST_NOT_FOUND || herr == NO_DATA)
        {
          g_set_error (error, G_RESOLVER_ERROR, G_RESOLVER_ERROR_NOT_FOUND,
                       _("No DNS record of the requested type for “%s”"), rrname);
        }
      else if (herr == TRY_AGAIN)
        {
          g_set_error (error, G_RESOLVER_ERROR, G_RESOLVER_ERROR_TEMPORARY_FAILURE,
                       _("Temporarily unable to resolve “%s”"), rrname);
        }
      else
        {
          g_set_error (error, G_RESOLVER_ERROR, G_RESOLVER_ERROR_INTERNAL,
                       _("Error resolving “%s”"), rrname);
        }

      return NULL;
    }

  records = NULL;

  header = (HEADER *)answer;
  p = answer + sizeof (HEADER);
  end = answer + len;

  /* Skip query */
  count = ntohs (header->qdcount);
  while (count-- && p < end)
    {
      p += dn_expand (answer, end, p, namebuf, sizeof (namebuf));
      p += 4;

      /* To silence gcc warnings */
      namebuf[0] = namebuf[1];
    }

  /* Read answers */
  count = ntohs (header->ancount);
  while (count-- && p < end)
    {
      p += dn_expand (answer, end, p, namebuf, sizeof (namebuf));
      GETSHORT (type, p);
      GETSHORT (qclass, p);
      GETLONG  (ttl, p);
      ttl = ttl; /* To avoid -Wunused-but-set-variable */
      GETSHORT (rdlength, p);

      if (type != rrtype || qclass != C_IN)
        {
          p += rdlength;
          continue;
        }

      switch (rrtype)
        {
        case T_SRV:
          record = parse_res_srv (answer, end, &p);
          break;
        case T_MX:
          record = parse_res_mx (answer, end, &p);
          break;
        case T_SOA:
          record = parse_res_soa (answer, end, &p);
          break;
        case T_NS:
          record = parse_res_ns (answer, end, &p);
          break;
        case T_TXT:
          record = parse_res_txt (answer, p + rdlength, &p);
          break;
        default:
          g_warn_if_reached ();
          record = NULL;
          break;
        }

      if (record != NULL)
        records = g_list_prepend (records, record);
    }

  if (records == NULL)
    {
      g_set_error (error, G_RESOLVER_ERROR, G_RESOLVER_ERROR_NOT_FOUND,
                   _("No DNS record of the requested type for “%s”"), rrname);

      return NULL;
    }
  else
    return records;
}
Example #21
0
/*
 * fsm_input - Input packet.
 */
void
fsm_input(fsm *f, u_char *inpacket, int l)
{
  u_char *inp = inpacket;
  u_char code, id;
  int len;

  /*
  * Parse header (code, id and length).
  * If packet too short, drop it.
  */
  if (l < HEADERLEN) {
    FSMDEBUG((LOG_WARNING, "fsm_input(%x): Rcvd short header.\n",
          f->protocol));
    return;
  }
  GETCHAR(code, inp);
  GETCHAR(id, inp);
  GETSHORT(len, inp);
  if (len < HEADERLEN) {
    FSMDEBUG((LOG_INFO, "fsm_input(%x): Rcvd illegal length.\n",
        f->protocol));
    return;
  }
  if (len > l) {
    FSMDEBUG((LOG_INFO, "fsm_input(%x): Rcvd short packet.\n",
        f->protocol));
    return;
  }
  len -= HEADERLEN;    /* subtract header length */

  if( f->state == LS_INITIAL || f->state == LS_STARTING ) {
    FSMDEBUG((LOG_INFO, "fsm_input(%x): Rcvd packet in state %d (%s).\n",
        f->protocol, f->state, ppperr_strerr[f->state]));
    return;
  }
  FSMDEBUG((LOG_INFO, "fsm_input(%s):%d,%d,%d\n", PROTO_NAME(f), code, id, l));
  /*
   * Action depends on code.
   */
  switch (code) {
    case CONFREQ:
      fsm_rconfreq(f, id, inp, len);
      break;
    
    case CONFACK:
      fsm_rconfack(f, id, inp, len);
      break;
    
    case CONFNAK:
    case CONFREJ:
      fsm_rconfnakrej(f, code, id, inp, len);
      break;
    
    case TERMREQ:
      fsm_rtermreq(f, id, inp, len);
      break;
    
    case TERMACK:
      fsm_rtermack(f);
      break;
    
    case CODEREJ:
      fsm_rcoderej(f, inp, len);
      break;
    
    default:
      if( !f->callbacks->extcode ||
          !(*f->callbacks->extcode)(f, code, id, inp, len) ) {
        fsm_sdata(f, CODEREJ, ++f->id, inpacket, len + HEADERLEN);
      }
      break;
  }
}
Example #22
0
/* ns_verify
 * Parameters:
 *	statp		res stuff
 *	msg		received message
 *	msglen		length of message
 *	key		tsig key used for verifying.
 *	querysig	(response), the signature in the query
 *	querysiglen	(response), the length of the signature in the query
 *	sig		(query), a buffer to hold the signature
 *	siglen		(query), input - length of signature buffer
 *				 output - length of signature
 *
 * Errors:
 *	- bad input (-1)
 *	- invalid dns message (NS_TSIG_ERROR_FORMERR)
 *	- TSIG is not present (NS_TSIG_ERROR_NO_TSIG)
 *	- key doesn't match (-ns_r_badkey)
 *	- TSIG verification fails with BADKEY (-ns_r_badkey)
 *	- TSIG verification fails with BADSIG (-ns_r_badsig)
 *	- TSIG verification fails with BADTIME (-ns_r_badtime)
 *	- TSIG verification succeeds, error set to BAKEY (ns_r_badkey)
 *	- TSIG verification succeeds, error set to BADSIG (ns_r_badsig)
 *	- TSIG verification succeeds, error set to BADTIME (ns_r_badtime)
 */
isc_result_t
ns_verify(u_char *msg, unsigned *msglen, void *k,
	  const u_char *querysig, unsigned querysiglen,
	  u_char *sig, unsigned *siglen, time_t *timesigned, int nostrip)
{
	HEADER *hp = (HEADER *)msg;
	DST_KEY *key = (DST_KEY *)k;
	u_char *cp = msg, *eom;
	char name[MAXDNAME], alg[MAXDNAME];
	u_char *recstart, *rdatastart;
	u_char *sigstart, *otherstart;
	unsigned n;
	int error;
	u_int16_t type, length;
	u_int16_t fudge, sigfieldlen, id, otherfieldlen;

	dst_init();
	if (msg == NULL || msglen == NULL || *msglen < 0)
		return ISC_R_INVALIDARG;

	eom = msg + *msglen;

	recstart = ns_find_tsig(msg, eom);
	if (recstart == NULL)
		return ISC_R_NO_TSIG;

	cp = recstart;

	/* Read the key name. */
	n = dn_expand(msg, eom, cp, name, MAXDNAME);
	if (n < 0)
		return ISC_R_FORMERR;
	cp += n;

	/* Read the type. */
	BOUNDS_CHECK(cp, 2*INT16SZ + INT32SZ + INT16SZ);
	GETSHORT(type, cp);
	if (type != ns_t_tsig)
		return ISC_R_NO_TSIG;

	/* Skip the class and TTL, save the length. */
	cp += INT16SZ + INT32SZ;
	GETSHORT(length, cp);
	if (eom - cp != length)
		return ISC_R_FORMERR;

	/* Read the algorithm name. */
	rdatastart = cp;
	n = dn_expand(msg, eom, cp, alg, MAXDNAME);
	if (n < 0)
		return ISC_R_FORMERR;
	if (ns_samename(alg, NS_TSIG_ALG_HMAC_MD5) != 1)
		return ISC_R_INVALIDKEY;
	cp += n;

	/* Read the time signed and fudge. */
	BOUNDS_CHECK(cp, INT16SZ + INT32SZ + INT16SZ);
	cp += INT16SZ;
	GETLONG((*timesigned), cp);
	GETSHORT(fudge, cp);

	/* Read the signature. */
	BOUNDS_CHECK(cp, INT16SZ);
	GETSHORT(sigfieldlen, cp);
	BOUNDS_CHECK(cp, sigfieldlen);
	sigstart = cp;
	cp += sigfieldlen;

	/* Read the original id and error. */
	BOUNDS_CHECK(cp, 2*INT16SZ);
	GETSHORT(id, cp);
	GETSHORT(error, cp);

	/* Parse the other data. */
	BOUNDS_CHECK(cp, INT16SZ);
	GETSHORT(otherfieldlen, cp);
	BOUNDS_CHECK(cp, otherfieldlen);
	otherstart = cp;
	cp += otherfieldlen;

	if (cp != eom)
		return ISC_R_FORMERR;

	/* Verify that the key used is OK. */
	if (key != NULL) {
		if (key->dk_alg != KEY_HMAC_MD5)
			return ISC_R_INVALIDKEY;
		if (error != ns_r_badsig && error != ns_r_badkey) {
			if (ns_samename(key->dk_key_name, name) != 1)
				return ISC_R_INVALIDKEY;
		}
	}

	hp->arcount = htons(ntohs(hp->arcount) - 1);

	/*
	 * Do the verification.
	 */

	if (key != NULL && error != ns_r_badsig && error != ns_r_badkey) {
		void *ctx;
		u_char buf[MAXDNAME];

		/* Digest the query signature, if this is a response. */
		dst_verify_data(SIG_MODE_INIT, key, &ctx, NULL, 0, NULL, 0);
		if (querysiglen > 0 && querysig != NULL) {
			u_int16_t len_n = htons(querysiglen);
			dst_verify_data(SIG_MODE_UPDATE, key, &ctx,
					(u_char *)&len_n, INT16SZ, NULL, 0);
			dst_verify_data(SIG_MODE_UPDATE, key, &ctx,
					querysig, querysiglen, NULL, 0);
		}
		
 		/* Digest the message. */
		dst_verify_data(SIG_MODE_UPDATE, key, &ctx, msg,
				(unsigned)(recstart - msg), NULL, 0);

		/* Digest the key name. */
		n = ns_name_ntol(recstart, buf, sizeof(buf));
		dst_verify_data(SIG_MODE_UPDATE, key, &ctx, buf, n, NULL, 0);

		/* Digest the class and TTL. */
		dst_verify_data(SIG_MODE_UPDATE, key, &ctx,
				recstart + dn_skipname(recstart, eom) + INT16SZ,
				INT16SZ + INT32SZ, NULL, 0);

		/* Digest the algorithm. */
		n = ns_name_ntol(rdatastart, buf, sizeof(buf));
		dst_verify_data(SIG_MODE_UPDATE, key, &ctx, buf, n, NULL, 0);

		/* Digest the time signed and fudge. */
		dst_verify_data(SIG_MODE_UPDATE, key, &ctx,
				rdatastart + dn_skipname(rdatastart, eom),
				INT16SZ + INT32SZ + INT16SZ, NULL, 0);

		/* Digest the error and other data. */
		dst_verify_data(SIG_MODE_UPDATE, key, &ctx,
				otherstart - INT16SZ - INT16SZ,
				(unsigned)otherfieldlen + INT16SZ + INT16SZ,
				NULL, 0);

		n = dst_verify_data(SIG_MODE_FINAL, key, &ctx, NULL, 0,
				    sigstart, sigfieldlen);

		if (n < 0)
			return ISC_R_BADSIG;

		if (sig != NULL && siglen != NULL) {
			if (*siglen < sigfieldlen)
				return ISC_R_NOSPACE;
			memcpy(sig, sigstart, sigfieldlen);
			*siglen = sigfieldlen;
		}
	} else {
		if (sigfieldlen > 0)
			return ISC_R_FORMERR;
		if (sig != NULL && siglen != NULL)
			*siglen = 0;
	}

	/* Reset the counter, since we still need to check for badtime. */
	hp->arcount = htons(ntohs(hp->arcount) + 1);

	/* Verify the time. */
	if (abs((*timesigned) - time(NULL)) > fudge)
		return ISC_R_BADTIME;

	if (nostrip == 0) {
		*msglen = recstart - msg;
		hp->arcount = htons(ntohs(hp->arcount) - 1);
	}

	if (error != NOERROR)
		return ns_rcode_to_isc (error);

	return ISC_R_SUCCESS;
}
Example #23
0
bool HHVM_FUNCTION(getmxrr, const String& hostname,
                   VRefParam mxhostsRef,
                   VRefParam weightsRef /* = null */) {
    IOStatusHelper io("dns_get_mx", hostname.data());
    int count, qdc;
    unsigned short type, weight;
    unsigned char ans[MAXPACKET];
    char buf[255 + 1];  // IETF STD 13 section 3.1; 255 bytes
    unsigned char *cp, *end;

    Array mxhosts;
    Array weights;
    SCOPE_EXIT {
        mxhostsRef.assignIfRef(mxhosts);
        weightsRef.assignIfRef(weights);
    };

    /* Go! */
    struct __res_state *res;
    res = ResolverInit::s_res.get()->getResolver();
    if (res == NULL) {
        return false;
    }

    int i = res_nsearch(res, hostname.data(), C_IN, DNS_T_MX,
                        (unsigned char*)&ans, sizeof(ans));
    if (i < 0) {
        res_nclose(res);
        php_dns_free_res(res);
        return false;
    }
    if (i > (int)sizeof(ans)) {
        i = sizeof(ans);
    }
    HEADER *hp = (HEADER *)&ans;
    cp = (unsigned char *)&ans + HFIXEDSZ;
    end = (unsigned char *)&ans +i;
    for (qdc = ntohs((unsigned short)hp->qdcount); qdc--; cp += i + QFIXEDSZ) {
        if ((i = dn_skipname(cp, end)) < 0 ) {
            res_nclose(res);
            php_dns_free_res(res);
            return false;
        }
    }
    count = ntohs((unsigned short)hp->ancount);
    while (--count >= 0 && cp < end) {
        if ((i = dn_skipname(cp, end)) < 0 ) {
            res_nclose(res);
            php_dns_free_res(res);
            return false;
        }
        cp += i;
        GETSHORT(type, cp);
        cp += INT16SZ + INT32SZ;
        GETSHORT(i, cp);
        if (type != DNS_T_MX) {
            cp += i;
            continue;
        }
        GETSHORT(weight, cp);
        if ((i = dn_expand(ans, end, cp, buf, sizeof(buf)-1)) < 0) {
            res_nclose(res);
            php_dns_free_res(res);
            return false;
        }
        cp += i;
        mxhosts.append(String(buf, CopyString));
        weights.append(weight);
    }
    res_nclose(res);
    php_dns_free_res(res);
    return true;
}
Example #24
0
isc_result_t
ns_verify_tcp(u_char *msg, unsigned *msglen, ns_tcp_tsig_state *state,
	      int required)
{
	HEADER *hp = (HEADER *)msg;
	u_char *recstart, *rdatastart, *sigstart;
	unsigned sigfieldlen, otherfieldlen;
	u_char *cp, *eom = msg + *msglen, *cp2;
	char name[MAXDNAME], alg[MAXDNAME];
	u_char buf[MAXDNAME];
	int n, type, length, fudge, id, error;
	time_t timesigned;

	if (msg == NULL || msglen == NULL || state == NULL)
		return ISC_R_INVALIDARG;

	state->counter++;
	if (state->counter == 0)
		return (ns_verify(msg, msglen, state->key,
				  state->sig, state->siglen,
				  state->sig, &state->siglen, &timesigned, 0));

	if (state->siglen > 0) {
		u_int16_t siglen_n = htons(state->siglen);

		dst_verify_data(SIG_MODE_INIT, state->key, &state->ctx,
				NULL, 0, NULL, 0);
		dst_verify_data(SIG_MODE_UPDATE, state->key, &state->ctx,
				(u_char *)&siglen_n, INT16SZ, NULL, 0);
		dst_verify_data(SIG_MODE_UPDATE, state->key, &state->ctx,
				state->sig, state->siglen, NULL, 0);
		state->siglen = 0;
	}

	cp = recstart = ns_find_tsig(msg, eom);

	if (recstart == NULL) {
		if (required)
			return ISC_R_NO_TSIG;
		dst_verify_data(SIG_MODE_UPDATE, state->key, &state->ctx,
				msg, *msglen, NULL, 0);
		return ISC_R_SUCCESS;
	}

	hp->arcount = htons(ntohs(hp->arcount) - 1);
	dst_verify_data(SIG_MODE_UPDATE, state->key, &state->ctx,
			msg, (unsigned)(recstart - msg), NULL, 0);
	
	/* Read the key name. */
	n = dn_expand(msg, eom, cp, name, MAXDNAME);
	if (n < 0)
		return ISC_R_FORMERR;
	cp += n;

	/* Read the type. */
	BOUNDS_CHECK(cp, 2*INT16SZ + INT32SZ + INT16SZ);
	GETSHORT(type, cp);
	if (type != ns_t_tsig)
		return ISC_R_NO_TSIG;

	/* Skip the class and TTL, save the length. */
	cp += INT16SZ + INT32SZ;
	GETSHORT(length, cp);
	if (eom - cp != length)
		return ISC_R_FORMERR;

	/* Read the algorithm name. */
	rdatastart = cp;
	n = dn_expand(msg, eom, cp, alg, MAXDNAME);
	if (n < 0)
		return ISC_R_FORMERR;
	if (ns_samename(alg, NS_TSIG_ALG_HMAC_MD5) != 1)
		return ISC_R_BADKEY;
	cp += n;

	/* Verify that the key used is OK. */
	if ((ns_samename(state->key->dk_key_name, name) != 1 ||
	     state->key->dk_alg != KEY_HMAC_MD5))
		return ISC_R_BADKEY;

	/* Read the time signed and fudge. */
	BOUNDS_CHECK(cp, INT16SZ + INT32SZ + INT16SZ);
	cp += INT16SZ;
	GETLONG(timesigned, cp);
	GETSHORT(fudge, cp);

	/* Read the signature. */
	BOUNDS_CHECK(cp, INT16SZ);
	GETSHORT(sigfieldlen, cp);
	BOUNDS_CHECK(cp, sigfieldlen);
	sigstart = cp;
	cp += sigfieldlen;

	/* Read the original id and error. */
	BOUNDS_CHECK(cp, 2*INT16SZ);
	GETSHORT(id, cp);
	GETSHORT(error, cp);

	/* Parse the other data. */
	BOUNDS_CHECK(cp, INT16SZ);
	GETSHORT(otherfieldlen, cp);
	BOUNDS_CHECK(cp, otherfieldlen);
	cp += otherfieldlen;

	if (cp != eom)
		return ISC_R_FORMERR;

	/*
	 * Do the verification.
	 */

	/* Digest the time signed and fudge. */
	cp2 = buf;
	PUTSHORT(0, cp2);       /* Top 16 bits of time. */
	PUTLONG(timesigned, cp2);
	PUTSHORT(NS_TSIG_FUDGE, cp2);

	dst_verify_data(SIG_MODE_UPDATE, state->key, &state->ctx,
			buf, (unsigned)(cp2 - buf), NULL, 0);

	n = dst_verify_data(SIG_MODE_FINAL, state->key, &state->ctx, NULL, 0,
			    sigstart, sigfieldlen);
	if (n < 0)
		return ISC_R_BADSIG;

	if (sigfieldlen > sizeof(state->sig))
		return ISC_R_BADSIG;

	if (sigfieldlen > sizeof(state->sig))
		return ISC_R_NOSPACE;

	memcpy(state->sig, sigstart, sigfieldlen);
	state->siglen = sigfieldlen;

	/* Verify the time. */
	if (abs(timesigned - time(NULL)) > fudge)
		return ISC_R_BADTIME;

	*msglen = recstart - msg;

	if (error != NOERROR)
		return ns_rcode_to_isc (error);

	return ISC_R_SUCCESS;
}
/*
 * fsm_input - Input packet.
 */
void fsm_input(fsm *f, u_char *inpacket, int l) {
    u_char *inp;
    u_char code, id;
    int len;

    /*
     * Parse header (code, id and length).
     * If packet too short, drop it.
     */
    inp = inpacket;
    if (l < HEADERLEN) {
	FSMDEBUG(("fsm_input(%x): Rcvd short header.", f->protocol));
	return;
    }
    GETCHAR(code, inp);
    GETCHAR(id, inp);
    GETSHORT(len, inp);
    if (len < HEADERLEN) {
	FSMDEBUG(("fsm_input(%x): Rcvd illegal length.", f->protocol));
	return;
    }
    if (len > l) {
	FSMDEBUG(("fsm_input(%x): Rcvd short packet.", f->protocol));
	return;
    }
    len -= HEADERLEN;		/* subtract header length */

    if( f->state == PPP_FSM_INITIAL || f->state == PPP_FSM_STARTING ){
	FSMDEBUG(("fsm_input(%x): Rcvd packet in state %d.",
		  f->protocol, f->state));
	return;
    }

    /*
     * Action depends on code.
     */
    switch (code) {
    case CONFREQ:
	fsm_rconfreq(f, id, inp, len);
	break;
    
    case CONFACK:
	fsm_rconfack(f, id, inp, len);
	break;
    
    case CONFNAK:
    case CONFREJ:
	fsm_rconfnakrej(f, code, id, inp, len);
	break;
    
    case TERMREQ:
	fsm_rtermreq(f, id, inp, len);
	break;
    
    case TERMACK:
	fsm_rtermack(f);
	break;
    
    case CODEREJ:
	fsm_rcoderej(f, inp, len);
	break;
    
    default:
	if( !f->callbacks->extcode
	   || !(*f->callbacks->extcode)(f, code, id, inp, len) )
	    fsm_sdata(f, CODEREJ, ++f->id, inpacket, len + HEADERLEN);
	break;
    }
}
Example #26
0
WORD _getshort (const BYTE *x)   /* in <arpa/nameserv.h> */
{
  WORD res;
  GETSHORT (res, x);
  return (res);
}
Example #27
0
File: dns.c Project: loganaden/exim
dns_record *
dns_next_rr(dns_answer *dnsa, dns_scan *dnss, int reset)
{
HEADER *h = (HEADER *)dnsa->answer;
int namelen;

/* Reset the saved data when requested to, and skip to the first required RR */

if (reset != RESET_NEXT)
  {
  dnss->rrcount = ntohs(h->qdcount);
  dnss->aptr = dnsa->answer + sizeof(HEADER);

  /* Skip over questions; failure to expand the name just gives up */

  while (dnss->rrcount-- > 0)
    {
    namelen = dn_expand(dnsa->answer, dnsa->answer + dnsa->answerlen,
      dnss->aptr, (DN_EXPAND_ARG4_TYPE) &(dnss->srr.name), DNS_MAXNAME);
    if (namelen < 0) { dnss->rrcount = 0; return NULL; }
    dnss->aptr += namelen + 4;    /* skip name & type & class */
    }

  /* Get the number of answer records. */

  dnss->rrcount = ntohs(h->ancount);

  /* Skip over answers if we want to look at the authority section. Also skip
  the NS records (i.e. authority section) if wanting to look at the additional
  records. */

  if (reset == RESET_ADDITIONAL) dnss->rrcount += ntohs(h->nscount);

  if (reset == RESET_AUTHORITY || reset == RESET_ADDITIONAL)
    {
    while (dnss->rrcount-- > 0)
      {
      namelen = dn_expand(dnsa->answer, dnsa->answer + dnsa->answerlen,
        dnss->aptr, (DN_EXPAND_ARG4_TYPE) &(dnss->srr.name), DNS_MAXNAME);
      if (namelen < 0) { dnss->rrcount = 0; return NULL; }
      dnss->aptr += namelen + 8;            /* skip name, type, class & TTL */
      GETSHORT(dnss->srr.size, dnss->aptr); /* size of data portion */
      dnss->aptr += dnss->srr.size;         /* skip over it */
      }
    dnss->rrcount = (reset == RESET_AUTHORITY)
      ? ntohs(h->nscount) : ntohs(h->arcount);
    }
  }

/* The variable dnss->aptr is now pointing at the next RR, and dnss->rrcount
contains the number of RR records left. */

if (dnss->rrcount-- <= 0) return NULL;

/* If expanding the RR domain name fails, behave as if no more records
(something safe). */

namelen = dn_expand(dnsa->answer, dnsa->answer + dnsa->answerlen, dnss->aptr,
  (DN_EXPAND_ARG4_TYPE) &(dnss->srr.name), DNS_MAXNAME);
if (namelen < 0) { dnss->rrcount = 0; return NULL; }

/* Move the pointer past the name and fill in the rest of the data structure
from the following bytes. */

dnss->aptr += namelen;
GETSHORT(dnss->srr.type, dnss->aptr); /* Record type */
dnss->aptr += 6;                      /* Don't want class or TTL */
GETSHORT(dnss->srr.size, dnss->aptr); /* Size of data portion */
dnss->srr.data = dnss->aptr;          /* The record's data follows */
dnss->aptr += dnss->srr.size;         /* Advance to next RR */

/* Return a pointer to the dns_record structure within the dns_answer. This is
for convenience so that the scans can use nice-looking for loops. */

return &(dnss->srr);
}
Example #28
0
char *option_string(int prot, unsigned int opt, unsigned char *val, int opt_len, char *buf, int buf_len)
{
    int o, i, j, nodecode = 0;
    const struct opttab_t *ot = opttab;

#ifdef HAVE_DHCP6
    if (prot == AF_INET6)
        ot = opttab6;
#endif

    for (o = 0; ot[o].name; o++)
        if (ot[o].val == opt)
        {
            if (buf)
            {
                memset(buf, 0, buf_len);

                if (ot[o].size & OT_ADDR_LIST)
                {
                    struct all_addr addr;
                    int addr_len = INADDRSZ;

#ifdef HAVE_DHCP6
                    if (prot == AF_INET6)
                        addr_len = IN6ADDRSZ;
#endif
                    for (buf[0]= 0, i = 0; i <= opt_len - addr_len; i += addr_len)
                    {
                        if (i != 0)
                            strncat(buf, ", ", buf_len - strlen(buf));
                        /* align */
                        memcpy(&addr, &val[i], addr_len);
                        inet_ntop(prot, &val[i], daemon->addrbuff, ADDRSTRLEN);
                        strncat(buf, daemon->addrbuff, buf_len - strlen(buf));
                    }
                }
                else if (ot[o].size & OT_NAME)
                    for (i = 0, j = 0; i < opt_len && j < buf_len ; i++)
                    {
                        char c = val[i];
                        if (isprint((int)c))
                            buf[j++] = c;
                    }
#ifdef HAVE_DHCP6
                /* We don't handle compressed rfc1035 names, so no good in IPv4 land */
                else if ((ot[o].size & OT_RFC1035_NAME) && prot == AF_INET6)
                {
                    i = 0, j = 0;
                    while (i < opt_len && val[i] != 0)
                    {
                        int k, l = i + val[i] + 1;
                        for (k = i + 1; k < opt_len && k < l && j < buf_len ; k++)
                        {
                            char c = val[k];
                            if (isprint((int)c))
                                buf[j++] = c;
                        }
                        i = l;
                        if (val[i] != 0 && j < buf_len)
                            buf[j++] = '.';
                    }
                }
                else if ((ot[o].size & OT_CSTRING))
                {
                    int k, len;
                    unsigned char *p;

                    i = 0, j = 0;
                    while (1)
                    {
                        p = &val[i];
                        GETSHORT(len, p);
                        for (k = 0; k < len && j < buf_len; k++)
                        {
                            char c = *p++;
                            if (isprint((int)c))
                                buf[j++] = c;
                        }
                        i += len +2;
                        if (i >= opt_len)
                            break;

                        if (j < buf_len)
                            buf[j++] = ',';
                    }
                }
#endif
                else if ((ot[o].size & (OT_DEC | OT_TIME)) && opt_len != 0)
                {
                    unsigned int dec = 0;

                    for (i = 0; i < opt_len; i++)
                        dec = (dec << 8) | val[i];

                    if (ot[o].size & OT_TIME)
                        prettyprint_time(buf, dec);
                    else
                        sprintf(buf, "%u", dec);
                }
                else
                    nodecode = 1;
            }
            break;
        }

    if (opt_len != 0 && buf && (!ot[o].name || nodecode))
    {
        int trunc  = 0;
        if (opt_len > 14)
        {
            trunc = 1;
            opt_len = 14;
        }
        print_mac(buf, val, opt_len);
        if (trunc)
            strncat(buf, "...", buf_len - strlen(buf));


    }

    return ot[o].name ? ot[o].name : "";

}
Example #29
0
static unsigned char *php_parserr(unsigned char *cp, querybuf *answer,
                                  int type_to_fetch, bool store,
                                  Array &subarray) {
  unsigned short type, cls ATTRIBUTE_UNUSED, dlen;
  unsigned long ttl;
  int64_t n, i;
  unsigned short s;
  unsigned char *tp, *p;
  char name[MAXHOSTNAMELEN];
  int have_v6_break = 0, in_v6_break = 0;

  n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, sizeof(name) - 2);
  if (n < 0) {
    return NULL;
  }
  cp += n;

  GETSHORT(type, cp);
  GETSHORT(cls, cp);
  GETLONG(ttl, cp);
  GETSHORT(dlen, cp);
  if (type_to_fetch != T_ANY && type != type_to_fetch) {
    cp += dlen;
    return cp;
  }

  if (!store) {
    cp += dlen;
    return cp;
  }

  subarray.set(s_host, String(name, CopyString));
  switch (type) {
  case DNS_T_A:
    subarray.set(s_type, s_A);
    snprintf(name, sizeof(name), "%d.%d.%d.%d", cp[0], cp[1], cp[2], cp[3]);
    subarray.set(s_ip, String(name, CopyString));
    cp += dlen;
    break;
  case DNS_T_MX:
    subarray.set(s_type, s_MX);
    GETSHORT(n, cp);
    subarray.set(s_pri, n);
    /* no break; */
  case DNS_T_CNAME:
    if (type == DNS_T_CNAME) {
      subarray.set(s_type, s_CNAME);
    }
    /* no break; */
  case DNS_T_NS:
    if (type == DNS_T_NS) {
      subarray.set(s_type, s_NS);
    }
    /* no break; */
  case DNS_T_PTR:
    if (type == DNS_T_PTR) {
      subarray.set(s_type, s_PTR);
    }
    n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) - 2);
    if (n < 0) {
      return NULL;
    }
    cp += n;
    subarray.set(s_target, String(name, CopyString));
    break;
  case DNS_T_HINFO:
    /* See RFC 1010 for values */
    subarray.set(s_type, s_HINFO);
    n = *cp & 0xFF;
    cp++;
    subarray.set(s_cpu, String((const char *)cp, n, CopyString));
    cp += n;
    n = *cp & 0xFF;
    cp++;
    subarray.set(s_os, String((const char *)cp, n, CopyString));
    cp += n;
    break;
  case DNS_T_TXT: {
    int ll = 0;

    subarray.set(s_type, s_TXT);
    String s = String(dlen, ReserveString);
    tp = (unsigned char *)s.bufferSlice().ptr;

    while (ll < dlen) {
      n = cp[ll];
      memcpy(tp + ll , cp + ll + 1, n);
      ll = ll + n + 1;
    }
    s.setSize(dlen > 0 ? dlen - 1 : 0);
    cp += dlen;

    subarray.set(s_txt, s);
    break;
  }
  case DNS_T_SOA:
    subarray.set(s_type, s_SOA);
    n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) -2);
    if (n < 0) {
      return NULL;
    }
    cp += n;
    subarray.set(s_mname, String(name, CopyString));
    n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) -2);
    if (n < 0) {
      return NULL;
    }
    cp += n;
    subarray.set(s_rname, String(name, CopyString));
    GETLONG(n, cp);
    subarray.set(s_serial, n);
    GETLONG(n, cp);
    subarray.set(s_refresh, n);
    GETLONG(n, cp);
    subarray.set(s_retry, n);
    GETLONG(n, cp);
    subarray.set(s_expire, n);
    GETLONG(n, cp);
    subarray.set(s_minimum_ttl, n);
    break;
  case DNS_T_AAAA:
    tp = (unsigned char *)name;
    for (i = 0; i < 8; i++) {
      GETSHORT(s, cp);
      if (s != 0) {
        if (tp > (u_char *)name) {
          in_v6_break = 0;
          tp[0] = ':';
          tp++;
        }
        tp += sprintf((char *)tp, "%x", s);
      } else {
        if (!have_v6_break) {
          have_v6_break = 1;
          in_v6_break = 1;
          tp[0] = ':';
          tp++;
        } else if (!in_v6_break) {
          tp[0] = ':';
          tp++;
          tp[0] = '0';
          tp++;
        }
      }
    }
    if (have_v6_break && in_v6_break) {
      tp[0] = ':';
      tp++;
    }
    tp[0] = '\0';
    subarray.set(s_type, s_AAAA);
    subarray.set(s_ipv6, String(name, CopyString));
    break;
  case DNS_T_A6:
    p = cp;
    subarray.set(s_type, s_A6);
    n = ((int)cp[0]) & 0xFF;
    cp++;
    subarray.set(s_masklen, n);
    tp = (unsigned char *)name;
    if (n > 15) {
      have_v6_break = 1;
      in_v6_break = 1;
      tp[0] = ':';
      tp++;
    }
    if (n % 16 > 8) {
      /* Partial short */
      if (cp[0] != 0) {
        if (tp > (u_char *)name) {
          in_v6_break = 0;
          tp[0] = ':';
          tp++;
        }
        sprintf((char *)tp, "%x", cp[0] & 0xFF);
      } else {
        if (!have_v6_break) {
          have_v6_break = 1;
          in_v6_break = 1;
          tp[0] = ':';
          tp++;
        } else if (!in_v6_break) {
          tp[0] = ':';
          tp++;
          tp[0] = '0';
          tp++;
        }
      }
      cp++;
    }
    for (i = (n + 8)/16; i < 8; i++) {
      GETSHORT(s, cp);
      if (s != 0) {
        if (tp > (u_char *)name) {
          in_v6_break = 0;
          tp[0] = ':';
          tp++;
        }
        tp += sprintf((char*)tp,"%x",s);
      } else {
        if (!have_v6_break) {
          have_v6_break = 1;
          in_v6_break = 1;
          tp[0] = ':';
          tp++;
        } else if (!in_v6_break) {
          tp[0] = ':';
          tp++;
          tp[0] = '0';
          tp++;
        }
      }
    }
    if (have_v6_break && in_v6_break) {
      tp[0] = ':';
      tp++;
    }
    tp[0] = '\0';
    subarray.set(s_ipv6, String(name, CopyString));
    if (cp < p + dlen) {
      n = dn_expand(answer->qb2, answer->qb2+65536, cp, name,
                    (sizeof name) - 2);
      if (n < 0) {
        return NULL;
      }
      cp += n;
      subarray.set(s_chain, String(name, CopyString));
    }
    break;
  case DNS_T_SRV:
    subarray.set(s_type, s_SRV);
    GETSHORT(n, cp);
    subarray.set(s_pri, n);
    GETSHORT(n, cp);
    subarray.set(s_weight, n);
    GETSHORT(n, cp);
    subarray.set(s_port, n);
    n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) - 2);
    if (n < 0) {
      return NULL;
    }
    cp += n;
    subarray.set(s_target, String(name, CopyString));
    break;
  case DNS_T_NAPTR:
    subarray.set(s_type, s_NAPTR);
    GETSHORT(n, cp);
    subarray.set(s_order, n);
    GETSHORT(n, cp);
    subarray.set(s_pref, n);
    n = (cp[0] & 0xFF);
    subarray.set(s_flags, String((const char *)(++cp), n, CopyString));
    cp += n;
    n = (cp[0] & 0xFF);
    subarray.set(s_services, String((const char *)(++cp), n, CopyString));
    cp += n;
    n = (cp[0] & 0xFF);
    subarray.set(s_regex, String((const char *)(++cp), n, CopyString));
    cp += n;
    n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) - 2);
    if (n < 0) {
      return NULL;
    }
    cp += n;
    subarray.set(s_replacement, String(name, CopyString));
    break;
  default:
    cp += dlen;
  }

  subarray.set(s_class, s_IN);
  subarray.set(s_ttl, (int)ttl);
  return cp;
}
Example #30
0
/* Receive packet */
void
l2tp_ctrl_input(l2tpd *_this, int listener_index, struct sockaddr *peer,
    struct sockaddr *sock, void *nat_t_ctx, u_char *pkt, int pktlen)
{
	int i, len, offsiz, reqlen, is_ctrl;
	uint16_t mestype;
	struct l2tp_avp *avp, *avp0;
	l2tp_ctrl *ctrl;
	l2tp_call *call;
	char buf[L2TP_AVP_MAXSIZ], errmsg[256];
	time_t curr_time;
	u_char *pkt0;
	struct l2tp_header hdr;
	char hbuf[NI_MAXHOST + NI_MAXSERV + 16];

	ctrl = NULL;
	curr_time = get_monosec();
	pkt0 = pkt;

	L2TP_CTRL_ASSERT(peer->sa_family == sock->sa_family);
	L2TP_CTRL_ASSERT(peer->sa_family == AF_INET ||
	    peer->sa_family == AF_INET6)
    /*
     * Parse L2TP Header
     */
	memset(&hdr, 0, sizeof(hdr));
	if (pktlen < 2) {
		snprintf(errmsg, sizeof(errmsg), "a short packet.  "
		    "length=%d", pktlen);
		goto bad_packet;
	}
	memcpy(&hdr, pkt, 2);
	pkt += 2;
	if (hdr.ver != L2TP_HEADER_VERSION_RFC2661) {
		/* XXX: only RFC2661 is supported */
		snprintf(errmsg, sizeof(errmsg),
		    "Unsupported version at header = %d", hdr.ver);
		goto bad_packet;
	}
	is_ctrl = (hdr.t != 0)? 1 : 0;

	/* calc required length */
	reqlen = 6;		/* for Flags, Tunnel-Id, Session-Id field */
	if (hdr.l) reqlen += 2;	/* for Length field (opt) */
	if (hdr.s) reqlen += 4;	/* for Ns, Nr field (opt) */
	if (hdr.o) reqlen += 2;	/* for Offset Size field (opt) */
	if (reqlen > pktlen) {
		snprintf(errmsg, sizeof(errmsg),
		    "a short packet. length=%d", pktlen);
		goto bad_packet;
	}

	if (hdr.l != 0) {
		GETSHORT(hdr.length, pkt);
		if (hdr.length > pktlen) {
			snprintf(errmsg, sizeof(errmsg),
			    "Actual packet size is smaller than the length "
			    "field %d < %d", pktlen, hdr.length);
			goto bad_packet;
		}
		pktlen = hdr.length;	/* remove trailing trash */
	}
	GETSHORT(hdr.tunnel_id, pkt);
	GETSHORT(hdr.session_id, pkt);
	if (hdr.s != 0) {
		GETSHORT(hdr.ns, pkt);
		GETSHORT(hdr.nr, pkt);
	}
	if (hdr.o != 0) {
		GETSHORT(offsiz, pkt);
		if (pktlen < offsiz) {
			snprintf(errmsg, sizeof(errmsg),
			    "offset field is bigger than remaining packet "
			    "length %d > %d", offsiz, pktlen);
			goto bad_packet;
		}
		pkt += offsiz;
	}
	L2TP_CTRL_ASSERT(pkt - pkt0 == reqlen);
	pktlen -= (pkt - pkt0);	/* cut down the length of header */

	ctrl = NULL;
	memset(buf, 0, sizeof(buf));
	mestype = 0;
	avp = NULL;

	if (is_ctrl) {
		avp0 = (struct l2tp_avp *)buf;
		avp = avp_find_message_type_avp(avp0, pkt, pktlen);
		if (avp != NULL)
			mestype = avp->attr_value[0] << 8 | avp->attr_value[1];
	}
	ctrl = l2tpd_get_ctrl(_this, hdr.tunnel_id);

	if (ctrl == NULL) {
		/* new control */
		if (!is_ctrl) {
			snprintf(errmsg, sizeof(errmsg),
			    "bad data message: tunnelId=%d is not "
			    "found.", hdr.tunnel_id);
			goto bad_packet;
		}
		if (mestype != L2TP_AVP_MESSAGE_TYPE_SCCRQ) {
			snprintf(errmsg, sizeof(errmsg),
			    "bad control message: tunnelId=%d is not "
			    "found.  mestype=%s", hdr.tunnel_id,
			    avp_mes_type_string(mestype));
			goto bad_packet;
		}

		if ((ctrl = l2tp_ctrl_create()) == NULL) {
			l2tp_ctrl_log(ctrl, LOG_ERR,
			    "l2tp_ctrl_create() failed: %m");
			goto fail;
		}

		if (l2tp_ctrl_init(ctrl, _this, peer, sock, nat_t_ctx) != 0) {
			l2tp_ctrl_log(ctrl, LOG_ERR,
			    "l2tp_ctrl_start() failed: %m");
			goto fail;
		}

		ctrl->listener_index = listener_index;
		l2tp_ctrl_reload(ctrl);
	} else {
		/*
		 * treat as an error if src address and port is not
		 * match. (because it is potentially DoS attach)
		 */
		int notmatch = 0;

		if (ctrl->peer.ss_family != peer->sa_family)
			notmatch = 1;
		else if (peer->sa_family == AF_INET) {
			if (SIN(peer)->sin_addr.s_addr != 
			    SIN(&ctrl->peer)->sin_addr.s_addr ||
			    SIN(peer)->sin_port != SIN(&ctrl->peer)->sin_port)
				notmatch = 1;
		} else if (peer->sa_family == AF_INET6) {
			if (!IN6_ARE_ADDR_EQUAL(&(SIN6(peer)->sin6_addr),
				    &(SIN6(&ctrl->peer)->sin6_addr)) ||
			    SIN6(peer)->sin6_port !=
				    SIN6(&ctrl->peer)->sin6_port)
				notmatch = 1;
 		}
		if (notmatch) {
			snprintf(errmsg, sizeof(errmsg),
			    "tunnelId=%u is already assigned for %s",
			    hdr.tunnel_id, addrport_tostring(
				(struct sockaddr *)&ctrl->peer,
				ctrl->peer.ss_len, hbuf, sizeof(hbuf)));
			goto bad_packet;
		}
	}
	ctrl->last_rcv = curr_time;
	call = NULL;
	if (hdr.session_id != 0) {
		/* search l2tp_call by Session ID */
		/* linear search is enough for this purpose */
		len = slist_length(&ctrl->call_list);
		for (i = 0; i < len; i++) {
			call = slist_get(&ctrl->call_list, i);
			if (call->session_id == hdr.session_id)
				break;
			call = NULL;
		}
	}
	if (!is_ctrl) {
		int delayed = 0;

		/* L2TP data */
		if (ctrl->state != L2TP_CTRL_STATE_ESTABLISHED) {
			l2tp_ctrl_log(ctrl, LOG_WARNING,
			    "Received Data packet in '%s'",
			    l2tp_ctrl_state_string(ctrl));
			goto fail;
		}
		if (call == NULL) {
			l2tp_ctrl_log(ctrl, LOG_WARNING,
			    "Received a data packet but it has no call.  "
			    "session_id=%u",  hdr.session_id);
			goto fail;
		}
		L2TP_CTRL_DBG((ctrl, DEBUG_LEVEL_2,
		    "call=%u RECV   ns=%u nr=%u snd_nxt=%u rcv_nxt=%u len=%d",
		    call->id, hdr.ns, hdr.nr, call->snd_nxt, call->rcv_nxt,
		    pktlen));
		if (call->state != L2TP_CALL_STATE_ESTABLISHED){
			l2tp_ctrl_log(ctrl, LOG_WARNING,
			    "Received a data packet but call is not "
			    "established");
			goto fail;
		}

		if (hdr.s != 0) {
			if (SEQ_LT(hdr.ns, call->rcv_nxt)) {
				if (SEQ_LT(hdr.ns,
				    call->rcv_nxt - L2TP_CALL_DELAY_LIMIT)) {
					/* sequence number seems to be delayed */
					/* XXX: need to log? */
					L2TP_CTRL_DBG((ctrl, LOG_DEBUG,
					    "receive a out of sequence "
					    "data packet: %u < %u.",
					    hdr.ns, call->rcv_nxt));
					return;
				}
				delayed = 1;
			} else {
				call->rcv_nxt = hdr.ns + 1;
			}
		}

		l2tp_call_ppp_input(call, pkt, pktlen, delayed);

		return;
	}
	if (hdr.s != 0) {
		L2TP_CTRL_DBG((ctrl, DEBUG_LEVEL_2,
		    "RECV %s ns=%u nr=%u snd_nxt=%u snd_una=%u rcv_nxt=%u "
		    "len=%d", (is_ctrl)? "C" : "", hdr.ns, hdr.nr,
		    ctrl->snd_nxt, ctrl->snd_una, ctrl->rcv_nxt, pktlen));

		if (pktlen <= 0)
			l2tp_ctrl_log(ctrl, LOG_INFO, "RecvZLB");

		if (SEQ_GT(hdr.nr, ctrl->snd_una)) {
			if (hdr.nr == ctrl->snd_nxt ||
			    SEQ_LT(hdr.nr, ctrl->snd_nxt))
				ctrl->snd_una = hdr.nr;
			else {
				l2tp_ctrl_log(ctrl, LOG_INFO,
				    "Received message has bad Nr field: "
				    "%u < %u.", hdr.ns, ctrl->snd_nxt);
				/* XXX Drop with ZLB? */
				goto fail;
			}
		}
		if (l2tp_ctrl_txwin_size(ctrl) <= 0) {
			/* no waiting ack */
			if (ctrl->hello_wait_ack != 0) {
				/*
				 * Reset Hello state, as an ack for the Hello
				 * is recived.
				 */
				ctrl->hello_wait_ack = 0;
				ctrl->hello_io_time = curr_time;
			}
			switch (ctrl->state) {
			case L2TP_CTRL_STATE_CLEANUP_WAIT:
				l2tp_ctrl_stop(ctrl, 0);
				return;
			}
		}
		if (hdr.ns != ctrl->rcv_nxt) {
			/* there are remaining packet */
			if (l2tp_ctrl_resend_una_packets(ctrl) <= 0) {
				/* resend or sent ZLB */
				l2tp_ctrl_send_ZLB(ctrl);
			}
#ifdef	L2TP_CTRL_DEBUG
			if (pktlen != 0) {	/* not ZLB */
				L2TP_CTRL_DBG((ctrl, LOG_DEBUG,
				    "receive out of sequence %u must be %u.  "
				    "mestype=%s", hdr.ns, ctrl->rcv_nxt,
				    avp_mes_type_string(mestype)));
			}
#endif
			return;
		}
		if (pktlen <= 0)
			return;		/* ZLB */

		if (l2tp_ctrl_txwin_is_full(ctrl)) {
			L2TP_CTRL_DBG((ctrl, LOG_DEBUG,
			    "Received message cannot be handled. "
			    "Transmission window is full."));
			l2tp_ctrl_send_ZLB(ctrl);
			return;
		}

		ctrl->rcv_nxt++;
		if (avp == NULL) {
			l2tpd_log(_this, LOG_WARNING,
			    "bad control message: no message-type AVP.");
			goto fail;
		}
	}

    /*
     * state machine (RFC2661 pp. 56-57)
     */
	switch (ctrl->state) {
	case L2TP_CTRL_STATE_IDLE:
		switch (mestype) {
		case L2TP_AVP_MESSAGE_TYPE_SCCRQ:
			if (l2tp_ctrl_recv_SCCRQ(ctrl, pkt, pktlen, _this,
			    peer) == 0) {
				/* acceptable */
				l2tp_ctrl_send_SCCRP(ctrl);
				ctrl->state = L2TP_CTRL_STATE_WAIT_CTL_CONN;
				return;
			}
			/*
			 * in case un-acceptable, it was already processed
			 * at l2tcp_ctrl_recv_SCCRQ
			 */
			return;
		case L2TP_AVP_MESSAGE_TYPE_SCCRP:
			/*
			 * RFC specifies that sent of StopCCN in the state,
			 * However as this implementation only support Passive
			 * open, this packet will not received.
			 */
			/* FALLTHROUGH */
		case L2TP_AVP_MESSAGE_TYPE_SCCCN:
		default:
			break;
		}
		goto fsm_fail;

	case L2TP_CTRL_STATE_WAIT_CTL_CONN:
	    /* Wait-Ctl-Conn */
		switch (mestype) {
		case L2TP_AVP_MESSAGE_TYPE_SCCCN:
			l2tp_ctrl_log(ctrl, LOG_INFO, "RecvSCCN");
			if (l2tp_ctrl_send_ZLB(ctrl) == 0) {
				ctrl->state = L2TP_CTRL_STATE_ESTABLISHED;
			}
			return;
		case L2TP_AVP_MESSAGE_TYPE_StopCCN:
			goto receive_stop_ccn;
		case L2TP_AVP_MESSAGE_TYPE_SCCRQ:
		case L2TP_AVP_MESSAGE_TYPE_SCCRP:
		default:
			break;
		}
		break;	/* fsm_fail */
	case L2TP_CTRL_STATE_ESTABLISHED:
	    /* Established */
		switch (mestype) {
		case L2TP_AVP_MESSAGE_TYPE_SCCCN:
		case L2TP_AVP_MESSAGE_TYPE_SCCRQ:
		case L2TP_AVP_MESSAGE_TYPE_SCCRP:
			break;
receive_stop_ccn:
		case L2TP_AVP_MESSAGE_TYPE_StopCCN:
			if (l2tp_ctrl_recv_StopCCN(ctrl, pkt, pktlen) == 0) {
				if (l2tp_ctrl_resend_una_packets(ctrl) <= 0)
					l2tp_ctrl_send_ZLB(ctrl);
				l2tp_ctrl_stop(ctrl, 0);
				return;
			}
			l2tp_ctrl_log(ctrl, LOG_ERR, "Received bad StopCCN");
			l2tp_ctrl_send_ZLB(ctrl);
			l2tp_ctrl_stop(ctrl, 0);
			return;

		case L2TP_AVP_MESSAGE_TYPE_HELLO:
			if (l2tp_ctrl_resend_una_packets(ctrl) <= 0)
				l2tp_ctrl_send_ZLB(ctrl);
			return;
		case L2TP_AVP_MESSAGE_TYPE_CDN:
		case L2TP_AVP_MESSAGE_TYPE_ICRP:
		case L2TP_AVP_MESSAGE_TYPE_ICCN:
			if (call == NULL) {
				l2tp_ctrl_log(ctrl, LOG_INFO,
				    "Unknown call message: %s",
				    avp_mes_type_string(mestype));
				goto fail;
			}
			/* FALLTHROUGH */
		case L2TP_AVP_MESSAGE_TYPE_ICRQ:
			l2tp_call_recv_packet(ctrl, call, mestype, pkt,
			    pktlen);
			return;
		default:
			break;
		}
		break;	/* fsm_fail */
	case L2TP_CTRL_STATE_CLEANUP_WAIT:
		if (mestype == L2TP_AVP_MESSAGE_TYPE_StopCCN) {
			/*
			 * We left ESTABLISHED state, but the peer sent StopCCN.
			 */
			goto receive_stop_ccn;
		}
		break;	/* fsm_fail */
	}

fsm_fail:
	/* state machine error */
	l2tp_ctrl_log(ctrl, LOG_WARNING, "Received %s in '%s' state",
	    avp_mes_type_string(mestype), l2tp_ctrl_state_string(ctrl));
	l2tp_ctrl_stop(ctrl, L2TP_STOP_CCN_RCODE_FSM_ERROR);

	return;
fail:
	if (ctrl != NULL && mestype != 0) {
		l2tp_ctrl_log(ctrl, LOG_WARNING, "Received %s in '%s' state",
		    avp_mes_type_string(mestype), l2tp_ctrl_state_string(ctrl));
		l2tp_ctrl_stop(ctrl, L2TP_STOP_CCN_RCODE_GENERAL_ERROR);
	}
	return;

bad_packet:
	l2tpd_log(_this, LOG_INFO, "Received from=%s: %s",
	    addrport_tostring(peer, peer->sa_len, hbuf, sizeof(hbuf)), errmsg);

	return;
}