added a "ipsec down-srcip <start> [<end>]" command to terminate IKE_SAs by remote...
authorMartin Willi <martin@strongswan.org>
Tue, 1 Jul 2008 12:48:56 +0000 (12:48 -0000)
committerMartin Willi <martin@strongswan.org>
Tue, 1 Jul 2008 12:48:56 +0000 (12:48 -0000)
src/charon/plugins/stroke/stroke_control.c
src/charon/plugins/stroke/stroke_control.h
src/charon/plugins/stroke/stroke_socket.c
src/ipsec/ipsec.in
src/stroke/stroke.c
src/stroke/stroke_keywords.h
src/stroke/stroke_keywords.txt
src/stroke/stroke_msg.h

index 2956b15..8fdd585 100644 (file)
@@ -18,6 +18,7 @@
 #include "stroke_control.h"
 
 #include <daemon.h>
+#include <processing/jobs/delete_ike_sa_job.h>
 
 typedef struct private_stroke_control_t private_stroke_control_t;
 
@@ -240,6 +241,75 @@ static void terminate(private_stroke_control_t *this, stroke_msg_t *msg, FILE *o
 }
 
 /**
+ * Implementation of stroke_control_t.terminate_srcip.
+ */
+static void terminate_srcip(private_stroke_control_t *this,
+                                                       stroke_msg_t *msg, FILE *out)
+{
+       enumerator_t *enumerator;
+       ike_sa_t *ike_sa;
+       host_t *start = NULL, *end = NULL, *vip;
+       chunk_t chunk_start, chunk_end, chunk_vip;
+       
+       if (msg->terminate_srcip.start)
+       {
+               start = host_create_from_string(msg->terminate_srcip.start, 0);
+       }
+       if (!start)
+       {
+               DBG1(DBG_CFG, "invalid start address: %s", msg->terminate_srcip.start);
+               return;
+       }
+       chunk_start = start->get_address(start);
+       if (msg->terminate_srcip.end)
+       {
+               end = host_create_from_string(msg->terminate_srcip.end, 0);
+               if (!end)
+               {
+                       DBG1(DBG_CFG, "invalid end address: %s", msg->terminate_srcip.end);
+                       start->destroy(start);
+                       return;
+               }
+               chunk_end = end->get_address(end);
+       }
+       
+       enumerator = charon->controller->create_ike_sa_enumerator(charon->controller);
+       while (enumerator->enumerate(enumerator, &ike_sa))
+       {
+               vip = ike_sa->get_virtual_ip(ike_sa, FALSE);
+               if (!vip)
+               {
+                       continue;
+               }
+               if (!end)
+               {
+                       if (!vip->ip_equals(vip, start))
+                       {
+                               continue;
+                       }
+               }
+               else
+               {
+                       chunk_vip = vip->get_address(vip);
+                       if (chunk_vip.len != chunk_start.len ||
+                               chunk_vip.len != chunk_end.len ||
+                               memcmp(chunk_vip.ptr, chunk_start.ptr, chunk_vip.len) < 0 ||
+                               memcmp(chunk_vip.ptr, chunk_end.ptr, chunk_vip.len) > 0)
+                       {
+                               continue;
+                       }
+               }
+
+               /* schedule delete asynchronously */
+               charon->processor->queue_job(charon->processor, (job_t*)
+                                               delete_ike_sa_job_create(ike_sa->get_id(ike_sa), TRUE));
+       }
+       enumerator->destroy(enumerator);
+       start->destroy(start);
+       DESTROY_IF(end);
+}
+
+/**
  * Implementation of stroke_control_t.route.
  */
 static void route(private_stroke_control_t *this, stroke_msg_t *msg, FILE *out)
@@ -336,6 +406,7 @@ stroke_control_t *stroke_control_create()
        
        this->public.initiate = (void(*)(stroke_control_t*, stroke_msg_t *msg, FILE *out))initiate;
        this->public.terminate = (void(*)(stroke_control_t*, stroke_msg_t *msg, FILE *out))terminate;
+       this->public.terminate_srcip = (void(*)(stroke_control_t*, stroke_msg_t *msg, FILE *out))terminate_srcip;
        this->public.route = (void(*)(stroke_control_t*, stroke_msg_t *msg, FILE *out))route;
        this->public.unroute = (void(*)(stroke_control_t*, stroke_msg_t *msg, FILE *out))unroute;
        this->public.destroy = (void(*)(stroke_control_t*))destroy;
