Receiving Ethernet frames from an UDP port - c

I need to listen on multiple UDP ports and process received datagrams as Ethernet frames. I cannot think of any other solution than creating a SOCK_RAW socket to receive ethernet frames, check if what I received is an UDP datagram and then extract the datagram to identify the UDP port.
Is there a better way? Is there some kind of socket that would let me receive UDP datagrams on a specific port and still access the whole Ethernet frame?

I suggest you to use pcap library. It's not hard and it's portable between wide area of systems. You can simply filter and capture what you want.
libpcap and WinPcap provide the packet-capture and filtering engines
of many open source and commercial network tools, including protocol
analyzers (packet sniffers), network monitors, network intrusion
detection systems, traffic-generators and network-testers.
Another suggestions is libcrafter which is a high-level packet creator and decoder. Though it's C++ only.

Not sure if this is supported on your platform, but try:
int s=socket(AF_INET,SOCK_PACKET,htons(ETH_P_ALL));
http://www.tldp.org/HOWTO/Ethernet-HOWTO-2.html

Related

How does the AF_PACKET socket work in Linux?

I am trying to write a C sniffer for Linux, and understand the actions happening in the kernel while sniffing.
I am having troubles finding an answer for the following question:
If I initialize my socket in the following way:
sock_raw = socket(AF_PACKET , SOCK_RAW , htons(ETH_P_ALL));
What happens in the kernel? How am I seeing all the incoming and outgoing packets, but not "hijacking" them? Because what I have understood do far is that when the kernel receives a packet, it sends it to the relevant protocol handler function. Therefore I can't understand - does the kernel clone the packet and sends it in addition to the socket I opened?
What happens in the kernel?
The kernel simply duplicates the packets as soon as it receives them from the physical layer (for incoming packets) or just before sending them out to the physical layer (for outgoing packets). One copy of each packet is sent to your socket (if you use ETH_PH_ALL then you are listening on all interfaces, but you could also bind(2) to a particular one). After a copy is sent to your socket, the other copy then continues being processed like it normally would (e.g. identifying and decoding the protocol, checking firewall rules, etc).
How am I seeing all the incoming and outgoing packets, but not "hijacking" them?
In order for hijacking to happen, you would need to write data to the socket injecting new packets (accurately crafted depending on the protocol you want to hijack). If you only read incoming packets, you are merely sniffing, without hijacking anything.
does the kernel clone the packet and sends it in addition to the socket I opened?
Yes, that's basically what happens. This image could help you visualize it.
man 7 packet also describes this:
Packet sockets are used to receive or send raw packets at the device driver (OSI Layer 2) level. They allow the user to implement protocol modules in user space on top of the physical layer.
The socket_type is either SOCK_RAW for raw packets including the link-level header or SOCK_DGRAM for cooked packets with the link-level header removed. The link-level header information is available in a common format in a sockaddr_ll structure. protocol is the IEEE 802.3 protocol number in network byte order. See the <linux/if_ether.h> include file for a list of allowed protocols. When protocol is set to htons(ETH_P_ALL), then all protocols are received. All incoming packets of that protocol type will be passed to the packet socket before they are passed to the protocols implemented in the kernel.

Debugging multicast reception

