OSDN Git Service

Make RTA_METRICS parsing work properly.
authorLorenzo Colitti <lorenzo@google.com>
Thu, 14 Jan 2016 07:15:24 +0000 (16:15 +0900)
committerLorenzo Colitti <lorenzo@google.com>
Thu, 14 Jan 2016 11:20:10 +0000 (20:20 +0900)
Currently, parsing RTA_METRICS attributes only works if the
attributes only contain a single RTAX_MTU attribute, but not
other attributes.

This is because _ParseAttributes usually operates on netlink data
structures, and thus takes a data structure (such as a RTMsg
instance) as input. In the special case of the RTA_METRICS
attribute, _Decode calls _ParseAttributes on a blob of nested
attributes and not a data structure (which is correct), but
incorrectly passes in a msg of "RTMsg", which is a data structure
class, not an instance.

The result is that _Decode throws an exception when reading
msg.family. This was not never spotted before because _Decode
had a special hack to parse RTAX_MTU and we never happened to
parse a RTA_METRICS that contained anything else.

Fix this by passing None into _ParseAttributes when we know that
there is no message, and fetching msg.family in _ParseAttributes
only when we know that the message is in fact a rtmsg. This
allows us to merge the hack that parses RTAX_MTU with the code
that parses the other arguments. Also, support RTAX_HOPLIMIT,
which is the attribute which caused us to discover this problem.

Change-Id: I1c396ab29850e6cff95d2e7327ef6d702a8046f7

tests/net_test/iproute.py

index 4f77528..2c63993 100644 (file)
@@ -102,6 +102,7 @@ RTA_UID = 18
 
 # Route metric attributes.
 RTAX_MTU = 2
+RTAX_HOPLIMIT = 10
 
 # Data structure formats.
 IfinfoMsg = cstruct.Struct(
@@ -248,10 +249,6 @@ class IPRoute(netlink.NetlinkSocket):
          will be the raw byte string.
     """
     if command == -RTA_METRICS:
-      if nla_type == RTAX_MTU:
-        return ("RTAX_MTU", struct.unpack("=I", nla_data)[0])
-
-    if command == -RTA_METRICS:
       name = self._GetConstantName(nla_type, "RTAX_")
     elif CommandSubject(command) == "ADDR":
       name = self._GetConstantName(nla_type, "IFA_")
@@ -267,14 +264,13 @@ class IPRoute(netlink.NetlinkSocket):
       # Don't know what this is. Leave it as an integer.
       name = nla_type
 
-    family = msg.family
-
     if name in ["FRA_PRIORITY", "FRA_FWMARK", "FRA_TABLE", "FRA_FWMASK",
                 "FRA_UID_START", "FRA_UID_END",
                 "RTA_OIF", "RTA_PRIORITY", "RTA_TABLE", "RTA_MARK",
                 "IFLA_MTU", "IFLA_TXQLEN", "IFLA_GROUP", "IFLA_EXT_MASK",
                 "IFLA_PROMISCUITY", "IFLA_NUM_RX_QUEUES",
-                "IFLA_NUM_TX_QUEUES", "NDA_PROBES"]:
+                "IFLA_NUM_TX_QUEUES", "NDA_PROBES", "RTAX_MTU",
+                "RTAX_HOPLIMIT"]:
       data = struct.unpack("=I", nla_data)[0]
     elif name == "FRA_SUPPRESS_PREFIXLEN":
       data = struct.unpack("=i", nla_data)[0]
@@ -283,11 +279,11 @@ class IPRoute(netlink.NetlinkSocket):
     elif name in ["IFA_ADDRESS", "IFA_LOCAL", "RTA_DST", "RTA_SRC",
                   "RTA_GATEWAY", "RTA_PREFSRC", "RTA_UID",
                   "NDA_DST"]:
-      data = socket.inet_ntop(family, nla_data)
+      data = socket.inet_ntop(msg.family, nla_data)
     elif name in ["FRA_IIFNAME", "FRA_OIFNAME", "IFLA_IFNAME", "IFLA_QDISC"]:
       data = nla_data.strip("\x00")
     elif name == "RTA_METRICS":
-      data = self._ParseAttributes(-RTA_METRICS, family, RTMsg, nla_data)
+      data = self._ParseAttributes(-RTA_METRICS, msg.family, None, nla_data)
     elif name == "RTA_CACHEINFO":
       data = RTACacheinfo(nla_data)
     elif name == "IFA_CACHEINFO":