supporting multiple comma seperated subnets in left/rightsubnet definition
authorMartin Willi <martin@strongswan.org>
Fri, 25 Apr 2008 12:41:37 +0000 (12:41 -0000)
committerMartin Willi <martin@strongswan.org>
Fri, 25 Apr 2008 12:41:37 +0000 (12:41 -0000)
e.g. leftsubnet=10.2.0.0/16,10.4.0.0/16

src/charon/plugins/stroke/stroke_config.c
src/charon/plugins/stroke/stroke_socket.c
src/starter/cmp.c
src/starter/confread.c
src/starter/confread.h
src/starter/ipsec.conf.5
src/starter/starterstroke.c
src/starter/starterwhack.c
src/stroke/stroke.c
src/stroke/stroke_msg.h

index 931dc9c..54b3bf8 100644 (file)
@@ -472,9 +472,9 @@ static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this,
                }
                if (!vip)
                {       /* if it is set to something like %poolname, request an address */
-                       if (msg->add_conn.me.subnet)
+                       if (msg->add_conn.me.subnets)
                        {       /* use the same addreass as in subnet, if any */
-                               if (strchr(msg->add_conn.me.subnet, '.'))
+                               if (strchr(msg->add_conn.me.subnets, '.'))
                                {
                                        vip = host_create_any(AF_INET);
                                }
@@ -620,27 +620,67 @@ static void build_auth_info(private_stroke_config_t *this,
 /**
  * build a traffic selector from a stroke_end
  */
-static traffic_selector_t *build_ts(private_stroke_config_t *this,
-                                                                       stroke_end_t *end)
+static void add_ts(private_stroke_config_t *this,
+                                  stroke_end_t *end, child_cfg_t *child_cfg, bool local)
 {
+       traffic_selector_t *ts;
+       
        if (end->tohost)
        {
-               return traffic_selector_create_dynamic(end->protocol,
+               ts = traffic_selector_create_dynamic(end->protocol,
                                        end->port ? end->port : 0, end->port ? end->port : 65535);
+               child_cfg->add_traffic_selector(child_cfg, local, ts);
        }
        else
        {
                host_t *net;
                
-               net = host_create_from_string(end->subnet ? end->subnet : end->address,
-                                                                         IKEV2_UDP_PORT);
-               if (!net)
+               if (!end->subnets)
                {
-                       DBG1(DBG_CFG, "invalid subnet: %s", end->subnet);
-                       return NULL;
+                       net = host_create_from_string(end->address, IKEV2_UDP_PORT);
+                       if (net)
+                       {
+                               ts = traffic_selector_create_from_subnet(net, 0, end->protocol,
+                                                                                                                end->port);
+                               child_cfg->add_traffic_selector(child_cfg, local, ts);
+                       }
+               }
+               else
+               {
+                       char *del, *start, *bits;
+                       
+                       start = end->subnets;
+                       do
+                       {
+                               int intbits = 0;
+                               
+                               del = strchr(start, ',');
+                               if (del)
+                               {
+                                       *del = '\0';
+                               }
+                               bits = strchr(start, '/');
+                               if (bits)
+                               {
+                                       *bits = '\0';
+                                       intbits = atoi(bits + 1);
+                               }
+                               
+                               net = host_create_from_string(start, IKEV2_UDP_PORT);
+                               if (net)
+                               {
+                                       ts = traffic_selector_create_from_subnet(net, intbits,
+                                                                                               end->protocol, end->port);
+                                       child_cfg->add_traffic_selector(child_cfg, local, ts);
+                               }
+                               else
+                               {
+                                       DBG1(DBG_CFG, "invalid subnet: %s, skipped", start);
+                               }
+                               start = del + 1;
+                       }
+                       while (del);
                }
-               return traffic_selector_create_from_subnet(net,
-                               end->subnet ? end->subnet_mask : 0, end->protocol, end->port);
        }
 }
 
@@ -651,7 +691,6 @@ static child_cfg_t *build_child_cfg(private_stroke_config_t *this,
                                                                        stroke_msg_t *msg)
 {
        child_cfg_t *child_cfg;
-       traffic_selector_t *ts;
        action_t dpd;
        
        switch (msg->add_conn.dpd.action)
@@ -673,21 +712,8 @@ static child_cfg_t *build_child_cfg(private_stroke_config_t *this,
                                msg->add_conn.me.updown, msg->add_conn.me.hostaccess,
                                msg->add_conn.mode, dpd, ACTION_NONE);
        
-       ts = build_ts(this, &msg->add_conn.me);
-       if (!ts)
-       {
-               child_cfg->destroy(child_cfg);
-               return NULL;
-       }
-       child_cfg->add_traffic_selector(child_cfg, TRUE, ts);
-       
-       ts = build_ts(this, &msg->add_conn.other);
-       if (!ts)
-       {
-               child_cfg->destroy(child_cfg);
-               return NULL;
-       }
-       child_cfg->add_traffic_selector(child_cfg, FALSE, ts);
+       add_ts(this, &msg->add_conn.me, child_cfg, TRUE);
+       add_ts(this, &msg->add_conn.other, child_cfg, FALSE);
        
        add_proposals(this, msg->add_conn.algorithms.esp, NULL, child_cfg);
        
index 53148b9..2ae22e4 100644 (file)
@@ -140,7 +140,7 @@ static void pop_string(stroke_msg_t *msg, char **string)
 static void pop_end(stroke_msg_t *msg, const char* label, stroke_end_t *end)
 {
        pop_string(msg, &end->address);
-       pop_string(msg, &end->subnet);
+       pop_string(msg, &end->subnets);
        pop_string(msg, &end->sourceip);
        pop_string(msg, &end->id);
        pop_string(msg, &end->cert);
@@ -149,7 +149,7 @@ static void pop_end(stroke_msg_t *msg, const char* label, stroke_end_t *end)
        pop_string(msg, &end->updown);
        
        DBG2(DBG_CFG, "  %s=%s", label, end->address);
-       DBG2(DBG_CFG, "  %ssubnet=%s", label, end->subnet);
+       DBG2(DBG_CFG, "  %ssubnet=%s", label, end->subnets);
        DBG2(DBG_CFG, "  %ssourceip=%s", label, end->sourceip);
        DBG2(DBG_CFG, "  %sid=%s", label, end->id);
        DBG2(DBG_CFG, "  %scert=%s", label, end->cert);
index 610b089..ad968db 100644 (file)
@@ -47,7 +47,7 @@ starter_cmp_end(starter_end_t *c1, starter_end_t *c2)
     }
     ADDCMP(nexthop);
     STRCMP(srcip);
-    SUBCMP(subnet);
+    STRCMP(subnet);
     VARCMP(has_client);
     VARCMP(has_client_wildcard);
     VARCMP(has_port_wildcard);
index 42b737e..606f1e3 100644 (file)
@@ -32,7 +32,7 @@
 #include "interfaces.h"
 
 /* strings containing a colon are interpreted as an IPv6 address */
-#define ip_version(string)     (strchr(string, ':') != NULL)? AF_INET6 : AF_INET;
+#define ip_version(string)     (strchr(string, '.') ? AF_INET : AF_INET6)
 
 static const char ike_defaults[] = "aes128-sha-modp2048";
 static const char esp_defaults[] = "aes128-sha1, 3des-md5";
@@ -189,7 +189,6 @@ kw_end(starter_conn_t *conn, starter_end_t *end, kw_token_t token
                        conn->policy |= POLICY_GROUP | POLICY_TUNNEL;
                        anyaddr(conn->addr_family, &end->addr);
                        anyaddr(conn->tunnel_addr_family, &any);
-                       initsubnet(&any, 0, '0', &end->subnet);
                        end->has_client = TRUE;
                }
                else
@@ -251,22 +250,44 @@ kw_end(starter_conn_t *conn, starter_end_t *end, kw_token_t token
                }
                else
                {
+                       ip_subnet net;
+                       char *pos;
+                       int len = 0;
+                       
                        end->has_client = TRUE;
                        conn->tunnel_addr_family = ip_version(value);
-                       ugh = ttosubnet(value, 0, conn->tunnel_addr_family, &end->subnet);
+                       
+                       pos = strchr(value, ',');
+                       if (pos)
+                       {
+                               len = pos - value;
+                       }
+                       ugh = ttosubnet(value, len, ip_version(value), &net);
                        if (ugh != NULL)
                        {
                                plog("# bad subnet: %s=%s [%s]", name, value, ugh);
                                goto err;
                        }
+                       end->subnet = clone_str(value, "subnet");
                }
                break;
        case KW_SUBNETWITHIN:
+       {
+               ip_subnet net;
+               
                end->has_client = TRUE;
                end->has_client_wildcard = TRUE;
                conn->tunnel_addr_family = ip_version(value);
-               ugh = ttosubnet(value, 0, conn->tunnel_addr_family, &end->subnet);
+
+               ugh = ttosubnet(value, 0, ip_version(value), &net);
+               if (ugh != NULL)
+               {
+                       plog("# bad subnet: %s=%s [%s]", name, value, ugh);
+                       goto err;
+               }
+               end->subnet = clone_str(value, "subnetwithin");
                break;
+       }
        case KW_PROTOPORT:
                ugh = ttoprotoport(value, 0, &end->protocol, &end->port, &has_port_wildcard);
                end->has_port_wildcard = has_port_wildcard;
@@ -827,6 +848,12 @@ free_also(also_t *head)
 static void
 confread_free_conn(starter_conn_t *conn)
 {
+       pfree(conn->left.subnet);
+       pfree(conn->right.subnet);
+       pfree(conn->left.virt);
+       pfree(conn->right.virt);
+       pfree(conn->left.srcip);
+       pfree(conn->right.srcip);
        free_args(KW_END_FIRST, KW_END_LAST,  (char *)&conn->left);
        free_args(KW_END_FIRST, KW_END_LAST,  (char *)&conn->right);
        free_args(KW_CONN_NAME, KW_CONN_LAST, (char *)conn);
index 5c0b714..d7e8ec3 100644 (file)
@@ -65,7 +65,7 @@ struct starter_end {
        char            *iface;
        ip_address      addr;
        ip_address      nexthop;
-       ip_subnet       subnet;
+       char            *subnet;
        bool            has_client;
        bool            has_client_wildcard;
        bool            has_port_wildcard;
index eefd216..fa66c88 100644 (file)
@@ -646,7 +646,9 @@ private subnet behind the left participant, expressed as
 if omitted, essentially assumed to be \fIleft\fB/32\fR,
 signifying that the left end of the connection goes to the left participant
 only. When using IKEv2, the configured subnet of the peers may differ, the
-protocol narrows it to the greates common subnet.
+protocol narrows it to the greatest common subnet. Further, IKEv2 supports
+multiple subnets separated by commas. IKEv1 only interprets the first subnet
+of such a definition.
 .TP
 .B leftsubnetwithin
 the peer can propose any subnet or single IP address that fits within the
index d75d25a..66b007e 100644 (file)
@@ -161,9 +161,7 @@ static void starter_stroke_add_end(stroke_msg_t *msg, stroke_end_t *msg_end, sta
        msg_end->updown = push_string(msg, conn_end->updown);
        ip_address2string(&conn_end->addr, buffer, sizeof(buffer));
        msg_end->address = push_string(msg, buffer);
-       ip_address2string(&conn_end->subnet.addr, buffer, sizeof(buffer));
-       msg_end->subnet = push_string(msg, buffer);
-       msg_end->subnet_mask = conn_end->subnet.maskbits;
+       msg_end->subnets = push_string(msg, conn_end->subnet);
        msg_end->sendcert = conn_end->sendcert;
        msg_end->hostaccess = conn_end->hostaccess;
        msg_end->tohost = !conn_end->has_client;
index 84c1972..4535a58 100644 (file)
@@ -32,6 +32,8 @@
 #include "confread.h"
 #include "files.h"
 
+#define ip_version(string)     (strchr(string, '.') ? AF_INET : AF_INET6)
+
 static int
 pack_str (char **p, char **next, char **roof)
 {
@@ -153,22 +155,22 @@ set_whack_end(whack_end_t *w, starter_end_t *end, sa_family_t family)
     if (end->srcip && end->srcip[0] != '%')
     {
        int len = 0;
-       char *pos, *v6;
+       char *pos;
 
        pos = strchr(end->srcip, '/');
-       v6 = strchr(end->srcip, ':');
        if (pos)
        {
            /* use first address only for pluto */
            len = pos - end->srcip;
        }
        w->has_srcip = !end->has_natip;
-       ttoaddr(end->srcip, len, v6 ? AF_INET6 : AF_INET, &w->host_srcip);
+       ttoaddr(end->srcip, len, ip_version(end->srcip), &w->host_srcip);
     }
     else
     {
        anyaddr(AF_INET, &w->host_srcip);       
-    }    
+    }
+    
     w->id                  = end->id;
     w->cert                = end->cert;
     w->ca                  = end->ca;
@@ -183,7 +185,17 @@ set_whack_end(whack_end_t *w, starter_end_t *end, sa_family_t family)
     w->host_nexthop        = end->nexthop;
 
     if (w->has_client)
-       w->client          = end->subnet;
+    {
+       char *pos;
+       int len = 0;
+
+       pos = strchr(end->subnet, ',');
+       if (pos)
+       {
+           len = pos - end->subnet;
+       }
+       ttosubnet(end->subnet, len, ip_version(end->subnet), &w->client);
+    }
     else
        w->client.addr.u.v4.sin_family = addrtypeof(&w->host_addr);
 
index 7743680..90d99ac 100644 (file)
@@ -100,8 +100,7 @@ static int send_stroke_msg (stroke_msg_t *msg)
 static int add_connection(char *name,
                                                  char *my_id, char *other_id, 
                                                  char *my_addr, char *other_addr,
-                                                 char *my_net, char *other_net,
-                                                 u_int my_netmask, u_int other_netmask)
+                                                 char *my_nets, char *other_nets)
 {
        stroke_msg_t msg;
        
@@ -118,14 +117,12 @@ static int add_connection(char *name,
        
        msg.add_conn.me.id = push_string(&msg, my_id);
        msg.add_conn.me.address = push_string(&msg, my_addr);
-       msg.add_conn.me.subnet = push_string(&msg, my_net);
-       msg.add_conn.me.subnet_mask = my_netmask;
+       msg.add_conn.me.subnets = push_string(&msg, my_nets);
        msg.add_conn.me.sendcert = 1;
        
        msg.add_conn.other.id = push_string(&msg, other_id);
        msg.add_conn.other.address = push_string(&msg, other_addr);
-       msg.add_conn.other.subnet = push_string(&msg, other_net);
-       msg.add_conn.other.subnet_mask = other_netmask;
+       msg.add_conn.other.subnets = push_string(&msg, other_nets);
        msg.add_conn.other.sendcert = 1;
        
        return send_stroke_msg(&msg);
@@ -277,8 +274,7 @@ static void exit_usage(char *error)
        printf("           MY_NET OTHER_NET MY_NETBITS OTHER_NETBITS\n");
        printf("    where: ID is any IKEv2 ID \n");
        printf("           ADDR is a IPv4 address\n");
-       printf("           NET is a IPv4 address of the subnet to tunnel\n");
-       printf("           NETBITS is the size of the subnet, as the \"24\" in 192.168.0.0/24\n");
+       printf("           NET is a IPv4 subnet in CIDR notation\n");
        printf("  Delete a connection:\n");
        printf("    stroke delete NAME\n");
        printf("    where: NAME is a connection name added with \"stroke add\"\n");
@@ -334,8 +330,7 @@ int main(int argc, char *argv[])
                        res = add_connection(argv[2],
                                                                 argv[3], argv[4], 
                                                                 argv[5], argv[6], 
-                                                                argv[7], argv[8], 
-                                                                atoi(argv[9]), atoi(argv[10]));
+                                                                argv[7], argv[8]);
                        break;
                case STROKE_DELETE:
                case STROKE_DEL:
index 96d13ae..9fa3449 100644 (file)
@@ -127,8 +127,7 @@ struct stroke_end_t {
        char *address;
        char *sourceip;
        int sourceip_size;
-       char *subnet;
-       int subnet_mask;
+       char *subnets;
        int sendcert;
        int hostaccess;
        int tohost;