【问题标题】:sendto() "invalid argument" error with IPv6 raw udp socket on linuxlinux上IPv6原始udp套接字的sendto()“无效参数”错误
【发布时间】:2014-01-04 03:12:06
【问题描述】:

我正在尝试使用原始套接字发送 udp 数据包。对于 IPv4,一切正常,但我无法解决 IPv6 套接字的问题,其中 sendto() 总是说无效参数。最初我在考虑 IPv6 的强制校验和,但 IPV6_CHECKSUM 选项应该可以解决这个问题,所以我现在没有选择。

我将 inaddr_any 用于 addr_from,并将一些 ipv6 地址用于 addr_to 具有相同的端口。我查看了 send_ip 工具源,它手动计算校验和并使用原始/原始套接字发送数据包,但我希望 linux 根据基于策略的路由规则自动形成具有必要源地址的 IP 数据包。

有没有人知道问题的根本原因是什么?或者任何使用 raw/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" );
     }
}

【问题讨论】:

  • 您使用什么作为 IPv6 地址 addr_fromaddr_to
  • 对于 addr_from,我使用了 in6addr_any,对于 addr_to,我使用了一些可以从主机访问的有效 IPv6 地址。 addr_to 和 addr_from 的端口号相同。
  • 您使用什么作为您的 IPv6 地址addr_to
  • 似乎我在你的问题中遗漏了一些东西。完整答案是:addr_to 是用 IPv6 地址和端口适当填充的 sockaddr_in6 结构。
  • 您说的是“一些有效的 IPv6 地址”。您需要准确说出实际地址。

标签: c linux sockets udp ipv6


【解决方案1】:

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

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

【讨论】:

  • 我明白了,不过我可以通过 tcp 和 udp 使用此类地址与普通或原始/原始 IPv6 套接字进行通信。我假设如果问题出在地址本身(例如操作系统拒绝它),无论套接字的类型如何,问题都会持续存在。我错过了什么吗?更新:我试过 3aaa 而不是 3ffe,但没有帮助。
  • 尝试使用真实、有效的 IPv6 地址。
猜你喜欢
  • 2018-06-16
  • 1970-01-01
  • 1970-01-01
  • 2015-12-07
  • 1970-01-01
  • 2016-01-07
  • 1970-01-01
  • 2015-07-27
  • 2020-02-20
相关资源
最近更新 更多