原始套接字在虚拟网络上发送两个数据包
当我尝试发送原始以太网数据包时,我在我的代码中遇到了sendto函数的问题。原始套接字在虚拟网络上发送两个数据包
我使用的Ubuntu 12.04.01 LTS,具有连接在两个vde_switches两个抽头的装置和一个dpipe
实施例:
我的发送PROGRAMM创建像下面的分组时,PROGRAMM被插座绑定从tap0发送数据包到tap1。在tap1上,一个接收器等待套接字上的所有数据包。
我的原始的以太网分组看起来如此:
目的地地址 __ _ _源地址 __ _ __ _ ___ 类型/长度 __ _数据
00:00:01:00:00:00_ __00:00:01:00:00:01_ ___ 长度字节_ _一些数据
实施例的分组发送:
00:00:01:00:00:00 00:00:01:00:00:01 (length in byte) (Message)test
但我PROGRAMM生成两个数据包,当我看到在Wireshark的:
第一分组是IPX包和[畸形报文]和十六进制看起来像(数据=试验)
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]
秒包未知协议
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
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);
}
}
请我需要一些帮助来查找我的错误。
谢谢你。
好吧,我明白为什么我的接收器收到两个数据包。第一个数据包是由我们发送的数据包,第二个数据包是单播给我们的。这个问题我不需要第一个数据包来接收。我测试了我的代码,并以这两个数据包为例进行了捕获。十六进制代码
第一架从Wireshark的:
0004 0001 0006 0000010000020000 0060 the message
第二帧:
0000 0001 0006 0000010000020000 1234 the message
这是Linux的熟捕获的手段:
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
我的问题:
Fi首先是可以过滤还是忽略第一个数据包?
第二个为什么包含第一个数据包是来自send结构的协议类型,第二个数据包是来自缓冲区的协议类型?
实施例:
对于第一分组
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;
为第二分组像802的缓冲区。3帧
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
我的接收器可以捕获第一分组而不2个vde_switches并且当我连接与dpipe和vde_plug开关我可以捕捉所述第二分组太之间的连接。
我建议你让这个问题成为一个新问题。添加一个新问题作为答案并不是这应该如何工作。 – thuovila
你是从所有网络设备捕获?这将解释你为什么得到两次包。尝试从一台设备捕获。为了捕获“到达”端,不要捕获发送数据包的设备,而是捕获发送数据包的设备。 – thuovila
这是从我的接收器代码剪断:创建套接字:sock_desc =套接字(AF_PACKET,SOCK_RAW,htons(ETH_P_ALL));在一个设备上绑定套接字:setsockopt(sock_desc,SOL_SOCKET,SO_BINDTODEVICE,&sock_in.ifr_name,strlen(sock_in.ifr_name));并接收数据包:recvfrom(sock_desc,buffer,ETH_FRAME_LEN,0,NULL,NULL); – Patzde
请给我们处理套接字创建操作的行。 我假设你已经创建了插座这样的:
int socket = socket(AF_PACKET,SOCK_RAW,IPPROTO_IP)
当你建立以太网头(顺便说一下,你应该使用而不是结构ethhdr,它的清洁剂),你是对的。 之后,您发送您的数据,而不会将L4标头和L3标头....这是正常的,您的代码不起作用。 我现在假设你是OSI Model。 如果不是这样的话,请在阅读下一篇文章之前阅读论文。
所以当你想创建一个RAW数据包时,你有很多事情要做。 例如,如果你想使用TCP/IP协议,你将不得不进行下一个工作
#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 ;
}
这是伪代码,但它告诉你如何发送原始数据包。 本文将做的工作适合你: RAW Socket TCP/IP
希望它会帮助你
安东尼
我觉得你的代码缺少以太网“包类型ID字段”。请参阅struct ethhdr in if_ether.h。现在您将convLen
放在原始位置。它可能匹配IPX的原始号码。尝试将其设置为某些内容(例如ETH_P_IP)或测试将其设置为零时发生的情况。
我知道你想制定自己的协议,并使用长度以太网地址后的字段。不过,我建议您至少保持以太网级别标头兼容,并在其之上(在以太网帧有效载荷中)构建自己的标头。否则你会遇到工具(比如wireshark)和试图解析以太网头的设备驱动程序的问题。至于你为什么发送两个数据包,我认为原因在于你从用户scanf输入的方式。 while循环是特有的。我建议尝试发送一些固定的输入数据,例如char msg[] = "Test";
对不起,如果答案是模糊的。这很难帮助你,因为你的代码不完整,我无法测试它。
这里的信息太少。你能否尝试做出一个完整的,可编辑的,有说服力的例子来展示你的问题。您是否使用RAW或DGRAM数据包套接字发送?请注意,PACKET_OTHERHOST对传出数据没有意义。 – thuovila