- Support for compressed 'domain name list' style DHCP option contents, and
in particular the domain search option (#119) was added.
+- The DHCP LEASEQUERY protocol as definied in RFC4388 is now implemented.
+ LEASEQUERY lets you query the DHCP server for information about a lease,
+ using either an IP address, MAC address, or client identifier. Thanks
+ to a patch from Justin Haddad.
+
+
Changes since 3.0.4
- A warning that host statements declared within subnet or shared-network
#ifndef lint
static char copyright[] =
-"$Id: conflex.c,v 1.101 2006/07/22 02:24:16 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n";
+"$Id: conflex.c,v 1.102 2006/07/25 13:25:59 shane Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
return LEASED_ADDRESS;
if (!strcasecmp (atom + 1, "ease-time"))
return LEASE_TIME;
+ if (!strcasecmp(atom + 1, "easequery"))
+ return LEASEQUERY;
if (!strcasecmp(atom + 1, "ength"))
return LENGTH;
if (!strcasecmp (atom + 1, "imit"))
#ifndef lint
static char copyright[] =
-"$Id: options.c,v 1.92 2006/07/22 02:24:16 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n";
+"$Id: options.c,v 1.93 2006/07/25 13:25:59 shane Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n";
#endif /* not lint */
#define DHCP_OPTION_DATA
/* If we weren't passed a buffer in which the data are saved and
refcounted, allocate one now. */
if (!bp) {
- if (!buffer_allocate (&lbp, length, MDL)) {
+ if (!buffer_allocate (&lbp, length + tp, MDL)) {
log_error ("no memory for option buffer.");
option_cache_dereference (&op, MDL);
return count;
}
+/*
+ * Add the option identified with the option number and data to the
+ * options state.
+ */
+int
+add_option(struct option_state *options,
+ unsigned int option_num,
+ void *data,
+ unsigned int data_len)
+{
+ struct option_cache *oc;
+ struct option *option;
+
+ /* INSIST(options != NULL); */
+ /* INSIST(data != NULL); */
+
+ option = NULL;
+ if (!option_code_hash_lookup(&option, dhcp_universe.code_hash,
+ &option_num, 0, MDL)) {
+ log_error("Attempting to add unknown option %d.", option_num);
+ return 0;
+ }
+
+ oc = NULL;
+ if (!option_cache_allocate(&oc, MDL)) {
+ log_error("No memory for option cache adding %s (option %d).",
+ option->name, option_num);
+ return 0;
+ }
+
+ if (!make_const_data(&oc->expression,
+ data,
+ data_len,
+ 0,
+ 0,
+ MDL)) {
+ log_error("No memory for constant data adding %s (option %d).",
+ option->name, option_num);
+ option_cache_dereference(&oc, MDL);
+ return 0;
+ }
+
+ oc->option = option;
+ save_option(&dhcp_universe, options, oc);
+ option_cache_dereference(&oc, MDL);
+
+ return 1;
+}
+
+
#ifndef lint
static char copyright[] =
-"$Id: tables.c,v 1.56 2006/07/22 02:24:16 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n";
+"$Id: tables.c,v 1.57 2006/07/25 13:25:59 shane Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
{ "nds-servers", "IA", &dhcp_universe, 85, 1 },
{ "nds-tree-name", "t", &dhcp_universe, 86, 1 },
{ "nds-context", "t", &dhcp_universe, 87, 1 },
+ { "client-last-transaction-time", "L", &dhcp_universe, 91, 1 },
+ { "associated-ip", "Ia", &dhcp_universe, 92, 1 },
{ "uap-servers", "t", &dhcp_universe, 98, 1 },
{ "subnet-selection", "I", &dhcp_universe, 118, 1 },
{ "domain-search", "D", &dhcp_universe, 119, 1 },
*/
#define DHCP_UDP_OVERHEAD (20 + /* IP header */ \
- 8) /* UDP header */
+ 8) /* UDP header */
#define DHCP_SNAME_LEN 64
#define DHCP_FILE_LEN 128
#define DHCP_FIXED_NON_UDP 236
#define DHCP_MIN_LEN 548
struct dhcp_packet {
- u_int8_t op; /* 0: Message opcode/type */
+ u_int8_t op; /* 0: Message opcode/type */
u_int8_t htype; /* 1: Hardware addr type (net/if_types.h) */
u_int8_t hlen; /* 2: Hardware addr length */
u_int8_t hops; /* 3: Number of relay agent hops from client */
char file [DHCP_FILE_LEN]; /* 104: Boot filename */
unsigned char options [DHCP_OPTION_LEN];
/* 212: Optional parameters
- (actual length dependent on MTU). */
+ (actual length dependent on MTU). */
};
/* BOOTP (rfc951) message types */
/* DHCP Option codes: */
-#define DHO_PAD 0
-#define DHO_SUBNET_MASK 1
-#define DHO_TIME_OFFSET 2
-#define DHO_ROUTERS 3
-#define DHO_TIME_SERVERS 4
-#define DHO_NAME_SERVERS 5
-#define DHO_DOMAIN_NAME_SERVERS 6
-#define DHO_LOG_SERVERS 7
-#define DHO_COOKIE_SERVERS 8
-#define DHO_LPR_SERVERS 9
-#define DHO_IMPRESS_SERVERS 10
-#define DHO_RESOURCE_LOCATION_SERVERS 11
-#define DHO_HOST_NAME 12
-#define DHO_BOOT_SIZE 13
-#define DHO_MERIT_DUMP 14
-#define DHO_DOMAIN_NAME 15
-#define DHO_SWAP_SERVER 16
-#define DHO_ROOT_PATH 17
-#define DHO_EXTENSIONS_PATH 18
-#define DHO_IP_FORWARDING 19
-#define DHO_NON_LOCAL_SOURCE_ROUTING 20
-#define DHO_POLICY_FILTER 21
-#define DHO_MAX_DGRAM_REASSEMBLY 22
-#define DHO_DEFAULT_IP_TTL 23
-#define DHO_PATH_MTU_AGING_TIMEOUT 24
-#define DHO_PATH_MTU_PLATEAU_TABLE 25
-#define DHO_INTERFACE_MTU 26
-#define DHO_ALL_SUBNETS_LOCAL 27
-#define DHO_BROADCAST_ADDRESS 28
-#define DHO_PERFORM_MASK_DISCOVERY 29
-#define DHO_MASK_SUPPLIER 30
-#define DHO_ROUTER_DISCOVERY 31
-#define DHO_ROUTER_SOLICITATION_ADDRESS 32
-#define DHO_STATIC_ROUTES 33
-#define DHO_TRAILER_ENCAPSULATION 34
-#define DHO_ARP_CACHE_TIMEOUT 35
-#define DHO_IEEE802_3_ENCAPSULATION 36
-#define DHO_DEFAULT_TCP_TTL 37
-#define DHO_TCP_KEEPALIVE_INTERVAL 38
-#define DHO_TCP_KEEPALIVE_GARBAGE 39
-#define DHO_NIS_DOMAIN 40
-#define DHO_NIS_SERVERS 41
-#define DHO_NTP_SERVERS 42
-#define DHO_VENDOR_ENCAPSULATED_OPTIONS 43
-#define DHO_NETBIOS_NAME_SERVERS 44
-#define DHO_NETBIOS_DD_SERVER 45
-#define DHO_NETBIOS_NODE_TYPE 46
-#define DHO_NETBIOS_SCOPE 47
-#define DHO_FONT_SERVERS 48
-#define DHO_X_DISPLAY_MANAGER 49
-#define DHO_DHCP_REQUESTED_ADDRESS 50
-#define DHO_DHCP_LEASE_TIME 51
-#define DHO_DHCP_OPTION_OVERLOAD 52
-#define DHO_DHCP_MESSAGE_TYPE 53
-#define DHO_DHCP_SERVER_IDENTIFIER 54
-#define DHO_DHCP_PARAMETER_REQUEST_LIST 55
-#define DHO_DHCP_MESSAGE 56
-#define DHO_DHCP_MAX_MESSAGE_SIZE 57
-#define DHO_DHCP_RENEWAL_TIME 58
-#define DHO_DHCP_REBINDING_TIME 59
-#define DHO_VENDOR_CLASS_IDENTIFIER 60
-#define DHO_DHCP_CLIENT_IDENTIFIER 61
-#define DHO_NWIP_DOMAIN_NAME 62
-#define DHO_NWIP_SUBOPTIONS 63
-#define DHO_USER_CLASS 77
-#define DHO_FQDN 81
-#define DHO_DHCP_AGENT_OPTIONS 82
-#define DHO_SUBNET_SELECTION 118 /* RFC3011! */
-#define DHO_DOMAIN_SEARCH 119 /* RFC3397 */
-#define DHO_VIVCO_SUBOPTIONS 124
-#define DHO_VIVSO_SUBOPTIONS 125
+#define DHO_PAD 0
+#define DHO_SUBNET_MASK 1
+#define DHO_TIME_OFFSET 2
+#define DHO_ROUTERS 3
+#define DHO_TIME_SERVERS 4
+#define DHO_NAME_SERVERS 5
+#define DHO_DOMAIN_NAME_SERVERS 6
+#define DHO_LOG_SERVERS 7
+#define DHO_COOKIE_SERVERS 8
+#define DHO_LPR_SERVERS 9
+#define DHO_IMPRESS_SERVERS 10
+#define DHO_RESOURCE_LOCATION_SERVERS 11
+#define DHO_HOST_NAME 12
+#define DHO_BOOT_SIZE 13
+#define DHO_MERIT_DUMP 14
+#define DHO_DOMAIN_NAME 15
+#define DHO_SWAP_SERVER 16
+#define DHO_ROOT_PATH 17
+#define DHO_EXTENSIONS_PATH 18
+#define DHO_IP_FORWARDING 19
+#define DHO_NON_LOCAL_SOURCE_ROUTING 20
+#define DHO_POLICY_FILTER 21
+#define DHO_MAX_DGRAM_REASSEMBLY 22
+#define DHO_DEFAULT_IP_TTL 23
+#define DHO_PATH_MTU_AGING_TIMEOUT 24
+#define DHO_PATH_MTU_PLATEAU_TABLE 25
+#define DHO_INTERFACE_MTU 26
+#define DHO_ALL_SUBNETS_LOCAL 27
+#define DHO_BROADCAST_ADDRESS 28
+#define DHO_PERFORM_MASK_DISCOVERY 29
+#define DHO_MASK_SUPPLIER 30
+#define DHO_ROUTER_DISCOVERY 31
+#define DHO_ROUTER_SOLICITATION_ADDRESS 32
+#define DHO_STATIC_ROUTES 33
+#define DHO_TRAILER_ENCAPSULATION 34
+#define DHO_ARP_CACHE_TIMEOUT 35
+#define DHO_IEEE802_3_ENCAPSULATION 36
+#define DHO_DEFAULT_TCP_TTL 37
+#define DHO_TCP_KEEPALIVE_INTERVAL 38
+#define DHO_TCP_KEEPALIVE_GARBAGE 39
+#define DHO_NIS_DOMAIN 40
+#define DHO_NIS_SERVERS 41
+#define DHO_NTP_SERVERS 42
+#define DHO_VENDOR_ENCAPSULATED_OPTIONS 43
+#define DHO_NETBIOS_NAME_SERVERS 44
+#define DHO_NETBIOS_DD_SERVER 45
+#define DHO_NETBIOS_NODE_TYPE 46
+#define DHO_NETBIOS_SCOPE 47
+#define DHO_FONT_SERVERS 48
+#define DHO_X_DISPLAY_MANAGER 49
+#define DHO_DHCP_REQUESTED_ADDRESS 50
+#define DHO_DHCP_LEASE_TIME 51
+#define DHO_DHCP_OPTION_OVERLOAD 52
+#define DHO_DHCP_MESSAGE_TYPE 53
+#define DHO_DHCP_SERVER_IDENTIFIER 54
+#define DHO_DHCP_PARAMETER_REQUEST_LIST 55
+#define DHO_DHCP_MESSAGE 56
+#define DHO_DHCP_MAX_MESSAGE_SIZE 57
+#define DHO_DHCP_RENEWAL_TIME 58
+#define DHO_DHCP_REBINDING_TIME 59
+#define DHO_VENDOR_CLASS_IDENTIFIER 60
+#define DHO_DHCP_CLIENT_IDENTIFIER 61
+#define DHO_NWIP_DOMAIN_NAME 62
+#define DHO_NWIP_SUBOPTIONS 63
+#define DHO_USER_CLASS 77
+#define DHO_FQDN 81
+#define DHO_DHCP_AGENT_OPTIONS 82
+#define DHO_CLIENT_LAST_TRANSACTION_TIME 91
+#define DHO_ASSOCIATED_IP 92
+#define DHO_SUBNET_SELECTION 118 /* RFC3011! */
+#define DHO_DOMAIN_SEARCH 119 /* RFC3397 */
+#define DHO_VIVCO_SUBOPTIONS 124
+#define DHO_VIVSO_SUBOPTIONS 125
/* The DHO_AUTHENTICATE option is not a standard yet, so I've
allocated an option out of the "local" option space for it on a
temporary basis. Once an option code number is assigned, I will
immediately and shamelessly break this, so don't count on it
continuing to work. */
-#define DHO_AUTHENTICATE 210
+#define DHO_AUTHENTICATE 210
-#define DHO_END 255
+#define DHO_END 255
/* DHCP message types. */
-#define DHCPDISCOVER 1
-#define DHCPOFFER 2
-#define DHCPREQUEST 3
-#define DHCPDECLINE 4
-#define DHCPACK 5
-#define DHCPNAK 6
-#define DHCPRELEASE 7
-#define DHCPINFORM 8
+#define DHCPDISCOVER 1
+#define DHCPOFFER 2
+#define DHCPREQUEST 3
+#define DHCPDECLINE 4
+#define DHCPACK 5
+#define DHCPNAK 6
+#define DHCPRELEASE 7
+#define DHCPINFORM 8
+#define DHCPLEASEQUERY 10
+#define DHCPLEASEUNASSIGNED 11
+#define DHCPLEASEUNKNOWN 12
+#define DHCPLEASEACTIVE 13
+
/* Relay Agent Information option subtypes: */
#define RAI_CIRCUIT_ID 1
struct lease *n_uid, *n_hw;
struct iaddr ip_addr;
- TIME starts, ends, timestamp, sort_time;
+ TIME starts, ends, sort_time;
char *client_hostname;
struct binding_scope *scope;
struct host_decl *host;
#define SV_PING_TIMEOUT 46
#define SV_RESERVE_INFINITE 47
#define SV_DDNS_CONFLICT_DETECT 48
+#define SV_LEASEQUERY 49
#if !defined (DEFAULT_PING_TIMEOUT)
# define DEFAULT_PING_TIMEOUT 1
struct dhcp_packet *, unsigned,
unsigned int, struct iaddr, struct hardware *));
+int add_option(struct option_state *options,
+ unsigned int option_num,
+ void *data,
+ unsigned int data_len);
+
/* dhcpd.c */
extern TIME cur_time;
struct shared_network *));
void parse_group_declaration PROTO ((struct parse *, struct group *));
int parse_fixed_addr_param PROTO ((struct option_cache **, struct parse *));
-TIME parse_timestamp PROTO ((struct parse *));
int parse_lease_declaration PROTO ((struct lease **, struct parse *));
void parse_address_range PROTO ((struct parse *, struct group *, int,
struct pool *, struct lease **));
void dhcprelease PROTO ((struct packet *, int));
void dhcpdecline PROTO ((struct packet *, int));
void dhcpinform PROTO ((struct packet *, int));
+void dhcpleasequery PROTO ((struct packet *, int));
void nak_lease PROTO ((struct packet *, struct iaddr *cip));
void ack_lease PROTO ((struct packet *, struct lease *,
unsigned int, TIME, char *, int, struct host_decl *));
unsigned cons_agent_information_options PROTO ((struct option_state *,
struct dhcp_packet *,
unsigned, unsigned));
+void get_server_source_address(struct in_addr *from,
+ struct option_state *options,
+ struct packet *packet);
/* bootp.c */
void bootp PROTO ((struct packet *));
void convert_ip_addr_or_hostname PROTO ((struct parse *, jrefproto, int));
void convert_fixed_addr_decl PROTO ((struct parse *, jrefproto));
void convert_option_decl PROTO ((struct parse *, jrefproto));
-void convert_timestamp PROTO ((struct parse *, jrefproto));
void convert_lease_statement PROTO ((struct parse *, jrefproto));
void convert_address_range PROTO ((struct parse *, jrefproto));
void convert_date PROTO ((struct parse *, jrefproto, char *));
MAX_LEASE_OWNERSHIP = 627,
MAX_BALANCE = 628,
MIN_BALANCE = 629,
- DOMAIN_LIST = 630
+ DOMAIN_LIST = 630,
+ LEASEQUERY = 631
};
#define is_identifier(x) ((x) >= FIRST_TOKEN && \
CATMANPAGES = dhcpd.cat8 dhcpd.conf.cat5 dhcpd.leases.cat5
SEDMANPAGES = dhcpd.man8 dhcpd.conf.man5 dhcpd.leases.man5
SRCS = dhcpd.c dhcp.c bootp.c confpars.c db.c class.c failover.c \
- omapi.c mdb.c stables.c salloc.c ddns.c
+ omapi.c mdb.c stables.c salloc.c ddns.c dhcpleasequery.c
OBJS = dhcpd.o dhcp.o bootp.o confpars.o db.o class.o failover.o \
- omapi.o mdb.o stables.o salloc.o ddns.o
+ omapi.o mdb.o stables.o salloc.o ddns.o dhcpleasequery.o
PROG = dhcpd
MAN = dhcpd.8 dhcpd.conf.5 dhcpd.leases.5
#ifndef lint
static char copyright[] =
-"$Id: confpars.c,v 1.158 2006/07/20 16:04:03 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n";
+"$Id: confpars.c,v 1.159 2006/07/25 13:26:00 shane Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
/* statement :== parameter | declaration
- parameter :== timestamp
- | DEFAULT_LEASE_TIME lease_time
+ parameter :== DEFAULT_LEASE_TIME lease_time
| MAX_LEASE_TIME lease_time
| DYNAMIC_BOOTP_LEASE_CUTOFF date
| DYNAMIC_BOOTP_LEASE_LENGTH lease_time
}
return 1;
- case TIMESTAMP:
- next_token (&val, (unsigned *)0, cfile);
- parsed_time = parse_timestamp (cfile);
- break;
-
case SHARED_NETWORK:
next_token (&val, (unsigned *)0, cfile);
if (type == SHARED_NET_DECL ||
return status;
}
-/* timestamp :== date
-
- Timestamps are actually not used in dhcpd.conf, which is a static file,
- but rather in the database file and the journal file. (Okay, actually
- they're not even used there yet). */
-
-TIME parse_timestamp (cfile)
- struct parse *cfile;
-{
- TIME rv;
-
- rv = parse_date (cfile);
- return rv;
-}
-
/* lease_declaration :== LEASE ip_address LBRACE lease_parameters RBRACE
lease_parameters :== <nil>
lease -> ends = t;
break;
- case TIMESTAMP:
- seenbit = 4;
- lease -> timestamp = t;
- break;
-
case TSTP:
seenbit = 65536;
lease -> tstp = t;
code = SV_CLIENT_UPDATES;
break;
+ case LEASEQUERY:
+ code = SV_LEASEQUERY;
+ break;
+
default:
parse_warn (cfile, "expecting allow/deny key");
skip_to_semi (cfile);
#ifndef lint
static char copyright[] =
-"$Id: dhcp.c,v 1.208 2006/07/17 15:16:43 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n";
+"$Id: dhcp.c,v 1.209 2006/07/25 13:26:00 shane Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
"DHCPACK",
"DHCPNAK",
"DHCPRELEASE",
- "DHCPINFORM"
+ "DHCPINFORM",
+ "(unknown)",
+ "DHCPLEASEQUERY",
+ "DHCPLEASEUNASSIGNED",
+ "DHCPLEASEUNKNOWN",
+ "DHCPLEASEACTIVE"
};
const int dhcp_type_name_max = ((sizeof dhcp_type_names) / sizeof (char *));
if (!locate_network (packet) &&
packet -> packet_type != DHCPREQUEST &&
- packet -> packet_type != DHCPINFORM) {
+ packet -> packet_type != DHCPINFORM &&
+ packet -> packet_type != DHCPLEASEQUERY) {
const char *s;
char typebuf [32];
errmsg = "unknown network segment";
dhcpinform (packet, ms_nulltp);
break;
+ case DHCPLEASEQUERY:
+ dhcpleasequery(packet, ms_nulltp);
+ break;
case DHCPACK:
case DHCPOFFER:
case DHCPNAK:
+ case DHCPLEASEUNASSIGNED:
+ case DHCPLEASEUNKNOWN:
+ case DHCPLEASEACTIVE:
break;
default:
packet -> raw -> hlen,
packet -> raw -> chaddr)
: (lease
- ? print_hex_1 (lease -> uid_len, lease -> uid,
- lease -> uid_len)
+ ? print_hex_1(lease->uid_len, lease->uid, 60)
: "<no identifier>")),
s ? "(" : "", s ? s : "", s ? ") " : "",
packet -> raw -> giaddr.s_addr
packet -> raw -> hlen,
packet -> raw -> chaddr)
: (lease
- ? print_hex_1 (lease -> uid_len, lease -> uid,
- lease -> uid_len)
+ ? print_hex_1(lease->uid_len, lease->uid, 60)
: "<no identifier>")),
s ? "(" : "", s ? s : "", s ? ") " : "",
packet -> raw -> giaddr.s_addr
packet -> raw -> hlen,
packet -> raw -> chaddr)
: (lease
- ? print_hex_1 (lease -> uid_len, lease -> uid,
- lease -> uid_len)
+ ? print_hex_1(lease->uid_len, lease->uid, 60)
: "<no identifier>")),
s ? "(" : "", s ? s : "", s ? ") " : "",
packet -> raw -> giaddr.s_addr
packet -> raw -> hlen,
packet -> raw -> chaddr)
: (lease
- ? print_hex_1 (lease -> uid_len, lease -> uid,
- lease -> uid_len)
+ ? print_hex_1(lease->uid_len, lease->uid, 60)
: "<no identifier>")),
s ? "(" : "", s ? s : "", s ? ") " : "",
packet -> raw -> giaddr.s_addr
option_cache_dereference (&oc, MDL);
}
- i = DHO_DHCP_SERVER_IDENTIFIER;
- if (!(oc = lookup_option (&dhcp_universe, options, i))) {
- use_primary:
- oc = (struct option_cache *)0;
- if (packet -> interface -> address_count > 0) {
- if (option_cache_allocate (&oc, MDL)) {
- if (make_const_data
- (&oc -> expression,
- ((unsigned char *)
- &packet -> interface -> addresses [0]),
- sizeof packet -> interface -> addresses [0],
- 0, 0, MDL)) {
- option_code_hash_lookup(&oc->option,
- dhcp_universe.code_hash,
- &i, 0, MDL);
- save_option (&dhcp_universe, options, oc);
- }
- option_cache_dereference (&oc, MDL);
- }
- from = packet -> interface -> addresses [0];
- }
- } else {
- if (evaluate_option_cache (&d1, packet, (struct lease *)0,
- (struct client_state *)0,
- packet -> options, options,
- &global_scope, oc, MDL)) {
- if (!d1.len || d1.len != sizeof from) {
- data_string_forget (&d1, MDL);
- goto use_primary;
- }
- memcpy (&from, d1.data, sizeof from);
- data_string_forget (&d1, MDL);
- } else
- goto use_primary;
- }
+ get_server_source_address(&from, options, packet);
/* Use the subnet mask from the subnet declaration if no other
mask has been provided. */
struct option_state *options = (struct option_state *)0;
struct expression *expr;
struct option_cache *oc = (struct option_cache *)0;
- struct iaddr myfrom;
option_state_allocate (&options, MDL);
memset (&outgoing, 0, sizeof outgoing);
save_option (&dhcp_universe, options, oc);
option_cache_dereference (&oc, MDL);
- i = DHO_DHCP_SERVER_IDENTIFIER;
- if (packet -> interface -> address_count > 0) {
- if (!(oc = lookup_option (&dhcp_universe, options, i))) {
- use_primary:
- oc = (struct option_cache *)0;
- if (option_cache_allocate (&oc, MDL)) {
- if (make_const_data
- (&oc -> expression,
- ((unsigned char *)
- &packet -> interface -> addresses [0]),
- sizeof packet -> interface -> addresses [0],
- 0, 0, MDL)) {
- option_code_hash_lookup(&oc->option,
- dhcp_universe.code_hash,
- &i, 0, MDL);
- save_option (&dhcp_universe, options, oc);
- }
- option_cache_dereference (&oc, MDL);
- }
- myfrom.len = sizeof packet -> interface -> addresses [0];
- memcpy (myfrom.iabuf,
- &packet -> interface -> addresses [0], myfrom.len);
- }
- } else {
- memset (&data, 0, sizeof data);
- if (evaluate_option_cache (&data, packet, (struct lease *)0,
- (struct client_state *)0,
- packet -> options, options,
- &global_scope, oc, MDL)) {
- if (!data.len ||
- data.len > sizeof myfrom.iabuf) {
- data_string_forget (&data, MDL);
- goto use_primary;
- }
- memcpy (myfrom.iabuf, data.data, data.len);
- myfrom.len = data.len;
- data_string_forget (&data, MDL);
- } else
- goto use_primary;
- }
+ get_server_source_address(&from, options, packet);
/* If there were agent options in the incoming packet, return
them. */
#endif
memset (to.sin_zero, 0, sizeof to.sin_zero);
- memcpy (&from, myfrom.iabuf, sizeof from);
-
/* Make sure that the packet is at least as big as a BOOTP packet. */
if (outgoing.packet_length < BOOTP_MIN_LEN)
outgoing.packet_length = BOOTP_MIN_LEN;
isc_result_t result;
int did_ping = 0;
TIME ping_timeout;
+ TIME lease_cltt;
+ struct in_addr from;
unsigned i, j;
int s1, s2;
if (lease -> state)
return;
+ /* Save original cltt for comparison later. */
+ lease_cltt = lease->cltt;
+
/* If the lease carries a host record, remember it. */
if (hp)
host_reference (&host, hp, MDL);
lt->tsfp = lease->tsfp;
lt->atsfp = lease->atsfp;
- /* Update Client Last Transaction Time. */
- lt->cltt = cur_time;
+ /* cltt set below */
/* Lease times less than MCLT are not a concern. */
if (lease_time > peer->mclt) {
lt -> next_binding_state = FTS_ACTIVE;
}
- lt -> timestamp = cur_time;
+ /* Update Client Last Transaction Time. */
+ lt->cltt = cur_time;
/* Record the uid, if given... */
oc = lookup_option (&dhcp_universe, packet -> options,
}
option_cache_dereference (&oc, MDL);
}
- i = DHO_DHCP_SERVER_IDENTIFIER;
- if (!(oc = lookup_option (&dhcp_universe,
- state -> options, i))) {
- use_primary:
- if (state -> ip -> address_count > 0) {
- oc = (struct option_cache *)0;
- if (option_cache_allocate (&oc, MDL)) {
- if (make_const_data
- (&oc -> expression,
- ((unsigned char *)
- &state -> ip -> addresses [0]),
- sizeof state -> ip -> addresses [0],
- 0, 0, MDL)) {
- option_code_hash_lookup(&oc->option,
- dhcp_universe.code_hash,
- &i, 0, MDL);
- save_option (&dhcp_universe,
- state -> options, oc);
- }
- option_cache_dereference (&oc, MDL);
- }
- state -> from.len =
- sizeof state -> ip -> addresses [0];
- memcpy (state -> from.iabuf,
- &state -> ip -> addresses [0],
- state -> from.len);
- }
- } else {
- if (evaluate_option_cache (&d1, packet, lease,
- (struct client_state *)0,
- packet -> options,
- state -> options,
- &lease -> scope, oc, MDL)) {
- if (!d1.len ||
- d1.len > sizeof state -> from.iabuf) {
- data_string_forget (&d1, MDL);
- goto use_primary;
- }
- memcpy (state -> from.iabuf, d1.data, d1.len);
- state -> from.len = d1.len;
- data_string_forget (&d1, MDL);
- } else
- goto use_primary;
- }
+
+ get_server_source_address(&from, state->options, packet);
+ memcpy(state->from.iabuf, &from, sizeof(from));
+ state->from.len = sizeof(from);
offered_lease_time =
state -> offered_expiry - cur_time;
option_cache_dereference (&oc, MDL);
}
} else {
+ /* XXXSK: should we use get_server_source_address() here? */
if (state -> ip -> address_count) {
state -> from.len =
sizeof state -> ip -> addresses [0];
/* If this is a DHCPOFFER, ping the lease address before actually
sending the offer. */
if (offer == DHCPOFFER && !(lease -> flags & STATIC_LEASE) &&
- cur_time - lease -> timestamp > 60 &&
+ ((cur_time - lease_cltt) > 60) &&
(!(oc = lookup_option (&server_universe, state -> options,
SV_PING_CHECKS)) ||
evaluate_boolean_option_cache (&ignorep, packet, lease,
packet -> options,
state -> options,
&lease -> scope, oc, MDL))) {
- lease -> timestamp = cur_time;
icmp_echorequest (&lease -> ip_addr);
/* Determine whether to use configured or default ping timeout.
(tvunref_t)lease_dereference);
++outstanding_pings;
} else {
- lease -> timestamp = cur_time;
- dhcp_reply (lease);
+ lease->cltt = cur_time;
+ dhcp_reply(lease);
}
}
? print_hw_addr (lease -> hardware_addr.hbuf [0],
lease -> hardware_addr.hlen - 1,
&lease -> hardware_addr.hbuf [1])
- : print_hex_1 (lease -> uid_len, lease -> uid,
- lease -> uid_len)),
+ : print_hex_1(lease->uid_len, lease->uid, 60)),
s ? "(" : "", s ? s : "", s ? ") " : "",
(state -> giaddr.s_addr
? inet_ntoa (state -> giaddr)
rhp -> client_identifier.len);
lease -> uid_len = rhp -> client_identifier.len;
lease -> hardware_addr = rhp -> interface;
- lease -> starts = lease -> timestamp = lease -> ends = MIN_TIME;
+ lease -> starts = lease -> cltt = lease -> ends = MIN_TIME;
lease -> flags = STATIC_LEASE;
lease -> binding_state = FTS_FREE;
/* Otherwise, fail. */
return 0;
}
+
+/*
+ * Try to figure out the source address to send packets from.
+ *
+ * If the packet we received specified the server address, then we
+ * will use that.
+ *
+ * Otherwise, use the first address from the interface. If we do
+ * this, we also save this into the option cache as the server
+ * address.
+ */
+void
+get_server_source_address(struct in_addr *from,
+ struct option_state *options,
+ struct packet *packet) {
+ int option_num;
+ struct option_cache *oc;
+ struct data_string d;
+ struct in_addr *a;
+ struct option *option;
+
+ option_num = DHO_DHCP_SERVER_IDENTIFIER;
+ oc = lookup_option(&dhcp_universe, options, option_num);
+ if ((oc != NULL) &&
+ evaluate_option_cache(&d, packet, NULL, NULL, packet->options,
+ options, &global_scope, oc, MDL)) {
+ if (d.len == sizeof(*from)) {
+ memcpy(from, d.data, sizeof(*from));
+ data_string_forget(&d, MDL);
+ return;
+ }
+ data_string_forget(&d, MDL);
+ }
+
+ if (packet->interface->address_count > 0) {
+ if (option_cache_allocate(&oc, MDL)) {
+ a = &packet->interface->addresses[0];
+ if (make_const_data(&oc->expression,
+ (char *)a, sizeof(*a),
+ 0, 0, MDL)) {
+ option_code_hash_lookup(&oc->option,
+ dhcp_universe.code_hash,
+ &option_num, 0, MDL);
+ save_option(&dhcp_universe, options, oc);
+ }
+ option_cache_dereference(&oc, MDL);
+ }
+ *from = packet->interface->addresses[0];
+ } else {
+ memset(from, 0, sizeof(*from));
+ }
+}
+
.\" see ``http://www.vix.com''. To learn more about Nominum, Inc., see
.\" ``http://www.nominum.com''.
.\"
-.\" $Id: dhcpd.conf.5,v 1.77 2006/07/19 20:13:57 dhankins Exp $
+.\" $Id: dhcpd.conf.5,v 1.78 2006/07/25 13:26:00 shane Exp $
.\"
.TH dhcpd.conf 5
.SH NAME
This is only relevant when doing \fIinterim\fR DNS updates. See the
documentation under the heading THE INTERIM DNS UPDATE SCHEME for
details.
+.PP
+.B The
+.I leasequery
+.B keyword
+.PP
+ \fBallow leasequery;\fR
+ \fBdeny leasequery;\fR
+.PP
+The \fBleasequery\fR flag tells the DHCP server whether or not to
+answer DHCPLEASEQUERY packets. The answer to a DHCPLEASEQUERY packet
+includes information about a specific lease, such as when it was
+issued and when it will expire. By default, the server will not
+respond to these packets.
.SH ALLOW AND DENY WITHIN POOL DECLARATIONS
.PP
The uses of the allow and deny keywords shown in the previous section
--- /dev/null
+/*
+ * Copyright (C) 2006 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "dhcpd.h"
+
+/*
+ * TODO: RFC4388 specifies that the server SHOULD store the
+ * vendor-class-id.
+ *
+ * TODO: RFC4388 specifies that the server SHOULD return the same
+ * options it would for a DHCREQUEST message, if no Parameter
+ * Request List option (option 55) is passed. We do not do that.
+ *
+ * TODO: RFC4388 specifies the creation of a "non-sensitive options"
+ * configuration list, and that these SHOULD be returned. We
+ * have no such list.
+ *
+ * TODO: RFC4388 says the server SHOULD use RFC3118, "Authentication
+ * for DHCP Messages".
+ *
+ * TODO: RFC4388 specifies that you SHOULD insure that you cannot be
+ * DoS'ed by DHCPLEASEQUERY message.
+ */
+
+/*
+ * If you query by hardware address or by client ID, then you may have
+ * more than one IP address for your query argument. We need to do two
+ * things:
+ *
+ * 1. Find the most recent lease.
+ * 2. Find all additional IP addresses for the query argument.
+ *
+ * We do this by looking through all of the leases associated with a
+ * given hardware address or client ID. We use the cltt (client last
+ * transaction time) of the lease, which only has a resolution of one
+ * second, so we might not actually give the very latest IP.
+ */
+
+static struct lease*
+next_hw(const struct lease *lease) {
+ /* INSIST(lease != NULL); */
+ return lease->n_hw;
+}
+
+static struct lease*
+next_uid(const struct lease *lease) {
+ /* INSIST(lease != NULL); */
+ return lease->n_uid;
+}
+
+void
+get_newest_lease(struct lease **retval,
+ struct lease *lease,
+ struct lease *(*next)(const struct lease *)) {
+
+ struct lease *p;
+ struct lease *newest;
+
+ /* INSIST(newest != NULL); */
+ /* INSIST(next != NULL); */
+
+ *retval = NULL;
+
+ if (lease == NULL) {
+ return;
+ }
+
+ newest = lease;
+ for (p=next(lease); p != NULL; p=next(p)) {
+ if (newest->binding_state == FTS_ACTIVE) {
+ if ((p->binding_state == FTS_ACTIVE) &&
+ (p->cltt > newest->cltt)) {
+ newest = p;
+ }
+ } else {
+ if (p->ends > newest->ends) {
+ newest = p;
+ }
+ }
+ }
+
+ lease_reference(retval, newest, MDL);
+}
+
+static int
+get_associated_ips(const struct lease *lease,
+ struct lease *(*next)(const struct lease *),
+ const struct lease *newest,
+ u_int32_t *associated_ips,
+ unsigned int associated_ips_size) {
+
+ const struct lease *p;
+ int cnt;
+
+ /* INSIST(next != NULL); */
+ /* INSIST(associated_ips != NULL); */
+
+ if (lease == NULL) {
+ return 0;
+ }
+
+ cnt = 0;
+ for (p=lease; p != NULL; p=next(p)) {
+ if ((p->binding_state == FTS_ACTIVE) && (p != newest)) {
+ if (cnt < associated_ips_size) {
+ memcpy(&associated_ips[cnt],
+ p->ip_addr.iabuf,
+ sizeof(associated_ips[cnt]));
+ }
+ cnt++;
+ }
+ }
+ return cnt;
+}
+
+
+void
+dhcpleasequery(struct packet *packet, int ms_nulltp) {
+ char msgbuf[256];
+ char dbg_info[128];
+ struct iaddr cip;
+ struct iaddr gip;
+ struct data_string uid;
+ struct hardware h;
+ struct lease *tmp_lease;
+ struct lease *lease;
+ int want_associated_ip;
+ int assoc_ip_cnt;
+ u_int32_t assoc_ips[40]; /* XXXSK: arbritrary maximum number of IPs */
+ const int nassoc_ips = sizeof(assoc_ips) / sizeof(assoc_ips[0]);
+
+ unsigned char dhcpMsgType;
+ const char *dhcp_msg_type_name;
+ struct subnet *subnet;
+ struct option_state *options;
+ struct option_cache *oc;
+ int allow_leasequery;
+ int ignorep;
+ u_int32_t lease_duration;
+ u_int32_t time_renewal;
+ u_int32_t time_rebinding;
+ u_int32_t time_expiry;
+ u_int32_t client_last_transaction_time;
+ struct sockaddr_in to;
+ struct in_addr siaddr;
+ struct data_string prl;
+ struct data_string *prl_ptr;
+
+ int i;
+ struct interface_info *interface;
+
+ /* INSIST(packet != NULL); */
+
+ /*
+ * Prepare log information.
+ */
+ snprintf(msgbuf, sizeof(msgbuf),
+ "DHCPLEASEQUERY from %s", inet_ntoa(packet->raw->giaddr));
+
+ /*
+ * We can't reply if there is no giaddr field.
+ */
+ if (!packet->raw->giaddr.s_addr) {
+ log_info("%s: missing giaddr, ciaddr is %s, no reply sent",
+ msgbuf, inet_ntoa(packet->raw->ciaddr));
+ return;
+ }
+
+ /*
+ * Set up our options, scope, and, um... stuff.
+ * This is basically copied from dhcpinform() in dhcp.c.
+ */
+ gip.len = sizeof(packet->raw->giaddr);
+ memcpy(gip.iabuf, &packet->raw->giaddr, sizeof(packet->raw->giaddr));
+
+ subnet = NULL;
+ find_subnet(&subnet, gip, MDL);
+ if (subnet == NULL) {
+ log_info("%s: unknown subnet for address %s",
+ msgbuf, piaddr(gip));
+ return;
+ }
+
+ options = NULL;
+ if (!option_state_allocate(&options, MDL)) {
+ subnet_dereference(&subnet, MDL);
+ log_error("No memory for option state.");
+ log_info("%s: out of memory, no reply sent", msgbuf);
+ return;
+ }
+
+ execute_statements_in_scope(NULL,
+ packet,
+ NULL,
+ NULL,
+ packet->options,
+ options,
+ &global_scope,
+ subnet->group,
+ NULL);
+ for (i=packet->class_count-1; i>=0; i--) {
+ execute_statements_in_scope(NULL,
+ packet,
+ NULL,
+ NULL,
+ packet->options,
+ options,
+ &global_scope,
+ packet->classes[i]->group,
+ subnet->group);
+ }
+
+ subnet_dereference(&subnet, MDL);
+
+ /*
+ * Because LEASEQUERY has some privacy concerns, default to deny.
+ */
+ allow_leasequery = 0;
+
+ /*
+ * See if we are authorised to do LEASEQUERY.
+ */
+ oc = lookup_option(&server_universe, options, SV_LEASEQUERY);
+ if (oc != NULL) {
+ allow_leasequery = evaluate_boolean_option_cache(&ignorep,
+ packet, NULL, NULL, packet->options,
+ options, &global_scope, oc, MDL);
+ }
+
+ if (!allow_leasequery) {
+ log_info("%s: LEASEQUERY not allowed, query ignored", msgbuf);
+ option_state_dereference(&options, MDL);
+ return;
+ }
+
+
+ /*
+ * Copy out the client IP address.
+ */
+ cip.len = sizeof(packet->raw->ciaddr);
+ memcpy(cip.iabuf, &packet->raw->ciaddr, sizeof(packet->raw->ciaddr));
+
+ /*
+ * If the client IP address is valid (not all zero), then we
+ * are looking for information about that IP address.
+ */
+ assoc_ip_cnt = 0;
+ if (memcmp(cip.iabuf, "\0\0\0", 4)) {
+
+ want_associated_ip = 0;
+
+ snprintf(dbg_info, sizeof(dbg_info), "IP %s", piaddr(cip));
+ find_lease_by_ip_addr(&lease, cip, MDL);
+
+
+ } else {
+
+ want_associated_ip = 1;
+
+ /*
+ * If the client IP address is all zero, then we will
+ * either look up by the client identifier (if we have
+ * one), or by the MAC address.
+ */
+
+ memset(&uid, 0, sizeof(uid));
+ if (get_option(&uid,
+ &dhcp_universe,
+ packet,
+ NULL,
+ NULL,
+ packet->options,
+ NULL,
+ packet->options,
+ &global_scope,
+ DHO_DHCP_CLIENT_IDENTIFIER,
+ MDL)) {
+
+ snprintf(dbg_info,
+ sizeof(dbg_info),
+ "client-id %s",
+ print_hex_1(uid.len, uid.data, 60));
+
+ find_lease_by_uid(&tmp_lease, uid.data, uid.len, MDL);
+ data_string_forget(&uid, MDL);
+ get_newest_lease(&lease, tmp_lease, next_uid);
+ assoc_ip_cnt = get_associated_ips(tmp_lease,
+ next_uid,
+ lease,
+ assoc_ips,
+ nassoc_ips);
+
+ } else {
+
+ if (packet->raw->hlen+1 > sizeof(h.hbuf)) {
+ log_info("%s: hardware length too long, "
+ "no reply sent", msgbuf);
+ option_state_dereference(&options, MDL);
+ return;
+ }
+
+ h.hlen = packet->raw->hlen + 1;
+ h.hbuf[0] = packet->raw->htype;
+ memcpy(&h.hbuf[1],
+ packet->raw->chaddr,
+ packet->raw->hlen);
+
+ snprintf(dbg_info,
+ sizeof(dbg_info),
+ "MAC address %s",
+ print_hw_addr(h.hbuf[0],
+ h.hlen - 1,
+ &h.hbuf[1]));
+
+ find_lease_by_hw_addr(&tmp_lease, h.hbuf, h.hlen, MDL);
+ get_newest_lease(&lease, tmp_lease, next_hw);
+ assoc_ip_cnt = get_associated_ips(tmp_lease,
+ next_hw,
+ lease,
+ assoc_ips,
+ nassoc_ips);
+
+ }
+
+ lease_dereference(&tmp_lease, MDL);
+
+ if (lease != NULL) {
+ memcpy(&packet->raw->ciaddr,
+ lease->ip_addr.iabuf,
+ sizeof(packet->raw->ciaddr));
+ }
+
+ /*
+ * Log if we have too many IP addresses associated
+ * with this client.
+ */
+ if (want_associated_ip && (assoc_ip_cnt > nassoc_ips)) {
+ log_info("%d IP addresses associated with %s, "
+ "only %d sent in reply.",
+ assoc_ip_cnt, dbg_info, nassoc_ips);
+ }
+ }
+
+ /*
+ * We now know the query target too, so can report this in
+ * our log message.
+ */
+ snprintf(msgbuf, sizeof(msgbuf),
+ "DHCPLEASEQUERY from %s for %s",
+ inet_ntoa(packet->raw->giaddr), dbg_info);
+
+ /*
+ * Figure our our return type.
+ */
+ if (lease == NULL) {
+ dhcpMsgType = DHCPLEASEUNKNOWN;
+ dhcp_msg_type_name = "DHCPLEASEUNKNOWN";
+ } else {
+ if (lease->binding_state == FTS_ACTIVE) {
+ dhcpMsgType = DHCPLEASEACTIVE;
+ dhcp_msg_type_name = "DHCPLEASEACTIVE";
+ } else {
+ dhcpMsgType = DHCPLEASEUNASSIGNED;
+ dhcp_msg_type_name = "DHCPLEASEUNASSIGNED";
+ }
+ }
+
+ /*
+ * Set options that only make sense if we have an active lease.
+ */
+
+ if (dhcpMsgType == DHCPLEASEACTIVE)
+ {
+
+ /*
+ * Set the hardware address fields.
+ */
+
+ packet->raw->hlen = lease->hardware_addr.hlen - 1;
+ packet->raw->htype = lease->hardware_addr.hbuf[0];
+ memcpy(packet->raw->chaddr,
+ &lease->hardware_addr.hbuf[1],
+ sizeof(packet->raw->chaddr));
+
+ /*
+ * Set client identifier option.
+ */
+ if (lease->uid_len > 0) {
+ if (!add_option(options,
+ DHO_DHCP_CLIENT_IDENTIFIER,
+ lease->uid,
+ lease->uid_len)) {
+ option_state_dereference(&options, MDL);
+ lease_dereference(&lease, MDL);
+ log_info("%s: out of memory, no reply sent",
+ msgbuf);
+ return;
+ }
+ }
+
+
+ /*
+ * Calculate T1 and T2, the times when the client
+ * tries to extend its lease on its networking
+ * address.
+ * These seem to be hard-coded in ISC DHCP, to 0.5 and
+ * 0.875 of the lease time.
+ */
+
+ lease_duration = lease->ends - lease->starts;
+ time_renewal = lease->starts +
+ (lease_duration / 2);
+ time_rebinding = lease->starts +
+ (lease_duration / 2) +
+ (lease_duration / 4) +
+ (lease_duration / 8);
+
+ if (time_renewal > cur_time) {
+ time_renewal = htonl(time_renewal - cur_time);
+ if (!add_option(options,
+ DHO_DHCP_RENEWAL_TIME,
+ &time_renewal,
+ sizeof(time_renewal))) {
+ option_state_dereference(&options, MDL);
+ lease_dereference(&lease, MDL);
+ log_info("%s: out of memory, no reply sent",
+ msgbuf);
+ return;
+ }
+ }
+
+ if (time_rebinding > cur_time) {
+ time_rebinding = htonl(time_rebinding - cur_time);
+ if (!add_option(options,
+ DHO_DHCP_REBINDING_TIME,
+ &time_rebinding,
+ sizeof(time_rebinding))) {
+ option_state_dereference(&options, MDL);
+ lease_dereference(&lease, MDL);
+ log_info("%s: out of memory, no reply sent",
+ msgbuf);
+ return;
+ }
+ }
+
+ if (lease->ends > cur_time) {
+ time_expiry = htonl(lease->ends - cur_time);
+ if (!add_option(options,
+ DHO_DHCP_LEASE_TIME,
+ &time_expiry,
+ sizeof(time_expiry))) {
+ option_state_dereference(&options, MDL);
+ lease_dereference(&lease, MDL);
+ log_info("%s: out of memory, no reply sent",
+ msgbuf);
+ return;
+ }
+ }
+
+
+ /*
+ * Set the relay agent info.
+ */
+
+ if (lease->agent_options != NULL) {
+ int idx = agent_universe.index;
+ struct option_chain_head **tmp1 =
+ (struct option_chain_head **)
+ &(options->universes[idx]);
+ struct option_chain_head *tmp2 =
+ (struct option_chain_head *)
+ lease->agent_options;
+
+ option_chain_head_reference(tmp1, tmp2, MDL);
+ }
+
+ /*
+ * Set the client last transaction time.
+ * We check to make sure we have a timestamp. For
+ * lease files that were saved before running a
+ * timestamp-aware version of the server, this may
+ * not be set.
+ */
+
+ if (lease->cltt != MIN_TIME) {
+ if (cur_time > lease->cltt) {
+ client_last_transaction_time =
+ htonl(cur_time - lease->cltt);
+ } else {
+ client_last_transaction_time = htonl(0);
+ }
+ if (!add_option(options,
+ DHO_CLIENT_LAST_TRANSACTION_TIME,
+ &client_last_transaction_time,
+ sizeof(client_last_transaction_time))) {
+ option_state_dereference(&options, MDL);
+ lease_dereference(&lease, MDL);
+ log_info("%s: out of memory, no reply sent",
+ msgbuf);
+ return;
+ }
+ }
+
+ /*
+ * Set associated IPs, if requested and there are some.
+ */
+ if (want_associated_ip && (assoc_ip_cnt > 0)) {
+ if (!add_option(options,
+ DHO_ASSOCIATED_IP,
+ assoc_ips,
+ assoc_ip_cnt * sizeof(assoc_ips[0]))) {
+ option_state_dereference(&options, MDL);
+ lease_dereference(&lease, MDL);
+ log_info("%s: out of memory, no reply sent",
+ msgbuf);
+ return;
+ }
+ }
+ }
+
+ /*
+ * Set the message type.
+ */
+
+ packet->raw->op = BOOTREPLY;
+
+ /*
+ * Set DHCP message type.
+ */
+ if (!add_option(options,
+ DHO_DHCP_MESSAGE_TYPE,
+ &dhcpMsgType,
+ sizeof(dhcpMsgType))) {
+ option_state_dereference(&options, MDL);
+ lease_dereference(&lease, MDL);
+ log_info("%s: error adding option, no reply sent", msgbuf);
+ return;
+ }
+
+ /*
+ * Log the message we've received.
+ */
+ log_info("%s", msgbuf);
+
+ /*
+ * Figure out which address to use to send from.
+ */
+ get_server_source_address(&siaddr, options, packet);
+
+ /*
+ * Set up the option buffer.
+ */
+
+ memset(&prl, 0, sizeof(prl));
+ oc = lookup_option(&dhcp_universe, options,
+ DHO_DHCP_PARAMETER_REQUEST_LIST);
+ if (oc != NULL) {
+ evaluate_option_cache(&prl,
+ packet,
+ NULL,
+ NULL,
+ packet->options,
+ options,
+ &global_scope,
+ oc,
+ MDL);
+ }
+ if (prl.len > 0) {
+ prl_ptr = &prl;
+ } else {
+ prl_ptr = NULL;
+ }
+
+ packet->packet_length = cons_options(packet,
+ packet->raw,
+ lease,
+ NULL,
+ 0,
+ packet->options,
+ options,
+ &global_scope,
+ 0,
+ 0,
+ 0,
+ prl_ptr,
+ NULL);
+
+ data_string_forget(&prl, MDL); /* SK: safe, even if empty */
+ option_state_dereference(&options, MDL);
+ lease_dereference(&lease, MDL);
+
+ to.sin_family = AF_INET;
+#ifdef HAVE_SA_LEN
+ to.sin_len = sizeof(to);
+#endif
+ memset(to.sin_zero, 0, sizeof(to.sin_zero));
+
+ /*
+ * Leasequery packets are be sent to the gateway address.
+ */
+ to.sin_addr = packet->raw->giaddr;
+ if (packet->raw->giaddr.s_addr != htonl(INADDR_LOOPBACK)) {
+ to.sin_port = local_port;
+ } else {
+ to.sin_port = remote_port; /* XXXSK: For debugging. */
+ }
+
+ /*
+ * The fallback_interface lets us send with a real IP
+ * address. The packet interface sends from all-zeros.
+ */
+ if (fallback_interface != NULL) {
+ interface = fallback_interface;
+ } else {
+ interface = packet->interface;
+ }
+
+ /*
+ * Report what we're sending.
+ */
+ log_info("%s to %s for %s (%d associated IPs)",
+ dhcp_msg_type_name,
+ inet_ntoa(to.sin_addr), dbg_info, assoc_ip_cnt);
+
+ send_packet(interface,
+ NULL,
+ packet->raw,
+ packet->packet_length,
+ siaddr,
+ &to,
+ NULL);
+}
+
#ifndef lint
static char copyright[] =
-"$Id: mdb.c,v 1.82 2006/07/18 18:15:53 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n";
+"$Id: mdb.c,v 1.83 2006/07/25 13:26:00 shane Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
#endif
lp -> ip_addr = ip_addr (subnet -> net,
subnet -> netmask, i + min);
- lp -> starts = lp -> timestamp = MIN_TIME;
+ lp -> starts = MIN_TIME;
lp -> ends = MIN_TIME;
subnet_reference (&lp -> subnet, subnet, MDL);
pool_reference (&lp -> pool, pool, MDL);
hw_hash_add (comp);
}
-#if defined (FAILOVER_PROTOCOL)
comp->cltt = lease->cltt;
+#if defined (FAILOVER_PROTOCOL)
comp->tstp = lease->tstp;
comp->tsfp = lease->tsfp;
comp->atsfp = lease->atsfp;
lt -> ip_addr = lease -> ip_addr;
lt -> starts = lease -> starts;
lt -> ends = lease -> ends;
- lt -> timestamp = lease -> timestamp;
lt -> uid_len = lease -> uid_len;
lt -> uid_max = lease -> uid_max;
if (lease -> uid == lease -> uid_buf) {