MAC vendor lookup: Difference between revisions
Added C implementation. |
|||
Line 82: | Line 82: | ||
sprintf(str,"http://api.macvendors.com/%s",argV[1]); |
sprintf(str,"http://api.macvendors.com/%s",argV[1]); |
||
curl_easy_setopt(curl, CURLOPT_URL, str); |
curl_easy_setopt(curl, CURLOPT_URL, str); |
||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); |
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); |
||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk); |
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk); |
||
Line 91: | Line 91: | ||
if (res == CURLE_OK) { |
if (res == CURLE_OK) { |
||
checkResponse(chunk.memory); |
|||
return EXIT_SUCCESS; |
return EXIT_SUCCESS; |
||
} |
} |
||
Line 108: | Line 108: | ||
C:\rosettaCode>macLookUp 10-11-22-33-44-55-66 |
C:\rosettaCode>macLookUp 10-11-22-33-44-55-66 |
||
N/A |
N/A |
||
</pre> |
</pre> |
||
=={{header|C sharp|C#}}== |
=={{header|C sharp|C#}}== |
||
Revision as of 00:02, 18 October 2017
You are encouraged to solve this task according to the task description, using any language you may know.
Every connected device around the world comes with a unique Media Access Control address, or a MAC address. A common task a network administrator may come across is being able to identify a network device's manufacturer when given only a MAC address.
- Basic Task
The task is to interface with one (or numerous) APIs that exist on the internet and retrieve the device manufacturer based on a supplied MAC address.
A MAC address that does not return a valid result should return the String "N/A". A error related to the network connectivity or the API should return a null result.
AutoHotkey
<lang AutoHotkey>macLookup(MAC){ WebRequest := ComObjCreate("WinHttp.WinHttpRequest.5.1") WebRequest.Open("GET", "http://api.macvendors.com/" MAC) WebRequest.Send() return WebRequest.ResponseText }</lang> Examples:<lang AutoHotkey>MsgBox % macLookup("00-14-22-01-23-45")</lang>
Outputs:
Dell Inc.
C
Takes MAC address as input, prints usage on incorrect invocation, requires libcurl <lang C> /*Abhishek Ghosh, 18th October 2017*/
- include <curl/curl.h>
- include <string.h>
- include <stdlib.h>
- include <stdio.h>
/* Length of http://api.macvendors.com/ */
- define FIXED_LENGTH 16
struct MemoryStruct {
char *memory; size_t size;
};
static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp) {
size_t realsize = size * nmemb; struct MemoryStruct *mem = (struct MemoryStruct *)userp; mem->memory = realloc(mem->memory, mem->size + realsize + 1); memcpy(&(mem->memory[mem->size]), contents, realsize); mem->size += realsize; mem->memory[mem->size] = 0; return realsize;
}
void checkResponse(char* str){ char ref[] = "Vendor not found"; int len = strlen(str),flag = 1,i;
if(len<16) fputs(str,stdout); else{ for(i=0;i<len && i<16;i++) flag = flag && (ref[i]==str[i]);
flag==1?fputs("N/A",stdout):fputs(str,stdout); } }
int main(int argC,char* argV[]) { if(argC!=2) printf("Usage : %s <MAC address>",argV[0]); else{ CURL *curl; int len = strlen(argV[1]); char* str = (char*)malloc((FIXED_LENGTH + len)*sizeof(char)); struct MemoryStruct chunk; CURLcode res;
chunk.memory = malloc(1); chunk.size = 0;
if ((curl = curl_easy_init()) != NULL) {
sprintf(str,"http://api.macvendors.com/%s",argV[1]);
curl_easy_setopt(curl, CURLOPT_URL, str);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);
free(str);
res = curl_easy_perform(curl);
if (res == CURLE_OK) {
checkResponse(chunk.memory);
return EXIT_SUCCESS; }
curl_easy_cleanup(curl);
} }
return EXIT_FAILURE;
} </lang> Invocation and output :
C:\rosettaCode>macLookUp 00-11-22-33-44-55-66 CIMSYS Inc C:\rosettaCode>macLookUp 10-11-22-33-44-55-66 N/A
C#
<lang csharp>using System; using System.Net; using System.Net.Http; using System.Threading.Tasks;
class Program {
static async Task<string> LookupMac(string MacAddress) { var uri = new Uri("http://api.macvendors.com/" + WebUtility.UrlEncode(MacAddress)); using (var wc = new HttpClient()) return await wc.GetStringAsync(uri); } static void Main(string[] args) { foreach (var mac in new string[] { "88:53:2E:67:07:BE", "FC:FB:FB:01:FA:21", "D4:F4:6F:C9:EF:8D" }) Console.WriteLine(mac + "\t" + LookupMac(mac).Result); Console.ReadLine(); }
}</lang>
- Output:
88:53:2E:67:07:BE Intel Corporate FC:FB:FB:01:FA:21 Cisco Systems, Inc D4:F4:6F:C9:EF:8D Apple, Inc.
Go
<lang go>package main
import ( "net/http" "fmt" "io/ioutil" )
func macLookUp(mac string) (res string){ resp, _ := http.Get("http://api.macvendors.com/" + mac) body, _ := ioutil.ReadAll(resp.Body) res = string(body) return }
func main() { fmt.Println(macLookUp("FC-A1-3E")) fmt.Println(macLookUp("FC:FB:FB:01:FA:21")) fmt.Println(macLookUp("BC:5F:F4")) } </lang>
- Output:
Samsung Electronics Co.,Ltd Cisco Systems, Inc ASRock Incorporation
Haskell
<lang haskell>#!/usr/bin/env stack {- stack
script --resolver lts-9.0 --package bytestring --package http-client --package http-types
-}
{-# LANGUAGE MultiWayIf #-}
import Control.Exception (try) import Control.Monad (forM_) import qualified Data.ByteString.Lazy.Char8 as L8 (ByteString, unpack) import Network.HTTP.Client
(Manager, parseRequest, httpLbs, responseStatus, responseBody, newManager, defaultManagerSettings, Response, HttpException)
import Network.HTTP.Types.Status (statusIsSuccessful, notFound404) import System.Environment (getArgs) import Text.Printf (printf)
fetchURL :: Manager
-> String -> IO (Either HttpException (Response L8.ByteString))
fetchURL mgr url = try $ do
req <- parseRequest url httpLbs req mgr
lookupMac :: Manager -> String -> IO String lookupMac mgr mac = do
eth <- fetchURL mgr $ "http://api.macvendors.com/" ++ mac return $ case eth of Left _ -> "null" Right resp -> let body = responseBody resp status = responseStatus resp in if | status == notFound404 -> "N/A" | not (statusIsSuccessful status) -> "null" | otherwise -> L8.unpack body
main :: IO () main = do
args <- getArgs mgr <- newManager defaultManagerSettings forM_ args $ \mac -> do putStr $ printf "%-17s" mac ++ " = " vendor <- lookupMac mgr mac putStrLn vendor</lang>
- Output:
$ ./RosettaMac.hs 00:15:ed:f0:00:00 ff:ff:ff:ff:ff:ff 88:53:2E:67:07:BE FC:FB:FB:01:FA:21 D4:F4:6F:C9:EF:8D banana 00:15:ed:f0:00:00 = Fulcrum Microsystems, Inc. ff:ff:ff:ff:ff:ff = N/A 88:53:2E:67:07:BE = Intel Corporate FC:FB:FB:01:FA:21 = Cisco Systems, Inc D4:F4:6F:C9:EF:8D = Apple, Inc. banana = N/A
J
Solution <lang j>require 'web/gethttp' lookupMACvendor=: [: gethttp 'http://api.macvendors.com/'&,</lang> Example Usage <lang j> addr=: '88:53:2E:67:07:BE';'FC:FB:FB:01:FA:21';'D4:F4:6F:C9:EF:8D';'23:45:67'
(,&' ' , lookupMACvendor)&> addr
88:53:2E:67:07:BE Intel Corporate FC:FB:FB:01:FA:21 Cisco Systems, Inc D4:F4:6F:C9:EF:8D Apple, Inc. 23:45:67 Vendor not found</lang>
Java
<lang java>package com.jamesdonnell.MACVendor;
import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL;
/** MAC Vendor Lookup class.
* www.JamesDonnell.com * @author James A. Donnell Jr. */
public class Lookup { /** Base URL for API. The API from www.macvendors.com was chosen. */ private static final String baseURL = "http://api.macvendors.com/";
/** Performs lookup on MAC address(es) supplied in arguments. * @param args MAC address(es) to lookup. */ public static void main(String[] args) { for (String arguments : args) System.out.println(arguments + ": " + get(arguments)); }
/** Performs lookup on supplied MAC address. * @param macAddress MAC address to lookup. * @return Manufacturer of MAC address. */ private static String get(String macAddress) { try { StringBuilder result = new StringBuilder(); URL url = new URL(baseURL + macAddress); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); String line; while ((line = rd.readLine()) != null) { result.append(line); } rd.close(); return result.toString(); } catch (FileNotFoundException e) { // MAC not found return "N/A"; } catch (IOException e) { // Error during lookup, either network or API. return null; } } }</lang>
Julia
<lang julia># v0.6.0
using Requests
function getvendor(addr::String)
try get("http://api.macvendors.com/$addr") |> readstring catch e nothing end
end
for addr in ["88:53:2E:67:07:BE", "FC:FB:FB:01:FA:21", "D4:F4:6F:C9:EF:8D", "23:45:67"]
println("$addr -> ", getvendor(addr))
end</lang>
- Output:
88:53:2E:67:07:BE -> Intel Corporate FC:FB:FB:01:FA:21 -> Cisco Systems, Inc D4:F4:6F:C9:EF:8D -> Apple, Inc. 23:45:67 -> Vendor not found
Kotlin
<lang scala>// version 1.1.2
import java.net.URL
fun lookupVendor(mac: String) = URL("http://api.macvendors.com/" + mac).readText()
fun main(args: Array<String>) {
val macs = arrayOf("FC-A1-3E", "FC:FB:FB:01:FA:21", "88:53:2E:67:07:BE", "D4:F4:6F:C9:EF:8D") for (mac in macs) println(lookupVendor(mac))
}</lang>
- Output:
Samsung Electronics Co.,Ltd Cisco Systems, Inc Intel Corporate Apple, Inc.
Lua
<lang lua>-- Requires LuaSocket extension by Lua -- Created by James A. Donnell Jr. -- www.JamesDonnell.com
local baseURL = "http://api.macvendors.com/"
local function lookup(macAddress) http = require "socket.http" result, statuscode, content = http.request(baseURL .. macAddress) return result end
local macAddress = "FC-A1-3E-2A-1C-33" print(lookup(macAddress))</lang>
Mathematica
<lang Mathematica>macLookup[mac_String] := Quiet[Check[Import["http://api.macvendors.com/" <> mac], "N/A"]]</lang>
Examples:<lang Mathematica>macLookup["00-14-22-01-23-45"]</lang>
Outputs:
Dell Inc.
Nim
<lang Nim>import httpclient
for mac in ["FC-A1-3E", "FC:FB:FB:01:FA:21", "BC:5F:F4"]:
echo newHttpClient().getContent("http://api.macvendors.com/"&mac)</lang>
- Output:
Samsung Electronics Co.,Ltd Cisco Systems, Inc ASRock Incorporation
Perl
<lang perl>#!/usr/bin/env perl -T use 5.018_002; use warnings; use LWP;
our $VERSION = 1.000_000;
my $ua = LWP::UserAgent->new;
my @macs = (
'FC-A1-3EFC:FB:FB:01:FA:21', '00,0d,4b', 'Rhubarb', '00-14-22-01-23-45', '10:dd:b1', 'D4:F4:6F:C9:EF:8D', 'FC-A1-3E', '88:53:2E:67:07:BE', '23:45:67', 'FC:FB:FB:01:FA:21', 'BC:5F:F4',
);
for my $mac (@macs) {
my $vendor = get_mac_vendor($mac); if ($vendor) { say "$mac = $vendor"; }
}
sub get_mac_vendor {
my $s = shift;
my $req = HTTP::Request->new( GET => "http://api.macvendors.com/$s" ); my $res = $ua->request($req);
# A error related to the network connectivity or the API should # return a null result. if ( $res->is_error ) { return; }
# A MAC address that does not return a valid result should # return the String "N/A". if ( !$res->content or $res->content eq 'Vendor not found' ) { return 'N/A'; }
return $res->content;
}
- IEEE 802:
- Six groups of two hexadecimal digits separated by hyphens or colons,
- like 01-23-45-67-89-ab or 01:23:45:67:89:ab
- Three groups of four hexadecimal digits separated by dots (.),
- like 0123.4567.89ab
- sub validmac {
- my $s = shift;
- my $hex = qr{ [A-Fa-f[:digit:]] }xms;
- my $hex2ws = qr{ [-:] $hex{2} }xms;
- if ( $s =~ m{\A $hex{2} $hex2ws{5} \z}xms
- or $s =~ m{\A $hex{4} [.] $hex{4} [.] $hex{4} \z}xms )
- {
- return 'true';
- }
- return;
- }</lang>
- Output:
FC-A1-3EFC:FB:FB:01:FA:21 = Samsung Electronics Co.,Ltd 00,0d,4b = Roku, Inc. 00-14-22-01-23-45 = Dell Inc. 10:dd:b1 = Apple, Inc. D4:F4:6F:C9:EF:8D = Apple, Inc. FC-A1-3E = Samsung Electronics Co.,Ltd 88:53:2E:67:07:BE = Intel Corporate FC:FB:FB:01:FA:21 = Cisco Systems, Inc BC:5F:F4 = ASRock Incorporation
Perl 6
<lang perl6>use HTTP::UserAgent;
my $ua = HTTP::UserAgent.new;
$ua.timeout = 10; # seconds
my $server = 'http://api.macvendors.com/';
sub lookup ($mac) {
my $response = $ua.get: "$server+$mac";
return $response.is-success ?? $response.content !! 'N/A';
CATCH { # Normally you would report some information about what default { Nil } # went wrong, but the task specifies to ignore errors. }
}
for < BC:5F:F4 FC-A1-3E 10:dd:b1 00,0d,4b 23:45:67 > -> $mac { say lookup $mac }</lang>
- Output:
ASRock Incorporation Samsung Electronics Co.,Ltd Apple, Inc. Roku, Inc. N/A
PicoLisp
<lang PicoLisp>(load "@lib/http.l")
(de maclookup (M)
(client "api.macvendors.com" 80 M (while (line)) (line T) ) )
(test
"Intel Corporate" (maclookup "88:53:2E:67:07:BE") )
(test
"Apple, Inc." (maclookup "D4:F4:6F:C9:EF:8D") )</lang>
Python
<lang python>import requests
for addr in ['88:53:2E:67:07:BE', 'FC:FB:FB:01:FA:21',
'D4:F4:6F:C9:EF:8D', '23:45:67']: vendor = requests.get('http://api.macvendors.com/' + addr).text print(addr, vendor)</lang>
- Output:
88:53:2E:67:07:BE Intel Corporate FC:FB:FB:01:FA:21 Cisco Systems, Inc D4:F4:6F:C9:EF:8D Apple, Inc. 23:45:67 Vendor not found
Racket
<lang racket>#lang racket
(require net/url)
(define (lookup-MAC-address addr)
(port->string (get-pure-port (url "http" #f "api.macvendors.com" #f #t (list (path/param addr null)) null #f))))
(module+ test (for ((i (in-list '("88:53:2E:67:07:BE"
"FC:FB:FB:01:FA:21" "D4:F4:6F:C9:EF:8D")))) (printf "~a\t~a~%" i (lookup-MAC-address i))))</lang>
- Output:
88:53:2E:67:07:BE Intel Corporate FC:FB:FB:01:FA:21 Cisco Systems, Inc D4:F4:6F:C9:EF:8D Apple, Inc.
Ruby
<lang ruby>require 'net/http'
arr = ['88:53:2E:67:07:BE', 'FC:FB:FB:01:FA:21', 'D4:F4:6F:C9:EF:8D', '23:45:67']
arr.each do |addr|
vendor = Net::HTTP.get('api.macvendors.com', "/#{addr}/") rescue nil puts "#{addr} #{vendor}"
end</lang>
- Output:
88:53:2E:67:07:BE Intel Corporate FC:FB:FB:01:FA:21 Cisco Systems, Inc D4:F4:6F:C9:EF:8D Apple, Inc. 23:45:67 Vendor not found
Tcl
<lang Tcl>package require http
- finally is a bit like go's defer
proc finally args {
tailcall trace add variable :#finally#: unset [list apply [list args $args]]
}
- basic wrapper for http::geturl
proc geturl {url} {
set tok [::http::geturl $url] finally ::http::cleanup $tok ::http::data $tok
} proc maclookup {mac} {
geturl http://api.macvendors.com/$mac
}
foreach mac {00-14-22-01-23-45 88:53:2E:67:07:BE} {
puts "$mac\t[maclookup $mac]"
}</lang>
- Output:
00-14-22-01-23-45 Dell Inc. 88:53:2E:67:07:BE Intel Corporate
zkl
Uses libcurl (the multiprotocol file transfer library) to do the web query <lang zkl>var [const] CURL=Import("zklCurl"); // libcurl const MAC_VENDORS="http://api.macvendors.com/";
fcn lookUp(macAddress){
httpAddr:=MAC_VENDORS + macAddress; vender:=CURL().get(httpAddr); //-->(Data,bytes of header,bytes of trailer) vender=vender[0].del(0,vender[1]); // remove HTTP header vender.text; // Data --> String (Data is a byte bucket)
}</lang> <lang zkl>lookUp("FC-A1-3E-2A-1C-33").println(); lookUp("4c:72:b9:56:fe:bc").println(); lookUp("foobar").println();</lang>
- Output:
Samsung Electronics Co.,Ltd PEGATRON CORPORATION Vendor not found