在SOCK_ RAW通信中创建以太网帧
creating Ethernet frame in SOCK_RAW communication
我做了一个简单的ping程序,因为我创建了一个缓冲区,并且只有我填充了IP frame
和icmp stucture
。当我运行该程序时,它正常工作。
我查看了Wireshark中的执行情况,以太网帧已正确包含在echo请求,目标MAC地址正确(MAC可能在arp缓存中找到),但以太网帧已自动创建,即使我没有将其填充到sock_raw
套接字通信中使用的缓冲区中。
另一个问题是,我的朋友尝试了相同的代码,但当他在以太网头中签入Wireshark时,MAC地址是00.00.00.00.00,这意味着它将发送到每个设备,具有正确IP的相应设备将回复,但我的不是这样
代码在这里
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#define BUFFER_SIZE 100
#define DEFAULT_NUM_PACKETS 10
char buf[BUFFER_SIZE];
char *message = "n ./output_file <sender_ip_addr> <dest_ip_addr> <no_of_reqs>n
<no_of_req> = is the number of requests to send and 10 is the default and mentioning 0 is infiniten";
void set_ip_layer_fields(struct icmphdr *icmp, struct ip *ip)
{
// IP layer
ip->ip_v = 4;
ip->ip_hl = sizeof*ip >> 2;
ip->ip_tos = 0;
ip->ip_len = htons(sizeof(buf));
ip->ip_id = 0;
ip->ip_off = 0;
ip->ip_ttl = 255;
ip->ip_p = 1;
ip->ip_sum = 0;
// ICMP Layer
icmp->type = 8;
icmp->code = 0;
icmp->checksum = htons(~(ICMP_ECHO << 8));
}
int main(int argc, char *argv[])
{
int s, i ;
struct ip *ip = (struct ip *)buf;
struct icmphdr *icmp = (struct icmphdr *)(ip + 1);
struct hostent *hp, *hp2;
struct sockaddr_in dst;
int num = DEFAULT_NUM_PACKETS;
if(argc < 3)
{
fprintf(stdout, "%sn",message);
exit(1);
}
// If enough arguments supplied
if(argc == 4)
num = atoi(argv[3]);
// Loop based on the no of requests
for(i = 1; num == 0 ? num == 0 : i <= num; i++)
{
memset(buf, 0, sizeof(buf));
if((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
{
perror("socket() error");
exit(1);
}
if((hp = gethostbyname(argv[2])) == NULL)
{
if((ip->ip_dst.s_addr = inet_addr(argv[2])) == -1)
{
fprintf(stderr, "%s: unknown host.n", argv[2]);
exit(1);
}
}
else
memcpy(&ip->ip_dst.s_addr, hp->h_addr_list[0], hp->h_length);
if((hp2 = gethostbyname(argv[1])) == NULL)
{
if((ip->ip_src.s_addr = inet_addr(argv[1])) == -1)
{
fprintf(stderr, "%s: unknown hostn", argv[1]);
exit(1);
}
}
else
memcpy(&ip->ip_src.s_addr, hp2->h_addr_list[0], hp->h_length);
set_ip_layer_fields(icmp, ip);
dst.sin_addr = ip->ip_dst;
dst.sin_family = AF_INET;
if(sendto(s, buf, sizeof(buf), 0, (struct sockaddr *)&dst, sizeof(dst)) < 0)
{
fprintf(stderr, "error while sendingn");
}
else
printf("request:%d sended successfullyn",i);
close(s);
}
return 0;
}
区别在于如何声明套接字。
使用IPPROTO_RAW
-以太网标头为您提供,您可以提供从IP标头开始的所有内容。
使用htons(ETH_P_ALL)
-您可以提供一切,包括以太网标头。
更多信息请点击此处:http://www.pdbuchan.com/rawsock/rawsock.html
此外,使用IPPROTO_RAW
意味着隐式设置了选项IP_HDRINCL
,这意味着使用数据包中的IP标头中的IP,而不是放置在sendto
中的信息。
通常,如果在原始套接字中指定所有内容,则会使用send
而不是sendto
,因为用于发送的所有信息都在标头中可用。
点击此处阅读有关IP_HDRINCL
的更多信息:http://man7.org/linux/man-pages/man7/raw.7.html
相关文章:
- 如何创建一个CMake变量,除非显式重写,否则使用默认值
- 使用std::multimap迭代器创建std::list
- 在全局变量中保存类的实例以重新创建类(创建"backup")
- 使用CMake创建QML插件
- 如何在c++中为模板函数实例创建快捷方式
- 在C++中,是否可以基于给定的标识符创建基类的新实例,反之亦然
- 创建一个函数以在输入为负数或零时输出字符串.第一次执行用户定义的函数
- OpenCV EqualizeHist()从彩色图像创建黑白图像
- 试图在visual studio上用C++创建一个桌面应用程序
- std::threads可以从Windows DLL中的全局变量创建/销毁吗?
- 如何在C++20中创建模板别名的推导指南
- 如何为模板化对象创建模板向量?VS正在投掷C3203
- 如何创建一个空的全局类并在启动时实例化它
- 无法创建抽象类的实例
- 链接到自行创建的dll失败
- 为什么我不能在不创建字符串变量的情况下使用函数的字符串输出
- 有没有一种方法可以创建一个带有哈希表的数据库,该哈希表具有恒定时间查找功能
- 如何在C++类内存结构中创建"spacer"?
- 在SOCK_ RAW通信中创建以太网帧
- 使用boost asio原始套接字(在C++中)创建一个第2层/以太网套接字