在Linux上使用IPv6原始UDP套接字时,sendto()函数出现“无效参数”错误

3
我正在尝试使用原始套接字发送UDP数据包。对于IPv4,一切正常,但我无法解决IPv6套接字的问题,其中sendto()总是显示无效参数。最初,我认为IPv6需要强制校验和,但是IPV6_CHECKSUM选项应该可以解决这个问题,所以现在我已经没有其他选择了。
我正在使用inaddr_any作为addr_from,使用某些ipv6地址作为addr_to,并使用相同的端口。我查看了send_ip工具源代码,它手动计算校验和并使用原始/原始套接字发送数据包,但我希望Linux根据基于策略的路由规则自动形成带有必要源地址的IP数据包。
是否有任何想法是问题的根本原因?或者有任何使用原始/IPPROTO_UDP套接字的可行示例吗?
提前感谢您!
PS:请忽略所有线程相关内容。
发送代码如下:
typedef struct thread_data {
    char msg[BUFFER_LENGTH];
    struct sockaddr_in6 addr_to;
    struct sockaddr_in6 addr_from;
} thread_data;

void create_packet( const thread_data* data, void** packet, size_t* size ) {
    size_t msg_len = strlen(data->msg), udp_len = sizeof(struct udphdr);
    struct udphdr udp = {0};

    udp.source = data->addr_from.sin6_port;
    udp.dest   = data->addr_to.sin6_port;
    udp.len    = htons(udp_len + msg_len);
    udp.check  = 0;

    *packet = malloc( udp_len + msg_len );
    if( !(*packet) ) {
        ERROR("malloc failed" );
    }

    memcpy( *packet, &udp, sizeof(struct udphdr));
    memcpy( (*packet) + udp_len, data->msg, msg_len);

    *size = udp_len + msg_len;
}

void client_thread( void* args ) {

    thread_data* data = (thread_data*)args;

    int sock = -1;
    if ( (sock = socket( AF_INET6, SOCK_RAW, IPPROTO_UDP )) < 0 ) {
        ERROR( "failed to create socket" );
    }

    int val = 2; //I tried to play with this value, but with no luck
    if( setsockopt( sock, IPPROTO_IPV6, IPV6_CHECKSUM, &val, sizeof(val) ) < 0 ) {
        ERROR("setsockopt failed" );
    }
    ssize_t res = sendto( sock, packet, size, 0, (struct sockaddr*)&(data->addr_to), sizeof(data->addr_to));
    if ( res < 0 ) {
        ERROR( "sendto failed" );
     }
}

对于addr_from,我使用了in6addr_any,而对于addr_to,我使用了一些可从主机访问的有效IPv6地址。端口号对于addr_to和addr_from是相同的。 - Alex
你用什么作为IPv6地址的“addr_to”? - Michael Hampton
似乎我在你的问题中漏掉了什么。完整的答案是:addr_to是sockaddr_in6结构体,填充有适当的IPv6地址和端口。 - Alex
这里是3ffe:80c0:22c:8132:a00:1bff:feff:1000。这有任何帮助吗? - Alex
现在你的问题可以得到回答了! - Michael Hampton
显示剩余3条评论
1个回答

0

您实际上尝试发送到一个无效的IPv6地址。

3ffe::/16范围内的地址是旧的6bone地址,已于几年前被废弃。这些地址现在被认为是无效的,并且可能会被现代操作系统、路由器等拒绝。


我明白了,尽管如此,我可以使用这个地址类通过常规或原始/原始IPv6套接字进行TCP和UDP通信。我认为,如果问题在于地址本身(例如,操作系统正在拒绝它),则无论套接字类型如何,问题都将持续存在。我有什么遗漏吗?更新:我尝试了3aaa而不是3ffe,但没有帮助。 - Alex
请尝试使用真实、有效的IPv6地址。 - Michael Hampton

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接