Community discussions

MikroTik App
 
snoozer
Member Candidate
Member Candidate
Topic Author
Posts: 154
Joined: Mon Jun 18, 2007 5:13 pm
Location: Schull, West-Cork, Ireland.

How to check if address is already in address-list ?

Thu Jan 20, 2011 7:00 pm

hello,

i have an accounting script which should add ip addresses to the address list 'overlimit' if the user is over 90% of their allowed volume. here the lines doing that:
# Add address to overlimit list
:if ([$percentage] > 90 ) do={
/ip firewall address-list add list=overlimit address=$targetip
}
problem now is that there are going to be duplicate lines after each run of the entire script because i have not yet checked beforehand if the address is already in the address-list 'overlimit'. can someone possibly explain to me how i can check if the address is already in the list and only add it if it does not already exists in the list ?

thanks
Jan
 
fewi
Forum Guru
Forum Guru
Posts: 7717
Joined: Tue Aug 11, 2009 3:19 am

Re: How to check if address is already in address-list ?

Thu Jan 20, 2011 7:53 pm

:if ([:len [/ip fire address-list find address="$targetip"]] > 0) do={:put "Found entry, do something";}
If you need to check if the IP is on a specific list, add an additional condition for the list name:
:if ([:len [/ip fire address-list find address="$targetip" and list="listName"]] > 0) do={:put "Found entry, do something";}
 
snoozer
Member Candidate
Member Candidate
Topic Author
Posts: 154
Joined: Mon Jun 18, 2007 5:13 pm
Location: Schull, West-Cork, Ireland.

Re: How to check if address is already in address-list ?

Thu Jan 20, 2011 9:03 pm

hi fewi,

i was looking into the 'find' before but was unsure what is supposed to happen. if i simply issue this on the cli nothing happens but i DO have entries with the list name i try to find.
[admin@Colla01] > ip firewall address-list print  
Flags: X - disabled, D - dynamic 
 #   LIST                                       ADDRESS                        
.
.
.
11   overlimit                                  10.27.99.16                    
12   overlimit                                  10.27.99.102                   
[admin@Colla01] >
next i issue the following:
[admin@Colla01] > ip firewall address-list find list=overlimit
[admin@Colla01] >
and thats it, nothing is returned. what am i missing here ?

Regards
Jan
 
fewi
Forum Guru
Forum Guru
Posts: 7717
Joined: Tue Aug 11, 2009 3:19 am

Re: How to check if address is already in address-list ?

Thu Jan 20, 2011 9:42 pm

'find' returns an array pointing to the items found, if any. 'find' does not print any output. ':len' returns the size of an array (when operating on arrays). So a better test would be:
:put [:len [/ip firewall address-list find list=overlimit]]
to print the size of the array returned by the 'find' command. You can also print the array directly, but you'll just get memory pointers. Still shows output, though:
:put [/ip firewall address-list find list=overlimit]
 
snoozer
Member Candidate
Member Candidate
Topic Author
Posts: 154
Joined: Mon Jun 18, 2007 5:13 pm
Location: Schull, West-Cork, Ireland.

Re: How to check if address is already in address-list ?

Thu Jan 20, 2011 10:10 pm

ok, thanks again. i think i know what the problem is. i aquire the targetip from the queue which returns for example 10.27.99.102/32. if i query the address-list it will not return the trailing /32. so my string $targetip will never match. i have to find a way to cut off the /32 from the string in order to match it with the address-list.

Jan
 
fewi
Forum Guru
Forum Guru
Posts: 7717
Joined: Tue Aug 11, 2009 3:19 am

Re: How to check if address is already in address-list ?

Thu Jan 20, 2011 10:19 pm

That's easily done, the scripting language has string manipulation commands:
http://wiki.mikrotik.com/wiki/Manual:Sc ... l_commands
:local IP "1.1.1.1/32";
:local STRIPPED [:pick $IP 0 [:find $IP "/"]];
:put $STRIPPED;
'pick' selects substrings, 'find' in a string context as a global command (':find') returns the position of a string within a string. To strip off a trailing netmask just pick the string from character 0 to the position of the first '/' character.

