c++csocketssctpgetsockopt

getsockopt "Invalid argument" for IPPROTO_SCTP, SCTP_STATUS


Scenario:

I've created SCTP one-to-many socket (functions that starts with big letter call corresponding standard functions with check for error and print errno to stderr)

int sock_fd,msg_flags;
char readbuf[BUFFSIZE];
struct sockaddr_in servaddr, cliaddr;
struct sctp_sndrcvinfo sri;
struct sctp_event_subscribe evnts;
int stream_increment=1;
socklen_t len;
size_t rd_sz;

sock_fd = Socket( AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);
bzero( &servaddr, sizeof( servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl( INADDR_ANY);
servaddr.sin_port = htons( SERV_PORT);

Bind( sock_fd, ( SA *) &servaddr, sizeof(servaddr));

bzero( &evnts, sizeof( evnts));
evnts.sctp_data_io_event = 1;
Setsockopt( sock_fd, IPPROTO_SCTP, SCTP_EVENTS, &evnts, sizeof( evnts));

Listen( sock_fd, LISTENQ);

Then I block in a call to sctp_recvmsg to read a message when it arrives

 rd_sz = Sctp_recvmsg( sock_fd, readbuf, sizeof( readbuf),
             (SA *)&cliaddr, &len, &sri,&msg_flags);

And after client connects I call getsockopt to retrieve the current state of an SCTP associations

len = sizeof(struct sockaddr_in);
socklen_t retsz;
struct sctp_status status;
retsz = sizeof(status); 
bzero(&status,sizeof(status));

status.sstat_assoc_id = sctp_address_to_associd(sock_fd, (SA *)&cliaddr, len);  
getsockopt( sock_fd, IPPROTO_SCTP, SCTP_STATUS, &status, &retsz);

function sctp_address_to_associd is:

sctp_assoc_t
sctp_address_to_associd(int sock_fd, struct sockaddr *sa, socklen_t salen)
{
    struct sctp_paddrparams sp;
    socklen_t siz;

    siz = sizeof(struct sctp_paddrparams);
    bzero(&sp,siz);
    memcpy(&sp.spp_address,sa,salen);
    sctp_opt_info(sock_fd,0,
           SCTP_PEER_ADDR_PARAMS, &sp, &siz);
    return(sp.spp_assoc_id);
}

Why getsockopt returns "Invalid argument"? errno = 22. OS is Linux Ubuntu 12.10.


Solution

  • The SCTP_PEER_ADDR_PARAMS socket option in the sctp_address_to_associd() function cannot be used to learn the association id, at least not on linux.

    Since you already get the association id from the sctp_recvmsg() call, use the association id of the struct sctp_sndrcvinfo instead:

    status.sstat_assoc_id = sri.sinfo_assoc_id;
    getsockopt( sock_fd, IPPROTO_SCTP, SCTP_STATUS, &status, &retsz);