diff --git a/RELNOTES b/RELNOTES index 59675213..2b8e10bc 100644 --- a/RELNOTES +++ b/RELNOTES @@ -122,6 +122,12 @@ and for prodding me into improving it. - The DHCP Relay Agent Information Option / Link Selection Sub-Option is now supported. (See RFC3527 for details). +- A new DDNS related server option, update-conflict-detection, has been + added. If this option is enabled, dhcpd will perform normal DHCID + conflict resolution (the default). If this option is disabled, it will + instead trust the assigned name implicitly (removing any other bindings + on that name). This option has not been made available in dhclient. + Changes since 3.0.4 - A warning that host statements declared within subnet or shared-network diff --git a/client/dhclient.c b/client/dhclient.c index fff2f3e1..53ac8317 100644 --- a/client/dhclient.c +++ b/client/dhclient.c @@ -32,7 +32,7 @@ #ifndef lint static char ocopyright[] = -"$Id: dhclient.c,v 1.141 2006/07/09 15:39:48 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n"; +"$Id: dhclient.c,v 1.142 2006/07/19 17:14:55 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" @@ -3178,7 +3178,7 @@ isc_result_t client_dns_update (struct client_state *client, int addp, int ttl) rcode = ddns_update_a (&ddns_fwd_name, client -> active -> address, &ddns_dhcid, ttl, - 1); + 1, 1); else rcode = ddns_remove_a (&ddns_fwd_name, client -> active -> address, diff --git a/common/dns.c b/common/dns.c index 97804ec5..44efb7ee 100644 --- a/common/dns.c +++ b/common/dns.c @@ -33,7 +33,7 @@ #ifndef lint static char copyright[] = -"$Id: dns.c,v 1.39 2006/06/01 20:23:17 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n"; +"$Id: dns.c,v 1.40 2006/07/19 17:14:55 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" @@ -518,10 +518,10 @@ int get_dhcid (struct data_string *id, /* Now for the DDNS update code that is shared between client and server... */ -isc_result_t ddns_update_a (struct data_string *ddns_fwd_name, - struct iaddr ddns_addr, - struct data_string *ddns_dhcid, - unsigned long ttl, int rrsetp) +isc_result_t +ddns_update_a(struct data_string *ddns_fwd_name, struct iaddr ddns_addr, + struct data_string *ddns_dhcid, unsigned long ttl, + unsigned rrsetp, unsigned conflict) { ns_updque updqueue; ns_updrec *updrec; @@ -654,23 +654,45 @@ isc_result_t ddns_update_a (struct data_string *ddns_fwd_name, minires_freeupdrec (updrec); } - /* - * DHCID RR exists, and matches client identity. + /* If we're doing conflict resolution, we use a set of prereqs. If + * not, we delete the DHCID in addition to all A rrsets. */ - updrec = minires_mkupdrec (S_PREREQ, - (const char *)ddns_fwd_name -> data, - C_IN, T_DHCID, 0); - if (!updrec) { - result = ISC_R_NOMEMORY; - goto error; + if (conflict) { + /* + * DHCID RR exists, and matches client identity. + */ + updrec = minires_mkupdrec (S_PREREQ, + (const char *)ddns_fwd_name -> data, + C_IN, T_DHCID, 0); + if (!updrec) { + result = ISC_R_NOMEMORY; + goto error; + } + + updrec -> r_data = ddns_dhcid -> data; + updrec -> r_size = ddns_dhcid -> len; + updrec -> r_opcode = YXRRSET; + + ISC_LIST_APPEND (updqueue, updrec, r_link); + } else { + /* + * Conflict detection override: delete DHCID RRs. + */ + updrec = minires_mkupdrec(S_UPDATE, ddns_fwd_name->data, + C_IN, T_DHCID, 0); + + if (!updrec) { + result = ISC_R_NOMEMORY; + goto error; + } + + updrec->r_data = NULL; + updrec->r_size = 0; + updrec->r_opcode = DELETE; + + ISC_LIST_APPEND(updqueue, updrec, r_link); } - updrec -> r_data = ddns_dhcid -> data; - updrec -> r_size = ddns_dhcid -> len; - updrec -> r_opcode = YXRRSET; - - ISC_LIST_APPEND (updqueue, updrec, r_link); - /* * Delete A RRset. diff --git a/includes/dhcpd.h b/includes/dhcpd.h index 4735be73..a0cc560b 100644 --- a/includes/dhcpd.h +++ b/includes/dhcpd.h @@ -510,6 +510,7 @@ struct lease_state { #define SV_DO_FORWARD_UPDATES 45 #define SV_PING_TIMEOUT 46 #define SV_RESERVE_INFINITE 47 +#define SV_DDNS_CONFLICT_DETECT 48 #if !defined (DEFAULT_PING_TIMEOUT) # define DEFAULT_PING_TIMEOUT 1 @@ -2186,8 +2187,9 @@ void forget_zone (struct dns_zone **); void repudiate_zone (struct dns_zone **); void cache_found_zone (ns_class, char *, struct in_addr *, int); int get_dhcid (struct data_string *, int, const u_int8_t *, unsigned); -isc_result_t ddns_update_a (struct data_string *, struct iaddr, - struct data_string *, unsigned long, int); +isc_result_t ddns_update_a(struct data_string *, struct iaddr, + struct data_string *, unsigned long, unsigned, + unsigned); isc_result_t ddns_remove_a (struct data_string *, struct iaddr, struct data_string *); #endif /* NSUPDATE */ diff --git a/server/ddns.c b/server/ddns.c index b2811324..483d9a3f 100644 --- a/server/ddns.c +++ b/server/ddns.c @@ -34,7 +34,7 @@ #ifndef lint static char copyright[] = -"$Id: ddns.c,v 1.19 2006/06/01 20:23:17 dhankins Exp $ Copyright (c) 2004-2005 Internet Systems Consortium. All rights reserved.\n"; +"$Id: ddns.c,v 1.20 2006/07/19 17:14:55 dhankins Exp $ Copyright (c) 2004-2005 Internet Systems Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" @@ -548,9 +548,23 @@ int ddns_updates (struct packet *packet, /* * Perform updates. */ - if (ddns_fwd_name.len && ddns_dhcid.len) + if (ddns_fwd_name.len && ddns_dhcid.len) { + unsigned conflict; + + oc = lookup_option(&server_universe, state->options, + SV_DDNS_CONFLICT_DETECT); + if (!oc || + evaluate_boolean_option_cache(&ignorep, packet, lease, + NULL, packet->options, + state->options, + &lease->scope, oc, MDL)) + conflict = 1; + else + conflict = 0; + rcode1 = ddns_update_a (&ddns_fwd_name, lease -> ip_addr, - &ddns_dhcid, ddns_ttl, 0); + &ddns_dhcid, ddns_ttl, 0, conflict); + } if (rcode1 == ISC_R_SUCCESS) { if (ddns_fwd_name.len && ddns_rev_name.len) diff --git a/server/dhcpd.conf.5 b/server/dhcpd.conf.5 index 2119a600..820f96bf 100644 --- a/server/dhcpd.conf.5 +++ b/server/dhcpd.conf.5 @@ -28,7 +28,7 @@ .\" see ``http://www.vix.com''. To learn more about Nominum, Inc., see .\" ``http://www.nominum.com''. .\" -.\" $Id: dhcpd.conf.5,v 1.75 2006/07/09 15:01:19 dhankins Exp $ +.\" $Id: dhcpd.conf.5,v 1.76 2006/07/19 17:14:55 dhankins Exp $ .\" .TH dhcpd.conf 5 .SH NAME @@ -2400,6 +2400,19 @@ directly to the server and not sent through a relay agent. .RE .PP The +.I update-conflict-detection +statement +.RS 0.25i +.PP +.B update-conflict-detection \fIflag\fB;\fR +.PP +If the \fIupdate-conflict-detection\fR parameter is true, the server will +perform standard DHCID multiple-client, one-name conflict detection. If +the parameter has been set false, the server will skip this check and +instead simply tear down any previous bindings to install the new +binding without question. The default is true. +.PP +The .I update-optimization statement .RS 0.25i diff --git a/server/stables.c b/server/stables.c index 7c7df5ca..4bfbaf25 100644 --- a/server/stables.c +++ b/server/stables.c @@ -34,7 +34,7 @@ #ifndef lint static char copyright[] = -"$Id: stables.c,v 1.31 2006/07/17 15:16:43 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; +"$Id: stables.c,v 1.32 2006/07/19 17:14:55 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" @@ -233,6 +233,7 @@ static struct option server_options[] = { { "do-forward-updates", "f", &server_universe, 45, 1 }, { "ping-timeout", "T", &server_universe, 46, 1 }, { "infinite-is-reserved", "f", &server_universe, 47, 1 }, + { "update-conflict-detection", "f", &server_universe, 48, 1 }, { NULL, NULL, NULL, 0, 0 } };