Re: question on ethernet raw socket and vlan tag



On Mar 6, 3:10 am, yozh...@xxxxxxxxx wrote:
Hi,

I want to write a small program that can send out some specific vlan
traffic. However, I can not make it work. If I put something except
0x8100 as the eh->h_proto, I can capture this packet in the wire; If I
put 0x8100, I just get nothing.

How can I deal with this problem? Is there something I can turn on or
off to solve this problem. I am using FC6, and the source codes I am
using are modified fromhttp://www.landshut.org/bnla01/members/Faustus/fh/linux/udp_vs_raw/ch....

Thanks!

Yong

Example Code

Example 1.4. Create a RAW ethernet socket

#include <sys/socket.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h>

...

int s; /*socketdescriptor*/

s = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (s == -1) { errorhandling ... }

Example 1.5. Send a RAW ethernet frame

#define ETH_FRAME_LEN 1518

...

/*target address*/
struct sockaddr_ll socket_address;

/*buffer for ethernet frame*/
void* buffer = (void*)malloc(ETH_FRAME_LEN);

/*pointer to ethenet header*/
unsigned char* etherhead = buffer;

/*userdata in ethernet frame*/
unsigned char* data = buffer + 14;

/*another pointer to ethernet header*/
struct ethhdr *eh = (struct ethhdr *)etherhead;

int send_result = 0;

/*our MAC address*/
unsigned char src_mac[6] = {0x00, 0x01, 0x02, 0xFA, 0x70, 0xAA};

/*other host MAC address*/
unsigned char dest_mac[6] = {0x00, 0x04, 0x75, 0xC8, 0x28, 0xE5};

/*prepare sockaddr_ll*/

/*RAW communication*/
socket_address.sll_family = PF_PACKET;
/*we don't use a protocoll above ethernet layer
->just use anything here*/
socket_address.sll_protocol = htons(ETH_P_IP);

/*index of the network device
see full code later how to retrieve it*/
socket_address.sll_ifindex = 2;

/*ARP hardware identifier is ethernet*/
socket_address.sll_hatype = ARPHRD_ETHER;

/*target is another host*/
socket_address.sll_pkttype = PACKET_OTHERHOST;

/*address length*/
socket_address.sll_halen = ETH_ALEN;
/*MAC - begin*/
socket_address.sll_addr[0] = 0x00;
socket_address.sll_addr[1] = 0x04;
socket_address.sll_addr[2] = 0x75;
socket_address.sll_addr[3] = 0xC8;
socket_address.sll_addr[4] = 0x28;
socket_address.sll_addr[5] = 0xE5;
/*MAC - end*/
socket_address.sll_addr[6] = 0x00;/*not used*/
socket_address.sll_addr[7] = 0x00;/*not used*/

/*set the frame header*/
memcpy((void*)buffer, (void*)dest_mac, ETH_ALEN);
memcpy((void*)(buffer+ETH_ALEN), (void*)src_mac, ETH_ALEN);
eh->h_proto = 0x00;
/*fill the frame with some data*/
for (j = 0; j < 1500; j++) {
data[j] = (unsigned char)((int) (255.0*rand()/(RAND_MAX+1.0)));

}

/*send the packet*/
send_result = sendto(s, buffer, ETH_FRAME_LEN, 0,
(struct sockaddr*)&socket_address, sizeof(socket_address));
if (send_result == -1) { errorhandling... }

Example 1.6. Receive a RAW ethernet frame

void* buffer = (void*)malloc(ETH_FRAME_LEN); /*Buffer for ethernet
frame*/
int length = 0; /*length of the received frame*/
...
length = recvfrom(s, buffer, ETH_FRAME_LEN, 0, NULL, NULL);
if (length == -1) { errorhandling .... }


Try it by changing the ETH_FRAME_LEN as 1514. From the socket code,
should be able to manage only the 14 bytes of ethernet header. The
remaining 4 FCS bytes will be added by the NIC driver. I use the below
code to generate the packets with vlan tag.


#include<stdio.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<linux/if_ether.h>
#include<linux/if_packet.h>
#include<linux/if_arp.h>
#include<netinet/in.h>
#include<netinet/ip.h>
#include<netinet/ip_icmp.h>

//function definition for IP checksum

unsigned short int csum(unsigned short int *buff, int words) {
unsigned int sum, i;
sum = 0;
for(i = 0;i < words; i++){
sum = sum + *(buff + i);
}
sum = (sum >> 16) + sum;
return ~sum;
}


