How to "listen" MAC address in ethernet network? - c++

When we send data to some server on the Internet, we specify its IP and port. If this server, for example, is written in C++, then sockets will be used on the server. But how does it work if we use Ethernet instead of the Internet? How can one computer understand that another computer sent data to it inside the ethernet network? Indeed, in this case, we do not use the IP and port to send data to the recipient, only the MAC address. How can you write a C++ program that "listens" to a MAC address and a client that can send data to the MAC address in C++? I don't fully understand Ethernet use cases in real world

Ethernet headers have an Ethertype field that tells ethernet to which process it should send the frame payload. You will need to establish a process and register an Ethertype number in the OS for that process in order to receive the payload of the frames with the Ethertype you are using.
You cannot just randomly choose an Ethertype number. You either reserve one with the IEEE, or you use one in an experimental range, e.g. 0x0101 to 0x01FF. There are several lists of currently reserved Ethertypes. IANA has Ethertypes, and it has information and links on how to reserve an Ethertype number and other lists.
Also, remember that you will not be able to use IP or any of the standard protocols (transport or application) above IP that depend on IP unless you write your own. Transport protocols, such as TCP in your OS, need IP for the required pseudo-header. You will need to write custom transport-layer protocol(s), applications, and application-layer protocol(s) that you may require to use your new custom protocol using your Ethertype.
Existing transport protocols, e.g. TCP, will not use your custom Ethertype protocol, and any existing application that use existing transport-layer protocols will also not work with your custom protocol.

Related

Ip Address resolution using Mac Address programatically

I am writing a discovery program, written in C++ that will run on linux, to enable me to determine if certain devices are connected to the network. I have the Mac Address of the other devices and I need to resolve their Ip Addresses.
I have checked /proc/net/arp and the devices don't appear.
I tried pinging the broadcast address and this doesn't reach the target and therefore the ARP cache is not updated. However, if I ping the ip address directly it is (but this is not an option).
Also, the devices can be configured with either static ips or can get them via dhcp.
Is there any way that I can determine the ip addresses given the Mac addresses?
Some years ago I'd have suggested to use RARP but it is not supported by Linux kernel any more. Unless there is already a solution I would suggest you the following home-made solution:
-You can use Packet sockets to implement your own Layer 2 protocol: instead of using IP as payload of the Ethernet frame you can select your own protocol code (for example: instead of 0x0800 for IP use 0xABAB, always a number greater than 1536)
-In each node you implement a simple server that use packet socket to read the frames with that protocol code or you could use pcap, as you prefer.
-Whenever you need the IP address of another node you send an Ethernet frame to that MAC address. The server will read the new frame and respond with another frame conveying its own IP address.
-If you choose this solution please remember the payload has to be at least 46 Bytes long, so you may need to use padding. Also you can use the TLV (type length value) format for your own protocol.
Read this:
http://en.wikipedia.org/wiki/Ethernet_frame
http://man7.org/linux/man-pages/man7/packet.7.html
I hope this helps.

how to get IP address of a computers that is directly connected to my PC

