标签:sockets raw-ethernet c-3 linux
我正在尝试使用C通过sendmsg发送原始以太网数据包.此代码成功打开一个原始数据包套接字,尝试用单个字节数组(char message [])填充struct iovec,然后用目标地址,地址长度和指向包含以下内容的struct iovec的指针填充struct msghdr消息. sendmsg()对于每个调用都返回EINVAL,但我不知道哪些参数无效. (我删除了一些perror()调用,以使该代码更易于阅读;输出为“无效参数”.)
我还没有找到任何有关sendmsg()如何与原始套接字一起工作的示例,但是使用sendto()的类似代码可以按预期工作.在该代码中,我明确地形成了以太网帧,包括标头和协议信息,但是据我了解,使用sendmsg()调用不是必需的吗?我也尝试过使message.iov_base指向一个缓冲区,该缓冲区包含包含14字节标头的显式格式的以太网帧,但是sendmsg()对此也很反感.
sendmsg()和sendmmsg()可以与原始以太网帧一起使用吗?关于iovec我是否缺少使它无效的东西?
30 int main(void) {
32 unsigned char dest[ETH_ALEN] = {0x11, 0x11, 0x11, 0x11, 0x11, 0x11}; // destination MAC address
33
34 // Socket variables
35 int s;
36 unsigned short protocol = htons(ETH_P_802_EX1);
38
39 // Message variables
40 char message[] = {"Test message. Test message. Test message!\n"};
41 size_t msg_len = strlen(message) + 1; // Message length includes null terminator
42 int e; // Error code
43 struct msghdr msg;
44 struct iovec msgvec;
45
46 // Setup source-side socket
47 s = socket(AF_PACKET, SOCK_RAW, protocol);
48 if (s < 0) { printf("%d: %s\n", errno, strerror(errno)); return EXIT_FAILURE; }
49
50 msgvec.iov_base = message;
51 msgvec.iov_len = msg_len;
52 memset(&msg, 0, sizeof(msg));
53 msg.msg_name = dest;
54 msg.msg_namelen = ETH_ALEN;
55 msg.msg_control = NULL;
56 msg.msg_controllen = 0;
57 msg.msg_flags = 0;
65 msg.msg_iov = &msgvec;
66 msg.msg_iovlen = 1;
67
68 for (int i=0; i<10; i++) {
69 e = sendmsg(s, &msg, 0);
73 }
79 close(s);
80 return EXIT_SUCCESS;
81 }
解决方法:
经过一些调整后,我使这段代码起作用.
我没有使用sendmsg()手册页中暗示的以字节字符串形式发送地址,而是使用struct sockaddr_ll.我也将iovec指向包含完整以太网帧(包括标头)的缓冲区.为什么手册页在sendto原型中显式指定了const struct sockaddr *,但msghdr定义中的void *对我来说仍然未知.
我在调用socket()之后添加了以下代码:
39 struct sockaddr_ll address;
40 struct ifreq buffer; // To get information with ioctl()
41 char ifname[] = {"eth0"};
42 int ifindex; // Interface index, from ioctl() call
57 memset(&buffer, 0, sizeof(buffer)); // Getting interface index value
58 strncpy(buffer.ifr_name, ifname, IFNAMSIZ);
59 ioctl(s, SIOCGIFINDEX, &buffer);
60 ifindex = buffer.ifr_ifindex;
61
62 // Setup sockaddr_ll address
63 memset( (void*) &address, 0, sizeof(address) );
64 address.sll_family = PF_PACKET;
65 address.sll_ifindex = ifindex;
66 address.sll_halen = ETH_ALEN;
67 memcpy( (void*) (address.sll_addr), (void*) dest, ETH_ALEN );
并将以下代码行替换为msghdr结构分配:
81 msg.msg_name = &address;
82 msg.msg_namelen = sizeof(address);
标签:sockets,raw-ethernet,c-3,linux 来源: https://codeday.me/bug/20191118/2028610.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。