Skip to content

Commit

Permalink
Merge pull request #48 from chrissie-c/loopback-single
Browse files Browse the repository at this point in the history
loopback: Only allow 1 link to localhost if loopback is used.
  • Loading branch information
fabbione committed Aug 4, 2017
2 parents 5449d79 + 5fb923c commit ae071dd
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 29 deletions.
3 changes: 2 additions & 1 deletion libknet/libknet.h
Expand Up @@ -941,7 +941,8 @@ int knet_addrtostr(const struct sockaddr_storage *ss, socklen_t sslen,
* type is allowed. Data sent down a LOOPBACK link will be copied directly from
* the knet send datafd to the knet receive datafd so the application must be set
* up to take data from that socket at least as often as it is sent or deadlocks
* could occur.
* could occur. If used, a LOOPBACK link must be the only link configured to the
* local host.
*/

struct transport_info {
Expand Down
23 changes: 18 additions & 5 deletions libknet/link.c
Expand Up @@ -60,7 +60,7 @@ int knet_link_set_config(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t l
struct sockaddr_storage *dst_addr,
uint64_t flags)
{
int savederrno = 0, err = 0;
int savederrno = 0, err = 0, i;
struct knet_host *host;
struct knet_link *link;

Expand Down Expand Up @@ -99,13 +99,15 @@ int knet_link_set_config(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t l

if (transport == KNET_TRANSPORT_LOOPBACK && knet_h->host_id != host_id) {
log_err(knet_h, KNET_SUB_LINK, "Cannot create loopback link to remote node");
errno = EINVAL;
err = -1;
savederrno = EINVAL;
goto exit_unlock;
}

if (transport == KNET_TRANSPORT_LOOPBACK && knet_h->host_id != host_id && knet_h->has_loop_link) {
log_err(knet_h, KNET_SUB_LINK, "Cannot create more than 1 loopback link");
errno = EINVAL;
if (knet_h->host_id == host_id && knet_h->has_loop_link) {
log_err(knet_h, KNET_SUB_LINK, "Cannot create more than 1 link when loopback is active");
err = -1;
savederrno = EINVAL;
goto exit_unlock;
}

Expand All @@ -118,6 +120,17 @@ int knet_link_set_config(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t l
goto exit_unlock;
}

if (transport == KNET_TRANSPORT_LOOPBACK && knet_h->host_id == host_id) {
for (i=0; i<KNET_MAX_LINK; i++) {
if (host->link[i].configured) {
log_err(knet_h, KNET_SUB_LINK, "Cannot add loopback link when other links are already configured.");
err = -1;
savederrno = EINVAL;
goto exit_unlock;
}
}
}

link = &host->link[link_id];

if (link->configured != 0) {
Expand Down
84 changes: 61 additions & 23 deletions libknet/tests/api_knet_send_loopback.c
Expand Up @@ -65,73 +65,111 @@ static void test(void)
exit(FAIL);
}

printf("Test knet_send with no send_buff\n");
flush_logs(logfds[0], stdout);

printf("Test configuring multiple links with loopback\n");

if ((!knet_send(knet_h, NULL, KNET_MAX_PACKET_SIZE, channel)) || (errno != EINVAL)) {
printf("knet_send accepted invalid send_buff or returned incorrect error: %s\n", strerror(errno));
if (knet_handle_enable_sock_notify(knet_h, &private_data, sock_notify) < 0) {
printf("knet_handle_enable_sock_notify failed: %s\n", strerror(errno));
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}

datafd = 0;
channel = -1;

if (knet_handle_add_datafd(knet_h, &datafd, &channel) < 0) {
printf("knet_handle_add_datafd failed: %s\n", strerror(errno));
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}

flush_logs(logfds[0], stdout);
if (knet_host_add(knet_h, 1) < 0) {
printf("knet_host_add failed: %s\n", strerror(errno));
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}

printf("Test knet_send with invalid send_buff len (0)\n");
if (knet_link_set_config(knet_h, 1, 0, KNET_TRANSPORT_LOOPBACK, &lo, &lo, 0) < 0) {
printf("Unable to configure link: %s\n", strerror(errno));
knet_host_remove(knet_h, 1);
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}

if ((!knet_send(knet_h, send_buff, 0, channel)) || (errno != EINVAL)) {
printf("knet_send accepted invalid send_buff len (0) or returned incorrect error: %s\n", strerror(errno));
if (knet_link_set_config(knet_h, 1, 1, KNET_TRANSPORT_LOOPBACK, &lo, &lo, 0) == 0) {
printf("Managed to configure two LOOPBACK links - this is wrong\n");
knet_host_remove(knet_h, 1);
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}

flush_logs(logfds[0], stdout);
printf("Test configuring UDP link after loopback\n");

printf("Test knet_send with invalid send_buff len (> KNET_MAX_PACKET_SIZE)\n");

if ((!knet_send(knet_h, send_buff, KNET_MAX_PACKET_SIZE + 1, channel)) || (errno != EINVAL)) {
printf("knet_send accepted invalid send_buff len (> KNET_MAX_PACKET_SIZE) or returned incorrect error: %s\n", strerror(errno));
if (knet_link_set_config(knet_h, 1, 1, KNET_TRANSPORT_UDP, &lo, &lo, 0) == 0) {
printf("Managed to configure UDP and LOOPBACK links together: %s\n", strerror(errno));
knet_host_remove(knet_h, 1);
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}

flush_logs(logfds[0], stdout);
printf("Test configuring UDP link before loopback\n");

printf("Test knet_send with valid data\n");

if (knet_handle_enable_sock_notify(knet_h, &private_data, sock_notify) < 0) {
printf("knet_handle_enable_sock_notify failed: %s\n", strerror(errno));
if (knet_link_clear_config(knet_h, 1, 0) < 0) {
printf("Failed to clear existing LOOPBACK link: %s\n", strerror(errno));
knet_host_remove(knet_h, 1);
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
}

datafd = 0;
channel = -1;
if (knet_link_set_config(knet_h, 1, 0, KNET_TRANSPORT_UDP, &lo, &lo, 0) < 0) {
printf("Failed to configure UDP link for testing: %s\n", strerror(errno));
knet_host_remove(knet_h, 1);
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}

if (knet_handle_add_datafd(knet_h, &datafd, &channel) < 0) {
printf("knet_handle_add_datafd failed: %s\n", strerror(errno));
if (knet_link_set_config(knet_h, 1, 1, KNET_TRANSPORT_LOOPBACK, &lo, &lo, 0) == 0) {
printf("Managed to configure LOOPBACK link after UDP: %s\n", strerror(errno));
knet_host_remove(knet_h, 1);
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}

if (knet_host_add(knet_h, 1) < 0) {
printf("knet_host_add failed: %s\n", strerror(errno));
flush_logs(logfds[0], stdout);
printf("Test knet_send with valid data\n");

if (knet_link_clear_config(knet_h, 1, 0) < 0) {
printf("Failed to clear existing UDP link: %s\n", strerror(errno));
knet_host_remove(knet_h, 1);
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}

if (knet_link_set_config(knet_h, 1, 0, KNET_TRANSPORT_LOOPBACK, &lo, &lo, 0) < 0) {
printf("Unable to configure link: %s\n", strerror(errno));
printf("Failed configure LOOPBACK link for sending: %s\n", strerror(errno));
knet_host_remove(knet_h, 1);
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
Expand Down

0 comments on commit ae071dd

Please sign in to comment.