import of dnsmasq-2.5.tar.gz

This commit is contained in:
Simon Kelley
2004-03-16 18:35:52 +00:00
parent 1cff166d37
commit 8a911ccc75
12 changed files with 116 additions and 58 deletions

View File

@@ -843,5 +843,21 @@ release 2.4
Added "bind-interfaces" option correctly. Added "bind-interfaces" option correctly.
release 2.5
Made "where are we allocating addresses?" code in DHCP
server cope with requests via a relay which is on a
directly connected network for which there is not a
configured netmask. This strange state of affairs occurs
with win4lin. Thanks to Alex Melt and Jim Horner for bug
reports and testing with this.
Fixed trivial-but-irritating missing #include which broke
compilation on *BSD.
Force --bind-interfaces if IP-aliased interface
specifications are used, since the sockets API provides
no other sane way to determine which alias of an
interface a packet was sent to. Thanks to Javier Kohen
for the bug report.

View File

@@ -5,7 +5,7 @@
############################################################################### ###############################################################################
Name: dnsmasq Name: dnsmasq
Version: 2.4 Version: 2.5
Release: 1 Release: 1
Copyright: GPL Copyright: GPL
Group: System Environment/Daemons Group: System Environment/Daemons

View File

@@ -5,7 +5,7 @@
############################################################################### ###############################################################################
Name: dnsmasq Name: dnsmasq
Version: 2.4 Version: 2.5
Release: 1 Release: 1
Copyright: GPL Copyright: GPL
Group: System Environment/Daemons Group: System Environment/Daemons

View File

@@ -5,7 +5,7 @@
############################################################################### ###############################################################################
Name: dnsmasq Name: dnsmasq
Version: 2.4 Version: 2.5
Release: 1 Release: 1
Copyright: GPL Copyright: GPL
Group: Productivity/Networking/DNS/Servers Group: Productivity/Networking/DNS/Servers

View File

@@ -82,7 +82,14 @@ flags are given, dnsmasq listens on all available interfaces unless overridden b
.B \-a .B \-a
or or
.B \-I .B \-I
flags. flags. If IP alias interfaces (eg "eth1:0") are used with
.B --interface
or
.B --except-interface
options, then the
.B --bind-interfaces
option will be automatically set. This is required for deeply boring
sockets-API reasons.
.TP .TP
.B \-I, --except-interface=<interface name> .B \-I, --except-interface=<interface name>
Do not listen on the specified interface. Do not listen on the specified interface.
@@ -108,7 +115,9 @@ requests that it shouldn't reply to. This has the advantage of
working even when interfaces come and go and change address. This working even when interfaces come and go and change address. This
option forces dnsmasq to really bind only the interfaces it is option forces dnsmasq to really bind only the interfaces it is
listening on. About the only time when this is useful is when listening on. About the only time when this is useful is when
running another nameserver on the same machine. running another nameserver on the same machine or using IP
alias. Specifying interfaces with IP alias automatically turns this
option on.
.TP .TP
.B \-b, --bogus-priv .B \-b, --bogus-priv
Bogus private reverse lookups. All reverse lookups for private IP ranges (ie 192.168.x.x, etc) Bogus private reverse lookups. All reverse lookups for private IP ranges (ie 192.168.x.x, etc)

View File

@@ -12,7 +12,7 @@
/* Author's email: simon@thekelleys.org.uk */ /* Author's email: simon@thekelleys.org.uk */
#define VERSION "2.4" #define VERSION "2.5"
#define FTABSIZ 150 /* max number of outstanding requests */ #define FTABSIZ 150 /* max number of outstanding requests */
#define TIMEOUT 20 /* drop queries after TIMEOUT seconds */ #define TIMEOUT 20 /* drop queries after TIMEOUT seconds */

View File

