/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
*/
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <resolv.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <netdb.h>
#include <syslog.h>
#include <kerberosv5/krb5.h>
#include <smbns_dyndns.h>
#include <smbns_krb.h>
/*
* The following can be removed once head/arpa/nameser_compat.h
* defines BADSIG, BADKEY and BADTIME.
*/
#ifndef BADSIG
#endif /* BADSIG */
#ifndef BADKEY
#endif /* BADKEY */
#ifndef BADTIME
#endif /* BADTIME */
/* internal use, in dyndns_add_entry */
/* Maximum retires if not authoritative */
/* Number of times to retry a DNS query */
/* Timeout value, in seconds, for DNS query responses */
#define DYNDNS_STATE_INIT 0
typedef struct dyndns_qentry {
int dqe_op;
/* fully-qualified domain name is in lower case */
typedef struct dyndns_queue {
static void dyndns_queue_request(int, const char *);
static void dyndns_queue_flush(list_t *);
static void dyndns_process(list_t *);
static int dyndns_update_core(char *);
static int dyndns_clear_rev_zone(char *);
static void dyndns_msgid_init(void);
static int dyndns_get_msgid(void);
static void dyndns_syslog(int, int, const char *);
void
dyndns_start(void)
{
return;
}
}
void
dyndns_stop(void)
{
switch (dyndns_queue.ddq_state) {
case DYNDNS_STATE_READY:
case DYNDNS_STATE_PUBLISHING:
break;
default:
break;
}
}
/*
* Clear all records in both zones.
*/
void
dyndns_clear_zones(void)
{
return;
}
}
/*
* Update all records in both zones.
*/
void
dyndns_update_zones(void)
{
return;
}
}
/*
* Add a request to the queue.
*
* To comply with RFC 4120 section 6.2.1, entry->dqe_fqdn is converted
* to lower case.
*/
static void
{
return;
return;
switch (dyndns_queue.ddq_state) {
case DYNDNS_STATE_READY:
case DYNDNS_STATE_PUBLISHING:
break;
default:
break;
}
}
/*
*/
static void
{
}
}
/*
* Dyndns update thread. While running, the thread waits on a condition
* variable until notified that an entry needs to be updated.
*
* If the outgoing queue is not empty, the thread wakes up every 60 seconds
* to retry.
*/
/*ARGSUSED*/
void *
{
return (NULL);
}
for (;;) {
}
break;
}
/*
* Transfer queued items to the local list so that
* the mutex can be released.
*/
}
}
return (NULL);
}
/*
* Remove items from the queue and process them.
*/
static void
{
return;
}
case DYNDNS_OP_CLEAR:
break;
case DYNDNS_OP_UPDATE:
break;
default:
break;
}
}
}
/*
* Dynamic DNS update API for kclient.
*
* Returns 0 upon success. Otherwise, returns -1.
*/
int
{
int rc;
if (smb_nic_init() != SMB_NIC_SUCCESS)
return (-1);
(void) smb_strlwr(fqdn);
smb_nic_fini();
return (rc);
}
/*
* Initializes the DNS message ID counter using the algorithm
* that resolver library uses to initialize the ID field of any res
* structure.
*/
static void
dyndns_msgid_init(void)
{
(void) mutex_lock(&dns_msgid_mtx);
(void) mutex_unlock(&dns_msgid_mtx);
}
static int
dyndns_get_msgid(void)
{
(void) mutex_lock(&dns_msgid_mtx);
(void) mutex_unlock(&dns_msgid_mtx);
return (id);
}
/*
* Log a DNS error message
*/
static void
{
struct {
int errnum;
char *errmsg;
} errtab[] = {
{ FORMERR, "message format error" },
{ SERVFAIL, "server internal error" },
{ NXDOMAIN, "entry should exist but does not exist" },
{ NOTIMP, "not supported" },
{ REFUSED, "operation refused" },
{ YXDOMAIN, "entry should not exist but does exist" },
{ YXRRSET, "RRSet should not exist but does exist" },
{ NXRRSET, "RRSet should exist but does not exist" },
{ NOTAUTH, "server is not authoritative for specified zone" },
{ NOTZONE, "name not within specified zone" },
{ BADSIG, "bad transaction signature (TSIG)" },
{ BADKEY, "bad transaction key (TKEY)" },
{ BADTIME, "time not synchronized" },
};
int i;
return;
break;
}
}
}
/*
* display_stat
* Display GSS error message from error code. This routine is used to display
* the mechanism independent and mechanism specific error messages for GSS
* routines. The major status error code is the mechanism independent error
* code and the minor status error code is the mechanism specific error code.
* Parameters:
* maj: GSS major status
* min: GSS minor status
* Returns:
* None
*/
static void
{
}
static char *
{
return (buf);
}
static char *
{
return (buf);
}
static char *
{
return (buf);
}
static char *
{
buf++;
return (buf);
}
static char *
{
buf += sizeof (int);
return (buf);
}
static char *
{
return (buf);
}
/*
* dyndns_stuff_str
* Converts a domain string by removing periods and replacing with a byte value
* of how many characters following period. A byte value is placed in front
* to indicate how many characters before first period. A NULL character is
* placed at the end. i.e. host.procom.com -> 4host5procom3com0
* Buffer space checking is done by caller.
* Parameters:
* ptr : address of pointer to buffer to store converted string
* zone: domain name string
* Returns:
* ptr: address of pointer to next available buffer space
* -1 : error
* 0 : success
*/
static int
{
int len;
len = 0;
zonePtr++;
len++;
}
if (*zonePtr == '.')
zonePtr++;
}
return (0);
}
/*
* dyndns_build_header
* Build the header for DNS query and DNS update request message.
* Parameters:
* ptr : address of pointer to buffer to store header
* buf_len : buffer length
* msg_id : message id
* query_req : use REQ_QUERY for query message or REQ_UPDATE for
* update message
* quest_zone_cnt : number of question record for query message or
* number of zone record for update message
* ans_prereq_cnt : number of answer record for query message or
* number of prerequisite record for update message
* nameser_update_cnt: number of name server for query message or
* number of update record for update message
* addit_cnt : number of additional record
* flags : query flags word
* Returns:
* ptr: address of pointer to next available buffer space
* -1 : error
* 0 : success
*/
static int
{
if (buf_len < 12) {
return (-1);
}
else
/* mesg opcode */
/* zone record count */
/* prerequiste record count */
/* update record count */
/* additional record count */
return (0);
}
/*
* dyndns_build_quest_zone
* Build the question section for query message or zone section for
* update message.
* Parameters:
* ptr : address of pointer to buffer to store question or zone section
* buf_len: buffer length
* name : question or zone name
* type : type of question or zone
* class : class of question or zone
* Returns:
* ptr: address of pointer to next available buffer space
* -1 : error
* 0 : success
*/
static int
int class)
{
char *zonePtr;
return (-1);
}
return (0);
}
/*
* dyndns_build_update
* Build update section of update message for adding and removing a record.
* If the ttl value is 0 then this message is for record deletion.
*
* Parameters:
* ptr : address of pointer to buffer to store update section
* buf_len : buffer length
* name : resource name of this record
* type : type of this record
* class : class of this record
* ttl : time-to-live, cached time of this entry by others and not
* within DNS database, a zero value for record(s) deletion
* data : data of this resource record
* forw_rev: UPDATE_FORW for forward zone, UPDATE_REV for reverse zone
* add_del : UPDATE_ADD for adding entry, UPDATE_DEL for removing zone
* del_type: DEL_ONE for deleting one entry, DEL_ALL for deleting all
* entries of the same resource name. Only valid for UPDATE_DEL.
* Returns:
* ptr: address of pointer to next available buffer space
* -1 : error
* 0 : success
*/
static int
{
char *namePtr;
isv4 = 1;
isv4 = 0;
if (add_del == UPDATE_ADD) {
if (forw_rev == UPDATE_FORW)
else
} else {
data_len = 0;
else if (forw_rev == UPDATE_FORW)
else
}
return (-1);
}
if (isv4)
else
return (0);
}
if (forw_rev == UPDATE_FORW) {
if (isv4) {
} else {
}
} else {
}
return (0);
}
/*
* dyndns_build_tkey
* Build TKEY section to establish security context for secure dynamic DNS
* update. DNS header and question sections need to be build before this
* section. The TKEY data are the tokens generated during security context
* establishment and the TKEY message is used to transmit those tokens, one
* at a time, to the DNS server.
* Parameters:
* ptr : address of pointer to buffer to store TKEY
* buf_len : buffer length
* name : key name, must be unique and same as for TSIG record
* key_expire: expiration time of this key in second
* data : TKEY data
* data_size : data size
* Returns:
* ptr: address of the pointer to the next available buffer space
* -1 : error
* 0 : success
*/
static int
{
char *namePtr;
return (-1);
}
/* 19 + 14 + data_size + 2 */
(void) gettimeofday(&tp, 0);
/* expiration, 86400 */
return (0);
}
/*
* dyndns_build_tsig
* Build TSIG section for secure dynamic DNS update. This routine will be
* called twice. First called with TSIG_UNSIGNED, and second with TSIG_SIGNED.
* The TSIG data is NULL and ignored for TSIG_UNSIGNED and is the update request
* message encrypted for TSIG_SIGNED. The message id must be the same id as the
* one in the update request before it is encrypted.
* Parameters:
* ptr : address of pointer to buffer to store TSIG
* buf_len : buffer length
* msg_id : message id
* name : key name, must be the same as in TKEY record
* fudge_time : amount of error time allow in seconds
* data : TSIG data if TSIG_SIGNED, otherwise NULL
* data_size : size of data, otherwise 0 if data is NULL
* data_signed: TSIG_SIGNED to indicate data is signed and encrypted,
* otherwise TSIG_UNSIGNED
* Returns:
* ptr: address of pointer to next available buffer space
* -1 : error
* 0 : success
*/
static int
{
char *namePtr;
if (data_signed == TSIG_UNSIGNED)
else
return (-1);
}
if (data_signed == TSIG_SIGNED)
if (data_signed == TSIG_SIGNED) {
/* 19 + 10 + data_size + 6 */
}
(void) gettimeofday(&tp, 0);
fudge |= fudge_time;
if (data_signed == TSIG_SIGNED) {
/* signed data size */
}
return (0);
}
/*
* dyndns_open_init_socket
* This routine creates a SOCK_STREAM or SOCK_DGRAM socket and initializes it
* by doing bind() and setting linger option to off.
*
* Parameters:
* sock_type: SOCK_STREAM for TCP or SOCK_DGRAM for UDP
* dest_addr: destination address in network byte order
* port : destination port number
* Returns:
* descriptor: descriptor referencing the created socket
* -1 : error
*/
static int
{
int s;
int family;
return (-1);
}
sizeof (my_addr)) < 0) {
(void) close(s);
return (-1);
}
sizeof (struct sockaddr_in)) < 0) {
(void) close(s);
return (-1);
}
} else {
sizeof (my6_addr)) < 0) {
(void) close(s);
return (-1);
}
sizeof (struct sockaddr_in6)) < 0) {
(void) close(s);
return (-1);
}
}
return (s);
}
/*
* dyndns_build_tkey_msg
* This routine is used to build the TKEY message to transmit GSS tokens
* during GSS security context establishment for secure DNS update. The
* TKEY message format uses the DNS query message format. The TKEY section
* is the answer section of the query message format.
* Microsoft uses a value of 86400 seconds (24 hours) for key expiration time.
* Parameters:
* buf : buffer to build and store TKEY message
* key_name: a unique key name, this same key name must be also be used in
* the TSIG message
* out_tok : TKEY message data (GSS tokens)
* Returns:
* id : message id of this TKEY message
* message size: the size of the TKEY message
* -1 : error
*/
static int
{
char *bufptr;
/* query section of query request */
zoneCount = 1;
/* answer section of query request */
preqCount = 1;
updateCount = 0;
additionalCount = 0;
*id = dyndns_get_msgid();
/* add TCP length info that follows this field */
return (-1);
}
return (-1);
}
return (-1);
}
}
/*
* dyndns_establish_sec_ctx
* This routine is used to establish a security context with the DNS server
* by building TKEY messages and sending them to the DNS server. TKEY messages
* are also received from the DNS server for processing. The security context
* establishment is done with the GSS client on the system producing a token
* and sending the token within the TKEY message to the GSS server on the DNS
* server. The GSS server then processes the token and then send a TKEY reply
* message with a new token to be processed by the GSS client. The GSS client
* processes the new token and then generates a new token to be sent to the
* GSS server. This cycle is continued until the security establishment is
* done. TCP is used to send and receive TKEY messages.
* Parameters:
* cred_handle : handle to credential
* s : socket descriptor to DNS server
* key_name : TKEY key name
* dns_hostname: fully qualified DNS hostname which will be used for
* constructing the DNS service principal name.
* oid : contains Kerberos 5 object identifier
* Returns:
* gss_context : handle to security context
*/
static int
{
int ret;
int service_sz;
int gss_flags;
int buf_sz;
if (service_name == NULL)
return (-1);
(void) free(service_name);
return (-1);
}
(void) free(service_name);
do {
if (*gss_context != GSS_C_NO_CONTEXT)
(void) gss_delete_sec_context(&min,
gss_context, NULL);
return (-1);
}
if ((maj == GSS_S_COMPLETE) &&
!(ret_flags & GSS_C_REPLAY_FLAG)) {
return (-1);
}
if ((maj == GSS_S_COMPLETE) &&
!(ret_flags & GSS_C_MUTUAL_FLAG)) {
return (-1);
}
return (-1);
}
return (-1);
}
return (-1);
}
return (-1);
}
return (-1);
}
/* bsd38 -> 2*7=14 */
}
} while (maj != GSS_S_COMPLETE);
return (0);
}
/*
* dyndns_get_sec_context
* Get security context for secure dynamic DNS update. This routine opens
* a TCP socket to the DNS server and establishes a security context with
* the DNS server using host principal to perform secure dynamic DNS update.
* Parameters:
* hostname: fully qualified hostname
* dns_ip : ip address of hostname in network byte order
* Returns:
* gss_handle: gss credential handle
* gss_context: gss security context
* -1: error
* 0: success
*/
static gss_ctx_id_t
{
int s;
oid = GSS_C_NO_OID;
sizeof (dns_hostname), 0)) {
return (NULL);
}
return (NULL);
}
dns_hostname, oid))
gss_context = NULL;
(void) close(s);
return (gss_context);
}
/*
* dyndns_build_add_remove_msg
* This routine builds the update request message for adding and removing DNS
* entries which is used for non-secure and secure DNS update.
* This routine builds an UDP message.
* Parameters:
* buf : buffer to build message
* update_zone: the type of zone to update, use UPDATE_FORW for forward
* lookup zone, use UPDATE_REV for reverse lookup zone
* hostname : fully qualified hostname to update DNS with
* ip_addr : IP address of hostname
* life_time : cached time of this entry by others and not within DNS
* database
* update_type: UPDATE_ADD to add entry, UPDATE_DEL to remove entry
* del_type : DEL_ONE for deleting one entry, DEL_ALL for deleting all
* entries of the same resource name. Only valid for UPDATE_DEL.
* addit_cnt : Indicate how many record is in the additional section of
* the DNS message. A value of zero is always used with
* non-secure update message. For secure update message,
* the value will be one because the signed TSIG message
* is added as the additional record of the DNS update message.
* id : DNS message ID. If a positive value then this ID value is
* used, otherwise the next incremented value is used
* level : This is the domain level which we send the request to, level
* zero is the default level, it can go upto 2 in reverse zone
* and virtually to any level in forward zone.
* Returns:
* buf : buffer containing update message
* id : DNS message ID
* int : size of update message
* -1 : error
*
* This function is changed to handle dynamic DNS update retires to higher
* authoritative domains.
*/
static int
{
int a, b, c, d;
char *bufptr;
char *p;
int i, j, k;
int fourcnt;
zoneCount = 1;
preqCount = 0;
updateCount = 1;
if (*id == 0)
*id = dyndns_get_msgid();
return (-1);
}
if (update_zone == UPDATE_FORW) {
p = (char *)hostname;
/* Try higher domains according to the level requested */
do {
/* domain */
return (-1);
zone += 1;
p = zone;
} while (--level >= 0);
} else {
c, b, a);
/* Try higher domains based on level requested */
while (--level >= 0) {
/* domain */
return (-1);
}
zone += 1;
p = zone;
}
d, c, b, a);
} else {
/*
* create reverse nibble ipv6 format
*/
i = 0;
j = 0;
while (ip_addr[i] != 0)
i++;
i--;
while (i >= 0) {
fourcnt = 3;
while ((i >= 0) && (ip_addr[i] != ':')) {
fourcnt --;
i--;
}
for (k = 0; k <= fourcnt; k++) {
resrc_buf[j++] = '0';
}
i--;
}
}
}
return (-1);
}
if (update_zone == UPDATE_FORW)
else
if (update_type == UPDATE_ADD) {
} else {
else
ttl = 0;
}
return (-1);
}
}
/*
* dyndns_build_unsigned_tsig_msg
* This routine is used to build the unsigned TSIG message for signing. The
* unsigned TSIG message contains the update request message with certain TSIG
* fields included. An error time of 300 seconds is used for fudge time. This
* is the number used by Microsoft clients.
* This routine builds a UDP message.
* Parameters:
* buf : buffer to build message
* update_zone: the type of zone to update, use UPDATE_FORW for forward
* lookup zone, use UPDATE_REV for reverse lookup zone
* hostname : fully qualified hostname to update DNS with
* ip_addr : IP address of hostname
* life_time : cached time of this entry by others and not within DNS
* database
* update_type: UPDATE_ADD to add entry, UPDATE_DEL to remove entry
* del_type : DEL_ONE for deleting one entry, DEL_ALL for deleting all
* entries of the same resource name. Only valid for UPDATE_DEL.
* key_name : same key name used in TKEY message
* id : DNS message ID. If a positive value then this ID value is
* used, otherwise the next incremented value is used
* level : This is the domain level which we send the request to, level
* zero is the default level, it can go upto 2 in reverse zone
* and virtually to any level in forward zone.
* Returns:
* buf : buffer containing update message
* id : DNS message ID
* int : size of update message
* -1 : error
*/
static int
{
char *bufptr;
int buf_sz;
return (-1);
}
return (-1);
}
}
/*
* dyndns_build_signed_tsig_msg
* This routine build the signed TSIG message which contains the update
* request message encrypted. An error time of 300 seconds is used for fudge
* time. This is the number used by Microsoft clients.
* This routine builds a UDP message.
* Parameters:
* buf : buffer to build message
* update_zone: the type of zone to update, use UPDATE_FORW for forward
* lookup zone, use UPDATE_REV for reverse lookup zone
* hostname : fully qualified hostname to update DNS with
* ip_addr : IP address of hostname
* life_time : cached time of this entry by others and not within DNS
* database
* update_type: UPDATE_ADD to add entry, UPDATE_DEL to remove entry
* del_type : DEL_ONE for deleting one entry, DEL_ALL for deleting all
* entries of the same resource name. Only valid for UPDATE_DEL.
* key_name : same key name used in TKEY message
* id : DNS message ID. If a positive value then this ID value is
* used, otherwise the next incremented value is used
* in_mic : the update request message encrypted
* level : This is the domain level which we send the request to, level
* zero is the default level, it can go upto 2 in reverse zone
* and virtually to any level in forward zone.
*
* Returns:
* buf : buffer containing update message
* id : DNS message ID
* int : size of update message
* -1 : error
*/
static int
{
char *bufptr;
int buf_sz;
return (-1);
}
return (-1);
}
}
/*
* dyndns_udp_send_recv
* This routine sends and receives UDP DNS request and reply messages.
*
* Pre-condition: Caller must call dyndns_open_init_socket() before calling
* this function.
*
* Parameters:
* s : socket descriptor
* buf : buffer containing data to send
* buf_sz : size of data to send
* Returns:
* -1 : error
* rec_buf: reply dat
* 0 : success
*/
static int
{
for (i = 0; i <= DYNDNS_MAX_QUERY_RETRIES; i++) {
return (-1);
}
if (retval == -1) {
return (-1);
} else if (retval > 0) {
addr_len = sizeof (struct sockaddr_in6);
return (-1);
}
break;
}
}
/* did not receive anything */
if (i == (DYNDNS_MAX_QUERY_RETRIES + 1)) {
return (-1);
}
return (0);
}
/*
* dyndns_sec_add_remove_entry
* Perform secure dynamic DNS update after getting security context.
* This routine opens a UDP socket to the DNS sever, gets the security context,
* builds the unsigned TSIG message and signed TSIG message. The signed TSIG
* message containing the encrypted update request message is sent to the DNS
* server. The response is received and check for error. If there is no
* error then credential handle and security context are released and the local
* NSS cached is purged.
* Parameters:
* update_zone : UPDATE_FORW for forward zone, UPDATE_REV for reverse zone
* hostname : fully qualified hostname
* ip_addr : ip address of hostname in string format
* life_time : cached time of this entry by others and not within DNS
* database
* max_retries : maximum retries for sending DNS update request
* recv_timeout: receive timeout
* update_type : UPDATE_ADD for adding entry, UPDATE_DEL for removing entry
* del_type : DEL_ONE for deleting one entry, DEL_ALL for deleting all
* entries of the same resource name. Only valid for UPDATE_DEL
* dns_str : DNS IP address in string format
* Returns:
* -1: error
* 0: success
*
* This function is enhanced to handle the case of NOTAUTH error when DNS server
* is not authoritative for specified zone. In this case we need to resend the
* same request to the higher authoritative domains.
* This is true for both secure and unsecure dynamic DNS updates.
*/
static int
char *dns_str)
{
int s2;
int ret;
char *key_name;
int buf_sz;
int level = 0;
return (-1);
}
if (gss_context != GSS_C_NO_CONTEXT)
return (-1);
}
id = 0;
if (gss_context != GSS_C_NO_CONTEXT)
return (-1);
}
/* sign update message */
if (gss_context != GSS_C_NO_CONTEXT)
return (-1);
}
if (gss_context != GSS_C_NO_CONTEXT)
return (-1);
}
if (gss_context != GSS_C_NO_CONTEXT)
return (-1);
}
if (gss_context != GSS_C_NO_CONTEXT)
/*
* If it is a NOTAUTH error we should retry with higher domains
* until we get a successful reply or the maximum retries is met.
*/
goto sec_retry_higher;
/* check here for update request is successful */
return (-1);
}
return (-1);
return (0);
}
/*
* dyndns_seach_entry
* Query DNS server for entry. This routine can indicate if an entry exist
* or not during forward or reverse lookup. Also can indicate if the data
* of the entry matched. For example, for forward lookup, the entry is
* searched using the hostname and the data is the IP address. For reverse
* lookup, the entry is searched using the IP address and the data is the
* hostname.
* Parameters:
* update_zone: UPDATE_FORW for forward zone, UPDATE_REV for reverse zone
* hostname : fully qualified hostname
* ip_addr : ip address of hostname in string format
* update_type: UPDATE_ADD for adding entry, UPDATE_DEL for removing entry
* Returns:
* time_out: no use
* is_match: is 1 for found matching entry, otherwise 0
* 1 : an entry exist but not necessarily match
* 0 : an entry does not exist
*/
/*ARGSUSED*/
static int
{
int salen;
int family;
*is_match = 0;
}
if (update_zone == UPDATE_FORW) {
return (NULL);
}
if (res) {
/*
* if both ips aren't the same family skip to
* the next record
*/
do {
salen);
*is_match = 1;
break;
}
salen);
/* need compare macro here */
IN6ADDRSZ)) {
*is_match = 1;
break;
}
}
return (1);
}
} else {
return (NULL);
*is_match = 1;
}
return (1);
}
/* entry does not exist */
return (0);
}
/*
* dyndns_add_remove_entry
* Perform non-secure dynamic DNS update. If it fails and host principal
* keys can be found in the local keytab file, secure update will be performed.
*
* This routine opens a UDP socket to the DNS sever, build the update request
* message, and sends the message to the DNS server. The response is received
* and check for error. If there is no error then the local NSS cached is
* purged. DNS may be used to check to see if an entry already exist before
* adding or to see if an entry does exist before removing it. Adding
* duplicate entries or removing non-existing entries does not cause any
* problems. DNS is not check when doing a delete all.
* Parameters:
* update_zone: UPDATE_FORW for forward zone, UPDATE_REV for reverse zone
* hostname : fully qualified hostname
* ip_addr : ip address of hostname in string format
* life_time : cached time of this entry by others and not within DNS
* database
* update_type: UPDATE_ADD to add entry, UPDATE_DEL to remove entry
* do_check : DNS_CHECK to check first in DNS, DNS_NOCHECK for no DNS
* checking before update
* del_type : DEL_ONE for deleting one entry, DEL_ALL for deleting all
* entries of the same resource name. Only valid for UPDATE_DEL.
* dns_str : DNS IP address in string format
* Returns:
* -1: error
* 0: success
*
* This function is enhanced to handle the case of NOTAUTH error when DNS server
* is not authoritative for specified zone. In this case we need to resend the
* same request to the higher authoritative domains.
* This is true for both secure and unsecure dynamic DNS updates.
*/
static int
{
int s;
int ret;
int buf_sz;
int level = 0;
char *fqdn;
char *p;
return (0);
return (0);
}
}
return (-1);
id = 0;
(void) close(s);
return (-1);
}
(void) close(s);
return (-1);
}
(void) close(s);
/*
* If it is a NOTAUTH error we should retry with higher domains
* until we get a successful reply
*/
goto retry_higher;
/* check here for update request is successful */
return (-1);
return (0);
}
return (-1);
return (-1);
}
return (-1);
fqdn = ++p;
} else {
"host principal \"%s\" in local keytab file.", hostname);
}
return (ret);
}
/*
* dyndns_add_entry
* Main routine to add an entry into DNS. The attempt will be made on the
* the servers returned by smb_get_nameserver(). Upon a successful
* attempt on any one of the server, the function will exit with 0.
* Otherwise, -1 is retuned to indicate the update attempt on all the
* nameservers has failed.
*
* Parameters:
* update_zone: the type of zone to update, use UPDATE_FORW for forward
* lookup zone, use UPDATE_REV for reverse lookup zone
* hostname : fully qualified hostname
* ip_addr : ip address of hostname in string format
* life_time : cached time of this entry by others and not within DNS
* database
* Returns:
* -1: error
* 0: success
*/
static int
int life_time)
{
const char *dns_str;
char *which_zone;
int i, cnt;
int rc = 0;
return (-1);
}
for (i = 0; i < cnt; i++) {
continue;
"forward" : "reverse";
rc = 1;
break;
}
}
return (rc ? 0 : -1);
}
/*
* dyndns_remove_entry
* Main routine to remove an entry or all entries of the same resource name
* from DNS. The update attempt will be made on the primary DNS server. If
* there is a failure then another attempt will be made on the secondary DNS
* server.
* Parameters:
* update_zone: the type of zone to update, use UPDATE_FORW for forward
* lookup zone, use UPDATE_REV for reverse lookup zone
* hostname : fully qualified hostname
* ip_addr : ip address of hostname in string format
* del_type : DEL_ONE for deleting one entry, DEL_ALL for deleting all
* entries of the same resource name. Only valid for UPDATE_DEL
* Returns:
* -1: error
* 0: success
*/
static int
int del_type)
{
const char *dns_str;
return (-1);
}
scnt = 0;
for (i = 0; i < cnt; i++) {
continue;
if (update_zone == UPDATE_FORW) {
"on forward lookup "
} else {
"entries of %s "
"in forward lookup zone...\n", hostname);
}
} else {
"on reverse lookup "
} else {
"entries of %s "
"in reverse lookup zone...\n", ip_addr);
}
}
scnt++;
break;
}
}
if (scnt)
return (0);
return (-1);
}
/*
* dyndns_update_core
* Perform dynamic update on both forward and reverse lookup zone using
* the specified hostname and IP addresses. Before updating DNS, existing
* host entries with the same hostname in the forward lookup zone are removed
* and existing pointer entries with the same IP addresses in the reverse
* lookup zone are removed. After DNS update, host entries for current
* hostname will show current IP addresses and pointer entries for current
* IP addresses will show current hostname.
* Parameters:
* fqdn - fully-qualified domain name (in lower case)
*
* Returns:
* -1: some dynamic DNS updates errors
* 0: successful or DDNS disabled.
*/
int
{
const char *my_str;
int rc;
return (0);
return (0);
return (-1);
/*
* To comply with RFC 4120 section 6.2.1, the fully-qualified hostname
* must be set to lower case.
*/
error = 0;
forw_update_ok = 0;
/*
* Dummy IP is okay since we are removing all using the hostname.
*/
forw_update_ok = 1;
} else {
error++;
}
return (-1);
do {
continue;
/* first try ipv4, then ipv6 */
error++;
continue;
}
if (forw_update_ok) {
DDNS_TTL);
if (rc == -1)
error++;
}
if (rc == 0) {
DDNS_TTL);
}
if (rc == -1)
error++;
return ((error == 0) ? 0 : -1);
}
/*
* dyndns_clear_rev_zone
* Clear the rev zone records. Must be called to clear the OLD if list
* of down records prior to updating the list with new information.
*
* Parameters:
* fqdn - fully-qualified domain name (in lower case)
* Returns:
* -1: some dynamic DNS updates errors
* 0: successful or DDNS disabled.
*/
int
{
int error;
int rc;
const char *my_str;
return (0);
return (-1);
/*
* To comply with RFC 4120 section 6.2.1, the fully-qualified hostname
* must be set to lower case.
*/
error = 0;
return (-1);
do {
continue;
error++;
continue;
}
if (rc != 0)
error++;
return ((error == 0) ? 0 : -1);
}