This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CC3200: Gratuitous ARP using raw socket

Part Number: CC3200

Hi,

We would like to send Gratuitous ARP while our device is connected.

Since no API can be used, we would like to use the raw socket to implement.

However, there is only little information about the raw socket.

If setting SL_SOCK_RAW in sl_socket(), the device cannot be connected according to your document.

So we use SL_SOCK_DGRAM in sl_socket(), but we do not know how to set the parameters because of a lack of information.

by setting SL_SOCK_DGRAM, layer 2 information is completed so that we do not need to build the MAC/LLC by ourselves?

But we still need to input the destination (FF:FF:FF:FF:FF:FF) in sendto(), LLC type to ARP, and so on.

Is there any idea how to accomplish this?

BR,

 Daniel.

  • Hi Daniel,

    Some documentation on using raw sockets can be found in the network programmer's guide. See this E2E post for more details:

    https://e2e.ti.com/support/wireless-connectivity/wifi/f/968/t/371144

    For raw sockets, there are different levels of raw socket. For the PHY and MAC level raw sockets, created using the SL_AF_RF option, you indeed do have to be disconnected from an AP. However, there also exists the option to use a network level raw socket, using sl_Socket(SL_AF_INET, SL_SOCK_RAW,...). If you then disable the IP headers through the sl_SetSockOpt(Sd, SL_IPPROTO_IP, SL_IP_HDRINCL,...) API, you can use the resulting raw socket to send and receive network layer packets such as ARP.

    There is the following E2E post with some code that you can use as a guide:

    https://e2e.ti.com/support/wireless-connectivity/wifi/f/968/p/821271/3055810#pi320995=1

    Do note that the code above may not accomplish exactly what you want, but it demonstrates opening a network-level raw socket. You'll have to work on your end to use that to build and send the needed ARP frame. TI does not have any official code or example that demonstrates the use of that network-level raw socket for ARP.

    Let me know if you need more clarification or have further questions on using raw sockets.

    Regards,

    Michael

  • Hi Michael,

    I have tried your suggestion but not work. The code is as follows.
    The return of every function seems right, but I cannot see any ARP packet from sniffer.
    Any suggestion or correction about this?

    BR,
    Daniel.


    #define ARP_HDR_LEN 8 /* base ARP header length */ #define ARP_ETHIP_LEN 20 /* base ARP message length */ #define ARP_HRD_ETH 0x0001 /* ethernet hardware */ #define ARP_PRO_IP 0x0800 /* IP protocol */ #define ETH_ADDR_LEN 6 #define IP_ADDR_LEN 4 #define ARP_OP_REQUEST 1 /* request to resolve ha given pa */ struct arp_hdr { uint16_t ar_hrd; /* format of hardware address */ uint16_t ar_pro; /* format of protocol address */ uint8_t ar_hln; /* length of hardware address (ETH_ADDR_LEN) */ uint8_t ar_pln; /* length of protocol address (IP_ADDR_LEN) */ uint16_t ar_op; /* operation */ }; struct arp_ethip { uint8_t ar_sha[ETH_ADDR_LEN]; /* sender hardware address */ uint8_t ar_spa[IP_ADDR_LEN]; /* sender protocol address */ uint8_t ar_tha[ETH_ADDR_LEN]; /* target hardware address */ uint8_t ar_tpa[IP_ADDR_LEN]; /* target protocol address */ }; void Wireless_Build_Arp_Packet(char* buf) { struct arp_hdr* arp1; struct arp_ethip* ethip; unsigned char mac[] = {0x00, 0xD0, 0xC9, 0xFD, 0x46, 0xCF}; unsigned char src_ip[4] = {0xc0, 0xa8, 0x02, 0x09}; unsigned char dest_mac[6] = {0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF}; unsigned char dest_ip[4] = {0xc0, 0xa8, 0x02, 0x09}; arp1 = (struct arp_hdr*)buf; arp1->ar_hrd = htons(ARP_HRD_ETH); arp1->ar_pro = htons(ARP_PRO_IP); arp1->ar_hln = ETH_ADDR_LEN; arp1->ar_pln = IP_ADDR_LEN; arp1->ar_op = ARP_OP_REQUEST; ethip = (struct arp_ethip*)(buf + ARP_HDR_LEN); memcpy(ethip->ar_sha, mac, ETH_ADDR_LEN); memcpy(ethip->ar_spa, &src_ip, IP_ADDR_LEN); memcpy(ethip->ar_tha, dest_mac, ETH_ADDR_LEN); memcpy(ethip->ar_tpa, &dest_ip, IP_ADDR_LEN); } void Wireless_Arp_Test() { int fd, ret, len; uint32_t header = 1; char buf[50]; SlTimeval_t tTimeout; fd = socket(SL_AF_INET, SL_SOCK_RAW, SL_IPPROTO_RAW); ret = sl_SetSockOpt(fd, SL_IPPROTO_IP, SL_IP_HDRINCL, &header, sizeof(header)); Wireless_Build_Arp_Packet(buf); len = ARP_HDR_LEN + ARP_ETHIP_LEN; ret = send(fd, buf, len, 0); close(fd); }

  • Hi,

    Have you tried also adding the Layer 2 ethernet header to the ARP frame that you send out? See this page for details on what to put in the ETH header: https://www.practicalnetworking.net/series/arp/traditional-arp/

    What output do you see on the sniffer when you send out the packet? Seeing how your air sniffer decodes your packet may give some clues as to what might be going wrong.

    Regards,

    Michael

  • Hi Michael,

    1. The Wi-Fi is not the same as ethernet, I do not think using ethernet header works.

    2. If I use the API: socket(SL_AF_INET, SL_SOCK_RAW, SL_IPPROTO_RAW)

        I have to build MAC and LLC layer by myself?

    BR,

     Daniel.

  • Hi Daniel,

    There is a method to open a L2 level socket, but still be connected to an AP. This uses the SL_AF_PACKET option, which is something I missed in your code previously. See the E2E thread here for an explanation on what you can do with that option:https://e2e.ti.com/support/wireless-connectivity/wifi/f/968/t/790971

    With the SL_AF_PACKET option to open what is logically an ETH socket, you need to add in the ethernet header to the ARP packet before you send it out. I fixed your ARP code to use the SL_AF_PACKET option and to add the ETH header before the ARP header:

    #define ARP_ETHIP_LEN 20 /* base ARP message length */
    
    #define ARP_HRD_ETH 0x0001 /* ethernet hardware */
    #define ARP_PRO_IP 0x0800 /* IP protocol */
    #define ETH_ADDR_LEN 6
    #define IP_ADDR_LEN 4
    #define ARP_OP_REQUEST 1 /* request to resolve ha given pa */
    
    struct arp_hdr {
        uint16_t ar_hrd; /* format of hardware address */
        uint16_t ar_pro; /* format of protocol address */
        uint8_t ar_hln;  /* length of hardware address (ETH_ADDR_LEN) */
        uint8_t ar_pln;  /* length of protocol address (IP_ADDR_LEN) */
        uint16_t ar_op;  /* operation */
    }arp_hdr;
    
    struct arp_ethip {
        uint8_t ar_sha[ETH_ADDR_LEN]; /* sender hardware address */
        uint8_t ar_spa[IP_ADDR_LEN];  /* sender protocol address */
        uint8_t ar_tha[ETH_ADDR_LEN]; /* target hardware address */
        uint8_t ar_tpa[IP_ADDR_LEN];  /* target protocol address */
    }arp_ethip;
    
    struct arp_eth_hdr {
        uint8_t dst_mac[ETH_ADDR_LEN];
        uint8_t src_mac[ETH_ADDR_LEN];
        uint8_t type[2];
    }arp_eth_hdr;
    #define ARP_HDR_LEN sizeof(arp_hdr)
    #define ETH_HDR_LEN sizeof(arp_eth_hdr)
    
    void Wireless_Build_Arp_Packet(char* buf)
    {
        struct arp_hdr* arp1;
        struct arp_ethip* ethip;
        struct arp_eth_hdr* ethhdr1;
        unsigned char mac[6] = {0x98, 0x84, 0xe3, 0xf5, 0xff, 0x4c};
        unsigned char src_ip[4] = {0xc0, 0xa8, 0x2b, 0xda};
        unsigned char dest_mac[6] = {0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF};
        unsigned char dest_ip[4] = {0xc0, 0xa8, 0x2b, 0x25};
        unsigned char eth_type[2] = {0x08, 0x06};
    
        ethhdr1 = (struct arp_eth_hdr*)buf;
        memcpy(ethhdr1->dst_mac, dest_mac, ETH_ADDR_LEN);
        memcpy(ethhdr1->src_mac, mac, ETH_ADDR_LEN);
        memcpy(ethhdr1->type, eth_type, 2);
    
    
        arp1 = (struct arp_hdr*)(buf+ ETH_HDR_LEN);
        arp1->ar_hrd = sl_Htons(ARP_HRD_ETH);
        arp1->ar_pro = sl_Htons(ARP_PRO_IP);
        arp1->ar_hln = ETH_ADDR_LEN;
        arp1->ar_pln = IP_ADDR_LEN;
        arp1->ar_op = sl_Htons(ARP_HRD_ETH);
    
        ethip = (struct arp_ethip*)(buf + ARP_HDR_LEN + ETH_HDR_LEN);
        memcpy(ethip->ar_sha, mac, ETH_ADDR_LEN);
        memcpy(ethip->ar_spa, src_ip, IP_ADDR_LEN);
        memcpy(ethip->ar_tha, dest_mac, ETH_ADDR_LEN);
        memcpy(ethip->ar_tpa, dest_ip, IP_ADDR_LEN);
    }
    void Wireless_Decode_Arp_Packet(char* buf){
        struct arp_hdr* arp1;
        struct arp_ethip* ethip;
        struct arp_eth_hdr* ethhdr1;
    
        ethhdr1 = (struct arp_eth_hdr*)buf;
        arp1 = (struct arp_hdr*)(buf+ ETH_HDR_LEN);
        ethip = (struct arp_ethip*)(buf + ARP_HDR_LEN + ETH_HDR_LEN);
        UART_PRINT("\n\rGot ARP response!\n\r");
        UART_PRINT("\n\rIP addr %i.%i.%i.%i ",ethip->ar_spa[0],ethip->ar_spa[1],ethip->ar_spa[2],ethip->ar_spa[3]);
        UART_PRINT("maps to MAC addr %x:%x:%x:%x:%x:%x!\n\r",ethip->ar_sha[0],ethip->ar_sha[1],ethip->ar_sha[2],ethip->ar_sha[3],ethip->ar_sha[4],ethip->ar_sha[5]);
    
    
    }
    void Wireless_Arp_Test()
    {
        int fd, ret, len;
        uint32_t header = 1;
        char buf[100];
        SlTimeval_t tTimeout;
    
        fd = sl_Socket(SL_AF_PACKET, SL_SOCK_RAW, SL_IPPROTO_RAW);
        Wireless_Build_Arp_Packet(buf);
        len = ARP_HDR_LEN + ARP_ETHIP_LEN + ETH_HDR_LEN;
        ret = sl_Send(fd, buf, len, 0);
        ret = sl_Recv(fd, buf, 40,0);
        Wireless_Decode_Arp_Packet(buf);
        sl_Close(fd);
    }

    Let me know if that doesn't work, or if you have further questions on using the low-level socket.

    Regards,
    Michael

  • Hi Michael,

    It works. Thanks for the help.

    BR,

     Daniel.