Skip to content

Instantly share code, notes, and snippets.

@benosman
Forked from SmartFinn/dhcp-leases-to-dns.rsc
Last active September 19, 2022 12:44
Show Gist options
  • Save benosman/1acb61b61b9b2742e3e727003cd7ef4a to your computer and use it in GitHub Desktop.
Save benosman/1acb61b61b9b2742e3e727003cd7ef4a to your computer and use it in GitHub Desktop.
MikroTik (RouterOS) script for automatically setting DNS records for clients when they obtain a DHCP lease
# MikroTik (RouterOS) script for automatically setting DNS records
# for clients when they obtain a DHCP lease.
#
# authors:
# SmartFinn <https://gist.github.com/SmartFinn>
# elevendroids <https://gist.github.com/elevendroids>
:local dnsTTL "00:15:00";
:local token "$leaseServerName-$leaseActMAC";
:local LogPrefix "[dhcp2dns]($leaseServerName | $leaseActMAC)"
# Normalize hostname (e.g. "-= My Phone =-" -> "my-phone")
# - convert to lowercase
# - truncate length to 63 chars
# - substitute disallowed chars with a hyphen
# param: name
:local normalizeHostname do={
:local result;
:local isInvalidChar true;
:local lower "abcdefghijklmnopqrstuvwxyz";
:local upper "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
:for i from=0 to=([:len $name]-1) do={
:local char [:pick $name $i];
:if ($i < 63) do={
:if ($char~"[a-zA-Z0-9]") do={
:local pos [ :find $upper $char ];
:if ($pos > -1) do={ :set char [ :pick $lower $pos ] };
:set result ($result . $char);
:set isInvalidChar false;
} else={
:if (!$isInvalidChar) do={
:set result ($result . "-");
:set isInvalidChar true;
};
};
};
};
# delete trailing hyphen
:if ($isInvalidChar) do={
:set result [:pick $result 0 ([:len $result]-1)];
}
:return $result;
};
:if ($leaseBound = 1) do={
# Getting the hostname and delete all disallowed chars from it
:local hostName $"lease-hostname";
:local macName;
:set hostName [$normalizeHostname name=$hostName];
:set macName [$normalizeHostname name=$leaseActMAC];
# Use MAC address as a hostname if the hostname is missing or contains only
# disallowed chars
:if ([:len $hostName] = 0) do={
:set hostName $macName;
};
# Getting the domain name from DHCP server. If a domain name is not
# specified will use hostname only
/ip dhcp-server network {
:local domainName [get [:pick [find $leaseActIP in address] 0] domain];
:if ([:len $domainName] > 0) do={
# Append domain name to the hostname and macname
:set hostName ($hostName . "." . $domainName);
:set macName ($macName . "." . $domainName);
};
};
:do {
/ip dns static {
:local entry [ find name=$hostName ]
:if ( $entry ) do={
:if ([ get $entry comment ] = $token) do={
:log warning "$LogPrefix: Updating existing entry for $hostName"
set $entry address=$leaseActIP ttl=$dnsTTL comment=$token
} else={
:log warning "$LogPrefix: Conflicting entry for $hostName already exists, using mac address fallback"
:local macEntry [ find name=$macName ]
:if ( $macEntry ) do={
:if ([ get $macEntry comment ] = $token) do={
:log warning "$LogPrefix: Updating existing entry for $macName"
set $macEntry address=$leaseActIP ttl=$dnsTTL comment=$token
} else={
:log warning "$LogPrefix: Conflicting entry for $macName already exists, skipping"
}
} else={
:log info "$LogPrefix: Adding entry for $macName"
add name=$macName address=$leaseActIP ttl=$dnsTTL comment=$token;
}
}
} else={
:log info "$LogPrefix: Adding entry for $hostName"
add name=$hostName address=$leaseActIP ttl=$dnsTTL comment=$token;
}
}
} on-error={
:log error "Fail to add DNS entry: $hostName -> $leaseActIP ($leaseActMAC)";
};
} else={
/ip dns static remove [find comment=$token];
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment