Implemented port ranges in kernel_netlink interface
authorAndreas Steffen <andreas.steffen@strongswan.org>
Thu, 3 Mar 2016 11:24:41 +0000 (12:24 +0100)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Fri, 4 Mar 2016 08:52:34 +0000 (09:52 +0100)
src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c

index 275aa6c..6d9d63a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) 2006-2015 Tobias Brunner
  * Copyright (C) 2005-2009 Martin Willi
- * Copyright (C) 2008 Andreas Steffen
+ * Copyright (C) 2008-2016 Andreas Steffen
  * Copyright (C) 2006-2007 Fabian Hartmann, Noah Heusser
  * Copyright (C) 2006 Daniel Roethlisberger
  * Copyright (C) 2005 Jan Hutter
@@ -702,15 +702,13 @@ static void ts2subnet(traffic_selector_t* ts,
 static void ts2ports(traffic_selector_t* ts,
                                         u_int16_t *port, u_int16_t *mask)
 {
-       /* Linux does not seem to accept complex portmasks. Only
-        * any or a specific port is allowed. We set to any, if we have
-        * a port range, or to a specific, if we have one port only.
-        */
-       u_int16_t from, to;
+       uint16_t from, to, bitmask;
+       int bit;
 
        from = ts->get_from_port(ts);
        to = ts->get_to_port(ts);
 
+       /* Quick check for a single port */
        if (from == to)
        {
                *port = htons(from);
@@ -718,9 +716,23 @@ static void ts2ports(traffic_selector_t* ts,
        }
        else
        {
-               *port = 0;
+               /* Compute the port mask for port ranges */
                *mask = 0;
+
+               for (bit = 15; bit >= 0; bit--)
+               {
+                       bitmask = 1 << bit;
+
+                       if ((bitmask & from) != (bitmask & to))
+                       {
+                               *port = htons(from & *mask);
+                               *mask = htons(*mask);
+                               return;
+                       }
+                       *mask |= bitmask;
+               }
        }
+       return;
 }
 
 /**