linux系统中,创建ipv6协议的raw接收服务端,当接收到对端的udp或者tcp报文并解析出对端源地址,并生成的ns组播地址,然后发送ns报文的程序代码
时间: 2024-03-17 09:42:47 浏览: 190
raw socket来实现ip报文的发送
4星 · 用户满意度95%
以下是一个简单的基于IPv6协议的Raw Socket的服务端程序,可以接收TCP或UDP报文,并解析出对端源地址,并生成NS组播地址,然后发送NS报文:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/icmp6.h>
#include <arpa/inet.h>
#include <netdb.h>
#define BUFFER_SIZE 1024
int main(int argc, char *argv[]) {
int sock_fd;
struct sockaddr_in6 server_addr;
char buffer[BUFFER_SIZE];
ssize_t num_bytes;
// 创建IPv6 Raw Socket
sock_fd = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
if (sock_fd == -1) {
perror("socket");
exit(EXIT_FAILURE);
}
// 初始化服务器地址结构体
bzero(&server_addr, sizeof(server_addr));
server_addr.sin6_family = AF_INET6;
server_addr.sin6_addr = in6addr_any;
// 绑定到本地地址
if (bind(sock_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
perror("bind");
exit(EXIT_FAILURE);
}
for (;;) {
// 读取数据报
num_bytes = recvfrom(sock_fd, buffer, BUFFER_SIZE, 0, NULL, NULL);
if (num_bytes == -1) {
perror("recvfrom");
exit(EXIT_FAILURE);
}
// 解析IP报文头
struct ip6_hdr *ip_header = (struct ip6_hdr *)buffer;
struct in6_addr src_addr = ip_header->ip6_src;
// 解析TCP或UDP报文头
uint8_t *transport_header = (uint8_t *)ip_header + sizeof(struct ip6_hdr);
uint16_t src_port = ntohs(*(uint16_t *)(transport_header));
uint16_t dst_port = ntohs(*(uint16_t *)(transport_header + sizeof(uint16_t)));
// 生成NS组播地址
struct in6_addr dst_addr;
dst_addr.s6_addr[0] = 0xff;
dst_addr.s6_addr[1] = 0x02;
dst_addr.s6_addr[11] = 0x01;
dst_addr.s6_addr[12] = 0xff;
memcpy(&dst_addr.s6_addr[13], &src_addr.s6_addr[13], 3);
// 构造ICMPv6 NS报文
memset(buffer, 0, BUFFER_SIZE);
struct nd_neighbor_solicit *ns_header = (struct nd_neighbor_solicit *)buffer;
ns_header->nd_ns_type = ND_NEIGHBOR_SOLICIT;
ns_header->nd_ns_code = 0;
ns_header->nd_ns_target = src_addr;
struct sockaddr_in6 dst_sockaddr;
dst_sockaddr.sin6_family = AF_INET6;
dst_sockaddr.sin6_addr = dst_addr;
// 发送ICMPv6 NS报文
if (sendto(sock_fd, buffer, sizeof(struct nd_neighbor_solicit), 0, (struct sockaddr *)&dst_sockaddr, sizeof(dst_sockaddr)) == -1) {
perror("sendto");
exit(EXIT_FAILURE);
}
}
close(sock_fd);
return 0;
}
```
这个程序会不断接收TCP或UDP报文,并解析出对端源地址,然后生成NS组播地址,构造ICMPv6 NS报文,发送给对端。注意,这个程序需要以root权限运行。
阅读全文