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

📄 dns.c

📁 DHCP服务器源码
💻 C
📖 第 1 页 / 共 2 页
字号:
	/*	 * DHCP clients and servers should use the following forms of client	 * identification, starting with the most preferable, and finishing	 * with the least preferable.  If the client does not send any of these	 * forms of identification, the DHCP/DDNS interaction is not defined by	 * this specification.  The most preferable form of identification is	 * the Globally Unique Identifier Option [TBD].  Next is the DHCP	 * Client Identifier option.  Last is the client's link-layer address,	 * as conveyed in its DHCPREQUEST message.  Implementors should note	 * that the link-layer address cannot be used if there are no	 * significant bytes in the chaddr field of the DHCP client's request,	 * because this does not constitute a unique identifier.	 *   -- "Interaction between DHCP and DNS"	 *      <draft-ietf-dhc-dhcp-dns-12.txt>	 *      M. Stapp, Y. Rekhter	 */	/* Put the type in the first two bytes. */	id -> buffer -> data [0] = "0123456789abcdef" [type >> 4];	id -> buffer -> data [1] = "0123456789abcdef" [type % 15];	/* Mash together an MD5 hash of the identifier. */	MD5_Init (&md5);	MD5_Update (&md5, data, len);	MD5_Final (buf, &md5);	/* Convert into ASCII. */	for (i = 0; i < MD5_DIGEST_LENGTH; i++) {		id -> buffer -> data [i * 2 + 2] =			"0123456789abcdef" [(buf [i] >> 4) & 0xf];		id -> buffer -> data [i * 2 + 3] =			"0123456789abcdef" [buf [i] & 0xf];	}	id -> len = MD5_DIGEST_LENGTH * 2 + 2;	id -> buffer -> data [id -> len] = 0;	id -> terminated = 1;	return 1;}/* 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){	ns_updque updqueue;	ns_updrec *updrec;	isc_result_t result;	char ddns_address [16];	if (ddns_addr.len != 4)		return ISC_R_INVALIDARG;	/* %Audit% Cannot exceed 16 bytes. %2004.06.17,Safe% */	sprintf (ddns_address, "%u.%u.%u.%u",		  ddns_addr.iabuf[0], ddns_addr.iabuf[1],		  ddns_addr.iabuf[2], ddns_addr.iabuf[3]);	/*	 * When a DHCP client or server intends to update an A RR, it first	 * prepares a DNS UPDATE query which includes as a prerequisite the	 * assertion that the name does not exist.  The update section of the	 * query attempts to add the new name and its IP address mapping (an A	 * RR), and the DHCID RR with its unique client-identity.	 *   -- "Interaction between DHCP and DNS"	 */	ISC_LIST_INIT (updqueue);	/*	 * A RR does not exist.	 */	updrec = minires_mkupdrec (S_PREREQ,				   (const char *)ddns_fwd_name -> data,				   C_IN, T_A, 0);	if (!updrec) {		result = ISC_R_NOMEMORY;		goto error;	}	updrec -> r_data = (unsigned char *)0;	updrec -> r_size = 0;	updrec -> r_opcode = rrsetp ? NXRRSET : NXDOMAIN;	ISC_LIST_APPEND (updqueue, updrec, r_link);	/*	 * Add A RR.	 */	updrec = minires_mkupdrec (S_UPDATE,				   (const char *)ddns_fwd_name -> data,				   C_IN, T_A, ttl);	if (!updrec) {		result = ISC_R_NOMEMORY;		goto error;	}	updrec -> r_data = (unsigned char *)ddns_address;	updrec -> r_size = strlen (ddns_address);	updrec -> r_opcode = ADD;	ISC_LIST_APPEND (updqueue, updrec, r_link);	/*	 * Add DHCID RR.	 */	updrec = minires_mkupdrec (S_UPDATE,				   (const char *)ddns_fwd_name -> data,				   C_IN, T_DHCID, ttl);	if (!updrec) {		result = ISC_R_NOMEMORY;		goto error;	}	updrec -> r_data = ddns_dhcid -> data;	updrec -> r_size = ddns_dhcid -> 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));#ifdef DEBUG_DNS_UPDATES	print_dns_status ((int)result, &updqueue);#endif	/*	 * If this update operation succeeds, the updater can conclude that it	 * has added a new name whose only RRs are the A and DHCID RR records.	 * The A RR update is now complete (and a client updater is finished,	 * while a server might proceed to perform a PTR RR update).	 *   -- "Interaction between DHCP and DNS"	 */	if (result == ISC_R_SUCCESS) {		log_info ("Added new forward map from %.*s to %s",			  (int)ddns_fwd_name -> len,			  (const char *)ddns_fwd_name -> data, ddns_address);		goto error;	}	/*	 * If the first update operation fails with YXDOMAIN, the updater can	 * conclude that the intended name is in use.  The updater then	 * attempts to confirm that the DNS name is not being used by some	 * other host. The updater prepares a second UPDATE query in which the	 * prerequisite is that the desired name has attached to it a DHCID RR	 * whose contents match the client identity.  The update section of	 * this query deletes the existing A records on the name, and adds the	 * A record that matches the DHCP binding and the DHCID RR with the	 * client identity.	 *   -- "Interaction between DHCP and DNS"	 */	if (result != (rrsetp ? ISC_R_YXRRSET : ISC_R_YXDOMAIN)) {		log_error ("Unable to add forward map from %.*s to %s: %s",			   (int)ddns_fwd_name -> len,			   (const char *)ddns_fwd_name -> data, ddns_address,			   isc_result_totext (result));		goto error;	}	while (!ISC_LIST_EMPTY (updqueue)) {		updrec = ISC_LIST_HEAD (updqueue);		ISC_LIST_UNLINK (updqueue, updrec, r_link);		minires_freeupdrec (updrec);	}	/*	 * 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);	/*	 * Delete A RRset.	 */	updrec = minires_mkupdrec (S_UPDATE,				   (const char *)ddns_fwd_name -> data,				   C_IN, T_A, 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 A RR.	 */	updrec = minires_mkupdrec (S_UPDATE,				   (const char *)ddns_fwd_name -> data,				   C_IN, T_A, ttl);	if (!updrec) {		result = ISC_R_NOMEMORY;		goto error;	}	updrec -> r_data = (unsigned char *)ddns_address;	updrec -> r_size = strlen (ddns_address);	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 (result != ISC_R_SUCCESS) {		if (result == YXRRSET || result == YXDOMAIN ||		    result == NXRRSET || result == NXDOMAIN)			log_error ("Forward map from %.*s to %s already in use",				   (int)ddns_fwd_name -> len,				   (const char *)ddns_fwd_name -> data,				   ddns_address);		else			log_error ("Can't update forward map %.*s to %s: %s",				   (int)ddns_fwd_name -> len,				   (const char *)ddns_fwd_name -> data,				   ddns_address, isc_result_totext (result));	} else {		log_info ("Added new forward map from %.*s to %s",			  (int)ddns_fwd_name -> len,			  (const char *)ddns_fwd_name -> data, ddns_address);	}#if defined (DEBUG_DNS_UPDATES)	print_dns_status ((int)result, &updqueue);#endif	/*	 * If this query succeeds, the updater can conclude that the current	 * client was the last client associated with the domain name, and that	 * the name now contains the updated A RR. The A RR update is now	 * complete (and a client updater is finished, while a server would	 * then proceed to perform a PTR RR update).	 *   -- "Interaction between DHCP and DNS"	 */	/*	 * If the second query fails with NXRRSET, the updater must conclude	 * that the client's desired name is in use by another host.  At this	 * juncture, the updater can decide (based on some administrative	 * configuration outside of the scope of this document) whether to let	 * the existing owner of the name keep that name, and to (possibly)	 * perform some name disambiguation operation on behalf of the current	 * client, or to replace the RRs on the name with RRs that represent	 * the current client. If the configured policy allows replacement of	 * existing records, the updater submits a query that deletes the	 * existing A RR and the existing DHCID RR, adding A and DHCID RRs that	 * represent the IP address and client-identity of the new client.	 *   -- "Interaction between DHCP and DNS"	 */  error:	while (!ISC_LIST_EMPTY (updqueue)) {		updrec = ISC_LIST_HEAD (updqueue);		ISC_LIST_UNLINK (updqueue, updrec, r_link);		minires_freeupdrec (updrec);	}	return result;}isc_result_t ddns_remove_a (struct data_string *ddns_fwd_name,			    struct iaddr ddns_addr,			    struct data_string *ddns_dhcid){	ns_updque updqueue;	ns_updrec *updrec;	isc_result_t result = SERVFAIL;	char ddns_address [16];	if (ddns_addr.len != 4)		return ISC_R_INVALIDARG;	/* %Audit% Cannot exceed 16 bytes. %2004.06.17,Safe% */	sprintf (ddns_address, "%u.%u.%u.%u",		  ddns_addr.iabuf[0], ddns_addr.iabuf[1],		  ddns_addr.iabuf[2], ddns_addr.iabuf[3]);	/*	 * The entity chosen to handle the A record for this client (either the	 * client or the server) SHOULD delete the A record that was added when	 * the lease was made to the client.	 *	 * In order to perform this delete, the updater prepares an UPDATE	 * query which contains two prerequisites.  The first prerequisite	 * asserts that the DHCID RR exists whose data is the client identity	 * described in Section 4.3. The second prerequisite asserts that the	 * data in the A RR contains the IP address of the lease that has	 * expired or been released.	 *   -- "Interaction between DHCP and DNS"	 */	ISC_LIST_INIT (updqueue);	/*	 * 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);	/*	 * A RR matches the expiring lease.	 */	updrec = minires_mkupdrec (S_PREREQ,				   (const char *)ddns_fwd_name -> data,				   C_IN, T_A, 0);	if (!updrec) {		result = ISC_R_NOMEMORY;		goto error;	}	updrec -> r_data = (unsigned char *)ddns_address;	updrec -> r_size = strlen (ddns_address);	updrec -> r_opcode = YXRRSET;	ISC_LIST_APPEND (updqueue, updrec, r_link);	/*	 * Delete appropriate A RR.	 */	updrec = minires_mkupdrec (S_UPDATE,				   (const char *)ddns_fwd_name -> data,				   C_IN, T_A, 0);	if (!updrec) {		result = ISC_R_NOMEMORY;		goto error;	}	updrec -> r_data = (unsigned char *)ddns_address;	updrec -> r_size = strlen (ddns_address);	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));	print_dns_status ((int)result, &updqueue);	/*	 * If the query fails, the updater MUST NOT delete the DNS name.  It	 * may be that the host whose lease on the server has expired has moved	 * to another network and obtained a lease from a different server,	 * which has caused the client's A RR to be replaced. It may also be	 * that some other client has been configured with a name that matches	 * the name of the DHCP client, and the policy was that the last client	 * to specify the name would get the name.  In this case, the DHCID RR	 * will no longer match the updater's notion of the client-identity of	 * the host pointed to by the DNS name.	 *   -- "Interaction between DHCP and DNS"	 */	if (result != ISC_R_SUCCESS) {		/* If the rrset isn't there, we didn't need to do the		   delete, which is success. */		if (result == ISC_R_NXRRSET || result == ISC_R_NXDOMAIN)			result = ISC_R_SUCCESS;			goto error;	}	while (!ISC_LIST_EMPTY (updqueue)) {		updrec = ISC_LIST_HEAD (updqueue);		ISC_LIST_UNLINK (updqueue, updrec, r_link);		minires_freeupdrec (updrec);	}	/* If the deletion of the A succeeded, and there are no A records	   left for this domain, then we can blow away the DHCID record	   as well.   We can't blow away the DHCID record above because	   it's possible that more than one A has been added to this	   domain name. */	ISC_LIST_INIT (updqueue);	/*	 * A RR does not exist.	 */	updrec = minires_mkupdrec (S_PREREQ,				   (const char *)ddns_fwd_name -> data,				   C_IN, T_A, 0);	if (!updrec) {		result = ISC_R_NOMEMORY;		goto error;	}	updrec -> r_data = (unsigned char *)0;	updrec -> r_size = 0;	updrec -> r_opcode = NXRRSET;	ISC_LIST_APPEND (updqueue, updrec, r_link);	/*	 * Delete appropriate DHCID RR.	 */	updrec = minires_mkupdrec (S_UPDATE,				  (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 = DELETE;	ISC_LIST_APPEND (updqueue, updrec, r_link);	/*	 * Attempt to perform the update.	 */	result = minires_nupdate (&resolver_state, ISC_LIST_HEAD (updqueue));	print_dns_status ((int)result, &updqueue);	/* 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;}#endif /* NSUPDATE */HASH_FUNCTIONS (dns_zone, const char *, struct dns_zone, dns_zone_hash_t,		dns_zone_reference, dns_zone_dereference)

⌨️ 快捷键说明

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