Skip to contentSkip to conversation

Improve ifconfig_sanity_check()

PATCH Superseded David Sommerseth 3 participants 3 messages Dec 9, 2016

v1 of 3 Superseded Latest is v3 →

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 Improve ifconfig_sanity_check()

- Instead of checking the complete in_addr_t (which lacked proper htonl()), just do a simple peek at the last byte which contains the first octet of an IP address or subnet mask.

- Improve error messages to also report errornous IP address usage when being in TOP_SUBNET

- Improve the TAP check too, providing the IP address used instead of the subnet mask

---
 src/openvpn/tun.c | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)
src/openvpn/tun.c +13 -3
index 8df3489..07748b1 100644
@@ -304,18 +304,28 @@ void
 ifconfig_sanity_check (bool tun, in_addr_t addr, int topology)
 {
   struct gc_arena gc = gc_new ();
-  const bool looks_like_netmask = ((addr & 0xFF000000) == 0xFF000000);
+  const bool looks_like_netmask = (((unsigned char *)&addr)[3] == 0xff);
+
   if (tun)
     {
       if (looks_like_netmask && (topology == TOP_NET30 || topology == TOP_P2P))
-	msg (M_WARN, "WARNING: Since you are using --dev tun with a point-to-point topology, the second argument to --ifconfig must be an IP address.  You are using something (%s) that looks more like a netmask. %s",
+        {
+          msg (M_WARN, "WARNING: Since you are using --dev tun with a point-to-point topology, the second argument to --ifconfig must be an IP address.  You are using something (%s) that looks more like a netmask. %s",
+               print_in_addr_t (addr, 0, &gc),
+               ifconfig_warn_how_to_silence);
+        }
+      else if (!looks_like_netmask && topology == TOP_SUBNET)
+        {
+          msg (M_WARN, "WARNING: Since you are using --dev tun with subnet topology, the second argument to --ifconfig must be a netmask, for example something like 255.255.255.0.  You are using something (%s) that looks more like an IP address. %s",
 	     print_in_addr_t (addr, 0, &gc),
 	     ifconfig_warn_how_to_silence);
+        }
     }
   else /* tap */
     {
       if (!looks_like_netmask)
-	msg (M_WARN, "WARNING: Since you are using --dev tap, the second argument to --ifconfig must be a netmask, for example something like 255.255.255.0. %s",
+	msg (M_WARN, "WARNING: Since you are using --dev tap, the second argument to --ifconfig must be a netmask, for example something like 255.255.255.0. You are using something (%s) that looks more like an IP address. %s",
+             print_in_addr_t (addr, 0, &gc),
 	     ifconfig_warn_how_to_silence);
     }
   gc_free (&gc);
Signature · 1 line
1.8.3.1
#1 lore raw

Hi,

Quoted 3 lines · David Sommerseth

- Instead of checking the complete in_addr_t (which lacked proper htonl()), just do a simple peek at the last byte which contains the first octet of an IP address or subnet mask.

Have you *tested* this on a non-intel platform?

I know that I said on IRC that we might do it that way, but looking at stuff like print_in_addr_t() I'm not sure our usage of in_addr_t is consistant with "normal usage of it" (namely, always in network byte order).

gert

Signature · 4 lines
USENET is *not* the non-clickable part of WWW!
                                                           //www.muc.de/~gert/
Gert Doering - Munich, Germany                             [email protected]...
fax: +49-89-35655025                        [email protected]...
#2 lore raw
Quoted 7 lines · Gert Doering

Hi,

Quoted 3 lines · David Sommerseth

- Instead of checking the complete in_addr_t (which lacked proper htonl()), just do a simple peek at the last byte which contains the first octet of an IP address or subnet mask.

Quoted 6 lines

Have you *tested* this on a non-intel platform?

I know that I said on IRC that we might do it that way, but looking at stuff like print_in_addr_t() I'm not sure our usage of in_addr_t is consistant with "normal usage of it" (namely, always in network byte order).

I don't have access to any big-endian machines. I might still have access to a virtual POWER8 machine, but that is configured in little-endian mode - so no difference from the Intel platform.

After I sent this patch, I started to ponder on if there were any performance reasons why to change the in_addr_t check. And I've come to the conclusion I doubt it makes much of a difference.

First of all, an IPv4 address is 32-bits, which is the smallest CPU variants we do support. So 0xff000000 or 0xff will just be copied into a 32-bit register anyway. Secondly, checking for just 0xff will remove one AND operation on the CPU and the mov(e) operation will just be slightly different as it only loads 8 bits from a memory region vs 32 bits. So we might end up with or without saving just a couple of CPU cycles. And when considering that this is code paths which is not called very often, it starts to smell very much like pointless micro-optimization.

I suggest we leave the in_addr_t parsing unchanged, and fix the message handling to differentiate between --ifconfig and --ifconfig-push. And after 2.4.0, we can look at the in_addr_t tackling to see if it behaves correctly on both big- and little-endian. If it doesn't behave well then we'll fix it.

Thoughts?

Signature · 4 lines
kind regards,

David Sommerseth
OpenVPN Technologies, Inc