我该如何发送带有以太网尾部的数据报?如果我使用SocketType.Raw,我将不得不发送整个IP头,但我不知道如何做到这一点。
我该如何发送带有以太网尾部的数据报?如果我使用SocketType.Raw,我将不得不发送整个IP头,但我不知道如何做到这一点。
那个尾随数据包用于填充以达到以太网帧的最小长度(46字节有效载荷)。因此,发送一个小于18字节的UDP数据包(因为IP + UDP通常为28字节)。
也许类似这样的东西?
#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("创建套接字时出错\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("套接字已创建\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("绑定错误"); exit(1); }
printf("已绑定\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("发送失败\n"); break; } else { printf("已发送\n"); } }
close(s); return(1);
}
这样将会得到一个原始数据包,你可以在wireshark上看到它。如果你想要IP头,或者想把它变成UDP或其他类似的东西,你可以使用这种方法并自己构建头文件(这很简单,看看rfcs或者直接使用wireshark来查看一堆其他数据包的头文件)。请注意,对于UDP协议,你不必计算校验和0x0000是一个有效的校验和,应该可以通过。
如果你只想要一个在末尾有零的UDP数据包,那么这个稍微相同,可能更容易,让我知道即可。