Question

I've a problem with my sendto function in my code, when I try to send a raw ethernet packet.

I use a Ubuntu 12.04.01 LTS, with two tap devices connected over two vde_switches and a dpipe

Example:

my send programm create the packet like below, the programm is binded by the socket from tap0 and send the packet to tap1. On tap1 one receiver wait for all packets on socket.

My raw ethernet packet looks so:

destination Addr ____source Addr _________ type/length ___data

00:00:01:00:00:00___00:00:01:00:00:01____ length in Byte__some data

Example packet to send:

00:00:01:00:00:00 00:00:01:00:00:01 (length in byte) (Message)test

but my programm generate two packets, when I look in wireshark:

first packet is an IPX packet and [Malformed Packet] and looks like in hex (data = test)

00 04 00 01 00 06 00 00 01 00 00 01 00 00 00 01 74 65 73 74 00

Linux cooked capture

Packet type: sent by us (4)

Link-layer address type: 1

Link-layer address length: 6

Source: 00:00:01:00:00:01

Protocol: Raw 802.3 (0x0001)

[Malformed Packet: IPX]

second packet unknown protocol

00 00 00 01 00 06 00 00 01 00 00 01 00 00 31 00 74 65 73 74 00

Linux cooked capture

Packet type: Unicast to us (0)

Link-layer address type: 1

Link-layer address length: 6

Source: 00:00:01:00:00:01

Protocol: Unknown (0x3100)

Data

Data: 7465737400

[Length: 5]

outcut from my source code

sock_desc = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));


/*struct for sending*/
    sock_addr.sll_family = AF_PACKET;
    sock_addr.sll_protocol = htons(ETH_P_802_3);
    sock_addr.sll_ifindex = if_nametoindex(argv[1]);
    sock_addr.sll_hatype = ARPHRD_ETHER; //Ethernet 10Mbps
    sock_addr.sll_pkttype = PACKET_HOST; // Paket zu irgendjemand
    sock_addr.sll_halen = ETH_ALEN; //6 Oktets in einer ethernet addr
    /*MAC Length 8 Oktets*/
    sock_addr.sll_addr[0] = frame.src_mac[0];
    sock_addr.sll_addr[1] = frame.src_mac[1];
    sock_addr.sll_addr[2] = frame.src_mac[2];
    sock_addr.sll_addr[3] = frame.src_mac[3];
    sock_addr.sll_addr[4] = frame.src_mac[4];
    sock_addr.sll_addr[5] = frame.src_mac[5];
    /*not in use*/  
    sock_addr.sll_addr[6] = 0x00;
    sock_addr.sll_addr[7] = 0x00;

    memset(buffer, '0', sizeof(char)*ETH_FRAME_LEN);
    /*set the frame header*/

    /*build RAW Ethernet packet*/
    buffer[0] = frame.dest_mac[0];
    buffer[1] = frame.dest_mac[1];
    buffer[2] = frame.dest_mac[2];
    buffer[3] = frame.dest_mac[3];
    buffer[4] = frame.dest_mac[4];
    buffer[5] = frame.dest_mac[5];

    buffer[6] = frame.src_mac[0];
    buffer[7] = frame.src_mac[1];
    buffer[8] = frame.src_mac[2];
    buffer[9] = frame.src_mac[3];
    buffer[10] = frame.src_mac[4];
    buffer[11] = frame.src_mac[5];

    while(frame.data[0] != '*'){
      printf("Input: ");
      scanf("%s", frame.data);

      tempLength = 0;
      while(frame.data[tempLength] != '\0'){
      tempLength++;
      }
      input = 0;
      for(sendLen = 14;sendLen <= (14+tempLength);sendLen++){
          buffer[sendLen] = frame.data[input];
          input++;
      }

      sprintf(convLen,"%x", (14 + input));
      buffer[12] = convLen[0];
      buffer[13] = convLen[1];

      length_in_byte = sendto(sock_desc, buffer, 14+input,0,(struct sockaddr*) &sock_addr,sizeof(struct sockaddr_ll));
      if(length_in_byte <= 0){
        printf("Error beim Senden");
      }else{
            printf("\n");
            printf("src: %02x:%02x:%02x:%02x:%02x:%02x\t->\tdest: %02x:%02x:%02x:%02x:%02x:%02x\n",frame.src_mac[0],frame.src_mac[1],frame.src_mac[2],frame.src_mac[3],frame.src_mac[4],frame.src_mac[5],frame.dest_mac[0],frame.dest_mac[1],frame.dest_mac[2],frame.dest_mac[3],frame.dest_mac[4],frame.dest_mac[5]);
            printf("Data: %s\n", frame.data);
      }
  }

please i need some help to find my mistake.

Thank you forward.

Was it helpful?

Solution 3

OK I see why my receiver receiv two packets. The first packet ist the send by us packet and the second is the Unicast to us. The problem I don't need the first packet to receive. I have test my code and have one capture with the two packets as example.

