Second try at port-limit option.

1) It's expected to fail to bind a new source port when they
   are scarce, suppress warning in log in this case.

2) Optimse bind_local when max_port - min_port is small. There's no
   randomness in this case, so we try all possible source ports
   rather than poking at random ones for an arbitrary number of tries.

3) In allocate_rfd() handle the case that all available source ports
   are already open. In this case we need to pick an existing
   socket/port to use, such that it has a different port from any we
   already hold. This gives the required property that the set of ports
   utilised by any given query is set by --port-limit and we don't
   re-use any until we have port-limit different ones.
This commit is contained in:
Simon Kelley
2022-09-09 17:09:32 +01:00
parent e518e87533
commit 3f56bb8ba1
4 changed files with 50 additions and 23 deletions

View File

@@ -2438,13 +2438,18 @@ static int random_sock(struct server *s)
if (local_bind(fd, &s->source_addr, s->interface, s->ifindex, 0))
return fd;
if (s->interface[0] == 0)
(void)prettyprint_addr(&s->source_addr, daemon->addrbuff);
else
safe_strncpy(daemon->addrbuff, s->interface, ADDRSTRLEN);
my_syslog(LOG_ERR, _("failed to bind server socket to %s: %s"),
daemon->addrbuff, strerror(errno));
/* don't log errors due to running out of available ports, we handle those. */
if (!sockaddr_isnull(&s->source_addr) || errno != EADDRINUSE)
{
if (s->interface[0] == 0)
(void)prettyprint_addr(&s->source_addr, daemon->addrbuff);
else
safe_strncpy(daemon->addrbuff, s->interface, ADDRSTRLEN);
my_syslog(LOG_ERR, _("failed to bind server socket to %s: %s"),
daemon->addrbuff, strerror(errno));
}
close(fd);
}
@@ -2518,16 +2523,6 @@ int allocate_rfd(struct randfd_list **fdlp, struct server *serv)
break;
}
/* We've hit the global limit on sockets before hitting the query limit,
use an exsiting socket as source in that case. */
if (!rfd && found)
{
*found_link = found->next;
found->next = *fdlp;
*fdlp = found;
return found->rfd->fd;
}
/* No good existing. Need new link. */
if ((rfl = daemon->rfl_spare))
daemon->rfl_spare = rfl->next;
@@ -2552,10 +2547,19 @@ int allocate_rfd(struct randfd_list **fdlp, struct server *serv)
server_isequal(serv, daemon->randomsocks[i].serv) &&
daemon->randomsocks[i].refcount != 0xfffe)
{
finger = i + 1;
rfd = &daemon->randomsocks[i];
rfd->refcount++;
break;
struct randfd_list *rl;
/* Don't pick one we already have. */
for (rl = *fdlp; rl; rl = rl->next)
if (rl->rfd == &daemon->randomsocks[i])
break;
if (!rl)
{
finger = i + 1;
rfd = &daemon->randomsocks[i];
rfd->refcount++;
break;
}
}
}