[英]sendto returns with Invalid Argument on UDP Raw Socket ipv6 in Linux due to sin6_port value?
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/ip6.h>
#include <netinet/udp.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
struct ip6_hdr;
struct udphdr;
int main(){
int clientSocket, portNum, nBytes;
char buffer[1024];
struct sockaddr_in serverAddr;
struct sockaddr_in6 serverAddr6;
socklen_t addr_size;
struct hostent *hp;
struct msghdr m;
struct in_addr **addr_list;
/*Create UDP socket*/
clientSocket = socket(PF_INET6, SOCK_RAW, IPPROTO_RAW);
/*Configure settings in address struct*/
hp = gethostbyname2("2001:0db8:0:f101::2", PF_INET6);
memset((char *)&serverAddr6, 0, sizeof(serverAddr6));
memcpy((char *)&serverAddr6.sin6_addr, hp->h_addr, hp->h_length);
serverAddr6.sin6_family = hp->h_addrtype;
// serverAddr6.sin6_port = htons(7891);
serverAddr6.sin6_port = 0;//htons(IPPROTO_RAW);
/*Initialize size variable to be used later on*/
const size_t IPV6_HEADER_LEN = 40;
const size_t UDP_HEADER_LEN = 8;
addr_size = sizeof serverAddr6;
size_t data_len = sizeof(serverAddr6) - IPV6_HEADER_LEN;
/*Populate ip header*/
struct ip6_hdr *iphdr = (struct ip6_hdr *)buffer;
iphdr->ip6_flow = htonl ((6 << 28) | (0 << 20) | 0); // IPv6 version (4 bits), Traffic class (8 bits), Flow label (20 bits)
iphdr->ip6_plen = data_len;
iphdr->ip6_nxt = IPPROTO_UDP;
iphdr->ip6_hops = 64;
//supposing src_addr and dst_addr pointers are never NULL
memcpy(&iphdr->ip6_src, (const in6_addr*)&serverAddr6.sin6_addr, sizeof(in6_addr));
memcpy(&iphdr->ip6_dst, (const in6_addr*)&serverAddr6.sin6_addr, sizeof(in6_addr));
/*Populate UDP header*/
udphdr * udp_header = reinterpret_cast<udphdr *>(buffer + IPV6_HEADER_LEN);
udp_header->source = htons(0);
udp_header->dest = htons(7891);
int len = sizeof(serverAddr6);
uint32_t data_length = (len - (IPV6_HEADER_LEN + UDP_HEADER_LEN));
udp_header->len = htons(data_length + sizeof(udphdr));
udp_header->check = htons(0);
for (int i=0; i<10; ++i)
{
sprintf(buffer, "%d", i);
nBytes = strlen(buffer) + 1;
/*Send message to server*/
if(sendto(clientSocket,buffer,nBytes,0,(struct sockaddr *)&serverAddr6,addr_size) == -1 )
{
printf("sendto(): %s\n", strerror(errno));
exit(0);
}
/*Receive message from server*/
// nBytes = recvfrom(clientSocket,buffer,1024,0,NULL, NULL);
// nBytes = recvmsg(clientSocket,&m,0);
if((nBytes = recvmsg(clientSocket,&m, 0)) == -1)
{
printf("recvmsg(): %s\n", strerror(errno));
// exit(0);
}
printf("Received from server: %s\n",buffer);
}
return 0;
}
我是套接字編程的新手。 我有以下代碼。 它返回sendto():無效參數經過調查,我發現包含以下內容的行:serverAddr6.sin6_port = htons(7891); *在代碼段中進行了注釋:在Google的幫助下,我在http://osdir.com/ml/linux.ipv6.usagi.users/2003-03/msg00004.html中找到了一種解決方案:
從內核源代碼看來,當您使用原始ipv6套接字時,必須設置
dest.sin6_port = htons(IPPROTO_RAW);
並在http://osdir.com/ml/linux.ipv6.usagi.users/2003-03/msg00005.html中 :
dest.sin6_port=0;
另一方面,我不能采用這種建議的解決方案,因為我必須將端口指定為除0以外的其他值。
有什么建議或解釋嗎?
我正在使用Python 3,並且還遇到OSError: [Errno 22] Invalid argument
發送IPv6程序包時OSError: [Errno 22] Invalid argument
。 但是,當我將sendto
參數的端口號設置為0
,將成功發送數據包,並且仍使用腳本生成的數據包(程序中的buffer
中指定的端口。
您應該使用不同的端口號來生成數據包並調用sendto
。 使用所需的端口號生成並使用端口號0
調用。
以下是我的代碼
s = socket.socket(AF_INET6, SOCK_RAW, IPPROTO_RAW)
s.setsockopt(IPPROTO_IPV6, IP_HDRINCL, 1)
s.sendto(GenerateIPv6Packet('::1', 53, '::1', 53), ('::1', 0))
# generate the packet with port 53 and call sendto with port 0
很抱歉以其他編程語言回答。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.