2
0
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:
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 (&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);

View File

@@ -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"))

View File

@@ -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, &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)
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;

View File

@@ -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 =

View File

@@ -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"))

View File

@@ -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

View File

@@ -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
View File

@@ -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, &lt);
/* 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;
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 ();

View File

@@ -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
View File

@@ -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 *));

View File

@@ -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 && \

View File

@@ -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 *));

View File

@@ -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 && \

View File

@@ -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, &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)
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;

View File

@@ -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

View File

@@ -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, &lt);
/* 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;
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 ();

View File

@@ -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

View File

@@ -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 =