summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoan Lledó <joanlluislledo@gmail.com>2019-06-22 12:00:02 +0200
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2019-08-12 00:00:23 +0200
commit9d671eb4dcc340eaed67cad7e0a9828c82c82231 (patch)
treeee95ca862f4064ddbd451091b71937d62ce099ea
parent3078c9460c62d2acbcea9c9a5eab6d666fad79e9 (diff)
lwip: Call if_change_flags() inside a thread-safe context
* lwip/port/netif/ifcommon.c: * Changing flags for a device (e.g. by inetutils-ifconfig) now takes the big lock to ensure the stack is not doing anything else. Message-Id: <20190622100002.11399-2-jlledom@member.fsf.org>
-rw-r--r--lwip/port/netif/ifcommon.c60
1 files changed, 55 insertions, 5 deletions
diff --git a/lwip/port/netif/ifcommon.c b/lwip/port/netif/ifcommon.c
index a7f28351..8a18f1d6 100644
--- a/lwip/port/netif/ifcommon.c
+++ b/lwip/port/netif/ifcommon.c
@@ -25,6 +25,8 @@
#include <net/if.h>
#include <errno.h>
+#include <lwip/tcpip.h>
+
/* Open the device and set the interface up */
static error_t
if_open (struct netif *netif)
@@ -99,6 +101,46 @@ if_terminate (struct netif * netif)
return ifc->terminate (netif);
}
+/* Args for _if_change_flags() */
+struct if_change_flags_args
+{
+ struct netif *netif;
+ uint16_t flags;
+ error_t err;
+};
+
+/*
+ * Implementation of if_change_flags(), called inside a thread-safe context
+ */
+static void
+_if_change_flags (void *arg)
+{
+ error_t err;
+ struct ifcommon *ifc;
+ uint16_t oldflags;
+ struct if_change_flags_args *args = arg;
+
+ ifc = netif_get_state (args->netif);
+
+ if (ifc == NULL)
+ {
+ /* The user provided no interface */
+ errno = EINVAL;
+ return;
+ }
+
+ oldflags = ifc->flags;
+
+ err = ifc->change_flags (args->netif, args->flags);
+
+ if (!err && ((oldflags ^ args->flags) & IFF_UP)) /* Bit is different ? */
+ err = ((oldflags & IFF_UP) ? if_close : if_open) (args->netif);
+
+ args->err = err;
+
+ return;
+}
+
/*
* Change device flags.
*
@@ -108,13 +150,21 @@ error_t
if_change_flags (struct netif * netif, uint16_t flags)
{
error_t err;
- struct ifcommon *ifc = netif_get_state (netif);
- uint16_t oldflags = ifc->flags;
- err = ifc->change_flags (netif, flags);
+ /*
+ * Call _if_change_flags() inside the tcpip_thread and wait for it to finish.
+ */
+ struct if_change_flags_args *args =
+ calloc (1, sizeof (struct if_change_flags_args));
+ args->netif = netif;
+ args->flags = flags;
+ err = tcpip_callback_wait(_if_change_flags, args);
+
+ if(!err)
+ /* Get the return value */
+ err = args->err;
- if ((oldflags ^ flags) & IFF_UP) /* Bit is different ? */
- ((oldflags & IFF_UP) ? if_close : if_open) (netif);
+ free (args);
return err;
}