2
0
mirror of https://gitlab.isc.org/isc-projects/dhcp synced 2025-08-30 22:05:23 +00:00

Intermediate changes to support actual DHCP protocol engine

This commit is contained in:
Ted Lemon
1996-02-21 12:11:09 +00:00
parent d9c6d82c49
commit 97ca16995f
29 changed files with 972 additions and 120 deletions

View File

@@ -11,6 +11,8 @@ CFLAGS += -DDEBUG -g -Wall -Wstrict-prototypes -Wno-unused \
-Wno-uninitialized -Werror
dhclient: dhclient.o confpars.o alloc.o memory.o options.o \
hash.o tables.o inet.o convert.o conflex.o errwarn.o tree.o
hash.o tables.o inet.o convert.o conflex.o errwarn.o \
tree.o print.o
cc -o dhclient dhclient.o confpars.o alloc.o memory.o options.o \
hash.o tables.o inet.o convert.o conflex.o errwarn.o tree.o
hash.o tables.o inet.o convert.o conflex.o errwarn.o \
print.o tree.o

View File

@@ -189,11 +189,51 @@ int main (argc, argv, envp)
cons_options ((struct packet *)0,
&outgoing, &decl, bufs);
memset (&raw.ciaddr, 0, sizeof raw.ciaddr);
memset (&raw.yiaddr, 0, sizeof raw.ciaddr);
memset (&raw.siaddr, 0, sizeof raw.ciaddr);
memset (&raw.giaddr, 0, sizeof raw.ciaddr);
if (decl.ciaddr) {
if (tree_evaluate (decl.ciaddr) != 4)
warn ("ciaddr is more"
" than one address");
else
memcpy (&raw.ciaddr,
decl.ciaddr -> value,
decl.ciaddr -> len);
} else
memset (&raw.ciaddr, 0, sizeof raw.ciaddr);
if (decl.yiaddr) {
if (tree_evaluate (decl.yiaddr) != 4)
warn ("yiaddr is more"
" than one address");
else
memcpy (&raw.yiaddr,
decl.yiaddr -> value,
decl.yiaddr -> len);
} else
memset (&raw.yiaddr, 0, sizeof raw.yiaddr);
if (decl.siaddr) {
if (tree_evaluate (decl.siaddr) != 4)
warn ("siaddr is more"
" than one address");
else
memcpy (&raw.siaddr,
decl.siaddr -> value,
decl.siaddr -> len);
} else
memset (&raw.siaddr, 0, sizeof raw.siaddr);
if (decl.giaddr) {
if (tree_evaluate (decl.giaddr) != 4)
warn ("giaddr is more"
" than one address");
else
memcpy (&raw.giaddr,
decl.giaddr -> value,
decl.giaddr -> len);
} else
memset (&raw.giaddr, 0, sizeof raw.giaddr);
raw.xid = xid++;
raw.xid = htons (raw.xid);
raw.secs = 0;

View File

@@ -274,6 +274,8 @@ static int intern (atom, dfv)
case 'c':
if (!strcasecmp (atom + 1, "lass"))
return CLASS;
if (!strcasecmp (atom + 1, "iaddr"))
return CIADDR;
break;
case 'e':
if (!strcasecmp (atom + 1, "thernet"))
@@ -287,6 +289,10 @@ static int intern (atom, dfv)
if (!strcasecmp (atom + 1, "ixed-address"))
return FIXED_ADDR;
break;
case 'g':
if (!strcasecmp (atom + 1, "iaddr"))
return GIADDR;
break;
case 'h':
if (!strcasecmp (atom + 1, "ost"))
return HOST;
@@ -312,6 +318,8 @@ static int intern (atom, dfv)
case 's':
if (!strcasecmp (atom + 1, "tarts"))
return STARTS;
if (!strcasecmp (atom + 1, "iaddr"))
return SIADDR;
break;
case 't':
if (!strcasecmp (atom + 1, "timestamp"))
@@ -321,6 +329,10 @@ static int intern (atom, dfv)
if (!strcasecmp (atom + 1, "id"))
return UID;
break;
case 'y':
if (!strcasecmp (atom + 1, "iaddr"))
return YIADDR;
break;
}
return dfv;
}

View File

@@ -103,6 +103,7 @@ void add_hash (table, name, len, pointer)
bp -> name = name;
bp -> value = pointer;
bp -> next = table -> buckets [hashno];
bp -> len = len;
table -> buckets [hashno] = bp;
}
@@ -140,10 +141,11 @@ unsigned char *hash_lookup (table, name, len)
struct hash_bucket *bp;
if (len) {
for (bp = table -> buckets [hashno]; bp; bp = bp -> next)
for (bp = table -> buckets [hashno]; bp; bp = bp -> next) {
if (len == bp -> len
&& !memcmp (bp -> name, name, len))
return bp -> value;
}
} else {
for (bp = table -> buckets [hashno]; bp; bp = bp -> next)
if (!strcmp (bp -> name, name))

View File

@@ -87,7 +87,7 @@ struct iaddr ip_addr (subnet, mask, host_address)
j = rv.len - sizeof habuf;
for (i = sizeof habuf - 1; i >= 0; i--) {
if (mask.iabuf [i + j]) {
if (habuf [i] > ~mask.iabuf [i + j]) {
if (habuf [i] > (mask.iabuf [i + j] ^ 0xFF)) {
rv.len = 0;
return rv;
}
@@ -97,10 +97,10 @@ struct iaddr ip_addr (subnet, mask, host_address)
return rv;
}
}
rv.iabuf [i + j] &= habuf [i];
rv.iabuf [i + j] |= habuf [i];
break;
}
rv.iabuf [i + j] = habuf [i];
} else
rv.iabuf [i + j] = habuf [i];
}
return rv;

View File