First frame in hex code from Wireshark:

0004 0001 0006 0000010000020000 0060 the message

Second frame:

0000 0001 0006 0000010000020000 1234 the message

This is Linux cooked capture an means:

2 Bytes packet typ // 0 = To us; 1 = Broadcast; 2 = Multicast; 3 = from somebody to somebody; 4 = sent by us

2 Bytes LINUX ARPHDR_ value
2 Bytes Link layer addr. lenght
8 Bytes source address
2 Bytes Ethernet protocol //e.g. 1 Novell 802.3 without 802.2 header; 4 frames with 802.2 header

My questions:

First is it possible to filter or ignore the first packet?

Second why contains the first packet the protocol typ from the send structur and the second packet the protocol typ from buffer?

Example:

For the first packet

sock_addr.sll_family = AF_PACKET;
sock_addr.sll_protocol = htons(0x0060);
sock_addr.sll_ifindex = 3;
sock_addr.sll_hatype = ARPHRD_ETHER;
sock_addr.sll_pkttype = PACKET_HOST;
sock_addr.sll_halen = ETH_ALEN; 
/*MAC Length 8 Oktets*/
sock_addr.sll_addr[0] = 0x00;
sock_addr.sll_addr[1] = 0x00;
sock_addr.sll_addr[2] = 0x01
sock_addr.sll_addr[3] = 0x00;
sock_addr.sll_addr[4] = 0x00;
sock_addr.sll_addr[5] = 0x02;
/*not in use*/  
sock_addr.sll_addr[6] = 0x00;
sock_addr.sll_addr[7] = 0x00;

for second packet the buffer like 802.3 frame

buffer[0-5] = 0x00 0x00 0x01 0x00 0x00 0x03 // Destination address
buffer[6-11] = 0x00 0x00 0x01 0x00 0x00 0x02 // Source address
buffer[12-13] = 0x12 0x34 // Protocol dummy typ

My receiver can capture the first packet without a connection between two vde_switches and when I connect the switches with dpipe and vde_plug can I capture the second packet too.

OTHER TIPS

Please give us the lines dealing with the socket creation operation. I assume you have created your socket like that :

int socket = socket(AF_PACKET,SOCK_RAW,IPPROTO_IP)

You are right when you build the ethernet header (by the way you should use instead struct ethhdr, it's cleaner). After that you send your data, without putting L4 header and L3 header.... It's normal that your code doesn't work. I assume you now the OSI Model. If it's not the case read the paper before reading the next text.

So when you want to create a RAW packet, you have many things to do before. For example if you want to use TCP/IP protocol you will have to do the next operation

 #include <unistd.h>
 #include <stdio.h>
 #include <sys/socket.h>
 #include <netinet/ip.h>
 #include <netinet/tcp.h>
 #DEFINE SIZEMAX 1000
 int main() {
 char buffer[65535] // MDU
 // CREATE YOUR SOCKET 
 int socket = socket(AF_PACKET,SOCK_RAW,IPPROTO_RAW) ; 
 // You can also specify some opt to your socket but I let you done your own stuffs
 struct ethhdr * ethdr ; 
 struct iphdr * iph ; 
 struct tcphdr * tcph; 
 // Fill all the fields of these last structures (i can't do it for you too long). 
 // Fill the buffer
 memcpy(buffer,ethdr,sizeof(struct ethhdr)) ; 
 // Deplace it to the good addr
 buffer = buffer + sizeof(struct ethhdr) ; 
 memcpy(buffer,iph,sizeof(struct iphdr)) ; 
 buffer = buffer + sizeof(struct iphdr)) ; 
 memcpy(buffer,tcph,sizeof(struct tcphdr)) ; 
 printf("your entry : \n") ; 
 char * entry = malloc(SIZEMAX) ; 
 sncanf("%s",entry,100) ; 
 buffer = buffer+ 100 ; 
 memcpy(buffer,entry,100) ; 
 int size_send = sendto(socket,.......) ;  
 if(size_send =< 0) 
   perror("error sending data") ; 

 return 0 ; 

}

This is pseudo-code but it tell you how to send raw packet. This paper will do the work for you : RAW Socket TCP/IP

Hope it will help you

Anthony

I think your code is missing the ethernet "packet type ID field". See struct ethhdr in if_ether.h. Now you put convLen where the proto should be. It probably matches the proto number of IPX. Try setting it to something (eg ETH_P_IP) or test what happens when you set it to zero.

I understand you want to make your own protocol and are using the field after the ethernet addresses for the length. However I do suggest you keep at least the ethernet level header standards compliant and build your own on top of that (in the ethernet frame payload). Otherwise youll get problems with tools(like wireshark) and device drivers that try to parse the ethernet headers.

As to why you send two packets, I think the reason lies in the way you scanf input from the user. The while loop is peculiar. I suggest trying to send some data with a fixed input, eg char msg[] = "Test";

Sorry if the answer is vague. It is difficult to help you, since your code is not complete and I can not test it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top