DHCP server DNS update

Hi

I’ve written a script to update dns when dhcp server issues a lease.

It consists of 3 parts:

  • script executed by dhcp server
  • two additional script used for mapping of the host name: conversion to lower case and replacement of forbidden characters

The two auxiliary scripts should be loaded on system level, preferably by scheduler on start-up.

:global mapHostName do={
# param: name
# max length = 63
# allowed chars a-z,0-9,-
	:local allowedChars "abcdefghijklmnopqrstuvwxyz0123456789-";
	:local numChars [:len $name];
	:if ($numChars > 63) do={:set numChars 63};
	:local result "";
	:for i from=0 to=($numChars - 1) do={
		:local char [:pick $name $i];
		:if ([:find $allowedChars $char] < 0) do={:set char "-"};
		:set result ($result . $char);
	}
	:return $result;
}

:global lowerCase do={
# param: entry
	:local lower "abcdefghijklmnopqrstuvwxyz";
	:local upper "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
	:local result "";
	:for i from=0 to=([:len $entry] - 1) do={
		:local char [:pick $entry $i];
		:local pos [:find $upper $char];
		:if ($pos > -1) do={:set char [:pick $lower $pos]};
		:set result ($result . $char);
	}
	:return $result;
}

The dhcp server script needs to associated with the server definition. Do replace your home domain name with your value:

{
:global lowerCase;
:global mapHostName;

:local parent ".your.domain.com";
:do {
	:if ([/ip dhcp-server lease get value-name=dynamic [find mac-address=$leaseActMAC]]) do={
		:if ($leaseBound = 1) do={
			:local host [/ip dhcp-server lease get value-name=host-name [find mac-address=$leaseActMAC ]];
			:if ([:len $host] = 0) do={:error "Error: no hostname for $leaseActMAC"};
			:set host [$lowerCase entry=$host];
			:set host [$mapHostName name=$host];
			:local fqdn ($host . $parent);
			:do {
				/ip dns static remove [find address=$leaseActIP];
				/ip dns static add address=$leaseActIP name=$fqdn;
			} on-error={:log error message="Failure during dns registration of $fqdn with $leaseActIP"}
		} else={
			/ip dns static remove [find address=$leaseActIP];
		}
	}
} on-error={:log error message="Look-up by MAC failed: $leaseActMAC"}
}

Additional note: the script only manages dynamic leases. For lease which are made static/fixed, dns should be managed manually.

If you wish to keep it simple and in one location place the auxiliary scripts in the dhcp server script and replace “:global xxxxx” by “:local xxxxx”. This will make these scripts private for dhcp script only.

Cheers

Updated:

  • take care of corner case “no/emtpy hostname for mac”
  • clean-up preexisting assignment

Thanks for the script.

How does this script handle host that already has an DNS name? Does it over write the old name or keep the old name?
Also I would like to set every host static at the same time as the DNS is given, would that be possible?

Since it’s dhcp initiated, it’s working on that basis: for existing dns entry with a different ip, it won’t touch it. But you could adjust it if you wish?
For same ip, it will clean-up first.


Regarding conversion to static, it’s probably possible, but I haven’t looked into it.

Update on the dhcp server script

{

# :log info message="leaseBound=$leaseBound, leaseServerName=$leaseServerName, leaseActMAC=$leaseActMAC, leaseActIP=$leaseActIP, lease-hostname=$"lease-hostname"";
:global lowerCase;
:global mapHostName;

# on de-assignment the lease data is already gone (currently) so fqdn is the only way to determine if it's a dynamic assignment
# if parent is reserved for dynamic entries, removal can happen "blindly", see below
:local parent ".dyn.home";

:local host $"lease-hostname";
:if ([:len $host] = 0) do={:error "Error: no hostname for $leaseActMAC"};
:set host [$lowerCase entry=$host];
:set host [$mapHostName name=$host];
:local fqdn ($host . $parent);

:if ($leaseBound = 1) do={
	:do {
		:if ([/ip dhcp-server lease get value-name=dynamic [find mac-address=$leaseActMAC]]) do={
			:log info message="dhcp server: $leaseActMAC -> $host"
			:do {
				/ip dns static add address=$leaseActIP name=$fqdn ttl=10m;
			} on-error={:log error message="Failure during dns registration of $fqdn with $leaseActIP"}
		}
	} on-error={:error "Look-up by MAC failed: $leaseActMAC"}
} else={
	/ip dns static remove [find address=$leaseActIP name=$fqdn];
}
}

With that some changes:

  • script is using $“lease-hostname” which is undocumented at this time, but wiki will be updated at some point
  • on de-assignment the lease data is already gone (on v6.44) so fqdn is the only way to determine if it’s a dynamic assignment
    ** with domain reserved for dynamic entries only, dns entry removal on dhcp lease removal can be done blindly and safely
  • “overwrite” will generate an error in logs and will stop the script, but if static and dynamic configuration is isolated, as explained above, this should not happen

Thanks for this script.

Quick question - is there any advantage to running this from the script call aka

/system script run DhcpToDns

vs having the whole code in the server script area?

Things all good in 6.47?