- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试在 Linux (Ubuntu 18.04) 上的 C 中创建一个测试程序,该程序使用 SOCK_RAW
通过 AF_PACKET/PF_PACKET 套接字发送一个空的 UDP 数据包.在这个程序中,我知道源和目标 MAC 地址和 IP。但是,它不起作用,我不确定我做错了什么。遗憾的是,我无法在网上找到很多关于这个问题的资源,因为我发现的大多数线程都更适用于在 AF_PACKET 套接字上接收数据包。该程序还声明它将正确数量的字节发送到目的地。不过,我在使用 tcpdump
时看不到数据包在源虚拟机和目标虚拟机上。
这是程序的代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/ip.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <linux/if.h>
#include <linux/if_packet.h>
#include <linux/udp.h>
#include <net/ethernet.h>
#include <string.h>
#include <error.h>
#include <errno.h>
#include <inttypes.h>
#define REDIRECT_HEADER
#include "csum.h"
#define MAX_PCKT_LENGTH 65535
int main()
{
int sockfd;
struct sockaddr_ll dst;
char pckt[MAX_PCKT_LENGTH];
sockfd = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW);
if (sockfd <= 0)
{
perror("socket");
exit(1);
}
dst.sll_family = AF_PACKET;
dst.sll_protocol = ETH_P_IP;
if ((dst.sll_ifindex = if_nametoindex("ens18")) == 0)
{
fprintf(stdout, "Interface 'ens18' not found.\n");
exit(1);
}
// Do destination ethernet MAC (ae:21:14:4b:3a:6d).
dst.sll_addr[0] = 0xAE;
dst.sll_addr[1] = 0x21;
dst.sll_addr[2] = 0x14;
dst.sll_addr[3] = 0x4B;
dst.sll_addr[4] = 0x3A;
dst.sll_addr[5] = 0x6D;
dst.sll_halen = 6;
// I tried doing this with and without bind. Still not working.
if (bind(sockfd, (struct sockaddr *)&dst, sizeof(dst)) < 0)
{
perror("bind");
exit(1);
}
struct ethhdr *ethhdr = (struct ethhdr *) (pckt);
struct iphdr *iphdr = (struct iphdr *) (pckt + sizeof(struct ethhdr));
struct udphdr *udphdr = (struct udphdr *) (pckt + sizeof(struct ethhdr) + sizeof(struct iphdr));
unsigned char *data = (unsigned char *) (pckt + sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr));
// Do source ethernet MAC (1a:c4:df:70:d8:a6).
ethhdr->h_source[0] = 0x1A;
ethhdr->h_source[1] = 0xC4;
ethhdr->h_source[2] = 0xDF;
ethhdr->h_source[3] = 0x70;
ethhdr->h_source[4] = 0xD8;
ethhdr->h_source[5] = 0xA6;
// Copy destination MAC to sockaddr_ll.
memcpy(ethhdr->h_dest, dst.sll_addr, 6);
// Protocol.
ethhdr->h_proto = ETH_P_IP;
// Fill out ip header.
iphdr->ihl = 5;
iphdr->version = 4;
iphdr->frag_off = 0;
iphdr->id = rand();
iphdr->protocol = IPPROTO_UDP;
iphdr->tos = 0x0;
iphdr->ttl = 64;
iphdr->saddr = inet_addr("10.50.0.3");
iphdr->daddr = inet_addr("10.50.0.4");
iphdr->tot_len = sizeof(struct iphdr) + sizeof(struct udphdr);
iphdr->check = 0;
iphdr->check = ip_fast_csum(iphdr, iphdr->ihl);
// Fill out UDP header.
udphdr->source = htons(27000);
udphdr->dest = htons(27015);
udphdr->len = htons(sizeof(struct udphdr));
udphdr->check = 0;
udphdr->check = csum_tcpudp_magic(iphdr->saddr, iphdr->daddr, sizeof(struct udphdr), IPPROTO_UDP, csum_partial(udphdr, sizeof(struct udphdr), 0));
// Send packet
uint16_t sent;
if ((sent = sendto(sockfd, pckt, iphdr->tot_len + sizeof(struct ethhdr), 0, (struct sockaddr *)&dst, sizeof(dst))) < 0)
{
perror("sendto");
}
fprintf(stdout, "Sent %d of data.\n", sent);
close(sockfd);
exit(0);
}
ens18: flags=323<UP,BROADCAST,RUNNING,PROMISC> mtu 1500
inet 10.50.0.3 netmask 255.255.255.0 broadcast 10.50.0.255
inet6 fe80::18c4:dfff:fe70:d8a6 prefixlen 64 scopeid 0x20<link>
ether 1a:c4:df:70:d8:a6 txqueuelen 1000 (Ethernet)
RX packets 1959766813 bytes 1896024793559 (1.8 TB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 1936101432 bytes 1333123918522 (1.3 TB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
ens18: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.50.0.4 netmask 255.255.255.0 broadcast 10.50.0.255
inet6 fe80::ac21:14ff:fe4b:3a6d prefixlen 64 scopeid 0x20<link>
ether ae:21:14:4b:3a:6d txqueuelen 1000 (Ethernet)
RX packets 1032069029 bytes 1251754298166 (1.2 TB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 74446483 bytes 9498785163 (9.4 GB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
SOCK_RAW
在这种情况下,因为我想获得更多经验,并且我不希望内核对数据包做任何事情(我读到使用
AF_PACKET
+
SOCK_RAW
将导致内核不会弄乱数据包)。
AF_PACKET
提交每个数据包之前,我是否只需向目标服务器发送一个 ARP 请求并获取 MAC 地址? +
SOCK_RAW
?
最佳答案
我能够弄清楚这个问题。我没有通过 htons()
将以太网协议(protocol) ( ETH_P_IP ) 转换为网络字节顺序因为它是一个大端。话虽如此,我不得不转换 iphdr->total_len
网络字节顺序也是如此。否则,根据 tcpdump
,IP header 的总长度将不正确。 .我没有在我制作的其他程序中这样做,并且效果很好。因此,我假设内核自动将 IP header 的总长度转换为网络字节顺序。
由于我使用的是 AF_PACKET 套接字发送,我必须做内核通常会做的事情。
这是任何想知道的人的程序的最终代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/ip.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <linux/if.h>
#include <linux/if_packet.h>
#include <linux/udp.h>
#include <net/ethernet.h>
#include <string.h>
#include <error.h>
#include <errno.h>
#include <inttypes.h>
#define REDIRECT_HEADER
#include "csum.h"
#define MAX_PCKT_LENGTH 65535
int main()
{
int sockfd;
struct sockaddr_ll dst;
char pckt[MAX_PCKT_LENGTH];
sockfd = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW);
if (sockfd <= 0)
{
perror("socket");
exit(1);
}
dst.sll_family = PF_PACKET;
dst.sll_protocol = htons(ETH_P_IP);
if ((dst.sll_ifindex = if_nametoindex("ens18")) == 0)
{
fprintf(stdout, "Interface 'ens18' not found.\n");
exit(1);
}
// Do destination ethernet MAC (ae:21:14:4b:3a:6d).
dst.sll_addr[0] = 0xAE;
dst.sll_addr[1] = 0x21;
dst.sll_addr[2] = 0x14;
dst.sll_addr[3] = 0x4B;
dst.sll_addr[4] = 0x3A;
dst.sll_addr[5] = 0x6D;
dst.sll_halen = ETH_ALEN;
// I tried doing this with and without bind. Still not working.
if (bind(sockfd, (struct sockaddr *)&dst, sizeof(dst)) < 0)
{
perror("bind");
exit(1);
}
struct ethhdr *ethhdr = (struct ethhdr *) (pckt);
struct iphdr *iphdr = (struct iphdr *) (pckt + sizeof(struct ethhdr));
struct udphdr *udphdr = (struct udphdr *) (pckt + sizeof(struct ethhdr) + sizeof(struct iphdr));
unsigned char *data = (unsigned char *) (pckt + sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr));
// Do source ethernet MAC (1a:c4:df:70:d8:a6).
ethhdr->h_source[0] = 0x1A;
ethhdr->h_source[1] = 0xC4;
ethhdr->h_source[2] = 0xDF;
ethhdr->h_source[3] = 0x70;
ethhdr->h_source[4] = 0xD8;
ethhdr->h_source[5] = 0xA6;
for (int i = 0; i < 30; i++)
{
memcpy(data + i, "b", 1);
}
// Copy destination MAC to sockaddr_ll.
memcpy(ethhdr->h_dest, dst.sll_addr, ETH_ALEN);
// Protocol.
ethhdr->h_proto = htons(ETH_P_IP);
// Fill out ip header.
iphdr->ihl = 5;
iphdr->version = 4;
iphdr->frag_off = 0;
iphdr->id = htons(0);
iphdr->protocol = IPPROTO_UDP;
iphdr->tos = 0x0;
iphdr->ttl = 64;
iphdr->saddr = inet_addr("10.50.0.3");
iphdr->daddr = inet_addr("10.50.0.4");
iphdr->tot_len = htons(sizeof(struct iphdr) + sizeof(struct udphdr) + 30);
iphdr->check = 0;
iphdr->check = ip_fast_csum(iphdr, iphdr->ihl);
// Fill out UDP header.
udphdr->source = htons(27000);
udphdr->dest = htons(27015);
udphdr->len = htons(sizeof(struct udphdr) + 30);
udphdr->check = 0;
udphdr->check = csum_tcpudp_magic(iphdr->saddr, iphdr->daddr, sizeof(struct udphdr) + 30, IPPROTO_UDP, csum_partial(udphdr, sizeof(struct udphdr) + 30, 0));
// Send packet
uint16_t sent;
int len = ntohs(iphdr->tot_len) + sizeof(struct ethhdr) + 30;
if ((sent = sendto(sockfd, pckt, len, 0, (struct sockaddr *)&dst, sizeof(dst))) < 0)
//if ((sent = write(sockfd, pckt, len)) < 0)
{
perror("sendto");
}
fprintf(stdout, "Sent %d of data. %d is IPHdr len. %d is len.\n", sent, iphdr->tot_len, len);
close(sockfd);
exit(0);
}
关于c - AF_PACKET 套接字在 C 中不发送带有 SOCK_RAW 的空 UDP 数据包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60685437/
我正在开发类似 netcat 的工具(主要用于自学)。我想发送带有我通过 SOCK_RAW 套接字构造的 IP 和 UDP header 的数据包。我在 Debian VM 上运行以下代码以通过套接字
我是套接字编程的新手,正在Linux机器(ubuntu)上尝试使用它 我无法理解选项“SOCK_RAW”,并且想要了解它。 “套接字”系统调用中“SOCK_RAW”选项的意义是什么? 最佳答案 原始模
我想做同样的事情,在开源应用程序中将 SOCK_DGRAM 转换为 SOCK_RAW。 在 sendto 函数中,当套接字为 SOCK_DGRAM 类型时,然后仅发送 RTP 像这样的数据 这里,m-
我的问题已被here粗略地讨论过。 而tl; dr解决方案是: iptables -A OUTPUT -p tcp --tcp-flags RST RST -j DROP 您可以修改此设置,以仅阻止您
我做了一个简单的 ping 程序,因为我创建了一个 buffer 并且只有我填充了 IP frame 和 icmp 结构,当我运行该程序时它工作正常。 我查看了 Wireshark 中的执行情况,以太
我正在开发一个开源软件,其中 SOCK_DGRAM 用于发送 RTP 数据包。 像这样: int sock = socket(af, SOCK_DGRAM, 0); 但我应该使用与 SOCK_RAW
我正在尝试实现一个 IPv6 UDP 客户端-服务器应用程序,它将让我获得逐跳扩展 header 的详细信息。因此,为此我想我必须使用 SOCK_RAW 来访问 IPv6 header 信息。 现在在
#include #include #include #include #include #include #include #include #include #include
如果我创建一个类型为 SOCK_RAW 的套接字仅发送一些数据而不接收任何数据,当内核继续接收网络数据包并将其数据报复制到某个缓冲区(应用程序?)时是否有任何问题。也就是说,somebuffer被填满
好吧,我意识到这种情况有点不寻常,但我需要仅使用原始套接字(在 C 中,在 Linux 中)建立 TCP 连接(3 次握手)——即我需要构造 IP header 和我自己的 TCP header 。我
所以我用 socket(AF_INET, SOCK_RAW, IPPROTO_UDP) 创建了一个套接字。然后我有一个无限循环的 recv() 。我知道它可以捕获所有数据报。但它会阻止数据报到达正确的
soc = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));在客户端,运行时,得到== -1错误 如果accept函数只能与UDP和TCP高层协议(prot
我最近一直在研究网络与 c 代码和密码学,在思考随机问题时,我偶然发现了一段用于数据包嗅探的代码,我对函数 中使用的实际套接字有疑问从()接收()。套接字通过以下 sock 函数 rawSock =
好吧,我意识到这种情况有点不寻常,但我需要仅使用原始套接字(在 C 中,在 linux 中)建立 TCP 连接(3 次握手)——即我需要构建 IP header 和我自己的 TCP header 。我
我在 Windows 上创建了一个 ping 实用程序。我正在使用带有 ICMP 协议(protocol)的原始套接字。我是我电脑的本地管理员。 由于代码很多,我不想在这里粘贴,但我找到了一个与我的非
我正在尝试发送数据包(不是 ip 数据包,而是 EAP 请求标识),但是 send() 函数返回 -1。 int sockfd = socket(AF_INET, SOCK_RAW, 0);
大家好,我有个问题,我似乎找不到关于在多播上发送原始数据包的文档,所有示例、解决方案和文档都以 UDP 用法为中心。 我以此为例:http://svn.python.org/projects/stac
在 C 中的 linux 上,设置接口(interface) PROMISC 并使用原始套接字后,我可以通过 read() 读取接口(interface)上的传入数据包。 然而,它并没有得到所有的数据
如果我使用以下参数和默认设置打印出在 RAW 套接字上发送的 IP header 的 header 字段值,我看到协议(protocol)号设置为“2”,属于 IGMP。 sock = socket
我正在尝试在 Linux (Ubuntu 18.04) 上的 C 中创建一个测试程序,该程序使用 SOCK_RAW 通过 AF_PACKET/PF_PACKET 套接字发送一个空的 UDP 数据包.在
我是一名优秀的程序员,十分优秀!