def _GetConstantName(self, module, value, prefix):
thismodule = sys.modules[module]
for name in dir(thismodule):
+ if name.startswith("INET_DIAG_BC"):
+ break
if (name.startswith(prefix) and
not name.startswith(prefix + "F_") and
- name.isupper() and
- getattr(thismodule, name) == value):
- return name
+ name.isupper() and getattr(thismodule, name) == value):
+ return name
return value
def _Decode(self, command, msg, nla_type, nla_data):
# If it's an attribute we know about, try to decode it.
nla_name, nla_data = self._Decode(command, msg, nla.nla_type, nla_data)
- # We only support unique attributes for now.
- if nla_name in attributes:
- raise ValueError("Duplicate attribute %d" % nla_name)
+ # We only support unique attributes for now, except for INET_DIAG_NONE,
+ # which can appear more than once but doesn't seem to contain any data.
+ if nla_name in attributes and nla_name != "INET_DIAG_NONE":
+ raise ValueError("Duplicate attribute %s" % nla_name)
attributes[nla_name] = nla_data
self._Debug(" %s" % str((nla_name, nla_data)))
data = data[attrlen:]
return (nlmsg, attributes), data
+ def _GetMsg(self, msgtype):
+ data = self._Recv()
+ if NLMsgHdr(data).type == NLMSG_ERROR:
+ self._ParseAck(data)
+ return self._ParseNLMsg(data, msgtype)[0]
+
def _GetMsgList(self, msgtype, data, expect_done):
out = []
while data:
self._ExpectDone()
return out
- def _Dump(self, command, msg, msgtype):
- """Sends a dump request and returns a list of decoded messages."""
+ def _Dump(self, command, msg, msgtype, attrs):
+ """Sends a dump request and returns a list of decoded messages.
+
+ Args:
+ command: An integer, the command to run (e.g., RTM_NEWADDR).
+ msg: A string, the raw bytes of the request (e.g., a packed RTMsg).
+ msgtype: A cstruct.Struct, the data type to parse the dump results as.
+ attrs: A string, the raw bytes of any request attributes to include.
+
+ Returns:
+ A list of (msg, attrs) tuples where msg is of type msgtype and attrs is
+ a dict of attributes.
+ """
# Create a netlink dump request containing the msg.
flags = NLM_F_DUMP | NLM_F_REQUEST
- length = len(NLMsgHdr) + len(msg)
+ length = len(NLMsgHdr) + len(msg) + len(attrs)
nlmsghdr = NLMsgHdr((length, command, flags, self.seq, self.pid))
# Send the request.
- self._Send(nlmsghdr.Pack() + msg.Pack())
+ self._Send(nlmsghdr.Pack() + msg.Pack() + attrs)
# Keep reading netlink messages until we get a NLMSG_DONE.
out = []
response_type = NLMsgHdr(data).type
if response_type == NLMSG_DONE:
break
+ elif response_type == NLMSG_ERROR:
+ # Likely means that the kernel didn't like our dump request.
+ # Parse the error and throw an exception.
+ self._ParseAck(data)
out.extend(self._GetMsgList(msgtype, data, False))
return out