Sctp_connectx() дает EINVAL на FreeBSD

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/sctp.h>
#include <stdio.h>
#include <string.h>

int main(int argc,char **argv)
{

    struct sockaddr_in remoteAddr;

    int clientSock = socket(PF_INET,SOCK_SEQPACKET,IPPROTO_SCTP);
    if(clientSock == -1) {
        perror("socket");
        return 1;
    }
    memset(&remoteAddr,0,sizeof remoteAddr);
    remoteAddr.sin_family = AF_INET;
    remoteAddr.sin_len = sizeof remoteAddr;
    remoteAddr.sin_port = htons(5555);
    remoteAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    sctp_assoc_t assoc_id = 0;
    if(sctp_connectx(clientSock,(struct sockaddr*)&remoteAddr,1, &assoc_id)!= 0) {
        perror("sctp_connectx");
        return 1;
    }
    printf("Connected! Assoc ID %d\n",(int)assoc_id);

    return 0;   
}

При запуске этот код не работает:

$ clang  -Wall sctp_connect.c 
$ ./a.out 
sctp_connectx: Invalid argument
$ uname -rp
11.0-RELEASE-p9 amd64

Но я не могу понять, что случилось. sctp_connectx() manpage говорит, что с EINVAL произойдет сбой, если был указан адрес с недопустимым семейством или без адресов - но это, похоже, не случай из кода.

sctp_connectx() имеет несколько частей, где он может сбой с EINVAL, но truss показывает, что он получает вызов setsockopt() так что ядро, которое не выполняет вызов:

socket(PF_INET,SOCK_SEQPACKET,132)       = 3 (0x3)
mmap(0x0,2097152,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANON,-1,0x0) = 34374418432 (0x800e00000)
setsockopt(0x3,0x84,0x8007,0x800e16000,0x14)     ERR#22 'Invalid argument'

Ответ 1

Я думаю, что ответ есть в вашем запросе. Если мы следим за трассировкой truss, тогда, как вы сказали, она терпит неудачу на setsockopt().

Таким образом, фактическая ошибка EINVAL возвращается setsockopt(). И согласно руководству FreeBSD setsockopt():

[EINVAL]: установка accept_filter (9) на не прослушивании      сокета.

- описание ошибки. Поэтому я думаю, что вы должны делать что-то ниже:

  • Исследуйте параметры сокета, правильно ли они относятся к вашему гнезду слушателя.
  • Проверить ошибки для функций htons() и inet_addr()

И мое предложение состоит в том, что вы не должны использовать inet_addr(), более подробно см. раздел BUG руководства. Я бы рекомендовал вместо этого использовать inet_aton().