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:
6
Makefile
6
Makefile
@@ -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
|
@@ -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;
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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))
|
||||
|
@@ -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
common/memory.c
123
common/memory.c
@@ -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, <);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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");
|
||||
|
12
conflex.c
12
conflex.c
@@ -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;
|
||||
}
|
||||
|
16
confpars.c
16
confpars.c
@@ -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);
|
||||
|
50
dhclient.c
50
dhclient.c
@@ -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
200
dhcp.c
@@ -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 (<, 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, <);
|
||||
|
||||
/* Send a response to the client... */
|
||||
dump_subnets ();
|
||||
}
|
||||
|
52
dhcpd.c
52
dhcpd.c
@@ -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)
|
||||
|
@@ -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
17
dhcpd.h
@@ -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 *));
|
||||
|
@@ -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
4
hash.c
@@ -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))
|
||||
|
@@ -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 *));
|
||||
|
@@ -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
8
inet.c
@@ -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
123
memory.c
@@ -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, <);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
|
@@ -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
45
print.c
@@ -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);
|
||||
}
|
||||
|
@@ -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);
|
||||
|
200
server/dhcp.c
200
server/dhcp.c
@@ -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 (<, 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, <);
|
||||
|
||||
/* Send a response to the client... */
|
||||
dump_subnets ();
|
||||
}
|
||||
|
@@ -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)
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user