Index: configure.ac ================================================================== --- configure.ac +++ configure.ac @@ -1489,20 +1489,14 @@ AC_CHECK_HEADER(netinet/tcp.h, [ AC_DEFINE(OF_HAVE_NETINET_TCP_H, 1, [Whether we have netinet/tcp.h]) ]) AC_CHECK_HEADER(netinet/sctp.h, [ - AC_SEARCH_LIBS(sctp_recvv, sctp, [ - AC_DEFINE(OF_HAVE_SCTP, 1, [Whether we have SCTP]) - AC_DEFINE(OF_HAVE_NETINET_SCTP_H, 1, - [Whether we have netinet/sctp.h]) - AC_SUBST(USE_SRCS_SCTP, '${SRCS_SCTP}') - - AS_IF([test x"$ac_lib" != x""], [ - OBJFW_LIBS="$OBJFW_LIBS -l$ac_lib" - ]) - ]) + AC_DEFINE(OF_HAVE_SCTP, 1, [Whether we have SCTP]) + AC_DEFINE(OF_HAVE_NETINET_SCTP_H, 1, + [Whether we have netinet/sctp.h]) + AC_SUBST(USE_SRCS_SCTP, '${SRCS_SCTP}') ]) AC_CHECK_HEADERS([arpa/inet.h netdb.h sys/sockio.h]) AC_CHECK_HEADERS([net/if.h], [], [], [ #ifdef OF_HAVE_SYS_SOCKET_H # include Index: src/OFSCTPSocket.m ================================================================== --- src/OFSCTPSocket.m +++ src/OFSCTPSocket.m @@ -361,28 +361,41 @@ ssize_t ret; struct iovec iov = { .iov_base = buffer, .iov_len = length }; - struct sctp_rcvinfo rcvinfo; - socklen_t rcvinfoSize = (socklen_t)sizeof(rcvinfo); - unsigned int infotype = SCTP_RECVV_RCVINFO; - int flags = 0; + char cmsgBuffer[CMSG_SPACE(sizeof(struct sctp_rcvinfo))]; + struct msghdr msg = { + .msg_iov = &iov, + .msg_iovlen = 1, + .msg_control = cmsgBuffer, + .msg_controllen = sizeof(cmsgBuffer) + }; + struct cmsghdr *cmsg; if (_socket == OFInvalidSocketHandle) @throw [OFNotOpenException exceptionWithObject: self]; - if ((ret = sctp_recvv(_socket, &iov, 1, NULL, NULL, - &rcvinfo, &rcvinfoSize, &infotype, &flags)) < 0) + if ((ret = recvmsg(_socket, &msg, 0)) < 0) @throw [OFReadFailedException exceptionWithObject: self requestedLength: length errNo: _OFSocketErrNo()]; - if (info != NULL) { - if (infotype == SCTP_RECVV_RCVINFO && - rcvinfoSize >= (socklen_t)sizeof(rcvinfo)) { + if (info == NULL) + return ret; + + *info = nil; + + for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; + cmsg = CMSG_NXTHDR(&msg, cmsg)) { + if (cmsg->cmsg_level != IPPROTO_SCTP) + continue; + + if (cmsg->cmsg_type == SCTP_RCVINFO) { + struct sctp_rcvinfo rcvinfo; + memcpy(&rcvinfo, CMSG_DATA(cmsg), sizeof(rcvinfo)); OFNumber *streamID = [OFNumber numberWithUnsignedShort: rcvinfo.rcv_sid]; OFNumber *PPID = [OFNumber numberWithUnsignedLong: rcvinfo.rcv_ppid]; OFNumber *unordered = [OFNumber numberWithBool: @@ -390,12 +403,13 @@ *info = [OFDictionary dictionaryWithKeysAndObjects: OFSCTPStreamID, streamID, OFSCTPPPID, PPID, OFSCTPUnordered, unordered, nil]; - } else - *info = [OFDictionary dictionary]; + + break; + } } return ret; } @@ -467,19 +481,31 @@ .snd_ppid = (uint32_t) [[info objectForKey: OFSCTPPPID] unsignedLongValue], .snd_flags = ([[info objectForKey: OFSCTPUnordered] boolValue] ? SCTP_UNORDERED : 0) }; + char cmsgBuffer[CMSG_SPACE(sizeof(sndinfo))]; + struct cmsghdr *cmsg = (struct cmsghdr *)(void *)&cmsgBuffer; + struct msghdr msg = { + .msg_iov = &iov, + .msg_iovlen = 1, + .msg_control = &cmsgBuffer, + .msg_controllen = sizeof(cmsgBuffer) + }; if (_socket == OFInvalidSocketHandle) @throw [OFNotOpenException exceptionWithObject: self]; if (length > SSIZE_MAX) @throw [OFOutOfRangeException exception]; - if ((bytesWritten = sctp_sendv(_socket, &iov, 1, NULL, 0, &sndinfo, - (socklen_t)sizeof(sndinfo), SCTP_SENDV_SNDINFO, 0)) < 0) + cmsg->cmsg_level = IPPROTO_SCTP; + cmsg->cmsg_type = SCTP_SNDINFO; + cmsg->cmsg_len = CMSG_LEN(sizeof(sndinfo)); + memcpy(CMSG_DATA(cmsg), &sndinfo, sizeof(sndinfo)); + + if ((bytesWritten = sendmsg(_socket, &msg, 0)) < 0) @throw [OFWriteFailedException exceptionWithObject: self requestedLength: length bytesWritten: 0 errNo: _OFSocketErrNo()];