@@ -48,7 +48,7 @@ static char copyright[] =
#include "dhcpd.h"
static struct host_decl *hosts;
static struct hash_table *subnet_hash;
static struct subnet *subnets;
static struct hash_table *lease_uid_hash;
static struct hash_table *lease_ip_addr_hash;
static struct hash_table *lease_hw_addr_hash;
@@ -98,12 +98,10 @@ void new_address_range (low, high, netmask)
struct lease *address_range, *lp, *plp;
struct subnet *subnet;
struct iaddr net;
int i, max;
int min, max, i;
char lowbuf [16], highbuf [16], netbuf [16];
/* Initialize the hash table if it hasn't been done yet. */
if (!subnet_hash)
subnet_hash = new_hash ();
if (!lease_uid_hash)
lease_uid_hash = new_hash ();
if (!lease_ip_addr_hash)
@@ -130,32 +128,40 @@ void new_address_range (low, high, netmask)
subnet -> net = net;
subnet -> netmask = netmask;
subnet -> leases = (struct lease *)0;
subnet -> last_lease = (struct lease *)0;
subnet -> next = (struct subnet *)0;
subnet -> default_lease_time = default_lease_time;
subnet -> max_lease_time = max_lease_time;
enter_subnet (subnet);
}
/* Get the high and low host addresses... */
max = host_addr (high, netmask);
i = host_addr (low, netmask);
min = host_addr (low, netmask);
/* Allow range to be specified high-to-low as well as low-to-high. */
if (i > max) {
max = i;
i = host_addr (high, netmask);
if (min > max) {
max = min;
min = host_addr (high, netmask);
}
/* Get a lease structure for each address in the range. */
address_range = new_leases (max - i + 1, "new_address_range");
address_range = new_leases (max - min + 1, "new_address_range");
if (!address_range) {
strcpy (lowbuf, piaddr (low));
strcpy (highbuf, piaddr (high));
error ("No memory for address range %s-%s.", lowbuf, highbuf);
}
memset (address_range, 0, (sizeof *address_range) * (max - i + 1));
memset (address_range, 0, (sizeof *address_range) * (max - min + 1));
/* Fill in the last lease if it hasn't been already... */
if (!subnet -> last_lease)
subnet -> last_lease = &address_range [0];
/* Fill out the lease structures with some minimal information. */
for (; i <= max; i++) {
for (i = 0; i < max - min + 1; i++) {
address_range [i].ip_addr =
ip_addr (subnet -> net, subnet -> netmask, i);
ip_addr (subnet -> net, subnet -> netmask, i + min);
address_range [i].starts =
address_range [i].timestamp = MIN_TIME;
address_range [i].ends = MIN_TIME;
@@ -200,13 +206,16 @@ void new_address_range (low, high, netmask)
}
}
struct subnet *find_subnet (subnet)
struct iaddr subnet;
struct subnet *find_subnet (addr)
struct iaddr addr;
{
struct subnet *rv;
return (struct subnet *)hash_lookup (subnet_hash,
(char *)subnet.iabuf, subnet.len);
for (rv = subnets; rv; rv = rv -> next) {
if (addr_eq (subnet_number (addr, rv -> netmask), rv -> net))
return rv;
}
return (struct subnet *)0;
}
/* Enter a new subnet into the subnet hash. */
@@ -214,8 +223,9 @@ struct subnet *find_subnet (subnet)
void enter_subnet (subnet)
struct subnet *subnet;
{
add_hash (subnet_hash, (char *)subnet -> net.iabuf,
subnet -> net.len, (unsigned char *)subnet);
/* XXX Sort the nets into a balanced tree to make searching quicker. */
subnet -> next = subnets;
subnets = subnet;
}
/* Enter a lease into the system. This is called by the parser each
@@ -259,6 +269,11 @@ void supersede_lease (comp, lease)
struct subnet *parent;
struct lease *lp;
printf ("Supersede_lease:\n");
print_lease (comp);
print_lease (lease);
printf ("\n");
/* If the existing lease hasn't expired and has a different
unique identifier or, if it doesn't have a unique
identifier, a different hardware address, then the two
@@ -290,7 +305,9 @@ void supersede_lease (comp, lease)
enter_uid = 1;
}
free (comp -> uid);
}
} else
enter_uid = 1;
if (comp -> hardware_addr.htype &&
((comp -> hardware_addr.hlen !=
lease -> hardware_addr.hlen) ||
@@ -303,7 +320,8 @@ void supersede_lease (comp, lease)
comp -> hardware_addr.haddr,
comp -> hardware_addr.hlen);
enter_hwaddr = 1;
}
} else if (!comp -> hardware_addr.htype)
enter_hwaddr = 1;
/* Copy the data files, but not the linkages. */
comp -> starts = lease -> starts;
@@ -317,16 +335,16 @@ void supersede_lease (comp, lease)
/* Record the lease in the uid hash if necessary. */
if (enter_uid && lease -> uid) {
add_hash (lease_uid_hash, lease -> uid,
lease -> uid_len, (unsigned char *)lease);
add_hash (lease_uid_hash, comp -> uid,
comp -> uid_len, (unsigned char *)comp);
}
/* Record it in the hardware address hash if necessary. */
if (enter_hwaddr && lease -> hardware_addr.htype) {
add_hash (lease_hw_addr_hash,
lease -> hardware_addr.haddr,
lease -> hardware_addr.hlen,
(unsigned char *)lease);
comp -> hardware_addr.haddr,
comp -> hardware_addr.hlen,
(unsigned char *)comp);
}
/* Remove the lease from its current place in the list. */
@@ -338,6 +356,9 @@ void supersede_lease (comp, lease)
if (comp -> next) {
comp -> next -> prev = comp -> prev;
}
if (comp -> contain -> last_lease == comp) {
comp -> contain -> last_lease = comp -> prev;
}
/* Find the last insertion point... */
if (comp == comp -> contain -> insertion_point ||
@@ -351,18 +372,20 @@ void supersede_lease (comp, lease)
/* Nothing on the list yet? Just make comp the
head of the list. */
comp -> contain -> leases = comp;
} else if (lp -> ends <= comp -> ends) {
comp -> contain -> last_lease = comp;
} else if (lp -> ends > comp -> ends) {
/* Skip down the list until we run out of list
or find a place for comp. */
while (lp -> next && lp -> ends < comp -> ends) {
while (lp -> next && lp -> ends > comp -> ends) {
lp = lp -> next;
}
if (lp -> ends < comp -> ends) {
if (lp -> ends > comp -> ends) {
/* If we ran out of list, put comp
at the end. */
lp -> next = comp;
comp -> prev = lp;
comp -> next = (struct lease *)0;
comp -> contain -> last_lease = comp;
} else {
/* If we didn't, put it between lp and
the previous item on the list. */
@@ -372,12 +395,12 @@ void supersede_lease (comp, lease)
lp -> prev = comp;
}
} else {
/* Skip ip the list until we run out of list
/* Skip up the list until we run out of list
or find a place for comp. */
while (lp -> prev && lp -> ends > comp -> ends) {
while (lp -> prev && lp -> ends < comp -> ends) {
lp = lp -> prev;
}
if (lp -> ends > comp -> ends) {
if (lp -> ends < comp -> ends) {
/* If we ran out of list, put comp
at the beginning. */
lp -> prev = comp;
@@ -397,6 +420,18 @@ void supersede_lease (comp, lease)
}
}
/* Release the specified lease and re-hash it as appropriate. */
void release_lease (lease)
struct lease *lease;
{
struct lease lt;
lease -> ends = 0;
lt = *lease;
supersede_lease (lease, &lt);
}
/* Locate the lease associated with a given IP address... */
struct lease *find_lease_by_ip_addr (addr)
@@ -417,3 +452,29 @@ struct lease *find_lease_by_uid (uid, len)
return lease;
}
struct lease *find_lease_by_hw_addr (hwaddr, hwlen)
unsigned char *hwaddr;
int hwlen;
{
struct lease *lease = (struct lease *)hash_lookup (lease_hw_addr_hash,
hwaddr, hwlen);
return lease;
}
void dump_subnets ()
{
struct lease *l;
struct subnet *s;
int i;
for (s = subnets; s; s = s -> next) {
printf ("Subnet %s", piaddr (s -> net));
printf (" netmask %s\n",
piaddr (s -> netmask));
for (l = s -> leases; l; l = l -> next) {
print_lease (l);
}
printf ("Last Lease:\n");
print_lease (s -> last_lease);
}
}

View File

@@ -94,8 +94,6 @@ void parse_option_buffer (packet, buffer, length)
int len;
int code;
printf ("parse_option_buffer (%x, %x, %d)\n",
(unsigned long)packet, (unsigned long)buffer, length);
for (s = buffer; *s != DHO_END && s < end; ) {
code = s [0];
/* Pad options don't have a length - just skip them. */
@@ -126,8 +124,6 @@ printf ("parse_option_buffer (%x, %x, %d)\n",
t [len] = 0;
packet -> options [code].len = len;
packet -> options [code].data = t;
printf ("%s=%s\n", dhcp_options [code].name,
pretty_print_option (code, t, len));
} else {
/* If it's a repeat, concatenate it to whatever
we last saw. This is really only required

View File

@@ -55,13 +55,46 @@ char *print_hw_addr (htype, hlen, data)
char *s;
int i;
s = habuf;
for (i = 0; i < hlen; i++) {
sprintf (s, "%x", data [i]);
s += strlen (s);
*s++ = ':';
if (htype == 0 || hlen == 0) {
strcpy (habuf, "<null>");
} else {
s = habuf;
for (i = 0; i < hlen; i++) {
sprintf (s, "%x", data [i]);
s += strlen (s);
*s++ = ':';
}
*--s = 0;
}
*--s = 0;
return habuf;
}
void print_lease (lease)
struct lease *lease;
{
struct tm *t;
char tbuf [32];
printf (" Lease %s",
piaddr (lease -> ip_addr));
t = gmtime (&lease -> starts);
strftime (tbuf, sizeof tbuf, "%D %H:%M:%S", t);
printf (" start %s", tbuf);
t = gmtime (&lease -> ends);
strftime (tbuf, sizeof tbuf, "%D %H:%M:%S", t);
printf (" end %s", tbuf);
t = gmtime (&lease -> timestamp);
strftime (tbuf, sizeof tbuf, "%D %H:%M:%S", t);
printf (" stamp %s\n", tbuf);
printf (" hardware addr = %s",
print_hw_addr (lease -> hardware_addr.htype,
lease -> hardware_addr.hlen,
lease -> hardware_addr.haddr));
printf (" host %s state %x\n",
lease -> host ? lease -> host -> name : "<none>",
lease -> state);
}

View File

@@ -184,6 +184,9 @@ void dispatch ()
/* Wait for a packet or a timeout... XXX */
count = select (max + 1, &r, &w, &x, (struct timeval *)0);
/* Get the current time... */
GET_TIME (&cur_time);
/* Not likely to be transitory... */
if (count < 0)
error ("select: %m");

View File

@@ -274,6 +274,8 @@ static int intern (atom, dfv)
case 'c':
if (!strcasecmp (atom + 1, "lass"))
return CLASS;
if (!strcasecmp (atom + 1, "iaddr"))
return CIADDR;
break;
case 'e':
if (!strcasecmp (atom + 1, "thernet"))
@@ -287,6 +289,10 @@ static int intern (atom, dfv)
if (!strcasecmp (atom + 1, "ixed-address"))
return FIXED_ADDR;
break;
case 'g':
if (!strcasecmp (atom + 1, "iaddr"))
return GIADDR;
break;
case 'h':
if (!strcasecmp (atom + 1, "ost"))
return HOST;
@@ -312,6 +318,8 @@ static int intern (atom, dfv)
case 's':
if (!strcasecmp (atom + 1, "tarts"))
return STARTS;
if (!strcasecmp (atom + 1, "iaddr"))
return SIADDR;
break;
case 't':
if (!strcasecmp (atom + 1, "timestamp"))
@@ -321,6 +329,10 @@ static int intern (atom, dfv)
if (!strcasecmp (atom + 1, "id"))
return UID;
break;
case 'y':
if (!strcasecmp (atom + 1, "iaddr"))
return YIADDR;
break;
}
return dfv;
}

View File

@@ -234,6 +234,22 @@ void parse_host_decl (cfile, bc, decl)
case OPTION:
parse_option_decl (cfile, bc, decl);
break;
case CIADDR:
decl -> ciaddr =
tree_cache (parse_ip_addr_or_hostname (cfile, bc, 0));
break;
case YIADDR:
decl -> yiaddr =
tree_cache (parse_ip_addr_or_hostname (cfile, bc, 0));
break;
case SIADDR:
decl -> siaddr =
tree_cache (parse_ip_addr_or_hostname (cfile, bc, 0));
break;
case GIADDR:
decl -> giaddr =
tree_cache (parse_ip_addr_or_hostname (cfile, bc, 0));
break;
default:
parse_warn ("expecting a dhcp option declaration.");
skip_to_semi (cfile);

View File

@@ -189,11 +189,51 @@ int main (argc, argv, envp)
cons_options ((struct packet *)0,
&outgoing, &decl, bufs);
memset (&raw.ciaddr, 0, sizeof raw.ciaddr);
memset (&raw.yiaddr, 0, sizeof raw.ciaddr);
memset (&raw.siaddr, 0, sizeof raw.ciaddr);
memset (&raw.giaddr, 0, sizeof raw.ciaddr);
if (decl.ciaddr) {
if (tree_evaluate (decl.ciaddr) != 4)
warn ("ciaddr is more"
" than one address");
else
memcpy (&raw.ciaddr,
decl.ciaddr -> value,
decl.ciaddr -> len);
} else
memset (&raw.ciaddr, 0, sizeof raw.ciaddr);
if (decl.yiaddr) {
if (tree_evaluate (decl.yiaddr) != 4)
warn ("yiaddr is more"
" than one address");
else
memcpy (&raw.yiaddr,
decl.yiaddr -> value,
decl.yiaddr -> len);
} else
memset (&raw.yiaddr, 0, sizeof raw.yiaddr);
if (decl.siaddr) {
if (tree_evaluate (decl.siaddr) != 4)
warn ("siaddr is more"
" than one address");
else
memcpy (&raw.siaddr,
decl.siaddr -> value,
decl.siaddr -> len);
} else
memset (&raw.siaddr, 0, sizeof raw.siaddr);
if (decl.giaddr) {
if (tree_evaluate (decl.giaddr) != 4)
warn ("giaddr is more"
" than one address");
else
memcpy (&raw.giaddr,
decl.giaddr -> value,
decl.giaddr -> len);
} else
memset (&raw.giaddr, 0, sizeof raw.giaddr);
raw.xid = xid++;
raw.xid = htons (raw.xid);
raw.secs = 0;

200
dhcp.c
View File

@@ -49,5 +49,205 @@ static char copyright[] =
void dhcp (packet)
struct packet *packet;
{
struct lease *uid_lease, *ip_lease, *hw_lease, *lease;
struct iaddr cip;
struct lease lt;
TIME lease_time;
dump_packet (packet);
/* Try to find a lease that's been assigned to the specified
unique client identifier. */
if (packet -> options [DHO_DHCP_CLIENT_IDENTIFIER].len)
uid_lease =
find_lease_by_uid (packet -> options
[DHO_DHCP_CLIENT_IDENTIFIER].data,
packet -> options
[DHO_DHCP_CLIENT_IDENTIFIER].len);
else
uid_lease = (struct lease *)0;
/* Try to find a lease that's been attached to the client's
hardware address... */
hw_lease = find_lease_by_hw_addr (packet -> raw -> chaddr,
packet -> raw -> hlen);
/* Try to find a lease that's been allocated to the client's
IP address. */
if (packet -> options [DHO_DHCP_REQUESTED_ADDRESS].len &&
packet -> options [DHO_DHCP_REQUESTED_ADDRESS].len
<= sizeof cip.iabuf) {
cip.len = packet -> options [DHO_DHCP_REQUESTED_ADDRESS].len;
memcpy (cip.iabuf,
packet -> options [DHO_DHCP_REQUESTED_ADDRESS].data,
packet -> options [DHO_DHCP_REQUESTED_ADDRESS].len);
memcpy (cip.iabuf, &packet -> raw -> ciaddr, 4);
ip_lease = find_lease_by_ip_addr (cip);
} else
ip_lease = (struct lease *)0;
printf ("First blush:\n");
if (ip_lease) {
printf ("ip_lease: ");
print_lease (ip_lease);
}
if (hw_lease) {
printf ("hw_lease: ");
print_lease (hw_lease);
}
if (uid_lease) {
printf ("uid_lease: ");
print_lease (uid_lease);
}
/* Toss extra pointers to the same lease... */
if (ip_lease == hw_lease)
ip_lease = (struct lease *)0;
if (hw_lease == uid_lease)
hw_lease = (struct lease *)0;
if (ip_lease == uid_lease)
ip_lease = (struct lease *)0;
printf ("Second blush:\n");
if (ip_lease) {
printf ("ip_lease: ");
print_lease (ip_lease);
}
if (hw_lease) {
printf ("hw_lease: ");
print_lease (hw_lease);
}
if (uid_lease) {
printf ("uid_lease: ");
print_lease (uid_lease);
}
/* If we got an ip address lease, make sure it isn't assigned to
some *other* client! If it was assigned to this client, we'd
have zeroed it out above, so the only way we can take it at this
point is if some other client had it but it's timed out, or if no
other client has ever had it. */
if (ip_lease &&
ip_lease -> ends >= cur_time)
ip_lease = (struct lease *)0;
/* Now eliminate leases that are on the wrong subnet... */
if (ip_lease && packet -> subnet != ip_lease -> contain) {
release_lease (ip_lease);
ip_lease = (struct lease *)0;
}
if (uid_lease && packet -> subnet != uid_lease -> contain) {
release_lease (uid_lease);
uid_lease = (struct lease *)0;
}
if (hw_lease && packet -> subnet != hw_lease -> contain) {
release_lease (hw_lease);
hw_lease = (struct lease *)0;
}
printf ("Third blush:\n");
if (ip_lease) {
printf ("ip_lease: ");
print_lease (ip_lease);
}
if (hw_lease) {
printf ("hw_lease: ");
print_lease (hw_lease);
}
if (uid_lease) {
printf ("uid_lease: ");
print_lease (uid_lease);
}
/* At this point, if ip_lease is nonzero, we can assign it to
this client. */
lease = ip_lease;
/* If we got a lease that matched the client identifier, we may want
to use it, but if we already have a lease we like, we must free
the lease that matched the client identifier. */
if (uid_lease) {
if (lease) {
release_lease (uid_lease);
} else
lease = uid_lease;
}
/* The lease that matched the hardware address is treated likewise. */
if (hw_lease) {
if (lease) {
release_lease (hw_lease);
} else
lease = hw_lease;
}
/* If we didn't find a lease, try to allocate one... */
if (!lease) {
lease = packet -> subnet -> last_lease;
/* If there are no leases in that subnet that have
expired, we have nothing to offer this client. */
if (lease -> ends >= cur_time) {
note ("no free leases on subnet %s",
piaddr (packet -> subnet -> net));
return;
}
lease -> host = (struct host_decl *)0;
}
/* At this point, we have a lease that we can offer the client.
Now we construct a lease structure that contains what we want,
and call supersede_lease to do the right thing with it. */
memset (&lt, 0, sizeof lt);
/* Use the ip address of the lease that we finally found in
the database. */
lt.ip_addr = lease -> ip_addr;
/* Start now. */
lt.starts = cur_time;
/* Figure out how long a lease to assign. */
if (packet -> options [DHO_DHCP_LEASE_TIME].len == 4) {
lease_time = getULong (packet ->
options [DHO_DHCP_LEASE_TIME].data);
/* Don't let the client ask for a longer lease than
is supported for this subnet. */
if (lease_time > packet -> subnet -> max_lease_time)
lease_time = packet -> subnet -> max_lease_time;
} else
lease_time = packet -> subnet -> default_lease_time;
lt.ends = cur_time + lease_time;
lt.timestamp = cur_time;
/* Record the uid, if given... */
if (packet -> options [DHO_DHCP_CLIENT_IDENTIFIER].len) {
lt.uid_len =
packet -> options [DHO_DHCP_CLIENT_IDENTIFIER].len;
lt.uid = packet -> options [DHO_DHCP_CLIENT_IDENTIFIER].data;
packet -> options [DHO_DHCP_CLIENT_IDENTIFIER].data =
(unsigned char *)0;
packet -> options [DHO_DHCP_CLIENT_IDENTIFIER].len = 0;
}
/* Record the hardware address, if given... */
lt.hardware_addr.hlen = packet -> raw -> hlen;
lt.hardware_addr.htype = packet -> raw -> htype;
memcpy (lt.hardware_addr.haddr, packet -> raw -> chaddr,
packet -> raw -> hlen);
lt.host = lease -> host; /* XXX */
lt.contain = lease -> contain;
/* Record the transaction id... */
lt.xid = packet -> raw -> xid;
/* Install the new information about this lease in the database. */
supersede_lease (lease, &lt);
/* Send a response to the client... */
dump_subnets ();
}

52
dhcpd.c
View File

@@ -50,7 +50,10 @@ static char copyright[] =
static void usage PROTO ((void));
TIME cur_time;
TIME default_lease_time = 43200; /* 12 hours... */
TIME max_lease_time = 86400; /* 24 hours... */
struct subnet *local_subnet;
u_int32_t *server_addrlist;
int server_addrcount;
u_int16_t server_port;
@@ -63,6 +66,7 @@ int main (argc, argv, envp)
int port = 0;
int i;
struct sockaddr_in name;
struct iaddr taddr;
u_int32_t *addrlist = (u_int32_t *)0;
int addrcount = 0;
struct tree *addrtree = (struct tree *)0;
@@ -148,7 +152,23 @@ int main (argc, argv, envp)
}
#endif
taddr.len = 0;
server_addrlist = get_interface_list (&server_addrcount);
for (i = 0; i < server_addrcount; i++) {
struct sockaddr_in foo;
foo.sin_addr.s_addr = server_addrlist [i];
printf ("Address %d: %s\n", i, inet_ntoa (foo.sin_addr));
if (server_addrlist [i] != htonl (INADDR_LOOPBACK)) {
if (taddr.len) {
error ("dhcpd currently does not support "
"multiple interfaces");
}
taddr.len = 4;
memcpy (taddr.iabuf, &server_addrlist [i], 4);
local_subnet = find_subnet (taddr);
}
}
/* Listen on the specified (or default) port on each specified
(or default) IP address. */
@@ -164,6 +184,8 @@ int main (argc, argv, envp)
close (i);
}
dump_subnets ();
/* Receive packets and dispatch them... */
dispatch ();
@@ -191,6 +213,7 @@ void do_packet (packbuf, len, from_port, from, sock)
{
struct packet *tp;
struct dhcp_packet *tdp;
struct iaddr ia;
if (!(tp = new_packet ("do_packet")))
return;
@@ -205,12 +228,29 @@ void do_packet (packbuf, len, from_port, from, sock)
tp -> client_port = from_port;
tp -> client_addr = from;
tp -> client_sock = sock;
parse_options (tp);
if (tp -> options_valid &&
tp -> options [DHO_DHCP_MESSAGE_TYPE].data)
dhcp (tp);
else
bootp (tp);
/* If this came through a gateway, find the corresponding subnet... */
if (tp -> raw -> giaddr.s_addr) {
ia.len = 4;
memcpy (ia.iabuf, &tp -> raw -> giaddr, 4);
tp -> subnet = find_subnet (ia);
} else {
tp -> subnet = local_subnet;
}
/* If the subnet from whence this packet came is unknown to us,
drop it on the floor... */
if (!tp -> subnet)
note ("Packet from unknown subnet: %s",
inet_ntoa (tp -> raw -> giaddr));
else {
parse_options (tp);
if (tp -> options_valid &&
tp -> options [DHO_DHCP_MESSAGE_TYPE].data)
dhcp (tp);
else
bootp (tp);
}
}
void dump_packet (tp)

View File

@@ -1,4 +1,5 @@
range 204.254.239.11 204.254.239.254 255.255.255.0;
range 204.254.239.11 204.254.239.17 255.255.255.0;
range 204.254.240.11 204.254.240.12 255.255.255.0;
host minuet
hardware ethernet 08:00:2b:35:0c:18

17
dhcpd.h
View File

@@ -53,6 +53,7 @@
#include <stdlib.h>
#include <sys/stat.h>
#include <ctype.h>
#include <time.h>
#include "dhcp.h"
#include "cdefs.h"
@@ -70,6 +71,7 @@ struct packet {
int client_port;
struct iaddr client_addr;
int client_sock;
struct subnet *subnet;
struct {
int len;
unsigned char *data;
@@ -91,6 +93,10 @@ struct host_decl {
char *filename;
char *server_name;
struct tree_cache *fixed_addr;
struct tree_cache *ciaddr;
struct tree_cache *yiaddr;
struct tree_cache *siaddr;
struct tree_cache *giaddr;
struct tree_cache *options [256];
};
@@ -106,13 +112,18 @@ struct lease {
struct subnet *contain;
struct hardware hardware_addr;
int state;
int xid;
};
struct subnet {
struct subnet *next;
struct iaddr net;
struct iaddr netmask;
TIME default_lease_time;
TIME max_lease_time;
struct lease *leases;
struct lease *insertion_point;
struct lease *last_lease;
};
/* Bitmask of dhcp option codes. */
@@ -162,6 +173,8 @@ int parse_warn PROTO ((char *, ...));
/* dhcpd.c */
TIME cur_time;
TIME default_lease_time;
TIME max_lease_time;
extern u_int32_t *server_addrlist;
extern int server_addrcount;
extern u_int16_t server_port;
@@ -225,8 +238,11 @@ extern struct subnet *find_subnet (struct iaddr);
void enter_subnet (struct subnet *);
void enter_lease PROTO ((struct lease *));
void supersede_lease PROTO ((struct lease *, struct lease *));
void release_lease PROTO ((struct lease *));
struct lease *find_lease_by_uid PROTO ((unsigned char *, int));
struct lease *find_lease_by_hw_addr PROTO ((unsigned char *, int));
struct lease *find_lease_by_ip_addr PROTO ((struct iaddr));
void dump_subnets PROTO ((void));
/* alloc.c */
VOIDPTR dmalloc PROTO ((int, char *));
@@ -251,6 +267,7 @@ void free_tree PROTO ((struct tree *, char *));
/* print.c */
char *print_hw_addr PROTO ((int, int, unsigned char *));
void print_lease PROTO ((struct lease *));
/* socket.c */
u_int32_t *get_interface_list PROTO ((int *));

View File

@@ -64,7 +64,11 @@
#define LEASE 271
#define RANGE 272
#define PACKET 273
#define LAST_TOKEN PACKET
#define CIADDR 274
#define YIADDR 275
#define SIADDR 276
#define GIADDR 277
#define LAST_TOKEN GIADDR
#define is_identifier(x) ((x) >= FIRST_TOKEN && \
(x) <= LAST_TOKEN && \

4
hash.c
View File

@@ -103,6 +103,7 @@ void add_hash (table, name, len, pointer)
bp -> name = name;
bp -> value = pointer;
bp -> next = table -> buckets [hashno];
bp -> len = len;
table -> buckets [hashno] = bp;
}
@@ -140,10 +141,11 @@ unsigned char *hash_lookup (table, name, len)
struct hash_bucket *bp;
if (len) {
for (bp = table -> buckets [hashno]; bp; bp = bp -> next)
for (bp = table -> buckets [hashno]; bp; bp = bp -> next) {
if (len == bp -> len
&& !memcmp (bp -> name, name, len))
return bp -> value;
}
} else {
for (bp = table -> buckets [hashno]; bp; bp = bp -> next)
if (!strcmp (bp -> name, name))

View File

@@ -53,6 +53,7 @@
#include <stdlib.h>
#include <sys/stat.h>
#include <ctype.h>
#include <time.h>
#include "dhcp.h"
#include "cdefs.h"
@@ -70,6 +71,7 @@ struct packet {
int client_port;
struct iaddr client_addr;
int client_sock;
struct subnet *subnet;
struct {
int len;
unsigned char *data;
@@ -91,6 +93,10 @@ struct host_decl {
char *filename;
char *server_name;
struct tree_cache *fixed_addr;
struct tree_cache *ciaddr;
struct tree_cache *yiaddr;
struct tree_cache *siaddr;
struct tree_cache *giaddr;
struct tree_cache *options [256];
};
@@ -106,13 +112,18 @@ struct lease {
struct subnet *contain;
struct hardware hardware_addr;
int state;
int xid;
};
struct subnet {
struct subnet *next;
struct iaddr net;
struct iaddr netmask;
TIME default_lease_time;
TIME max_lease_time;
struct lease *leases;
struct lease *insertion_point;
struct lease *last_lease;
};
/* Bitmask of dhcp option codes. */
@@ -162,6 +173,8 @@ int parse_warn PROTO ((char *, ...));
/* dhcpd.c */
TIME cur_time;
TIME default_lease_time;
TIME max_lease_time;
extern u_int32_t *server_addrlist;
extern int server_addrcount;
extern u_int16_t server_port;
@@ -225,8 +238,11 @@ extern struct subnet *find_subnet (struct iaddr);
void enter_subnet (struct subnet *);
void enter_lease PROTO ((struct lease *));
void supersede_lease PROTO ((struct lease *, struct lease *));
void release_lease PROTO ((struct lease *));
struct lease *find_lease_by_uid PROTO ((unsigned char *, int));
struct lease *find_lease_by_hw_addr PROTO ((unsigned char *, int));
struct lease *find_lease_by_ip_addr PROTO ((struct iaddr));
void dump_subnets PROTO ((void));
/* alloc.c */
VOIDPTR dmalloc PROTO ((int, char *));
@@ -251,6 +267,7 @@ void free_tree PROTO ((struct tree *, char *));
/* print.c */
char *print_hw_addr PROTO ((int, int, unsigned char *));
void print_lease PROTO ((struct lease *));
/* socket.c */
u_int32_t *get_interface_list PROTO ((int *));

View File

@@ -64,7 +64,11 @@
#define LEASE 271
#define RANGE 272
#define PACKET 273
#define LAST_TOKEN PACKET
#define CIADDR 274
#define YIADDR 275
#define SIADDR 276
#define GIADDR 277
#define LAST_TOKEN GIADDR
#define is_identifier(x) ((x) >= FIRST_TOKEN && \
(x) <= LAST_TOKEN && \

8
inet.c
View File

@@ -87,7 +87,7 @@ struct iaddr ip_addr (subnet, mask, host_address)
j = rv.len - sizeof habuf;
for (i = sizeof habuf - 1; i >= 0; i--) {
if (mask.iabuf [i + j]) {
if (habuf [i] > ~mask.iabuf [i + j]) {
if (habuf [i] > (mask.iabuf [i + j] ^ 0xFF)) {
rv.len = 0;
return rv;
}
@@ -97,10 +97,10 @@ struct iaddr ip_addr (subnet, mask, host_address)
return rv;
}
}
rv.iabuf [i + j] &= habuf [i];
rv.iabuf [i + j] |= habuf [i];
break;
}
rv.iabuf [i + j] = habuf [i];
} else
rv.iabuf [i + j] = habuf [i];
}
return rv;

123
memory.c
View File

@@ -48,7 +48,7 @@ static char copyright[] =
#include "dhcpd.h"
static struct host_decl *hosts;
static struct hash_table *subnet_hash;
static struct subnet *subnets;
static struct hash_table *lease_uid_hash;
static struct hash_table *lease_ip_addr_hash;
static struct hash_table *lease_hw_addr_hash;
@@ -98,12 +98,10 @@ void new_address_range (low, high, netmask)
struct lease *address_range, *lp, *plp;
struct subnet *subnet;
struct iaddr net;
int i, max;
int min, max, i;
char lowbuf [16], highbuf [16], netbuf [16];
/* Initialize the hash table if it hasn't been done yet. */
if (!subnet_hash)
subnet_hash = new_hash ();
if (!lease_uid_hash)
lease_uid_hash = new_hash ();
if (!lease_ip_addr_hash)
@@ -130,32 +128,40 @@ void new_address_range (low, high, netmask)
subnet -> net = net;
subnet -> netmask = netmask;
subnet -> leases = (struct lease *)0;
subnet -> last_lease = (struct lease *)0;
subnet -> next = (struct subnet *)0;
subnet -> default_lease_time = default_lease_time;
subnet -> max_lease_time = max_lease_time;
enter_subnet (subnet);
}
/* Get the high and low host addresses... */
max = host_addr (high, netmask);
i = host_addr (low, netmask);
min = host_addr (low, netmask);
/* Allow range to be specified high-to-low as well as low-to-high. */
if (i > max) {
max = i;
i = host_addr (high, netmask);
if (min > max) {
max = min;
min = host_addr (high, netmask);
}
/* Get a lease structure for each address in the range. */
address_range = new_leases (max - i + 1, "new_address_range");
address_range = new_leases (max - min + 1, "new_address_range");
if (!address_range) {
strcpy (lowbuf, piaddr (low));
strcpy (highbuf, piaddr (high));
error ("No memory for address range %s-%s.", lowbuf, highbuf);
}
memset (address_range, 0, (sizeof *address_range) * (max - i + 1));
memset (address_range, 0, (sizeof *address_range) * (max - min + 1));
/* Fill in the last lease if it hasn't been already... */
if (!subnet -> last_lease)
subnet -> last_lease = &address_range [0];
/* Fill out the lease structures with some minimal information. */
for (; i <= max; i++) {
for (i = 0; i < max - min + 1; i++) {
address_range [i].ip_addr =
ip_addr (subnet -> net, subnet -> netmask, i);
ip_addr (subnet -> net, subnet -> netmask, i + min);
address_range [i].starts =
address_range [i].timestamp = MIN_TIME;
address_range [i].ends = MIN_TIME;
@@ -200,13 +206,16 @@ void new_address_range (low, high, netmask)
}
}
struct subnet *find_subnet (subnet)
struct iaddr subnet;
struct subnet *find_subnet (addr)
struct iaddr addr;
{
struct subnet *rv;
return (struct subnet *)hash_lookup (subnet_hash,
(char *)subnet.iabuf, subnet.len);
for (rv = subnets; rv; rv = rv -> next) {
if (addr_eq (subnet_number (addr, rv -> netmask), rv -> net))
return rv;
}
return (struct subnet *)0;
}
/* Enter a new subnet into the subnet hash. */
@@ -214,8 +223,9 @@ struct subnet *find_subnet (subnet)
void enter_subnet (subnet)
struct subnet *subnet;
{
add_hash (subnet_hash, (char *)subnet -> net.iabuf,
subnet -> net.len, (unsigned char *)subnet);
/* XXX Sort the nets into a balanced tree to make searching quicker. */
subnet -> next = subnets;
subnets = subnet;
}
/* Enter a lease into the system. This is called by the parser each
@@ -259,6 +269,11 @@ void supersede_lease (comp, lease)
struct subnet *parent;
struct lease *lp;
printf ("Supersede_lease:\n");
print_lease (comp);
print_lease (lease);
printf ("\n");
/* If the existing lease hasn't expired and has a different
unique identifier or, if it doesn't have a unique
identifier, a different hardware address, then the two
@@ -290,7 +305,9 @@ void supersede_lease (comp, lease)
enter_uid = 1;
}
free (comp -> uid);
}
} else
enter_uid = 1;
if (comp -> hardware_addr.htype &&
((comp -> hardware_addr.hlen !=
lease -> hardware_addr.hlen) ||
@@ -303,7 +320,8 @@ void supersede_lease (comp, lease)
comp -> hardware_addr.haddr,
comp -> hardware_addr.hlen);
enter_hwaddr = 1;
}
} else if (!comp -> hardware_addr.htype)
enter_hwaddr = 1;
/* Copy the data files, but not the linkages. */
comp -> starts = lease -> starts;
@@ -317,16 +335,16 @@ void supersede_lease (comp, lease)
/* Record the lease in the uid hash if necessary. */
if (enter_uid && lease -> uid) {
add_hash (lease_uid_hash, lease -> uid,
lease -> uid_len, (unsigned char *)lease);
add_hash (lease_uid_hash, comp -> uid,
comp -> uid_len, (unsigned char *)comp);
}
/* Record it in the hardware address hash if necessary. */
if (enter_hwaddr && lease -> hardware_addr.htype) {
add_hash (lease_hw_addr_hash,
lease -> hardware_addr.haddr,
lease -> hardware_addr.hlen,
(unsigned char *)lease);
comp -> hardware_addr.haddr,
comp -> hardware_addr.hlen,
(unsigned char *)comp);
}
/* Remove the lease from its current place in the list. */
@@ -338,6 +356,9 @@ void supersede_lease (comp, lease)
if (comp -> next) {
comp -> next -> prev = comp -> prev;
}
if (comp -> contain -> last_lease == comp) {
comp -> contain -> last_lease = comp -> prev;
}
/* Find the last insertion point... */
if (comp == comp -> contain -> insertion_point ||
@@ -351,18 +372,20 @@ void supersede_lease (comp, lease)
/* Nothing on the list yet? Just make comp the
head of the list. */
comp -> contain -> leases = comp;
} else if (lp -> ends <= comp -> ends) {
comp -> contain -> last_lease = comp;
} else if (lp -> ends > comp -> ends) {
/* Skip down the list until we run out of list
or find a place for comp. */
while (lp -> next && lp -> ends < comp -> ends) {
while (lp -> next && lp -> ends > comp -> ends) {
lp = lp -> next;
}
if (lp -> ends < comp -> ends) {
if (lp -> ends > comp -> ends) {
/* If we ran out of list, put comp
at the end. */
lp -> next = comp;
comp -> prev = lp;
comp -> next = (struct lease *)0;
comp -> contain -> last_lease = comp;
} else {
/* If we didn't, put it between lp and
the previous item on the list. */
@@ -372,12 +395,12 @@ void supersede_lease (comp, lease)
lp -> prev = comp;
}
} else {
/* Skip ip the list until we run out of list
/* Skip up the list until we run out of list
or find a place for comp. */
while (lp -> prev && lp -> ends > comp -> ends) {
while (lp -> prev && lp -> ends < comp -> ends) {
lp = lp -> prev;
}
if (lp -> ends > comp -> ends) {
if (lp -> ends < comp -> ends) {
/* If we ran out of list, put comp
at the beginning. */
lp -> prev = comp;
@@ -397,6 +420,18 @@ void supersede_lease (comp, lease)
}
}
/* Release the specified lease and re-hash it as appropriate. */
void release_lease (lease)
struct lease *lease;
{
struct lease lt;
lease -> ends = 0;
lt = *lease;
supersede_lease (lease, &lt);
}
/* Locate the lease associated with a given IP address... */
struct lease *find_lease_by_ip_addr (addr)
@@ -417,3 +452,29 @@ struct lease *find_lease_by_uid (uid, len)
return lease;
}
struct lease *find_lease_by_hw_addr (hwaddr, hwlen)
unsigned char *hwaddr;
int hwlen;
{
struct lease *lease = (struct lease *)hash_lookup (lease_hw_addr_hash,
hwaddr, hwlen);
return lease;
}
void dump_subnets ()
{
struct lease *l;
struct subnet *s;
int i;
for (s = subnets; s; s = s -> next) {
printf ("Subnet %s", piaddr (s -> net));
printf (" netmask %s\n",
piaddr (s -> netmask));
for (l = s -> leases; l; l = l -> next) {
print_lease (l);
}
printf ("Last Lease:\n");
print_lease (s -> last_lease);
}
}

View File

@@ -94,8 +94,6 @@ void parse_option_buffer (packet, buffer, length)
int len;
int code;
printf ("parse_option_buffer (%x, %x, %d)\n",
(unsigned long)packet, (unsigned long)buffer, length);
for (s = buffer; *s != DHO_END && s < end; ) {
code = s [0];
/* Pad options don't have a length - just skip them. */
@@ -126,8 +124,6 @@ printf ("parse_option_buffer (%x, %x, %d)\n",
t [len] = 0;
packet -> options [code].len = len;
packet -> options [code].data = t;
printf ("%s=%s\n", dhcp_options [code].name,
pretty_print_option (code, t, len));
} else {
/* If it's a repeat, concatenate it to whatever
we last saw. This is really only required

45
print.c
View File

@@ -55,13 +55,46 @@ char *print_hw_addr (htype, hlen, data)
char *s;
int i;
s = habuf;
for (i = 0; i < hlen; i++) {
sprintf (s, "%x", data [i]);
s += strlen (s);
*s++ = ':';
if (htype == 0 || hlen == 0) {
strcpy (habuf, "<null>");
} else {
s = habuf;
for (i = 0; i < hlen; i++) {
sprintf (s, "%x", data [i]);
s += strlen (s);
*s++ = ':';
}
*--s = 0;
}
*--s = 0;
return habuf;
}
void print_lease (lease)
struct lease *lease;
{
struct tm *t;
char tbuf [32];
printf (" Lease %s",
piaddr (lease -> ip_addr));
t = gmtime (&lease -> starts);
strftime (tbuf, sizeof tbuf, "%D %H:%M:%S", t);
printf (" start %s", tbuf);
t = gmtime (&lease -> ends);
strftime (tbuf, sizeof tbuf, "%D %H:%M:%S", t);
printf (" end %s", tbuf);
t = gmtime (&lease -> timestamp);
strftime (tbuf, sizeof tbuf, "%D %H:%M:%S", t);
printf (" stamp %s\n", tbuf);
printf (" hardware addr = %s",
print_hw_addr (lease -> hardware_addr.htype,
lease -> hardware_addr.hlen,
lease -> hardware_addr.haddr));
printf (" host %s state %x\n",
lease -> host ? lease -> host -> name : "<none>",
lease -> state);
}

View File

@@ -234,6 +234,22 @@ void parse_host_decl (cfile, bc, decl)
case OPTION:
parse_option_decl (cfile, bc, decl);
break;
case CIADDR:
decl -> ciaddr =
tree_cache (parse_ip_addr_or_hostname (cfile, bc, 0));
break;
case YIADDR:
decl -> yiaddr =
tree_cache (parse_ip_addr_or_hostname (cfile, bc, 0));
break;
case SIADDR:
decl -> siaddr =
tree_cache (parse_ip_addr_or_hostname (cfile, bc, 0));
break;
case GIADDR:
decl -> giaddr =
tree_cache (parse_ip_addr_or_hostname (cfile, bc, 0));
break;
default:
parse_warn ("expecting a dhcp option declaration.");
skip_to_semi (cfile);

View File

@@ -49,5 +49,205 @@ static char copyright[] =
void dhcp (packet)
struct packet *packet;
{
struct lease *uid_lease, *ip_lease, *hw_lease, *lease;
struct iaddr cip;
struct lease lt;
TIME lease_time;
dump_packet (packet);
/* Try to find a lease that's been assigned to the specified
unique client identifier. */
if (packet -> options [DHO_DHCP_CLIENT_IDENTIFIER].len)
uid_lease =
find_lease_by_uid (packet -> options
[DHO_DHCP_CLIENT_IDENTIFIER].data,
packet -> options
[DHO_DHCP_CLIENT_IDENTIFIER].len);
else
uid_lease = (struct lease *)0;
/* Try to find a lease that's been attached to the client's
hardware address... */
hw_lease = find_lease_by_hw_addr (packet -> raw -> chaddr,
packet -> raw -> hlen);
/* Try to find a lease that's been allocated to the client's
IP address. */
if (packet -> options [DHO_DHCP_REQUESTED_ADDRESS].len &&
packet -> options [DHO_DHCP_REQUESTED_ADDRESS].len
<= sizeof cip.iabuf) {
cip.len = packet -> options [DHO_DHCP_REQUESTED_ADDRESS].len;
memcpy (cip.iabuf,
packet -> options [DHO_DHCP_REQUESTED_ADDRESS].data,
packet -> options [DHO_DHCP_REQUESTED_ADDRESS].len);
memcpy (cip.iabuf, &packet -> raw -> ciaddr, 4);
ip_lease = find_lease_by_ip_addr (cip);
} else
ip_lease = (struct lease *)0;
printf ("First blush:\n");
if (ip_lease) {
printf ("ip_lease: ");
print_lease (ip_lease);
}
if (hw_lease) {
printf ("hw_lease: ");
print_lease (hw_lease);
}
if (uid_lease) {
printf ("uid_lease: ");
print_lease (uid_lease);
}
/* Toss extra pointers to the same lease... */
if (ip_lease == hw_lease)
ip_lease = (struct lease *)0;
if (hw_lease == uid_lease)
hw_lease = (struct lease *)0;
if (ip_lease == uid_lease)
ip_lease = (struct lease *)0;
printf ("Second blush:\n");
if (ip_lease) {
printf ("ip_lease: ");
print_lease (ip_lease);
}
if (hw_lease) {
printf ("hw_lease: ");
print_lease (hw_lease);
}
if (uid_lease) {
printf ("uid_lease: ");
print_lease (uid_lease);
}
/* If we got an ip address lease, make sure it isn't assigned to
some *other* client! If it was assigned to this client, we'd
have zeroed it out above, so the only way we can take it at this
point is if some other client had it but it's timed out, or if no
other client has ever had it. */
if (ip_lease &&
ip_lease -> ends >= cur_time)
ip_lease = (struct lease *)0;
/* Now eliminate leases that are on the wrong subnet... */
if (ip_lease && packet -> subnet != ip_lease -> contain) {
release_lease (ip_lease);
ip_lease = (struct lease *)0;
}
if (uid_lease && packet -> subnet != uid_lease -> contain) {
release_lease (uid_lease);
uid_lease = (struct lease *)0;
}
if (hw_lease && packet -> subnet != hw_lease -> contain) {
release_lease (hw_lease);
hw_lease = (struct lease *)0;
}
printf ("Third blush:\n");
if (ip_lease) {
printf ("ip_lease: ");
print_lease (ip_lease);
}
if (hw_lease) {
printf ("hw_lease: ");
print_lease (hw_lease);
}
if (uid_lease) {
printf ("uid_lease: ");
print_lease (uid_lease);
}
/* At this point, if ip_lease is nonzero, we can assign it to
this client. */
lease = ip_lease;
/* If we got a lease that matched the client identifier, we may want
to use it, but if we already have a lease we like, we must free
the lease that matched the client identifier. */
if (uid_lease) {
if (lease) {
release_lease (uid_lease);
} else
lease = uid_lease;
}
/* The lease that matched the hardware address is treated likewise. */
if (hw_lease) {
if (lease) {
release_lease (hw_lease);
} else
lease = hw_lease;
}
/* If we didn't find a lease, try to allocate one... */
if (!lease) {
lease = packet -> subnet -> last_lease;
/* If there are no leases in that subnet that have
expired, we have nothing to offer this client. */
if (lease -> ends >= cur_time) {
note ("no free leases on subnet %s",
piaddr (packet -> subnet -> net));
return;
}
lease -> host = (struct host_decl *)0;
}
/* At this point, we have a lease that we can offer the client.
Now we construct a lease structure that contains what we want,
and call supersede_lease to do the right thing with it. */
memset (&lt, 0, sizeof lt);
/* Use the ip address of the lease that we finally found in
the database. */
lt.ip_addr = lease -> ip_addr;
/* Start now. */
lt.starts = cur_time;
/* Figure out how long a lease to assign. */
if (packet -> options [DHO_DHCP_LEASE_TIME].len == 4) {
lease_time = getULong (packet ->
options [DHO_DHCP_LEASE_TIME].data);
/* Don't let the client ask for a longer lease than
is supported for this subnet. */
if (lease_time > packet -> subnet -> max_lease_time)
lease_time = packet -> subnet -> max_lease_time;
} else
lease_time = packet -> subnet -> default_lease_time;
lt.ends = cur_time + lease_time;
lt.timestamp = cur_time;
/* Record the uid, if given... */
if (packet -> options [DHO_DHCP_CLIENT_IDENTIFIER].len) {
lt.uid_len =
packet -> options [DHO_DHCP_CLIENT_IDENTIFIER].len;
lt.uid = packet -> options [DHO_DHCP_CLIENT_IDENTIFIER].data;
packet -> options [DHO_DHCP_CLIENT_IDENTIFIER].data =
(unsigned char *)0;
packet -> options [DHO_DHCP_CLIENT_IDENTIFIER].len = 0;
}
/* Record the hardware address, if given... */
lt.hardware_addr.hlen = packet -> raw -> hlen;
lt.hardware_addr.htype = packet -> raw -> htype;
memcpy (lt.hardware_addr.haddr, packet -> raw -> chaddr,
packet -> raw -> hlen);
lt.host = lease -> host; /* XXX */
lt.contain = lease -> contain;
/* Record the transaction id... */
lt.xid = packet -> raw -> xid;
/* Install the new information about this lease in the database. */
supersede_lease (lease, &lt);
/* Send a response to the client... */
dump_subnets ();
}

View File

@@ -50,7 +50,10 @@ static char copyright[] =
static void usage PROTO ((void));
TIME cur_time;
TIME default_lease_time = 43200; /* 12 hours... */
TIME max_lease_time = 86400; /* 24 hours... */
struct subnet *local_subnet;
u_int32_t *server_addrlist;
int server_addrcount;
u_int16_t server_port;
@@ -63,6 +66,7 @@ int main (argc, argv, envp)
int port = 0;
int i;
struct sockaddr_in name;
struct iaddr taddr;
u_int32_t *addrlist = (u_int32_t *)0;
int addrcount = 0;
struct tree *addrtree = (struct tree *)0;
@@ -148,7 +152,23 @@ int main (argc, argv, envp)
}
#endif
taddr.len = 0;
server_addrlist = get_interface_list (&server_addrcount);
for (i = 0; i < server_addrcount; i++) {
struct sockaddr_in foo;
foo.sin_addr.s_addr = server_addrlist [i];
printf ("Address %d: %s\n", i, inet_ntoa (foo.sin_addr));
if (server_addrlist [i] != htonl (INADDR_LOOPBACK)) {
if (taddr.len) {
error ("dhcpd currently does not support "
"multiple interfaces");
}
taddr.len = 4;
memcpy (taddr.iabuf, &server_addrlist [i], 4);
local_subnet = find_subnet (taddr);
}
}
/* Listen on the specified (or default) port on each specified
(or default) IP address. */
@@ -164,6 +184,8 @@ int main (argc, argv, envp)
close (i);
}
dump_subnets ();
/* Receive packets and dispatch them... */
dispatch ();
@@ -191,6 +213,7 @@ void do_packet (packbuf, len, from_port, from, sock)
{
struct packet *tp;
struct dhcp_packet *tdp;
struct iaddr ia;
if (!(tp = new_packet ("do_packet")))
return;
@@ -205,12 +228,29 @@ void do_packet (packbuf, len, from_port, from, sock)
tp -> client_port = from_port;
tp -> client_addr = from;
tp -> client_sock = sock;
parse_options (tp);
if (tp -> options_valid &&
tp -> options [DHO_DHCP_MESSAGE_TYPE].data)
dhcp (tp);
else
bootp (tp);
/* If this came through a gateway, find the corresponding subnet... */
if (tp -> raw -> giaddr.s_addr) {
ia.len = 4;
memcpy (ia.iabuf, &tp -> raw -> giaddr, 4);
tp -> subnet = find_subnet (ia);
} else {
tp -> subnet = local_subnet;
}
/* If the subnet from whence this packet came is unknown to us,
drop it on the floor... */
if (!tp -> subnet)
note ("Packet from unknown subnet: %s",
inet_ntoa (tp -> raw -> giaddr));
else {
parse_options (tp);
if (tp -> options_valid &&
tp -> options [DHO_DHCP_MESSAGE_TYPE].data)
dhcp (tp);
else
bootp (tp);
}
}
void dump_packet (tp)

View File

@@ -1,4 +1,5 @@
range 204.254.239.11 204.254.239.254 255.255.255.0;
range 204.254.239.11 204.254.239.17 255.255.255.0;
range 204.254.240.11 204.254.240.12 255.255.255.0;
host minuet
hardware ethernet 08:00:2b:35:0c:18

View File

@@ -184,6 +184,9 @@ void dispatch ()
/* Wait for a packet or a timeout... XXX */
count = select (max + 1, &r, &w, &x, (struct timeval *)0);
/* Get the current time... */
GET_TIME (&cur_time);
/* Not likely to be transitory... */
if (count < 0)
error ("select: %m");