@@ -75,7 +75,8 @@ void dhcp_packet(struct dhcp_context *contexts, char *packet,
struct iovec iov[2]; struct iovec iov[2];
struct cmsghdr *cmptr; struct cmsghdr *cmptr;
int sz, newlen, iface_index = 0; int sz, newlen, iface_index = 0;
struct in_addr source, real_netmask, iface_addr, netmask_save, broadcast_save; struct in_addr source, iface_netmask, iface_addr, iface_broadcast;
struct in_addr netmask_save, broadcast_save, router;
#ifdef HAVE_BPF #ifdef HAVE_BPF
unsigned char iface_hwaddr[ETHER_ADDR_LEN]; unsigned char iface_hwaddr[ETHER_ADDR_LEN];
#endif #endif
@@ -112,7 +113,8 @@ void dhcp_packet(struct dhcp_context *contexts, char *packet,
if (cmptr->cmsg_level == SOL_IP && cmptr->cmsg_type == IP_PKTINFO) if (cmptr->cmsg_level == SOL_IP && cmptr->cmsg_type == IP_PKTINFO)
iface_index = ((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_ifindex; iface_index = ((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_ifindex;
if (!iface_index || !if_indextoname(iface_index, ifr.ifr_name)) if (!(ifr.ifr_ifindex = iface_index) ||
ioctl(dhcp_fd, SIOCGIFNAME, &ifr) == -1)
return; return;
#elif defined(IP_RECVIF) #elif defined(IP_RECVIF)
@@ -169,17 +171,30 @@ void dhcp_packet(struct dhcp_context *contexts, char *packet,
/* If the packet came via a relay, use that address to look up the context, /* If the packet came via a relay, use that address to look up the context,
else use the address of the interface is arrived on. */ else use the address of the interface is arrived on. */
source = mess->giaddr.s_addr ? mess->giaddr : iface_addr; source = mess->giaddr.s_addr ? mess->giaddr : iface_addr;
iface_netmask.s_addr = 0;
iface_broadcast.s_addr = 0;
if (ioctl(dhcp_fd, SIOCGIFNETMASK, &ifr) != -1)
{
iface_netmask = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
/* we can use the interface netmask if either the packet came direct,
or it came via a relay listening on the same network. This sounds unlikely,
but it happens with win4lin. */
if ((source.s_addr & iface_netmask.s_addr) != (iface_addr.s_addr & iface_netmask.s_addr))
iface_netmask.s_addr = 0;
else if (ioctl(dhcp_fd, SIOCGIFBRDADDR, &ifr) != -1)
iface_broadcast = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
}
for (context = contexts; context; context = context->next) for (context = contexts; context; context = context->next)
{ {
if (!context->netmask.s_addr && !mess->giaddr.s_addr && ioctl(dhcp_fd, SIOCGIFNETMASK, &ifr) != -1) struct in_addr netmask = context->netmask.s_addr ? context->netmask : iface_netmask;
real_netmask = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
else if (netmask.s_addr &&
real_netmask = context->netmask; (source.s_addr & netmask.s_addr) == (context->start.s_addr & netmask.s_addr) &&
(source.s_addr & netmask.s_addr) == (context->end.s_addr & netmask.s_addr))
if (real_netmask.s_addr &&
(source.s_addr & real_netmask.s_addr) == (context->start.s_addr & real_netmask.s_addr) &&
(source.s_addr & real_netmask.s_addr) == (context->end.s_addr & real_netmask.s_addr))
break; break;
} }
@@ -192,26 +207,34 @@ void dhcp_packet(struct dhcp_context *contexts, char *packet,
netmask_save = context->netmask; netmask_save = context->netmask;
broadcast_save = context->broadcast; broadcast_save = context->broadcast;
context->netmask = real_netmask; if (!context->netmask.s_addr)
context->netmask = iface_netmask;
if (!context->broadcast.s_addr) if (!context->broadcast.s_addr)
{ {
if (mess->giaddr.s_addr) if (iface_broadcast.s_addr)
context->broadcast.s_addr = (mess->giaddr.s_addr & real_netmask.s_addr) | ~real_netmask.s_addr; context->broadcast = iface_broadcast;
else if (ioctl(dhcp_fd, SIOCGIFBRDADDR, &ifr) != -1)
context->broadcast = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
else else
context->broadcast.s_addr = (iface_addr.s_addr & real_netmask.s_addr) | ~real_netmask.s_addr; context->broadcast.s_addr = (source.s_addr & context->netmask.s_addr) | ~context->netmask.s_addr;
} }
if (ioctl(dhcp_fd, SIOCGIFMTU, &ifr) == -1) if (ioctl(dhcp_fd, SIOCGIFMTU, &ifr) == -1)
ifr.ifr_mtu = ETHERMTU; ifr.ifr_mtu = ETHERMTU;
/* Normally, we set the default route to point to the machine which is getting the
DHCP broadcast, either this machine or a relay. In the special case that the relay
is on the same network as us, we set the default route to us, not the relay.
This is the win4lin scenario again. */
if ((source.s_addr & context->netmask.s_addr) == (iface_addr.s_addr & context->netmask.s_addr))
router = iface_addr;
else
router = source;
lease_prune(NULL, now); /* lose any expired leases */ lease_prune(NULL, now); /* lose any expired leases */
newlen = dhcp_reply(context, iface_addr, ifr.ifr_name, ifr.ifr_mtu, newlen = dhcp_reply(context, iface_addr, ifr.ifr_name, ifr.ifr_mtu,
rawpacket, sz, now, namebuff, rawpacket, sz, now, namebuff,
dhcp_opts, dhcp_configs, domain_suffix, dhcp_file, dhcp_opts, dhcp_configs, domain_suffix, dhcp_file,
dhcp_sname, dhcp_next_server); dhcp_sname, dhcp_next_server, router);
lease_update_file(0, now); lease_update_file(0, now);
lease_update_dns(); lease_update_dns();

View File

@@ -40,6 +40,7 @@
# include <sys/sockio.h> # include <sys/sockio.h>
#endif #endif
#include <sys/time.h> #include <sys/time.h>
#include <limits.h>
#include <net/if.h> #include <net/if.h>
#include <unistd.h> #include <unistd.h>
#include <stdio.h> #include <stdio.h>
@@ -403,5 +404,5 @@ int dhcp_reply(struct dhcp_context *context,
unsigned int sz, time_t now, char *namebuff, unsigned int sz, time_t now, char *namebuff,
struct dhcp_opt *dhcp_opts, struct dhcp_config *dhcp_configs, struct dhcp_opt *dhcp_opts, struct dhcp_config *dhcp_configs,
char *domain_suffix, char *dhcp_file, char *dhcp_sname, char *domain_suffix, char *dhcp_file, char *dhcp_sname,
struct in_addr dhcp_next_server); struct in_addr dhcp_next_server, struct in_addr router);

View File

@@ -104,7 +104,6 @@ static void send_from(int fd, int nowild, char *packet, int len,
msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
cmptr->cmsg_type = IPV6_PKTINFO; cmptr->cmsg_type = IPV6_PKTINFO;
cmptr->cmsg_level = IPV6_LEVEL; cmptr->cmsg_level = IPV6_LEVEL;
cmptr->cmsg_level = IPPROTO_IPV6;
} }
#endif #endif
@@ -368,11 +367,10 @@ struct server *receive_query(struct listener *listen, char *packet, char *mxname
union mysockaddr source_addr; union mysockaddr source_addr;
struct iname *tmp; struct iname *tmp;
struct all_addr dst_addr; struct all_addr dst_addr;
int m, n, gotit = 0; int m, n, if_index = 0;
struct iovec iov[1]; struct iovec iov[1];
struct msghdr msg; struct msghdr msg;
struct cmsghdr *cmptr; struct cmsghdr *cmptr;
char if_name[IF_NAMESIZE];
union { union {
struct cmsghdr align; /* this ensures alignment */ struct cmsghdr align; /* this ensures alignment */
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
@@ -414,20 +412,16 @@ struct server *receive_query(struct listener *listen, char *packet, char *mxname
if (cmptr->cmsg_level == SOL_IP && cmptr->cmsg_type == IP_PKTINFO) if (cmptr->cmsg_level == SOL_IP && cmptr->cmsg_type == IP_PKTINFO)
{ {
dst_addr.addr.addr4 = ((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_spec_dst; dst_addr.addr.addr4 = ((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_spec_dst;
if_indextoname(((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_ifindex, if_name); if_index = ((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_ifindex;
gotit = 1;
} }
#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF) #elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
if (!(options & OPT_NOWILD) && listen->family == AF_INET) if (!(options & OPT_NOWILD) && listen->family == AF_INET)
{ {
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr)) for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR) if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR)
{ dst_addr.addr.addr4 = *((struct in_addr *)CMSG_DATA(cmptr));
dst_addr.addr.addr4 = *((struct in_addr *)CMSG_DATA(cmptr));
gotit = 1;
}
else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF) else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
if_indextoname(((struct sockaddr_dl *)CMSG_DATA(cmptr))->sdl_index, if_name); if_index = ((struct sockaddr_dl *)CMSG_DATA(cmptr))->sdl_index;
} }
#endif #endif
@@ -438,8 +432,7 @@ struct server *receive_query(struct listener *listen, char *packet, char *mxname
if (cmptr->cmsg_level == IPV6_LEVEL && cmptr->cmsg_type == IPV6_PKTINFO) if (cmptr->cmsg_level == IPV6_LEVEL && cmptr->cmsg_type == IPV6_PKTINFO)
{ {
dst_addr.addr.addr6 = ((struct in6_pktinfo *)CMSG_DATA(cmptr))->ipi6_addr; dst_addr.addr.addr6 = ((struct in6_pktinfo *)CMSG_DATA(cmptr))->ipi6_addr;
if_indextoname(((struct in6_pktinfo *)CMSG_DATA(cmptr))->ipi6_ifindex, if_name); if_index =((struct in6_pktinfo *)CMSG_DATA(cmptr))->ipi6_ifindex;
gotit = 1;
} }
} }
#endif #endif
@@ -450,17 +443,31 @@ struct server *receive_query(struct listener *listen, char *packet, char *mxname
/* enforce available interface configuration */ /* enforce available interface configuration */
if (!(options & OPT_NOWILD)) if (!(options & OPT_NOWILD))
{ {
if (!gotit) struct ifreq ifr;
if (if_index == 0)
return last_server; return last_server;
if (except || names)
{
#ifdef SIOCGIFNAME
ifr.ifr_ifindex = if_index;
if (ioctl(listen->fd, SIOCGIFNAME, &ifr) == -1)
return last_server;
#else
if (!if_indextoname(if_index, ifr.ifr_name))
return last_server;
#endif
}
for (tmp = except; tmp; tmp = tmp->next) for (tmp = except; tmp; tmp = tmp->next)
if (tmp->name && (strcmp(tmp->name, if_name) == 0)) if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
return last_server; return last_server;
if (names || addrs) if (names || addrs)
{ {
for (tmp = names; tmp; tmp = tmp->next) for (tmp = names; tmp; tmp = tmp->next)
if (tmp->name && (strcmp(tmp->name, if_name) == 0)) if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
break; break;
if (!tmp) if (!tmp)
for (tmp = addrs; tmp; tmp = tmp->next) for (tmp = addrs; tmp; tmp = tmp->next)

View File

@@ -145,7 +145,7 @@ struct irec *enumerate_interfaces(struct iname *names,
lo->next = names->next; lo->next = names->next;
names->next = lo; names->next = lo;
} }
if ((new = add_iface(iface, ifr->ifr_name, if ((new = add_iface(iface, ifr->ifr_name,
&addr, names, addrs, except))) &addr, names, addrs, except)))
{ {

View File

@@ -165,7 +165,6 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
char *conffile = CONFFILE; char *conffile = CONFFILE;
int conffile_set = 0; int conffile_set = 0;
int lineno = 0; int lineno = 0;
opterr = 0; opterr = 0;
*min_leasetime = UINT_MAX; *min_leasetime = UINT_MAX;
@@ -359,6 +358,8 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
/* new->name may be NULL if someone does /* new->name may be NULL if someone does
"interface=" to disable all interfaces except loop. */ "interface=" to disable all interfaces except loop. */
new->name = safe_string_alloc(optarg); new->name = safe_string_alloc(optarg);
if (strchr(optarg, ':'))
flags |= OPT_NOWILD;
break; break;
} }
@@ -368,6 +369,8 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
new->next = *if_except; new->next = *if_except;
*if_except = new; *if_except = new;
new->name = safe_string_alloc(optarg); new->name = safe_string_alloc(optarg);
if (strchr(optarg, ':'))
flags |= OPT_NOWILD;
break; break;
} }
@@ -684,14 +687,13 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
} }
new->lease_time = atoi(a[leasepos]) * fac; new->lease_time = atoi(a[leasepos]) * fac;
if (new->lease_time < *min_leasetime)
*min_leasetime = new->lease_time;
} }
} }
} }
new->last = new->start; new->last = new->start;
if (new->lease_time < *min_leasetime)
*min_leasetime = new->lease_time;
break; break;
} }
@@ -803,17 +805,17 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
new->hostname = safe_string_alloc(a[j]); new->hostname = safe_string_alloc(a[j]);
} }
else else
{ new->lease_time = atoi(a[j]) * fac;
new->lease_time = atoi(a[j]) * fac;
if (new->lease_time < *min_leasetime)
*min_leasetime = new->lease_time;
}
} }
if (option == '?') if (option == '?')
free(new); free(new);
else else
*dhcp_conf = new; {
if (new->lease_time < *min_leasetime)
*min_leasetime = new->lease_time;
*dhcp_conf = new;
}
break; break;
} }
@@ -1023,7 +1025,7 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
*resolv_files = 0; *resolv_files = 0;
else if (*resolv_files && (*resolv_files)->next && (flags & OPT_NO_POLL)) else if (*resolv_files && (*resolv_files)->next && (flags & OPT_NO_POLL))
die("only one resolv.conf file allowed in no-poll mode.", NULL); die("only one resolv.conf file allowed in no-poll mode.", NULL);
return flags; return flags;
} }

