smbns_dyndns.c revision 7b59d02d2a384be9a08087b14defadd214b3c1dd
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * CDDL HEADER START
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The contents of this file are subject to the terms of the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Common Development and Distribution License (the "License").
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * You may not use this file except in compliance with the License.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * or http://www.opensolaris.org/os/licensing.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * See the License for the specific language governing permissions
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * and limitations under the License.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * When distributing Covered Code, include this CDDL HEADER in each
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * If applicable, add the following below this CDDL HEADER, with the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * fields enclosed by brackets "[]" replaced with your own identifying
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * information: Portions Copyright [yyyy] [name of copyright owner]
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * CDDL HEADER END
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Use is subject to license terms.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#pragma ident "%Z%%M% %I% %E% SMI"
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <assert.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <errno.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <stdio.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <stdlib.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <strings.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <sys/types.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <sys/socket.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <netinet/in.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <arpa/inet.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <sys/time.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <unistd.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <string.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <arpa/nameser.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <resolv.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <netdb.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <rpc/rpc.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <syslog.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <gssapi/gssapi.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <kerberosv5/krb5.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <net/if.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <smbns_dyndns.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/* internal use, in dyndns_add_entry */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#define DEL_NONE 2
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/* Maximum retires if not authoritative */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#define MAX_AUTH_RETRIES 3
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as/* Number of times to retry a DNS query */
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as#define DYNDNS_MAX_QUERY_RETRIES 3
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as/* Timeout value, in seconds, for DNS query responses */
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as#define DYNDNS_QUERY_TIMEOUT 2
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
dc20a3024900c47dd2ee44b9707e6df38f7d62a5asstatic uint16_t dns_msgid;
dc20a3024900c47dd2ee44b9707e6df38f7d62a5asmutex_t dns_msgid_mtx;
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as
dc20a3024900c47dd2ee44b9707e6df38f7d62a5asint
dc20a3024900c47dd2ee44b9707e6df38f7d62a5asdns_msgid_init(void)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as struct __res_state res;
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as bzero(&res, sizeof (struct __res_state));
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as if (res_ninit(&res) < 0)
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as (void) mutex_lock(&dns_msgid_mtx);
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as dns_msgid = res.id;
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as (void) mutex_unlock(&dns_msgid_mtx);
cbfb650a37bf2b1cd913645ee5ab0d1a13ef6246cp res_ndestroy(&res);
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as return (0);
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as}
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as
dc20a3024900c47dd2ee44b9707e6df38f7d62a5asint
dc20a3024900c47dd2ee44b9707e6df38f7d62a5asdns_get_msgid(void)
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as{
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as uint16_t id;
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as (void) mutex_lock(&dns_msgid_mtx);
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as id = ++dns_msgid;
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as (void) mutex_unlock(&dns_msgid_mtx);
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as return (id);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * XXX The following should be removed once head/arpa/nameser_compat.h
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * defines BADSIG, BADKEY, BADTIME macros
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#ifndef BADSIG
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#define BADSIG ns_r_badsig
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#endif /* BADSIG */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#ifndef BADKEY
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#define BADKEY ns_r_badkey
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#endif /* BADKEY */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#ifndef BADTIME
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#define BADTIME ns_r_badtime
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#endif /* BADTIME */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * dyndns_msg_err
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Display error message for DNS error code found in the DNS header in
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * reply message.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Parameters:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * err: DNS errer code
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * None
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwvoid
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwdyndns_msg_err(int err)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw switch (err) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case NOERROR:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case FORMERR:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw syslog(LOG_ERR, "DNS message format error\n");
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case SERVFAIL:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw syslog(LOG_ERR, "DNS server internal error\n");
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case NXDOMAIN:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw syslog(LOG_ERR, "DNS entry should exist but does not exist\n");
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case NOTIMP:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw syslog(LOG_ERR, "DNS opcode not supported\n");
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case REFUSED:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw syslog(LOG_ERR, "DNS operation refused\n");
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case YXDOMAIN:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw syslog(LOG_ERR, "DNS entry shouldn't exist but does exist\n");
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case YXRRSET:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw syslog(LOG_ERR, "DNS RRSet shouldn't exist but does exist\n");
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case NXRRSET:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw syslog(LOG_ERR, "DNS RRSet should exist but does not exist\n");
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case NOTAUTH:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw syslog(LOG_ERR, "DNS server is not authoritative "
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw "for specified zone\n");
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case NOTZONE:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw syslog(LOG_ERR, "Name in Prereq or Update section not "
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw "within specified zone\n");
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case BADSIG:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw syslog(LOG_ERR, "Bad transaction signature (TSIG)");
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case BADKEY:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw syslog(LOG_ERR, "Bad transaction key (TKEY)");
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case BADTIME:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw syslog(LOG_ERR, "Time not synchronized");
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw default:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw syslog(LOG_ERR, "Unknown DNS error\n");
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * display_stat
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Display GSS error message from error code. This routine is used to display
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * the mechanism independent and mechanism specific error messages for GSS
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * routines. The major status error code is the mechanism independent error
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * code and the minor status error code is the mechanism specific error code.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Parameters:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * maj: GSS major status
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * min: GSS minor status
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * None
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwdisplay_stat(OM_uint32 maj, OM_uint32 min)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw gss_buffer_desc msg;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw OM_uint32 msg_ctx = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw OM_uint32 min2;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) gss_display_status(&min2, maj, GSS_C_GSS_CODE, GSS_C_NULL_OID,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw &msg_ctx, &msg);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw syslog(LOG_ERR, "dyndns: GSS major status error: %s\n",
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (char *)msg.value);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) gss_display_status(&min2, min, GSS_C_MECH_CODE, GSS_C_NULL_OID,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw &msg_ctx, &msg);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw syslog(LOG_ERR, "dyndns: GSS minor status error: %s\n",
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (char *)msg.value);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic char *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwdyndns_put_nshort(char *buf, uint16_t val)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint16_t nval;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw nval = htons(val);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) memcpy(buf, &nval, sizeof (uint16_t));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw buf += sizeof (uint16_t);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (buf);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwchar *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwdyndns_get_nshort(char *buf, uint16_t *val)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint16_t nval;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) memcpy(&nval, buf, sizeof (uint16_t));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *val = ntohs(nval);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw buf += sizeof (uint16_t);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (buf);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic char *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwdyndns_put_nlong(char *buf, uint32_t val)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint32_t lval;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw lval = htonl(val);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) memcpy(buf, &lval, sizeof (uint32_t));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw buf += sizeof (uint32_t);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (buf);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic char *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwdyndns_put_byte(char *buf, char val)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *buf = val;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw buf++;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (buf);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic char *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwdyndns_put_int(char *buf, int val)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) memcpy(buf, &val, sizeof (int));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw buf += sizeof (int);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (buf);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwchar *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwdyndns_get_int(char *buf, int *val)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) memcpy(val, buf, sizeof (int));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw buf += sizeof (int);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (buf);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * dyndns_stuff_str
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Converts a domain string by removing periods and replacing with a byte value
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * of how many characters following period. A byte value is placed in front
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * to indicate how many characters before first period. A NULL character is
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * placed at the end. i.e. host.procom.com -> 4host5procom3com0
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Buffer space checking is done by caller.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Parameters:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * ptr : address of pointer to buffer to store converted string
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * zone: domain name string
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * ptr: address of pointer to next available buffer space
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * -1 : error
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * 0 : success
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwdyndns_stuff_str(char **ptr, char *zone)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int len;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw char *lenPtr, *zonePtr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (zonePtr = zone; *zonePtr; ) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw lenPtr = *ptr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *ptr = *ptr + 1;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw len = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw while (*zonePtr != '.' && *zonePtr != 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *ptr = dyndns_put_byte(*ptr, *zonePtr);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw zonePtr++;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw len++;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *lenPtr = len;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (*zonePtr == '.')
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw zonePtr++;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *ptr = dyndns_put_byte(*ptr, 0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * dyndns_build_header
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Build the header for DNS query and DNS update request message.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Parameters:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * ptr : address of pointer to buffer to store header
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * buf_len : buffer length
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * msg_id : message id
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * query_req : use REQ_QUERY for query message or REQ_UPDATE for
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * update message
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * quest_zone_cnt : number of question record for query message or
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * number of zone record for update message
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * ans_prereq_cnt : number of answer record for query message or
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * number of prerequisite record for update message
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * nameser_update_cnt: number of name server for query message or
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * number of update record for update message
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * addit_cnt : number of additional record
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * flags : query flags word
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * ptr: address of pointer to next available buffer space
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * -1 : error
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * 0 : success
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwint
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwdyndns_build_header(char **ptr, int buf_len, uint16_t msg_id, int query_req,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint16_t quest_zone_cnt, uint16_t ans_prereq_cnt,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint16_t nameser_update_cnt, uint16_t addit_cnt, int flags)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint16_t opcode;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (buf_len < 12) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw syslog(LOG_ERR, "dyndns: no more buf for header section\n");
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *ptr = dyndns_put_nshort(*ptr, msg_id); /* mesg ID */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (query_req == REQ_QUERY)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw opcode = ns_o_query; /* query msg */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw else
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw opcode = ns_o_update << 11; /* update msg */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw opcode |= flags;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* mesg opcode */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *ptr = dyndns_put_nshort(*ptr, opcode);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* zone record count */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *ptr = dyndns_put_nshort(*ptr, quest_zone_cnt);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* prerequiste record count */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *ptr = dyndns_put_nshort(*ptr, ans_prereq_cnt);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* update record count */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *ptr = dyndns_put_nshort(*ptr, nameser_update_cnt);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* additional record count */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *ptr = dyndns_put_nshort(*ptr, addit_cnt);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * dyndns_build_quest_zone
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Build the question section for query message or zone section for
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * update message.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Parameters:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * ptr : address of pointer to buffer to store question or zone section
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * buf_len: buffer length
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * name : question or zone name
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * type : type of question or zone
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * class : class of question or zone
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * ptr: address of pointer to next available buffer space
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * -1 : error
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * 0 : success
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwint
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwdyndns_build_quest_zone(char **ptr, int buf_len, char *name, int type,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int class)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw char *zonePtr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((strlen(name) + 6) > buf_len) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw syslog(LOG_ERR, "dyndns: no more buf "
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw "for question/zone section\n");
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw zonePtr = *ptr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) dyndns_stuff_str(&zonePtr, name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *ptr = zonePtr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *ptr = dyndns_put_nshort(*ptr, type);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *ptr = dyndns_put_nshort(*ptr, class);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * dyndns_build_update
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Build update section of update message for adding and removing a record.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * If the ttl value is 0 then this message is for record deletion.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Parameters:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * ptr : address of pointer to buffer to store update section
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * buf_len : buffer length
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * name : resource name of this record
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * type : type of this record
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * class : class of this record
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * ttl : time-to-live, cached time of this entry by others and not
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * within DNS database, a zero value for record(s) deletion
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * data : data of this resource record
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * forw_rev: UPDATE_FORW for forward zone, UPDATE_REV for reverse zone
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * add_del : UPDATE_ADD for adding entry, UPDATE_DEL for removing zone
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * del_type: DEL_ONE for deleting one entry, DEL_ALL for deleting all
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * entries of the same resource name. Only valid for UPDATE_DEL.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * ptr: address of pointer to next available buffer space
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * -1 : error
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * 0 : success
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwdyndns_build_update(char **ptr, int buf_len, char *name, int type, int class,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint32_t ttl, char *data, int forw_rev, int add_del, int del_type)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw char *namePtr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int rec_len, data_len;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rec_len = strlen(name) + 10;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (add_del == UPDATE_ADD) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (forw_rev == UPDATE_FORW)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw data_len = 4;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw else
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw data_len = strlen(data) + 2;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw } else {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (del_type == DEL_ALL)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw data_len = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw else if (forw_rev == UPDATE_FORW)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw data_len = 4;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw else
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw data_len = strlen(data) + 2;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (rec_len + data_len > buf_len) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw syslog(LOG_ERR, "dyndns: no more buf for update section\n");
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw namePtr = *ptr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) dyndns_stuff_str(&namePtr, name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *ptr = namePtr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *ptr = dyndns_put_nshort(*ptr, type);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *ptr = dyndns_put_nshort(*ptr, class);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *ptr = dyndns_put_nlong(*ptr, ttl);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (add_del == UPDATE_DEL && del_type == DEL_ALL) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *ptr = dyndns_put_nshort(*ptr, 0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (forw_rev == UPDATE_FORW) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *ptr = dyndns_put_nshort(*ptr, 4);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *ptr = dyndns_put_int(*ptr, inet_addr(data)); /* ip address */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw } else {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *ptr = dyndns_put_nshort(*ptr, strlen(data)+2);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw namePtr = *ptr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) dyndns_stuff_str(&namePtr, data); /* hostname */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *ptr = namePtr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * dyndns_build_tkey
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Build TKEY section to establish security context for secure dynamic DNS
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * update. DNS header and question sections need to be build before this
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * section. The TKEY data are the tokens generated during security context
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * establishment and the TKEY message is used to transmit those tokens, one
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * at a time, to the DNS server.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Parameters:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * ptr : address of pointer to buffer to store TKEY
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * buf_len : buffer length
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * name : key name, must be unique and same as for TSIG record
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * key_expire: expiration time of this key in second
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * data : TKEY data
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * data_size : data size
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * ptr: address of the pointer to the next available buffer space
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * -1 : error
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * 0 : success
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwdyndns_build_tkey(char **ptr, int buf_len, char *name, int key_expire,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw char *data, int data_size)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw char *namePtr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct timeval tp;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (strlen(name)+2 + 45 + data_size > buf_len) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw syslog(LOG_ERR, "dyndns: no more buf for TKEY record\n");
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw namePtr = *ptr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) dyndns_stuff_str(&namePtr, name); /* unique global name */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *ptr = namePtr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *ptr = dyndns_put_nshort(*ptr, ns_t_tkey);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *ptr = dyndns_put_nshort(*ptr, ns_c_any);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *ptr = dyndns_put_nlong(*ptr, 0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* 19 + 14 + data_size + 2 */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *ptr = dyndns_put_nshort(*ptr, 35 + data_size);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw namePtr = *ptr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) dyndns_stuff_str(&namePtr, "gss.microsoft.com");
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *ptr = namePtr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) gettimeofday(&tp, 0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *ptr = dyndns_put_nlong(*ptr, tp.tv_sec); /* inception */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* expiration, 86400 */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *ptr = dyndns_put_nlong(*ptr, tp.tv_sec + key_expire);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *ptr = dyndns_put_nshort(*ptr, MODE_GSS_API); /* mode: gss-api */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *ptr = dyndns_put_nshort(*ptr, 0); /* error */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *ptr = dyndns_put_nshort(*ptr, data_size); /* key size */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) memcpy(*ptr, data, data_size); /* key data */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *ptr += data_size;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *ptr = dyndns_put_nshort(*ptr, 0); /* other */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * dyndns_build_tsig
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Build TSIG section for secure dynamic DNS update. This routine will be
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * called twice. First called with TSIG_UNSIGNED, and second with TSIG_SIGNED.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The TSIG data is NULL and ignored for TSIG_UNSIGNED and is the update request
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * message encrypted for TSIG_SIGNED. The message id must be the same id as the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * one in the update request before it is encrypted.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Parameters:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * ptr : address of pointer to buffer to store TSIG
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * buf_len : buffer length
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * msg_id : message id
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * name : key name, must be the same as in TKEY record
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * fudge_time : amount of error time allow in seconds
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * data : TSIG data if TSIG_SIGNED, otherwise NULL
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * data_size : size of data, otherwise 0 if data is NULL
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * data_signed: TSIG_SIGNED to indicate data is signed and encrypted,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * otherwise TSIG_UNSIGNED
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * ptr: address of pointer to next available buffer space
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * -1 : error
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * 0 : success
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwdyndns_build_tsig(char **ptr, int buf_len, int msg_id, char *name,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int fudge_time, char *data, int data_size, int data_signed)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw char *namePtr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct timeval tp;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int signtime, fudge, rec_len;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (data_signed == TSIG_UNSIGNED)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rec_len = strlen(name)+2 + 37;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw else
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rec_len = strlen(name)+2 + 45 + data_size;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (rec_len > buf_len) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw syslog(LOG_ERR, "dyndns: no more buf for TSIG record\n");
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw namePtr = *ptr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) dyndns_stuff_str(&namePtr, name); /* unique global name */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *ptr = namePtr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (data_signed == TSIG_SIGNED)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *ptr = dyndns_put_nshort(*ptr, ns_t_tsig);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *ptr = dyndns_put_nshort(*ptr, ns_c_any);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *ptr = dyndns_put_nlong(*ptr, 0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (data_signed == TSIG_SIGNED) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* 19 + 10 + data_size + 6 */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *ptr = dyndns_put_nshort(*ptr, 35 + data_size);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw namePtr = *ptr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) dyndns_stuff_str(&namePtr, "gss.microsoft.com");
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *ptr = namePtr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) gettimeofday(&tp, 0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw signtime = tp.tv_sec >> 16;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *ptr = dyndns_put_nlong(*ptr, signtime); /* sign time */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw fudge = tp.tv_sec << 16;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw fudge |= fudge_time;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *ptr = dyndns_put_nlong(*ptr, fudge); /* fudge time */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (data_signed == TSIG_SIGNED) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* signed data size */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *ptr = dyndns_put_nshort(*ptr, data_size);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) memcpy(*ptr, data, data_size); /* signed data */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *ptr += data_size;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *ptr = dyndns_put_nshort(*ptr, msg_id); /* original id */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *ptr = dyndns_put_nshort(*ptr, 0); /* error */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *ptr = dyndns_put_nshort(*ptr, 0); /* other */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * dyndns_open_init_socket
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * This routine creates a SOCK_STREAM or SOCK_DGRAM socket and initializes it
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * by doing bind() and setting linger option to off.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Parameters:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * sock_type: SOCK_STREAM for TCP or SOCK_DGRAM for UDP
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * dest_addr: destination address in network byte order
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * port : destination port number
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * descriptor: descriptor referencing the created socket
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * -1 : error
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwint
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwdyndns_open_init_socket(int sock_type, unsigned long dest_addr, int port)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int s;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct sockaddr_in my_addr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct linger l;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct sockaddr_in serv_addr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((s = socket(AF_INET, sock_type, 0)) == -1) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw syslog(LOG_ERR, "dyndns: socket err\n");
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw l.l_onoff = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (setsockopt(s, SOL_SOCKET, SO_LINGER,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (char *)&l, sizeof (l)) == -1) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw syslog(LOG_ERR, "dyndns: setsocket err\n");
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) close(s);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw bzero(&my_addr, sizeof (my_addr));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw my_addr.sin_family = AF_INET;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw my_addr.sin_port = htons(0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (bind(s, (struct sockaddr *)&my_addr, sizeof (my_addr)) < 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw syslog(LOG_ERR, "dyndns: client bind err\n");
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) close(s);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw serv_addr.sin_family = AF_INET;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw serv_addr.sin_port = htons(port);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw serv_addr.sin_addr.s_addr = dest_addr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (connect(s, (struct sockaddr *)&serv_addr,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw sizeof (struct sockaddr_in)) < 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw syslog(LOG_ERR, "dyndns: client connect err (%s)\n",
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw strerror(errno));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) close(s);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (s);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * dyndns_build_tkey_msg
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * This routine is used to build the TKEY message to transmit GSS tokens
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * during GSS security context establishment for secure DNS update. The
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * TKEY message format uses the DNS query message format. The TKEY section
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * is the answer section of the query message format.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Microsoft uses a value of 86400 seconds (24 hours) for key expiration time.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Parameters:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * buf : buffer to build and store TKEY message
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * key_name: a unique key name, this same key name must be also be used in
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * the TSIG message
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * out_tok : TKEY message data (GSS tokens)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * id : message id of this TKEY message
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * message size: the size of the TKEY message
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * -1 : error
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwdyndns_build_tkey_msg(char *buf, char *key_name, uint16_t *id,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw gss_buffer_desc *out_tok)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int queryReq, zoneCount, preqCount, updateCount, additionalCount;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int zoneType, zoneClass;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw char *bufptr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw queryReq = REQ_QUERY;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* query section of query request */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw zoneCount = 1;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* answer section of query request */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw preqCount = 1;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw updateCount = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw additionalCount = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) memset(buf, 0, MAX_TCP_SIZE);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw bufptr = buf;
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as *id = dns_get_msgid();
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* add TCP length info that follows this field */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw bufptr = dyndns_put_nshort(bufptr,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw 26 + (strlen(key_name)+2)*2 + 35 + out_tok->length);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (dyndns_build_header(&bufptr, BUFLEN_TCP(bufptr, buf), *id, queryReq,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw zoneCount, preqCount, updateCount, additionalCount, 0) == -1) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw zoneType = ns_t_tkey;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw zoneClass = ns_c_in;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (dyndns_build_quest_zone(&bufptr, BUFLEN_TCP(bufptr, buf), key_name,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw zoneType, zoneClass) == -1) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (dyndns_build_tkey(&bufptr, BUFLEN_TCP(bufptr, buf), key_name,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw 86400, out_tok->value, out_tok->length) == -1) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (bufptr - buf);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * dyndns_establish_sec_ctx
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * This routine is used to establish a security context with the DNS server
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * by building TKEY messages and sending them to the DNS server. TKEY messages
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * are also received from the DNS server for processing. The security context
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * establishment is done with the GSS client on the system producing a token
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * and sending the token within the TKEY message to the GSS server on the DNS
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * server. The GSS server then processes the token and then send a TKEY reply
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * message with a new token to be processed by the GSS client. The GSS client
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * processes the new token and then generates a new token to be sent to the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * GSS server. This cycle is continued until the security establishment is
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * done. TCP is used to send and receive TKEY messages.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Parameters:
55bf511df53aad0fdb7eb3fa349f0308cc05234cas * cred_handle : handle to credential
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * s : socket descriptor to DNS server
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * key_name : TKEY key name
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * dns_hostname: fully qualified DNS hostname
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * oid : contains Kerberos 5 object identifier
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * gss_context : handle to security context
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int
55bf511df53aad0fdb7eb3fa349f0308cc05234casdyndns_establish_sec_ctx(gss_ctx_id_t *gss_context, gss_cred_id_t cred_handle,
55bf511df53aad0fdb7eb3fa349f0308cc05234cas int s, char *key_name, char *dns_hostname, gss_OID oid)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint16_t id, rid, rsz;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw char buf[MAX_TCP_SIZE], buf2[MAX_TCP_SIZE];
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int ret;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw char *service_name, *tmpptr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int service_sz;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw OM_uint32 min, maj, time_rec;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw gss_buffer_desc service_buf, in_tok, out_tok;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw gss_name_t target_name;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw gss_buffer_desc *inputptr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int gss_flags;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw OM_uint32 ret_flags;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int buf_sz;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw service_sz = strlen(dns_hostname) + 5;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw service_name = (char *)malloc(sizeof (char) * service_sz);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (service_name == NULL) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw syslog(LOG_ERR, "Malloc failed for %d bytes ", service_sz);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) snprintf(service_name, service_sz, "DNS@%s", dns_hostname);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw service_buf.value = service_name;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw service_buf.length = strlen(service_name)+1;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((maj = gss_import_name(&min, &service_buf,
55bf511df53aad0fdb7eb3fa349f0308cc05234cas GSS_C_NT_HOSTBASED_SERVICE, &target_name)) != GSS_S_COMPLETE) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw display_stat(maj, min);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) free(service_name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) free(service_name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw inputptr = GSS_C_NO_BUFFER;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *gss_context = GSS_C_NO_CONTEXT;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw gss_flags = GSS_C_MUTUAL_FLAG | GSS_C_DELEG_FLAG | GSS_C_REPLAY_FLAG |
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw GSS_C_SEQUENCE_FLAG | GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw do {
55bf511df53aad0fdb7eb3fa349f0308cc05234cas maj = gss_init_sec_context(&min, cred_handle, gss_context,
55bf511df53aad0fdb7eb3fa349f0308cc05234cas target_name, oid, gss_flags, 0, NULL, inputptr, NULL,
55bf511df53aad0fdb7eb3fa349f0308cc05234cas &out_tok, &ret_flags, &time_rec);
55bf511df53aad0fdb7eb3fa349f0308cc05234cas
55bf511df53aad0fdb7eb3fa349f0308cc05234cas if (maj != GSS_S_COMPLETE && maj != GSS_S_CONTINUE_NEEDED) {
55bf511df53aad0fdb7eb3fa349f0308cc05234cas assert(gss_context);
55bf511df53aad0fdb7eb3fa349f0308cc05234cas if (*gss_context != GSS_C_NO_CONTEXT)
55bf511df53aad0fdb7eb3fa349f0308cc05234cas (void) gss_delete_sec_context(&min,
55bf511df53aad0fdb7eb3fa349f0308cc05234cas gss_context, NULL);
55bf511df53aad0fdb7eb3fa349f0308cc05234cas
55bf511df53aad0fdb7eb3fa349f0308cc05234cas display_stat(maj, min);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) gss_release_name(&min, &target_name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((maj == GSS_S_COMPLETE) &&
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw !(ret_flags & GSS_C_REPLAY_FLAG)) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw syslog(LOG_ERR, "dyndns: No GSS_C_REPLAY_FLAG\n");
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (out_tok.length > 0)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) gss_release_buffer(&min, &out_tok);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) gss_release_name(&min, &target_name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((maj == GSS_S_COMPLETE) &&
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw !(ret_flags & GSS_C_MUTUAL_FLAG)) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw syslog(LOG_ERR, "dyndns: No GSS_C_MUTUAL_FLAG\n");
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (out_tok.length > 0)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) gss_release_buffer(&min, &out_tok);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) gss_release_name(&min, &target_name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (out_tok.length > 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((buf_sz = dyndns_build_tkey_msg(buf, key_name,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw &id, &out_tok)) <= 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) gss_release_buffer(&min, &out_tok);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) gss_release_name(&min, &target_name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) gss_release_buffer(&min, &out_tok);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (send(s, buf, buf_sz, 0) == -1) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw syslog(LOG_ERR, "dyndns: TKEY send error\n");
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) gss_release_name(&min, &target_name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw bzero(buf2, MAX_TCP_SIZE);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (recv(s, buf2, MAX_TCP_SIZE, 0) == -1) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw syslog(LOG_ERR, "dyndns: TKEY "
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw "reply recv error\n");
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) gss_release_name(&min, &target_name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ret = buf2[5] & 0xf; /* error field in TCP */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (ret != NOERROR) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw syslog(LOG_ERR, "dyndns: Error in "
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw "TKEY reply: %d: ", ret);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw dyndns_msg_err(ret);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) gss_release_name(&min, &target_name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw tmpptr = &buf2[2];
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) dyndns_get_nshort(tmpptr, &rid);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (id != rid) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) gss_release_name(&min, &target_name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw tmpptr = &buf2[59+(strlen(key_name)+2)*2];
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) dyndns_get_nshort(tmpptr, &rsz);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw in_tok.length = rsz;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* bsd38 -> 2*7=14 */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw in_tok.value = &buf2[61+(strlen(key_name)+2)*2];
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw inputptr = &in_tok;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw } while (maj != GSS_S_COMPLETE);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) gss_release_name(&min, &target_name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * dyndns_get_sec_context
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Get security context for secure dynamic DNS update. This routine opens
55bf511df53aad0fdb7eb3fa349f0308cc05234cas * a TCP socket to the DNS server and establishes a security context with
55bf511df53aad0fdb7eb3fa349f0308cc05234cas * the DNS server using host principal to perform secure dynamic DNS update.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Parameters:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * hostname: fully qualified hostname
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * dns_ip : ip address of hostname in network byte order
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * gss_handle: gss credential handle
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * gss_context: gss security context
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * -1: error
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * 0: success
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic gss_ctx_id_t
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwdyndns_get_sec_context(const char *hostname, int dns_ip)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int s;
55bf511df53aad0fdb7eb3fa349f0308cc05234cas gss_cred_id_t cred_handle;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw gss_ctx_id_t gss_context;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw gss_OID oid;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct hostent *hentry;
55bf511df53aad0fdb7eb3fa349f0308cc05234cas char *key_name, dns_hostname[MAXHOSTNAMELEN];
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
55bf511df53aad0fdb7eb3fa349f0308cc05234cas cred_handle = GSS_C_NO_CREDENTIAL;
55bf511df53aad0fdb7eb3fa349f0308cc05234cas oid = GSS_C_NO_OID;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw key_name = (char *)hostname;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw hentry = gethostbyaddr((char *)&dns_ip, 4, AF_INET);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (hentry == NULL) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw syslog(LOG_ERR, "dyndns: Can't get DNS "
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw "hostname from DNS ip.\n");
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (NULL);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) strcpy(dns_hostname, hentry->h_name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((s = dyndns_open_init_socket(SOCK_STREAM, dns_ip, 53)) < 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (NULL);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
55bf511df53aad0fdb7eb3fa349f0308cc05234cas if (dyndns_establish_sec_ctx(&gss_context, cred_handle, s, key_name,
55bf511df53aad0fdb7eb3fa349f0308cc05234cas dns_hostname, oid))
55bf511df53aad0fdb7eb3fa349f0308cc05234cas gss_context = NULL;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) close(s);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (gss_context);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * dyndns_build_add_remove_msg
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * This routine builds the update request message for adding and removing DNS
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * entries which is used for non-secure and secure DNS update.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * This routine builds an UDP message.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Parameters:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * buf : buffer to build message
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * update_zone: the type of zone to update, use UPDATE_FORW for forward
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * lookup zone, use UPDATE_REV for reverse lookup zone
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * hostname : fully qualified hostname to update DNS with
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * ip_addr : IP address of hostname
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * life_time : cached time of this entry by others and not within DNS
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * database
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * update_type: UPDATE_ADD to add entry, UPDATE_DEL to remove entry
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * del_type : DEL_ONE for deleting one entry, DEL_ALL for deleting all
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * entries of the same resource name. Only valid for UPDATE_DEL.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * addit_cnt : Indicate how many record is in the additional section of
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * the DNS message. A value of zero is always used with
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * non-secure update message. For secure update message,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * the value will be one because the signed TSIG message
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * is added as the additional record of the DNS update message.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * id : DNS message ID. If a positive value then this ID value is
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * used, otherwise the next incremented value is used
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * level : This is the domain level which we send the request to, level
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * zero is the default level, it can go upto 2 in reverse zone
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * and virtually to any level in forward zone.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * buf : buffer containing update message
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * id : DNS message ID
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * int : size of update message
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * -1 : error
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * This function is changed to handle dynamic DNS update retires to higher
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * authoritative domains.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwdyndns_build_add_remove_msg(char *buf, int update_zone, const char *hostname,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw const char *ip_addr, int life_time, int update_type, int del_type,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int addit_cnt, uint16_t *id, int level)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int a, b, c, d;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw char *bufptr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int queryReq, zoneCount, preqCount, updateCount, additionalCount;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw char *zone, *resource, *data, zone_buf[100], resrc_buf[100];
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int zoneType, zoneClass, type, class, ttl;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw char *p;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw queryReq = REQ_UPDATE;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw zoneCount = 1;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw preqCount = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw updateCount = 1;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw additionalCount = addit_cnt;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) memset(buf, 0, NS_PACKETSZ);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw bufptr = buf;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (*id == 0)
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as *id = dns_get_msgid();
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (dyndns_build_header(&bufptr, BUFLEN_UDP(bufptr, buf), *id, queryReq,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw zoneCount, preqCount, updateCount, additionalCount, 0) == -1) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw zoneType = ns_t_soa;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw zoneClass = ns_c_in;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (update_zone == UPDATE_FORW) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw p = (char *)hostname;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Try higher domains according to the level requested */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw do {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* domain */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((zone = (char *)strchr(p, '.')) == NULL)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw zone += 1;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw p = zone;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw } while (--level >= 0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw resource = (char *)hostname;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw data = (char *)ip_addr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw } else {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) sscanf(ip_addr, "%d.%d.%d.%d", &a, &b, &c, &d);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) sprintf(zone_buf, "%d.%d.%d.in-addr.arpa", c, b, a);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw zone = p = zone_buf;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Try higher domains according to the level requested */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw while (--level >= 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* domain */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((zone = (char *)strchr(p, '.')) == NULL) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw zone += 1;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw p = zone;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) sprintf(resrc_buf, "%d.%d.%d.%d.in-addr.arpa",
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw d, c, b, a);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw resource = resrc_buf; /* ip info */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw data = (char *)hostname;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (dyndns_build_quest_zone(&bufptr, BUFLEN_UDP(bufptr, buf), zone,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw zoneType, zoneClass) == -1) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (update_zone == UPDATE_FORW)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw type = ns_t_a;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw else
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw type = ns_t_ptr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (update_type == UPDATE_ADD) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw class = ns_c_in;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ttl = life_time;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw } else {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (del_type == DEL_ONE)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw class = ns_c_none; /* remove one */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw else
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw class = ns_c_any; /* remove all */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ttl = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (dyndns_build_update(&bufptr, BUFLEN_UDP(bufptr, buf),
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw resource, type, class, ttl, data, update_zone,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw update_type, del_type) == -1) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (bufptr - buf);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * dyndns_build_unsigned_tsig_msg
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * This routine is used to build the unsigned TSIG message for signing. The
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * unsigned TSIG message contains the update request message with certain TSIG
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * fields included. An error time of 300 seconds is used for fudge time. This
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * is the number used by Microsoft clients.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * This routine builds a UDP message.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Parameters:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * buf : buffer to build message
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * update_zone: the type of zone to update, use UPDATE_FORW for forward
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * lookup zone, use UPDATE_REV for reverse lookup zone
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * hostname : fully qualified hostname to update DNS with
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * ip_addr : IP address of hostname
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * life_time : cached time of this entry by others and not within DNS
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * database
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * update_type: UPDATE_ADD to add entry, UPDATE_DEL to remove entry
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * del_type : DEL_ONE for deleting one entry, DEL_ALL for deleting all
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * entries of the same resource name. Only valid for UPDATE_DEL.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * key_name : same key name used in TKEY message
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * id : DNS message ID. If a positive value then this ID value is
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * used, otherwise the next incremented value is used
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * level : This is the domain level which we send the request to, level
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * zero is the default level, it can go upto 2 in reverse zone
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * and virtually to any level in forward zone.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * buf : buffer containing update message
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * id : DNS message ID
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * int : size of update message
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * -1 : error
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwdyndns_build_unsigned_tsig_msg(char *buf, int update_zone, const char *hostname,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw const char *ip_addr, int life_time, int update_type, int del_type,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw char *key_name, uint16_t *id, int level)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw char *bufptr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int buf_sz;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((buf_sz = dyndns_build_add_remove_msg(buf, update_zone, hostname,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ip_addr, life_time, update_type, del_type, 0, id, level)) <= 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw bufptr = buf + buf_sz;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (dyndns_build_tsig(&bufptr, BUFLEN_UDP(bufptr, buf), 0,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw key_name, 300, NULL, 0, TSIG_UNSIGNED) == -1) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (bufptr - buf);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * dyndns_build_signed_tsig_msg
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * This routine build the signed TSIG message which contains the update
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * request message encrypted. An error time of 300 seconds is used for fudge
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * time. This is the number used by Microsoft clients.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * This routine builds a UDP message.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Parameters:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * buf : buffer to build message
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * update_zone: the type of zone to update, use UPDATE_FORW for forward
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * lookup zone, use UPDATE_REV for reverse lookup zone
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * hostname : fully qualified hostname to update DNS with
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * ip_addr : IP address of hostname
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * life_time : cached time of this entry by others and not within DNS
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * database
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * update_type: UPDATE_ADD to add entry, UPDATE_DEL to remove entry
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * del_type : DEL_ONE for deleting one entry, DEL_ALL for deleting all
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * entries of the same resource name. Only valid for UPDATE_DEL.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * key_name : same key name used in TKEY message
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * id : DNS message ID. If a positive value then this ID value is
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * used, otherwise the next incremented value is used
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * in_mic : the update request message encrypted
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * level : This is the domain level which we send the request to, level
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * zero is the default level, it can go upto 2 in reverse zone
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * and virtually to any level in forward zone.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * buf : buffer containing update message
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * id : DNS message ID
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * int : size of update message
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * -1 : error
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwdyndns_build_signed_tsig_msg(char *buf, int update_zone, const char *hostname,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw const char *ip_addr, int life_time, int update_type, int del_type,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw char *key_name, uint16_t *id, gss_buffer_desc *in_mic, int level)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw char *bufptr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int buf_sz;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((buf_sz = dyndns_build_add_remove_msg(buf, update_zone, hostname,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ip_addr, life_time, update_type, del_type, 1, id, level)) <= 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw bufptr = buf + buf_sz;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (dyndns_build_tsig(&bufptr, BUFLEN_UDP(bufptr, buf),
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *id, key_name, 300, in_mic->value,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw in_mic->length, TSIG_SIGNED) == -1) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (bufptr - buf);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * dyndns_udp_send_recv
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as * This routine sends and receives UDP DNS request and reply messages.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Pre-condition: Caller must call dyndns_open_init_socket() before calling
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * this function.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Parameters:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * s : socket descriptor
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * buf : buffer containing data to send
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * buf_sz : size of data to send
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * -1 : error
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * rec_buf: reply dat
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * 0 : success
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwint
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwdyndns_udp_send_recv(int s, char *buf, int buf_sz, char *rec_buf)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as int i, retval, addr_len;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct timeval tv, timeout;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw fd_set rfds;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct sockaddr_in from_addr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw timeout.tv_usec = 0;
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as timeout.tv_sec = DYNDNS_QUERY_TIMEOUT;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as for (i = 0; i <= DYNDNS_MAX_QUERY_RETRIES; i++) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (send(s, buf, buf_sz, 0) == -1) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw syslog(LOG_ERR, "dyndns: UDP send error (%s)\n",
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw strerror(errno));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw FD_ZERO(&rfds);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw FD_SET(s, &rfds);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw tv = timeout;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw retval = select(s+1, &rfds, NULL, NULL, &tv);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (retval == -1) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw } else if (retval > 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw bzero(rec_buf, NS_PACKETSZ);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* required by recvfrom */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw addr_len = sizeof (struct sockaddr_in);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (recvfrom(s, rec_buf, NS_PACKETSZ, 0,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (struct sockaddr *)&from_addr, &addr_len) == -1) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw syslog(LOG_ERR, "dyndns: UDP recv err\n");
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as /* did not receive anything */
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as if (i == (DYNDNS_MAX_QUERY_RETRIES + 1)) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw syslog(LOG_ERR, "dyndns: max retries for UDP recv reached\n");
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * dyndns_sec_add_remove_entry
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Perform secure dynamic DNS update after getting security context.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * This routine opens a UDP socket to the DNS sever, gets the security context,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * builds the unsigned TSIG message and signed TSIG message. The signed TSIG
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * message containing the encrypted update request message is sent to the DNS
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * server. The response is received and check for error. If there is no
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * error then credential handle and security context are released and the local
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * NSS cached is purged.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Parameters:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * update_zone : UPDATE_FORW for forward zone, UPDATE_REV for reverse zone
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * hostname : fully qualified hostname
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * ip_addr : ip address of hostname in string format
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * life_time : cached time of this entry by others and not within DNS
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * database
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * max_retries : maximum retries for sending DNS update request
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * recv_timeout: receive timeout
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * update_type : UPDATE_ADD for adding entry, UPDATE_DEL for removing entry
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * del_type : DEL_ONE for deleting one entry, DEL_ALL for deleting all
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * entries of the same resource name. Only valid for UPDATE_DEL
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * dns_str : DNS IP address in string format
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * -1: error
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * 0: success
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * This function is enhanced to handle the case of NOTAUTH error when DNS server
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * is not authoritative for specified zone. In this case we need to resend the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * same request to the higher authoritative domains.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * This is true for both secure and unsecure dynamic DNS updates.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwdyndns_sec_add_remove_entry(int update_zone, const char *hostname,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw const char *ip_addr, int life_time, int update_type, int del_type,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw char *dns_str)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int s2;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint16_t id, rid;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw char buf[NS_PACKETSZ], buf2[NS_PACKETSZ];
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int ret;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw OM_uint32 min, maj;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw gss_buffer_desc in_mic, out_mic;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw gss_ctx_id_t gss_context;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int dns_ip;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw char *key_name;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int buf_sz;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int level = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw assert(dns_str);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw assert(*dns_str);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw dns_ip = inet_addr(dns_str);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwsec_retry_higher:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((gss_context = dyndns_get_sec_context(hostname,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw dns_ip)) == NULL) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw key_name = (char *)hostname;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((s2 = dyndns_open_init_socket(SOCK_DGRAM, dns_ip, 53)) < 0) {
55bf511df53aad0fdb7eb3fa349f0308cc05234cas if (gss_context != GSS_C_NO_CONTEXT)
55bf511df53aad0fdb7eb3fa349f0308cc05234cas (void) gss_delete_sec_context(&min, &gss_context, NULL);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw id = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((buf_sz = dyndns_build_unsigned_tsig_msg(buf, update_zone, hostname,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ip_addr, life_time, update_type, del_type,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw key_name, &id, level)) <= 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) close(s2);
55bf511df53aad0fdb7eb3fa349f0308cc05234cas if (gss_context != GSS_C_NO_CONTEXT)
55bf511df53aad0fdb7eb3fa349f0308cc05234cas (void) gss_delete_sec_context(&min, &gss_context, NULL);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw in_mic.length = buf_sz;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw in_mic.value = buf;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* sign update message */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((maj = gss_get_mic(&min, gss_context, 0, &in_mic, &out_mic)) !=
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw GSS_S_COMPLETE) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw display_stat(maj, min);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) close(s2);
55bf511df53aad0fdb7eb3fa349f0308cc05234cas if (gss_context != GSS_C_NO_CONTEXT)
55bf511df53aad0fdb7eb3fa349f0308cc05234cas (void) gss_delete_sec_context(&min, &gss_context, NULL);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((buf_sz = dyndns_build_signed_tsig_msg(buf, update_zone, hostname,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ip_addr, life_time, update_type, del_type, key_name, &id,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw &out_mic, level)) <= 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) close(s2);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) gss_release_buffer(&min, &out_mic);
55bf511df53aad0fdb7eb3fa349f0308cc05234cas if (gss_context != GSS_C_NO_CONTEXT)
55bf511df53aad0fdb7eb3fa349f0308cc05234cas (void) gss_delete_sec_context(&min, &gss_context, NULL);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) gss_release_buffer(&min, &out_mic);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (dyndns_udp_send_recv(s2, buf, buf_sz, buf2)) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) close(s2);
55bf511df53aad0fdb7eb3fa349f0308cc05234cas if (gss_context != GSS_C_NO_CONTEXT)
55bf511df53aad0fdb7eb3fa349f0308cc05234cas (void) gss_delete_sec_context(&min, &gss_context, NULL);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) close(s2);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
55bf511df53aad0fdb7eb3fa349f0308cc05234cas if (gss_context != GSS_C_NO_CONTEXT)
55bf511df53aad0fdb7eb3fa349f0308cc05234cas (void) gss_delete_sec_context(&min, &gss_context, NULL);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ret = buf2[3] & 0xf; /* error field in UDP */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * If it is a NOTAUTH error we should retry with higher domains
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * until we get a successful reply or the maximum retries is met.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (ret == NOTAUTH && level++ < MAX_AUTH_RETRIES)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw goto sec_retry_higher;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* check here for update request is successful */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (ret != NOERROR) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw syslog(LOG_ERR, "dyndns: Error in TSIG reply: %d: ", ret);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw dyndns_msg_err(ret);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) dyndns_get_nshort(buf2, &rid);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (id != rid)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * dyndns_seach_entry
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Query DNS server for entry. This routine can indicate if an entry exist
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * or not during forward or reverse lookup. Also can indicate if the data
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * of the entry matched. For example, for forward lookup, the entry is
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * searched using the hostname and the data is the IP address. For reverse
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * lookup, the entry is searched using the IP address and the data is the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * hostname.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Parameters:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * update_zone: UPDATE_FORW for forward zone, UPDATE_REV for reverse zone
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * hostname : fully qualified hostname
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * ip_addr : ip address of hostname in string format
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * update_type: UPDATE_ADD for adding entry, UPDATE_DEL for removing entry
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * time_out: no use
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * is_match: is 1 for found matching entry, otherwise 0
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * 1 : an entry exist but not necessarily match
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * 0 : an entry does not exist
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*ARGSUSED*/
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwdyndns_search_entry(int update_zone, const char *hostname, const char *ip_addr,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int update_type, struct timeval *time_out, int *is_match)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct hostent *hentry;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct in_addr in;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw in_addr_t ip;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int i;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *is_match = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (update_zone == UPDATE_FORW) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw hentry = gethostbyname(hostname);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (hentry) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ip = inet_addr(ip_addr);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (i = 0; hentry->h_addr_list[i]; i++) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) memcpy(&in.s_addr,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw hentry->h_addr_list[i], sizeof (in.s_addr));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (ip == in.s_addr) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *is_match = 1;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw } else {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int dns_ip = inet_addr(ip_addr);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw hentry = gethostbyaddr((char *)&dns_ip, 4, AF_INET);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (hentry) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (strncasecmp(hentry->h_name, hostname,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw strlen(hostname)) == 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *is_match = 1;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* entry does not exist */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * dyndns_add_remove_entry
55bf511df53aad0fdb7eb3fa349f0308cc05234cas * Perform non-secure dynamic DNS update. If it fails and the system is in
55bf511df53aad0fdb7eb3fa349f0308cc05234cas * domain mode, secure update will be performed.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * This routine opens a UDP socket to the DNS sever, build the update request
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * message, and sends the message to the DNS server. The response is received
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * and check for error. If there is no error then the local NSS cached is
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * purged. DNS may be used to check to see if an entry already exist before
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * adding or to see if an entry does exist before removing it. Adding
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * duplicate entries or removing non-existing entries does not cause any
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * problems. DNS is not check when doing a delete all.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Parameters:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * update_zone: UPDATE_FORW for forward zone, UPDATE_REV for reverse zone
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * hostname : fully qualified hostname
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * ip_addr : ip address of hostname in string format
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * life_time : cached time of this entry by others and not within DNS
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * database
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * update_type: UPDATE_ADD to add entry, UPDATE_DEL to remove entry
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * do_check : DNS_CHECK to check first in DNS, DNS_NOCHECK for no DNS
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * checking before update
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * del_type : DEL_ONE for deleting one entry, DEL_ALL for deleting all
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * entries of the same resource name. Only valid for UPDATE_DEL.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * dns_str : DNS IP address in string format
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * -1: error
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * 0: success
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * This function is enhanced to handle the case of NOTAUTH error when DNS server
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * is not authoritative for specified zone. In this case we need to resend the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * same request to the higher authoritative domains.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * This is true for both secure and unsecure dynamic DNS updates.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwdyndns_add_remove_entry(int update_zone, const char *hostname,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw const char *ip_addr, int life_time, int update_type,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int do_check, int del_type, char *dns_str)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int s;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint16_t id, rid;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw char buf[NS_PACKETSZ], buf2[NS_PACKETSZ];
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int ret, dns_ip;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int is_exist, is_match;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct timeval timeout;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int buf_sz;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int level = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw assert(dns_str);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw assert(*dns_str);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw dns_ip = inet_addr(dns_str);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (do_check == DNS_CHECK && del_type != DEL_ALL) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw is_exist = dyndns_search_entry(update_zone, hostname, ip_addr,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw update_type, &timeout, &is_match);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (update_type == UPDATE_ADD && is_exist && is_match) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw } else if (update_type == UPDATE_DEL && !is_exist) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwretry_higher:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((s = dyndns_open_init_socket(SOCK_DGRAM, dns_ip, 53)) < 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw id = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((buf_sz = dyndns_build_add_remove_msg(buf, update_zone, hostname,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ip_addr, life_time, update_type, del_type, 0, &id, level)) <= 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) close(s);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (dyndns_udp_send_recv(s, buf, buf_sz, buf2)) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) close(s);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) close(s);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ret = buf2[3] & 0xf; /* error field in UDP */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * If it is a NOTAUTH error we should retry with higher domains
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * until we get a successful reply
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (ret == NOTAUTH && level++ < MAX_AUTH_RETRIES)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw goto retry_higher;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* check here for update request is successful */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (ret == NOERROR) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) dyndns_get_nshort(buf2, &rid);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (id != rid)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (ret == NOTIMP) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw syslog(LOG_ERR, "dyndns: DNS does not "
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw "support dynamic update\n");
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw } else if (ret == NOTAUTH) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw syslog(LOG_ERR, "dyndns: DNS is not authoritative for "
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw "zone name in zone section\n");
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as if (smb_config_get_secmode() == SMB_SECMODE_DOMAIN)
55bf511df53aad0fdb7eb3fa349f0308cc05234cas ret = dyndns_sec_add_remove_entry(update_zone, hostname,
55bf511df53aad0fdb7eb3fa349f0308cc05234cas ip_addr, life_time, update_type, del_type, dns_str);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (ret);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * dyndns_add_entry
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Main routine to add an entry into DNS. The attempt will be made on the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * the servers returned by smb_get_nameserver(). Upon a successful
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * attempt on any one of the server, the function will exit with 0.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Otherwise, -1 is retuned to indicate the update attempt on all the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * nameservers has failed.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Parameters:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * update_zone: the type of zone to update, use UPDATE_FORW for forward
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * lookup zone, use UPDATE_REV for reverse lookup zone
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * hostname : fully qualified hostname
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * ip_addr : ip address of hostname in string format
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * life_time : cached time of this entry by others and not within DNS
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * database
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * -1: error
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * 0: success
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwdyndns_add_entry(int update_zone, const char *hostname, const char *ip_addr,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int life_time)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw char *dns_str;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct in_addr ns_list[MAXNS];
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int i, cnt;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int addr, rc = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (hostname == NULL || ip_addr == NULL) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw addr = (int)inet_addr(ip_addr);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((addr == -1) || (addr == 0)) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw cnt = smb_get_nameservers(ns_list, MAXNS);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (i = 0; i < cnt; i++) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw dns_str = inet_ntoa(ns_list[i]);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((dns_str == NULL) ||
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (strcmp(dns_str, "0.0.0.0") == 0)) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw continue;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (update_zone == UPDATE_FORW) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw syslog(LOG_DEBUG, "Dynamic update on forward lookup "
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw "zone for %s (%s)...\n", hostname, ip_addr);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw } else {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw syslog(LOG_DEBUG, "Dynamic update on reverse lookup "
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw "zone for %s (%s)...\n", hostname, ip_addr);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (dyndns_add_remove_entry(update_zone, hostname,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ip_addr, life_time,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw UPDATE_ADD, DNS_NOCHECK, DEL_NONE, dns_str) != -1) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = 1;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (rc ? 0 : -1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * dyndns_remove_entry
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Main routine to remove an entry or all entries of the same resource name
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * from DNS. The update attempt will be made on the primary DNS server. If
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * there is a failure then another attempt will be made on the secondary DNS
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * server.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Parameters:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * update_zone: the type of zone to update, use UPDATE_FORW for forward
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * lookup zone, use UPDATE_REV for reverse lookup zone
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * hostname : fully qualified hostname
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * ip_addr : ip address of hostname in string format
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * del_type : DEL_ONE for deleting one entry, DEL_ALL for deleting all
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * entries of the same resource name. Only valid for UPDATE_DEL
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * -1: error
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * 0: success
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwdyndns_remove_entry(int update_zone, const char *hostname, const char *ip_addr,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int del_type)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw char *dns_str;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct in_addr ns_list[MAXNS];
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int i, cnt, scnt;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int addr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((hostname == NULL || ip_addr == NULL)) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw addr = (int)inet_addr(ip_addr);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((addr == -1) || (addr == 0)) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw cnt = smb_get_nameservers(ns_list, MAXNS);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw scnt = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (i = 0; i < cnt; i++) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw dns_str = inet_ntoa(ns_list[i]);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((dns_str == NULL) ||
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (strcmp(dns_str, "0.0.0.0") == 0)) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw continue;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (update_zone == UPDATE_FORW) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (del_type == DEL_ONE) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw syslog(LOG_DEBUG, "Dynamic update "
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw "on forward lookup "
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw "zone for %s (%s)...\n", hostname, ip_addr);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw } else {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw syslog(LOG_DEBUG, "Removing all "
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw "entries of %s "
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw "in forward lookup zone...\n", hostname);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw } else {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (del_type == DEL_ONE) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw syslog(LOG_DEBUG, "Dynamic update "
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw "on reverse lookup "
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw "zone for %s (%s)...\n", hostname, ip_addr);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw } else {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw syslog(LOG_DEBUG, "Removing all "
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw "entries of %s "
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw "in reverse lookup zone...\n", ip_addr);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (dyndns_add_remove_entry(update_zone, hostname, ip_addr, 0,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw UPDATE_DEL, DNS_NOCHECK, del_type, dns_str) != -1) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw scnt++;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (scnt)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * dyndns_update
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Perform dynamic update on both forward and reverse lookup zone using
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * current hostname and IP addresses. Before updating DNS, existing host
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * entries with the same hostname in the forward lookup zone are removed
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * and existing pointer entries with the same IP addresses in the reverse
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * lookup zone are removed. After DNS update, host entries for current
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * hostname will show current IP addresses and pointer entries for current
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * IP addresses will show current hostname.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Parameters:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * None
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * -1: some dynamic DNS updates errors
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * 0: successful
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwint
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwdyndns_update(void)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
7b59d02d2a384be9a08087b14defadd214b3c1ddjb int forw_update_ok, error;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw char fqdn[MAXHOSTNAMELEN];
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw char *my_ip;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct in_addr addr;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb smb_niciter_t ni;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int rc;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as if (!smb_config_getbool(SMB_CI_DYNDNS_ENABLE))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (smb_getfqhostname(fqdn, MAXHOSTNAMELEN) != 0)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw error = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw forw_update_ok = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Dummy IP is okay since we are removing all using the hostname.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (dyndns_remove_entry(UPDATE_FORW, fqdn, "1.1.1.1", DEL_ALL) == 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw forw_update_ok = 1;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw } else {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw error++;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
7b59d02d2a384be9a08087b14defadd214b3c1ddjb if (smb_nic_getfirst(&ni) != 0)
7b59d02d2a384be9a08087b14defadd214b3c1ddjb return (-1);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjb do {
7b59d02d2a384be9a08087b14defadd214b3c1ddjb if (ni.ni_nic.nic_sysflags & (IFF_STANDBY | IFF_PRIVATE))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw continue;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
7b59d02d2a384be9a08087b14defadd214b3c1ddjb addr.s_addr = ni.ni_nic.nic_ip;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw my_ip = (char *)strdup(inet_ntoa(addr));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (my_ip == NULL) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw error++;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw continue;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (forw_update_ok) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = dyndns_add_entry(UPDATE_FORW, fqdn, my_ip,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw DDNS_TTL);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (rc == -1)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw error++;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = dyndns_remove_entry(UPDATE_REV, fqdn, my_ip, DEL_ALL);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (rc == 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = dyndns_add_entry(UPDATE_REV, fqdn, my_ip,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw DDNS_TTL);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (rc == -1)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw error++;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) free(my_ip);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb } while (smb_nic_getnext(&ni) == 0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return ((error == 0) ? 0 : -1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * dyndns_clear_rev_zone
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Clear the rev zone records. Must be called to clear the OLD if list
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * of down records prior to updating the list with new information.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Parameters:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * None
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * -1: some dynamic DNS updates errors
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * 0: successful
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwint
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwdyndns_clear_rev_zone(void)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
7b59d02d2a384be9a08087b14defadd214b3c1ddjb int error;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw char fqdn[MAXHOSTNAMELEN];
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw char *my_ip;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct in_addr addr;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb smb_niciter_t ni;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int rc;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as if (!smb_config_getbool(SMB_CI_DYNDNS_ENABLE))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (smb_getfqhostname(fqdn, MAXHOSTNAMELEN) != 0)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw error = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
7b59d02d2a384be9a08087b14defadd214b3c1ddjb if (smb_nic_getfirst(&ni) != 0)
7b59d02d2a384be9a08087b14defadd214b3c1ddjb return (-1);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjb do {
7b59d02d2a384be9a08087b14defadd214b3c1ddjb if (ni.ni_nic.nic_sysflags & (IFF_STANDBY | IFF_PRIVATE))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw continue;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
7b59d02d2a384be9a08087b14defadd214b3c1ddjb addr.s_addr = ni.ni_nic.nic_ip;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw my_ip = (char *)strdup(inet_ntoa(addr));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (my_ip == NULL) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw error++;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw continue;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = dyndns_remove_entry(UPDATE_REV, fqdn, my_ip, DEL_ALL);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (rc != 0)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw error++;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) free(my_ip);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb } while (smb_nic_getnext(&ni) == 0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return ((error == 0) ? 0 : -1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}