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() говорится, что это не удастся с 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'

person binary01    schedule 17.05.2017    source источник
comment
хороший минимальный воспроизводимый пример... хороший результат... попробуйте решить эту проблему в одиночку... почему этот вопрос не имеет голоса?   -  person Stargateur    schedule 22.06.2017
comment
Человек в Linux сказал EINVAL Неверный порт или адрес. Надеюсь, это поможет.   -  person Stargateur    schedule 22.06.2017
comment
Conectx подразумевает, что это интерфейс 1:1? Я думаю, что вы не можете использовать тип сокета SOCK_SEQPACKET, здесь вам нужно использовать SOCK_STREAM?   -  person amritanshu    schedule 22.06.2017
comment
@Stargateur Это не помогает. Тот же самый код отлично работает в Linux.   -  person binary01    schedule 23.06.2017
comment
@amritanshu Та же проблема при использовании SOCK_STREAM,   -  person binary01    schedule 23.06.2017
comment
да, на самом деле у меня нет настройки freebsd в основном на Linux, и я пытался экстраполировать вещи, чтобы помочь вам, обратите внимание, что я не получаю EINVAL на Linux для вашего кода. Двигаясь вперед, вызов setsocketopt будет отображаться в sctp_do_connectx в sctp_usrreq.c, одна из причин, по которой этот вызов для подключения может завершиться неудачей (с EINVAL), заключается в том, что SCTP_REUSE_PORT не включен для сокета.   -  person amritanshu    schedule 23.06.2017
comment
Он отлично работает для меня. Но у меня немного другая версия FreeBSD :( michalo@darkstar:~/src % ./a.out Connected! Assoc ID 3 michalo@darkstar:~/src % uname -rp 10.3-RELEASE-p11 amd64   -  person Oo.oO    schedule 28.06.2017
comment
попытаться выяснить, является ли ваш адрес действительным? напечатать адрес после преобразования его в строку ba2str(), кажется, вы не используете истинный аргумент freebsd.org/cgi/   -  person EsmaeelE    schedule 03.08.2017
comment
petanode.com/blog/posts/   -  person EsmaeelE    schedule 03.08.2017


Ответы (1)


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

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

[EINVAL]: была предпринята попытка установки accept_filter(9) на непрослушиваемый сокет.

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

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

И я предлагаю вам не использовать inet_addr(), для более подробной информации см. раздел «ОШИБКИ» руководства. Вместо этого я бы рекомендовал использовать inet_aton().

person Pushpendra    schedule 12.09.2017