I'd like to debug multicast reception by the Linux kernel, because I'm not receiving any packets. Let me be more specific: I'm building a flexible userland transport mode network daemon. One of the options of running it, is using UDP sockets. One of the use cases, is to transport UDP packets that go to multicast addresses.
So I end up with UDP packets to a multicast destination, transported by a UDP packet to the same multicast destination. That's asking for trouble, I know, but I get away with it: using SO_BINDTODEVICE, I can pretty much cheat my way through the routing table and packets are sent out as I intended.
On the receiving side, I'm not so lucky. Linux does not give my receiving socket the multicast packets. It just won't see them, although tcpdump proves that they arrive at the interface. Note that unicast - using the very same sockets - is not a problem at all. I can send and receive them to my heart's content. Not so with multicast.
So I'd like to know what the Linux kernel 'thinks' in that bit between receiving the packet (which it obviously does), and giving it to my process' UDP server socket (which it doesn't do). Any thoughts?

raw socket listener

This is a quick question for linux c programming raw sockets. If I wanted to just listen to any interface with a raw socket, must I actually bind to an ip address or interface to listen to traffic? From what I understand, I feel like I should be able to just call sock(); and then start recvfrom() traffic. Maybe I'm wrong, but I've seen some programs that don't use it.
You are right, the only thing you will need to do is call socket() and then recvfrom(). Nevertheless be aware of the fact that there are some limitations with listening using SOCK_RAW.
If you're not using raw sockets on a "send-and-forget" basis, you will
be interested in reading the reply packet(s) for your raw packet(s).
The decision logic for whether a packet will be delivered to a raw
socket can be enumarated as such:
TCP and UDP packets are never delivered to raw sockets, they are always handled by the kernel protocol stack.
Copies of ICMP packets are delivered to a matching raw socket. For some of the ICMP types (ICMP echo request, ICMP timestamp request,
mask request) the kernel, at the same time, may wish to do some
processing and generate replies.
All IGMP packets are delivered to raw sockets: e.g. OSPF packets.
All other packets destined for protocols that are not processed by a kernel subsystem are delivered to raw sockets.
The fact that you're dealing with a protocol for which reply packets
are delivered to your raw socket does not necessarily mean that you'll
get the reply packet. For this you may also need to consider:
setting the protocol accordingly while creating your socket via socket(2)system call. For instance, if you're sending an ICMP
echo-request packet, and want to receive ICMP echo-reply, you can set
the protocol argument (3rd argument) to IPPROTO_ICMP).
setting the protocol argument in socket(2) to 0, so any protocol number in the received packet header will match.
defining a local address for your socket (via e.g. bind(2)), so if the destination address matches the socket's local address, it'll be
delivered to your application also.
For more details you can read e.g. this.
If you meant to capture the traffic on a interface, you can use libpcap.

WINAPI: CreateFile to Network Adapter to Read Raw Bytes

Is it possible to read a Network Adapter similar to a Serial Port? I know that Serial Ports can be read with CreateFile WINAPI Function. Is there a similar way to read raw bytes from a Network Adapter?
I am aware of the WiFi/Network Functions but the WiFi Examples are fairly sparse.
You can pass the SOCK_RAW flag when you create the socket using WSASocket() (or socket(), as your tastes run). This is described in further detail under TCP/IP Raw Sockets on MSDN.
From that page --
Once an application creates a socket
of type SOCK_RAW, this socket may be
used to send and receive data. All
packets sent or received on a socket
of type SOCK_RAW are treated as
datagrams on an unconnected socket.
Of note, Microsoft crippled their raw sockets implementation after Windows XP SP2; the details are described on the MSDN page in the section Limitations on Raw Sockets:
TCP data cannot be sent over raw sockets.
UDP datagrams with an invalid source address cannot be sent over raw
sockets.
A call to the bind function with a raw socket is not allowed.
If these limitations are too restrictive, you can fall back to the previously recommended winpcap library.
If you want to capture raw packets you need a support driver like WinPCAP to do that.

Accessing data link layer packets

I want to create a socket for accessing IPv4 packets from data link layer. From unix network programming V1,
socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP))
1)I am implementing a dhcp client, is this the correct way of doing that? (means without accessing data link layer, i cannot receive reply from dhcp server) or is there any other easier way?
also, since this socket will receive all IPv4 packets destined for my system, how should I distinguish dhcp reply packet from other packets?
2)please suggest me a good link/tuorial for network programming with data link layer access. In the above book, it is not detailed description.
This is my code
Did you tried looking at PCAP libraries?
It provides nice filtering functions on IP, port and other things.
Do you need the link layer headers too? If so, You need to use SOCK_RAW—SOCK_DGRAM will remove the link layer header before feeding it to your application.
You can identify DHCP requests by the source and destination ports, since DHCP generates traffic on UDP ports 67 and 68.

Resources