6
votes

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.

1

1 Answers

3
votes

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?