I am trying to send an OAM ethernet frame using raw socket. I was successful in doing so.
The send function I have written is:
int send_frame(sock_info *info,char *buf,int length)
{
struct sockaddr_ll dest_addr;
memset(&dest_addr,0,sizeof(struct sockaddr_ll));
dest_addr.sll_family = PF_PACKET;
dest_addr.sll_protocol = htons(8902);
dest_addr.sll_ifindex = info->if_index;
dest_addr.sll_halen = ETH_MAC_ADDR_LEN;
dest_addr.sll_pkttype = PACKET_OTHERHOST;
dest_addr.sll_hatype = ARPHRD_ETHER;
memset(dest_addr.sll_addr,0,8);
dest_addr.sll_addr[0] = 0x00;
dest_addr.sll_addr[1] = 0xE0;
dest_addr.sll_addr[2] = 0x0C;
dest_addr.sll_addr[3] = 0x00;
dest_addr.sll_addr[4] = 0x95;
dest_addr.sll_addr[5] = 0x02;
return sendto(info->sock_fd, buf, length, 0, (struct sockaddr*) &dest_addr, sizeof(struct sockaddr_ll));
}
I was unable to capture the packet using wireshark. After tryiing too many things, I found out that buffer used to send should have all ethernet frame fields (starting from destination address). When I added the destination and source address and other ethernet fields into the buffer, I was able to capture the packet using wireshark. So the send function doesn't use the MAC address stored in dest_addr.sll_addr
.
My question is, Then what's the need of sll_addr
field in the struct sockaddr_ll
? Manuals say that it is the destination MAC address.
A raw socket allows an application to directly access lower level protocols, which means a raw socket receives un-extracted packets (see Figure 2). There is no need to provide the port and IP address to a raw socket, unlike in the case of stream and datagram sockets.
Raw packet is used when you dont have any, the first bytes captured are directly the IPv6 or IPv4 header. Raw IP; the packet begins with an IPv4 or IPv6 header, with the "version" field of the header indicating whether it's an IPv4 or IPv6 header.
A raw Ethernet packet is the complete Layer 2 network frame that is sent to the physical wire. Sending a frame like this allows you to manipulate the target and source MAC addresses and the Layer 3 protocol fields.
The raw socket interface provides direct access to lower layer protocols, such as the Internet Protocol (IP) and Internet Control Message Protocol (ICMP or ICMPv6). You can use raw sockets to test new protocol implementations.
To me it sounds like it works as the manual page describes it (man 7 packet):
SOCK_RAW packets are passed to and from the device driver without any changes in the packet data. When receiving a packet, the address is still parsed and passed in a standard sockaddr_ll address structure. When transmitting a packet, the user supplied buffer should contain the physical layer header. That packet is then queued unmodified to the network driver of the interface defined by the destination address. Some device drivers always add other headers. SOCK_RAW is similar to but not compatible with the obsolete PF_INET/SOCK_PACKET of Linux 2.0.
The buffer here refers to the 2nd parameter of sendto()
. So, the stuct sockaddr_ll is only used to return data to the caller, not to format the RAW packet. Maybe you want to user SOCK_DGRAM or libpcap instead?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With