routing/unrouting through interface
authorMartin Willi <martin@strongswan.org>
Wed, 16 May 2007 08:32:15 +0000 (08:32 -0000)
committerMartin Willi <martin@strongswan.org>
Wed, 16 May 2007 08:32:15 +0000 (08:32 -0000)
src/charon/control/interface_manager.c
src/charon/control/interfaces/stroke_interface.c
src/charon/sa/ike_sa.c
src/charon/sa/ike_sa.h

index 79f412e..8d9bdb6 100644 (file)
@@ -183,6 +183,62 @@ static bool terminate_child_listener(interface_bus_listener_t *this, signal_t si
 }
 
 /**
+ * listener function for route
+ */
+static bool route_listener(interface_bus_listener_t *this, signal_t signal,
+                                                  level_t level, int thread, ike_sa_t *ike_sa,
+                                                  char* format, va_list args)
+{
+       if (this->ike_sa == ike_sa)
+       {
+               if (!this->callback(this->param, signal, level, ike_sa, format, args))
+               {
+                       this->cancelled = TRUE;
+                       return FALSE;
+               }
+               switch (signal)
+               {
+                       case CHILD_ROUTE_SUCCESS:
+                       case CHILD_ROUTE_FAILED:
+                       {
+                               return FALSE;
+                       }
+                       default:
+                               break;
+               }
+       }
+       return TRUE;
+}
+
+/**
+ * listener function for unroute
+ */
+static bool unroute_listener(interface_bus_listener_t *this, signal_t signal,
+                                                    level_t level, int thread, ike_sa_t *ike_sa,
+                                                    char* format, va_list args)
+{
+       if (this->ike_sa == ike_sa)
+       {
+               if (!this->callback(this->param, signal, level, ike_sa, format, args))
+               {
+                       this->cancelled = TRUE;
+                       return FALSE;
+               }
+               switch (signal)
+               {
+                       case CHILD_UNROUTE_SUCCESS:
+                       case CHILD_UNROUTE_FAILED:
+                       {
+                               return FALSE;
+                       }
+                       default:
+                               break;
+               }
+       }
+       return TRUE;
+}
+
+/**
  * Implementation of interface_manager_t.initiate.
  */
 static status_t initiate(private_interface_manager_t *this,
@@ -377,6 +433,7 @@ static status_t terminate_child(interface_manager_t *this, u_int32_t reqid,
        
        if (child_sa == NULL)
        {
+               charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
                return NOT_FOUND;
        }
        
@@ -453,7 +510,40 @@ static status_t route(interface_manager_t *this,
                                          peer_cfg_t *peer_cfg, child_cfg_t *child_cfg,
                                          interface_manager_cb_t callback, void *param)
 {
-       return FAILED;
+       ike_sa_t *ike_sa;
+       ike_cfg_t *ike_cfg;
+       status_t status = SUCCESS;
+       
+       ike_cfg = peer_cfg->get_ike_cfg(peer_cfg);
+       
+       ike_sa = charon->ike_sa_manager->checkout_by_peer(charon->ike_sa_manager,
+                               ike_cfg->get_my_host(ike_cfg), ike_cfg->get_other_host(ike_cfg),
+                               peer_cfg->get_my_id(peer_cfg), peer_cfg->get_other_id(peer_cfg));
+       
+       if (ike_sa->get_peer_cfg(ike_sa) == NULL)
+       {
+               ike_sa->set_peer_cfg(ike_sa, peer_cfg);
+       }
+               
+       /* we listen passively only, as routing is done by one thread only */
+       if (callback)
+       {
+               interface_bus_listener_t listener;
+       
+               listener.listener.signal = (void*)route_listener;
+               listener.callback = callback;
+               listener.ike_sa = ike_sa;
+               listener.param = param;
+               listener.cancelled = FALSE;
+               charon->bus->add_listener(charon->bus, &listener.listener);
+       }
+       
+       if (ike_sa->route(ike_sa, child_cfg) != SUCCESS)
+       {
+               status = FAILED;
+       }
+       charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+       return status;
 }
 
 /**
@@ -462,7 +552,39 @@ static status_t route(interface_manager_t *this,
 static status_t unroute(interface_manager_t *this, u_int32_t reqid, 
                                                interface_manager_cb_t callback, void *param)
 {
-       return FAILED;
+       ike_sa_t *ike_sa;
+       status_t status;
+       
+       ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager,
+                                                                                                       reqid, TRUE);                                                   
+       if (ike_sa == NULL)
+       {
+               return NOT_FOUND;
+       }
+       
+       /* we listen passively only, as routing is done by one thread only */
+       if (callback)
+       {
+               interface_bus_listener_t listener;
+       
+               listener.listener.signal = (void*)unroute_listener;
+               listener.callback = callback;
+               listener.ike_sa = ike_sa;
+               listener.param = param;
+               listener.cancelled = FALSE;
+               charon->bus->add_listener(charon->bus, &listener.listener);
+       }
+       status = ike_sa->unroute(ike_sa, reqid);
+       if (status == DESTROY_ME)
+       {
+               charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, ike_sa);
+               status = SUCCESS;
+       }
+       else
+       {
+               charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+       }
+       return status;
 }
 
 /**
index 96dcc76..bbfc650 100755 (executable)
@@ -755,18 +755,17 @@ static void stroke_initiate(private_stroke_interface_t *this,
 }
 
 /**
- * route/unroute a policy (install SPD entries)
+ * route a policy (install SPD entries)
  */
 static void stroke_route(private_stroke_interface_t *this,
-                                                stroke_msg_t *msg, FILE *out, bool route)
+                                                stroke_msg_t *msg, FILE *out)
 {
-       route_job_t *job;
        peer_cfg_t *peer_cfg;
        child_cfg_t *child_cfg;
+       stroke_log_info_t info;
        
        pop_string(msg, &(msg->route.name));
-       DBG1(DBG_CFG, "received stroke: %s '%s'",
-                route ? "route" : "unroute", msg->route.name);
+       DBG1(DBG_CFG, "received stroke: route '%s'", msg->route.name);
        
        peer_cfg = get_peer_cfg_by_name(msg->route.name);
        if (peer_cfg == NULL)
@@ -787,10 +786,57 @@ static void stroke_route(private_stroke_interface_t *this,
                peer_cfg->destroy(peer_cfg);
                return;
        }
-       fprintf(out, "%s policy '%s'\n",
-                       route ? "routing" : "unrouting", msg->route.name);
-       job = route_job_create(peer_cfg, child_cfg, route);
-       charon->job_queue->add(charon->job_queue, (job_t*)job);
+       
+       info.out = out;
+       info.level = msg->output_verbosity;
+       charon->interfaces->route(charon->interfaces, peer_cfg, child_cfg,
+                                                         (interface_manager_cb_t)stroke_log, &info);
+       peer_cfg->destroy(peer_cfg);
+       child_cfg->destroy(child_cfg);
+}
+
+/**
+ * unroute a policy
+ */
+static void stroke_unroute(private_stroke_interface_t *this,
+                                                  stroke_msg_t *msg, FILE *out)
+{
+       char *name;
+       ike_sa_t *ike_sa;
+       iterator_t *iterator;
+       stroke_log_info_t info;
+       
+       pop_string(msg, &(msg->terminate.name));
+       name = msg->terminate.name;
+       
+       info.out = out;
+       info.level = msg->output_verbosity;
+       
+       iterator = charon->interfaces->create_ike_sa_iterator(charon->interfaces);
+       while (iterator->iterate(iterator, (void**)&ike_sa))
+       {
+               child_sa_t *child_sa;
+               iterator_t *children;
+               u_int32_t id;
+
+               children = ike_sa->create_child_sa_iterator(ike_sa);
+               while (children->iterate(children, (void**)&child_sa))
+               {
+                       if (child_sa->get_state(child_sa) == CHILD_ROUTED &&
+                               streq(name, child_sa->get_name(child_sa)))
+                       {
+                               id = child_sa->get_reqid(child_sa);
+                               children->destroy(children);
+                               iterator->destroy(iterator);
+                               charon->interfaces->unroute(charon->interfaces, id,
+                                                               (interface_manager_cb_t)stroke_log, &info);
+                               return;
+                       }
+               }
+               children->destroy(children);
+       }
+       iterator->destroy(iterator);
+       DBG1(DBG_CFG, "no such SA found");
 }
 
 /**
@@ -1479,10 +1525,10 @@ static void stroke_process(private_stroke_interface_t *this, int strokefd)
                        stroke_initiate(this, msg, out);
                        break;
                case STR_ROUTE:
-                       stroke_route(this, msg, out, TRUE);
+                       stroke_route(this, msg, out);
                        break;
                case STR_UNROUTE:
-                       stroke_route(this, msg, out, FALSE);
+                       stroke_unroute(this, msg, out);
                        break;
                case STR_TERMINATE:
                        stroke_terminate(this, msg, out);
index 16c87bf..d907f63 100644 (file)
@@ -935,7 +935,7 @@ static status_t route(private_ike_sa_t *this, child_cfg_t *child_cfg)
 /**
  * Implementation of ike_sa_t.unroute.
  */
