我正在尝试编写一个函数,该函数接收字节流(包括以太网头和可能封装在以太网数据包中的上层协议),并在特定接口上将其发送到网络上。
这是我的代码摘要:
// create socket
int s = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (s < 0) {
// error handling
}
// set up to just receive/send packets on one interface (stored in the variable iface_name e.g. eth0)
struct ifreq ifr;
bzero(&ifr, sizeof(struct ifreq));
strncpy(ifr.ifr_ifrn.ifrn_name, iface_name, IFNAMSIZ);
if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
// error handling
}
// set up socaddr for write
struct sockaddr sa;
sa.sa_family = PF_PACKET;
sa.sa_data = htons(ETH_P_ALL);
// write to wire
// buf has type char* and len has type int
// buf contains ethernet header, followed by payload (e.g. ARP packet or IP packet)
if ( sendto(s, buf, len, 0, &sa, sizeof(struct sockaddr) ) < 0 ) {
perror("sendto");
// more error handling
}
我得到错误
sendto: Invalid argument
如何解决此错误?
我最初的猜测是这是由
sa
参数引起的,因为所有其他参数都是相当标准的,没有什么大不了的。我可以用this example中的sockaddr_ll
类型的参数替换它,但这将意味着从buf
中提取标题信息,这似乎没有意义,因为它已经存在,可以开始使用了。肯定有更好的办法?封装,取消封装,重新封装,发送似乎有太多不必要的步骤。我正在为一些预先存在的代码编写底层接口,因此无法将输入修改为不包含数据链接层标头。 最佳答案
它是您的图书馆:
http://linux.die.net/man/7/raw
参见标题定义
看看他是怎么做插座的
他没有使用htons,而是:
IPPROTO_RAW位于
#include <netinet/in.h>
关于c - 在C(Linux)中将原始数据包注入(inject)网络,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/17970874/