Finding MacAddress from IP Address in a platform independent way - macos

I need to findout the mac address of the device from which my device gets TCP requests, I ll be getting the ip address of the device by tcp endpoint but i need to find out the mac address of the device.My application will be running on both windows and linux, so please suggest me a cross platform method to find the mac address.. Any boost libraries will help me doing the same??

Firstly, you can't find the MAC address for any network interface that is not on the same local area network. That information is not transmitted beyond the router.
There is a command line tool called arp that is available on Unix and also Windows that will list IP addresses and MAC addresses of interfaces that have been in communication with your PC. i.e.
arp -a
on Windows gives something like:
Interface: 9.175.198.236 --- 0x2
Internet Address Physical Address Type
9.175.198.129 00-1b-53-46-fa-7f dynamic
and on a Unix-alike looks like:
foo.bar.com (10.27.68.72) at 00:50:56:AE:00:0B [ether] on eth0
baz.bar.com (10.27.68.77) at 00:50:56:AE:00:10 [ether] on eth0
? (10.27.68.1) at 00:50:5A:1B:44:01 [ether] on eth0
You can try invoking it and parsing the output programmatically.

arp source code is available in the below link, take the piece of code that interests you! It is c code so it should work fine.
http://www.opensource.apple.com/source/network_cmds/network_cmds-328/arp.tproj/arp.c

First thing to note is that at TCP layer, you don't know the MAC addresses.
For your case, I guess you can do two things:
use arp or write a piece of code similar to arp which looks for MAC given the IP address.
The problem with this approach is that it won't work in cases when the source is in another network.
write your server in such a way that it requests for this information from the client sending TCP request. This can be done post TCP establishment. The client should also be able to look up the machine's MAC address for the given IP.

Related

Getting MAC Address of devices using Local Network IP Address(192.168.xxx.xxx)

I am building a Mini-Project and I came across this problem..I have to find MAC Addresses of all Devices that were in my Home Network .Here I got all the devices local IP addresses (I pinged from 1 to 255 and noted down all responded devices IP's).Here i am using Windows with python 2.7.x .I do also need the Network Card Manufacturer Name.
In other words I just want the raw data that the WI-FI Watcher shows.
My aim to get MAC and Network Card Manufacturer Name
First of all please make sure you ping all the hosts in your subnet. I would ping the broadcast address first, then just in case all of them, maybe some of them did not respond to your broadcast.
This way you will fill the local ARP cache of your machine. Then you can run this executable:
arp -a -v
Which will output information on all the IP addresses and their corresponding MAC address.
Then it's just a matter of looking up the OUI of the MAC address.
In pure python, as you mention in your comment, you can use "Scapy". you can find an ARP ping example here:
https://freezion.com/2009/01/22/arp-ping-using-scapy/
Basically:
from scapy import srp,Ether,ARP,conf
conf.verb=0
ans,unans=srp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst=sys.argv[1]),
timeout=2)
For OUI lookup, you can use this small bit of code, although it has an external dependency:
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)
Also, you can try the OUI parser lib from Wireshark.
NOTE: this does not work if ICMP is disabled on the destination hosts, in that case you have to run a traditional portscan and find open ports.

destination MAC to use when sending to remote host (is it my router)?

