mirror of
http://thekelleys.org.uk/git/dnsmasq.git
synced 2026-10-31 13:10:35 +00:00
import of dnsmasq-2.32.tar.gz
This commit is contained in:
1 parent
7cebd20fe7
commit
849a8357ba
24 files changed
+6621
-4429
No files matched your search
@@ -26,17 +26,6 @@ static struct iovec ifreq = {
|
||||
.iov_len = 0
|
||||
};
|
||||
|
||||
struct header {
|
||||
struct ether_header ether;
|
||||
struct ip ip;
|
||||
struct udphdr {
|
||||
u16 uh_sport; /* source port */
|
||||
u16 uh_dport; /* destination port */
|
||||
u16 uh_ulen; /* udp length */
|
||||
u16 uh_sum; /* udp checksum */
|
||||
} udp;
|
||||
};
|
||||
|
||||
void init_bpf(struct daemon *daemon)
|
||||
{
|
||||
int i = 0;
|
||||
@@ -69,9 +58,17 @@ void send_via_bpf(struct daemon *daemon, struct dhcp_packet *mess, size_t len,
|
||||
Build the packet by steam, and send directly, bypassing
|
||||
the kernel IP stack */
|
||||
|
||||
struct header header;
|
||||
struct ether_header ether;
|
||||
struct ip ip;
|
||||
struct udphdr {
|
||||
u16 uh_sport; /* source port */
|
||||
u16 uh_dport; /* destination port */
|
||||
u16 uh_ulen; /* udp length */
|
||||
u16 uh_sum; /* udp checksum */
|
||||
} udp;
|
||||
|
||||
u32 i, sum;
|
||||
struct iovec iov[2];
|
||||
struct iovec iov[4];
|
||||
|
||||
/* Only know how to do ethernet on *BSD */
|
||||
if (mess->htype != ARPHRD_ETHER || mess->hlen != ETHER_ADDR_LEN)
|
||||
@@ -85,62 +82,67 @@ void send_via_bpf(struct daemon *daemon, struct dhcp_packet *mess, size_t len,
|
||||
if (ioctl(daemon->dhcpfd, SIOCGIFADDR, ifr) < 0)
|
||||
return;
|
||||
|
||||
memcpy(header.ether.ether_shost, LLADDR((struct sockaddr_dl *)&ifr->ifr_addr), ETHER_ADDR_LEN);
|
||||
header.ether.ether_type = htons(ETHERTYPE_IP);
|
||||
memcpy(ether.ether_shost, LLADDR((struct sockaddr_dl *)&ifr->ifr_addr), ETHER_ADDR_LEN);
|
||||
ether.ether_type = htons(ETHERTYPE_IP);
|
||||
|
||||
if (ntohs(mess->flags) & 0x8000)
|
||||
{
|
||||
memset(header.ether.ether_dhost, 255, ETHER_ADDR_LEN);
|
||||
header.ip.ip_dst.s_addr = INADDR_BROADCAST;
|
||||
memset(ether.ether_dhost, 255, ETHER_ADDR_LEN);
|
||||
ip.ip_dst.s_addr = INADDR_BROADCAST;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(header.ether.ether_dhost, mess->chaddr, ETHER_ADDR_LEN);
|
||||
header.ip.ip_dst.s_addr = mess->yiaddr.s_addr;
|
||||
memcpy(ether.ether_dhost, mess->chaddr, ETHER_ADDR_LEN);
|
||||
ip.ip_dst.s_addr = mess->yiaddr.s_addr;
|
||||
}
|
||||
|
||||
header.ip.ip_p = IPPROTO_UDP;
|
||||
header.ip.ip_src.s_addr = iface_addr.s_addr;
|
||||
header.ip.ip_len = htons(sizeof(struct ip) +
|
||||
sizeof(struct udphdr) +
|
||||
len) ;
|
||||
header.ip.ip_hl = sizeof(struct ip) / 4;
|
||||
header.ip.ip_v = IPVERSION;
|
||||
header.ip.ip_tos = 0;
|
||||
header.ip.ip_id = htons(0);
|
||||
header.ip.ip_off = htons(0x4000); /* don't fragment */
|
||||
header.ip.ip_ttl = IPDEFTTL;
|
||||
header.ip.ip_sum = 0;
|
||||
ip.ip_p = IPPROTO_UDP;
|
||||
ip.ip_src.s_addr = iface_addr.s_addr;
|
||||
ip.ip_len = htons(sizeof(struct ip) +
|
||||
sizeof(struct udphdr) +
|
||||
len) ;
|
||||
ip.ip_hl = sizeof(struct ip) / 4;
|
||||
ip.ip_v = IPVERSION;
|
||||
ip.ip_tos = 0;
|
||||
ip.ip_id = htons(0);
|
||||
ip.ip_off = htons(0x4000); /* don't fragment */
|
||||
ip.ip_ttl = IPDEFTTL;
|
||||
ip.ip_sum = 0;
|
||||
for (sum = 0, i = 0; i < sizeof(struct ip) / 2; i++)
|
||||
sum += ((u16 *)&header.ip)[i];
|
||||
sum += ((u16 *)&ip)[i];
|
||||
while (sum>>16)
|
||||
sum = (sum & 0xffff) + (sum >> 16);
|
||||
header.ip.ip_sum = (sum == 0xffff) ? sum : ~sum;
|
||||
ip.ip_sum = (sum == 0xffff) ? sum : ~sum;
|
||||
|
||||
header.udp.uh_sport = htons(DHCP_SERVER_PORT);
|
||||
header.udp.uh_dport = htons(DHCP_CLIENT_PORT);
|
||||
udp.uh_sport = htons(DHCP_SERVER_PORT);
|
||||
udp.uh_dport = htons(DHCP_CLIENT_PORT);
|
||||
if (len & 1)
|
||||
((char *)mess)[len] = 0; /* for checksum, in case length is odd. */
|
||||
header.udp.uh_sum = 0;
|
||||
header.udp.uh_ulen = sum = htons(sizeof(struct udphdr) + len);
|
||||
udp.uh_sum = 0;
|
||||
udp.uh_ulen = sum = htons(sizeof(struct udphdr) + len);
|
||||
sum += htons(IPPROTO_UDP);
|
||||
for (i = 0; i < 4; i++)
|
||||
sum += ((u16 *)&header.ip.ip_src)[i];
|
||||
sum += ((u16 *)&ip.ip_src)[i];
|
||||
for (i = 0; i < sizeof(struct udphdr)/2; i++)
|
||||
sum += ((u16 *)&header.udp)[i];
|
||||
sum += ((u16 *)&udp)[i];
|
||||
for (i = 0; i < (len + 1) / 2; i++)
|
||||
sum += ((u16 *)mess)[i];
|
||||
while (sum>>16)
|
||||
sum = (sum & 0xffff) + (sum >> 16);
|
||||
header.udp.uh_sum = (sum == 0xffff) ? sum : ~sum;
|
||||
udp.uh_sum = (sum == 0xffff) ? sum : ~sum;
|
||||
|
||||
ioctl(daemon->dhcp_raw_fd, BIOCSETIF, ifr);
|
||||
|
||||
iov[0].iov_base = &header;
|
||||
iov[0].iov_len = sizeof(struct header);
|
||||
iov[1].iov_base = mess;
|
||||
iov[1].iov_len = len;
|
||||
while (writev(daemon->dhcp_raw_fd, iov, 2) == -1 && retry_send());
|
||||
iov[0].iov_base = ðer;
|
||||
iov[0].iov_len = sizeof(ether);
|
||||
iov[1].iov_base = &ip;
|
||||
iov[1].iov_len = sizeof(ip);
|
||||
iov[2].iov_base = &udp;
|
||||
iov[2].iov_len = sizeof(udp);
|
||||
iov[3].iov_base = mess;
|
||||
iov[3].iov_len = len;
|
||||
|
||||
while (writev(daemon->dhcp_raw_fd, iov, 4) == -1 && retry_send());
|
||||
}
|
||||
|
||||
int iface_enumerate(struct daemon *daemon, void *parm, int (*ipv4_callback)(), int (*ipv6_callback)())
|
||||
@@ -150,31 +152,33 @@ int iface_enumerate(struct daemon *daemon, void *parm, int (*ipv4_callback)(), i
|
||||
struct ifconf ifc;
|
||||
int fd, errsav, ret = 0;
|
||||
int lastlen = 0;
|
||||
size_t len;
|
||||
size_t len = 0;
|
||||
|
||||
if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
|
||||
return 0;
|
||||
|
||||
for (len = 0; ; len += 10*sizeof(struct ifreq))
|
||||
|
||||
while(1)
|
||||
{
|
||||
if (!expand_buf(&ifconf, len))
|
||||
goto err;
|
||||
|
||||
ifc.ifc_len = len;
|
||||
ifc.ifc_buf = ifconf.iov_base;
|
||||
|
||||
if (ioctl(fd, SIOCGIFCONF, &ifc) == -1)
|
||||
{
|
||||
if (errno != EINVAL || lastlen != 0)
|
||||
goto err;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ifc.ifc_len == lastlen)
|
||||
break; /* got a big enough buffer now */
|
||||
lastlen = ifc.ifc_len;
|
||||
}
|
||||
}
|
||||
len += 10*sizeof(struct ifreq);
|
||||
|
||||
if (!expand_buf(&ifconf, len))
|
||||
goto err;
|
||||
|
||||
ifc.ifc_len = len;
|
||||
ifc.ifc_buf = ifconf.iov_base;
|
||||
|
||||
if (ioctl(fd, SIOCGIFCONF, &ifc) == -1)
|
||||
{
|
||||
if (errno != EINVAL || lastlen != 0)
|
||||
goto err;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ifc.ifc_len == lastlen)
|
||||
break; /* got a big enough buffer now */
|
||||
lastlen = ifc.ifc_len;
|
||||
}
|
||||
}
|
||||
|
||||
for (ptr = ifc.ifc_buf; ptr < ifc.ifc_buf + ifc.ifc_len; ptr += len )
|
||||
{
|
||||
|
||||
+2
-15
@@ -10,7 +10,7 @@
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#define VERSION "2.31"
|
||||
#define VERSION "2.32"
|
||||
|
||||
#define FTABSIZ 150 /* max number of outstanding requests */
|
||||
#define MAX_PROCS 20 /* max no children for TCP requests */
|
||||
@@ -23,6 +23,7 @@
|
||||
#define MAXLEASES 150 /* maximum number of DHCP leases */
|
||||
#define PING_WAIT 3 /* wait for ping address-in-use test */
|
||||
#define PING_CACHE_TIME 30 /* Ping test assumed to be valid this long. */
|
||||
#define DECLINE_BACKOFF 600 /* disable DECLINEd static addresses for this long */
|
||||
#define DHCP_PACKET_MAX 16384 /* hard limit on DHCP packet size */
|
||||
#define SMALLDNAME 40 /* most domain names are smaller than this */
|
||||
#define HOSTSFILE "/etc/hosts"
|
||||
@@ -53,20 +54,6 @@
|
||||
#define DNSMASQ_SERVICE "uk.org.thekelleys.dnsmasq"
|
||||
#define DNSMASQ_PATH "/uk/org/thekelleys/dnsmasq"
|
||||
|
||||
/* Logfile stuff - change this to change the options and facility */
|
||||
/* debug is true if the --no-daemon flag is given */
|
||||
#ifdef LOG_PERROR
|
||||
# define DNSMASQ_LOG_OPT(debug) (debug) ? LOG_PERROR : LOG_PID
|
||||
#else
|
||||
# define DNSMASQ_LOG_OPT(debug) (debug) ? 0 : LOG_PID
|
||||
#endif
|
||||
|
||||
#ifdef LOG_LOCAL0
|
||||
# define DNSMASQ_LOG_FAC(debug) (debug) ? LOG_LOCAL0 : LOG_DAEMON
|
||||
#else
|
||||
# define DNSMASQ_LOG_FAC(debug) LOG_DAEMON
|
||||
#endif
|
||||
|
||||
/* A small collection of RR-types which are missing on some platforms */
|
||||
|
||||
#ifndef T_SRV
|
||||
|
||||
+40
-20
@@ -47,6 +47,7 @@ void dhcp_init(struct daemon *daemon)
|
||||
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &oneopt, sizeof(oneopt)) == -1)
|
||||
die(_("failed to set SO_REUSEADDR on DHCP socket: %s"), NULL);
|
||||
|
||||
memset(&saddr, 0, sizeof(saddr));
|
||||
saddr.sin_family = AF_INET;
|
||||
saddr.sin_port = htons(DHCP_SERVER_PORT);
|
||||
saddr.sin_addr.s_addr = INADDR_ANY;
|
||||
@@ -237,9 +238,10 @@ void dhcp_packet(struct daemon *daemon, time_t now)
|
||||
dest.sin_port = htons(DHCP_CLIENT_PORT);
|
||||
}
|
||||
#ifdef HAVE_LINUX_NETWORK
|
||||
else if (ntohs(mess->flags) & 0x8000)
|
||||
else if ((ntohs(mess->flags) & 0x8000) || mess->hlen == 0 ||
|
||||
mess->hlen > sizeof(ifr.ifr_addr.sa_data) || mess->htype == 0)
|
||||
{
|
||||
/* broadcast to 255.255.255.255 */
|
||||
/* broadcast to 255.255.255.255 (or mac address invalid) */
|
||||
struct in_pktinfo *pkt;
|
||||
msg.msg_control = control_u.control;
|
||||
msg.msg_controllen = sizeof(control_u);
|
||||
@@ -255,21 +257,17 @@ void dhcp_packet(struct daemon *daemon, time_t now)
|
||||
}
|
||||
else
|
||||
{
|
||||
/* unicast to unconfigured client */
|
||||
/* unicast to unconfigured client. Inject mac address direct into ARP cache.
|
||||
struct sockaddr limits size to 14 bytes. */
|
||||
struct arpreq req;
|
||||
dest.sin_addr = mess->yiaddr;
|
||||
dest.sin_port = htons(DHCP_CLIENT_PORT);
|
||||
if (mess->hlen != 0 && mess->hlen <= 14 && mess->htype != 0)
|
||||
{
|
||||
/* inject mac address direct into ARP cache.
|
||||
struct sockaddr limits size to 14 bytes. */
|
||||
struct arpreq req;
|
||||
*((struct sockaddr_in *)&req.arp_pa) = dest;
|
||||
req.arp_ha.sa_family = mess->htype;
|
||||
memcpy(req.arp_ha.sa_data, mess->chaddr, mess->hlen);
|
||||
strncpy(req.arp_dev, ifr.ifr_name, 16);
|
||||
req.arp_flags = ATF_COM;
|
||||
ioctl(daemon->dhcpfd, SIOCSARP, &req);
|
||||
}
|
||||
*((struct sockaddr_in *)&req.arp_pa) = dest;
|
||||
req.arp_ha.sa_family = mess->htype;
|
||||
memcpy(req.arp_ha.sa_data, mess->chaddr, mess->hlen);
|
||||
strncpy(req.arp_dev, ifr.ifr_name, 16);
|
||||
req.arp_flags = ATF_COM;
|
||||
ioctl(daemon->dhcpfd, SIOCSARP, &req);
|
||||
}
|
||||
#else
|
||||
else
|
||||
@@ -366,7 +364,7 @@ struct dhcp_context *address_available(struct dhcp_context *context, struct in_a
|
||||
struct dhcp_context *tmp;
|
||||
|
||||
for (tmp = context; tmp; tmp = tmp->current)
|
||||
if (taddr.s_addr == context->local.s_addr)
|
||||
if (taddr.s_addr == context->router.s_addr)
|
||||
return NULL;
|
||||
|
||||
for (tmp = context; tmp; tmp = tmp->current)
|
||||
@@ -481,7 +479,7 @@ int address_allocate(struct dhcp_context *context, struct daemon *daemon,
|
||||
do {
|
||||
/* eliminate addresses in use by the server. */
|
||||
for (d = context; d; d = d->current)
|
||||
if (addr.s_addr == d->local.s_addr)
|
||||
if (addr.s_addr == d->router.s_addr)
|
||||
break;
|
||||
|
||||
if (!d &&
|
||||
@@ -622,6 +620,7 @@ void dhcp_read_ethers(struct daemon *daemon)
|
||||
char *ip, *cp;
|
||||
struct in_addr addr;
|
||||
unsigned char hwaddr[ETHER_ADDR_LEN];
|
||||
struct dhcp_config **up, *tmp;
|
||||
struct dhcp_config *config, *configs = daemon->dhcp_conf;
|
||||
int count = 0, lineno = 0;
|
||||
|
||||
@@ -633,6 +632,22 @@ void dhcp_read_ethers(struct daemon *daemon)
|
||||
return;
|
||||
}
|
||||
|
||||
/* This can be called again on SIGHUP, so remove entries created last time round. */
|
||||
for (up = &daemon->dhcp_conf, config = configs; config; config = tmp)
|
||||
{
|
||||
tmp = config->next;
|
||||
if (config->flags & CONFIG_FROM_ETHERS)
|
||||
{
|
||||
*up = tmp;
|
||||
/* cannot have a clid */
|
||||
if (config->flags & CONFIG_NAME)
|
||||
free(config->hostname);
|
||||
free(config);
|
||||
}
|
||||
else
|
||||
up = &config->next;
|
||||
}
|
||||
|
||||
while (fgets(buff, MAXDNAME, f))
|
||||
{
|
||||
lineno++;
|
||||
@@ -700,7 +715,7 @@ void dhcp_read_ethers(struct daemon *daemon)
|
||||
{
|
||||
if (!(config = malloc(sizeof(struct dhcp_config))))
|
||||
continue;
|
||||
config->flags = 0;
|
||||
config->flags = CONFIG_FROM_ETHERS;
|
||||
config->wildcard_mask = 0;
|
||||
config->next = configs;
|
||||
configs = config;
|
||||
@@ -740,10 +755,15 @@ void dhcp_update_configs(struct dhcp_config *configs)
|
||||
This goes through /etc/hosts and sets static addresses for any DHCP config
|
||||
records which don't have an address and whose name matches.
|
||||
We take care to maintain the invariant that any IP address can appear
|
||||
in at most one dhcp-host. */
|
||||
in at most one dhcp-host. Since /etc/hosts can be re-read by SIGHUP,
|
||||
restore the status-quo ante first. */
|
||||
|
||||
struct dhcp_config *config;
|
||||
struct crec *crec;
|
||||
|
||||
for (config = configs; config; config = config->next)
|
||||
if (config->flags & CONFIG_ADDR_HOSTS)
|
||||
config->flags &= ~(CONFIG_ADDR | CONFIG_ADDR_HOSTS);
|
||||
|
||||
for (config = configs; config; config = config->next)
|
||||
if (!(config->flags & CONFIG_ADDR) &&
|
||||
@@ -757,7 +777,7 @@ void dhcp_update_configs(struct dhcp_config *configs)
|
||||
else
|
||||
{
|
||||
config->addr = crec->addr.addr.addr.addr4;
|
||||
config->flags |= CONFIG_ADDR;
|
||||
config->flags |= CONFIG_ADDR | CONFIG_ADDR_HOSTS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+39
-31
@@ -128,7 +128,6 @@ int main (int argc, char **argv)
|
||||
else if (!(daemon->listeners = create_wildcard_listeners(daemon->port)))
|
||||
die(_("failed to create listening socket: %s"), NULL);
|
||||
|
||||
forward_init(1);
|
||||
cache_init(daemon->cachesize, daemon->options & OPT_LOG);
|
||||
|
||||
now = dnsmasq_time();
|
||||
@@ -167,6 +166,7 @@ int main (int argc, char **argv)
|
||||
if (daemon->query_port)
|
||||
{
|
||||
union mysockaddr addr;
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.in.sin_family = AF_INET;
|
||||
addr.in.sin_addr.s_addr = INADDR_ANY;
|
||||
addr.in.sin_port = htons(daemon->query_port);
|
||||
@@ -175,11 +175,10 @@ int main (int argc, char **argv)
|
||||
#endif
|
||||
allocate_sfd(&addr, &daemon->sfds);
|
||||
#ifdef HAVE_IPV6
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.in6.sin6_family = AF_INET6;
|
||||
addr.in6.sin6_addr = in6addr_any;
|
||||
addr.in6.sin6_port = htons(daemon->query_port);
|
||||
addr.in6.sin6_flowinfo = 0;
|
||||
addr.in6.sin6_scope_id = 0;
|
||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||
addr.in6.sin6_len = sizeof(struct sockaddr_in6);
|
||||
#endif
|
||||
@@ -197,7 +196,19 @@ int main (int argc, char **argv)
|
||||
sig = SIGHUP;
|
||||
write(pipewrite, &sig, 1);
|
||||
|
||||
if (!(daemon->options & OPT_DEBUG))
|
||||
if (daemon->options & OPT_DEBUG)
|
||||
{
|
||||
#ifdef LOG_PERROR
|
||||
openlog("dnsmasq", LOG_PERROR, daemon->log_fac);
|
||||
#else
|
||||
openlog("dnsmasq", 0, daemon->log_fac);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LINUX_NETWORK
|
||||
prctl(PR_SET_DUMPABLE, 1);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
FILE *pidfile;
|
||||
struct passwd *ent_pw = daemon->username ? getpwnam(daemon->username) : NULL;
|
||||
@@ -322,16 +333,10 @@ int main (int argc, char **argv)
|
||||
capset(hdr, data);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#ifdef HAVE_LINUX_NETWORK
|
||||
else
|
||||
prctl(PR_SET_DUMPABLE, 1);
|
||||
#endif
|
||||
|
||||
openlog("dnsmasq",
|
||||
DNSMASQ_LOG_OPT(daemon->options & OPT_DEBUG),
|
||||
DNSMASQ_LOG_FAC(daemon->options & OPT_DEBUG));
|
||||
|
||||
openlog("dnsmasq", LOG_PID, daemon->log_fac);
|
||||
}
|
||||
|
||||
if (daemon->cachesize != 0)
|
||||
syslog(LOG_INFO, _("started, version %s cachesize %d"), VERSION, daemon->cachesize);
|
||||
else
|
||||
@@ -444,7 +449,7 @@ int main (int argc, char **argv)
|
||||
|
||||
/* Check for changes to resolv files once per second max. */
|
||||
/* Don't go silent for long periods if the clock goes backwards. */
|
||||
if (last == 0 || difftime(now, last) > 1.0 || difftime(now, last) < 1.0)
|
||||
if (last == 0 || difftime(now, last) > 1.0 || difftime(now, last) < -1.0)
|
||||
{
|
||||
last = now;
|
||||
|
||||
@@ -472,14 +477,11 @@ int main (int argc, char **argv)
|
||||
else
|
||||
{
|
||||
res->logged = 0;
|
||||
if (statbuf.st_mtime != res->mtime)
|
||||
if (statbuf.st_mtime != res->mtime &&
|
||||
difftime(statbuf.st_mtime, last_change) > 0.0)
|
||||
{
|
||||
res->mtime = statbuf.st_mtime;
|
||||
if (difftime(res->mtime, last_change) > 0.0)
|
||||
{
|
||||
last_change = res->mtime;
|
||||
latest = res;
|
||||
}
|
||||
last_change = statbuf.st_mtime;
|
||||
latest = res;
|
||||
}
|
||||
}
|
||||
res = res->next;
|
||||
@@ -487,8 +489,19 @@ int main (int argc, char **argv)
|
||||
|
||||
if (latest)
|
||||
{
|
||||
reload_servers(latest->name, daemon);
|
||||
check_servers(daemon);
|
||||
static int warned = 0;
|
||||
if (reload_servers(latest->name, daemon))
|
||||
{
|
||||
syslog(LOG_INFO, _("reading %s"), latest->name);
|
||||
latest->mtime = last_change;
|
||||
warned = 0;
|
||||
check_servers(daemon);
|
||||
}
|
||||
else if (!warned)
|
||||
{
|
||||
syslog(LOG_WARNING, _("no servers found in %s, will retry"), latest->name);
|
||||
warned = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -529,16 +542,11 @@ int main (int argc, char **argv)
|
||||
/* Knock all our children on the head. */
|
||||
for (i = 0; i < MAX_PROCS; i++)
|
||||
if (daemon->tcp_pids[i] != 0)
|
||||
kill(daemon->tcp_pids[i], SIGQUIT);
|
||||
kill(daemon->tcp_pids[i], SIGALRM);
|
||||
|
||||
if (daemon->dhcp)
|
||||
{
|
||||
if (daemon->script_pid != 0)
|
||||
kill(daemon->script_pid, SIGQUIT);
|
||||
/* close this carefully */
|
||||
fclose(daemon->lease_stream);
|
||||
}
|
||||
|
||||
fclose(daemon->lease_stream);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
+9
-4
@@ -16,8 +16,6 @@
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
/* get this before config.h too. */
|
||||
#include <syslog.h>
|
||||
#ifdef __APPLE__
|
||||
/* need this before arpa/nameser.h */
|
||||
# define BIND_8_COMPAT
|
||||
@@ -69,6 +67,8 @@
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip_icmp.h>
|
||||
#include <sys/uio.h>
|
||||
#include <syslog.h>
|
||||
#include <dirent.h>
|
||||
#ifndef HAVE_LINUX_NETWORK
|
||||
# include <net/if_dl.h>
|
||||
#endif
|
||||
@@ -319,6 +319,7 @@ struct dhcp_config {
|
||||
char *hostname;
|
||||
struct dhcp_netid netid;
|
||||
struct in_addr addr;
|
||||
time_t decline_time;
|
||||
unsigned int lease_time, wildcard_mask;
|
||||
struct dhcp_config *next;
|
||||
};
|
||||
@@ -331,6 +332,9 @@ struct dhcp_config {
|
||||
#define CONFIG_ADDR 32
|
||||
#define CONFIG_NETID 64
|
||||
#define CONFIG_NOCLID 128
|
||||
#define CONFIG_FROM_ETHERS 256 /* entry created by /etc/ethers */
|
||||
#define CONFIG_ADDR_HOSTS 512 /* address added by from /etc/hosts */
|
||||
#define CONFIG_DECLINED 1024 /* address declined by client */
|
||||
|
||||
struct dhcp_opt {
|
||||
int opt, len, flags;
|
||||
@@ -417,6 +421,7 @@ struct daemon {
|
||||
struct iname *if_names, *if_addrs, *if_except, *dhcp_except;
|
||||
struct bogus_addr *bogus_addr;
|
||||
struct server *servers;
|
||||
int log_fac; /* log facility */
|
||||
int cachesize;
|
||||
int port, query_port;
|
||||
unsigned long local_ttl;
|
||||
@@ -532,15 +537,15 @@ char *print_mac(struct daemon *daemon, unsigned char *mac, int len);
|
||||
struct daemon *read_opts (int argc, char **argv, char *compile_opts);
|
||||
|
||||
/* forward.c */
|
||||
void forward_init(int first);
|
||||
void reply_query(struct serverfd *sfd, struct daemon *daemon, time_t now);
|
||||
void receive_query(struct listener *listen, struct daemon *daemon, time_t now);
|
||||
unsigned char *tcp_request(struct daemon *daemon, int confd, time_t now,
|
||||
struct in_addr local_addr, struct in_addr netmask);
|
||||
void server_gone(struct daemon *daemon, struct server *server);
|
||||
|
||||
/* network.c */
|
||||
struct serverfd *allocate_sfd(union mysockaddr *addr, struct serverfd **sfds);
|
||||
void reload_servers(char *fname, struct daemon *daemon);
|
||||
int reload_servers(char *fname, struct daemon *daemon);
|
||||
void check_servers(struct daemon *daemon);
|
||||
int enumerate_interfaces(struct daemon *daemon);
|
||||
struct listener *create_wildcard_listeners(int port);
|
||||
|
||||
+16
-11
@@ -12,7 +12,7 @@
|
||||
|
||||
#include "dnsmasq.h"
|
||||
|
||||
static struct frec *frec_list;
|
||||
static struct frec *frec_list = NULL;
|
||||
|
||||
static struct frec *get_new_frec(time_t now);
|
||||
static struct frec *lookup_frec(unsigned short id);
|
||||
@@ -21,16 +21,6 @@ static struct frec *lookup_frec_by_sender(unsigned short id,
|
||||
unsigned int crc);
|
||||
static unsigned short get_id(void);
|
||||
|
||||
/* May be called more than once. */
|
||||
void forward_init(int first)
|
||||
{
|
||||
struct frec *f;
|
||||
|
||||
if (first)
|
||||
frec_list = NULL;
|
||||
for (f = frec_list; f; f = f->next)
|
||||
f->new_id = 0;
|
||||
}
|
||||
|
||||
/* Send a UDP packet with it's source address set as "source"
|
||||
unless nowild is true, when we just send it with the kernel default */
|
||||
@@ -927,6 +917,21 @@ static struct frec *lookup_frec_by_sender(unsigned short id,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* A server record is going away, remove references to it */
|
||||
void server_gone(struct daemon *daemon, struct server *server)
|
||||
{
|
||||
struct frec *f;
|
||||
|
||||
for (f = frec_list; f; f = f->next)
|
||||
if (f->new_id != 0 && f->sentto == server)
|
||||
f->new_id = 0;
|
||||
|
||||
if (daemon->last_server == server)
|
||||
daemon->last_server = NULL;
|
||||
|
||||
if (daemon->srv_save == server)
|
||||
daemon->srv_save = NULL;
|
||||
}
|
||||
|
||||
/* return unique random ids between 1 and 65535 */
|
||||
static unsigned short get_id(void)
|
||||
|
||||
+2
-3
@@ -18,7 +18,6 @@ static int dns_dirty, file_dirty, leases_left;
|
||||
void lease_init(struct daemon *daemon, time_t now)
|
||||
{
|
||||
unsigned long ei;
|
||||
unsigned char hwaddr[DHCP_CHADDR_MAX];
|
||||
struct in_addr addr;
|
||||
struct dhcp_lease *lease;
|
||||
int flags, clid_len, hw_len, hw_type;
|
||||
@@ -43,7 +42,7 @@ void lease_init(struct daemon *daemon, time_t now)
|
||||
&ei, daemon->dhcp_buff2, daemon->namebuff,
|
||||
daemon->dhcp_buff, daemon->packet) == 5)
|
||||
{
|
||||
hw_len = parse_hex(daemon->dhcp_buff2, hwaddr, DHCP_CHADDR_MAX, NULL, &hw_type);
|
||||
hw_len = parse_hex(daemon->dhcp_buff2, (unsigned char *)daemon->dhcp_buff2, DHCP_CHADDR_MAX, NULL, &hw_type);
|
||||
/* For backwards compatibility, no explict MAC address type means ether. */
|
||||
if (hw_type == 0 && hw_len != 0)
|
||||
hw_type = ARPHRD_ETHER;
|
||||
@@ -72,7 +71,7 @@ void lease_init(struct daemon *daemon, time_t now)
|
||||
lease->expires = (time_t)ei;
|
||||
#endif
|
||||
|
||||
lease_set_hwaddr(lease, hwaddr, (unsigned char *)daemon->packet, hw_len, hw_type, clid_len);
|
||||
lease_set_hwaddr(lease, (unsigned char *)daemon->dhcp_buff2, (unsigned char *)daemon->packet, hw_len, hw_type, clid_len);
|
||||
|
||||
if (strcmp(daemon->dhcp_buff, "*") != 0)
|
||||
lease_set_hostname(lease, daemon->dhcp_buff, daemon->domain_suffix, 0);
|
||||
|
||||
+85
-88
@@ -141,6 +141,7 @@ static int iface_allowed_v6(struct daemon *daemon, struct in6_addr *local,
|
||||
|
||||
netmask.s_addr = 0;
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||
addr.in6.sin6_len = sizeof(addr.in6);
|
||||
#endif
|
||||
@@ -148,8 +149,7 @@ static int iface_allowed_v6(struct daemon *daemon, struct in6_addr *local,
|
||||
addr.in6.sin6_addr = *local;
|
||||
addr.in6.sin6_port = htons(daemon->port);
|
||||
addr.in6.sin6_scope_id = scope;
|
||||
addr.in6.sin6_flowinfo = 0;
|
||||
|
||||
|
||||
return iface_allowed(daemon, (struct irec **)vparam, if_index, &addr, netmask);
|
||||
}
|
||||
#endif
|
||||
@@ -158,7 +158,8 @@ static int iface_allowed_v4(struct daemon *daemon, struct in_addr local, int if_
|
||||
struct in_addr netmask, struct in_addr broadcast, void *vparam)
|
||||
{
|
||||
union mysockaddr addr;
|
||||
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||
addr.in.sin_len = sizeof(addr.in);
|
||||
#endif
|
||||
@@ -202,11 +203,10 @@ static int create_ipv6_listener(struct listener **link, int port)
|
||||
struct listener *l;
|
||||
int opt = 1;
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.in6.sin6_family = AF_INET6;
|
||||
addr.in6.sin6_addr = in6addr_any;
|
||||
addr.in6.sin6_port = htons(port);
|
||||
addr.in6.sin6_flowinfo = 0;
|
||||
addr.in6.sin6_scope_id = 0;
|
||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||
addr.in6.sin6_len = sizeof(addr.in6);
|
||||
#endif
|
||||
@@ -254,6 +254,7 @@ struct listener *create_wildcard_listeners(int port)
|
||||
struct listener *l, *l6 = NULL;
|
||||
int tcpfd, fd;
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.in.sin_family = AF_INET;
|
||||
addr.in.sin_addr.s_addr = INADDR_ANY;
|
||||
addr.in.sin_port = htons(port);
|
||||
@@ -394,11 +395,6 @@ void check_servers(struct daemon *daemon)
|
||||
struct server *new, *tmp, *ret = NULL;
|
||||
int port = 0;
|
||||
|
||||
/* forward table rules reference servers, so have to blow them away */
|
||||
forward_init(0);
|
||||
|
||||
daemon->last_server = daemon->srv_save = NULL;
|
||||
|
||||
for (new = daemon->servers; new; new = tmp)
|
||||
{
|
||||
tmp = new->next;
|
||||
@@ -450,25 +446,37 @@ void check_servers(struct daemon *daemon)
|
||||
|
||||
daemon->servers = ret;
|
||||
}
|
||||
|
||||
void reload_servers(char *fname, struct daemon *daemon)
|
||||
|
||||
/* Return zero if no servers found, in that case we keep polling.
|
||||
This is a protection against an update-time/write race on resolv.conf */
|
||||
int reload_servers(char *fname, struct daemon *daemon)
|
||||
{
|
||||
FILE *f;
|
||||
char *line;
|
||||
struct server *old_servers = NULL;
|
||||
struct server *new_servers = NULL;
|
||||
struct server *serv = daemon->servers;
|
||||
struct server *serv;
|
||||
int gotone = 0;
|
||||
|
||||
/* buff happens to be MAXDNAME long... */
|
||||
if (!(f = fopen(fname, "r")))
|
||||
{
|
||||
syslog(LOG_ERR, _("failed to read %s: %m"), fname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* move old servers to free list - we can reuse the memory
|
||||
and not risk malloc if there are the same or fewer new servers.
|
||||
Servers which were specced on the command line go to the new list. */
|
||||
while (serv)
|
||||
for (serv = daemon->servers; serv;)
|
||||
{
|
||||
struct server *tmp = serv->next;
|
||||
if (serv->flags & SERV_FROM_RESOLV)
|
||||
{
|
||||
serv->next = old_servers;
|
||||
old_servers = serv;
|
||||
old_servers = serv;
|
||||
/* forward table rules reference servers, so have to blow them away */
|
||||
server_gone(daemon, serv);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -477,82 +485,68 @@ void reload_servers(char *fname, struct daemon *daemon)
|
||||
}
|
||||
serv = tmp;
|
||||
}
|
||||
|
||||
/* buff happens to be NAXDNAME long... */
|
||||
f = fopen(fname, "r");
|
||||
if (!f)
|
||||
{
|
||||
syslog(LOG_ERR, _("failed to read %s: %m"), fname);
|
||||
}
|
||||
else
|
||||
{
|
||||
syslog(LOG_INFO, _("reading %s"), fname);
|
||||
while ((line = fgets(daemon->namebuff, MAXDNAME, f)))
|
||||
{
|
||||
union mysockaddr addr, source_addr;
|
||||
char *token = strtok(line, " \t\n\r");
|
||||
struct server *serv;
|
||||
|
||||
if (!token || strcmp(token, "nameserver") != 0)
|
||||
continue;
|
||||
if (!(token = strtok(NULL, " \t\n\r")))
|
||||
continue;
|
||||
|
||||
#ifdef HAVE_IPV6
|
||||
if (inet_pton(AF_INET, token, &addr.in.sin_addr) > 0)
|
||||
#else
|
||||
if ((addr.in.sin_addr.s_addr = inet_addr(token)) != (in_addr_t) -1)
|
||||
#endif
|
||||
{
|
||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||
source_addr.in.sin_len = addr.in.sin_len = sizeof(source_addr.in);
|
||||
#endif
|
||||
source_addr.in.sin_family = addr.in.sin_family = AF_INET;
|
||||
addr.in.sin_port = htons(NAMESERVER_PORT);
|
||||
source_addr.in.sin_addr.s_addr = INADDR_ANY;
|
||||
source_addr.in.sin_port = htons(daemon->query_port);
|
||||
}
|
||||
#ifdef HAVE_IPV6
|
||||
else if (inet_pton(AF_INET6, token, &addr.in6.sin6_addr) > 0)
|
||||
{
|
||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||
source_addr.in6.sin6_len = addr.in6.sin6_len = sizeof(source_addr.in6);
|
||||
#endif
|
||||
source_addr.in6.sin6_family = addr.in6.sin6_family = AF_INET6;
|
||||
addr.in6.sin6_port = htons(NAMESERVER_PORT);
|
||||
source_addr.in6.sin6_flowinfo = addr.in6.sin6_flowinfo = 0;
|
||||
source_addr.in6.sin6_scope_id = addr.in6.sin6_scope_id = 0;
|
||||
source_addr.in6.sin6_addr = in6addr_any;
|
||||
source_addr.in6.sin6_port = htons(daemon->query_port);
|
||||
}
|
||||
#endif /* IPV6 */
|
||||
else
|
||||
continue;
|
||||
|
||||
if (old_servers)
|
||||
{
|
||||
serv = old_servers;
|
||||
old_servers = old_servers->next;
|
||||
}
|
||||
else if (!(serv = malloc(sizeof (struct server))))
|
||||
continue;
|
||||
|
||||
/* this list is reverse ordered:
|
||||
it gets reversed again in check_servers */
|
||||
serv->next = new_servers;
|
||||
new_servers = serv;
|
||||
serv->addr = addr;
|
||||
serv->source_addr = source_addr;
|
||||
serv->domain = NULL;
|
||||
serv->sfd = NULL;
|
||||
serv->flags = SERV_FROM_RESOLV;
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
while ((line = fgets(daemon->namebuff, MAXDNAME, f)))
|
||||
{
|
||||
union mysockaddr addr, source_addr;
|
||||
char *token = strtok(line, " \t\n\r");
|
||||
|
||||
if (!token || strcmp(token, "nameserver") != 0)
|
||||
continue;
|
||||
if (!(token = strtok(NULL, " \t\n\r")))
|
||||
continue;
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
memset(&source_addr, 0, sizeof(source_addr));
|
||||
|
||||
if ((addr.in.sin_addr.s_addr = inet_addr(token)) != (in_addr_t) -1)
|
||||
{
|
||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||
source_addr.in.sin_len = addr.in.sin_len = sizeof(source_addr.in);
|
||||
#endif
|
||||
source_addr.in.sin_family = addr.in.sin_family = AF_INET;
|
||||
addr.in.sin_port = htons(NAMESERVER_PORT);
|
||||
source_addr.in.sin_addr.s_addr = INADDR_ANY;
|
||||
source_addr.in.sin_port = htons(daemon->query_port);
|
||||
}
|
||||
#ifdef HAVE_IPV6
|
||||
else if (inet_pton(AF_INET6, token, &addr.in6.sin6_addr) > 0)
|
||||
{
|
||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||
source_addr.in6.sin6_len = addr.in6.sin6_len = sizeof(source_addr.in6);
|
||||
#endif
|
||||
source_addr.in6.sin6_family = addr.in6.sin6_family = AF_INET6;
|
||||
addr.in6.sin6_port = htons(NAMESERVER_PORT);
|
||||
source_addr.in6.sin6_addr = in6addr_any;
|
||||
source_addr.in6.sin6_port = htons(daemon->query_port);
|
||||
}
|
||||
#endif /* IPV6 */
|
||||
else
|
||||
continue;
|
||||
|
||||
if (old_servers)
|
||||
{
|
||||
serv = old_servers;
|
||||
old_servers = old_servers->next;
|
||||
}
|
||||
else if (!(serv = malloc(sizeof (struct server))))
|
||||
continue;
|
||||
|
||||
/* this list is reverse ordered:
|
||||
it gets reversed again in check_servers */
|
||||
serv->next = new_servers;
|
||||
new_servers = serv;
|
||||
serv->addr = addr;
|
||||
serv->source_addr = source_addr;
|
||||
serv->domain = NULL;
|
||||
serv->sfd = NULL;
|
||||
serv->flags = SERV_FROM_RESOLV;
|
||||
|
||||
gotone = 1;
|
||||
}
|
||||
|
||||
/* Free any memory not used. */
|
||||
while(old_servers)
|
||||
while (old_servers)
|
||||
{
|
||||
struct server *tmp = old_servers->next;
|
||||
free(old_servers);
|
||||
@@ -560,6 +554,9 @@ void reload_servers(char *fname, struct daemon *daemon)
|
||||
}
|
||||
|
||||
daemon->servers = new_servers;
|
||||
fclose(f);
|
||||
|
||||
return gotone;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+1637
-1557
File diff suppressed because it is too large.
Load diff
+19
-10
@@ -109,9 +109,10 @@ size_t dhcp_reply(struct daemon *daemon, struct dhcp_context *context, char *ifa
|
||||
unsigned short fuzz = 0;
|
||||
unsigned int mess_type = 0;
|
||||
unsigned char fqdn_flags = 0;
|
||||
subnet_addr.s_addr = 0;
|
||||
unsigned char *agent_id = NULL;
|
||||
|
||||
subnet_addr.s_addr = 0;
|
||||
|
||||
if (mess->op != BOOTREQUEST || mess->hlen > DHCP_CHADDR_MAX)
|
||||
return 0;
|
||||
|
||||
@@ -524,13 +525,12 @@ size_t dhcp_reply(struct daemon *daemon, struct dhcp_context *context, char *ifa
|
||||
*q++ = c;
|
||||
}
|
||||
*q++ = 0; /* add terminator */
|
||||
message = daemon->dhcp_buff;
|
||||
}
|
||||
|
||||
if (!(opt = option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ)))
|
||||
return 0;
|
||||
|
||||
log_packet(daemon, "DECLINE", option_ptr(opt), mess, iface_name, message);
|
||||
log_packet(daemon, "DECLINE", option_ptr(opt), mess, iface_name, daemon->dhcp_buff);
|
||||
|
||||
if (lease && lease->addr.s_addr == option_addr(opt).s_addr)
|
||||
lease_prune(lease, now);
|
||||
@@ -538,8 +538,11 @@ size_t dhcp_reply(struct daemon *daemon, struct dhcp_context *context, char *ifa
|
||||
if (have_config(config, CONFIG_ADDR) &&
|
||||
config->addr.s_addr == option_addr(opt).s_addr)
|
||||
{
|
||||
syslog(LOG_WARNING, _("disabling DHCP static address %s"), inet_ntoa(config->addr));
|
||||
config->flags &= ~CONFIG_ADDR ;
|
||||
prettyprint_time(daemon->dhcp_buff, DECLINE_BACKOFF);
|
||||
syslog(LOG_WARNING, _("disabling DHCP static address %s for %s"),
|
||||
inet_ntoa(config->addr), daemon->dhcp_buff);
|
||||
config->flags |= CONFIG_DECLINED;
|
||||
config->decline_time = now;
|
||||
}
|
||||
else
|
||||
/* make sure this host gets a different address next time. */
|
||||
@@ -578,18 +581,22 @@ size_t dhcp_reply(struct daemon *daemon, struct dhcp_context *context, char *ifa
|
||||
conf.s_addr = 0;
|
||||
if (have_config(config, CONFIG_ADDR))
|
||||
{
|
||||
char *addrs = inet_ntoa(config->addr);
|
||||
|
||||
if ((ltmp = lease_find_by_addr(config->addr)) && ltmp != lease)
|
||||
syslog(LOG_WARNING, _("not using configured address %s because it is leased to %s"),
|
||||
inet_ntoa(config->addr), print_mac(daemon, ltmp->hwaddr, ltmp->hwaddr_len));
|
||||
addrs, print_mac(daemon, ltmp->hwaddr, ltmp->hwaddr_len));
|
||||
else
|
||||
{
|
||||
struct dhcp_context *tmp;
|
||||
for (tmp = context; tmp; tmp = tmp->current)
|
||||
if (context->local.s_addr == config->addr.s_addr)
|
||||
if (context->router.s_addr == config->addr.s_addr)
|
||||
break;
|
||||
if (tmp)
|
||||
syslog(LOG_WARNING, _("not using configured address %s because it is in use by the server"),
|
||||
inet_ntoa(config->addr));
|
||||
syslog(LOG_WARNING, _("not using configured address %s because it is in use by the server or relay"), addrs);
|
||||
else if (have_config(config, CONFIG_DECLINED) &&
|
||||
difftime(now, config->decline_time) < (float)DECLINE_BACKOFF)
|
||||
syslog(LOG_WARNING, _("not using configured address %s because it was previously declined"), addrs);
|
||||
else
|
||||
conf = config->addr;
|
||||
}
|
||||
@@ -699,7 +706,7 @@ size_t dhcp_reply(struct daemon *daemon, struct dhcp_context *context, char *ifa
|
||||
|
||||
if (have_config(config, CONFIG_ADDR))
|
||||
for (tmp = context; tmp; tmp = tmp->current)
|
||||
if (context->local.s_addr == config->addr.s_addr)
|
||||
if (context->router.s_addr == config->addr.s_addr)
|
||||
break;
|
||||
|
||||
if (!(context = narrow_context(context, mess->yiaddr)))
|
||||
@@ -720,6 +727,8 @@ size_t dhcp_reply(struct daemon *daemon, struct dhcp_context *context, char *ifa
|
||||
an endless protocol loop will ensue. */
|
||||
else if (!tmp &&
|
||||
have_config(config, CONFIG_ADDR) &&
|
||||
(!have_config(config, CONFIG_DECLINED) ||
|
||||
difftime(now, config->decline_time) > (float)DECLINE_BACKOFF) &&
|
||||
config->addr.s_addr != mess->yiaddr.s_addr &&
|
||||
(!(ltmp = lease_find_by_addr(config->addr)) || ltmp == lease))
|
||||
message = _("static lease available");
|
||||
|
||||
Reference in new issue
Block a user