Example #1
0
        /// <summary>
        /// Removes a <see cref="DynDnsHostEntry" /> registration from the Dynamic
        /// DNS cluster.
        /// </summary>
        /// <param name="hostEntry">The host/IP address <see cref="DynDnsHostEntry" /> to be unregistered.</param>
        /// <remarks>
        /// <note>
        /// This method does not throw an exception if the registration is not present.
        /// </note>
        /// </remarks>
        /// <exception cref="InvalidOperationException">Thrown if the client has not been started.</exception>
        public void Unregister(DynDnsHostEntry hostEntry)
        {
            using (TimedLock.Lock(syncLock))
            {
                if (hosts.ContainsKey(hostEntry))
                {
                    // For UDP mode, we need to send two immediate Unregister message to each DNS
                    // server for the host entry.

                    if (settings.Mode == DynDnsMode.Udp && isOpen)
                    {
                        for (int i = 0; i < 2; i++)
                        {
                            DynDnsMessage message;
                            byte[]        packet;

                            message = new DynDnsMessage(DynDnsMessageFlag.OpUnregister, hostEntry);
                            packet  = message.ToArray(settings.SharedKey);

                            foreach (var nameServer in settings.NameServers)
                            {
                                socket.SendTo(packet, nameServer);
                            }
                        }
                    }

                    // Remove the host entry from the local table.

                    hosts.Remove(hostEntry);
                    Register();
                }
            }
        }
Example #2
0
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="flags">Specifies the operation to be performed in addition to operation related options.</param>
 /// <param name="hostEntry">The host entry information.</param>
 public DynDnsMessage(DynDnsMessageFlag flags, DynDnsHostEntry hostEntry)
 {
     this.TimeStampUtc = DateTime.UtcNow;
     this.Version      = FormatVer;
     this.Flags        = flags;
     this.HostEntry    = hostEntry;
 }
Example #3
0
        /// <summary>
        /// Decrypts and deserializes a message from a byte buffer.
        /// </summary>
        /// <param name="buffer">The buffer.</param>
        /// <param name="sharedKey">The shared encryption key.</param>
        /// <exception cref="FormatException">Thrown if the buffer does not contain a valid message.</exception>
        public DynDnsMessage(byte[] buffer, SymmetricKey sharedKey)
        {
            try
            {
                using (var ms = new EnhancedMemoryStream(Crypto.Decrypt(buffer, sharedKey)))
                {
                    if (ms.ReadInt32Le() != Magic)
                    {
                        throw new Exception();
                    }

                    this.Version = ms.ReadByte();
                    if (this.Version < FormatVer)
                    {
                        throw new FormatException(string.Format("DynDnsMessage version [{0}] is not supported.", this.Version));
                    }

                    this.TimeStampUtc = new DateTime(ms.ReadInt64Le());
                    this.Flags        = (DynDnsMessageFlag)ms.ReadInt32Le();
                    this.HostEntry    = new DynDnsHostEntry(ms.ReadString16());
                }
            }
            catch (Exception e)
            {
                throw new FormatException("Invalid Dynamic DNS message.", e);
            }
        }
Example #4
0
 /// <summary>
 /// Registers a <see cref="DynDnsHostEntry" /> with the Dynamic DNS cluster.
 /// </summary>
 /// <param name="hostEntry">The host/IP address <see cref="DynDnsHostEntry" /> to be registered.</param>
 /// <remarks>
 /// <note>
 /// This method does not throw an exception if the registration is already registered.
 /// </note>
 /// </remarks>
 /// <exception cref="InvalidOperationException">Thrown if the client has not been started.</exception>
 public void Register(DynDnsHostEntry hostEntry)
 {
     using (TimedLock.Lock(syncLock))
     {
         if (!hosts.ContainsKey(hostEntry))
         {
             hosts[hostEntry] = hostEntry;
             Register();
         }
     }
 }
Example #5
0
        /// <summary>
        /// Returns a copy of the <see cref="DynDnsHostEntry" /> registrations currently
        /// exposed to the Dynamic DNS cluster.
        /// </summary>
        /// <returns>A <see cref="DynDnsHostEntry" /> array listing the current registrations.</returns>
        /// <exception cref="InvalidOperationException">Thrown if the client has not been started.</exception>
        public DynDnsHostEntry[] GetHostRegistrations()
        {
            using (TimedLock.Lock(syncLock))
            {
                var list = new DynDnsHostEntry[hosts.Count];
                int i;

                i = 0;
                foreach (DynDnsHostEntry hostEntry in hosts.Values)
                {
                    list[i++] = hostEntry;
                }

                return(list);
            }
        }
