disconnecting interfaces properly on bridge destruction
[strongswan.git] / src / dumm / bridge.c
index fa30ab6..209e54f 100644 (file)
@@ -31,6 +31,11 @@ struct private_bridge_t {
        /** list of attached interfaces */
        linked_list_t *ifaces;
 };
+
+/**
+ * defined in iface.c
+ */
+bool iface_control(char *name, bool up);
        
 /**
  * Implementation of bridge_t.get_name.
@@ -41,24 +46,24 @@ static char* get_name(private_bridge_t *this)
 }
 
 /**
- * Implementation of bridge_t.create_iface_iterator.
+ * Implementation of bridge_t.create_iface_enumerator.
  */
-static iterator_t* create_iface_iterator(private_bridge_t *this)
+static enumerator_t* create_iface_enumerator(private_bridge_t *this)
 {
-       return this->ifaces->create_iterator(this->ifaces, TRUE);
+       return this->ifaces->create_enumerator(this->ifaces);
 }
 
 /**
- * Implementation of bridge_t.del_iface.
+ * Implementation of bridge_t.disconnect_iface.
  */
-static bool del_iface(private_bridge_t *this, iface_t *iface)
+static bool disconnect_iface(private_bridge_t *this, iface_t *iface)
 {
-       iterator_t *iterator;
-       iface_t *current;
+       enumerator_t *enumerator;
+       iface_t *current = NULL;
        bool good = FALSE;
 
-       iterator = this->ifaces->create_iterator(this->ifaces, TRUE);
-       while (iterator->iterate(iterator, (void**)&current))
+       enumerator = this->ifaces->create_enumerator(this->ifaces);
+       while (enumerator->enumerate(enumerator, (void**)&current))
        {
                if (current == iface)
                {
@@ -69,6 +74,8 @@ static bool del_iface(private_bridge_t *this, iface_t *iface)
                        }
                        else
                        {
+                               iface->set_bridge(iface, NULL);
+                               this->ifaces->remove_at(this->ifaces, enumerator);
                                good = TRUE;
                        }
                        break;
@@ -79,14 +86,14 @@ static bool del_iface(private_bridge_t *this, iface_t *iface)
                DBG1("iface '%s' not found on bridge '%s'", iface->get_hostif(iface),
                         this->name);
        }
-       iterator->destroy(iterator);
+       enumerator->destroy(enumerator);
        return good;
 }
 
 /**
- * Implementation of bridge_t.add_iface.
+ * Implementation of bridge_t.connect_iface.
  */
-static bool add_iface(private_bridge_t *this, iface_t *iface)
+static bool connect_iface(private_bridge_t *this, iface_t *iface)
 {
        if (br_add_interface(this->name, iface->get_hostif(iface)) != 0)
        {
@@ -94,6 +101,7 @@ static bool add_iface(private_bridge_t *this, iface_t *iface)
                         iface->get_hostif(iface), this->name);
                return FALSE;
        }
+       iface->set_bridge(iface, &this->public);
        this->ifaces->insert_last(this->ifaces, iface);
        return TRUE;
 }
@@ -108,7 +116,21 @@ static int instances = 0;
  */
 static void destroy(private_bridge_t *this)
 {
+       enumerator_t *enumerator;
+       iface_t *iface;
+
+       enumerator = this->ifaces->create_enumerator(this->ifaces);
+       while (enumerator->enumerate(enumerator, (void**)&iface))
+       {
+               if (br_del_interface(this->name, iface->get_hostif(iface)) != 0)
+               {
+                       DBG1("disconnecting iface '%s' failed: %m", iface->get_hostif(iface));
+               }
+               iface->set_bridge(iface, NULL);
+       }
+       enumerator->destroy(enumerator);
        this->ifaces->destroy(this->ifaces);
+       iface_control(this->name, FALSE);
        if (br_del_bridge(this->name) != 0)
        {
                DBG1("deleting bridge '%s' from kernel failed: %m", this->name);
@@ -139,9 +161,9 @@ bridge_t *bridge_create(char *name)
        
        this = malloc_thing(private_bridge_t);
        this->public.get_name = (char*(*)(bridge_t*))get_name;
-       this->public.create_iface_iterator = (iterator_t*(*)(bridge_t*))create_iface_iterator;
-       this->public.del_iface = (bool(*)(bridge_t*, iface_t *iface))del_iface;
-       this->public.add_iface = (bool(*)(bridge_t*, iface_t *iface))add_iface;
+       this->public.create_iface_enumerator = (enumerator_t*(*)(bridge_t*))create_iface_enumerator;
+       this->public.disconnect_iface = (bool(*)(bridge_t*, iface_t *iface))disconnect_iface;
+       this->public.connect_iface = (bool(*)(bridge_t*, iface_t *iface))connect_iface;
        this->public.destroy = (void*)destroy;
 
        if (br_add_bridge(name) != 0)
@@ -150,6 +172,10 @@ bridge_t *bridge_create(char *name)
                free(this);
                return NULL;
        }
+       if (!iface_control(name, TRUE))
+       {
+               DBG1("bringing bridge '%s' up failed: %m", name);
+       }
 
        this->name = strdup(name);
        this->ifaces = linked_list_create();