简体   繁体   中英

sendto() “invalid argument” error with IPv6 raw udp socket on linux

I'm trying to send udp packets with raw sockets. For IPv4 everything works fine, but I can't break through problem with IPv6 sockets, where sendto() always says invalid argument. Initially I was thinking about mandatory checksum for IPv6, but IPV6_CHECKSUM option should fix that, so I'm out of options now.

I'm using inaddr_any for addr_from, and some ipv6 address for addr_to with the same port. I looked through send_ip tool sources, it manually computes checksum and sends packet with raw/raw socket, but I want linux to automatically form IP packet with necessary source address according to policy based routing rules.

Does anyone have any ideas what is the root cause of the issue? Or any working example with raw/ipproto_udp socket?

Thanks in advance!

PS: please disregard all threading stuff

sending code is:

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" );
     }
}

You actually tried to send to an invalid IPv6 address.

Addresses within 3ffe::/16 are old 6bone addresses which were decommissioned several years ago. These addresses are now considered invalid, and may be rejected by modern operating systems, routers, etc.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM