Community discussions

MikroTik App
 
MTNick
Member Candidate
Member Candidate
Topic Author
Posts: 106
Joined: Fri Nov 24, 2023 6:43 am

Script to obtain vendor info from MAC addresses (help needed)

Wed Oct 23, 2024 2:01 am

Greetings everyone. Looking for help in the script below. The script requires user input of the network address. Once the network address is known, it then finds the bridge name, clears the arp table, runs an ip-scan, gathers MACs from the found bridge & grabs the IP's by matching the MAC address to the arp table. Need help on how to reach out for each MAC address found to obtain the vendor name & add it to the file.

I found a great script created by excession in a thread here: viewtopic.php?t=211539. Script works great in ROS 7 & only supported in ROS 7 as stated by the op. Looking for something similar to obtain the vendor names.

The majority of Mikrotik's are mostly running 6.45.9 and some on 6.49.10. Does anyone know how, in ROS 6.45.x or above, to have the script below reach out & get the vendor info? The MAC address is defined as $mac in the script below.

Update: Changed the script as it failed or skipped over duplicate macs. It clears the arp table, ip-scan the range, get macs, ip addresses, bridge host interface & ether name comments. Do a mac lookup for each item. Output is shown in cli & also saved to a file (identity_IP-Scan_interface_date-time.txt). A bridge must exist. The script will request a value, user inputs the ip range of the printed available networks (ip --> addresses), 192.168.88.1/24 as example, the script will find the interface & run with it.

Update2: Updated to follow IEEE standards for OUI lookup. Replaced date/time conversion with rextended's version (works properly in all ROS versions). Removed some items needed for personal needs/use.

Update3: Put back the date command that was missing for the title. Added arp cleanup suggested by wfburton.

Update4: Added to validate that a bridge interface does exist in bridge hosts (/interface bridge host) prior to running.

Thank you to excession for providing the code to make the mac lookup work.
Thank you rextended for your input, suggestions and scripts.
Thank you to all the forum guru's & users having this info available searching throughout the forum, and providing assistance when stumped.

# disclaimer: novice attempt for this to work in ros 6.45.9 & above.
:local version "IP-Scanner_v2.3.4"
:local note "Compatible with RouterOS versions 6.45.9 & above"
:local scanTime "30"
:local date [/system clock get date]
:local name [/system identity get name]
:put ""
:put "### $version"
:put "### $note"

