接收所有 IPv6 数据包
Receive all IPv6 packets
我如何接收所有 IPv6 数据包(TCP、UDP、ICMP 等),例如在 lo
接口上。我正在使用命令 ping6 ::1
发送 ICMP 数据包,但是收到了 none 个数据包。
谢谢
#include <linux/if_ether.h>
#include <error.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <netinet/in.h>
#include <netinet/ip6.h>
#include <string.h>
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
int main() {
int socket_fd;
char buffer[1480];
struct sockaddr_in6 sin6;
struct sockaddr sin;
socket_fd = socket(AF_INET6, SOCK_RAW, IPPROTO_RAW);
setsockopt(socket_fd , SOL_SOCKET , SO_BINDTODEVICE , "lo" , strlen("lo")+ 1 );
if (socket_fd < 0) {
perror("Failed to create socket");
}
ssize_t data_size;
// Why am I unable to receve any data?
data_size = recvfrom(socket_fd, buffer, 1480, 0, &sin, (socklen_t *) &sin);
return 0;
}
在尝试从中读取数据之前,您没有bind()
将套接字连接到地址。
When a socket is created with socket(2), it exists in a name space (address family) but has no address assigned to it. bind() assigns the address specified by addr to the socket referred to by the file descriptor sockfd. addrlen specifies the size, in bytes, of the address structure pointed to by addr. Traditionally, this operation is called "assigning a name to a socket".
另请参阅:how to bind raw socket to specific interface
RFC3542 表示如下:
We note that IPPROTO_RAW
has no special meaning to an IPv6 raw socket (and the IANA
currently reserves the value of 255 when used as a next-header
field).
因此 IPPROTO_RAW 未保留给 sending/receiving IPv6 数据包。
对于 IPv4,您可以使用 IPPROTO_RAW 仅用于发送,不能用于接收。见 man raw(7):
An IPPROTO_RAW socket is send only. If you really want to receive
all IP packets, use a packet(7) socket with the ETH_P_IP protocol.
Note that packet sockets don't reassemble IP fragments, unlike raw
sockets.
您可以使用以下内容:
socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))
但这可能会导致其他问题。
如果您只是想监控流量,请勾选pcap-library。
我如何接收所有 IPv6 数据包(TCP、UDP、ICMP 等),例如在 lo
接口上。我正在使用命令 ping6 ::1
发送 ICMP 数据包,但是收到了 none 个数据包。
谢谢
#include <linux/if_ether.h>
#include <error.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <netinet/in.h>
#include <netinet/ip6.h>
#include <string.h>
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
int main() {
int socket_fd;
char buffer[1480];
struct sockaddr_in6 sin6;
struct sockaddr sin;
socket_fd = socket(AF_INET6, SOCK_RAW, IPPROTO_RAW);
setsockopt(socket_fd , SOL_SOCKET , SO_BINDTODEVICE , "lo" , strlen("lo")+ 1 );
if (socket_fd < 0) {
perror("Failed to create socket");
}
ssize_t data_size;
// Why am I unable to receve any data?
data_size = recvfrom(socket_fd, buffer, 1480, 0, &sin, (socklen_t *) &sin);
return 0;
}
在尝试从中读取数据之前,您没有bind()
将套接字连接到地址。
When a socket is created with socket(2), it exists in a name space (address family) but has no address assigned to it. bind() assigns the address specified by addr to the socket referred to by the file descriptor sockfd. addrlen specifies the size, in bytes, of the address structure pointed to by addr. Traditionally, this operation is called "assigning a name to a socket".
另请参阅:how to bind raw socket to specific interface
RFC3542 表示如下:
We note that IPPROTO_RAW has no special meaning to an IPv6 raw socket (and the IANA currently reserves the value of 255 when used as a next-header field).
因此 IPPROTO_RAW 未保留给 sending/receiving IPv6 数据包。
对于 IPv4,您可以使用 IPPROTO_RAW 仅用于发送,不能用于接收。见 man raw(7):
An IPPROTO_RAW socket is send only. If you really want to receive all IP packets, use a packet(7) socket with the ETH_P_IP protocol. Note that packet sockets don't reassemble IP fragments, unlike raw sockets.
您可以使用以下内容:
socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))
但这可能会导致其他问题。
如果您只是想监控流量,请勾选pcap-library。