我的程序应该发送UDP数据报,使用Raw套接字用于IPv6协议。
我必须在套接字选项中使用IPV6 CHECKSUM
。代码编译得很好,但是TCPDump的长度很差。
IP6 fe80 :: 20c:29ff:fe95:c051.24576> waw02s13-in-x03.1e100.net.0:UDP,坏长度12280> 40
我错过了什么或我做错了什么?
int main(int argc, char** argv) {
int sockfd;
int offset;
int retval;
struct addrinfo hints;
struct addrinfo *rp, *result;
unsigned char datagram[sizeof(struct ip6_hdr) + sizeof(struct udphdr)
] = {0};
struct ip6_hdr *ip_header = (struct ip6_hdr *)datagram;
struct udphdr *udp_header = (struct udphdr *)
(datagram + sizeof(struct ip6_hdr));
if (argc != 3) {
fprintf(
stderr,
"Invocation: %s <HOSTNAME OR IP ADDRESS> <PORT>\n",
argv[0]
);
exit(EXIT_FAILURE);
}
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_INET6;
hints.ai_socktype = SOCK_RAW;
hints.ai_protocol = IPPROTO_UDP;
retval = getaddrinfo(argv[1], NULL, &hints, &result);
if (retval != 0) {
fprintf(stderr, "getaddrinfo(): %s\n", gai_strerror(retval));
exit(EXIT_FAILURE);
}
offset = 6;
for (rp = result; rp != NULL; rp = rp->ai_next) {
sockfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if (sockfd == -1) {
perror("socket()");
continue;
}
retval = setsockopt(
sockfd,
IPPROTO_IPV6, IPV6_CHECKSUM,
&offset, sizeof(offset)
);
if (retval == -1) {
perror("setsockopt()");
exit(EXIT_FAILURE);
} else {
break;
}
}
if (rp == NULL) {
fprintf(stderr, "Client failure: could not create socket.\n");
exit(EXIT_FAILURE);
}
ip_header->ip6_flow = htonl((6 << 28) | (0 << 20) | 0);
ip_header->ip6_hops = 255;
ip_header->ip6_nxt = IPPROTO_UDP;
ip_header->ip6_plen = sizeof(struct ip6_hdr)
+ sizeof(struct udphdr);
inet_pton(AF_INET6, SOURCE_ADDRESS, &(ip_header->ip6_src));
inet_pton(AF_INET6, argv[1], &(ip_header->ip6_dst));
udp_header->uh_sport = htons(SOURCE_PORT);
udp_header->uh_dport = htons(atoi(argv[2]));
udp_header->uh_ulen = htons(ip_header->ip6_plen);
fprintf(stdout, "Sending UDP...\n");
for (;;) {
retval = sendto(
sockfd,
datagram, ip_header->ip6_plen,
0,
rp->ai_addr, rp->ai_addrlen
);
if (retval == -1) {
perror("sendto()");
}
sleep(1);
}
exit(EXIT_SUCCESS);
}
有什么想法吗?