index 9176792..9269644 100644 (file)
@@ -49,6 +49,13 @@ struct stroke_control_t {
        void (*terminate)(stroke_control_t *this, stroke_msg_t *msg, FILE *out);
        
        /**
+        * Terminate a connection by peers virtual IP.
+        *
+        * @param msg           stroke message
+        */
+       void (*terminate_srcip)(stroke_control_t *this, stroke_msg_t *msg, FILE *out);
+       
+       /**
         * Route a connection.
         *
         * @param msg           stroke message
index 92e295a..d8ea24e 100644 (file)
@@ -215,6 +215,20 @@ static void stroke_terminate(private_stroke_socket_t *this, stroke_msg_t *msg, F
        DBG1(DBG_CFG, "received stroke: terminate '%s'", msg->terminate.name);
 
        this->control->terminate(this->control, msg, out);
+}      
+
+/**
+ * terminate a connection by peers virtual IP
+ */
+static void stroke_terminate_srcip(private_stroke_socket_t *this,
+                                                                  stroke_msg_t *msg, FILE *out)
+{
+       pop_string(msg, &msg->terminate_srcip.start);
+       pop_string(msg, &msg->terminate_srcip.end);
+       DBG1(DBG_CFG, "received stroke: terminate-srcip %s-%s",
+                msg->terminate_srcip.start, msg->terminate_srcip.end);
+
+       this->control->terminate_srcip(this->control, msg, out);
 }
 
 /**
@@ -430,6 +444,9 @@ static job_requeue_t process(stroke_job_context_t *ctx)
                case STR_TERMINATE:
                        stroke_terminate(this, msg, out);
                        break;
+               case STR_TERMINATE_SRCIP:
+                       stroke_terminate_srcip(this, msg, out);
+                       break;
                case STR_STATUS:
                        stroke_status(this, msg, out, FALSE);
                        break;
index 9cae247..6ef2faf 100755 (executable)
@@ -116,6 +116,21 @@ down)
        fi
        exit "$rc"
        ;;
+down-srcip)
+       shift
+       if [ "$#" -lt 1 ]
+       then
+           echo "Usage: ipsec down-srcip <start> [<end>]"
+           exit 2
+       fi
+       rc=7
+       if [ -e $IPSEC_CHARON_PID ]
+       then
+               $IPSEC_STROKE down-srcip $*
+               rc="$?"
+       fi
+       exit "$rc"
+       ;;
 listalgs|listpubkeys|\listcards|\rereadgroups)
        op="$1"
        shift
index 90d99ac..01537b3 100644 (file)
@@ -158,6 +158,17 @@ static int terminate_connection(char *name)
        return send_stroke_msg(&msg);
 }
 
+static int terminate_connection_srcip(char *start, char *end)
+{
+       stroke_msg_t msg;
+       
+       msg.type = STR_TERMINATE_SRCIP;
+       msg.length = offsetof(stroke_msg_t, buffer);
+       msg.terminate_srcip.start = push_string(&msg, start);
+       msg.terminate_srcip.end = push_string(&msg, end);
+       return send_stroke_msg(&msg);
+}
+
 static int route_connection(char *name)
 {
        stroke_msg_t msg;
@@ -284,6 +295,9 @@ static void exit_usage(char *error)
        printf("  Terminate a connection:\n");
        printf("    stroke down NAME\n");
        printf("    where: NAME is a connection name added with \"stroke add\"\n");
+       printf("  Terminate a connection by remote srcip:\n");
+       printf("    stroke down-srcip START [END]\n");
+       printf("    where: START and optional END define the clients source IP\n");
        printf("  Set loglevel for a logging type:\n");
        printf("    stroke loglevel TYPE LEVEL\n");
        printf("    where: TYPE is any|dmn|mgr|ike|chd|job|cfg|knl|net|enc|lib\n");
@@ -354,6 +368,13 @@ int main(int argc, char *argv[])
                        }
                        res = terminate_connection(argv[2]);
                        break;
+               case STROKE_DOWNSRCIP:
+                       if (argc < 3)
+                       {
+                               exit_usage("\"down-srcip\" needs start and end address");
+                       }
+                       res = terminate_connection_srcip(argv[2], argc > 3 ? argv[3] : NULL);
+                       break;
                case STROKE_ROUTE:
                        if (argc < 3)
                        {
index 7bad0d4..b998631 100644 (file)
@@ -26,6 +26,7 @@ typedef enum {
        STROKE_UNROUTE,
        STROKE_UP,
        STROKE_DOWN,
+       STROKE_DOWNSRCIP,
        STROKE_LOGLEVEL,
        STROKE_STATUS,
        STROKE_STATUSALL,
index 672203c..dfe03fb 100644 (file)
@@ -33,6 +33,7 @@ route,           STROKE_ROUTE
 unroute,         STROKE_UNROUTE
 up,              STROKE_UP
 down,            STROKE_DOWN
+down-srcip,      STROKE_DOWNSRCIP
 loglevel,        STROKE_LOGLEVEL
 status,          STROKE_STATUS
 statusall,       STROKE_STATUSALL
index 8258fdc..40447e3 100644 (file)
@@ -158,6 +158,8 @@ struct stroke_msg_t {
                STR_DEL_CONN,
                /* terminate connection */
                STR_TERMINATE,
+               /* terminate connection by peers srcip/virtual ip */
+               STR_TERMINATE_SRCIP,
                /* show connection status */
                STR_STATUS,
                /* show verbose connection status */
@@ -187,6 +189,12 @@ struct stroke_msg_t {
                struct {
                        char *name;
                } initiate, route, unroute, terminate, status, del_conn, del_ca;
+               
+               /* data for STR_TERMINATE_SRCIP */
+               struct {
+                       char *start;
+                       char *end;
+               } terminate_srcip;
 
                /* data for STR_ADD_CONN */
                struct {