-static status_t unroute(private_ike_sa_t *this, child_cfg_t *child_cfg)
+static status_t unroute(private_ike_sa_t *this, u_int32_t reqid)
 {
        iterator_t *iterator;
        child_sa_t *child_sa;
@@ -948,7 +948,7 @@ static status_t unroute(private_ike_sa_t *this, child_cfg_t *child_cfg)
        while (iterator->iterate(iterator, (void**)&child_sa))
        {
                if (child_sa->get_state(child_sa) == CHILD_ROUTED &&
-                       streq(child_sa->get_name(child_sa), child_cfg->get_name(child_cfg)))
+                       child_sa->get_reqid(child_sa) == reqid)
                {
                        iterator->remove(iterator);
                        SIG(CHILD_UNROUTE_SUCCESS, "CHILD_SA unrouted");
@@ -1873,7 +1873,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
        this->public.process_message = (status_t(*)(ike_sa_t*, message_t*)) process_message;
        this->public.initiate = (status_t(*)(ike_sa_t*,child_cfg_t*)) initiate;
        this->public.route = (status_t(*)(ike_sa_t*,child_cfg_t*)) route;
-       this->public.unroute = (status_t(*)(ike_sa_t*,child_cfg_t*)) unroute;
+       this->public.unroute = (status_t(*)(ike_sa_t*,u_int32_t)) unroute;
        this->public.acquire = (status_t(*)(ike_sa_t*,u_int32_t)) acquire;
        this->public.get_ike_cfg = (ike_cfg_t*(*)(ike_sa_t*))get_ike_cfg;
        this->public.set_ike_cfg = (void(*)(ike_sa_t*,ike_cfg_t*))set_ike_cfg;
index 0f977c7..0f01528 100644 (file)
@@ -333,12 +333,13 @@ struct ike_sa_t {
         * @brief Unroute a policy in the kernel previously routed.
         *
         * @param this                  calling object
-        * @param child_cfg             child config to unroute
+        * @param reqid                 reqid of CHILD_SA to unroute
         * @return                              
         *                                              - SUCCESS if route removed
+        *                                              - NOT_FOUND if CHILD_SA not found
         *                                              - DESTROY_ME if last CHILD_SA was unrouted
         */
-       status_t (*unroute) (ike_sa_t *this, child_cfg_t *child_cfg);
+       status_t (*unroute) (ike_sa_t *this, u_int32_t reqid);
        
        /**
         * @brief Acquire connection setup for an installed kernel policy.