Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 981
Alon Gubkin Avatar asked Aug 07 '10 12:08

Alon Gubkin


2 Answers

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.

like image 126
old_timer Avatar answered Sep 30 '22 21:09

old_timer


That trailer is used to pad ethernet frames to their minimum length (46 bytes of payload). So send a small UDP packet - smaller than 18 bytes (as IP + UDP is normally 28 bytes)

like image 42
nos Avatar answered Sep 30 '22 22:09

nos