{
# Convert date and time for the file name, needed for ROS version 6
:local simplercurrdatetimestr do={
    /system clock
    :local vdate [get date]
    :local vtime [get time]
    :local vdoff [:toarray "0,4,5,7,8,10"]
    :local MM    [:pick $vdate ($vdoff->2) ($vdoff->3)]
    :local M     [:tonum $MM]
    :if ($vdate ~ ".../../....") do={
        :set vdoff [:toarray "7,11,1,3,4,6"]
        :set M     ([:find "xxanebarprayunulugepctovecANEBARPRAYUNULUGEPCTOVEC" [:pick $vdate ($vdoff->2) ($vdoff->3)] -1] / 2)
        :if ($M>12) do={:set M ($M - 12)}
        :set MM    [:pick (100 + $M) 1 3]
    }
    :local yyyy [:pick $vdate ($vdoff->0) ($vdoff->1)]
    :local dd   [:pick $vdate ($vdoff->4) ($vdoff->5)]
    :local HH   [:pick $vtime 0  2]
    :local mm   [:pick $vtime 3  5]
    :local ss   [:pick $vtime 6  8]

    :return "$MM-$dd-$yyyy_$HH.$mm.$ss"
}

:local dateTime [$simplercurrdatetimestr]

# Gather network address from user & find the interface
:put ""
:put "### Listing available address-list"
:put ""
/ip address print
:put ""
:local requestvalue do={:put $1 ; :return}
:local scanRange [$requestvalue "Enter the address of the interface to scan. Hint: not an ether# -- Example: 192.168.88.1/24"]
:put ""
:local scanBridge [/ip address get [find where address="$scanRange"] interface]
:local scanInterface [/interface bridge host get [find interface=$"scanBridge"] bridge]
:put "### Found bridge: $scanInterface"
:local fileName "$name_IP-Scan_$scanInterface_$dateTime"
/file remove [find where name=$"fileName".txt]
:delay 2s

# Clear the arp table
:put "### Clearing the arp table"
:local dumplist [/ip arp find]
:foreach i in=$dumplist do={
    /ip arp remove $i
}

# Scan the range, get macs, ip addresses, bridge host interface & ether name comments. Do a mac lookup for each item
:local ipScan   ""
:local buffer1   ""
:local vendor 
:local arpCount 0
:delay 2s
:put "### Scanning $scanRange for $scanTime seconds. Standby..."
:put ""
:delay 2s
:set $ipScan ($ipScan.[/tool ip-scan address-range="$scanRange" duration=$scanTime])
:put "### Looking up OUI vendor info. Standby...\r\n"
/ip arp
:foreach item in=[find interface=$"scanInterface"] do={
    :local mac   [get $item mac-address]
    :local arpIP   [get $item address]
    :local ipScanip "$ipScan$[get $item address]"
    :local ipScanmac "$ipScan$[get $item mac-address]"
    :if ([:len $mac] > 0) do={
      :do {
      :local int [/interface bridge host get [find where mac-address=$ipScanmac] interface]
      :local comment [/interface ethernet get [find where name=$int] comment]
      :local secBit [:pick "$ipScanmac" 1 2 ]
      :if ( ($secBit = "2") or ($secBit = "6") or ($secBit = "A") or ($secBit = "E") ) do={
        :set vendor "* LOCAL PRIVATE *"}  else={
        :local vendorResult [/tool fetch url=("https://api.maclookup.app/v2/macs/".[:pick $ipScanmac 0 8]."/company/name") as-value output=user]
        :if (($vendorResult->"status")="finished") do={:set vendor ($vendorResult->"data")}
        :delay 0.5}
          :if ($vendor = "IEEE Registration Authority") do={
          :local vendorResult2 [/tool fetch url=("https://api.maclookup.app/v2/macs/".[:pick $ipScanmac 0 10]."/company/name") as-value output=user]
          :if (($vendorResult2->"status")="finished") do={:set vendor ($vendorResult2->"data")}
          :delay 0.5}
            :if ($vendor = "IEEE Registration Authority") do={
            :local vendorResult3 [/tool fetch url=("https://api.maclookup.app/v2/macs/".[:pick $ipScanmac 0 13]."/company/name") as-value output=user]
            :if (($vendorResult3->"status")="finished") do={:set vendor ($vendorResult3->"data")}
            :delay 0.5}
    :set $buffer1 ($buffer1."IP: $ipScanip | MAC: $ipScanmac | Interface: $int | Comment: $comment | MLU: $vendor\r\n")
    :set arpCount ($arpCount + 1)
  } on-error={};
}}

# Grab bridge-host items
:local brHost1   ""
:local brVendor ""
:local brCount 0
/interface bridge host
:foreach brItem in=[find bridge="$scanInterface" local=no] do={
    :do {
    :local brMac [get $brItem mac-address]
    :local brInt [get $brItem interface]
    :local secBit2 [:pick "$brMac" 1 2 ]
    :if ( ($secBit2 = "2") or ($secBit2 = "6") or ($secBit2 = "A") or ($secBit2 = "E") ) do={
      :set brVendor "* LOCAL PRIVATE *"}  else={
      :local brVendorResult [/tool fetch url=("https://api.maclookup.app/v2/macs/".[:pick $brMac 0 8]."/company/name") as-value output=user]
      :if (($brVendorResult->"status")="finished") do={:set brVendor ($brVendorResult->"data")}
      :delay 0.5}
        :if ($brVendor = "IEEE Registration Authority") do={
        :local brVendorResult2 [/tool fetch url=("https://api.maclookup.app/v2/macs/".[:pick $ipScanmac 0 10]."/company/name") as-value output=user]
        :if (($brVendorResult2->"status")="finished") do={:set brVendor ($brVendorResult2->"data")}
        :delay 0.5}
          :if ($brVendor = "IEEE Registration Authority") do={
          :local brVendorResult3 [/tool fetch url=("https://api.maclookup.app/v2/macs/".[:pick $ipScanmac 0 13]."/company/name") as-value output=user]
          :if (($brVendorResult3->"status")="finished") do={:set brVendor ($brVendorResult3->"data")}
          :delay 0.5}
    :set $brHost1 ($brHost1."MAC: $brMac | Interface: $brInt | MLU: $brVendor\r\n")
    :set brCount ($brCount + 1)
} on-error={:put "error - duplicate MAC detected"};}

# ARP Clean-up
/ip arp remove [find where !complete]

# Messages
:local title "Identity: $name | Scanned Bridge: $scanInterface | Scanned Range: $scanRange | Date: $date | Version: $version\r\n"
:local detected "### Total devices with an address detected on '$scanInterface': $arpCount"
:local dump "### Below is a dump of the data collected from '$scanInterface' & IP range '$scanRange'. If there are duplicate MAC addresses, they will NOT be listed in the Bridge-Host dump\r\n"
:local brCountNote "### Total items found in bridge-host for '$scanInterface': $brCount"

# List the results
:put "$detected"
:put "$buffer1"
:delay 1s
:put "$dump"
:put "$brCountNote"
:put "$brHost1"

# Put the results in a file
:put "### Writing to file"
/file print file=$fileName
:delay 1s
:execute [/file set $fileName contents="$title\r\n$detected\r\n$buffer1\r\n$dump\r\n$brCountNote\r\n$brHost1"]

# Instructions
:put "### The file: '$fileName' is located in 'Files' (left sidebar menu)"
:put "### To download the file locally, right click on the file & select download"
:put "### Be sure to delete the file from this device once it's downloaded locally"
:put ""
}