For various reasons, I'm trying to construct and send raw TCP packets to a remote host (ex. google.com) with raw sockets. I'm trying to use pcap, so the raw socket code can be ported to Windows at some point.
Looks pretty straightforward...
1. ethernet header
2. ip header
3. tcp header
4. segment (optional)
2,3,4 are straightforward. #1 is the rub because I don't know what to use for the destination MAC address of google.com. From what I can tell, ARP is useless for telling me that MAC because I have to be connected to google's router for it to work. Snag.
So that makes me ask this question:
Should I use the MAC of MY router as the destination MAC address in the ethernet header when sending to a host not in LAN? And when the packet is forwarded, does every router it hits tear out that Ethernet header and replace it with the appropriate source/destination MACs so it gets to Google.com? That is the only thing that sounds reasonable.
Side note, I think this was the motivation here, but the question never quite made it:
how to determinate destination MAC address
That's right. The source MAC address in the ethernet header should be the MAC address of the interface you're sending from, and the destination MAC address should be your router's MAC on its interface that is connected to your LAN.
It's important to remember that Link-Layer addresses are used within networks (in this case, both your MAC address and your router's internal interface are on your LAN), while Network Layer (IPv4/IPv6) addressing is used to route your packet from the source host to the destination host (this is ignoring NAT and a whole bunch of other grossness that arises in IPv4).
What will happen when you send your Ethernet frame out of your interface is the following:
Your router will end up with the frame after it travels through 0 or more switches, which know where your router's internal MAC address is from receiving traffic from it in the past. Your router knows the frame is for it because its internal MAC address is the destination MAC.
Your router will strip off the Ethernet header. Then, it will inspect the destination IP address, and determine how to forward that packet based on that address. If we're talking about your home router, it is probably also changing the source IP address (something called Network Address Translation, or NAT), but since it isn't in the scope of your question I'll leave that alone.
Before it forwards the packet to the next router on the path toward the destination IP address, the router needs to put another Link-Layer header back on the IP datagram because it stripped off the one you had put on it. So, it will create a new Link-Layer header using its outgoing interface's MAC address as the source MAC, and the MAC address of the next router's internal MAC address as the destination. In this way, the Link-Layer header is re-written "hop-by-hop".
Somedays before even I faced the same confusion. So long story short yes the destination MAC address will be the gateway router MAC address. And about how I determined is - like this -
I used the command
route -n
Then I used the command
arp -n
The output is as you can see -
goutbose#####:~$ route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.39.51.1 0.0.0.0 UG 0 0 0 enp2s0f0
goutbose####:~$ arp -n
Address HWtype HWaddress Flags Mask Iface
10.39.51.130 ether 00:1a:c5:01:12:94 C enp2s0f0
Now you can hardcode your destination MAC in your packets as I did as an easy hack or if you want you can design your own ARP resolution which is way out of my knowledge scope to help you out. My implementation to implement my own ICMP ping request using raw sockets is as follows -
https://github.com/Goutam1511/Socket-Programming-with-C/blob/master/myping.c
Although a late reply I hope it may help somebody else out because there are very little resources related to using raw socket in the link layer.

Ruby sending packet to a known MAC address

I like to send packet to a device with only MAC address associated to it and also connecting to my local LAN.
Is there anything in ruby / gem library that I can use to perform such task?
I want to do something like tcpreplay but in ruby instead. Thanks!
MACs are the addresses used on OSI layer 2, the package type you are using on this layer are e.g Ethernet frames. IP Sockets live on layer 3/4, thus if you are using an IP socket, you are sending IP packet.
So if you want to send something "to a MAC address", you need to send raw Ethernet frames which need to be understood on the other side. Given the really low level of this stuff, this is rarely what you really want to do.
Instead, you should try to get the proper IP addresses of the remote device in your local network (technically the broadcast domain) with either a broadcast/reply mechanism or with multicast (which is used e.g. by Bonjour). That way you can always use the much more supported IP layer. For that, your device needs to have an IP address of course. You can establish those with mechanisms like DHCP or address auto configuration for IPv6.
As for your question, I'm not aware of any library for Ruby to send raw Ethernet frames. But given you would need to invent a new protocol besides IP anyway (which is hard, really hard), sending the package is probably the least of your concerns.
I suppose there are a couple of approaches. You didn't say whether you wanted to send an IP packet of some kind, and if so you didn't say which IP protocol. (I can tell you want to send an ethernet frame but ... what encapsulated protocol?)
Anyway, you can open a SOCK_RAW with Ruby, something like:
Socket.open(Socket::PF_INET, Socket::SOCK_RAW, Socket::IPPROTO_RAW)
Another approach might be to just pick a link-local IP and then establish an IP/MAC mapping in your local ARP cache with something like:
system "arp -s host hw_addr"
Then you could communicate with it using more familiar socket ops using the link-local IP address.
You need to be root for all of these things.

Find IP address of directly connected device

