[PATCH phosphor-networkd] networking: ip address validation

OpenBMC Patches openbmc-patches at stwcx.xyz
Fri Jul 15 07:10:40 AEST 2016


From: "Edward A. James" <eajames at us.ibm.com>

issue # 202

Signed-off-by: Edward A. James <eajames at us.ibm.com>
---
 netman.py | 69 +++++++++++++++++++++++++++++++++++++++------------------------
 1 file changed, 43 insertions(+), 26 deletions(-)

diff --git a/netman.py b/netman.py
index 90cb022..c75675f 100755
--- a/netman.py
+++ b/netman.py
@@ -1,6 +1,7 @@
 #!/usr/bin/env python
 
 from subprocess import call, Popen, PIPE
+from IPy import IP
 import sys
 import subprocess
 import dbus
@@ -82,29 +83,45 @@ class NetMan (dbus.service.Object):
         if re.compile(macre).search(mac) : return True
         else: return False
 
-    def _isvalidip(self, family, ipaddr):
-        if family == socket.AF_INET:
-            try:
-                socket.inet_pton(socket.AF_INET, ipaddr)
-            except AttributeError:  # no inet_pton here, sorry
-                try:
-                    socket.inet_aton(ipaddr)
-                except socket.error:
-                    return False
-                return ipaddr.count('.') == 3
-            except socket.error:  # not a valid address
-                return False
-
-            return True
-
-        elif family == socket.AF_INET6:
-            try:
-                socket.inet_pton(socket.AF_INET6, ipaddr)
-            except socket.error:  # not a valid address
-                return False
-            return True
-
-        else: return False
+    def _isvalidip(self, ipaddr, netmask = '0'):
+	try:
+	    ip = IP(ipaddr)
+	except ValueError:
+	    return False
+
+	ipstr = ip.strNormal(0)
+
+	if ip.version() == 4:	# no special considerations for ipv6 now
+	    ip_parts = ipstr.split(".")
+	    if len(ip_parts) != 4:
+		return False
+
+	    first, second, third, fourth = [int(part) for part in ip_parts]
+	    if first == 0 and second == 0 and third == 0 and fourth == 0:
+		return False 	# "this" network disallowed
+	    if first >= 224:
+		return False	# class D multicast and class E disallowed
+	    if first == 192 and second == 88 and third == 99:
+		return False	# ipv6 relay
+	    if fourth == 0 or fourth == 255:	# possibly invalid, check mask
+		ipstr_masked = ip.strNormal(1)
+		if ipstr_masked.count("/") == 0:
+		    if netmask == '0':
+			return True	# no netmask available
+
+		    try:
+			maskedip = IP(ipaddr + "/" + netmask, make_net=True)
+		    except:
+			return False	# must be bad netmask
+
+		    ipstr_masked = maskedip.strNormal(1)
+
+		parts = ipstr_masked.split("/")
+		mask_bin = int(parts[1])
+		if mask_bin >= 24:
+		    return False	# no .0 or .255 is valid
+
+	return True
 
     def _getAddr (self, target, device):
         netprov     = network_providers [self.provider]
@@ -165,8 +182,8 @@ class NetMan (dbus.service.Object):
     @dbus.service.method(DBUS_NAME, "ssss", "x")
     def SetAddress4 (self, device, ipaddr, netmask, gateway):
         if not self._isvaliddev (device) : raise ValueError, "Invalid Device"
-        if not self._isvalidip (socket.AF_INET, ipaddr) : raise ValueError, "Malformed IP Address"
-        if not self._isvalidip (socket.AF_INET, gateway) : raise ValueError, "Malformed GW Address"
+        if not self._isvalidip (ipaddr, netmask) : raise ValueError, "Malformed IP Address"
+        if not self._isvalidip (gateway) : raise ValueError, "Malformed GW Address"
         if not self._isvalidmask (netmask) : raise ValueError, "Invalid Mask"
 
         prefixLen = getPrefixLen (netmask)
@@ -254,7 +271,7 @@ class NetMan (dbus.service.Object):
         file_opened = False
         if len(dns_entry) > 0:
             for dns in dns_entry:
-                if not self._isvalidip (socket.AF_INET, dns):
+                if not self._isvalidip (dns):
                     if dns == "DHCP_AUTO=":
                         #This DNS is supplied by DHCP.
                         dhcp_auto = True
-- 
2.9.0




More information about the openbmc mailing list