}
static uint32_t
-_pdns_get_handles_for_name(sdns_handle_t *sdns, const char *name, pdns_handle_t ***pdns)
+_pdns_get_handles_for_name(sdns_handle_t *sdns, const char *name, uint32_t nlabels, pdns_handle_t ***pdns)
{
char *p, *vname;
int i, j, k, count;
{
if (sdns->client[i]->name == NULL) continue;
+ /* Special case: Don't send to ".local[.]" queries to mDNSResponder if nlabels > 2 */
+ if ((nlabels > 2) && (sdns->client[i]->flags & DNS_FLAG_FORWARD_TO_MDNSRESPONDER) && (!strcasecmp(sdns->client[i]->name, "local"))) continue;
+
if (!strcasecmp(sdns->client[i]->name, p))
{
if (count == 0)
tick = time(NULL);
/*
* Subsequent threads sleep for the remaining duration.
- * We add one to round up the interval since our garnularity is coarse.
+ * We add one to round up the interval since our granularity is coarse.
*/
snooze = 1 + (sdns->dns_delay - tick);
if (snooze < 0) snooze = 0;
}
static int
-_sdns_send(sdns_handle_t *sdns, const char *name, uint32_t class, uint32_t type, uint32_t fqdn, char *buf, uint32_t len, struct sockaddr *from, uint32_t *fromlen, int *min)
+_sdns_send(sdns_handle_t *sdns, const char *name, uint32_t class, uint32_t type, uint32_t fqdn, char *buf, uint32_t len, struct sockaddr *from, uint32_t *fromlen, uint32_t nlabels, int *min)
{
char *qname;
pdns_handle_t **pdns;
*min = -1;
m = -1;
- pdns_count = _pdns_get_handles_for_name(sdns, name, &pdns);
+ pdns_count = _pdns_get_handles_for_name(sdns, name, nlabels, &pdns);
if (pdns_count == 0) return -1;
_sdns_search(sdns_handle_t *sdns, const char *name, uint32_t class, uint32_t type, uint32_t fqdn, uint32_t recurse, char *buf, uint32_t len, struct sockaddr *from, uint32_t *fromlen, int *min)
{
pdns_handle_t *primary, **pdns;
- int i, n, ndots, status;
+ int i, n, ndots, nlabels, status;
int m, tmin, minstate;
char *dot, *qname;
uint32_t pdns_count;
/* the last dot is the last character, name is fully qualified */
if ((fqdn == 0) && (dot != NULL) && (*(dot + 1) == '\0')) fqdn = 1;
+ /* number of labels */
+ nlabels = n + 1 - fqdn;
+
/*
* If n >= ndots, or it's a FQDN, or if it's a PTR query,
* we try a query with the name "as is".
if ((n >= ndots) || (fqdn == 1) || (type == ns_t_ptr))
{
tmin = -1;
- status = _sdns_send(sdns, name, class, type, fqdn, buf, len, from, fromlen, &tmin);
+ status = _sdns_send(sdns, name, class, type, fqdn, buf, len, from, fromlen, nlabels, &tmin);
if (status > 0) return status;
if (tmin < 0) minstate = -1;
res_build_start(res_state x)
{
res_state res;
- int rf;
res = NULL;
res->retry = RES_DFLRETRY;
res->options = RES_DEFAULT;
-
- rf = open("/dev/random", O_RDONLY, 0);
- read(rf, &(res->id), 2);
- close(rf);
+ res->id = res_randomid();
res->ndots = 1;
res->_vcsock = -1;
#endif
u_int
-res_randomid(void) {
- struct timeval now;
+res_randomid(void)
+{
#ifdef __APPLE__
- int rf;
- static u_int x = 0;
-
- if (x == 0)
- {
- rf = open("/dev/random", O_RDONLY, 0);
- if (rf >= 0)
- {
- read(rf, &x, sizeof(u_int));
- close(rf);
- }
- else
- {
- x = (getpid() << 10) + time(NULL);
- }
-
- srandom(x);
- }
-
- return random();
-#endif
-
+ return arc4random();
+#else
+ struct timeval now;
gettimeofday(&now, NULL);
return (0xffff & (now.tv_sec ^ now.tv_usec ^ getpid()));
+#endif
}
/*
#define MAX_HOOK_RETRIES 42
+/* port randomization */
+#define RANDOM_BIND_MAX_TRIES 16
+#define RANDOM_BIND_FIRST IPPORT_HIFIRSTAUTO
+#define RANDOM_BIND_LAST IPPORT_HILASTAUTO
+
/* Forward. */
static int get_salen __P((const struct sockaddr *));
static int interrupt_pipe_enabled = 0;
static pthread_key_t interrupt_pipe_key;
+static int
+bind_random(int sock)
+{
+ int i, status;
+ uint16_t src_port;
+ struct sockaddr_in local;
+
+ src_port = 0;
+ status = -1;
+
+ for (i = 0; (i < RANDOM_BIND_MAX_TRIES) && (status < 0); i++)
+ {
+ /* random port in the range RANDOM_BIND_FIRST to RANDOM_BIND_LAST */
+ src_port = (res_randomid() % (RANDOM_BIND_LAST - RANDOM_BIND_FIRST)) + RANDOM_BIND_FIRST;
+ memset(&local, 0, sizeof(struct sockaddr_in));
+ local.sin_port = htons(src_port);
+
+ status = bind(sock, (struct sockaddr *)&local, sizeof(struct sockaddr_in));
+ }
+
+ return status;
+}
+
void
res_delete_interrupt_token(void *token)
{
return DNS_RES_STATUS_SYSTEM_ERROR;
}
+ bind_random(EXT(statp).nssocks[ns]);
+
#ifndef CANNOT_CONNECT_DGRAM
/*
* On a 4.3BSD+ machine (client and server,