sendto()linux上的IPv6 raw udp socket出现“invalid argument”错误

时间:2013-12-16 16:31:00

标签: c linux sockets udp ipv6

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

我使用inaddr_any作为addr_from,并使用相同端口的addr_to使用一些ipv6地址。我查看了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" );
     }
}

1 个答案:

答案 0 :(得分:0)

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

3ffe::/16内的地址是几年前退役的旧6bone地址。这些地址现在被视为无效,可能被现代操作系统,路由器等拒绝