Beispiel #1
0
void strategy_update_remote_addr_list(vpn_ctx_t *ctx) {
  int i;
  time_t now;
  struct sockaddr *remote_addrp = ctx->remote_addrp;

  time(&now);
  socklen_t remote_addrlen = ctx->remote_addrlen;

  // if already in list, update time and return
  for (i = 0; i < ctx->nknown_addr; i++) {
    if (remote_addrlen == ctx->known_addrs[i].addrlen) {
      if (0 == memcmp(remote_addrp, &ctx->known_addrs[i].addr,
                      remote_addrlen)) {
        ctx->known_addrs[i].last_recv_time = now;
        return;
      }
    }
  }
  // if address list is not full, just append remote addr
  if (ctx->nknown_addr < ctx->args->concurrency) {
    save_addr(&ctx->known_addrs[ctx->nknown_addr], remote_addrp,
              remote_addrlen, now);
    ctx->nknown_addr++;
    return;
  }
  // if full, replace the oldest
  addr_info_t *oldest_addr_info = NULL;
  for (i = 0; i < ctx->nknown_addr; i++) {
    if (oldest_addr_info == NULL ||
        oldest_addr_info->last_recv_time >
          ctx->known_addrs[i].last_recv_time) {
      oldest_addr_info = &ctx->known_addrs[i];
    }
  }
  if (oldest_addr_info) {
    save_addr(oldest_addr_info, remote_addrp, remote_addrlen, now);
  }
}
Beispiel #2
0
static ad_disc_cds_t *
srv_parse(uchar_t *msg, int len, int *scnt, int *maxcnt)
{
	ad_disc_cds_t *cds;
	ad_disc_cds_t *cds_res = NULL;
	HEADER *hdr;
	int i, qdcount, ancount, nscount, arcount;
	uchar_t *ptr, *eom;
	uchar_t *end;
	uint16_t type;
	/* LINTED  E_FUNC_SET_NOT_USED */
	uint16_t class __unused;
	uint32_t rttl;
	uint16_t size;
	char namebuf[NS_MAXDNAME];

	eom = msg + len;
	hdr = (void *)msg;
	ptr = msg + sizeof (HEADER);

	qdcount = ntohs(hdr->qdcount);
	ancount = ntohs(hdr->ancount);
	nscount = ntohs(hdr->nscount);
	arcount = ntohs(hdr->arcount);

	/* skip the question section */

	len = ns_skiprr(ptr, eom, ns_s_qd, qdcount);
	if (len < 0) {
		logger(LOG_ERR, "DNS query invalid message format");
		return (NULL);
	}
	ptr += len;

	/*
	 * Walk through the answer section, building the result array.
	 * The array size is +2 because we (possibly) add the preferred
	 * DC if it was not there, and an empty one (null termination).
	 */

	*maxcnt = ancount + 2;
	cds_res = calloc(*maxcnt, sizeof (*cds_res));
	if (cds_res == NULL) {
		logger(LOG_ERR, "Out of memory");
		return (NULL);
	}

	cds = cds_res;
	for (i = 0; i < ancount; i++) {

		len = dn_expand(msg, eom, ptr, namebuf,
		    sizeof (namebuf));
		if (len < 0) {
			logger(LOG_ERR, "DNS query invalid message format");
			goto err;
		}
		ptr += len;
		NS_GET16(type, ptr);
		NS_GET16(class, ptr);
		NS_GET32(rttl, ptr);
		NS_GET16(size, ptr);
		if ((end = ptr + size) > eom) {
			logger(LOG_ERR, "DNS query invalid message format");
			goto err;
		}

		if (type != T_SRV) {
			ptr = end;
			continue;
		}

		NS_GET16(cds->cds_ds.priority, ptr);
		NS_GET16(cds->cds_ds.weight, ptr);
		NS_GET16(cds->cds_ds.port, ptr);
		len = dn_expand(msg, eom, ptr, cds->cds_ds.host,
		    sizeof (cds->cds_ds.host));
		if (len < 0) {
			logger(LOG_ERR, "DNS query invalid SRV record");
			goto err;
		}

		cds->cds_ds.ttl = rttl;

		if (DBG(DNS, 2)) {
			logger(LOG_DEBUG, "    %s", namebuf);
			logger(LOG_DEBUG,
			    "        ttl=%d pri=%d weight=%d %s:%d",
			    rttl, cds->cds_ds.priority, cds->cds_ds.weight,
			    cds->cds_ds.host, cds->cds_ds.port);
		}
		cds++;

		/* move ptr to the end of current record */
		ptr = end;
	}
	*scnt = (cds - cds_res);

	/* skip the nameservers section (if any) */

	len = ns_skiprr(ptr, eom, ns_s_ns, nscount);
	if (len < 0) {
		logger(LOG_ERR, "DNS query invalid message format");
		goto err;
	}
	ptr += len;

	/* walk through the additional records */
	for (i = 0; i < arcount; i++) {
		sa_family_t af;

		len = dn_expand(msg, eom, ptr, namebuf,
		    sizeof (namebuf));
		if (len < 0) {
			logger(LOG_ERR, "DNS query invalid message format");
			goto err;
		}
		ptr += len;
		NS_GET16(type, ptr);
		NS_GET16(class, ptr);
		NS_GET32(rttl, ptr);
		NS_GET16(size, ptr);
		if ((end = ptr + size) > eom) {
			logger(LOG_ERR, "DNS query invalid message format");
			goto err;
		}
		switch (type) {
		case ns_t_a:
			af = AF_INET;
			break;
		case ns_t_aaaa:
			af = AF_INET6;
			break;
		default:
			continue;
		}

		if (DBG(DNS, 2)) {
			char abuf[INET6_ADDRSTRLEN];
			const char *ap;

			ap = inet_ntop(af, ptr, abuf, sizeof (abuf));
			logger(LOG_DEBUG, "    %s    %s    %s",
			    (af == AF_INET) ? "A   " : "AAAA",
			    (ap) ? ap : "?", namebuf);
		}

		/* Find the server, add to its address list. */
		for (cds = cds_res; cds->cds_ds.host[0] != '\0'; cds++)
			if (0 == strcmp(namebuf, cds->cds_ds.host))
				save_addr(cds, af, ptr, size);

		/* move ptr to the end of current record */
		ptr = end;
	}

	return (cds_res);

err:
	free(cds_res);
	return (NULL);
}