Search code examples
network-programmingethernet

How can I send a datagram with an Ethernet trailer?


How can I send a datagram with an Ethernet trailer? If I use SocketType.Raw, I'll have to send the whole IP header and I have no idea how to do that.


Solution

  • Something like this perhaps?

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #include <unistd.h>
    
    #include <sys/socket.h>
    #include <linux/if_packet.h>
    #include <linux/if_ether.h>
    #include <linux/if_arp.h>
    
    #include <sys/ioctl.h>
    
    int s;
    
    unsigned char buffer[513];
    
    struct sockaddr_ll socket_address;
    
    int main ( void )
    {
        unsigned char seq;
        unsigned int ra;
        int length;
        struct ifreq ifr;
    
        s = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
        if (s == -1)
        {
            printf("error creating socket\n");
            return(1);
        }
    
        memset(&ifr,0, sizeof(struct ifreq));
        strncpy(ifr.ifr_name,"eth0",IFNAMSIZ);
        if(ioctl(s, SIOCGIFINDEX, &ifr) < 0)
        {
            perror("ioctl SIOCGIFINDEX");
            exit(1);
        }
    
        printf("index %d\n",ifr.ifr_ifindex);
    
    
        printf("socket created\n");
    
        memset(&socket_address,0,sizeof(socket_address));
    
        socket_address.sll_family = PF_PACKET;
        socket_address.sll_protocol = htons(ETH_P_ALL);
        socket_address.sll_ifindex = ifr.ifr_ifindex;
    
        if (bind(s, (struct sockaddr *)(&socket_address), sizeof(socket_address)) < 0)
        {
            perror("bind error");
            exit(1);
        }
    
        printf("bound\n");
    
        length=27;
    
        memset(buffer,0,sizeof(buffer));
    //destination
        buffer[ 0]=0xFF;
        buffer[ 1]=0xFF;
        buffer[ 2]=0xFF;
        buffer[ 3]=0xFF;
        buffer[ 4]=0xFF;
        buffer[ 5]=0xFF;
    //source
        buffer[ 6]=0x00;
        buffer[ 7]=0x19;
        buffer[ 8]=0xd1;
        buffer[ 9]=0x02;
        buffer[10]=0xdc;
        buffer[11]=0xb3;
    //length
        buffer[12]=((length-14)>>8)&0xFF;
        buffer[13]=((length-14)>>0)&0xFF;
    //payload
        buffer[14]=0x12;
        buffer[15]=0x34;
    
        for(ra=0;ra<20;ra++)
        {
            buffer[16]=ra;
            if(send(s,buffer,length,0) < 0 )
            {
                printf("sendto failed\n");
                break;
            }
            else
            {
                printf("sent\n");
            }
        }
    
        close(s);
        return(1);
    
    }
    

    That should give a raw packet that you can see on wireshark. if you want to have the ip eader, or make it a udp or something like that you can use this method and build the header yourself (it is trivial look at the rfcs or just use wireshark to look at a bunch of other packet headers). Note that for udp you do not have to compute a checksum 0x0000 is a valid checksum that is supposed to pass on through.

    If all you want is a udp packet with zeros at the end that is somewhat the same, probably easier, let me know.