⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ddns.c

📁 DHCP服务器源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* ddns.c   Dynamic DNS updates. *//* * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") * Copyright (c) 2000-2003 by Internet Software Consortium * * 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. * *   Internet Systems Consortium, Inc. *   950 Charter Street *   Redwood City, CA 94063 *   <info@isc.org> *   http://www.isc.org/ * * This software has been donated to Internet Systems Consortium * by Damien Neil of Nominum, Inc. * * To learn more about Internet Systems Consortium, see * ``http://www.isc.org/''.   To learn more about Nominum, Inc., see * ``http://www.nominum.com''. */#ifndef lintstatic char copyright[] ="$Id: ddns.c,v 1.15.2.14 2004/06/17 20:54:40 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium.  All rights reserved.\n";#endif /* not lint */#include "dhcpd.h"#include "dst/md5.h"#include "minires/minires.h"#ifdef NSUPDATE/* DN: No way of checking that there is enough space in a data_string's   buffer.  Be certain to allocate enough!   TL: This is why the expression evaluation code allocates a *new*   data_string.   :') */static void data_string_append (struct data_string *ds1,				struct data_string *ds2){	memcpy (ds1 -> buffer -> data + ds1 -> len,		ds2 -> data,		ds2 -> len);	ds1 -> len += ds2 -> len;}static isc_result_t ddns_update_ptr (struct data_string *ddns_fwd_name,				     struct data_string *ddns_rev_name,				     unsigned long ttl){	ns_updque updqueue;	ns_updrec *updrec;	isc_result_t result = ISC_R_UNEXPECTED;	/*	 * The DHCP server submits a DNS query which deletes all of the PTR RRs	 * associated with the lease IP address, and adds a PTR RR whose data	 * is the client's (possibly disambiguated) host name. The server also	 * adds a DHCID RR specified in Section 4.3.	 *   -- "Interaction between DHCP and DNS"	 */	ISC_LIST_INIT (updqueue);	/*	 * Delete all PTR RRs.	 */	updrec = minires_mkupdrec (S_UPDATE,				   (const char *)ddns_rev_name -> data,				   C_IN, T_PTR, 0);	if (!updrec) {		result = ISC_R_NOMEMORY;		goto error;	}	updrec -> r_data = (unsigned char *)0;	updrec -> r_size = 0;	updrec -> r_opcode = DELETE;	ISC_LIST_APPEND (updqueue, updrec, r_link);	/*	 * Add PTR RR.	 */	updrec = minires_mkupdrec (S_UPDATE,				   (const char *)ddns_rev_name -> data,				   C_IN, T_PTR, ttl);	if (!updrec) {		result = ISC_R_NOMEMORY;		goto error;	}	updrec -> r_data = ddns_fwd_name -> data;	updrec -> r_size = ddns_fwd_name -> len;	updrec -> r_opcode = ADD;	ISC_LIST_APPEND (updqueue, updrec, r_link);	/*	 * Attempt to perform the update.	 */	result = minires_nupdate (&resolver_state, ISC_LIST_HEAD (updqueue));#if defined (DEBUG)	print_dns_status ((int)result, &updqueue);#endif	if (result == ISC_R_SUCCESS) {		log_info ("added reverse map from %.*s to %.*s",			  (int)ddns_rev_name -> len,			  (const char *)ddns_rev_name -> data,			  (int)ddns_fwd_name -> len,			  (const char *)ddns_fwd_name -> data);	} else {		log_error ("unable to add reverse map from %.*s to %.*s: %s",			   (int)ddns_rev_name -> len,			   (const char *)ddns_rev_name -> data,			   (int)ddns_fwd_name -> len,			   (const char *)ddns_fwd_name -> data,			   isc_result_totext (result));	}	/* Fall through. */      error:	while (!ISC_LIST_EMPTY (updqueue)) {		updrec = ISC_LIST_HEAD (updqueue);		ISC_LIST_UNLINK (updqueue, updrec, r_link);		minires_freeupdrec (updrec);	}	return result;}static isc_result_t ddns_remove_ptr (struct data_string *ddns_rev_name){	ns_updque updqueue;	ns_updrec *updrec;	isc_result_t result;	/*	 * When a lease expires or a DHCP client issues a DHCPRELEASE request,	 * the DHCP server SHOULD delete the PTR RR that matches the DHCP	 * binding, if one was successfully added. The server's update query	 * SHOULD assert that the name in the PTR record matches the name of	 * the client whose lease has expired or been released.	 *   -- "Interaction between DHCP and DNS"	 */	ISC_LIST_INIT (updqueue);	/*	 * Delete the PTR RRset for the leased address.	 */	updrec = minires_mkupdrec (S_UPDATE,				   (const char *)ddns_rev_name -> data,				   C_IN, T_PTR, 0);	if (!updrec) {		result = ISC_R_NOMEMORY;		goto error;	}	updrec -> r_data = (unsigned char *)0;	updrec -> r_size = 0;	updrec -> r_opcode = DELETE;	ISC_LIST_APPEND (updqueue, updrec, r_link);	/*	 * Attempt to perform the update.	 */	result = minires_nupdate (&resolver_state, ISC_LIST_HEAD (updqueue));#if defined (DEBUG)	print_dns_status ((int)result, &updqueue);#endif	if (result == ISC_R_SUCCESS) {		log_info ("removed reverse map on %.*s",			  (int)ddns_rev_name -> len,			  (const char *)ddns_rev_name -> data);	} else {		if (result != ISC_R_NXRRSET && result != ISC_R_NXDOMAIN)			log_error ("can't remove reverse map on %.*s: %s",				   (int)ddns_rev_name -> len,				   (const char *)ddns_rev_name -> data,				   isc_result_totext (result));	}	/* Not there is success. */	if (result == ISC_R_NXRRSET || result == ISC_R_NXDOMAIN)		result = ISC_R_SUCCESS;	/* Fall through. */      error:	while (!ISC_LIST_EMPTY (updqueue)) {		updrec = ISC_LIST_HEAD (updqueue);		ISC_LIST_UNLINK (updqueue, updrec, r_link);		minires_freeupdrec (updrec);	}	return result;}int ddns_updates (struct packet *packet,		  struct lease *lease, struct lease *old,		  struct lease_state *state){	unsigned long ddns_ttl = DEFAULT_DDNS_TTL;	struct data_string ddns_hostname;	struct data_string ddns_domainname;	struct data_string old_ddns_fwd_name;	struct data_string ddns_fwd_name;	struct data_string ddns_rev_name;	struct data_string ddns_dhcid;	unsigned len;	struct data_string d1;	struct option_cache *oc;	int s1, s2;	int result = 0;	isc_result_t rcode1 = ISC_R_SUCCESS, rcode2 = ISC_R_SUCCESS;	int server_updates_a = 1;	struct buffer *bp = (struct buffer *)0;	int ignorep = 0;	if (ddns_update_style != 2)		return 0;	/* Can only cope with IPv4 addrs at the moment. */	if (lease -> ip_addr . len != 4)		return 0;	memset (&ddns_hostname, 0, sizeof (ddns_hostname));	memset (&ddns_domainname, 0, sizeof (ddns_domainname));	memset (&old_ddns_fwd_name, 0, sizeof (ddns_fwd_name));	memset (&ddns_fwd_name, 0, sizeof (ddns_fwd_name));	memset (&ddns_rev_name, 0, sizeof (ddns_rev_name));	memset (&ddns_dhcid, 0, sizeof (ddns_dhcid));	/* If we are allowed to accept the client's update of its own A	   record, see if the client wants to update its own A record. */	if (!(oc = lookup_option (&server_universe, state -> options,				  SV_CLIENT_UPDATES)) ||	    evaluate_boolean_option_cache (&ignorep, packet, lease,					   (struct client_state *)0,					   packet -> options,					   state -> options,					   &lease -> scope, oc, MDL)) {		/* If there's no fqdn.no-client-update or if it's		   nonzero, don't try to use the client-supplied		   XXX */		if (!(oc = lookup_option (&fqdn_universe, packet -> options,					  FQDN_SERVER_UPDATE)) ||		    evaluate_boolean_option_cache (&ignorep, packet, lease,						   (struct client_state *)0,						   packet -> options,						   state -> options,						   &lease -> scope, oc, MDL))			goto noclient;		/* Win98 and Win2k will happily claim to be willing to		   update an unqualified domain name. */		if (!(oc = lookup_option (&fqdn_universe, packet -> options,					  FQDN_DOMAINNAME)))			goto noclient;		if (!(oc = lookup_option (&fqdn_universe, packet -> options,					  FQDN_FQDN)) ||		    !evaluate_option_cache (&ddns_fwd_name, packet, lease,					    (struct client_state *)0,					    packet -> options,					    state -> options,					    &lease -> scope, oc, MDL))			goto noclient;		server_updates_a = 0;		goto client_updates;	}      noclient:	/* If do-forward-updates is disabled, this basically means don't	   do an update unless the client is participating, so if we get	   here and do-forward-updates is disabled, we can stop. */	if ((oc = lookup_option (&server_universe, state -> options,				 SV_DO_FORWARD_UPDATES)) &&	    !evaluate_boolean_option_cache (&ignorep, packet, lease,					    (struct client_state *)0,					    packet -> options,					    state -> options,					    &lease -> scope, oc, MDL)) {		return 0;	}	/* If it's a static lease, then don't do the DNS update unless we're	   specifically configured to do so.   If the client asked to do its	   own update and we allowed that, we don't do this test. */	if (lease -> flags & STATIC_LEASE) {		if (!(oc = lookup_option (&server_universe, state -> options,					  SV_UPDATE_STATIC_LEASES)) ||		    !evaluate_boolean_option_cache (&ignorep, packet, lease,						    (struct client_state *)0,						    packet -> options,						    state -> options,						    &lease -> scope, oc, MDL))			return 0;	}	/*	 * Compute the name for the A record.	 */	s1 = s2 = 0;	oc = lookup_option (&server_universe, state -> options,			    SV_DDNS_HOST_NAME);	if (oc)		s1 = evaluate_option_cache (&ddns_hostname, packet, lease,					    (struct client_state *)0,					    packet -> options,					    state -> options,					    &lease -> scope, oc, MDL);	oc = lookup_option (&server_universe, state -> options,			    SV_DDNS_DOMAIN_NAME);	if (oc)		s2 = evaluate_option_cache (&ddns_domainname, packet, lease,					    (struct client_state *)0,					    packet -> options,					    state -> options,					    &lease -> scope, oc, MDL);	if (s1 && s2) {		if (ddns_hostname.len + ddns_domainname.len > 253) {			log_error ("ddns_update: host.domain name too long");			goto out;		}		buffer_allocate (&ddns_fwd_name.buffer,				 ddns_hostname.len + ddns_domainname.len + 2,				 MDL);		if (ddns_fwd_name.buffer) {			ddns_fwd_name.data = ddns_fwd_name.buffer -> data;			data_string_append (&ddns_fwd_name, &ddns_hostname);			ddns_fwd_name.buffer -> data [ddns_fwd_name.len] = '.';			ddns_fwd_name.len++;			data_string_append (&ddns_fwd_name, &ddns_domainname);			ddns_fwd_name.buffer -> data [ddns_fwd_name.len] ='\0';			ddns_fwd_name.terminated = 1;		}	}      client_updates:	/* See if there's a name already stored on the lease. */	if (find_bound_string (&old_ddns_fwd_name,			       lease -> scope, "ddns-fwd-name")) {		/* If there is, see if it's different. */		if (old_ddns_fwd_name.len != ddns_fwd_name.len ||		    memcmp (old_ddns_fwd_name.data, ddns_fwd_name.data,			    old_ddns_fwd_name.len)) {			/* If the name is different, try to delete			   the old A record. */			if (!ddns_removals (lease))				goto out;			/* If the delete succeeded, go install the new			   record. */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -