Skip to content

Commit

Permalink
Use the kernel struct size for SCTP event subscription
Browse files Browse the repository at this point in the history
Signed-off-by: Ferenc Wágner <wferi@debian.org>
  • Loading branch information
wferi committed Dec 17, 2018
1 parent 81b209b commit f9b987c
Showing 1 changed file with 61 additions and 10 deletions.
71 changes: 61 additions & 10 deletions libknet/transport_sctp.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ typedef struct sctp_handle_info {
int listensockfd[2];
pthread_t connect_thread;
pthread_t listen_thread;
socklen_t event_subscribe_kernel_size;
const char *event_subscribe_buffer;
} sctp_handle_info_t;

/*
Expand Down Expand Up @@ -130,16 +132,11 @@ static int _close_connect_socket(knet_handle_t knet_h, struct knet_link *kn_link
static int _enable_sctp_notifications(knet_handle_t knet_h, int sock, const char *type)
{
int err = 0, savederrno = 0;
struct sctp_event_subscribe events;

memset(&events, 0, sizeof (events));
events.sctp_data_io_event = 1;
events.sctp_association_event = 1;
events.sctp_send_failure_event = 1;
events.sctp_address_event = 1;
events.sctp_peer_error_event = 1;
events.sctp_shutdown_event = 1;
if (setsockopt(sock, IPPROTO_SCTP, SCTP_EVENTS, &events, sizeof (events)) < 0) {
sctp_handle_info_t *handle_info = knet_h->transports[KNET_TRANSPORT_SCTP];

if (setsockopt(sock, IPPROTO_SCTP, SCTP_EVENTS,
handle_info->event_subscribe_buffer,
handle_info->event_subscribe_kernel_size) < 0) {
savederrno = errno;
err = -1;
log_err(knet_h, KNET_SUB_TRANSP_SCTP, "Unable to enable %s events: %s",
Expand Down Expand Up @@ -1314,6 +1311,15 @@ int sctp_transport_init(knet_handle_t knet_h)
int err = 0, savederrno = 0;
sctp_handle_info_t *handle_info;
struct epoll_event ev;
int test_socket;
char dummy_events[100];
struct sctp_event_subscribe *events;
/* Below we set the first 6 fields of this expanding struct.
* SCTP_EVENTS is deprecated, but SCTP_EVENT is not available
* on Linux; on the other hand, FreeBSD and old Linux does not
* accept small transfers, so we can't simply use this minimum
* everywhere. Thus we query and store the native size. */
const unsigned int subscribe_min = 6;

if (knet_h->transports[KNET_TRANSPORT_SCTP]) {
errno = EEXIST;
Expand All @@ -1329,6 +1335,51 @@ int sctp_transport_init(knet_handle_t knet_h)

knet_h->transports[KNET_TRANSPORT_SCTP] = handle_info;

test_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_SCTP);
if (test_socket < 0) {
savederrno = errno;
err = -1;
log_err(knet_h, KNET_SUB_TRANSP_SCTP, "Unable to create test socket: %s",
strerror(savederrno));
goto exit_fail;
}
handle_info->event_subscribe_kernel_size = sizeof dummy_events;
if (getsockopt(test_socket, IPPROTO_SCTP, SCTP_EVENTS, &dummy_events,
&handle_info->event_subscribe_kernel_size)) {
close(test_socket);
savederrno = errno;
err = -1;
log_err(knet_h, KNET_SUB_TRANSP_SCTP, "Unable to query kernel size of struct sctp_event_subscribe: %s",
strerror(savederrno));
goto exit_fail;
}
close(test_socket);
if (handle_info->event_subscribe_kernel_size < subscribe_min) {
savederrno = ERANGE;
err = -1;
log_err(knet_h, KNET_SUB_TRANSP_SCTP,
"No kernel support for the necessary notifications: struct sctp_event_subscribe is %u bytes, %u needed",
handle_info->event_subscribe_kernel_size, subscribe_min);
goto exit_fail;
}
events = calloc(1, handle_info->event_subscribe_kernel_size);
if (!events) {
savederrno = errno;
err = -1;
log_err(knet_h, KNET_SUB_TRANSP_SCTP,
"Failed to allocate event subscribe buffer: %s", strerror(savederrno));
goto exit_fail;
}
events->sctp_data_io_event = 1;
events->sctp_association_event = 1;
events->sctp_address_event = 1;
events->sctp_send_failure_event = 1;
events->sctp_peer_error_event = 1;
events->sctp_shutdown_event = 1;
handle_info->event_subscribe_buffer = (const char *)events;
log_debug(knet_h, KNET_SUB_TRANSP_SCTP, "Size of struct sctp_event_subscribe is %u in kernel, %zu in user space",
handle_info->event_subscribe_kernel_size, sizeof(struct sctp_event_subscribe));

knet_list_init(&handle_info->listen_links_list);
knet_list_init(&handle_info->connect_links_list);

Expand Down

0 comments on commit f9b987c

Please sign in to comment.