"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "src/network.c" between
dnsmasq-2.81.tar.xz and dnsmasq-2.82.tar.xz

About: Dnsmasq is a lightweight caching DNS forwarder and DHCP server.

network.c  (dnsmasq-2.81.tar.xz):network.c  (dnsmasq-2.82.tar.xz)
skipping to change at line 387 skipping to change at line 387
if (!(iface_flags & IFACE_PERMANENT) || (iface_flags & (IFACE _DEPRECATED | IFACE_TENTATIVE))) if (!(iface_flags & IFACE_PERMANENT) || (iface_flags & (IFACE _DEPRECATED | IFACE_TENTATIVE)))
al->flags |= ADDRLIST_REVONLY; al->flags |= ADDRLIST_REVONLY;
} }
} }
} }
} }
/* check whether the interface IP has been added already /* check whether the interface IP has been added already
we call this routine multiple times. */ we call this routine multiple times. */
for (iface = daemon->interfaces; iface; iface = iface->next) for (iface = daemon->interfaces; iface; iface = iface->next)
if (sockaddr_isequal(&iface->addr, addr)) if (sockaddr_isequal(&iface->addr, addr) && iface->index == if_index)
{ {
iface->dad = !!(iface_flags & IFACE_TENTATIVE); iface->dad = !!(iface_flags & IFACE_TENTATIVE);
iface->found = 1; /* for garbage collection */ iface->found = 1; /* for garbage collection */
iface->netmask = netmask;
return 1; return 1;
} }
/* If we are restricting the set of interfaces to use, make /* If we are restricting the set of interfaces to use, make
sure that loopback interfaces are in that set. */ sure that loopback interfaces are in that set. */
if (daemon->if_names && loopback) if (daemon->if_names && loopback)
{ {
struct iname *lo; struct iname *lo;
for (lo = daemon->if_names; lo; lo = lo->next) for (lo = daemon->if_names; lo; lo = lo->next)
if (lo->name && strcmp(lo->name, ifr.ifr_name) == 0) if (lo->name && strcmp(lo->name, ifr.ifr_name) == 0)
skipping to change at line 531 skipping to change at line 532
addr.in.sin_family = AF_INET; addr.in.sin_family = AF_INET;
addr.in.sin_addr = local; addr.in.sin_addr = local;
addr.in.sin_port = htons(daemon->port); addr.in.sin_port = htons(daemon->port);
/* determine prefix length from netmask */ /* determine prefix length from netmask */
for (prefix = 32, bit = 1; (bit & ntohl(netmask.s_addr)) == 0 && prefix != 0; bit = bit << 1, prefix--); for (prefix = 32, bit = 1; (bit & ntohl(netmask.s_addr)) == 0 && prefix != 0; bit = bit << 1, prefix--);
return iface_allowed((struct iface_param *)vparam, if_index, label, &addr, net mask, prefix, 0); return iface_allowed((struct iface_param *)vparam, if_index, label, &addr, net mask, prefix, 0);
} }
/*
* Clean old interfaces no longer found.
*/
static void clean_interfaces()
{
struct irec *iface;
struct irec **up = &daemon->interfaces;
for (iface = *up; iface; iface = *up)
{
if (!iface->found && !iface->done)
{
*up = iface->next;
free(iface->name);
free(iface);
}
else
{
up = &iface->next;
}
}
}
/** Release listener if no other interface needs it.
*
* @return 1 if released, 0 if still required
*/
static int release_listener(struct listener *l)
{
if (l->used > 1)
{
struct irec *iface;
for (iface = daemon->interfaces; iface; iface = iface->next)
if (iface->done && sockaddr_isequal(&l->addr, &iface->addr))
{
if (iface->found)
{
/* update listener to point to active interface instead */
if (!l->iface->found)
l->iface = iface;
}
else
{
l->used--;
iface->done = 0;
}
}
/* Someone is still using this listener, skip its deletion */
if (l->used > 0)
return 0;
}
if (l->iface->done)
{
int port;
port = prettyprint_addr(&l->iface->addr, daemon->addrbuff);
my_syslog(LOG_DEBUG, _("stopped listening on %s(#%d): %s port %d"),
l->iface->name, l->iface->index, daemon->addrbuff, port);
/* In case it ever returns */
l->iface->done = 0;
}
if (l->fd != -1)
close(l->fd);
if (l->tcpfd != -1)
close(l->tcpfd);
if (l->tftpfd != -1)
close(l->tftpfd);
free(l);
return 1;
}
int enumerate_interfaces(int reset) int enumerate_interfaces(int reset)
{ {
static struct addrlist *spare = NULL; static struct addrlist *spare = NULL;
static int done = 0; static int done = 0;
struct iface_param param; struct iface_param param;
int errsave, ret = 1; int errsave, ret = 1;
struct addrlist *addr, *tmp; struct addrlist *addr, *tmp;
struct interface_name *intname; struct interface_name *intname;
struct irec *iface; struct irec *iface;
#ifdef HAVE_AUTH #ifdef HAVE_AUTH
skipping to change at line 628 skipping to change at line 704
if (option_bool(OPT_CLEVERBIND)) if (option_bool(OPT_CLEVERBIND))
{ {
/* Garbage-collect listeners listening on addresses that no longer exist. /* Garbage-collect listeners listening on addresses that no longer exist.
Does nothing when not binding interfaces or for listeners on localhost, Does nothing when not binding interfaces or for listeners on localhost,
since the ->iface field is NULL. Note that this needs the protections since the ->iface field is NULL. Note that this needs the protections
against reentrancy, hence it's here. It also means there's a possibilit y, against reentrancy, hence it's here. It also means there's a possibilit y,
in OPT_CLEVERBIND mode, that at listener will just disappear after in OPT_CLEVERBIND mode, that at listener will just disappear after
a call to enumerate_interfaces, this is checked OK on all calls. */ a call to enumerate_interfaces, this is checked OK on all calls. */
struct listener *l, *tmp, **up; struct listener *l, *tmp, **up;
int freed = 0;
for (up = &daemon->listeners, l = daemon->listeners; l; l = tmp) for (up = &daemon->listeners, l = daemon->listeners; l; l = tmp)
{ {
tmp = l->next; tmp = l->next;
if (!l->iface || l->iface->found) if (!l->iface || l->iface->found)
up = &l->next; up = &l->next;
else else if (release_listener(l))
{ {
*up = l->next; *up = tmp;
freed = 1;
/* In case it ever returns */
l->iface->done = 0;
if (l->fd != -1)
close(l->fd);
if (l->tcpfd != -1)
close(l->tcpfd);
if (l->tftpfd != -1)
close(l->tftpfd);
free(l);
} }
} }
if (freed)
clean_interfaces();
} }
errno = errsave; errno = errsave;
spare = param.spare; spare = param.spare;
return ret; return ret;
} }
/* set NONBLOCK bit on fd: See Stevens 16.6 */ /* set NONBLOCK bit on fd: See Stevens 16.6 */
int fix_fd(int fd) int fix_fd(int fd)
skipping to change at line 892 skipping to change at line 961
tftpfd = make_sock(addr, SOCK_DGRAM, dienow); tftpfd = make_sock(addr, SOCK_DGRAM, dienow);
addr->in6.sin6_port = save; addr->in6.sin6_port = save;
} }
} }
#endif #endif
if (fd != -1 || tcpfd != -1 || tftpfd != -1) if (fd != -1 || tcpfd != -1 || tftpfd != -1)
{ {
l = safe_malloc(sizeof(struct listener)); l = safe_malloc(sizeof(struct listener));
l->next = NULL; l->next = NULL;
l->family = addr->sa.sa_family;
l->fd = fd; l->fd = fd;
l->tcpfd = tcpfd; l->tcpfd = tcpfd;
l->tftpfd = tftpfd; l->tftpfd = tftpfd;
l->addr = *addr;
l->used = 1;
l->iface = NULL; l->iface = NULL;
} }
return l; return l;
} }
void create_wildcard_listeners(void) void create_wildcard_listeners(void)
{ {
union mysockaddr addr; union mysockaddr addr;
struct listener *l, *l6; struct listener *l, *l6;
skipping to change at line 934 skipping to change at line 1004
l6 = create_listeners(&addr, !!option_bool(OPT_TFTP), 1); l6 = create_listeners(&addr, !!option_bool(OPT_TFTP), 1);
if (l) if (l)
l->next = l6; l->next = l6;
else else
l = l6; l = l6;
daemon->listeners = l; daemon->listeners = l;
} }
static struct listener *find_listener(union mysockaddr *addr)
{
struct listener *l;
for (l = daemon->listeners; l; l = l->next)
if (sockaddr_isequal(&l->addr, addr))
return l;
return NULL;
}
void create_bound_listeners(int dienow) void create_bound_listeners(int dienow)
{ {
struct listener *new; struct listener *new;
struct irec *iface; struct irec *iface;
struct iname *if_tmp; struct iname *if_tmp;
struct listener *existing;
for (iface = daemon->interfaces; iface; iface = iface->next) for (iface = daemon->interfaces; iface; iface = iface->next)
if (!iface->done && !iface->dad && iface->found && if (!iface->done && !iface->dad && iface->found)
(new = create_listeners(&iface->addr, iface->tftp_ok, dienow)))
{ {
new->iface = iface; existing = find_listener(&iface->addr);
new->next = daemon->listeners; if (existing)
daemon->listeners = new; {
iface->done = 1; iface->done = 1;
existing->used++; /* increase usage counter */
}
else if ((new = create_listeners(&iface->addr, iface->tftp_ok, dienow)))
{
new->iface = iface;
new->next = daemon->listeners;
daemon->listeners = new;
iface->done = 1;
/* Don't log the initial set of listen addresses created
at startup, since this is happening before the logging
system is initialised and the sign-on printed. */
if (!dienow)
{
int port = prettyprint_addr(&iface->addr, daemon->addrbuff);
my_syslog(LOG_DEBUG, _("listening on %s(#%d): %s port %d"),
iface->name, iface->index, daemon->addrbuff, port);
}
}
} }
/* Check for --listen-address options that haven't been used because there's /* Check for --listen-address options that haven't been used because there's
no interface with a matching address. These may be valid: eg it's possible no interface with a matching address. These may be valid: eg it's possible
to listen on 127.0.1.1 even if the loopback interface is 127.0.0.1 to listen on 127.0.1.1 even if the loopback interface is 127.0.0.1
If the address isn't valid the bind() will fail and we'll die() If the address isn't valid the bind() will fail and we'll die()
(except in bind-dynamic mode, when we'll complain but keep trying.) (except in bind-dynamic mode, when we'll complain but keep trying.)
The resulting listeners have the ->iface field NULL, and this has to be The resulting listeners have the ->iface field NULL, and this has to be
handled by the DNS and TFTP code. It disables --localise-queries processing handled by the DNS and TFTP code. It disables --localise-queries processing
(no netmask) and some MTU login the tftp code. */ (no netmask) and some MTU login the tftp code. */
for (if_tmp = daemon->if_addrs; if_tmp; if_tmp = if_tmp->next) for (if_tmp = daemon->if_addrs; if_tmp; if_tmp = if_tmp->next)
if (!if_tmp->used && if (!if_tmp->used &&
(new = create_listeners(&if_tmp->addr, !!option_bool(OPT_TFTP), dienow))) (new = create_listeners(&if_tmp->addr, !!option_bool(OPT_TFTP), dienow)))
{ {
new->next = daemon->listeners; new->next = daemon->listeners;
daemon->listeners = new; daemon->listeners = new;
if (!dienow)
{
int port = prettyprint_addr(&if_tmp->addr, daemon->addrbuff);
my_syslog(LOG_DEBUG, _("listening on %s port %d"), daemon->addrbuff,
port);
}
} }
} }
/* In --bind-interfaces, the only access control is the addresses we're listenin g on. /* In --bind-interfaces, the only access control is the addresses we're listenin g on.
There's nothing to avoid a query to the address of an internal interface arri ving via There's nothing to avoid a query to the address of an internal interface arri ving via
an external interface where we don't want to accept queries, except that in t he usual an external interface where we don't want to accept queries, except that in t he usual
case the addresses of internal interfaces are RFC1918. When bind-interfaces i n use, case the addresses of internal interfaces are RFC1918. When bind-interfaces i n use,
and we listen on an address that looks like it's probably globally routeable, shout. and we listen on an address that looks like it's probably globally routeable, shout.
The fix is to use --bind-dynamic, which actually checks the arrival interface too. The fix is to use --bind-dynamic, which actually checks the arrival interface too.
skipping to change at line 1297 skipping to change at line 1401
if ((sfd = allocate_sfd(&addr, ""))) if ((sfd = allocate_sfd(&addr, "")))
sfd->preallocated = 1; sfd->preallocated = 1;
} }
for (srv = daemon->servers; srv; srv = srv->next) for (srv = daemon->servers; srv; srv = srv->next)
if (!(srv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)) && if (!(srv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)) &&
!allocate_sfd(&srv->source_addr, srv->interface) && !allocate_sfd(&srv->source_addr, srv->interface) &&
errno != 0 && errno != 0 &&
option_bool(OPT_NOWILD)) option_bool(OPT_NOWILD))
{ {
prettyprint_addr(&srv->source_addr, daemon->namebuff); (void)prettyprint_addr(&srv->source_addr, daemon->namebuff);
if (srv->interface[0] != 0) if (srv->interface[0] != 0)
{ {
strcat(daemon->namebuff, " "); strcat(daemon->namebuff, " ");
strcat(daemon->namebuff, srv->interface); strcat(daemon->namebuff, srv->interface);
} }
die(_("failed to bind server socket for %s: %s"), die(_("failed to bind server socket for %s: %s"),
daemon->namebuff, EC_BADNET); daemon->namebuff, EC_BADNET);
} }
} }
 End of changes. 15 change blocks. 
23 lines changed or deleted 128 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)