Here's a screenshot of the output
Screenshot 2024-11-02 at 11.33.33 AM.png
You do not have the required permissions to view the files attached to this post.
Last edited by MTNick on Sun Nov 03, 2024 6:46 pm, edited 5 times in total.
 
excession
Member Candidate
Member Candidate
Posts: 122
Joined: Mon May 11, 2015 8:16 pm

Re: Script to obtain vendor info from MAC addresses (help needed)  [SOLVED]

Mon Oct 28, 2024 4:10 pm

This part from my script is the bit I think you're after and this does work in ROS v6:
:local vendor 
:local vendorResult [/tool fetch url="https://api.maclookup.app/v2/macs/$MAC-ADDRESS-HERE/company/name" as-value output=user]
:if (($vendorResult->"status")="finished") do={:set vendor ($vendorResult->"data")}
:delay 0.5
As I recall the only part from my script that doesn't work in v6 is the as-value parameter on the ip-scan function, and you're already working around that. Please keep the above :delay in your script, this is required to meet the usage limits on the api.
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 12522
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: Script to obtain vendor info from MAC addresses (help needed)

Mon Oct 28, 2024 4:43 pm

Do not forget also the other considerations:
the first is that the entire mac-address is sent to the site (uselessly), instead of just the vendor part, screwing up privacy,

the second is that the invented/random or local-use mac-addresses are also requested (bit 2 and 1 of the first byte),
which are a waste of resources for those who host the service for free.

and:
[...]
if vendor = "IEEE Registration Authority"
[...]
:set url ("https://api.maclookup.app/v2/macs/".[:pick $macAddress 0 11]."/company/name")
[...]
if vendor = "IEEE Registration Authority"
[...]
:set url ("https://api.maclookup.app/v2/macs/".[:pick $macAddress 0 13]."0/company/name")
[...]


Often who provide api for free, after excessive abuse, drop the service...
 
MTNick
Member Candidate
Member Candidate
Topic Author
Posts: 106
Joined: Fri Nov 24, 2023 6:43 am

Re: Script to obtain vendor info from MAC addresses (help needed)

Thu Oct 31, 2024 1:30 am

@excession. The code you provided worked. I've had issues using as-value as well, but for some reason, it worked. Tested roughly 30-50 times using multiple routers & various use cases (small - mid networks). Worked every time. Thank you!

@rextended: I'll work on adding what you suggested. I read your post in excession's thread, actually I read a lot of your posts lol. Much good info in there. I'm not good with scripts but getting better as I learn.

Initial post is updated
 
MTNick
Member Candidate
Member Candidate
Topic Author
Posts: 106
Joined: Fri Nov 24, 2023 6:43 am

Re: Script to obtain vendor info from MAC addresses (help needed)

Sun Nov 03, 2024 2:12 am

@rextended: Added your suggestions for the IEEE standards

Initial post updated
 
MTNick
Member Candidate
Member Candidate
Topic Author
Posts: 106
Joined: Fri Nov 24, 2023 6:43 am

Re: Script to obtain vendor info from MAC addresses (help needed)

Sun Nov 03, 2024 2:10 pm

Thank you for this script!

At the end of the script can you add this

#ARP Clean-up
/ip/arp/remove [find where !complete]

I tried modifying it but got nowhere.

Greetings wfburton. I added your suggestion for arp cleanup to the script. In ROS version 6, the "/" can't be used. The arp cleanup command, or any command, would look like:

/ip arp remove [find where !complete]

Initial post updated
 
MTNick
Member Candidate
Member Candidate
Topic Author
Posts: 106
Joined: Fri Nov 24, 2023 6:43 am

Re: Script to obtain vendor info from MAC addresses (help needed)

Sun Nov 03, 2024 6:50 pm

Thanks for the fix but something broke.

Nothing broke. Does your sfp-sfpplus1 exist as a "bridge" in /interface bridge host ? Assuming it doesn't would be reason why it failed to provide any data. Thanks for pointing that out though. I added to validate that a bridge does exist prior to running.

Initial post updated
 
MTNick
Member Candidate
Member Candidate
Topic Author
Posts: 106
Joined: Fri Nov 24, 2023 6:43 am

Re: Script to obtain vendor info from MAC addresses (help needed)

Sun Nov 03, 2024 8:29 pm

It is working properly. Again, the script requires that the bridge exists. In your printout of /interface bridge host, the "bridge" is not sfp-sfpplus1. The bridge is bridgeLocal

I guess I can explain why the script was made this way. In what I do, we mostly deal with public LAN blocks. The addresses reside on a bridge. It's why the bridge must exist in this script in order for it to run.

However, we can get this to work. Some changes are needed on how the script runs & where it's looking for the data. If you wouldn't mind, please create a new thread and I'll help you out there & post a script that'll work for your use case.

Btw, I have no idea how to add an api key. I can look into it & try to implement it for you. But lets get the script working for you first before messing with the api key

Who is online

Users browsing this forum: No registered users and 9 guests