Also: pasting the above right into a router won't work due to scope. Either collapse it all into one line with the semicolons separating the commands, or wrap all three lines in curly braces ('{}').
[admin@router] > {
{... :local IP "1.1.1.1/32";  
{... :local STRIPPED [:pick $IP 0 [:find $IP "/"]];
{... :put $STRIPPED;                               
{... }              
1.1.1.1
[admin@router]
 
snoozer
Member Candidate
Member Candidate
Topic Author
Posts: 154
Joined: Mon Jun 18, 2007 5:13 pm
Location: Schull, West-Cork, Ireland.

Re: How to check if address is already in address-list ?

Thu Jan 20, 2011 11:14 pm

hi fewi,

sorry for asking so seemingly silly questions but i am complete newbie to scripting on ROS. i have tried what you mentioned above on the command line. only why is it a difference if i type the ip address directly into the line and on the other hand if i obtain it from the result of a command ? here my example concerning the queue named 'queue111'
[admin@Colla01] > :local IP [/queue simple get queue111 target-addresses];:local STRIPPED [:pick $IP 0 [:find $IP "/"]];:put $STRIPPED;
10.27.99.102/32
[admin@Colla01] > :local IP "10.27.99.102/32";:local STRIPPED [:pick $IP 0 [:find $IP "/"]];:put $STRIPPED;                            
10.27.99.102
[admin@Colla01] >
should not both give an ip address stripped of the netmask ?

here the queue in question:
[admin@Colla01] > queue simple print where name=queue111 
Flags: X - disabled, I - invalid, D - dynamic 
 1    ;;; NAME_abc!1#email@example.com!99#2566013908
      name="queue111" target-addresses=10.27.99.102/32 dst-address=0.0.0.0/0 interface=all parent=none direction=both priority=8 queue=default/default 
      limit-at=0/0 max-limit=0/0 burst-limit=0/0 burst-threshold=0/0 burst-time=0s/0s total-queue=default-small 
[admin@Colla01] >
regards
Jan
 
fewi
Forum Guru
Forum Guru
Posts: 7717
Joined: Tue Aug 11, 2009 3:19 am

Re: How to check if address is already in address-list ?

Thu Jan 20, 2011 11:34 pm

Looks like you have to explicitly convert the datatype returned by the 'get' command to a string via the ':tostr' command first:
[admin@router] /queue simple> :local IP [get 0 target-address]; :put $IP; :local STRIPPED [:pick $IP 0 [:find $IP "/"]];:put $STRIPPED;
10.2.1.5/32
10.2.1.5/32
[admin@router] /queue simple> :local IP [:tostr [get 0 target-address]]; :put $IP; :local STRIPPED [:pick $IP 0 [:find $IP "/"]];:put $STRIPPED;
10.2.1.5/32
10.2.1.5
[admin@router] /queue simple> 
 
snoozer
Member Candidate
Member Candidate
Topic Author
Posts: 154
Joined: Mon Jun 18, 2007 5:13 pm
Location: Schull, West-Cork, Ireland.

Re: How to check if address is already in address-list ?

Thu Jan 20, 2011 11:39 pm

yes, that's it. thanks a lot fewi !!

Have Fun!
Jan
 
flydvorkin
just joined
Posts: 15
Joined: Mon Mar 11, 2019 12:59 pm

Re: How to check if address is already in address-list ?

Thu Feb 04, 2021 11:13 am

# input:
#           var checkIp (type ip)
#           var checkNet (various types: 192.168.0.0/24; 192.168.0.0-192.168.0.255; 192.168.0.100)
#
# return:
#           var bool true (if checkIp match checkNet)
#           var bool false (if checkIp not match checkNet)
:global isIpMatchNet4 do={
    :if ( [ :typeof [ :find $checkNet "/" ] ] = "num" ) do={
        :return ( [ :toip $checkIp ] in $checkNet );
    };
    :if ( [ :typeof [ :find $checkNet "-" ] ] = "num" ) do={
        :local lowip [ :toip [ :pick $checkNet 0 [ :find $checkNet "-" ] ] ];
        :local highip [ :toip [ :pick $checkNet ( [ :find $checkNet "-" ] + 1 ) [ :len $checkNet ] ] ];
        if ( $lowip <= [ :toip $checkIp ] and [ :toip $checkIp ] <= $highip ) do={ :return true; };
    };
    :if ( [ :typeof [ :toip $checkNet ] ] = "ip" ) do={
        if ( [ :toip $checkIp ] = [ :toip $checkNet ] ) do={ :return true; };
    };
    :return false;
};

# input:
#           var checkIp (type ip)
#           var addrListName (type string)
#
# return:
#           var bool true (if checkIp in addrListName)
#           var bool false (if checkIp not in addrListName)
:global isIpInAddrList4 do={
    :global isIpMatchNet4;
    :local findInAddrList false;
    :foreach i in=[ /ip firewall address-list find list=$addrListName ] do={
        :if ( [ /ip firewall address-list get $i disabled ] != yes ) do={
            :if ( [ $isIpMatchNet4 checkIp=$checkIp checkNet=[ /ip firewall address-list get $i address ] ] ) do={
                :set findInAddrList true;
            };
        };
    };
    :return $findInAddrList;
};
Usage:
:global isIpMatchNet4;
:global isIpInAddrList4;

:put [ $isIpInAddrList4 checkIp=8.8.8.8 addrListName="whitelist" ];
true - if 8.8.8.8 in whitelist

Who is online

Users browsing this forum: Bing [Bot] and 19 guests