I'm trying to write a function that can get me the IP adress (and the name of the device as bonus) of devices that are in my network, the network is gonna be a direct connection between two computers using Ethernet cable or creating an access point (using wi-fi)
I tried to search about how to do it but it seems like I need to listen to the network or something which seems to be difficult.
hope you can guide me to what I should do or read to get started.
Note: I'm using Windows on both computers.
Edited:
P.S: I need the IP Address so I can send a message to the other computer using winsock in a Client/Server program I wrote.
can't I make the server send its IP to the client or the opposite ?
If your software is running on both machines, you can have one (or both) machines send out a particular broadcast (or, if you prefer, multicast) UDP packet on a specific port. Your program should also be listening on that same port. When it receives that packet (using recvfrom()), recvfrom()'s fifth argument will contain the IP address of the machine that sent the packet, i.e. the IP address you want.
(If OTOH your software is not running on the remote machine, you'll need to use some more general-purpose discovery mechanism such as mDNS or LLDP -- hopefully you won't have to do that, though, as it's a good deal more complicated)

Sending arbitrary (raw) packets

I've seen it asked elsewhere but no one answers it to my satisfaction: how can I receive and send raw packets?
By "raw packets", I mean where I have to generate all the headers and data, so that the bytes are completely arbitrary, and I am not restricted in any way. This is why Microsofts RAW sockets won't work, because you can't send TCP or UDP packets with incorrect source addresses.
I know you can send packets like I want to with WinPCAP but you cannot receive raw information with it, which I also need to do.
First of all decide what protocol layer you want to test malformed data on:
Ethernet
If you want to generate and receive invalid Ethernet frames with a wrong ethernet checksum, you are more or less out of luck as the checksumming is often done in hardware, and in the cases they're not, the driver for the NIC performs the checksumming and there's no way around that at least on Windows. NetBSD provides that option for most of it drivers that does ethernet checksumming in the OS driver though.
The alternative is to buy specialized hardware, (e.g. cards from Napatech, you might find cheaper ones though), which provides an API for sending and receiving ethernet frames however invalid you would want.
Be aware that sending by sending invalid ethernet frames, the receiving end or a router inbetween will just throw the frames away, they will never reach the application nor the OS IP layer. You'll be testing the NIC or NIC driver on the receiving end.
IP
If all you want is to send/receive invalid IP packets, winpcap lets you do this. Generate the packets, set up winpcap to capture packets, use winpcap to send..
Be aware that packets with an invalid IP checksum other invalid fields, the TCP/IP stack the receiving application runs on will just throw the IP packets away, as will any IP/layer 3 router inbetween the sender and receiver do. They will not reach the application. If you're generating valid IP packets, you'll also need to generate valid UDP and implement a TCP session with valid TCP packets yourself in order for the application to process them, otherwise they'll also be thrown away by the TCP/IP stack
You'll be testing the lower part of the TCP/IP stack on the receiving end.
TCP/UDP
This is not that different from sending/receiving invalid IP packets. You an do all this with winpcap, though routers will not throw them away, as long as the ethernet/IP headers are ok. An application will not receive these packets though, they'll be thrown away by the TCP/IP stack.
You'll be testing the upperpart of the TCP/IP stack on the receiving end.
Application Layer
This is the (sane) way of actually testing the application(unless your "application" actually is a TCP/IP stack, or lower). You send/receive data as any application would using sockets, but generate malformed application data as you want. The application will receive this data, it's not thrown away by lower protocol layers.
Although one particular form of tests with TCP can be hard to test - namely varying the TCP segments sent, if you e.g. want to test that an application correctly interprets the TCP data as a stream. (e.g. you want to send the string "hello" in 5 segments and somehow cause the receiving application to read() the characters one by one). If you don't need speed, you can usually get that behaviour by inserting pauses in the sending and turn off nagel's algorithm (TCP_NDELAY) and/or tune the NIC MTU.
Remember that any muckery with lower level protocols in a TCP stream, e.g. cause one of the packets to have an invalid/diffferent IP source address just gets thrown away by lower level layers.
You'll be testing an application running on top of TCP/UDP(or any other IP protocol).
Alternatives
switch to another OS, where you at least can use raw sockets without the restrictions of recent windows.
Implement a transparent drop insert solution based on the "Ethernet" or "IP" alternative above. i.e. you have your normal client application, your normal server application. You break a cable inbetween them, insert your box with 2 NICs where you programatically alter bytes of the frames received and send them back out again on the other NIC. This'll allow you to easily introduce packet delays in the system as well. Linux' netfilter already have this capability which you can easily build on top of, often with just configuration or scripting.
If you can alter the receiving application you want to test, have it read data from something else such as a file or pipe and feed it random bytes/packets as you wish.
Hybrid model, mainly for TCP application testing, but also useful for e.g. testing UDP ICMP responses. Set up a TCP connection using sockets. Send your invalid application data using sockets. Introduce random malformed packets(much easier than programming with raw sockets that set up a TCP session and then introduce lower layer errors). Send malformed IP or UDP/TCP packets, or perhaps ICMP packets using WinPcap, though communicate with the socket code to the winpcap code so you'll the addresses/port correct, such that the receiving application sees it.
Check out NS/2

C++ windows32 winsock UDP routing?

In C++ using Windows32 using windows socket library using UDP is there a way to give a client routing information to another client to establish a connection between clients without having to route through the server
Clarification:
server - waits for computers and gives routing info - a detached server
client - sends a ack request and waits for routing info - a normal user computer
but ok so its not posible to give routing info to clients to interconnect clients without requiring the data to be forwarded through the server?
Short answer: no.
Long answer: No matter what information you include in your UDP packet, at the transport layer it's just another IP packet, and your NIC will slap the appropriate headers on it and send it on its way. Unless the hosts are directly connected to each other, the network topology will dictate how many hops (routers/switches) it has to make to get there.
Addendum:
I'm not sure what you mean by server (I read it as "router" initially, but you could just as easily have been talking about a Domain Name Server (DNS)). If you are trying to avoid DNS lookup, you can easily do this by providing an IP address directly (assuming you know it). However, DNS lookup is a one-time process--once the IP address is known, the DNS host is not involved in routing your UDP packets in any way.
Short answer: no
Long answer: yes --- but you have to use IPPROTO_IP, not IPPROTO_UDP. Use IP_OPTIONS option in setsockopt() to set source routing.

Sending data between two ethernet interfaces on the same box

I would like to send data between two ethernet interfaces that are connected with a crossover cable in Linux. The two ethernet interfaces are on the same box. I defined the ethernet interfaces to have different static ip addresses (1.2.3.4 and 5.6.7.8) and have been using sockets to send bytes from one IP address to the other. I want to emphasize that I want the data to leave the box one interface of the box and get received on the other interface of the same box. One consequence of this is that unplugging the cable would prevent communication between the client and server on the same box.
The kernel is smarter than me I guess and decides it doesn't need to send information out on the wire and routes the data directly between the sockets internally, thus negating the test. I have tried to use SO_BINDTODEVICE to force the client to send data out of a particular interface, but the server never sees it. I am really stuck and this doesn't seem like it should be this difficult.
There are two entries in the route -n table
Dest Gateway Genmask flags metric use interface
1.2.3.0 0.0.0.0 255.255.255.0 U 0 0 eth0
5.6.7.0 0.0.0.0 255.255.255.0 U 0 0 eth1
You can not communicate using IP between 1.2.3.4/24 to 5.6.7.8/24 without going though a router. The problem is that IP can only talk to other computers in the same network segment. To calulate the network address you need to do a logic AND between both the interface address and the subnet mask. This will give you the network addresses. If the two network addresses are different then a router will be required. In your example you will have network address 1.2.3.0 and 5.6.7.0. Because these are different it will will to send data.
More importantly most network stacks are smart enough to see that if both interfaces are on the same computer it will not send the data all the way to the phyical interface. It will probably only send the message though the IP stack. But again it would need to be vaild address for it to work.
You should even be able to test a similar setup using just loopback network devices. (virtual network cards.)
Try using the following two IP addresses:
192.168.64.1
192.168.64.2
I'm not sure this is the problem, but 1.2.3.4 and 5.6.7.8 aren't on the same subnet. (Because when you apply the mask to each one, you don't get the same network address, as the Dest column is showing you.)