Is there a way to find out the IP address of a device that is directly connected to a specific ethernet interface? I.e. given one host, one wired ethernet connection and one second host connected to this wired connection, which layer or protocol below IP could be used to find this out.
I would also be comfortable with a Windows-only solution using some Windows-API function or callback.
(I know that the real way to do this would probably via DHCP, but this is about discovering a legacy device.)
Mmh ... there are many ways.
I answer another network discovery question, and I write a little getting started.
Some tcpip stacks reply to icmp broadcasts.
So you can try a PING to your network broadcast address.
For example, you have ip 192.168.1.1 and subnet 255.255.255.0
ping 192.168.1.255
stop the ping after 5 seconds
watch the devices replies : arp -a
Note : on step 3. you get the lists of the MAC-to-IP cached entries, so there are also the hosts in your subnet you exchange data to in the last minutes, even if they don't reply to icmp_get.
Note (2) : now I am on linux. I am not sure, but it can be windows doesn't reply to icm_get via broadcast.
Is it the only one device attached to your pc ?
Is it a router or another simple pc ?
To use DHCP, you'd have to run a DHCP server on the primary and a client on the secondary; the primary could then query the server to find out what address it handed out. Probably overkill.
I can't help you with Windows directly. On Unix, the "arp" command will tell you what IP addresses are known to be attached to the local ethernet segment. Windows will have this same information (since it's a core part of the IP/Ethernet interface) but I don't know how you get at it.
Of course, the networking stack will only know about the other host if it has previously seen traffic from it. You may have to first send a broadcast packet on the interface to elicit some sort of response and thus populate the local ARP table.
Windows 7 has the arp command within it.
arp -a should show you the static and dynamic type interfaces connected to your system.
Your Best Approach is to install Wireshark, reboot the device wait for the TCP/UDP stream , broadcasts will announce the IP address for both Ethernet ports
This is especially useful when the device connected does not have DHCP Client enabled, then you can go from there.
You can also get information from directly connected networking devices, such as network switches with LDWin, a portable and free Windows program published on github:
http://www.sysadmit.com/2016/11/windows-como-saber-la-ip-del-switch-al-que-estoy-conectado.html
LDWin supports the following methods of link discovery: CDP (Cisco Discovery Protocol) and LLDP (Link Layer Discovery Protocol).
You can obtain the model, management IP, VLAN identifier, Port identifier, firmware version, etc.

Network discovery on a Mac

Is there a Mac/Unix commands that lets you see the local network in terms of machines/IP addresses? If there's something on the Mac that is gui-based that would be great too.
ping the broadcast address (the broadcast address is printed as part of the output to ifconfig en0)
The hosts answering are on your local network. (You may also try arp -a but that only keeps track of recently contacted hosts so you may want to run it after the broadcast.)
There is a program called Bonjour Browser that will list well known services that have registered on your local network. I believe that most Macs have one or more registered protocols by default.
The only way to reliably do this is to scan the network using ping sweeps and similar techniques looking for open ports etc on various addresses. You can do that with nmap which is available for OS X. See http://www.netadmintools.com/art406.html for an example.
EDIT: Just to clarify, as diciu pointed out, you can usually ping the broadcast address and/or use your arp cache as well. This will probably work for most home networks where directed broadcast is allowed.
If not, then you would need to run a ping sweep with a tool like nmap to individually check each address for an available host. Many network discovery/scanning tools can check for more than just ping, looking for listening ports, SNMP, etc. as well.
in the days of tiger (10.4) every mac broadcast a 'presence' service on bonjour, which made finding macintoshes on the network a snap. alas, no more...
You can use netdiscover on Mac OS, which is based on ARP packets. It will send ARP requests and scan the response.
For example, run netdiscover command sudo netdiscover -i en0 -r 10.106.0.0/16 in my local network would bring the following result:
Try IP Scanner 2.5 for OS X. http://10base-t.com/ Looking for others, but that's the only real one I've found for OS X.
You can use Nmap but that seems to be a bit much for your stated goals.
OS X ships with netstat, or open Up /Applications/Utilities/Network Utility.app, perhaps this will work for you?
EDIT: oops. netstat doesn't do what I thought.
angry IP scanner for a no mus - no fuss IP scanner with basic port scanning.
NMap and Zenmap for the big power scans.
I actually use both together, as nmap can get easily sidetracked by certain reverse proxy boxes.

Resources