View File

@@ -61,7 +61,7 @@ static unsigned char *do_req_options(struct dhcp_context *context,
unsigned char *req_options, unsigned char *req_options,
struct dhcp_opt *config_opts, struct dhcp_opt *config_opts,
char *domainname, char *hostname, char *domainname, char *hostname,
struct in_addr relay, struct in_addr router,
struct in_addr iface_addr, struct in_addr iface_addr,
int iface_mtu); int iface_mtu);
@@ -74,7 +74,7 @@ int dhcp_reply(struct dhcp_context *context,
unsigned int sz, time_t now, char *namebuff, unsigned int sz, time_t now, char *namebuff,
struct dhcp_opt *dhcp_opts, struct dhcp_config *dhcp_configs, struct dhcp_opt *dhcp_opts, struct dhcp_config *dhcp_configs,
char *domain_suffix, char *dhcp_file, char *dhcp_sname, char *domain_suffix, char *dhcp_file, char *dhcp_sname,
struct in_addr dhcp_next_server) struct in_addr dhcp_next_server, struct in_addr router)
{ {
unsigned char *opt, *clid; unsigned char *opt, *clid;
struct dhcp_lease *lease; struct dhcp_lease *lease;
@@ -265,7 +265,7 @@ int dhcp_reply(struct dhcp_context *context,
p = option_put(p, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(iface_addr.s_addr)); p = option_put(p, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(iface_addr.s_addr));
p = option_put(p, end, OPTION_LEASE_TIME, 4, expires_time); p = option_put(p, end, OPTION_LEASE_TIME, 4, expires_time);
p = do_req_options(context, p, end, req_options, dhcp_opts, domain_suffix, p = do_req_options(context, p, end, req_options, dhcp_opts, domain_suffix,
NULL, mess->giaddr, iface_addr, iface_mtu); NULL, router, iface_addr, iface_mtu);
p = option_put(p, end, OPTION_END, 0, 0); p = option_put(p, end, OPTION_END, 0, 0);
log_packet("OFFER" , &mess->yiaddr, mess->chaddr, iface_name, NULL); log_packet("OFFER" , &mess->yiaddr, mess->chaddr, iface_name, NULL);
@@ -354,7 +354,7 @@ int dhcp_reply(struct dhcp_context *context,
p = option_put(p, end, OPTION_T2, 4, ((renewal_time * 7)/8) - fuzz); p = option_put(p, end, OPTION_T2, 4, ((renewal_time * 7)/8) - fuzz);
} }
p = do_req_options(context, p, end, req_options, dhcp_opts, domain_suffix, p = do_req_options(context, p, end, req_options, dhcp_opts, domain_suffix,
hostname, mess->giaddr, iface_addr, iface_mtu); hostname, router, iface_addr, iface_mtu);
p = option_put(p, end, OPTION_END, 0, 0); p = option_put(p, end, OPTION_END, 0, 0);
return p - (unsigned char *)mess; return p - (unsigned char *)mess;
@@ -364,7 +364,7 @@ int dhcp_reply(struct dhcp_context *context,
p = option_put(p, end, OPTION_MESSAGE_TYPE, 1, DHCPACK); p = option_put(p, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
p = option_put(p, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(iface_addr.s_addr)); p = option_put(p, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(iface_addr.s_addr));
p = do_req_options(context, p, end, req_options, dhcp_opts, domain_suffix, p = do_req_options(context, p, end, req_options, dhcp_opts, domain_suffix,
hostname, mess->giaddr, iface_addr, iface_mtu); hostname, router, iface_addr, iface_mtu);
p = option_put(p, end, OPTION_END, 0, 0); p = option_put(p, end, OPTION_END, 0, 0);
log_packet("ACK", &mess->ciaddr, mess->chaddr, iface_name, hostname); log_packet("ACK", &mess->ciaddr, mess->chaddr, iface_name, hostname);
@@ -538,7 +538,7 @@ static unsigned char *do_req_options(struct dhcp_context *context,
unsigned char *req_options, unsigned char *req_options,
struct dhcp_opt *config_opts, struct dhcp_opt *config_opts,
char *domainname, char *hostname, char *domainname, char *hostname,
struct in_addr relay, struct in_addr router,
struct in_addr iface_addr, struct in_addr iface_addr,
int iface_mtu) int iface_mtu)
{ {
@@ -563,7 +563,7 @@ static unsigned char *do_req_options(struct dhcp_context *context,
if (in_list(req_options, OPTION_ROUTER) && if (in_list(req_options, OPTION_ROUTER) &&
!option_find2(context, config_opts, OPTION_ROUTER)) !option_find2(context, config_opts, OPTION_ROUTER))
p = option_put(p, end, OPTION_ROUTER, INADDRSZ, p = option_put(p, end, OPTION_ROUTER, INADDRSZ,
ntohl(relay.s_addr ? relay.s_addr : iface_addr.s_addr )); ntohl(router.s_addr));
if (in_list(req_options, OPTION_DNSSERVER) && if (in_list(req_options, OPTION_DNSSERVER) &&
!option_find2(context, config_opts, OPTION_DNSSERVER)) !option_find2(context, config_opts, OPTION_DNSSERVER))