import of dnsmasq-2.27.tar.gz

This commit is contained in:
Simon Kelley
2006-03-16 20:16:06 +00:00
parent aedef83058
commit cdeda28f82
27 changed files with 2427 additions and 1966 deletions

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2005 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2006 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -15,9 +15,8 @@
#include "dnsmasq.h"
static struct dhcp_lease *leases;
static FILE *lease_file;
static int dns_dirty;
enum { no, yes, force } file_dirty;
static enum { no, yes, force } file_dirty;
static int leases_left;
void lease_init(struct daemon *daemon, time_t now)
@@ -25,25 +24,25 @@ void lease_init(struct daemon *daemon, time_t now)
unsigned int a0, a1, a2, a3;
unsigned long ei;
time_t expires;
unsigned char hwaddr[ETHER_ADDR_LEN];
unsigned char hwaddr[DHCP_CHADDR_MAX];
struct in_addr addr;
struct dhcp_lease *lease;
int clid_len = 0;
int clid_len = 0, hw_len, hw_type;
int has_old = 0;
leases = NULL;
leases_left = daemon->dhcp_max;
/* NOTE: need a+ mode to create file if it doesn't exist */
if (!(lease_file = fopen(daemon->lease_file, "a+")))
if (!(daemon->lease_stream = fopen(daemon->lease_file, "a+")))
die(_("cannot open or create leases file: %s"), NULL);
/* a+ mode lease pointer at end. */
rewind(lease_file);
rewind(daemon->lease_stream);
/* client-id max length is 255 which is 255*2 digits + 254 colons
borrow DNS packet buffer which is always larger than 1000 bytes */
while (fscanf(lease_file, "%lu %40s %d.%d.%d.%d %255s %764s",
while (fscanf(daemon->lease_stream, "%lu %255s %d.%d.%d.%d %255s %764s",
&ei, daemon->dhcp_buff2, &a0, &a1, &a2, &a3,
daemon->dhcp_buff, daemon->packet) == 8)
{
@@ -64,16 +63,20 @@ void lease_init(struct daemon *daemon, time_t now)
}
#endif
parse_hex(daemon->dhcp_buff2, hwaddr, ETHER_ADDR_LEN, NULL);
hw_len = parse_hex(daemon->dhcp_buff2, hwaddr, DHCP_CHADDR_MAX, NULL, &hw_type);
/* For backwards compatibility, no explict MAC address type means ether. */
if (hw_type == 0)
hw_type = ARPHRD_ETHER;
addr.s_addr = htonl((a0<<24) + (a1<<16) + (a2<<8) + a3);
/* decode hex in place */
if (strcmp(daemon->packet, "*") == 0)
clid_len = 0;
else
clid_len = parse_hex(daemon->packet, (unsigned char *)daemon->packet, 255, NULL);
clid_len = parse_hex(daemon->packet, (unsigned char *)daemon->packet, 255, NULL, NULL);
if (!(lease = lease_allocate(hwaddr, (unsigned char *)daemon->packet, clid_len, addr)))
if (!(lease = lease_allocate(hwaddr, (unsigned char *)daemon->packet, hw_len, hw_type, clid_len, addr)))
die (_("too many stored leases"), NULL);
lease->expires = expires;
@@ -84,8 +87,6 @@ void lease_init(struct daemon *daemon, time_t now)
dns_dirty = 1;
file_dirty = has_old ? yes: no;
daemon->lease_fd = fileno(lease_file);
}
void lease_update_from_configs(struct daemon *daemon)
@@ -97,7 +98,8 @@ void lease_update_from_configs(struct daemon *daemon)
char *name;
for (lease = leases; lease; lease = lease->next)
if ((config = find_config(daemon->dhcp_conf, NULL, lease->clid, lease->clid_len, lease->hwaddr, NULL)) &&
if ((config = find_config(daemon->dhcp_conf, NULL, lease->clid, lease->clid_len,
lease->hwaddr, lease->hwaddr_len, lease->hwaddr_type, NULL)) &&
(config->flags & CONFIG_NAME) &&
(!(config->flags & CONFIG_ADDR) || config->addr.s_addr == lease->addr.s_addr))
lease_set_hostname(lease, config->hostname, daemon->domain_suffix, 1);
@@ -105,11 +107,12 @@ void lease_update_from_configs(struct daemon *daemon)
lease_set_hostname(lease, name, daemon->domain_suffix, 1); /* updates auth flag only */
}
void lease_update_file(int always, time_t now)
void lease_update_file(struct daemon *daemon, int always, time_t now)
{
struct dhcp_lease *lease;
int i = always; /* avoid warning */
unsigned long expires;
char *mess;
#ifdef HAVE_BROKEN_RTC
if (always || file_dirty == force)
@@ -119,8 +122,10 @@ void lease_update_file(int always, time_t now)
if (file_dirty != no)
{
#endif
rewind(lease_file);
ftruncate(fileno(lease_file), 0);
errno = 0;
rewind(daemon->lease_stream);
if (errno != 0 || ftruncate(fileno(daemon->lease_stream), 0) != 0)
goto write_err;
for (lease = leases; lease; lease = lease->next)
{
@@ -133,27 +138,51 @@ void lease_update_file(int always, time_t now)
expires = now; /* eliminate warning */
expires = (unsigned long)lease->expires;
#endif
fprintf(lease_file, "%lu %.2x:%.2x:%.2x:%.2x:%.2x:%.2x %s %s ",
expires, lease->hwaddr[0], lease->hwaddr[1],
lease->hwaddr[2], lease->hwaddr[3], lease->hwaddr[4],
lease->hwaddr[5], inet_ntoa(lease->addr),
lease->hostname && strlen(lease->hostname) != 0 ? lease->hostname : "*");
if (fprintf(daemon->lease_stream, "%lu ", expires) < 0)
goto write_err;
if (lease->hwaddr_type != ARPHRD_ETHER &&
fprintf(daemon->lease_stream, "%.2x-", lease->hwaddr_type) < 0)
goto write_err;
for (i = 0; i < lease->hwaddr_len - 1; i++)
if (fprintf(daemon->lease_stream, "%.2x:", lease->hwaddr[i]) < 0)
goto write_err;
if (fprintf(daemon->lease_stream, "%.2x", lease->hwaddr[i]) < 0)
goto write_err;
if (fprintf(daemon->lease_stream, " %s %s ", inet_ntoa(lease->addr),
lease->hostname && strlen(lease->hostname) != 0 ? lease->hostname : "*") < 0)
goto write_err;
if (lease->clid && lease->clid_len != 0)
{
for (i = 0; i < lease->clid_len - 1; i++)
fprintf(lease_file, "%.2x:", lease->clid[i]);
fprintf(lease_file, "%.2x\n", lease->clid[i]);
if (fprintf(daemon->lease_stream, "%.2x:", lease->clid[i]) < 0)
goto write_err;
if (fprintf(daemon->lease_stream, "%.2x\n", lease->clid[i]) < 0)
goto write_err;
}
else
fprintf(lease_file, "*\n");
if (fprintf(daemon->lease_stream, "*\n") < 0)
goto write_err;
}
fflush(lease_file);
fsync(fileno(lease_file));
if (fflush(daemon->lease_stream) != 0)
goto write_err;
if (fsync(fileno(daemon->lease_stream)) < 0)
goto write_err;
file_dirty = no;
}
return;
write_err:
mess = _("failed to write");
#ifdef HAVE_BROKEN_RTC
syslog(LOG_ERR, "%s %s: %m", mess, daemon->lease_file);
#else
syslog(LOG_ERR, "%s %s: %m (retry in %ds)", mess, daemon->lease_file, LEASE_RETRY);
alarm(LEASE_RETRY);
#endif
}
void lease_update_dns(struct daemon *daemon)
@@ -204,7 +233,7 @@ void lease_prune(struct dhcp_lease *target, time_t now)
}
struct dhcp_lease *lease_find_by_client(unsigned char *hwaddr,
struct dhcp_lease *lease_find_by_client(unsigned char *hwaddr, int hw_len, int hw_type,
unsigned char *clid, int clid_len)
{
struct dhcp_lease *lease;
@@ -217,7 +246,9 @@ struct dhcp_lease *lease_find_by_client(unsigned char *hwaddr,
for (lease = leases; lease; lease = lease->next)
if ((!lease->clid || !clid) &&
memcmp(hwaddr, lease->hwaddr, ETHER_ADDR_LEN) == 0)
lease->hwaddr_len == hw_len &&
lease->hwaddr_type == hw_type &&
memcmp(hwaddr, lease->hwaddr, hw_len) == 0)
return lease;
return NULL;
@@ -236,7 +267,7 @@ struct dhcp_lease *lease_find_by_addr(struct in_addr addr)
struct dhcp_lease *lease_allocate(unsigned char *hwaddr, unsigned char *clid,
int clid_len, struct in_addr addr)
int hw_len, int hw_type, int clid_len, struct in_addr addr)
{
struct dhcp_lease *lease;
if (!leases_left || !(lease = malloc(sizeof(struct dhcp_lease))))
@@ -245,10 +276,10 @@ struct dhcp_lease *lease_allocate(unsigned char *hwaddr, unsigned char *clid,
lease->clid = NULL;
lease->hostname = lease->fqdn = NULL;
lease->addr = addr;
memset(lease->hwaddr, 0, ETHER_ADDR_LEN);
memset(lease->hwaddr, 0, DHCP_CHADDR_MAX);
lease->expires = 1;
if (!lease_set_hwaddr(lease, hwaddr, clid, clid_len))
if (!lease_set_hwaddr(lease, hwaddr, clid, hw_len, hw_type, clid_len))
{
free(lease);
return NULL;
@@ -274,12 +305,16 @@ void lease_set_expires(struct dhcp_lease *lease, time_t exp)
}
int lease_set_hwaddr(struct dhcp_lease *lease, unsigned char *hwaddr,
unsigned char *clid, int clid_len)
unsigned char *clid, int hw_len, int hw_type, int clid_len)
{
if (memcmp(lease->hwaddr, hwaddr, ETHER_ADDR_LEN) != 0)
if (hw_len != lease->hwaddr_len ||
hw_type != lease->hwaddr_type ||
memcmp(lease->hwaddr, hwaddr, hw_len) != 0)
{
file_dirty = force;
memcpy(lease->hwaddr, hwaddr, ETHER_ADDR_LEN);
memcpy(lease->hwaddr, hwaddr, hw_len);
lease->hwaddr_len = hw_len;
lease->hwaddr_type = hw_type;
}
/* only update clid when one is available, stops packets