Yeah, I already found the solution to my problem. my mistake was to just start scribbling away in the console and trying things like:
/log print where...
:put [/log find ...]
but when I tried /log [tab] to see what can be done, there was NO /log get showing up. so I thought /log get would not be implemented.
however this turns out to be a peculiarity of that tab expansion, /log get really does exist and I could use it.
In my case I am working around a problem with IPsec in combination with NAT. I have a client system which is a MikroTik router connected via a WiFi link to a home internet connection with NAT active (not MikroTik), and then setting up an L2TP/IPsec connection to the central router.
Sometimes when that WiFi link is bad the IPsec link times out on our end and not on the client end, and/or the NAT router sees a new UDP port 500 session before the other one was cleared and takes another source port number.
Because of that, the two sides of IPsec no longer get in agreement with eachother, and that situation is permanent. It apparently is an issue with this particular NAT implementation because other links never have this issue here.
I found that by blocking the traffic from that system for a couple of minutes and then allowing it again, the connection is established "fresh" and this issue is worked around.
So I wrote this and scheduled it every 2 minutes:
# scan log buffer for ipsec error messages
# when error is "phase1 negotiation failed due to time up", temporarily block the sender
:global lastTime;
:local currentBuf [ :toarray [ /log find topics=ipsec,error and message~"phase1 negotiation failed due to" ] ] ;
:local currentLineCount [ :len $currentBuf ] ;
:if ($currentLineCount > 0) do={
:local currentTime [/log get [ :pick $currentBuf ($currentLineCount -1) ] time ] ;
if ($currentTime != $lastTime) do={
:set lastTime $currentTime ;
:local currentMessage [/log get [ :pick $currentBuf ($currentLineCount -1) ] message ] ;
:if ($currentMessage~"due to time up") do={
:local ipaddress [:pick $currentMessage ([:find $currentMessage "<=>" ]+3) 99 ] ;
:set ipaddress [:pick $ipaddress 0 [:find $ipaddress "[" ] ];
:local activepeers [ :toarray [ /ip ipsec active-peers find where remote-address=$ipaddress and state=established ] ] ;
:if ( [ :len $activepeers ] = 0) do={
:log info "Temporarily blocking $ipaddress due to errors" ;
/ip firewall address-list add list=blocked address=$ipaddress timeout="00:05:00" ;
}
}
}
}
The address-list "blocked" will block all traffic for that IP both in input and output chain.
It appears to work fine, I saw the problem happen 2 times and it was nicely recovered.
Before, I would see the link is down and 100 messages on the console with "phase1 negotiation failed due to time up" and the connection still down.
The message is matched in two parts because blocking the IP will result in a new message "phase1 negotiation failed due to send error" and this should be regarded as the new "last message" but not trigger another blocking.