2
0
mirror of https://gitlab.isc.org/isc-projects/dhcp synced 2025-09-02 15:25:48 +00:00

Incremental changes to support DHCP protocol

This commit is contained in:
Ted Lemon
1996-02-21 15:16:18 +00:00
parent 7e24ffd3ef
commit 685963dcf4
22 changed files with 590 additions and 316 deletions

View File

@@ -105,12 +105,15 @@ int main (argc, argv, envp)
FD_ZERO (&w); FD_ZERO (&w);
FD_ZERO (&x); FD_ZERO (&x);
FD_SET (sock, &r); FD_SET (sock, &r);
FD_SET (sock, &w);
FD_SET (sock, &x);
FD_SET (0, &r); /* stdin */ FD_SET (0, &r); /* stdin */
if (select (sock + 1, &r, &w, &x, (struct timeval *)0) < 0) { if (select (sock + 1, &r, &w, &x, (struct timeval *)0) < 0) {
error ("select: %m"); error ("select: %m");
} }
if (FD_ISSET (sock, &r)) { if (FD_ISSET (sock, &r) || FD_ISSET (sock, &w)
|| FD_ISSET (sock, &x)) {
if ((result = if ((result =
recvfrom (sock, packbuf, sizeof packbuf, 0, recvfrom (sock, packbuf, sizeof packbuf, 0,
(struct sockaddr *)&from, &fromlen)) (struct sockaddr *)&from, &fromlen))
@@ -188,7 +191,7 @@ int main (argc, argv, envp)
} }
cons_options ((struct packet *)0, cons_options ((struct packet *)0,
&outgoing, &decl, bufs); &outgoing, decl.options, bufs);
if (decl.ciaddr) { if (decl.ciaddr) {
tree_evaluate (decl.ciaddr); tree_evaluate (decl.ciaddr);

View File

@@ -277,6 +277,10 @@ static int intern (atom, dfv)
if (!strcasecmp (atom + 1, "iaddr")) if (!strcasecmp (atom + 1, "iaddr"))
return CIADDR; return CIADDR;
break; break;
case 'd':
if (!strcasecmp (atom + 1, "efault-lease-time"))
return DEFAULT_LEASE_TIME;
break;
case 'e': case 'e':
if (!strcasecmp (atom + 1, "thernet")) if (!strcasecmp (atom + 1, "thernet"))
return ETHERNET; return ETHERNET;
@@ -303,6 +307,14 @@ static int intern (atom, dfv)
if (!strcasecmp (atom + 1, "ease")) if (!strcasecmp (atom + 1, "ease"))
return LEASE; return LEASE;
break; 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': case 'p':
if (!strcasecmp (atom + 1, "acket")) if (!strcasecmp (atom + 1, "acket"))
return PACKET; return PACKET;
@@ -320,6 +332,8 @@ static int intern (atom, dfv)
return STARTS; return STARTS;
if (!strcasecmp (atom + 1, "iaddr")) if (!strcasecmp (atom + 1, "iaddr"))
return SIADDR; return SIADDR;
if (!strcasecmp (atom + 1, "ubnet"))
return SUBNET;
break; break;
case 't': case 't':
if (!strcasecmp (atom + 1, "timestamp")) if (!strcasecmp (atom + 1, "timestamp"))

View File

@@ -92,11 +92,11 @@ struct host_decl *find_host_by_addr (htype, haddr, hlen)
return (struct host_decl *)0; return (struct host_decl *)0;
} }
void new_address_range (low, high, netmask) void new_address_range (low, high, subnet)
struct iaddr low, high, netmask; struct iaddr low, high;
struct subnet *subnet;
{ {
struct lease *address_range, *lp, *plp; struct lease *address_range, *lp, *plp;
struct subnet *subnet;
struct iaddr net; struct iaddr net;
int min, max, i; int min, max, i;
char lowbuf [16], highbuf [16], netbuf [16]; char lowbuf [16], highbuf [16], netbuf [16];
@@ -110,39 +110,23 @@ void new_address_range (low, high, netmask)
lease_hw_addr_hash = new_hash (); lease_hw_addr_hash = new_hash ();
/* Make sure that high and low addresses are in same subnet. */ /* Make sure that high and low addresses are in same subnet. */
net = subnet_number (low, netmask); net = subnet_number (low, subnet -> netmask);
if (!addr_eq (net, subnet_number (high, netmask))) { if (!addr_eq (net, subnet_number (high, subnet -> netmask))) {
strcpy (lowbuf, piaddr (low)); strcpy (lowbuf, piaddr (low));
strcpy (highbuf, piaddr (high)); strcpy (highbuf, piaddr (high));
strcpy (netbuf, piaddr (netmask)); strcpy (netbuf, piaddr (subnet -> netmask));
error ("Address range %s to %s, netmask %s spans %s!", error ("Address range %s to %s, netmask %s spans %s!",
lowbuf, highbuf, netbuf, "multiple subnets"); 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... */ /* Get the high and low host addresses... */
max = host_addr (high, netmask); max = host_addr (high, subnet -> netmask);
min = host_addr (low, netmask); min = host_addr (low, subnet -> netmask);
/* Allow range to be specified high-to-low as well as low-to-high. */ /* Allow range to be specified high-to-low as well as low-to-high. */
if (min > max) { if (min > max) {
max = min; max = min;
min = host_addr (high, netmask); min = host_addr (high, subnet -> netmask);
} }
/* Get a lease structure for each address in the range. */ /* 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)); memset (address_range, 0, (sizeof *address_range) * (max - min + 1));
/* Fill in the last lease if it hasn't been already... */ /* 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]; subnet -> last_lease = &address_range [0];
}
/* Fill out the lease structures with some minimal information. */ /* Fill out the lease structures with some minimal information. */
for (i = 0; i < max - min + 1; i++) { for (i = 0; i < max - min + 1; i++) {
@@ -269,11 +254,6 @@ void supersede_lease (comp, lease)
struct subnet *parent; struct subnet *parent;
struct lease *lp; 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 /* If the existing lease hasn't expired and has a different
unique identifier or, if it doesn't have a unique unique identifier or, if it doesn't have a unique
identifier, a different hardware address, then the two identifier, a different hardware address, then the two
@@ -325,7 +305,6 @@ printf ("\n");
/* Copy the data files, but not the linkages. */ /* Copy the data files, but not the linkages. */
comp -> starts = lease -> starts; comp -> starts = lease -> starts;
comp -> ends = lease -> ends;
comp -> timestamp = lease -> timestamp; comp -> timestamp = lease -> timestamp;
comp -> uid = lease -> uid; comp -> uid = lease -> uid;
comp -> uid_len = lease -> uid_len; comp -> uid_len = lease -> uid_len;
@@ -373,13 +352,13 @@ printf ("\n");
head of the list. */ head of the list. */
comp -> contain -> leases = comp; comp -> contain -> leases = comp;
comp -> contain -> last_lease = 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 /* Skip down the list until we run out of list
or find a place for comp. */ or find a place for comp. */
while (lp -> next && lp -> ends > comp -> ends) { while (lp -> next && lp -> ends > lease -> ends) {
lp = lp -> next; lp = lp -> next;
} }
if (lp -> ends > comp -> ends) { if (lp -> ends > lease -> ends) {
/* If we ran out of list, put comp /* If we ran out of list, put comp
at the end. */ at the end. */
lp -> next = comp; lp -> next = comp;
@@ -389,7 +368,7 @@ printf ("\n");
} else { } else {
/* If we didn't, put it between lp and /* If we didn't, put it between lp and
the previous item on the list. */ the previous item on the list. */
comp -> prev = lp -> prev; if ((comp -> prev = lp -> prev))
comp -> prev -> next = comp; comp -> prev -> next = comp;
comp -> next = lp; comp -> next = lp;
lp -> prev = comp; lp -> prev = comp;
@@ -397,10 +376,10 @@ printf ("\n");
} else { } else {
/* Skip up the list until we run out of list /* Skip up the list until we run out of list
or find a place for comp. */ or find a place for comp. */
while (lp -> prev && lp -> ends < comp -> ends) { while (lp -> prev && lp -> ends < lease -> ends) {
lp = lp -> prev; lp = lp -> prev;
} }
if (lp -> ends < comp -> ends) { if (lp -> ends < lease -> ends) {
/* If we ran out of list, put comp /* If we ran out of list, put comp
at the beginning. */ at the beginning. */
lp -> prev = comp; lp -> prev = comp;
@@ -410,13 +389,14 @@ printf ("\n");
} else { } else {
/* If we didn't, put it between lp and /* If we didn't, put it between lp and
the next item on the list. */ the next item on the list. */
comp -> next = lp -> next; if ((comp -> next = lp -> next))
comp -> next -> prev = comp; comp -> next -> prev = comp;
comp -> prev = lp; comp -> prev = lp;
lp -> next = comp; lp -> next = comp;
} }
} }
comp -> contain -> insertion_point = comp; comp -> contain -> insertion_point = comp;
comp -> ends = lease -> ends;
} }
} }
@@ -427,8 +407,8 @@ void release_lease (lease)
{ {
struct lease lt; struct lease lt;
lease -> ends = 0;
lt = *lease; lt = *lease;
lt.ends = cur_time;
supersede_lease (lease, &lt); supersede_lease (lease, &lt);
} }

View File

@@ -150,10 +150,10 @@ void parse_option_buffer (packet, buffer, length)
/* Cons up options based on client-supplied desired option list (if any) /* Cons up options based on client-supplied desired option list (if any)
and selected server option list. */ and selected server option list. */
void cons_options (inpacket, outpacket, hp, overload) void cons_options (inpacket, outpacket, options, overload)
struct packet *inpacket; struct packet *inpacket;
struct packet *outpacket; struct packet *outpacket;
struct host_decl *hp; struct tree_cache **options;
int overload; /* Overload flags that may be set. */ int overload; /* Overload flags that may be set. */
{ {
option_mask options_have; /* Options we can send. */ 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. */ /* Make a bitmask of all the options we have available. */
OPTION_ZERO (options_have); OPTION_ZERO (options_have);
for (i = 0; i < 256; i++) for (i = 0; i < 256; i++)
if (hp -> options [i]) if (options [i])
OPTION_SET (options_have, i); OPTION_SET (options_have, i);
/* Put the cookie up front... */ /* Put the cookie up front... */
@@ -235,7 +235,7 @@ void cons_options (inpacket, outpacket, hp, overload)
int length; int length;
/* If no data is available for this option, skip it. */ /* If no data is available for this option, skip it. */
if (!hp -> options [code]) if (!options [code])
continue; continue;
/* Don't look at options that have already been stored. */ /* Don't look at options that have already been stored. */
@@ -243,11 +243,11 @@ void cons_options (inpacket, outpacket, hp, overload)
continue; continue;
/* Find the value of the option... */ /* Find the value of the option... */
if (!tree_evaluate (hp -> options [code])) if (!tree_evaluate (options [code]))
continue; continue;
/* We should now have a constant length for the option. */ /* 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 there's no space for this option, skip it. */
if ((bufix + OPTION_SPACE (length) + reserved) > buflen) { if ((bufix + OPTION_SPACE (length) + reserved) > buflen) {
@@ -260,7 +260,7 @@ void cons_options (inpacket, outpacket, hp, overload)
} }
/* Otherwise, store the option. */ /* Otherwise, store the option. */
result = store_option (hp, code, result = store_option (options, code,
buffer + bufix, buffer + bufix,
buflen - bufix - reserved, buflen - bufix - reserved,
stored_length); stored_length);
@@ -268,16 +268,16 @@ void cons_options (inpacket, outpacket, hp, overload)
/* The following test should always succeed because of /* The following test should always succeed because of
preconditioning above. */ preconditioning above. */
if (stored_length [code] == hp -> options [code] -> len) if (stored_length [code] == options [code] -> len)
OPTION_SET (options_done, code); OPTION_SET (options_done, code);
else { else {
warn ("%s: Only stored %d out of %d bytes.", warn ("%s: Only stored %d out of %d bytes.",
dhcp_options [code].name, dhcp_options [code].name,
stored_length [code], stored_length [code],
hp -> options [code] -> len); options [code] -> len);
if (++missed == 1) { if (++missed == 1) {
missed_code = code; missed_code = code;
missed_length = hp -> options [code] -> len missed_length = options [code] -> len
- stored_length [code]; - stored_length [code];
} }
} }
@@ -300,20 +300,20 @@ void cons_options (inpacket, outpacket, hp, overload)
overloading. */ overloading. */
if (reserved && missed == 1 if (reserved && missed == 1
&& (bufix + OPTION_SPACE (missed_length) <= buflen)) { && (bufix + OPTION_SPACE (missed_length) <= buflen)) {
result = store_option (hp, missed_code, result = store_option (options, missed_code,
buffer + bufix, buflen - bufix, buffer + bufix, buflen - bufix,
stored_length); stored_length);
bufix += result; bufix += result;
/* This test should always fail -- we'll send bad /* This test should always fail -- we'll send bad
data if it doesn't. */ data if it doesn't. */
if (stored_length [missed_code] if (stored_length [missed_code]
== hp -> options [missed_code] -> len) { == options [missed_code] -> len) {
OPTION_SET (options_done, missed_code); OPTION_SET (options_done, missed_code);
} else { } else {
warn ("%s (last): Only stored %d out of %d bytes.", warn ("%s (last): Only stored %d out of %d bytes.",
dhcp_options [missed_code].name, dhcp_options [missed_code].name,
stored_length [missed_code], stored_length [missed_code],
hp -> options [missed_code] -> len); options [missed_code] -> len);
} }
return; return;
} }
@@ -323,7 +323,7 @@ void cons_options (inpacket, outpacket, hp, overload)
option into the current buffer and part into the next. */ option into the current buffer and part into the next. */
if (bufix + OPTION_SPACE (missed_length) + reserved if (bufix + OPTION_SPACE (missed_length) + reserved
< buflen + (overload & 1 ? 128 : 0) + (overload & 2 ? 64 : 0)) { < buflen + (overload & 1 ? 128 : 0) + (overload & 2 ? 64 : 0)) {
result = store_option (hp, missed_code, result = store_option (options, missed_code,
buffer + bufix, buffer + bufix,
buflen - bufix - reserved, buflen - bufix - reserved,
stored_length); stored_length);
@@ -331,7 +331,7 @@ void cons_options (inpacket, outpacket, hp, overload)
/* This test should never fail. */ /* This test should never fail. */
if (stored_length [missed_code] if (stored_length [missed_code]
== hp -> options [missed_code] -> len) { == options [missed_code] -> len) {
OPTION_SET (options_done, missed_code); OPTION_SET (options_done, missed_code);
warn ("%s: Unexpected completed store.", warn ("%s: Unexpected completed store.",
dhcp_options [missed_code].name); 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 data that has been stored so far. Return 1 if all the option data
has been stored. */ has been stored. */
int store_option (hp, code, buffer, buflen, stored_length) int store_option (options, code, buffer, buflen, stored_length)
struct host_decl *hp; struct tree_cache **options;
unsigned char code; unsigned char code;
unsigned char *buffer; unsigned char *buffer;
int buflen; int buflen;
int *stored_length; int *stored_length;
{ {
int length = hp -> options [code] -> len - stored_length [code]; int length = options [code] -> len - stored_length [code];
int bufix = 0; int bufix = 0;
printf ("store_option: length = %d buflen = %d packet %d stored %d\n", 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) { if (length > buflen) {
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; unsigned char incr = length > 255 ? 255 : length;
buffer [bufix] = code; buffer [bufix] = code;
buffer [bufix + 1] = incr; buffer [bufix + 1] = incr;
memcpy (buffer + bufix + 2, (hp -> options [code] -> value memcpy (buffer + bufix + 2, (options [code] -> value
+ stored_length [code]), incr); + stored_length [code]), incr);
length -= incr; length -= incr;
stored_length [code] += incr; stored_length [code] += incr;

View File

@@ -326,6 +326,17 @@ struct option dhcp_options [256] = {
/* Default dhcp option priority list (this is ad hoc and should not be /* Default dhcp option priority list (this is ad hoc and should not be
mistaken for a carefully crafted and optimized list). */ mistaken for a carefully crafted and optimized list). */
unsigned char dhcp_option_default_priority_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_SUBNET_MASK,
DHO_TIME_OFFSET, DHO_TIME_OFFSET,
DHO_ROUTERS, DHO_ROUTERS,
@@ -375,18 +386,7 @@ unsigned char dhcp_option_default_priority_list [] = {
DHO_NETBIOS_SCOPE, DHO_NETBIOS_SCOPE,
DHO_FONT_SERVERS, DHO_FONT_SERVERS,
DHO_X_DISPLAY_MANAGER, 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_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 = int sizeof_dhcp_option_default_priority_list =

View File

@@ -277,6 +277,10 @@ static int intern (atom, dfv)
if (!strcasecmp (atom + 1, "iaddr")) if (!strcasecmp (atom + 1, "iaddr"))
return CIADDR; return CIADDR;
break; break;
case 'd':
if (!strcasecmp (atom + 1, "efault-lease-time"))
return DEFAULT_LEASE_TIME;
break;
case 'e': case 'e':
if (!strcasecmp (atom + 1, "thernet")) if (!strcasecmp (atom + 1, "thernet"))
return ETHERNET; return ETHERNET;
@@ -303,6 +307,14 @@ static int intern (atom, dfv)
if (!strcasecmp (atom + 1, "ease")) if (!strcasecmp (atom + 1, "ease"))
return LEASE; return LEASE;
break; 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': case 'p':
if (!strcasecmp (atom + 1, "acket")) if (!strcasecmp (atom + 1, "acket"))
return PACKET; return PACKET;
@@ -320,6 +332,8 @@ static int intern (atom, dfv)
return STARTS; return STARTS;
if (!strcasecmp (atom + 1, "iaddr")) if (!strcasecmp (atom + 1, "iaddr"))
return SIADDR; return SIADDR;
if (!strcasecmp (atom + 1, "ubnet"))
return SUBNET;
break; break;
case 't': case 't':
if (!strcasecmp (atom + 1, "timestamp")) if (!strcasecmp (atom + 1, "timestamp"))

View File

@@ -102,9 +102,9 @@ void parse_statement (cfile)
parsed_time = parse_timestamp (cfile, &bc); parsed_time = parse_timestamp (cfile, &bc);
} }
break; break;
case RANGE: case SUBNET:
if (!setjmp (bc)) { if (!setjmp (bc)) {
parse_address_range (cfile, &bc); parse_subnet_statement (cfile, &bc);
} }
break; break;
default: default:
@@ -209,6 +209,113 @@ char *parse_host_name (cfile, bc)
return s; 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 /* host_declaration :== hardware_declaration | filename_declaration
| fixed_addr_declaration | option_declaration */ | fixed_addr_declaration | option_declaration */
@@ -232,7 +339,7 @@ void parse_host_decl (cfile, bc, decl)
parse_fixed_addr_decl (cfile, bc, decl); parse_fixed_addr_decl (cfile, bc, decl);
break; break;
case OPTION: case OPTION:
parse_option_decl (cfile, bc, decl); parse_option_decl (cfile, bc, decl -> options);
break; break;
case CIADDR: case CIADDR:
decl -> 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 would be painful to come up with BNF for it. However, it always
starts as above. */ starts as above. */
void parse_option_decl (cfile, bc, decl) void parse_option_decl (cfile, bc, options)
FILE *cfile; FILE *cfile;
jmp_buf *bc; jmp_buf *bc;
struct host_decl *decl; struct tree_cache **options;
{ {
char *val; char *val;
int token; int token;
@@ -570,11 +677,11 @@ void parse_option_decl (cfile, bc, decl)
} }
} while (*fmt == 'A'); } while (*fmt == 'A');
if (decl -> options [option -> code]) { if (options [option -> code]) {
parse_warn ("duplicate option code %d (%s).", parse_warn ("duplicate option code %d (%s).",
option -> code, option -> name); option -> code, option -> name);
} }
decl -> options [option -> code] = tree_cache (tree); options [option -> code] = tree_cache (tree);
} }
/* timestamp :== TIMESTAMP date SEMI /* timestamp :== TIMESTAMP date SEMI
@@ -724,13 +831,14 @@ struct lease *parse_lease_statement (cfile, bc)
return &lease; 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; FILE *cfile;
jmp_buf *bc; jmp_buf *bc;
struct subnet *subnet;
{ {
struct iaddr low, high, mask; struct iaddr low, high;
unsigned char addr [4]; unsigned char addr [4];
int len = sizeof addr; int len = sizeof addr;
int token; int token;
@@ -746,21 +854,8 @@ void parse_address_range (cfile, bc)
memcpy (high.iabuf, addr, len); memcpy (high.iabuf, addr, len);
high.len = 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... */ /* 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 /* date :== NUMBER NUMBER/NUMBER/NUMBER NUMBER:NUMBER:NUMBER

View File

@@ -105,12 +105,15 @@ int main (argc, argv, envp)
FD_ZERO (&w); FD_ZERO (&w);
FD_ZERO (&x); FD_ZERO (&x);
FD_SET (sock, &r); FD_SET (sock, &r);
FD_SET (sock, &w);
FD_SET (sock, &x);
FD_SET (0, &r); /* stdin */ FD_SET (0, &r); /* stdin */
if (select (sock + 1, &r, &w, &x, (struct timeval *)0) < 0) { if (select (sock + 1, &r, &w, &x, (struct timeval *)0) < 0) {
error ("select: %m"); error ("select: %m");
} }
if (FD_ISSET (sock, &r)) { if (FD_ISSET (sock, &r) || FD_ISSET (sock, &w)
|| FD_ISSET (sock, &x)) {
if ((result = if ((result =
recvfrom (sock, packbuf, sizeof packbuf, 0, recvfrom (sock, packbuf, sizeof packbuf, 0,
(struct sockaddr *)&from, &fromlen)) (struct sockaddr *)&from, &fromlen))
@@ -188,7 +191,7 @@ int main (argc, argv, envp)
} }
cons_options ((struct packet *)0, cons_options ((struct packet *)0,
&outgoing, &decl, bufs); &outgoing, decl.options, bufs);
if (decl.ciaddr) { if (decl.ciaddr) {
tree_evaluate (decl.ciaddr); tree_evaluate (decl.ciaddr);

119
dhcp.c
View File

@@ -54,6 +54,18 @@ void dhcp (packet)
struct lease lt; struct lease lt;
TIME lease_time; 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); dump_packet (packet);
/* Try to find a lease that's been assigned to the specified /* Try to find a lease that's been assigned to the specified
@@ -86,20 +98,6 @@ void dhcp (packet)
} else } else
ip_lease = (struct lease *)0; 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... */ /* Toss extra pointers to the same lease... */
if (ip_lease == hw_lease) if (ip_lease == hw_lease)
ip_lease = (struct lease *)0; ip_lease = (struct lease *)0;
@@ -108,20 +106,6 @@ void dhcp (packet)
if (ip_lease == uid_lease) if (ip_lease == uid_lease)
ip_lease = (struct lease *)0; 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 /* 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 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 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; 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 /* At this point, if ip_lease is nonzero, we can assign it to
this client. */ this client. */
lease = ip_lease; lease = ip_lease;
@@ -249,5 +219,68 @@ void dhcp (packet)
supersede_lease (lease, &lt); supersede_lease (lease, &lt);
/* Send a response to the client... */ /* 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
View File

@@ -57,6 +57,7 @@ struct subnet *local_subnet;
u_int32_t *server_addrlist; u_int32_t *server_addrlist;
int server_addrcount; int server_addrcount;
u_int16_t server_port; u_int16_t server_port;
struct iaddr siaddr;
int main (argc, argv, envp) int main (argc, argv, envp)
int argc; int argc;
@@ -66,7 +67,6 @@ int main (argc, argv, envp)
int port = 0; int port = 0;
int i; int i;
struct sockaddr_in name; struct sockaddr_in name;
struct iaddr taddr;
u_int32_t *addrlist = (u_int32_t *)0; u_int32_t *addrlist = (u_int32_t *)0;
int addrcount = 0; int addrcount = 0;
struct tree *addrtree = (struct tree *)0; struct tree *addrtree = (struct tree *)0;
@@ -152,7 +152,7 @@ int main (argc, argv, envp)
} }
#endif #endif
taddr.len = 0; siaddr.len = 0;
server_addrlist = get_interface_list (&server_addrcount); server_addrlist = get_interface_list (&server_addrcount);
for (i = 0; i < server_addrcount; i++) { for (i = 0; i < server_addrcount; i++) {
struct sockaddr_in foo; struct sockaddr_in foo;
@@ -160,13 +160,13 @@ int main (argc, argv, envp)
printf ("Address %d: %s\n", i, inet_ntoa (foo.sin_addr)); printf ("Address %d: %s\n", i, inet_ntoa (foo.sin_addr));
if (server_addrlist [i] != htonl (INADDR_LOOPBACK)) { if (server_addrlist [i] != htonl (INADDR_LOOPBACK)) {
if (taddr.len) { if (siaddr.len) {
error ("dhcpd currently does not support " error ("dhcpd currently does not support "
"multiple interfaces"); "multiple interfaces");
} }
taddr.len = 4; siaddr.len = 4;
memcpy (taddr.iabuf, &server_addrlist [i], 4); memcpy (siaddr.iabuf, &server_addrlist [i], 4);
local_subnet = find_subnet (taddr); local_subnet = find_subnet (siaddr);
} }
} }
@@ -184,8 +184,6 @@ int main (argc, argv, envp)
close (i); close (i);
} }
dump_subnets ();
/* Receive packets and dispatch them... */ /* Receive packets and dispatch them... */
dispatch (); dispatch ();

View File

@@ -1,5 +1,8 @@
range 204.254.239.11 204.254.239.17 255.255.255.0; subnet 204.254.239.0 netmask 255.255.255.0
range 204.254.240.11 204.254.240.12 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 host minuet
hardware ethernet 08:00:2b:35:0c:18 hardware ethernet 08:00:2b:35:0c:18

16
dhcpd.h
View File

@@ -121,6 +121,7 @@ struct subnet {
struct iaddr netmask; struct iaddr netmask;
TIME default_lease_time; TIME default_lease_time;
TIME max_lease_time; TIME max_lease_time;
struct tree_cache *options [256];
struct lease *leases; struct lease *leases;
struct lease *insertion_point; struct lease *insertion_point;
struct lease *last_lease; struct lease *last_lease;
@@ -159,8 +160,8 @@ typedef unsigned char option_mask [16];
void parse_options PROTO ((struct packet *)); void parse_options PROTO ((struct packet *));
void parse_option_buffer PROTO ((struct packet *, unsigned char *, int)); void parse_option_buffer PROTO ((struct packet *, unsigned char *, int));
void cons_options PROTO ((struct packet *, struct packet *, void cons_options PROTO ((struct packet *, struct packet *,
struct host_decl *, int)); struct tree_cache **, int));
int store_option PROTO ((struct host_decl *, unsigned char, int store_option PROTO ((struct tree_cache **, unsigned char,
unsigned char *, int, int *)); unsigned char *, int, int *));
char *pretty_print_option PROTO ((unsigned char, unsigned char *, int)); char *pretty_print_option PROTO ((unsigned char, unsigned char *, int));
@@ -175,9 +176,12 @@ int parse_warn PROTO ((char *, ...));
TIME cur_time; TIME cur_time;
TIME default_lease_time; TIME default_lease_time;
TIME max_lease_time; TIME max_lease_time;
extern u_int32_t *server_addrlist; extern u_int32_t *server_addrlist;
extern int server_addrcount; extern int server_addrcount;
extern u_int16_t server_port; extern u_int16_t server_port;
struct iaddr siaddr;
int main PROTO ((int, char **, char **)); int main PROTO ((int, char **, char **));
void cleanup PROTO ((void)); void cleanup PROTO ((void));
void do_packet PROTO ((unsigned char *, int, void do_packet PROTO ((unsigned char *, int,
@@ -196,17 +200,19 @@ void parse_statement PROTO ((FILE *));
void skip_to_semi PROTO ((FILE *)); void skip_to_semi PROTO ((FILE *));
struct host_decl *parse_host_statement PROTO ((FILE *, jmp_buf *)); struct host_decl *parse_host_statement PROTO ((FILE *, jmp_buf *));
char *parse_host_name 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_host_decl PROTO ((FILE *, jmp_buf *, struct host_decl *));
void parse_hardware_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 *)); struct hardware parse_hardware_addr PROTO ((FILE *, jmp_buf *));
void parse_filename_decl PROTO ((FILE *, jmp_buf *, struct host_decl *)); void parse_filename_decl PROTO ((FILE *, jmp_buf *, struct host_decl *));
struct tree *parse_ip_addr_or_hostname PROTO ((FILE *, jmp_buf *, int)); 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_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_timestamp PROTO ((FILE *, jmp_buf *));
TIME parse_date PROTO ((FILE *, jmp_buf *)); TIME parse_date PROTO ((FILE *, jmp_buf *));
struct lease *parse_lease_statement 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 *parse_numeric_aggregate PROTO ((FILE *, jmp_buf *,
unsigned char *, int *, unsigned char *, int *,
int, int, 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_name PROTO ((char *name));
struct host_decl *find_host_by_addr PROTO ((int, unsigned char *, int)); struct host_decl *find_host_by_addr PROTO ((int, unsigned char *, int));
void new_address_range PROTO ((struct iaddr, struct iaddr, void new_address_range PROTO ((struct iaddr, struct iaddr,
struct iaddr)); struct subnet *));
extern struct subnet *find_subnet (struct iaddr); extern struct subnet *find_subnet (struct iaddr);
void enter_subnet (struct subnet *); void enter_subnet (struct subnet *);
void enter_lease PROTO ((struct lease *)); void enter_lease PROTO ((struct lease *));

View File

@@ -68,7 +68,12 @@
#define YIADDR 275 #define YIADDR 275
#define SIADDR 276 #define SIADDR 276
#define GIADDR 277 #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 && \ #define is_identifier(x) ((x) >= FIRST_TOKEN && \
(x) <= LAST_TOKEN && \ (x) <= LAST_TOKEN && \

View File

@@ -121,6 +121,7 @@ struct subnet {
struct iaddr netmask; struct iaddr netmask;
TIME default_lease_time; TIME default_lease_time;
TIME max_lease_time; TIME max_lease_time;
struct tree_cache *options [256];
struct lease *leases; struct lease *leases;
struct lease *insertion_point; struct lease *insertion_point;
struct lease *last_lease; struct lease *last_lease;
@@ -159,8 +160,8 @@ typedef unsigned char option_mask [16];
void parse_options PROTO ((struct packet *)); void parse_options PROTO ((struct packet *));
void parse_option_buffer PROTO ((struct packet *, unsigned char *, int)); void parse_option_buffer PROTO ((struct packet *, unsigned char *, int));
void cons_options PROTO ((struct packet *, struct packet *, void cons_options PROTO ((struct packet *, struct packet *,
struct host_decl *, int)); struct tree_cache **, int));
int store_option PROTO ((struct host_decl *, unsigned char, int store_option PROTO ((struct tree_cache **, unsigned char,
unsigned char *, int, int *)); unsigned char *, int, int *));
char *pretty_print_option PROTO ((unsigned char, unsigned char *, int)); char *pretty_print_option PROTO ((unsigned char, unsigned char *, int));
@@ -175,9 +176,12 @@ int parse_warn PROTO ((char *, ...));
TIME cur_time; TIME cur_time;
TIME default_lease_time; TIME default_lease_time;
TIME max_lease_time; TIME max_lease_time;
extern u_int32_t *server_addrlist; extern u_int32_t *server_addrlist;
extern int server_addrcount; extern int server_addrcount;
extern u_int16_t server_port; extern u_int16_t server_port;
struct iaddr siaddr;
int main PROTO ((int, char **, char **)); int main PROTO ((int, char **, char **));
void cleanup PROTO ((void)); void cleanup PROTO ((void));
void do_packet PROTO ((unsigned char *, int, void do_packet PROTO ((unsigned char *, int,
@@ -196,17 +200,19 @@ void parse_statement PROTO ((FILE *));
void skip_to_semi PROTO ((FILE *)); void skip_to_semi PROTO ((FILE *));
struct host_decl *parse_host_statement PROTO ((FILE *, jmp_buf *)); struct host_decl *parse_host_statement PROTO ((FILE *, jmp_buf *));
char *parse_host_name 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_host_decl PROTO ((FILE *, jmp_buf *, struct host_decl *));
void parse_hardware_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 *)); struct hardware parse_hardware_addr PROTO ((FILE *, jmp_buf *));
void parse_filename_decl PROTO ((FILE *, jmp_buf *, struct host_decl *)); void parse_filename_decl PROTO ((FILE *, jmp_buf *, struct host_decl *));
struct tree *parse_ip_addr_or_hostname PROTO ((FILE *, jmp_buf *, int)); 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_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_timestamp PROTO ((FILE *, jmp_buf *));
TIME parse_date PROTO ((FILE *, jmp_buf *)); TIME parse_date PROTO ((FILE *, jmp_buf *));
struct lease *parse_lease_statement 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 *parse_numeric_aggregate PROTO ((FILE *, jmp_buf *,
unsigned char *, int *, unsigned char *, int *,
int, int, 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_name PROTO ((char *name));
struct host_decl *find_host_by_addr PROTO ((int, unsigned char *, int)); struct host_decl *find_host_by_addr PROTO ((int, unsigned char *, int));
void new_address_range PROTO ((struct iaddr, struct iaddr, void new_address_range PROTO ((struct iaddr, struct iaddr,
struct iaddr)); struct subnet *));
extern struct subnet *find_subnet (struct iaddr); extern struct subnet *find_subnet (struct iaddr);
void enter_subnet (struct subnet *); void enter_subnet (struct subnet *);
void enter_lease PROTO ((struct lease *)); void enter_lease PROTO ((struct lease *));

View File

@@ -68,7 +68,12 @@
#define YIADDR 275 #define YIADDR 275
#define SIADDR 276 #define SIADDR 276
#define GIADDR 277 #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 && \ #define is_identifier(x) ((x) >= FIRST_TOKEN && \
(x) <= LAST_TOKEN && \ (x) <= LAST_TOKEN && \

View File

@@ -92,11 +92,11 @@ struct host_decl *find_host_by_addr (htype, haddr, hlen)
return (struct host_decl *)0; return (struct host_decl *)0;
} }
void new_address_range (low, high, netmask) void new_address_range (low, high, subnet)
struct iaddr low, high, netmask; struct iaddr low, high;
struct subnet *subnet;
{ {
struct lease *address_range, *lp, *plp; struct lease *address_range, *lp, *plp;
struct subnet *subnet;
struct iaddr net; struct iaddr net;
int min, max, i; int min, max, i;
char lowbuf [16], highbuf [16], netbuf [16]; char lowbuf [16], highbuf [16], netbuf [16];
@@ -110,39 +110,23 @@ void new_address_range (low, high, netmask)
lease_hw_addr_hash = new_hash (); lease_hw_addr_hash = new_hash ();
/* Make sure that high and low addresses are in same subnet. */ /* Make sure that high and low addresses are in same subnet. */
net = subnet_number (low, netmask); net = subnet_number (low, subnet -> netmask);
if (!addr_eq (net, subnet_number (high, netmask))) { if (!addr_eq (net, subnet_number (high, subnet -> netmask))) {
strcpy (lowbuf, piaddr (low)); strcpy (lowbuf, piaddr (low));
strcpy (highbuf, piaddr (high)); strcpy (highbuf, piaddr (high));
strcpy (netbuf, piaddr (netmask)); strcpy (netbuf, piaddr (subnet -> netmask));
error ("Address range %s to %s, netmask %s spans %s!", error ("Address range %s to %s, netmask %s spans %s!",
lowbuf, highbuf, netbuf, "multiple subnets"); 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... */ /* Get the high and low host addresses... */
max = host_addr (high, netmask); max = host_addr (high, subnet -> netmask);
min = host_addr (low, netmask); min = host_addr (low, subnet -> netmask);
/* Allow range to be specified high-to-low as well as low-to-high. */ /* Allow range to be specified high-to-low as well as low-to-high. */
if (min > max) { if (min > max) {
max = min; max = min;
min = host_addr (high, netmask); min = host_addr (high, subnet -> netmask);
} }
/* Get a lease structure for each address in the range. */ /* 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)); memset (address_range, 0, (sizeof *address_range) * (max - min + 1));
/* Fill in the last lease if it hasn't been already... */ /* 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]; subnet -> last_lease = &address_range [0];
}
/* Fill out the lease structures with some minimal information. */ /* Fill out the lease structures with some minimal information. */
for (i = 0; i < max - min + 1; i++) { for (i = 0; i < max - min + 1; i++) {
@@ -269,11 +254,6 @@ void supersede_lease (comp, lease)
struct subnet *parent; struct subnet *parent;
struct lease *lp; 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 /* If the existing lease hasn't expired and has a different
unique identifier or, if it doesn't have a unique unique identifier or, if it doesn't have a unique
identifier, a different hardware address, then the two identifier, a different hardware address, then the two
@@ -325,7 +305,6 @@ printf ("\n");
/* Copy the data files, but not the linkages. */ /* Copy the data files, but not the linkages. */
comp -> starts = lease -> starts; comp -> starts = lease -> starts;
comp -> ends = lease -> ends;
comp -> timestamp = lease -> timestamp; comp -> timestamp = lease -> timestamp;
comp -> uid = lease -> uid; comp -> uid = lease -> uid;
comp -> uid_len = lease -> uid_len; comp -> uid_len = lease -> uid_len;
@@ -373,13 +352,13 @@ printf ("\n");
head of the list. */ head of the list. */
comp -> contain -> leases = comp; comp -> contain -> leases = comp;
comp -> contain -> last_lease = 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 /* Skip down the list until we run out of list
or find a place for comp. */ or find a place for comp. */
while (lp -> next && lp -> ends > comp -> ends) { while (lp -> next && lp -> ends > lease -> ends) {
lp = lp -> next; lp = lp -> next;
} }
if (lp -> ends > comp -> ends) { if (lp -> ends > lease -> ends) {
/* If we ran out of list, put comp /* If we ran out of list, put comp
at the end. */ at the end. */
lp -> next = comp; lp -> next = comp;
@@ -389,7 +368,7 @@ printf ("\n");
} else { } else {
/* If we didn't, put it between lp and /* If we didn't, put it between lp and
the previous item on the list. */ the previous item on the list. */
comp -> prev = lp -> prev; if ((comp -> prev = lp -> prev))
comp -> prev -> next = comp; comp -> prev -> next = comp;
comp -> next = lp; comp -> next = lp;
lp -> prev = comp; lp -> prev = comp;
@@ -397,10 +376,10 @@ printf ("\n");
} else { } else {
/* Skip up the list until we run out of list /* Skip up the list until we run out of list
or find a place for comp. */ or find a place for comp. */
while (lp -> prev && lp -> ends < comp -> ends) { while (lp -> prev && lp -> ends < lease -> ends) {
lp = lp -> prev; lp = lp -> prev;
} }
if (lp -> ends < comp -> ends) { if (lp -> ends < lease -> ends) {
/* If we ran out of list, put comp /* If we ran out of list, put comp
at the beginning. */ at the beginning. */
lp -> prev = comp; lp -> prev = comp;
@@ -410,13 +389,14 @@ printf ("\n");
} else { } else {
/* If we didn't, put it between lp and /* If we didn't, put it between lp and
the next item on the list. */ the next item on the list. */
comp -> next = lp -> next; if ((comp -> next = lp -> next))
comp -> next -> prev = comp; comp -> next -> prev = comp;
comp -> prev = lp; comp -> prev = lp;
lp -> next = comp; lp -> next = comp;
} }
} }
comp -> contain -> insertion_point = comp; comp -> contain -> insertion_point = comp;
comp -> ends = lease -> ends;
} }
} }
@@ -427,8 +407,8 @@ void release_lease (lease)
{ {
struct lease lt; struct lease lt;
lease -> ends = 0;
lt = *lease; lt = *lease;
lt.ends = cur_time;
supersede_lease (lease, &lt); supersede_lease (lease, &lt);
} }

View File

@@ -150,10 +150,10 @@ void parse_option_buffer (packet, buffer, length)
/* Cons up options based on client-supplied desired option list (if any) /* Cons up options based on client-supplied desired option list (if any)
and selected server option list. */ and selected server option list. */
void cons_options (inpacket, outpacket, hp, overload) void cons_options (inpacket, outpacket, options, overload)
struct packet *inpacket; struct packet *inpacket;
struct packet *outpacket; struct packet *outpacket;
struct host_decl *hp; struct tree_cache **options;
int overload; /* Overload flags that may be set. */ int overload; /* Overload flags that may be set. */
{ {
option_mask options_have; /* Options we can send. */ 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. */ /* Make a bitmask of all the options we have available. */
OPTION_ZERO (options_have); OPTION_ZERO (options_have);
for (i = 0; i < 256; i++) for (i = 0; i < 256; i++)
if (hp -> options [i]) if (options [i])
OPTION_SET (options_have, i); OPTION_SET (options_have, i);
/* Put the cookie up front... */ /* Put the cookie up front... */
@@ -235,7 +235,7 @@ void cons_options (inpacket, outpacket, hp, overload)
int length; int length;
/* If no data is available for this option, skip it. */ /* If no data is available for this option, skip it. */
if (!hp -> options [code]) if (!options [code])
continue; continue;
/* Don't look at options that have already been stored. */ /* Don't look at options that have already been stored. */
@@ -243,11 +243,11 @@ void cons_options (inpacket, outpacket, hp, overload)
continue; continue;
/* Find the value of the option... */ /* Find the value of the option... */
if (!tree_evaluate (hp -> options [code])) if (!tree_evaluate (options [code]))
continue; continue;
/* We should now have a constant length for the option. */ /* 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 there's no space for this option, skip it. */
if ((bufix + OPTION_SPACE (length) + reserved) > buflen) { if ((bufix + OPTION_SPACE (length) + reserved) > buflen) {
@@ -260,7 +260,7 @@ void cons_options (inpacket, outpacket, hp, overload)
} }
/* Otherwise, store the option. */ /* Otherwise, store the option. */
result = store_option (hp, code, result = store_option (options, code,
buffer + bufix, buffer + bufix,
buflen - bufix - reserved, buflen - bufix - reserved,
stored_length); stored_length);
@@ -268,16 +268,16 @@ void cons_options (inpacket, outpacket, hp, overload)
/* The following test should always succeed because of /* The following test should always succeed because of
preconditioning above. */ preconditioning above. */
if (stored_length [code] == hp -> options [code] -> len) if (stored_length [code] == options [code] -> len)
OPTION_SET (options_done, code); OPTION_SET (options_done, code);
else { else {
warn ("%s: Only stored %d out of %d bytes.", warn ("%s: Only stored %d out of %d bytes.",
dhcp_options [code].name, dhcp_options [code].name,
stored_length [code], stored_length [code],
hp -> options [code] -> len); options [code] -> len);
if (++missed == 1) { if (++missed == 1) {
missed_code = code; missed_code = code;
missed_length = hp -> options [code] -> len missed_length = options [code] -> len
- stored_length [code]; - stored_length [code];
} }
} }
@@ -300,20 +300,20 @@ void cons_options (inpacket, outpacket, hp, overload)
overloading. */ overloading. */
if (reserved && missed == 1 if (reserved && missed == 1
&& (bufix + OPTION_SPACE (missed_length) <= buflen)) { && (bufix + OPTION_SPACE (missed_length) <= buflen)) {
result = store_option (hp, missed_code, result = store_option (options, missed_code,
buffer + bufix, buflen - bufix, buffer + bufix, buflen - bufix,
stored_length); stored_length);
bufix += result; bufix += result;
/* This test should always fail -- we'll send bad /* This test should always fail -- we'll send bad
data if it doesn't. */ data if it doesn't. */
if (stored_length [missed_code] if (stored_length [missed_code]
== hp -> options [missed_code] -> len) { == options [missed_code] -> len) {
OPTION_SET (options_done, missed_code); OPTION_SET (options_done, missed_code);
} else { } else {
warn ("%s (last): Only stored %d out of %d bytes.", warn ("%s (last): Only stored %d out of %d bytes.",
dhcp_options [missed_code].name, dhcp_options [missed_code].name,
stored_length [missed_code], stored_length [missed_code],
hp -> options [missed_code] -> len); options [missed_code] -> len);
} }
return; return;
} }
@@ -323,7 +323,7 @@ void cons_options (inpacket, outpacket, hp, overload)
option into the current buffer and part into the next. */ option into the current buffer and part into the next. */
if (bufix + OPTION_SPACE (missed_length) + reserved if (bufix + OPTION_SPACE (missed_length) + reserved
< buflen + (overload & 1 ? 128 : 0) + (overload & 2 ? 64 : 0)) { < buflen + (overload & 1 ? 128 : 0) + (overload & 2 ? 64 : 0)) {
result = store_option (hp, missed_code, result = store_option (options, missed_code,
buffer + bufix, buffer + bufix,
buflen - bufix - reserved, buflen - bufix - reserved,
stored_length); stored_length);
@@ -331,7 +331,7 @@ void cons_options (inpacket, outpacket, hp, overload)
/* This test should never fail. */ /* This test should never fail. */
if (stored_length [missed_code] if (stored_length [missed_code]
== hp -> options [missed_code] -> len) { == options [missed_code] -> len) {
OPTION_SET (options_done, missed_code); OPTION_SET (options_done, missed_code);
warn ("%s: Unexpected completed store.", warn ("%s: Unexpected completed store.",
dhcp_options [missed_code].name); 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 data that has been stored so far. Return 1 if all the option data
has been stored. */ has been stored. */
int store_option (hp, code, buffer, buflen, stored_length) int store_option (options, code, buffer, buflen, stored_length)
struct host_decl *hp; struct tree_cache **options;
unsigned char code; unsigned char code;
unsigned char *buffer; unsigned char *buffer;
int buflen; int buflen;
int *stored_length; int *stored_length;
{ {
int length = hp -> options [code] -> len - stored_length [code]; int length = options [code] -> len - stored_length [code];
int bufix = 0; int bufix = 0;
printf ("store_option: length = %d buflen = %d packet %d stored %d\n", 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) { if (length > buflen) {
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; unsigned char incr = length > 255 ? 255 : length;
buffer [bufix] = code; buffer [bufix] = code;
buffer [bufix + 1] = incr; buffer [bufix + 1] = incr;
memcpy (buffer + bufix + 2, (hp -> options [code] -> value memcpy (buffer + bufix + 2, (options [code] -> value
+ stored_length [code]), incr); + stored_length [code]), incr);
length -= incr; length -= incr;
stored_length [code] += incr; stored_length [code] += incr;

View File

@@ -102,9 +102,9 @@ void parse_statement (cfile)
parsed_time = parse_timestamp (cfile, &bc); parsed_time = parse_timestamp (cfile, &bc);
} }
break; break;
case RANGE: case SUBNET:
if (!setjmp (bc)) { if (!setjmp (bc)) {
parse_address_range (cfile, &bc); parse_subnet_statement (cfile, &bc);
} }
break; break;
default: default:
@@ -209,6 +209,113 @@ char *parse_host_name (cfile, bc)
return s; 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 /* host_declaration :== hardware_declaration | filename_declaration
| fixed_addr_declaration | option_declaration */ | fixed_addr_declaration | option_declaration */
@@ -232,7 +339,7 @@ void parse_host_decl (cfile, bc, decl)
parse_fixed_addr_decl (cfile, bc, decl); parse_fixed_addr_decl (cfile, bc, decl);
break; break;
case OPTION: case OPTION:
parse_option_decl (cfile, bc, decl); parse_option_decl (cfile, bc, decl -> options);
break; break;
case CIADDR: case CIADDR:
decl -> 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 would be painful to come up with BNF for it. However, it always
starts as above. */ starts as above. */
void parse_option_decl (cfile, bc, decl) void parse_option_decl (cfile, bc, options)
FILE *cfile; FILE *cfile;
jmp_buf *bc; jmp_buf *bc;
struct host_decl *decl; struct tree_cache **options;
{ {
char *val; char *val;
int token; int token;
@@ -570,11 +677,11 @@ void parse_option_decl (cfile, bc, decl)
} }
} while (*fmt == 'A'); } while (*fmt == 'A');
if (decl -> options [option -> code]) { if (options [option -> code]) {
parse_warn ("duplicate option code %d (%s).", parse_warn ("duplicate option code %d (%s).",
option -> code, option -> name); option -> code, option -> name);
} }
decl -> options [option -> code] = tree_cache (tree); options [option -> code] = tree_cache (tree);
} }
/* timestamp :== TIMESTAMP date SEMI /* timestamp :== TIMESTAMP date SEMI
@@ -724,13 +831,14 @@ struct lease *parse_lease_statement (cfile, bc)
return &lease; 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; FILE *cfile;
jmp_buf *bc; jmp_buf *bc;
struct subnet *subnet;
{ {
struct iaddr low, high, mask; struct iaddr low, high;
unsigned char addr [4]; unsigned char addr [4];
int len = sizeof addr; int len = sizeof addr;
int token; int token;
@@ -746,21 +854,8 @@ void parse_address_range (cfile, bc)
memcpy (high.iabuf, addr, len); memcpy (high.iabuf, addr, len);
high.len = 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... */ /* 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 /* date :== NUMBER NUMBER/NUMBER/NUMBER NUMBER:NUMBER:NUMBER

View File

@@ -54,6 +54,18 @@ void dhcp (packet)
struct lease lt; struct lease lt;
TIME lease_time; 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); dump_packet (packet);
/* Try to find a lease that's been assigned to the specified /* Try to find a lease that's been assigned to the specified
@@ -86,20 +98,6 @@ void dhcp (packet)
} else } else
ip_lease = (struct lease *)0; 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... */ /* Toss extra pointers to the same lease... */
if (ip_lease == hw_lease) if (ip_lease == hw_lease)
ip_lease = (struct lease *)0; ip_lease = (struct lease *)0;
@@ -108,20 +106,6 @@ void dhcp (packet)
if (ip_lease == uid_lease) if (ip_lease == uid_lease)
ip_lease = (struct lease *)0; 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 /* 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 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 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; 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 /* At this point, if ip_lease is nonzero, we can assign it to
this client. */ this client. */
lease = ip_lease; lease = ip_lease;
@@ -249,5 +219,68 @@ void dhcp (packet)
supersede_lease (lease, &lt); supersede_lease (lease, &lt);
/* Send a response to the client... */ /* 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");
} }

View File

@@ -57,6 +57,7 @@ struct subnet *local_subnet;
u_int32_t *server_addrlist; u_int32_t *server_addrlist;
int server_addrcount; int server_addrcount;
u_int16_t server_port; u_int16_t server_port;
struct iaddr siaddr;
int main (argc, argv, envp) int main (argc, argv, envp)
int argc; int argc;
@@ -66,7 +67,6 @@ int main (argc, argv, envp)
int port = 0; int port = 0;
int i; int i;
struct sockaddr_in name; struct sockaddr_in name;
struct iaddr taddr;
u_int32_t *addrlist = (u_int32_t *)0; u_int32_t *addrlist = (u_int32_t *)0;
int addrcount = 0; int addrcount = 0;
struct tree *addrtree = (struct tree *)0; struct tree *addrtree = (struct tree *)0;
@@ -152,7 +152,7 @@ int main (argc, argv, envp)
} }
#endif #endif
taddr.len = 0; siaddr.len = 0;
server_addrlist = get_interface_list (&server_addrcount); server_addrlist = get_interface_list (&server_addrcount);
for (i = 0; i < server_addrcount; i++) { for (i = 0; i < server_addrcount; i++) {
struct sockaddr_in foo; struct sockaddr_in foo;
@@ -160,13 +160,13 @@ int main (argc, argv, envp)
printf ("Address %d: %s\n", i, inet_ntoa (foo.sin_addr)); printf ("Address %d: %s\n", i, inet_ntoa (foo.sin_addr));
if (server_addrlist [i] != htonl (INADDR_LOOPBACK)) { if (server_addrlist [i] != htonl (INADDR_LOOPBACK)) {
if (taddr.len) { if (siaddr.len) {
error ("dhcpd currently does not support " error ("dhcpd currently does not support "
"multiple interfaces"); "multiple interfaces");
} }
taddr.len = 4; siaddr.len = 4;
memcpy (taddr.iabuf, &server_addrlist [i], 4); memcpy (siaddr.iabuf, &server_addrlist [i], 4);
local_subnet = find_subnet (taddr); local_subnet = find_subnet (siaddr);
} }
} }
@@ -184,8 +184,6 @@ int main (argc, argv, envp)
close (i); close (i);
} }
dump_subnets ();
/* Receive packets and dispatch them... */ /* Receive packets and dispatch them... */
dispatch (); dispatch ();

View File

@@ -1,5 +1,8 @@
range 204.254.239.11 204.254.239.17 255.255.255.0; subnet 204.254.239.0 netmask 255.255.255.0
range 204.254.240.11 204.254.240.12 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 host minuet
hardware ethernet 08:00:2b:35:0c:18 hardware ethernet 08:00:2b:35:0c:18

View File

@@ -326,6 +326,17 @@ struct option dhcp_options [256] = {
/* Default dhcp option priority list (this is ad hoc and should not be /* Default dhcp option priority list (this is ad hoc and should not be
mistaken for a carefully crafted and optimized list). */ mistaken for a carefully crafted and optimized list). */
unsigned char dhcp_option_default_priority_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_SUBNET_MASK,
DHO_TIME_OFFSET, DHO_TIME_OFFSET,
DHO_ROUTERS, DHO_ROUTERS,
@@ -375,18 +386,7 @@ unsigned char dhcp_option_default_priority_list [] = {
DHO_NETBIOS_SCOPE, DHO_NETBIOS_SCOPE,
DHO_FONT_SERVERS, DHO_FONT_SERVERS,
DHO_X_DISPLAY_MANAGER, 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_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 = int sizeof_dhcp_option_default_priority_list =