Community discussions

MikroTik App
 
teamer
just joined
Topic Author
Posts: 21
Joined: Mon Sep 12, 2016 9:18 am

ipcalc

Wed Dec 28, 2016 11:12 pm

On the occasion I have written functional analogue of ipcalc.
This is my near the first Mikrotik script, so don't hesitate to comment.
:global ipcalc do={
#
# GL(c), 2016
#
  :local pOpt $1
  :local pIpaddr $2
  :local pNetmask $3

  :if ([:len $pOpt] = 0) do={
    :error "ipcalc usage:\n\r    \$ipcalc [-m|-p|-n|-b] ipaddr[/prefix] [netmask]"
    :return
  }

  :local lIpaddr
  :local lPrefix

  :local pos [:find $pIpaddr "/"]
  :if ($pos >= 0) do={
    :set lIpaddr [:toip [:pick $pIpaddr 0 $pos]]
    :set lPrefix [:tonum [:pick $pIpaddr ($pos + 1) [:len $pIpaddr]]]
  } else={
    :set lIpaddr [:toip $pIpaddr]
  }

  :if ((([:len $lPrefix] > 0) && ("$lIpaddr/$lPrefix" != $pIpaddr)) || \
       (([:len $lPrefix] = 0) && ("$lIpaddr" != $pIpaddr)) || \
       ([:len $lIpaddr] = 0)) do={
    :error "ipcalc failed: invalid ip address: $pIpaddr"
  }

  :local lNetmask [:toip $pNetmask]

  :if (([:len $pNetmask] != 0) && ($lNetmask != $pNetmask)) do={
    :error "ipcalc failed: invalid netmask: $pNetmask"
  }

# specified netmask always has precedence over prefix

  :if ([:len $lNetmask] > 0) do={
    :set lPrefix 0
    :while (($lPrefix < 32) && (($lNetmask<<$lPrefix) != 0.0.0.0)) do={
      :set lPrefix ($lPrefix + 1)
    }
  } else={
    :if ([:len $lPrefix] = 0) do={
      :local bits [:tonum [:pick $lIpaddr 0 [:find $lIpaddr "."]]]
      :if (($bits & 128) = 0) do={
        :set lPrefix 8
      }
      :if (($bits & 192) = 128) do={
        :set lPrefix 16
      }
      :if (($bits & 192) = 192) do={
        :set lPrefix 24
      }
    }
    :set lNetmask (255.255.255.255<<(32-$lPrefix))
  }

  :if ($pOpt = "-m") do={ :return $lNetmask }
  :if ($pOpt = "-p") do={ :return $lPrefix }
  :if ($pOpt = "-n") do={ :return ($lIpaddr & $lNetmask) }
  :if ($pOpt = "-b") do={ :return (($lIpaddr & $lNetmask) | (~$lNetmask)) }

  :error "ipcalc failed: unknown option: $pOpt"
}