mirror of
https://gitlab.isc.org/isc-projects/dhcp
synced 2025-09-02 07:15:44 +00:00
Incremental changes to support DHCP protocol
This commit is contained in:
@@ -105,12 +105,15 @@ int main (argc, argv, envp)
|
||||
FD_ZERO (&w);
|
||||
FD_ZERO (&x);
|
||||
FD_SET (sock, &r);
|
||||
FD_SET (sock, &w);
|
||||
FD_SET (sock, &x);
|
||||
FD_SET (0, &r); /* stdin */
|
||||
|
||||
if (select (sock + 1, &r, &w, &x, (struct timeval *)0) < 0) {
|
||||
error ("select: %m");
|
||||
}
|
||||
if (FD_ISSET (sock, &r)) {
|
||||
if (FD_ISSET (sock, &r) || FD_ISSET (sock, &w)
|
||||
|| FD_ISSET (sock, &x)) {
|
||||
if ((result =
|
||||
recvfrom (sock, packbuf, sizeof packbuf, 0,
|
||||
(struct sockaddr *)&from, &fromlen))
|
||||
@@ -188,7 +191,7 @@ int main (argc, argv, envp)
|
||||
}
|
||||
|
||||
cons_options ((struct packet *)0,
|
||||
&outgoing, &decl, bufs);
|
||||
&outgoing, decl.options, bufs);
|
||||
|
||||
if (decl.ciaddr) {
|
||||
tree_evaluate (decl.ciaddr);
|
||||
|
@@ -277,6 +277,10 @@ static int intern (atom, dfv)
|
||||
if (!strcasecmp (atom + 1, "iaddr"))
|
||||
return CIADDR;
|
||||
break;
|
||||
case 'd':
|
||||
if (!strcasecmp (atom + 1, "efault-lease-time"))
|
||||
return DEFAULT_LEASE_TIME;
|
||||
break;
|
||||
case 'e':
|
||||
if (!strcasecmp (atom + 1, "thernet"))
|
||||
return ETHERNET;
|
||||
@@ -303,6 +307,14 @@ static int intern (atom, dfv)
|
||||
if (!strcasecmp (atom + 1, "ease"))
|
||||
return LEASE;
|
||||
break;
|
||||
case 'm':
|
||||
if (!strcasecmp (atom + 1, "ax-lease-time"))
|
||||
return MAX_LEASE_TIME;
|
||||
break;
|
||||
case 'n':
|
||||
if (!strcasecmp (atom + 1, "etmask"))
|
||||
return NETMASK;
|
||||
break;
|
||||
case 'p':
|
||||
if (!strcasecmp (atom + 1, "acket"))
|
||||
return PACKET;
|
||||
@@ -320,6 +332,8 @@ static int intern (atom, dfv)
|
||||
return STARTS;
|
||||
if (!strcasecmp (atom + 1, "iaddr"))
|
||||
return SIADDR;
|
||||
if (!strcasecmp (atom + 1, "ubnet"))
|
||||
return SUBNET;
|
||||
break;
|
||||
case 't':
|
||||
if (!strcasecmp (atom + 1, "timestamp"))
|
||||
|
@@ -92,11 +92,11 @@ struct host_decl *find_host_by_addr (htype, haddr, hlen)
|
||||
return (struct host_decl *)0;
|
||||
}
|
||||
|
||||
void new_address_range (low, high, netmask)
|
||||
struct iaddr low, high, netmask;
|
||||
void new_address_range (low, high, subnet)
|
||||
struct iaddr low, high;
|
||||
struct subnet *subnet;
|
||||
{
|
||||
struct lease *address_range, *lp, *plp;
|
||||
struct subnet *subnet;
|
||||
struct iaddr net;
|
||||
int min, max, i;
|
||||
char lowbuf [16], highbuf [16], netbuf [16];
|
||||
@@ -110,39 +110,23 @@ void new_address_range (low, high, netmask)
|
||||
lease_hw_addr_hash = new_hash ();
|
||||
|
||||
/* Make sure that high and low addresses are in same subnet. */
|
||||
net = subnet_number (low, netmask);
|
||||
if (!addr_eq (net, subnet_number (high, netmask))) {
|
||||
net = subnet_number (low, subnet -> netmask);
|
||||
if (!addr_eq (net, subnet_number (high, subnet -> netmask))) {
|
||||
strcpy (lowbuf, piaddr (low));
|
||||
strcpy (highbuf, piaddr (high));
|
||||
strcpy (netbuf, piaddr (netmask));
|
||||
strcpy (netbuf, piaddr (subnet -> netmask));
|
||||
error ("Address range %s to %s, netmask %s spans %s!",
|
||||
lowbuf, highbuf, netbuf, "multiple subnets");
|
||||
}
|
||||
|
||||
/* See if this subnet is already known - if not, make a new one. */
|
||||
subnet = find_subnet (net);
|
||||
if (!subnet) {
|
||||
subnet = new_subnet ("new_address_range");
|
||||
if (!subnet)
|
||||
error ("No memory for new subnet");
|
||||
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);
|
||||
min = host_addr (low, netmask);
|
||||
max = host_addr (high, subnet -> netmask);
|
||||
min = host_addr (low, subnet -> netmask);
|
||||
|
||||
/* Allow range to be specified high-to-low as well as low-to-high. */
|
||||
if (min > max) {
|
||||
max = min;
|
||||
min = host_addr (high, netmask);
|
||||
min = host_addr (high, subnet -> netmask);
|
||||
}
|
||||
|
||||
/* Get a lease structure for each address in the range. */
|
||||
@@ -155,8 +139,9 @@ void new_address_range (low, high, netmask)
|
||||
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)
|
||||
if (!subnet -> last_lease) {
|
||||
subnet -> last_lease = &address_range [0];
|
||||
}
|
||||
|
||||
/* Fill out the lease structures with some minimal information. */
|
||||
for (i = 0; i < max - min + 1; i++) {
|
||||
@@ -269,11 +254,6 @@ 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
|
||||
@@ -325,7 +305,6 @@ printf ("\n");
|
||||
|
||||
/* Copy the data files, but not the linkages. */
|
||||
comp -> starts = lease -> starts;
|
||||
comp -> ends = lease -> ends;
|
||||
comp -> timestamp = lease -> timestamp;
|
||||
comp -> uid = lease -> uid;
|
||||
comp -> uid_len = lease -> uid_len;
|
||||
@@ -373,13 +352,13 @@ printf ("\n");
|
||||
head of the list. */
|
||||
comp -> contain -> leases = comp;
|
||||
comp -> contain -> last_lease = comp;
|
||||
} else if (lp -> ends > comp -> ends) {
|
||||
} else if (lp -> ends > lease -> 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 > lease -> ends) {
|
||||
lp = lp -> next;
|
||||
}
|
||||
if (lp -> ends > comp -> ends) {
|
||||
if (lp -> ends > lease -> ends) {
|
||||
/* If we ran out of list, put comp
|
||||
at the end. */
|
||||
lp -> next = comp;
|
||||
@@ -389,7 +368,7 @@ printf ("\n");
|
||||
} else {
|
||||
/* If we didn't, put it between lp and
|
||||
the previous item on the list. */
|
||||
comp -> prev = lp -> prev;
|
||||
if ((comp -> prev = lp -> prev))
|
||||
comp -> prev -> next = comp;
|
||||
comp -> next = lp;
|
||||
lp -> prev = comp;
|
||||
@@ -397,10 +376,10 @@ printf ("\n");
|
||||
} else {
|
||||
/* 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 < lease -> ends) {
|
||||
lp = lp -> prev;
|
||||
}
|
||||
if (lp -> ends < comp -> ends) {
|
||||
if (lp -> ends < lease -> ends) {
|
||||
/* If we ran out of list, put comp
|
||||
at the beginning. */
|
||||
lp -> prev = comp;
|
||||
@@ -410,13 +389,14 @@ printf ("\n");
|
||||
} else {
|
||||
/* If we didn't, put it between lp and
|
||||
the next item on the list. */
|
||||
comp -> next = lp -> next;
|
||||
if ((comp -> next = lp -> next))
|
||||
comp -> next -> prev = comp;
|
||||
comp -> prev = lp;
|
||||
lp -> next = comp;
|
||||
}
|
||||
}
|
||||
comp -> contain -> insertion_point = comp;
|
||||
comp -> ends = lease -> ends;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -427,8 +407,8 @@ void release_lease (lease)
|
||||
{
|
||||
struct lease lt;
|
||||
|
||||
lease -> ends = 0;
|
||||
lt = *lease;
|
||||
lt.ends = cur_time;
|
||||
supersede_lease (lease, <);
|
||||
}
|
||||
|
||||
|
@@ -150,10 +150,10 @@ void parse_option_buffer (packet, buffer, length)
|
||||
/* Cons up options based on client-supplied desired option list (if any)
|
||||
and selected server option list. */
|
||||
|
||||
void cons_options (inpacket, outpacket, hp, overload)
|
||||
void cons_options (inpacket, outpacket, options, overload)
|
||||
struct packet *inpacket;
|
||||
struct packet *outpacket;
|
||||
struct host_decl *hp;
|
||||
struct tree_cache **options;
|
||||
int overload; /* Overload flags that may be set. */
|
||||
{
|
||||
option_mask options_have; /* Options we can send. */
|
||||
@@ -217,7 +217,7 @@ void cons_options (inpacket, outpacket, hp, overload)
|
||||
/* Make a bitmask of all the options we have available. */
|
||||
OPTION_ZERO (options_have);
|
||||
for (i = 0; i < 256; i++)
|
||||
if (hp -> options [i])
|
||||
if (options [i])
|
||||
OPTION_SET (options_have, i);
|
||||
|
||||
/* Put the cookie up front... */
|
||||
@@ -235,7 +235,7 @@ void cons_options (inpacket, outpacket, hp, overload)
|
||||
int length;
|
||||
|
||||
/* If no data is available for this option, skip it. */
|
||||
if (!hp -> options [code])
|
||||
if (!options [code])
|
||||
continue;
|
||||
|
||||
/* Don't look at options that have already been stored. */
|
||||
@@ -243,11 +243,11 @@ void cons_options (inpacket, outpacket, hp, overload)
|
||||
continue;
|
||||
|
||||
/* Find the value of the option... */
|
||||
if (!tree_evaluate (hp -> options [code]))
|
||||
if (!tree_evaluate (options [code]))
|
||||
continue;
|
||||
|
||||
/* We should now have a constant length for the option. */
|
||||
length = (hp -> options [code] -> len - stored_length [code]);
|
||||
length = (options [code] -> len - stored_length [code]);
|
||||
|
||||
/* If there's no space for this option, skip it. */
|
||||
if ((bufix + OPTION_SPACE (length) + reserved) > buflen) {
|
||||
@@ -260,7 +260,7 @@ void cons_options (inpacket, outpacket, hp, overload)
|
||||
}
|
||||
|
||||
/* Otherwise, store the option. */
|
||||
result = store_option (hp, code,
|
||||
result = store_option (options, code,
|
||||
buffer + bufix,
|
||||
buflen - bufix - reserved,
|
||||
stored_length);
|
||||
@@ -268,16 +268,16 @@ void cons_options (inpacket, outpacket, hp, overload)
|
||||
|
||||
/* The following test should always succeed because of
|
||||
preconditioning above. */
|
||||
if (stored_length [code] == hp -> options [code] -> len)
|
||||
if (stored_length [code] == options [code] -> len)
|
||||
OPTION_SET (options_done, code);
|
||||
else {
|
||||
warn ("%s: Only stored %d out of %d bytes.",
|
||||
dhcp_options [code].name,
|
||||
stored_length [code],
|
||||
hp -> options [code] -> len);
|
||||
options [code] -> len);
|
||||
if (++missed == 1) {
|
||||
missed_code = code;
|
||||
missed_length = hp -> options [code] -> len
|
||||
missed_length = options [code] -> len
|
||||
- stored_length [code];
|
||||
}
|
||||
}
|
||||
@@ -300,20 +300,20 @@ void cons_options (inpacket, outpacket, hp, overload)
|
||||
overloading. */
|
||||
if (reserved && missed == 1
|
||||
&& (bufix + OPTION_SPACE (missed_length) <= buflen)) {
|
||||
result = store_option (hp, missed_code,
|
||||
result = store_option (options, missed_code,
|
||||
buffer + bufix, buflen - bufix,
|
||||
stored_length);
|
||||
bufix += result;
|
||||
/* This test should always fail -- we'll send bad
|
||||
data if it doesn't. */
|
||||
if (stored_length [missed_code]
|
||||
== hp -> options [missed_code] -> len) {
|
||||
== options [missed_code] -> len) {
|
||||
OPTION_SET (options_done, missed_code);
|
||||
} else {
|
||||
warn ("%s (last): Only stored %d out of %d bytes.",
|
||||
dhcp_options [missed_code].name,
|
||||
stored_length [missed_code],
|
||||
hp -> options [missed_code] -> len);
|
||||
options [missed_code] -> len);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -323,7 +323,7 @@ void cons_options (inpacket, outpacket, hp, overload)
|
||||
option into the current buffer and part into the next. */
|
||||
if (bufix + OPTION_SPACE (missed_length) + reserved
|
||||
< buflen + (overload & 1 ? 128 : 0) + (overload & 2 ? 64 : 0)) {
|
||||
result = store_option (hp, missed_code,
|
||||
result = store_option (options, missed_code,
|
||||
buffer + bufix,
|
||||
buflen - bufix - reserved,
|
||||
stored_length);
|
||||
@@ -331,7 +331,7 @@ void cons_options (inpacket, outpacket, hp, overload)
|
||||
|
||||
/* This test should never fail. */
|
||||
if (stored_length [missed_code]
|
||||
== hp -> options [missed_code] -> len) {
|
||||
== options [missed_code] -> len) {
|
||||
OPTION_SET (options_done, missed_code);
|
||||
warn ("%s: Unexpected completed store.",
|
||||
dhcp_options [missed_code].name);
|
||||
@@ -391,17 +391,17 @@ void cons_options (inpacket, outpacket, hp, overload)
|
||||
data that has been stored so far. Return 1 if all the option data
|
||||
has been stored. */
|
||||
|
||||
int store_option (hp, code, buffer, buflen, stored_length)
|
||||
struct host_decl *hp;
|
||||
int store_option (options, code, buffer, buflen, stored_length)
|
||||
struct tree_cache **options;
|
||||
unsigned char code;
|
||||
unsigned char *buffer;
|
||||
int buflen;
|
||||
int *stored_length;
|
||||
{
|
||||
int length = hp -> options [code] -> len - stored_length [code];
|
||||
int length = options [code] -> len - stored_length [code];
|
||||
int bufix = 0;
|
||||
printf ("store_option: length = %d buflen = %d packet %d stored %d\n",
|
||||
length, buflen, hp -> options [code] -> len, stored_length [code]);
|
||||
length, buflen, options [code] -> len, stored_length [code]);
|
||||
if (length > buflen) {
|
||||
length = buflen;
|
||||
}
|
||||
@@ -415,7 +415,7 @@ printf ("store_option: length = %d buflen = %d packet %d stored %d\n",
|
||||
unsigned char incr = length > 255 ? 255 : length;
|
||||
buffer [bufix] = code;
|
||||
buffer [bufix + 1] = incr;
|
||||
memcpy (buffer + bufix + 2, (hp -> options [code] -> value
|
||||
memcpy (buffer + bufix + 2, (options [code] -> value
|
||||
+ stored_length [code]), incr);
|
||||
length -= incr;
|
||||
stored_length [code] += incr;
|
||||
|
@@ -326,6 +326,17 @@ struct option dhcp_options [256] = {
|
||||
/* Default dhcp option priority list (this is ad hoc and should not be
|
||||
mistaken for a carefully crafted and optimized list). */
|
||||
unsigned char dhcp_option_default_priority_list [] = {
|
||||
DHO_DHCP_REQUESTED_ADDRESS,
|
||||
DHO_DHCP_LEASE_TIME,
|
||||
DHO_DHCP_MESSAGE_TYPE,
|
||||
DHO_DHCP_OPTION_OVERLOAD,
|
||||
DHO_DHCP_SERVER_IDENTIFIER,
|
||||
DHO_DHCP_MESSAGE,
|
||||
DHO_DHCP_MAX_MESSAGE_SIZE,
|
||||
DHO_DHCP_RENEWAL_TIME,
|
||||
DHO_DHCP_REBINDING_TIME,
|
||||
DHO_DHCP_CLASS_IDENTIFIER,
|
||||
DHO_DHCP_CLIENT_IDENTIFIER,
|
||||
DHO_SUBNET_MASK,
|
||||
DHO_TIME_OFFSET,
|
||||
DHO_ROUTERS,
|
||||
@@ -375,18 +386,7 @@ unsigned char dhcp_option_default_priority_list [] = {
|
||||
DHO_NETBIOS_SCOPE,
|
||||
DHO_FONT_SERVERS,
|
||||
DHO_X_DISPLAY_MANAGER,
|
||||
DHO_DHCP_REQUESTED_ADDRESS,
|
||||
DHO_DHCP_LEASE_TIME,
|
||||
DHO_DHCP_OPTION_OVERLOAD,
|
||||
DHO_DHCP_MESSAGE_TYPE,
|
||||
DHO_DHCP_SERVER_IDENTIFIER,
|
||||
DHO_DHCP_PARAMETER_REQUEST_LIST,
|
||||
DHO_DHCP_MESSAGE,
|
||||
DHO_DHCP_MAX_MESSAGE_SIZE,
|
||||
DHO_DHCP_RENEWAL_TIME,
|
||||
DHO_DHCP_REBINDING_TIME,
|
||||
DHO_DHCP_CLASS_IDENTIFIER,
|
||||
DHO_DHCP_CLIENT_IDENTIFIER,
|
||||
};
|
||||
|
||||
int sizeof_dhcp_option_default_priority_list =
|
||||
|
14
conflex.c
14
conflex.c
@@ -277,6 +277,10 @@ static int intern (atom, dfv)
|
||||
if (!strcasecmp (atom + 1, "iaddr"))
|
||||
return CIADDR;
|
||||
break;
|
||||
case 'd':
|
||||
if (!strcasecmp (atom + 1, "efault-lease-time"))
|
||||
return DEFAULT_LEASE_TIME;
|
||||
break;
|
||||
case 'e':
|
||||
if (!strcasecmp (atom + 1, "thernet"))
|
||||
return ETHERNET;
|
||||
@@ -303,6 +307,14 @@ static int intern (atom, dfv)
|
||||
if (!strcasecmp (atom + 1, "ease"))
|
||||
return LEASE;
|
||||
break;
|
||||
case 'm':
|
||||
if (!strcasecmp (atom + 1, "ax-lease-time"))
|
||||
return MAX_LEASE_TIME;
|
||||
break;
|
||||
case 'n':
|
||||
if (!strcasecmp (atom + 1, "etmask"))
|
||||
return NETMASK;
|
||||
break;
|
||||
case 'p':
|
||||
if (!strcasecmp (atom + 1, "acket"))
|
||||
return PACKET;
|
||||
@@ -320,6 +332,8 @@ static int intern (atom, dfv)
|
||||
return STARTS;
|
||||
if (!strcasecmp (atom + 1, "iaddr"))
|
||||
return SIADDR;
|
||||
if (!strcasecmp (atom + 1, "ubnet"))
|
||||
return SUBNET;
|
||||
break;
|
||||
case 't':
|
||||
if (!strcasecmp (atom + 1, "timestamp"))
|
||||
|
143
confpars.c
143
confpars.c
@@ -102,9 +102,9 @@ void parse_statement (cfile)
|
||||
parsed_time = parse_timestamp (cfile, &bc);
|
||||
}
|
||||
break;
|
||||
case RANGE:
|
||||
case SUBNET:
|
||||
if (!setjmp (bc)) {
|
||||
parse_address_range (cfile, &bc);
|
||||
parse_subnet_statement (cfile, &bc);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -209,6 +209,113 @@ char *parse_host_name (cfile, bc)
|
||||
return s;
|
||||
}
|
||||
|
||||
/* subnet_statement :== SUBNET net NETMASK netmask declarations SEMI
|
||||
host_declarations :== <nil> | host_declaration
|
||||
| host_declarations host_declaration SEMI */
|
||||
|
||||
struct subnet *parse_subnet_statement (cfile, bc)
|
||||
FILE *cfile;
|
||||
jmp_buf *bc;
|
||||
{
|
||||
char *val;
|
||||
int token;
|
||||
struct subnet *subnet;
|
||||
struct iaddr net, netmask;
|
||||
unsigned char addr [4];
|
||||
int len = sizeof addr;
|
||||
|
||||
subnet = new_subnet ("parse_subnet_statement");
|
||||
if (!subnet)
|
||||
error ("No memory for new subnet");
|
||||
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;
|
||||
|
||||
/* Get the network number... */
|
||||
parse_numeric_aggregate (cfile, bc, addr, &len, DOT, 10, 8);
|
||||
memcpy (net.iabuf, addr, len);
|
||||
net.len = len;
|
||||
subnet -> net = net;
|
||||
|
||||
token = next_token (&val, cfile);
|
||||
if (token != NETMASK) {
|
||||
parse_warn ("Expecting netmask");
|
||||
skip_to_semi (cfile);
|
||||
longjmp (*bc, 1);
|
||||
}
|
||||
|
||||
/* Get the netmask... */
|
||||
parse_numeric_aggregate (cfile, bc, addr, &len, DOT, 10, 8);
|
||||
memcpy (netmask.iabuf, addr, len);
|
||||
netmask.len = len;
|
||||
subnet -> netmask = netmask;
|
||||
|
||||
enter_subnet (subnet);
|
||||
|
||||
do {
|
||||
token = peek_token (&val, cfile);
|
||||
if (token == SEMI) {
|
||||
token = next_token (&val, cfile);
|
||||
break;
|
||||
}
|
||||
parse_subnet_decl (cfile, bc, subnet);
|
||||
} while (1);
|
||||
return subnet;
|
||||
}
|
||||
|
||||
/* subnet_declaration :== hardware_declaration | filename_declaration
|
||||
| fixed_addr_declaration | option_declaration */
|
||||
|
||||
void parse_subnet_decl (cfile, bc, decl)
|
||||
FILE *cfile;
|
||||
jmp_buf *bc;
|
||||
struct subnet *decl;
|
||||
{
|
||||
char *val;
|
||||
int token;
|
||||
|
||||
token = next_token (&val, cfile);
|
||||
switch (token) {
|
||||
case RANGE:
|
||||
parse_address_range (cfile, bc, decl);
|
||||
break;
|
||||
|
||||
case OPTION:
|
||||
parse_option_decl (cfile, bc, decl -> options);
|
||||
break;
|
||||
|
||||
case DEFAULT_LEASE_TIME:
|
||||
token = next_token (&val, cfile);
|
||||
if (token != NUMBER) {
|
||||
parse_warn ("Expecting numeric default lease time");
|
||||
skip_to_semi (cfile);
|
||||
longjmp (*bc, 1);
|
||||
}
|
||||
convert_num ((unsigned char *)&decl -> default_lease_time,
|
||||
val, 10, 4);
|
||||
break;
|
||||
|
||||
case MAX_LEASE_TIME:
|
||||
token = next_token (&val, cfile);
|
||||
if (token != NUMBER) {
|
||||
parse_warn ("Expecting numeric max lease time");
|
||||
skip_to_semi (cfile);
|
||||
longjmp (*bc, 1);
|
||||
}
|
||||
convert_num ((unsigned char *)&decl -> max_lease_time,
|
||||
val, 10, 4);
|
||||
break;
|
||||
|
||||
default:
|
||||
parse_warn ("expecting a subnet declaration.");
|
||||
skip_to_semi (cfile);
|
||||
longjmp (*bc, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* host_declaration :== hardware_declaration | filename_declaration
|
||||
| fixed_addr_declaration | option_declaration */
|
||||
|
||||
@@ -232,7 +339,7 @@ void parse_host_decl (cfile, bc, decl)
|
||||
parse_fixed_addr_decl (cfile, bc, decl);
|
||||
break;
|
||||
case OPTION:
|
||||
parse_option_decl (cfile, bc, decl);
|
||||
parse_option_decl (cfile, bc, decl -> options);
|
||||
break;
|
||||
case CIADDR:
|
||||
decl -> ciaddr =
|
||||
@@ -400,10 +507,10 @@ void parse_fixed_addr_decl (cfile, bc, decl)
|
||||
would be painful to come up with BNF for it. However, it always
|
||||
starts as above. */
|
||||
|
||||
void parse_option_decl (cfile, bc, decl)
|
||||
void parse_option_decl (cfile, bc, options)
|
||||
FILE *cfile;
|
||||
jmp_buf *bc;
|
||||
struct host_decl *decl;
|
||||
struct tree_cache **options;
|
||||
{
|
||||
char *val;
|
||||
int token;
|
||||
@@ -570,11 +677,11 @@ void parse_option_decl (cfile, bc, decl)
|
||||
}
|
||||
} while (*fmt == 'A');
|
||||
|
||||
if (decl -> options [option -> code]) {
|
||||
if (options [option -> code]) {
|
||||
parse_warn ("duplicate option code %d (%s).",
|
||||
option -> code, option -> name);
|
||||
}
|
||||
decl -> options [option -> code] = tree_cache (tree);
|
||||
options [option -> code] = tree_cache (tree);
|
||||
}
|
||||
|
||||
/* timestamp :== TIMESTAMP date SEMI
|
||||
@@ -724,13 +831,14 @@ struct lease *parse_lease_statement (cfile, bc)
|
||||
return &lease;
|
||||
}
|
||||
|
||||
/* address_range :== RANGE ip_address ip_address ip_address SEMI */
|
||||
/* address_range :== RANGE ip_address ip_address */
|
||||
|
||||
void parse_address_range (cfile, bc)
|
||||
void parse_address_range (cfile, bc, subnet)
|
||||
FILE *cfile;
|
||||
jmp_buf *bc;
|
||||
struct subnet *subnet;
|
||||
{
|
||||
struct iaddr low, high, mask;
|
||||
struct iaddr low, high;
|
||||
unsigned char addr [4];
|
||||
int len = sizeof addr;
|
||||
int token;
|
||||
@@ -746,21 +854,8 @@ void parse_address_range (cfile, bc)
|
||||
memcpy (high.iabuf, addr, len);
|
||||
high.len = len;
|
||||
|
||||
/* Get the netmask of the subnet containing the range... */
|
||||
parse_numeric_aggregate (cfile, bc, addr, &len, DOT, 10, 8);
|
||||
memcpy (mask.iabuf, addr, len);
|
||||
mask.len = len;
|
||||
|
||||
/* Snarf the semi... */
|
||||
token = next_token (&val, cfile);
|
||||
if (token != SEMI) {
|
||||
parse_warn ("semicolon expected");
|
||||
skip_to_semi (cfile);
|
||||
longjmp (*bc, 1);
|
||||
}
|
||||
|
||||
/* Create the new address range... */
|
||||
new_address_range (low, high, mask);
|
||||
new_address_range (low, high, subnet);
|
||||
}
|
||||
|
||||
/* date :== NUMBER NUMBER/NUMBER/NUMBER NUMBER:NUMBER:NUMBER
|
||||
|
@@ -105,12 +105,15 @@ int main (argc, argv, envp)
|
||||
FD_ZERO (&w);
|
||||
FD_ZERO (&x);
|
||||
FD_SET (sock, &r);
|
||||
FD_SET (sock, &w);
|
||||
FD_SET (sock, &x);
|
||||
FD_SET (0, &r); /* stdin */
|
||||
|
||||
if (select (sock + 1, &r, &w, &x, (struct timeval *)0) < 0) {
|
||||
error ("select: %m");
|
||||
}
|
||||
if (FD_ISSET (sock, &r)) {
|
||||
if (FD_ISSET (sock, &r) || FD_ISSET (sock, &w)
|
||||
|| FD_ISSET (sock, &x)) {
|
||||
if ((result =
|
||||
recvfrom (sock, packbuf, sizeof packbuf, 0,
|
||||
(struct sockaddr *)&from, &fromlen))
|
||||
@@ -188,7 +191,7 @@ int main (argc, argv, envp)
|
||||
}
|
||||
|
||||
cons_options ((struct packet *)0,
|
||||
&outgoing, &decl, bufs);
|
||||
&outgoing, decl.options, bufs);
|
||||
|
||||
if (decl.ciaddr) {
|
||||
tree_evaluate (decl.ciaddr);
|
||||
|
119
dhcp.c
119
dhcp.c
@@ -54,6 +54,18 @@ void dhcp (packet)
|
||||
struct lease lt;
|
||||
TIME lease_time;
|
||||
|
||||
int bufs = 0;
|
||||
struct packet outgoing;
|
||||
struct dhcp_packet raw;
|
||||
struct tree_cache *options [256];
|
||||
struct sockaddr_in to;
|
||||
int result;
|
||||
|
||||
unsigned char dhcpoffer = DHCPOFFER;
|
||||
struct tree_cache dhcpoffer_tree;
|
||||
unsigned char lease_time_buf [4];
|
||||
struct tree_cache lease_time_tree;
|
||||
|
||||
dump_packet (packet);
|
||||
|
||||
/* Try to find a lease that's been assigned to the specified
|
||||
@@ -86,20 +98,6 @@ void dhcp (packet)
|
||||
} 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;
|
||||
@@ -108,20 +106,6 @@ void dhcp (packet)
|
||||
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
|
||||
@@ -145,20 +129,6 @@ void dhcp (packet)
|
||||
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;
|
||||
@@ -249,5 +219,68 @@ void dhcp (packet)
|
||||
supersede_lease (lease, <);
|
||||
|
||||
/* Send a response to the client... */
|
||||
dump_subnets ();
|
||||
|
||||
memset (&outgoing, 0, sizeof outgoing);
|
||||
memset (&raw, 0, sizeof raw);
|
||||
outgoing.raw = &raw;
|
||||
|
||||
/* Copy in the filename if given; otherwise, flag the filename
|
||||
buffer as available for options. */
|
||||
bufs |= 1; /* XXX */
|
||||
|
||||
/* Copy in the server name if given; otherwise, flag the
|
||||
server_name buffer as available for options. */
|
||||
bufs |= 2; /* XXX */
|
||||
|
||||
memcpy (raw.chaddr, packet -> raw -> chaddr, packet -> raw -> hlen);
|
||||
raw.hlen = packet -> raw -> hlen;
|
||||
raw.htype = packet -> raw -> htype;
|
||||
|
||||
/* Start out with the subnet options... */
|
||||
memcpy (options, packet -> subnet -> options, sizeof options);
|
||||
|
||||
/* Now put in options that override those. */
|
||||
options [DHO_DHCP_MESSAGE_TYPE] = &dhcpoffer_tree;
|
||||
options [DHO_DHCP_MESSAGE_TYPE] -> value = &dhcpoffer;
|
||||
options [DHO_DHCP_MESSAGE_TYPE] -> len = sizeof dhcpoffer;
|
||||
options [DHO_DHCP_MESSAGE_TYPE] -> buf_size = sizeof dhcpoffer;
|
||||
options [DHO_DHCP_MESSAGE_TYPE] -> timeout = 0xFFFFFFFF;
|
||||
options [DHO_DHCP_MESSAGE_TYPE] -> tree = (struct tree *)0;
|
||||
|
||||
|
||||
putULong (lease_time_buf, lease -> ends - cur_time);
|
||||
options [DHO_DHCP_LEASE_TIME] = &lease_time_tree;
|
||||
options [DHO_DHCP_LEASE_TIME] -> value = lease_time_buf;
|
||||
options [DHO_DHCP_LEASE_TIME] -> len = sizeof lease_time_buf;
|
||||
options [DHO_DHCP_LEASE_TIME] -> buf_size = sizeof lease_time_buf;
|
||||
options [DHO_DHCP_LEASE_TIME] -> timeout = 0xFFFFFFFF;
|
||||
options [DHO_DHCP_LEASE_TIME] -> tree = (struct tree *)0;
|
||||
|
||||
cons_options (packet, &outgoing, options, bufs);
|
||||
|
||||
raw.ciaddr = packet -> raw -> ciaddr;
|
||||
memcpy (&raw.yiaddr, lease -> ip_addr.iabuf, 4);
|
||||
memcpy (&raw.siaddr, siaddr.iabuf, 4);
|
||||
raw.giaddr = packet -> raw -> giaddr;
|
||||
|
||||
raw.xid = packet -> raw -> xid;
|
||||
raw.secs = packet -> raw -> secs;
|
||||
raw.flags = packet -> raw -> flags;
|
||||
raw.hops = packet -> raw -> hops;
|
||||
raw.op = BOOTREPLY;
|
||||
|
||||
to.sin_port = htons (2000);
|
||||
to.sin_addr.s_addr = INADDR_BROADCAST;
|
||||
to.sin_family = AF_INET;
|
||||
to.sin_len = sizeof to;
|
||||
memset (to.sin_zero, 0, sizeof to.sin_zero);
|
||||
|
||||
note ("Sending dhcp reply to %s, port %d",
|
||||
inet_ntoa (to.sin_addr), htons (to.sin_port));
|
||||
|
||||
errno = 0;
|
||||
result = sendto (packet -> client_sock, &raw, outgoing.packet_length,
|
||||
0, (struct sockaddr *)&to, sizeof to);
|
||||
if (result < 0)
|
||||
warn ("sendto: %m");
|
||||
}
|
||||
|
14
dhcpd.c
14
dhcpd.c
@@ -57,6 +57,7 @@ struct subnet *local_subnet;
|
||||
u_int32_t *server_addrlist;
|
||||
int server_addrcount;
|
||||
u_int16_t server_port;
|
||||
struct iaddr siaddr;
|
||||
|
||||
int main (argc, argv, envp)
|
||||
int argc;
|
||||
@@ -66,7 +67,6 @@ 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;
|
||||
@@ -152,7 +152,7 @@ int main (argc, argv, envp)
|
||||
}
|
||||
#endif
|
||||
|
||||
taddr.len = 0;
|
||||
siaddr.len = 0;
|
||||
server_addrlist = get_interface_list (&server_addrcount);
|
||||
for (i = 0; i < server_addrcount; i++) {
|
||||
struct sockaddr_in foo;
|
||||
@@ -160,13 +160,13 @@ int main (argc, argv, envp)
|
||||
printf ("Address %d: %s\n", i, inet_ntoa (foo.sin_addr));
|
||||
|
||||
if (server_addrlist [i] != htonl (INADDR_LOOPBACK)) {
|
||||
if (taddr.len) {
|
||||
if (siaddr.len) {
|
||||
error ("dhcpd currently does not support "
|
||||
"multiple interfaces");
|
||||
}
|
||||
taddr.len = 4;
|
||||
memcpy (taddr.iabuf, &server_addrlist [i], 4);
|
||||
local_subnet = find_subnet (taddr);
|
||||
siaddr.len = 4;
|
||||
memcpy (siaddr.iabuf, &server_addrlist [i], 4);
|
||||
local_subnet = find_subnet (siaddr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,8 +184,6 @@ int main (argc, argv, envp)
|
||||
close (i);
|
||||
}
|
||||
|
||||
dump_subnets ();
|
||||
|
||||
/* Receive packets and dispatch them... */
|
||||
dispatch ();
|
||||
|
||||
|
@@ -1,5 +1,8 @@
|
||||
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;
|
||||
subnet 204.254.239.0 netmask 255.255.255.0
|
||||
range 204.254.239.11 204.254.239.17;
|
||||
|
||||
subnet 204.254.240.0 netmask 255.255.255.0
|
||||
range 204.254.240.11 204.254.240.12;
|
||||
|
||||
host minuet
|
||||
hardware ethernet 08:00:2b:35:0c:18
|
||||
|
16
dhcpd.h
16
dhcpd.h
@@ -121,6 +121,7 @@ struct subnet {
|
||||
struct iaddr netmask;
|
||||
TIME default_lease_time;
|
||||
TIME max_lease_time;
|
||||
struct tree_cache *options [256];
|
||||
struct lease *leases;
|
||||
struct lease *insertion_point;
|
||||
struct lease *last_lease;
|
||||
@@ -159,8 +160,8 @@ typedef unsigned char option_mask [16];
|
||||
void parse_options PROTO ((struct packet *));
|
||||
void parse_option_buffer PROTO ((struct packet *, unsigned char *, int));
|
||||
void cons_options PROTO ((struct packet *, struct packet *,
|
||||
struct host_decl *, int));
|
||||
int store_option PROTO ((struct host_decl *, unsigned char,
|
||||
struct tree_cache **, int));
|
||||
int store_option PROTO ((struct tree_cache **, unsigned char,
|
||||
unsigned char *, int, int *));
|
||||
char *pretty_print_option PROTO ((unsigned char, unsigned char *, int));
|
||||
|
||||
@@ -175,9 +176,12 @@ int parse_warn PROTO ((char *, ...));
|
||||
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;
|
||||
struct iaddr siaddr;
|
||||
|
||||
int main PROTO ((int, char **, char **));
|
||||
void cleanup PROTO ((void));
|
||||
void do_packet PROTO ((unsigned char *, int,
|
||||
@@ -196,17 +200,19 @@ void parse_statement PROTO ((FILE *));
|
||||
void skip_to_semi PROTO ((FILE *));
|
||||
struct host_decl *parse_host_statement PROTO ((FILE *, jmp_buf *));
|
||||
char *parse_host_name PROTO ((FILE *, jmp_buf *));
|
||||
struct subnet *parse_subnet_statement PROTO ((FILE *, jmp_buf *));
|
||||
void parse_subnet_decl PROTO ((FILE *, jmp_buf *, struct subnet *));
|
||||
void parse_host_decl PROTO ((FILE *, jmp_buf *, struct host_decl *));
|
||||
void parse_hardware_decl PROTO ((FILE *, jmp_buf *, struct host_decl *));
|
||||
struct hardware parse_hardware_addr PROTO ((FILE *, jmp_buf *));
|
||||
void parse_filename_decl PROTO ((FILE *, jmp_buf *, struct host_decl *));
|
||||
struct tree *parse_ip_addr_or_hostname PROTO ((FILE *, jmp_buf *, int));
|
||||
void parse_fixed_addr_decl PROTO ((FILE *, jmp_buf *, struct host_decl *));
|
||||
void parse_option_decl PROTO ((FILE *, jmp_buf *, struct host_decl *));
|
||||
void parse_option_decl PROTO ((FILE *, jmp_buf *, struct tree_cache **));
|
||||
TIME parse_timestamp PROTO ((FILE *, jmp_buf *));
|
||||
TIME parse_date PROTO ((FILE *, jmp_buf *));
|
||||
struct lease *parse_lease_statement PROTO ((FILE *, jmp_buf *));
|
||||
void parse_address_range PROTO ((FILE *, jmp_buf *));
|
||||
void parse_address_range PROTO ((FILE *, jmp_buf *, struct subnet *));
|
||||
unsigned char *parse_numeric_aggregate PROTO ((FILE *, jmp_buf *,
|
||||
unsigned char *, int *,
|
||||
int, int, int));
|
||||
@@ -233,7 +239,7 @@ void enter_host PROTO ((struct host_decl *));
|
||||
struct host_decl *find_host_by_name PROTO ((char *name));
|
||||
struct host_decl *find_host_by_addr PROTO ((int, unsigned char *, int));
|
||||
void new_address_range PROTO ((struct iaddr, struct iaddr,
|
||||
struct iaddr));
|
||||
struct subnet *));
|
||||
extern struct subnet *find_subnet (struct iaddr);
|
||||
void enter_subnet (struct subnet *);
|
||||
void enter_lease PROTO ((struct lease *));
|
||||
|
@@ -68,7 +68,12 @@
|
||||
#define YIADDR 275
|
||||
#define SIADDR 276
|
||||
#define GIADDR 277
|
||||
#define LAST_TOKEN GIADDR
|
||||
#define SUBNET 278
|
||||
#define NETMASK 279
|
||||
#define DEFAULT_LEASE_TIME 280
|
||||
#define MAX_LEASE_TIME 281
|
||||
|
||||
#define LAST_TOKEN MAX_LEASE_TIME
|
||||
|
||||
#define is_identifier(x) ((x) >= FIRST_TOKEN && \
|
||||
(x) <= LAST_TOKEN && \
|
||||
|
@@ -121,6 +121,7 @@ struct subnet {
|
||||
struct iaddr netmask;
|
||||
TIME default_lease_time;
|
||||
TIME max_lease_time;
|
||||
struct tree_cache *options [256];
|
||||
struct lease *leases;
|
||||
struct lease *insertion_point;
|
||||
struct lease *last_lease;
|
||||
@@ -159,8 +160,8 @@ typedef unsigned char option_mask [16];
|
||||
void parse_options PROTO ((struct packet *));
|
||||
void parse_option_buffer PROTO ((struct packet *, unsigned char *, int));
|
||||
void cons_options PROTO ((struct packet *, struct packet *,
|
||||
struct host_decl *, int));
|
||||
int store_option PROTO ((struct host_decl *, unsigned char,
|
||||
struct tree_cache **, int));
|
||||
int store_option PROTO ((struct tree_cache **, unsigned char,
|
||||
unsigned char *, int, int *));
|
||||
char *pretty_print_option PROTO ((unsigned char, unsigned char *, int));
|
||||
|
||||
@@ -175,9 +176,12 @@ int parse_warn PROTO ((char *, ...));
|
||||
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;
|
||||
struct iaddr siaddr;
|
||||
|
||||
int main PROTO ((int, char **, char **));
|
||||
void cleanup PROTO ((void));
|
||||
void do_packet PROTO ((unsigned char *, int,
|
||||
@@ -196,17 +200,19 @@ void parse_statement PROTO ((FILE *));
|
||||
void skip_to_semi PROTO ((FILE *));
|
||||
struct host_decl *parse_host_statement PROTO ((FILE *, jmp_buf *));
|
||||
char *parse_host_name PROTO ((FILE *, jmp_buf *));
|
||||
struct subnet *parse_subnet_statement PROTO ((FILE *, jmp_buf *));
|
||||
void parse_subnet_decl PROTO ((FILE *, jmp_buf *, struct subnet *));
|
||||
void parse_host_decl PROTO ((FILE *, jmp_buf *, struct host_decl *));
|
||||
void parse_hardware_decl PROTO ((FILE *, jmp_buf *, struct host_decl *));
|
||||
struct hardware parse_hardware_addr PROTO ((FILE *, jmp_buf *));
|
||||
void parse_filename_decl PROTO ((FILE *, jmp_buf *, struct host_decl *));
|
||||
struct tree *parse_ip_addr_or_hostname PROTO ((FILE *, jmp_buf *, int));
|
||||
void parse_fixed_addr_decl PROTO ((FILE *, jmp_buf *, struct host_decl *));
|
||||
void parse_option_decl PROTO ((FILE *, jmp_buf *, struct host_decl *));
|
||||
void parse_option_decl PROTO ((FILE *, jmp_buf *, struct tree_cache **));
|
||||
TIME parse_timestamp PROTO ((FILE *, jmp_buf *));
|
||||
TIME parse_date PROTO ((FILE *, jmp_buf *));
|
||||
struct lease *parse_lease_statement PROTO ((FILE *, jmp_buf *));
|
||||
void parse_address_range PROTO ((FILE *, jmp_buf *));
|
||||
void parse_address_range PROTO ((FILE *, jmp_buf *, struct subnet *));
|
||||
unsigned char *parse_numeric_aggregate PROTO ((FILE *, jmp_buf *,
|
||||
unsigned char *, int *,
|
||||
int, int, int));
|
||||
@@ -233,7 +239,7 @@ void enter_host PROTO ((struct host_decl *));
|
||||
struct host_decl *find_host_by_name PROTO ((char *name));
|
||||
struct host_decl *find_host_by_addr PROTO ((int, unsigned char *, int));
|
||||
void new_address_range PROTO ((struct iaddr, struct iaddr,
|
||||
struct iaddr));
|
||||
struct subnet *));
|
||||
extern struct subnet *find_subnet (struct iaddr);
|
||||
void enter_subnet (struct subnet *);
|
||||
void enter_lease PROTO ((struct lease *));
|
||||
|
@@ -68,7 +68,12 @@
|
||||
#define YIADDR 275
|
||||
#define SIADDR 276
|
||||
#define GIADDR 277
|
||||
#define LAST_TOKEN GIADDR
|
||||
#define SUBNET 278
|
||||
#define NETMASK 279
|
||||
#define DEFAULT_LEASE_TIME 280
|
||||
#define MAX_LEASE_TIME 281
|
||||
|
||||
#define LAST_TOKEN MAX_LEASE_TIME
|
||||
|
||||
#define is_identifier(x) ((x) >= FIRST_TOKEN && \
|
||||
(x) <= LAST_TOKEN && \
|
||||
|
60
memory.c
60
memory.c
@@ -92,11 +92,11 @@ struct host_decl *find_host_by_addr (htype, haddr, hlen)
|
||||
return (struct host_decl *)0;
|
||||
}
|
||||
|
||||
void new_address_range (low, high, netmask)
|
||||
struct iaddr low, high, netmask;
|
||||
void new_address_range (low, high, subnet)
|
||||
struct iaddr low, high;
|
||||
struct subnet *subnet;
|
||||
{
|
||||
struct lease *address_range, *lp, *plp;
|
||||
struct subnet *subnet;
|
||||
struct iaddr net;
|
||||
int min, max, i;
|
||||
char lowbuf [16], highbuf [16], netbuf [16];
|
||||
@@ -110,39 +110,23 @@ void new_address_range (low, high, netmask)
|
||||
lease_hw_addr_hash = new_hash ();
|
||||
|
||||
/* Make sure that high and low addresses are in same subnet. */
|
||||
net = subnet_number (low, netmask);
|
||||
if (!addr_eq (net, subnet_number (high, netmask))) {
|
||||
net = subnet_number (low, subnet -> netmask);
|
||||
if (!addr_eq (net, subnet_number (high, subnet -> netmask))) {
|
||||
strcpy (lowbuf, piaddr (low));
|
||||
strcpy (highbuf, piaddr (high));
|
||||
strcpy (netbuf, piaddr (netmask));
|
||||
strcpy (netbuf, piaddr (subnet -> netmask));
|
||||
error ("Address range %s to %s, netmask %s spans %s!",
|
||||
lowbuf, highbuf, netbuf, "multiple subnets");
|
||||
}
|
||||
|
||||
/* See if this subnet is already known - if not, make a new one. */
|
||||
subnet = find_subnet (net);
|
||||
if (!subnet) {
|
||||
subnet = new_subnet ("new_address_range");
|
||||
if (!subnet)
|
||||
error ("No memory for new subnet");
|
||||
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);
|
||||
min = host_addr (low, netmask);
|
||||
max = host_addr (high, subnet -> netmask);
|
||||
min = host_addr (low, subnet -> netmask);
|
||||
|
||||
/* Allow range to be specified high-to-low as well as low-to-high. */
|
||||
if (min > max) {
|
||||
max = min;
|
||||
min = host_addr (high, netmask);
|
||||
min = host_addr (high, subnet -> netmask);
|
||||
}
|
||||
|
||||
/* Get a lease structure for each address in the range. */
|
||||
@@ -155,8 +139,9 @@ void new_address_range (low, high, netmask)
|
||||
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)
|
||||
if (!subnet -> last_lease) {
|
||||
subnet -> last_lease = &address_range [0];
|
||||
}
|
||||
|
||||
/* Fill out the lease structures with some minimal information. */
|
||||
for (i = 0; i < max - min + 1; i++) {
|
||||
@@ -269,11 +254,6 @@ 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
|
||||
@@ -325,7 +305,6 @@ printf ("\n");
|
||||
|
||||
/* Copy the data files, but not the linkages. */
|
||||
comp -> starts = lease -> starts;
|
||||
comp -> ends = lease -> ends;
|
||||
comp -> timestamp = lease -> timestamp;
|
||||
comp -> uid = lease -> uid;
|
||||
comp -> uid_len = lease -> uid_len;
|
||||
@@ -373,13 +352,13 @@ printf ("\n");
|
||||
head of the list. */
|
||||
comp -> contain -> leases = comp;
|
||||
comp -> contain -> last_lease = comp;
|
||||
} else if (lp -> ends > comp -> ends) {
|
||||
} else if (lp -> ends > lease -> 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 > lease -> ends) {
|
||||
lp = lp -> next;
|
||||
}
|
||||
if (lp -> ends > comp -> ends) {
|
||||
if (lp -> ends > lease -> ends) {
|
||||
/* If we ran out of list, put comp
|
||||
at the end. */
|
||||
lp -> next = comp;
|
||||
@@ -389,7 +368,7 @@ printf ("\n");
|
||||
} else {
|
||||
/* If we didn't, put it between lp and
|
||||
the previous item on the list. */
|
||||
comp -> prev = lp -> prev;
|
||||
if ((comp -> prev = lp -> prev))
|
||||
comp -> prev -> next = comp;
|
||||
comp -> next = lp;
|
||||
lp -> prev = comp;
|
||||
@@ -397,10 +376,10 @@ printf ("\n");
|
||||
} else {
|
||||
/* 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 < lease -> ends) {
|
||||
lp = lp -> prev;
|
||||
}
|
||||
if (lp -> ends < comp -> ends) {
|
||||
if (lp -> ends < lease -> ends) {
|
||||
/* If we ran out of list, put comp
|
||||
at the beginning. */
|
||||
lp -> prev = comp;
|
||||
@@ -410,13 +389,14 @@ printf ("\n");
|
||||
} else {
|
||||
/* If we didn't, put it between lp and
|
||||
the next item on the list. */
|
||||
comp -> next = lp -> next;
|
||||
if ((comp -> next = lp -> next))
|
||||
comp -> next -> prev = comp;
|
||||
comp -> prev = lp;
|
||||
lp -> next = comp;
|
||||
}
|
||||
}
|
||||
comp -> contain -> insertion_point = comp;
|
||||
comp -> ends = lease -> ends;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -427,8 +407,8 @@ void release_lease (lease)
|
||||
{
|
||||
struct lease lt;
|
||||
|
||||
lease -> ends = 0;
|
||||
lt = *lease;
|
||||
lt.ends = cur_time;
|
||||
supersede_lease (lease, <);
|
||||
}
|
||||
|
||||
|
40
options.c
40
options.c
@@ -150,10 +150,10 @@ void parse_option_buffer (packet, buffer, length)
|
||||
/* Cons up options based on client-supplied desired option list (if any)
|
||||
and selected server option list. */
|
||||
|
||||
void cons_options (inpacket, outpacket, hp, overload)
|
||||
void cons_options (inpacket, outpacket, options, overload)
|
||||
struct packet *inpacket;
|
||||
struct packet *outpacket;
|
||||
struct host_decl *hp;
|
||||
struct tree_cache **options;
|
||||
int overload; /* Overload flags that may be set. */
|
||||
{
|
||||
option_mask options_have; /* Options we can send. */
|
||||
@@ -217,7 +217,7 @@ void cons_options (inpacket, outpacket, hp, overload)
|
||||
/* Make a bitmask of all the options we have available. */
|
||||
OPTION_ZERO (options_have);
|
||||
for (i = 0; i < 256; i++)
|
||||
if (hp -> options [i])
|
||||
if (options [i])
|
||||
OPTION_SET (options_have, i);
|
||||
|
||||
/* Put the cookie up front... */
|
||||
@@ -235,7 +235,7 @@ void cons_options (inpacket, outpacket, hp, overload)
|
||||
int length;
|
||||
|
||||
/* If no data is available for this option, skip it. */
|
||||
if (!hp -> options [code])
|
||||
if (!options [code])
|
||||
continue;
|
||||
|
||||
/* Don't look at options that have already been stored. */
|
||||
@@ -243,11 +243,11 @@ void cons_options (inpacket, outpacket, hp, overload)
|
||||
continue;
|
||||
|
||||
/* Find the value of the option... */
|
||||
if (!tree_evaluate (hp -> options [code]))
|
||||
if (!tree_evaluate (options [code]))
|
||||
continue;
|
||||
|
||||
/* We should now have a constant length for the option. */
|
||||
length = (hp -> options [code] -> len - stored_length [code]);
|
||||
length = (options [code] -> len - stored_length [code]);
|
||||
|
||||
/* If there's no space for this option, skip it. */
|
||||
if ((bufix + OPTION_SPACE (length) + reserved) > buflen) {
|
||||
@@ -260,7 +260,7 @@ void cons_options (inpacket, outpacket, hp, overload)
|
||||
}
|
||||
|
||||
/* Otherwise, store the option. */
|
||||
result = store_option (hp, code,
|
||||
result = store_option (options, code,
|
||||
buffer + bufix,
|
||||
buflen - bufix - reserved,
|
||||
stored_length);
|
||||
@@ -268,16 +268,16 @@ void cons_options (inpacket, outpacket, hp, overload)
|
||||
|
||||
/* The following test should always succeed because of
|
||||
preconditioning above. */
|
||||
if (stored_length [code] == hp -> options [code] -> len)
|
||||
if (stored_length [code] == options [code] -> len)
|
||||
OPTION_SET (options_done, code);
|
||||
else {
|
||||
warn ("%s: Only stored %d out of %d bytes.",
|
||||
dhcp_options [code].name,
|
||||
stored_length [code],
|
||||
hp -> options [code] -> len);
|
||||
options [code] -> len);
|
||||
if (++missed == 1) {
|
||||
missed_code = code;
|
||||
missed_length = hp -> options [code] -> len
|
||||
missed_length = options [code] -> len
|
||||
- stored_length [code];
|
||||
}
|
||||
}
|
||||
@@ -300,20 +300,20 @@ void cons_options (inpacket, outpacket, hp, overload)
|
||||
overloading. */
|
||||
if (reserved && missed == 1
|
||||
&& (bufix + OPTION_SPACE (missed_length) <= buflen)) {
|
||||
result = store_option (hp, missed_code,
|
||||
result = store_option (options, missed_code,
|
||||
buffer + bufix, buflen - bufix,
|
||||
stored_length);
|
||||
bufix += result;
|
||||
/* This test should always fail -- we'll send bad
|
||||
data if it doesn't. */
|
||||
if (stored_length [missed_code]
|
||||
== hp -> options [missed_code] -> len) {
|
||||
== options [missed_code] -> len) {
|
||||
OPTION_SET (options_done, missed_code);
|
||||
} else {
|
||||
warn ("%s (last): Only stored %d out of %d bytes.",
|
||||
dhcp_options [missed_code].name,
|
||||
stored_length [missed_code],
|
||||
hp -> options [missed_code] -> len);
|
||||
options [missed_code] -> len);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -323,7 +323,7 @@ void cons_options (inpacket, outpacket, hp, overload)
|
||||
option into the current buffer and part into the next. */
|
||||
if (bufix + OPTION_SPACE (missed_length) + reserved
|
||||
< buflen + (overload & 1 ? 128 : 0) + (overload & 2 ? 64 : 0)) {
|
||||
result = store_option (hp, missed_code,
|
||||
result = store_option (options, missed_code,
|
||||
buffer + bufix,
|
||||
buflen - bufix - reserved,
|
||||
stored_length);
|
||||
@@ -331,7 +331,7 @@ void cons_options (inpacket, outpacket, hp, overload)
|
||||
|
||||
/* This test should never fail. */
|
||||
if (stored_length [missed_code]
|
||||
== hp -> options [missed_code] -> len) {
|
||||
== options [missed_code] -> len) {
|
||||
OPTION_SET (options_done, missed_code);
|
||||
warn ("%s: Unexpected completed store.",
|
||||
dhcp_options [missed_code].name);
|
||||
@@ -391,17 +391,17 @@ void cons_options (inpacket, outpacket, hp, overload)
|
||||
data that has been stored so far. Return 1 if all the option data
|
||||
has been stored. */
|
||||
|
||||
int store_option (hp, code, buffer, buflen, stored_length)
|
||||
struct host_decl *hp;
|
||||
int store_option (options, code, buffer, buflen, stored_length)
|
||||
struct tree_cache **options;
|
||||
unsigned char code;
|
||||
unsigned char *buffer;
|
||||
int buflen;
|
||||
int *stored_length;
|
||||
{
|
||||
int length = hp -> options [code] -> len - stored_length [code];
|
||||
int length = options [code] -> len - stored_length [code];
|
||||
int bufix = 0;
|
||||
printf ("store_option: length = %d buflen = %d packet %d stored %d\n",
|
||||
length, buflen, hp -> options [code] -> len, stored_length [code]);
|
||||
length, buflen, options [code] -> len, stored_length [code]);
|
||||
if (length > buflen) {
|
||||
length = buflen;
|
||||
}
|
||||
@@ -415,7 +415,7 @@ printf ("store_option: length = %d buflen = %d packet %d stored %d\n",
|
||||
unsigned char incr = length > 255 ? 255 : length;
|
||||
buffer [bufix] = code;
|
||||
buffer [bufix + 1] = incr;
|
||||
memcpy (buffer + bufix + 2, (hp -> options [code] -> value
|
||||
memcpy (buffer + bufix + 2, (options [code] -> value
|
||||
+ stored_length [code]), incr);
|
||||
length -= incr;
|
||||
stored_length [code] += incr;
|
||||
|
@@ -102,9 +102,9 @@ void parse_statement (cfile)
|
||||
parsed_time = parse_timestamp (cfile, &bc);
|
||||
}
|
||||
break;
|
||||
case RANGE:
|
||||
case SUBNET:
|
||||
if (!setjmp (bc)) {
|
||||
parse_address_range (cfile, &bc);
|
||||
parse_subnet_statement (cfile, &bc);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -209,6 +209,113 @@ char *parse_host_name (cfile, bc)
|
||||
return s;
|
||||
}
|
||||
|
||||
/* subnet_statement :== SUBNET net NETMASK netmask declarations SEMI
|
||||
host_declarations :== <nil> | host_declaration
|
||||
| host_declarations host_declaration SEMI */
|
||||
|
||||
struct subnet *parse_subnet_statement (cfile, bc)
|
||||
FILE *cfile;
|
||||
jmp_buf *bc;
|
||||
{
|
||||
char *val;
|
||||
int token;
|
||||
struct subnet *subnet;
|
||||
struct iaddr net, netmask;
|
||||
unsigned char addr [4];
|
||||
int len = sizeof addr;
|
||||
|
||||
subnet = new_subnet ("parse_subnet_statement");
|
||||
if (!subnet)
|
||||
error ("No memory for new subnet");
|
||||
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;
|
||||
|
||||
/* Get the network number... */
|
||||
parse_numeric_aggregate (cfile, bc, addr, &len, DOT, 10, 8);
|
||||
memcpy (net.iabuf, addr, len);
|
||||
net.len = len;
|
||||
subnet -> net = net;
|
||||
|
||||
token = next_token (&val, cfile);
|
||||
if (token != NETMASK) {
|
||||
parse_warn ("Expecting netmask");
|
||||
skip_to_semi (cfile);
|
||||
longjmp (*bc, 1);
|
||||
}
|
||||
|
||||
/* Get the netmask... */
|
||||
parse_numeric_aggregate (cfile, bc, addr, &len, DOT, 10, 8);
|
||||
memcpy (netmask.iabuf, addr, len);
|
||||
netmask.len = len;
|
||||
subnet -> netmask = netmask;
|
||||
|
||||
enter_subnet (subnet);
|
||||
|
||||
do {
|
||||
token = peek_token (&val, cfile);
|
||||
if (token == SEMI) {
|
||||
token = next_token (&val, cfile);
|
||||
break;
|
||||
}
|
||||
parse_subnet_decl (cfile, bc, subnet);
|
||||
} while (1);
|
||||
return subnet;
|
||||
}
|
||||
|
||||
/* subnet_declaration :== hardware_declaration | filename_declaration
|
||||
| fixed_addr_declaration | option_declaration */
|
||||
|
||||
void parse_subnet_decl (cfile, bc, decl)
|
||||
FILE *cfile;
|
||||
jmp_buf *bc;
|
||||
struct subnet *decl;
|
||||
{
|
||||
char *val;
|
||||
int token;
|
||||
|
||||
token = next_token (&val, cfile);
|
||||
switch (token) {
|
||||
case RANGE:
|
||||
parse_address_range (cfile, bc, decl);
|
||||
break;
|
||||
|
||||
case OPTION:
|
||||
parse_option_decl (cfile, bc, decl -> options);
|
||||
break;
|
||||
|
||||
case DEFAULT_LEASE_TIME:
|
||||
token = next_token (&val, cfile);
|
||||
if (token != NUMBER) {
|
||||
parse_warn ("Expecting numeric default lease time");
|
||||
skip_to_semi (cfile);
|
||||
longjmp (*bc, 1);
|
||||
}
|
||||
convert_num ((unsigned char *)&decl -> default_lease_time,
|
||||
val, 10, 4);
|
||||
break;
|
||||
|
||||
case MAX_LEASE_TIME:
|
||||
token = next_token (&val, cfile);
|
||||
if (token != NUMBER) {
|
||||
parse_warn ("Expecting numeric max lease time");
|
||||
skip_to_semi (cfile);
|
||||
longjmp (*bc, 1);
|
||||
}
|
||||
convert_num ((unsigned char *)&decl -> max_lease_time,
|
||||
val, 10, 4);
|
||||
break;
|
||||
|
||||
default:
|
||||
parse_warn ("expecting a subnet declaration.");
|
||||
skip_to_semi (cfile);
|
||||
longjmp (*bc, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* host_declaration :== hardware_declaration | filename_declaration
|
||||
| fixed_addr_declaration | option_declaration */
|
||||
|
||||
@@ -232,7 +339,7 @@ void parse_host_decl (cfile, bc, decl)
|
||||
parse_fixed_addr_decl (cfile, bc, decl);
|
||||
break;
|
||||
case OPTION:
|
||||
parse_option_decl (cfile, bc, decl);
|
||||
parse_option_decl (cfile, bc, decl -> options);
|
||||
break;
|
||||
case CIADDR:
|
||||
decl -> ciaddr =
|
||||
@@ -400,10 +507,10 @@ void parse_fixed_addr_decl (cfile, bc, decl)
|
||||
would be painful to come up with BNF for it. However, it always
|
||||
starts as above. */
|
||||
|
||||
void parse_option_decl (cfile, bc, decl)
|
||||
void parse_option_decl (cfile, bc, options)
|
||||
FILE *cfile;
|
||||
jmp_buf *bc;
|
||||
struct host_decl *decl;
|
||||
struct tree_cache **options;
|
||||
{
|
||||
char *val;
|
||||
int token;
|
||||
@@ -570,11 +677,11 @@ void parse_option_decl (cfile, bc, decl)
|
||||
}
|
||||
} while (*fmt == 'A');
|
||||
|
||||
if (decl -> options [option -> code]) {
|
||||
if (options [option -> code]) {
|
||||
parse_warn ("duplicate option code %d (%s).",
|
||||
option -> code, option -> name);
|
||||
}
|
||||
decl -> options [option -> code] = tree_cache (tree);
|
||||
options [option -> code] = tree_cache (tree);
|
||||
}
|
||||
|
||||
/* timestamp :== TIMESTAMP date SEMI
|
||||
@@ -724,13 +831,14 @@ struct lease *parse_lease_statement (cfile, bc)
|
||||
return &lease;
|
||||
}
|
||||
|
||||
/* address_range :== RANGE ip_address ip_address ip_address SEMI */
|
||||
/* address_range :== RANGE ip_address ip_address */
|
||||
|
||||
void parse_address_range (cfile, bc)
|
||||
void parse_address_range (cfile, bc, subnet)
|
||||
FILE *cfile;
|
||||
jmp_buf *bc;
|
||||
struct subnet *subnet;
|
||||
{
|
||||
struct iaddr low, high, mask;
|
||||
struct iaddr low, high;
|
||||
unsigned char addr [4];
|
||||
int len = sizeof addr;
|
||||
int token;
|
||||
@@ -746,21 +854,8 @@ void parse_address_range (cfile, bc)
|
||||
memcpy (high.iabuf, addr, len);
|
||||
high.len = len;
|
||||
|
||||
/* Get the netmask of the subnet containing the range... */
|
||||
parse_numeric_aggregate (cfile, bc, addr, &len, DOT, 10, 8);
|
||||
memcpy (mask.iabuf, addr, len);
|
||||
mask.len = len;
|
||||
|
||||
/* Snarf the semi... */
|
||||
token = next_token (&val, cfile);
|
||||
if (token != SEMI) {
|
||||
parse_warn ("semicolon expected");
|
||||
skip_to_semi (cfile);
|
||||
longjmp (*bc, 1);
|
||||
}
|
||||
|
||||
/* Create the new address range... */
|
||||
new_address_range (low, high, mask);
|
||||
new_address_range (low, high, subnet);
|
||||
}
|
||||
|
||||
/* date :== NUMBER NUMBER/NUMBER/NUMBER NUMBER:NUMBER:NUMBER
|
||||
|
119
server/dhcp.c
119
server/dhcp.c
@@ -54,6 +54,18 @@ void dhcp (packet)
|
||||
struct lease lt;
|
||||
TIME lease_time;
|
||||
|
||||
int bufs = 0;
|
||||
struct packet outgoing;
|
||||
struct dhcp_packet raw;
|
||||
struct tree_cache *options [256];
|
||||
struct sockaddr_in to;
|
||||
int result;
|
||||
|
||||
unsigned char dhcpoffer = DHCPOFFER;
|
||||
struct tree_cache dhcpoffer_tree;
|
||||
unsigned char lease_time_buf [4];
|
||||
struct tree_cache lease_time_tree;
|
||||
|
||||
dump_packet (packet);
|
||||
|
||||
/* Try to find a lease that's been assigned to the specified
|
||||
@@ -86,20 +98,6 @@ void dhcp (packet)
|
||||
} 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;
|
||||
@@ -108,20 +106,6 @@ void dhcp (packet)
|
||||
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
|
||||
@@ -145,20 +129,6 @@ void dhcp (packet)
|
||||
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;
|
||||
@@ -249,5 +219,68 @@ void dhcp (packet)
|
||||
supersede_lease (lease, <);
|
||||
|
||||
/* Send a response to the client... */
|
||||
dump_subnets ();
|
||||
|
||||
memset (&outgoing, 0, sizeof outgoing);
|
||||
memset (&raw, 0, sizeof raw);
|
||||
outgoing.raw = &raw;
|
||||
|
||||
/* Copy in the filename if given; otherwise, flag the filename
|
||||
buffer as available for options. */
|
||||
bufs |= 1; /* XXX */
|
||||
|
||||
/* Copy in the server name if given; otherwise, flag the
|
||||
server_name buffer as available for options. */
|
||||
bufs |= 2; /* XXX */
|
||||
|
||||
memcpy (raw.chaddr, packet -> raw -> chaddr, packet -> raw -> hlen);
|
||||
raw.hlen = packet -> raw -> hlen;
|
||||
raw.htype = packet -> raw -> htype;
|
||||
|
||||
/* Start out with the subnet options... */
|
||||
memcpy (options, packet -> subnet -> options, sizeof options);
|
||||
|
||||
/* Now put in options that override those. */
|
||||
options [DHO_DHCP_MESSAGE_TYPE] = &dhcpoffer_tree;
|
||||
options [DHO_DHCP_MESSAGE_TYPE] -> value = &dhcpoffer;
|
||||
options [DHO_DHCP_MESSAGE_TYPE] -> len = sizeof dhcpoffer;
|
||||
options [DHO_DHCP_MESSAGE_TYPE] -> buf_size = sizeof dhcpoffer;
|
||||
options [DHO_DHCP_MESSAGE_TYPE] -> timeout = 0xFFFFFFFF;
|
||||
options [DHO_DHCP_MESSAGE_TYPE] -> tree = (struct tree *)0;
|
||||
|
||||
|
||||
putULong (lease_time_buf, lease -> ends - cur_time);
|
||||
options [DHO_DHCP_LEASE_TIME] = &lease_time_tree;
|
||||
options [DHO_DHCP_LEASE_TIME] -> value = lease_time_buf;
|
||||
options [DHO_DHCP_LEASE_TIME] -> len = sizeof lease_time_buf;
|
||||
options [DHO_DHCP_LEASE_TIME] -> buf_size = sizeof lease_time_buf;
|
||||
options [DHO_DHCP_LEASE_TIME] -> timeout = 0xFFFFFFFF;
|
||||
options [DHO_DHCP_LEASE_TIME] -> tree = (struct tree *)0;
|
||||
|
||||
cons_options (packet, &outgoing, options, bufs);
|
||||
|
||||
raw.ciaddr = packet -> raw -> ciaddr;
|
||||
memcpy (&raw.yiaddr, lease -> ip_addr.iabuf, 4);
|
||||
memcpy (&raw.siaddr, siaddr.iabuf, 4);
|
||||
raw.giaddr = packet -> raw -> giaddr;
|
||||
|
||||
raw.xid = packet -> raw -> xid;
|
||||
raw.secs = packet -> raw -> secs;
|
||||
raw.flags = packet -> raw -> flags;
|
||||
raw.hops = packet -> raw -> hops;
|
||||
raw.op = BOOTREPLY;
|
||||
|
||||
to.sin_port = htons (2000);
|
||||
to.sin_addr.s_addr = INADDR_BROADCAST;
|
||||
to.sin_family = AF_INET;
|
||||
to.sin_len = sizeof to;
|
||||
memset (to.sin_zero, 0, sizeof to.sin_zero);
|
||||
|
||||
note ("Sending dhcp reply to %s, port %d",
|
||||
inet_ntoa (to.sin_addr), htons (to.sin_port));
|
||||
|
||||
errno = 0;
|
||||
result = sendto (packet -> client_sock, &raw, outgoing.packet_length,
|
||||
0, (struct sockaddr *)&to, sizeof to);
|
||||
if (result < 0)
|
||||
warn ("sendto: %m");
|
||||
}
|
||||
|
@@ -57,6 +57,7 @@ struct subnet *local_subnet;
|
||||
u_int32_t *server_addrlist;
|
||||
int server_addrcount;
|
||||
u_int16_t server_port;
|
||||
struct iaddr siaddr;
|
||||
|
||||
int main (argc, argv, envp)
|
||||
int argc;
|
||||
@@ -66,7 +67,6 @@ 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;
|
||||
@@ -152,7 +152,7 @@ int main (argc, argv, envp)
|
||||
}
|
||||
#endif
|
||||
|
||||
taddr.len = 0;
|
||||
siaddr.len = 0;
|
||||
server_addrlist = get_interface_list (&server_addrcount);
|
||||
for (i = 0; i < server_addrcount; i++) {
|
||||
struct sockaddr_in foo;
|
||||
@@ -160,13 +160,13 @@ int main (argc, argv, envp)
|
||||
printf ("Address %d: %s\n", i, inet_ntoa (foo.sin_addr));
|
||||
|
||||
if (server_addrlist [i] != htonl (INADDR_LOOPBACK)) {
|
||||
if (taddr.len) {
|
||||
if (siaddr.len) {
|
||||
error ("dhcpd currently does not support "
|
||||
"multiple interfaces");
|
||||
}
|
||||
taddr.len = 4;
|
||||
memcpy (taddr.iabuf, &server_addrlist [i], 4);
|
||||
local_subnet = find_subnet (taddr);
|
||||
siaddr.len = 4;
|
||||
memcpy (siaddr.iabuf, &server_addrlist [i], 4);
|
||||
local_subnet = find_subnet (siaddr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,8 +184,6 @@ int main (argc, argv, envp)
|
||||
close (i);
|
||||
}
|
||||
|
||||
dump_subnets ();
|
||||
|
||||
/* Receive packets and dispatch them... */
|
||||
dispatch ();
|
||||
|
||||
|
@@ -1,5 +1,8 @@
|
||||
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;
|
||||
subnet 204.254.239.0 netmask 255.255.255.0
|
||||
range 204.254.239.11 204.254.239.17;
|
||||
|
||||
subnet 204.254.240.0 netmask 255.255.255.0
|
||||
range 204.254.240.11 204.254.240.12;
|
||||
|
||||
host minuet
|
||||
hardware ethernet 08:00:2b:35:0c:18
|
||||
|
22
tables.c
22
tables.c
@@ -326,6 +326,17 @@ struct option dhcp_options [256] = {
|
||||
/* Default dhcp option priority list (this is ad hoc and should not be
|
||||
mistaken for a carefully crafted and optimized list). */
|
||||
unsigned char dhcp_option_default_priority_list [] = {
|
||||
DHO_DHCP_REQUESTED_ADDRESS,
|
||||
DHO_DHCP_LEASE_TIME,
|
||||
DHO_DHCP_MESSAGE_TYPE,
|
||||
DHO_DHCP_OPTION_OVERLOAD,
|
||||
DHO_DHCP_SERVER_IDENTIFIER,
|
||||
DHO_DHCP_MESSAGE,
|
||||
DHO_DHCP_MAX_MESSAGE_SIZE,
|
||||
DHO_DHCP_RENEWAL_TIME,
|
||||
DHO_DHCP_REBINDING_TIME,
|
||||
DHO_DHCP_CLASS_IDENTIFIER,
|
||||
DHO_DHCP_CLIENT_IDENTIFIER,
|
||||
DHO_SUBNET_MASK,
|
||||
DHO_TIME_OFFSET,
|
||||
DHO_ROUTERS,
|
||||
@@ -375,18 +386,7 @@ unsigned char dhcp_option_default_priority_list [] = {
|
||||
DHO_NETBIOS_SCOPE,
|
||||
DHO_FONT_SERVERS,
|
||||
DHO_X_DISPLAY_MANAGER,
|
||||
DHO_DHCP_REQUESTED_ADDRESS,
|
||||
DHO_DHCP_LEASE_TIME,
|
||||
DHO_DHCP_OPTION_OVERLOAD,
|
||||
DHO_DHCP_MESSAGE_TYPE,
|
||||
DHO_DHCP_SERVER_IDENTIFIER,
|
||||
DHO_DHCP_PARAMETER_REQUEST_LIST,
|
||||
DHO_DHCP_MESSAGE,
|
||||
DHO_DHCP_MAX_MESSAGE_SIZE,
|
||||
DHO_DHCP_RENEWAL_TIME,
|
||||
DHO_DHCP_REBINDING_TIME,
|
||||
DHO_DHCP_CLASS_IDENTIFIER,
|
||||
DHO_DHCP_CLIENT_IDENTIFIER,
|
||||
};
|
||||
|
||||
int sizeof_dhcp_option_default_priority_list =
|
||||
|
Reference in New Issue
Block a user