Example #6
0
        /// <summary>
        /// Loads DNS client settings from a configuration section.
        /// </summary>
        /// <param name="keyPrefix">The configuration section key prefix (or <c>null</c>).</param>
        /// <remarks>
        /// <para>
        /// The settings will loaded are:
        /// </para>
        /// <div class="tablediv">
        /// <table class="dtTABLE" cellspacing="0" ID="Table1">
        /// <tr valign="top">
        /// <th width="1">Setting</th>
        /// <th width="1">Default</th>
        /// <th width="90%">Description</th>
        /// </tr>
        /// <tr valign="top">
        ///     <td>Enabled</td>
        ///     <td>true</td>
        ///     <td>
        ///     Indicates whether the dynamic DNS client should be enabled.
        ///     </td>
        /// </tr>
        /// <tr valign="top">
        ///     <td>NetworkBinding</td>
        ///     <td>ANY</td>
        ///     <td>
        ///     Specifies the <see cref="NetworkBinding" /> the DNS client
        ///     should use for sending UDP host registration messages to the
        ///     DNS servers.
        ///     </td>
        /// </tr>
        /// <tr valign="top">
        ///     <td>Mode</td>
        ///     <td>Cluster</td>
        ///     <td>
        ///     Controls how the client registers hosts with the DNS server.  The possible values
        ///     are <see cref="DynDnsMode.Udp" /> or <see cref="DynDnsMode.Cluster"/>.
        ///     <see cref="DynDnsMode.Both" /> is not allowed for DNS clients.
        ///     </td>
        /// </tr>
        /// <tr valign="top">
        ///     <td>SharedKey</td>
        ///     <td>(see note)</td>
        ///     <td>
        ///     Shared symmetric encryption key used to decrypt UDP registration messages
        ///     sent by DNS clients while in <see cref="DynDnsMode.Udp" /> mode.  This
        ///     key must match the shared key configured for the client.  This defaults
        ///     to a reasonable value.
        ///     </td>
        /// </tr>
        /// <tr valign="top">
        ///     <td>Domain</td>
        ///     <td>(see note)</td>
        ///     <td>
        ///     <para>
        ///     Specifies the name server domain for the name server.  If this is
        ///     specified, the DNS client will periodically query DNS for the NS
        ///     records for the domain and then use the IP addresses to send UDP
        ///     host registration messages to the servers.
        ///     </para>
        ///     <para>
        ///     This setting must be formatted as a network binding with a host name
        ///     and port, such as <b>LILLTEK.NET:DYNAMIC-DNS</b>.
        ///     </para>
        ///     <note>
        ///     One of <b>Domain</b> or <b>NameServer</b> must be specified when when <b>Mode=UDP</b>.
        ///     If both settings are present, then <b>Domain</b> will be used.
        ///     </note>
        ///     </td>
        /// </tr>
        /// <tr valign="top">
        ///     <td>NameServer[#]</td>
        ///     <td>(see note)</td>
        ///     <td>
        ///     <para>
        ///     Specifies the network bindings for the DNS servers for the delivery
        ///     of UDP host registration messages.  These entries may include
        ///     IP addresses or host names, but note that host name lookups are
        ///     performed only once by the server, when it starts.
        ///     </para>
        ///     <note>
        ///     One of <b>Domain</b> or <b>NameServer</b> must be specified when when <b>Mode=UDP</b>.
        ///     If both settings are present, then <b>Domain</b> will be used.
        ///     </note>
        ///     </td>
        /// </tr>
        /// <tr valign="top">
        ///     <td>BkInterval</td>
        ///     <td>1s</td>
        ///     <td>
        ///     Minimum interval for which background activities will be scheduled.
        ///     </td>
        /// </tr>
        /// <tr valign="top">
        ///     <td>DomainRefreshInterval</td>
        ///     <td>15m</td>
        ///     <td>
        ///     Interval at which DNS NS queries will be performed to refresh the list of
        ///     name servers for the specified <b>Domain</b>.
        ///     </td>
        /// </tr>
        /// <tr valign="top">
        ///     <td>UdpRegisterInterval</td>
        ///     <td>60s</td>
        ///     <td>
        ///     Interval at which UDP host registration messages will be sent to the
        ///     DNS servers when operating in <b>Mode=UDP</b>.
        ///     </td>
        /// </tr>
        /// <tr valign="top">
        ///     <td>Host[#]</td>
        ///     <td>(optional)</td>
        ///     <td>
        ///     <para>
        ///     The set of static host entries to be returned by the DNS server.  These
        ///     entries are formatted as:
        ///     </para>
        ///     <code lang="none">
        ///     &lt;host name&gt; "," &lt;ip or cname&gt; [ "," &lt;TTL&gt; [ "," &lt;host-mode&gt; [ ";" "NAT" ] ] ]
        ///     </code>
        ///     <para>
        ///     where <b>host name</b> is the DNS name being registered, <b>ip</b> or <b>cname</b>
        ///     specifies the IP address or CNAME reference to the host, <b>TTL</b> is the optional
        ///     time-to-live (TTL) to use for the entry in seconds, and <b>host-mode</b> is the optional
        ///     host entry mode, one of <b>ADDRESS</b>, <b>ADDRESSLIST</b>, or <b>CNAME</b>.
        ///     </para>
        ///     <para>
        ///     The <b>TTL</b> value defaults to -1 seconds (indicating that the server's default TTL
        ///     will be used) and the <b>host-mode</b> defaults to <b>ADDRESS</b> for IP addresses or
        ///     <b>CNAME</b> for CNAME references. You can also set <b>TTL=-1</b> to use the DNS server
        ///     default for this.
        ///     </para>
        ///     <note>
        ///     A host mode of <b>ADDRESS</b> or <b>ADDRESSLIST</b> can only be specified for IP
        ///     addresses and <b>CNAME</b> can only be specified for CNAME entries.
        ///     </note>
        ///     </td>
        /// </tr>
        /// <tr valign="top">
        ///     <td>Cluster</td>
        ///     <td>(see note)</td>
        ///     <td>
        ///     <b>Cluster</b> is a subsection in the configuration that
        ///     that specifies the settings required to establish a cooperative
        ///     cluster with the Dynamic DNS instances on the network while operating
        ///     in CLUSTER mode.  The client uses the <see cref="ClusterMember" /> class
        ///     to perform the work necessary to join the cluster.  The <b>ClusterBaseEP</b>
        ///     setting is required.
        ///     </td>
        /// </tr>
        /// </table>
        /// </div>
        /// </remarks>
        public DynDnsClientSettings(string keyPrefix)
        {
            Config config = new Config(keyPrefix);

            string[] list;
            List <DynDnsHostEntry> registrations;
            List <NetworkBinding>  bindings;

            list          = config.GetArray("Host");
            registrations = new List <DynDnsHostEntry>(list.Length);

            for (int i = 0; i < list.Length; i++)
            {
                try
                {
                    registrations.Add(DynDnsHostEntry.Parse(list[i]));
                }
                catch
                {
                    SysLog.LogWarning("DynamicDnsClient: Error parsing host registration [{0}Host[{1}]={2}].", config.KeyPrefix, i, list[i]);
                }
            }

            this.Hosts = registrations.ToArray();

            list     = config.GetArray("NameServer");
            bindings = new List <NetworkBinding>(list.Length);

            for (int i = 0; i < list.Length; i++)
            {
                try
                {
                    bindings.Add(new NetworkBinding((list[i])));
                }
                catch
                {
                    SysLog.LogWarning("DynamicDnsClient: Error parsing name server binding [{0}NameServer[{1}]={2}].", config.KeyPrefix, i, list[i]);
                }
            }

            this.NameServers = bindings.ToArray();

            this.Enabled = config.Get("Enabled", this.Enabled);

            if (this.Enabled)
            {
                this.NetworkBinding        = config.Get("NetworkBinding", this.NetworkBinding);
                this.Mode                  = config.Get <DynDnsMode>("Mode", this.Mode);
                this.SharedKey             = new SymmetricKey(config.Get("SharedKey", "aes:BcskocQ2W4aIGEemkPsy5dhAxuWllweKLVToK1NoYzg=:5UUVxRPml8L4WH82unR74A=="));
                this.Domain                = config.Get("Domain", this.Domain);
                this.BkInterval            = config.Get("BkInterval", this.BkInterval);
                this.DomainRefreshInterval = config.Get("DomainRefreshInterval", this.DomainRefreshInterval);
                this.UdpRegisterInterval   = config.Get("UdpRegisterInterval", this.UdpRegisterInterval);

                if (this.Mode == DynDnsMode.Cluster)
                {
                    this.Cluster = ClusterMemberSettings.LoadConfig(config.KeyPrefix + "Cluster");
                }

                if (this.Mode == DynDnsMode.Both)
                {
                    throw new FormatException("DynamicDnsClient: [Mode=BOTH] is not supported.");
                }

                if (this.Mode == DynDnsMode.Udp && this.Domain.IsAny && this.NameServers.Length == 0)
                {
                    throw new FormatException("DynDnsClient: One of DOMAIN or NAMESERVER[#] must be specified when [Mode=UDP].");
                }
            }
        }