DHCP/DNS sync script

Hi all,

I finally found a chance to play with the scripting facilities of my MikroTik box (CRS 125-24G-1S-RM) at home. I took one of the DHCP/DNS scripts from the wiki and enhanced it a bit. I’d love to get some feedback on it!

https://github.com/mmastrac/snippets/blob/master/mikrotik/dhcp-dns.rsc

Some thoughts/bugs about the scripting language for the MikroTik folks from this project:

  • :find returns a weird nil when it can’t find a substring in a string: :typeof [find “abcd” “e”] = “nil”, but [find “abcd” “e”] = nil doesn’t work! Example:
[admin@MikroTik] /ip dns static> :put ([:typeof [:find "abcd" "e"]]!="nil")
false
[admin@MikroTik] /ip dns static> :put ([:typeof [:find "abcd" "e"]]="nil")
true
[admin@MikroTik] /ip dns static> :put ([:find "abcd" "e"]=nil)

[admin@MikroTik] /ip dns static> :put ([:find "abcd" "e"]!=nil)
  • I’d love to have a way to extract text via regexp, versus just matching strings
  • Missing toupper/tolower functions - this could be done easily if there was a command like the unix tr (http://en.wikipedia.org/wiki/Tr_(Unix))
  • I occasionally ran into bugs where an iterator variable from a foreach would become invalid after running a [find] in an unrelated system. I can try to turn this into a repro case.

Overall this was an interesting project to work on, and the scripting facilities on the MikroTik were pretty good.

You did a lot more than enhance it a bit. I attempted some of the features you did, such as rationalising the input hostname from DHCP, but found the limitations of Mikrotik scripting too serious to overcome. Congratulations!

However, I suspect the price is that this script executes many loops inside other loops. Do you find it to be slow on large data sets? I have about 50 hosts to sync. My own code sanitised hostnames by looping through the characters of the hostname and slicing out bad characters. It caused the script runtime to increase from 3 seconds to 15. It also and made it much harder to answer the question “does the DNS entry for server1 match the DHCP record server1\000”? Yes, server1 sends a null character in its hostname to DHCP, and you can’t fix it because it’s a printer with a poor DHCP client. In the end I decided not to try to clean up the inputs.

There we have to disagree. I found the Mikrotik scripting language to be poorly documented and lacking many features I wanted to use. Even printing test output is hard, requiring you to output to the system log to see what’s going on. And don’t get me started on the unhelpful parser - you’ve got an error somewhere? Have fun finding it!

I’ve written my own sync script but I’m not going to put myself through that again.

My version is here:

http://www.tolaris.com/2014/09/27/synchronising-dhcp-and-dns-on-mikrotik-routers/

Thanks! I found it difficult to work with the Mikrotik scripts a lot of the time, but I ended up just pushing through some of the difficult parts. I really wish there was some support for scripts to reference each other through a global scope. I ended up having to pass helper functions as explicit parameters, which seems kind of crazy to me.

However, I suspect the price is that this script executes many loops inside other loops. Do you find it to be slow on large data sets? I have about 50 hosts to sync. My own code sanitised hostnames by looping through the characters of the hostname and slicing out bad characters. It caused the script runtime to increase from 3 seconds to 15. It also and made it much harder to answer the question “does the DNS entry for server1 match the DHCP record server1\000”? Yes, server1 sends a null character in its hostname to DHCP, and you can’t fix it because it’s a printer with a poor DHCP client. In the end I decided not to try to clean up the inputs.

For my site I’ve got 20 DHCP leases. It takes about ~3s to process them all. Note that I only need to process leases that don’t already have the "AUTO " comment prefix, which removes a lot of the work. I didn’t want to re-process the whole world on each scan through. This means that the script can scale pretty far, assuming you don’t have 50-odd leases changing every minute.

[quote=“mmastrac”]
Overall this was an interesting project to work on, and the scripting facilities on the MikroTik were pretty good.
[/quote]

There we have to disagree. I found the Mikrotik scripting language to be poorly documented and lacking many features I wanted to use. Even printing test output is hard, requiring you to output to the system log to see what’s going on. And don’t get me started on the unhelpful parser - you’ve got an error somewhere? Have fun finding it!

Hah yeah, I was trying to be diplomatic. I made judicious use of the logging facilities while developing as well. There are all sorts of crazy edge cases around iterators and things that just make life a huge PITA. The secret to finding parser errors is to SSH in and use the script print facilities. The syntax highlighting disappears around the parse error. Wish I’d discovered that sooner. I also found the built-in script editor pretty late in the game. I’ve been using the Sublime Text plugin.

I’ve written my own sync script but I’m not going to put myself through that again.

My version is here:

http://www.tolaris.com/2014/09/27/synchronising-dhcp-and-dns-on-mikrotik-routers/

Cool. Thanks for the feedback! I think we’d probably have a much easier time of things if we could use Regexps for search/replace on top of just matching.