3

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" );
     }
}
manuell
  • 7,528
  • 5
  • 31
  • 58
Alex
  • 63
  • 1
  • 8

1 Answers1

0

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.

Michael Hampton
  • 9,737
  • 4
  • 55
  • 96
  • I see, nevertheless I'm able to communicate over tcp and udp using this class of addresses with usual or raw/raw IPv6 sockets. I assume if the problem is in the address itself(e.g OS is rejecting it) problem will persist disregarding to type of the socket. Am I missing something? Update: I've tried 3aaa instead of 3ffe, that didn't help. – Alex Dec 19 '13 at 12:19
  • Try using real, valid IPv6 addresses. – Michael Hampton Dec 19 '13 at 19:59