DHCP Client Script when provider renews lease

My provider renews the lease every 2 days.
I get these entries in log:

May/16/2020 16:05:05 dhcp,critical,error dhcp-client on ether1 lost IP address 44.33.22.11 - received NAK from dhcp server 10.20.30.40
May/16/2020 16:05:05 dhcp,info dhcp-client on ether1 got IP address 44.33.22.11

My script in the script section of DHCP client does not work.

#check DHCP-lease for ether1
:if ([/ip dhcp-client get [find interface=“ether1”] status] = “bound”) do={
/system script run refreshdyndns
:log info “DHCP lease ready”
}

The script ‘refreshdyndns’ itself runs OK in a scheduled task or started manually.

What does the script have to look like for it to work?

hello friend, try this script

:if ( [/ping 8.8.8.8 interface= “ETHERT 1” count=6 ] = 0) do={/ip dhcp-client release numbers=0}




ETHERT 1 = WAN

My client script is
“:if ($bound=1) do={ /ip route set [find commen
t="WANNAME"] gateway=($"gateway-address") disabled=no; :log warning
_("New ISP1 gateway: ".($"gateway-address")) }”

With add default distance route of 255.

I use recursive IP route settings…

The problem is that the variables accessible inside the script are not the same ones you can see using /ip dhcp-client print detail - very confusing.

So your script has to look as follows:

:if ($bound=1) do={
  /system script run refreshdyndns
  :log info "DHCP lease ready"
}

Well sindy!

I modified the script to:
:if ($bound=1) do={
:log info “DHCP lease ready”
/system script run refreshdyndns
}

and now I get the log entry after getting the IP

May/16/2020 16:05:05 dhcp,critical,error dhcp-client on ether1 lost IP address 44.33.22.11 - received NAK from dhcp server 10.20.30.40
May/16/2020 16:05:05 dhcp,info dhcp-client on ether1 got IP address 44.33.22.11
DHCP lease ready

But the script is not running, there are no log entries.
Attached the script refreshdyndns:

DynDNS refresh

:local ddnsbase “sub01.DOMAIN.TLD”
:local hostsarray {
{“sub01.DOMAIN.TLD”;“DOMAIN.TLD-id01”;“pwd”};
{“sub02.DOMAIN.TLD”;“DOMAIN.TLD-id02”;“pwd”};
{“sub03.DOMAIN.TLD”;“DOMAIN.TLD-id03”;“pwd”};
{“sub04.DOMAIN.TLD”;“DOMAIN.TLD-id04”;“pwd”}
}
:local ddnshost
:local ddnsuser
:local ddnspass
:local theinterface “ether1”
:local msghd “DynDNS:”
:local emailaddressRT “log@DOMAIN.TLD”

:local ipddns [:resolve $ddnsbase]
:local ipfresh [/ip address get [/ip address find interface=$theinterface] address]
:if ([ :typeof $ipfresh ] = nil ) do={
:log info (“$msghd NO IP address on $theinterface”)
} else={
:set ipfresh [:pick $ipfresh 0 [:find $ipfresh “/”]]

#CHECK new<>old IP
:if ($ipddns != $ipfresh) do={
:foreach hstarr in=$hostsarray do={
:set ddnshost [($hstarr->0)]
:set ddnsuser [($hstarr->1)]
:set ddnspass [($hstarr->2)]
:log info (“$msghd $ddnshost DNSRECORDIP=$ipddns INTERFACE $theinterface CURRENTIP=$ipfresh UPDATING $ddnshost->$ipfresh”)
:local srcpath “nic/update?system=dyndns&hostname=$ddnshost&myip=$ipfresh”

/tool fetch address=www.PROVIDER.com host=www.PROVIDER.com src-path=$srcpath mode=https user=$ddnsuser password=$ddnspass dst-path=(“/DynDNS.$ddnshost”)
:delay 1

:local result [/file get “DynDNS.$ddnshost” contents]
:log info “$msghd PROVIDER response: $result”

:local firstword [:pick $result 0 5]
:if ($firstword = “good “) do={
:log info “$msghd SUCCESS”
} else={
:if ($firstword = “nochg”) do={
:log info “$msghd NOCHANGE”
/tool e-mail send to=”$emailaddressRT” subject=“$msghd FAILED IP $ipfresh” body=“an error occured”
} else={
:log info “$msghd FAILED”
}
}

:local ipddns $ipfresh
:log info “$msghd $ddnshost DNS RECORD = $ipfresh”
}
} else={
#EXIT when IP did not change
:log info “$msghd IP $ipfresh checked OK”
}
}

When IP doesnt change, script runs until position “#CHECK new<>old IP”
and finishes at position “#EXIT when IP did not change”

Have I missed something in the srcipt?

I cannot see anything wrong in the script, nor can Mikrotik’s syntax check, but that says nothing about runtime issues. The way to go is to log about every step on the path which does not work, to see whether the foreach works at all and what are the actual values of the variables.

As the refreshdyndns script gets spawned by the DHCP client’s one, the issue must be in the refreshdyndns one. But it may behave different when spawned by the DHCP client script due to different environment - you have to debug. To speed up the debugging, it might make sense to run your own DHCP-server with a short lease time, and a test client - each of them linked to a dedicated Ethernet interface. Disabling and re-enabling the WAN is another way to speed up the process.

sindy,
the script has an error at the function-call
:local ipddns [:resolve $ddnsbase]
and doesn’t finish.
I set some log entrees right before and after this function.
Didn’t know, the script environment acts like this.

Are there any documentations about the environ and the hidden variables available?

I do not see anything wrong with that call. Perhaps it’s a race condition because resolving is not yet available?
You can try to catch runtime error:

:local ipddns;
:do {
  :set ipddns [:resolve $ddnsbase];
} on-error={
  :log warning "Resolving failed.";
}

Or try to wait…

:local ipddns "";
:while ($ipddns = "") do={
  :do {
    :set ipddns [:resolve $ddnsbase];
  } on-error={
    :log warning "Resolving failed.";
    :delay 1s;
  }
}

Untested… But something like this should work. :sunglasses:

I placed a delay on the very begining of the whole code.

But what I also checked are the policy settings.
Setting all of them except dude and the script runs OK.

The policy settings are not easy to understand!?!
As a scheduled task they may be different to a script task in DHCP-client or similar situations.

I also have this problem. Help me please.
dhcp-client on ether1-WAN lost IP address 10.132.73.82 - received NAK from dhcp server 10.132.73.81
dhcp-client on ether1-WAN got IP address 10.132.73.82

Got same problem.

:if ($bound = 1) do={
/system/script/run myscript
:log warn "blahblah"
}

If “/system/script/run myscript” is present in script body, next command - “:log warn…” does not show its output in log, like there is a syntax error or something. When I comment this line like

:if ($bound = 1) do={
#/system/script/run myscript
:log warn "blahblah"
}

I can see record “blahblah” in the log.
Script myscript in /system/scripts is correct and works perfectly, if I run it manually.
The question is simple: what’s wrong and how to force DHCP client script to call script from /system/scripts correctly?