void main(int argc, char *argv[]) {

if(argc < 4) {
printf("Usage. %s SrcIP DstIP Packet_rate VLANid\n", argv[0]);
printf("Ex. %s 192.168.1.1 192.168.1.100 50\nSupply VLANid to generate
packets with VLAN tag\n");
exit(1);
}

int sock, n, tmp, tmp1, count = atoi(argv[3]), ethhdr_size = 14, stat
= 0;
unsigned short int vid = 0, vlanproto;
if(argc == 5) {
ethhdr_size = 18;
vid = htons(atoi(argv[4]));
}
struct sockaddr_ll sock_addr;
unsigned char buff[100] = { 0 };
struct ethhdr *eh = (struct ethhdr *)buff;
struct ip *iphdr = (struct ip *)(buff + ethhdr_size);
struct icmphdr *ich = (struct icmphdr *)(buff + sizeof(struct ip) +
ethhdr_size);

sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if(sock < 0) {
fprintf(stdout, "Error on creating the socket\n");
exit(1);
}


unsigned char dst_mac[6] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x56 };
unsigned char src_mac[6] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x10 };

sock_addr.sll_family = PF_PACKET;
sock_addr.sll_protocol = htons(ETH_P_IP);
sock_addr.sll_ifindex = 2;
sock_addr.sll_hatype = ARPHRD_ETHER;
sock_addr.sll_pkttype = PACKET_OTHERHOST;
sock_addr.sll_halen = ETH_ALEN;
sock_addr.sll_addr[0] = 0x00;
sock_addr.sll_addr[1] = 0x11;
sock_addr.sll_addr[2] = 0x22;
sock_addr.sll_addr[3] = 0x33;
sock_addr.sll_addr[4] = 0x44;
sock_addr.sll_addr[5] = 0x56;
sock_addr.sll_addr[6] = 0x00;
sock_addr.sll_addr[7] = 0x00;

memcpy((void *)buff, (void *)dst_mac, 6);
memcpy((void *)(buff + 6), (void *)src_mac, 6);
if(argc == 5) {
eh->h_proto = htons(0x8100);
vlanproto = htons(0x0800);
memcpy((void *)(buff + 14), (void *) &vid, 2);
memcpy((void *)(buff + 16), (void *) &vlanproto, 2);
} else {
eh->h_proto = htons(0x0800);
}

iphdr->ip_hl = 5;
iphdr->ip_v = 4;
iphdr->ip_tos = 0;
iphdr->ip_len = htons(sizeof(buff) - ethhdr_size);
iphdr->ip_id = 0;
iphdr->ip_off = 0;
iphdr->ip_ttl = 64;
iphdr->ip_p = 1;
iphdr->ip_sum = 0;
iphdr->ip_src.s_addr = inet_addr(argv[1]);
iphdr->ip_dst.s_addr = inet_addr(argv[2]);

ich->type = 8;
ich->code = 0;
ich->checksum = 0;
ich->un.echo.id = 0;
ich->un.echo.sequence = 11;

for(tmp = 0; tmp < 20; tmp++) {

ich->checksum = 0;
iphdr->ip_sum = 0;
ich->code = tmp;
ich->checksum = csum((unsigned short int *)(buff + sizeof(struct ip) +
ethhdr_size), 4);
iphdr->ip_sum = csum((unsigned short int *)(buff + ethhdr_size), iphdr-
ip_hl << 1 );

for(tmp1 = 0;tmp1 < count; tmp1++) {
n = (sendto(sock, buff, sizeof(buff), 0, (struct sockaddr
*)&sock_addr, sizeof(sock_addr)));
if(n < 0) {
perror("Perror");
fprintf(stdout, "Error on sending l2 packet \n");
} else {
printf(".");
stat++;
}
}

}
close(sock);
printf("\nStatistics: %d packets sent on the socket\n", stat);
}

.



Relevant Pages

  • Re: [PATCH] 802.1p priority (fixed)
    ... > that vlan 0 is reserved and means that the tag is only a priority. ... I don't object to an interface based solution. ... extern void setvlantag(const char *, int, int, const struct afswtch *rafp); ...
    (freebsd-net)
  • Re: Raw Ethernet Packet Capture
    ... I am writing a very basic raw ethernet sniffer based on what I found ... of char, and the compiler you are using is treating char as a signed ... you pass a char which is signed to printf (which is a variadic ... function) it gets promoted to s signed int (in most implementations, ...
    (comp.lang.c)
  • Re: [PATCH] 802.1p priority (fixed)
    ... extern void setvlantag(const char *, int, int, const struct afswtch *rafp); ... VLAN header for packets sent from the ...
    (freebsd-net)
  • Re: native vlan for mgmt
    ... I have a router with the fa0/0 configured with sub interfaces my mgmt vlan ... : int fa0/0 ... To complete a "Router on a Stick" Configuartion with VLAN 100 as the ... I cannot telnet to the switch or ping the switch on 10.1.10.15 or the router ...
    (comp.dcom.sys.cisco)
  • Re: NAT question
    ... interface and the other onto the new vlan. ... only have one active IP address for a vlan per switch on layer 2 ... int vlan1 ...
    (comp.dcom.sys.cisco)