1*2f2c4c7aSAndroid Build Coastguard Worker#!/usr/bin/python3 2*2f2c4c7aSAndroid Build Coastguard Worker# 3*2f2c4c7aSAndroid Build Coastguard Worker# Copyright 2014 The Android Open Source Project 4*2f2c4c7aSAndroid Build Coastguard Worker# 5*2f2c4c7aSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 6*2f2c4c7aSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 7*2f2c4c7aSAndroid Build Coastguard Worker# You may obtain a copy of the License at 8*2f2c4c7aSAndroid Build Coastguard Worker# 9*2f2c4c7aSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 10*2f2c4c7aSAndroid Build Coastguard Worker# 11*2f2c4c7aSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 12*2f2c4c7aSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 13*2f2c4c7aSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14*2f2c4c7aSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 15*2f2c4c7aSAndroid Build Coastguard Worker# limitations under the License. 16*2f2c4c7aSAndroid Build Coastguard Worker 17*2f2c4c7aSAndroid Build Coastguard Worker"""Partial Python implementation of iproute functionality.""" 18*2f2c4c7aSAndroid Build Coastguard Worker 19*2f2c4c7aSAndroid Build Coastguard Worker# pylint: disable=g-bad-todo 20*2f2c4c7aSAndroid Build Coastguard Worker 21*2f2c4c7aSAndroid Build Coastguard Workerimport os 22*2f2c4c7aSAndroid Build Coastguard Workerimport socket 23*2f2c4c7aSAndroid Build Coastguard Workerimport struct 24*2f2c4c7aSAndroid Build Coastguard Workerimport sys 25*2f2c4c7aSAndroid Build Coastguard Worker 26*2f2c4c7aSAndroid Build Coastguard Workerimport cstruct 27*2f2c4c7aSAndroid Build Coastguard Workerimport util 28*2f2c4c7aSAndroid Build Coastguard Worker 29*2f2c4c7aSAndroid Build Coastguard Worker### Base netlink constants. See include/uapi/linux/netlink.h. 30*2f2c4c7aSAndroid Build Coastguard WorkerNETLINK_ROUTE = 0 31*2f2c4c7aSAndroid Build Coastguard WorkerNETLINK_SOCK_DIAG = 4 32*2f2c4c7aSAndroid Build Coastguard WorkerNETLINK_XFRM = 6 33*2f2c4c7aSAndroid Build Coastguard WorkerNETLINK_GENERIC = 16 34*2f2c4c7aSAndroid Build Coastguard Worker 35*2f2c4c7aSAndroid Build Coastguard Worker# Request constants. 36*2f2c4c7aSAndroid Build Coastguard WorkerNLM_F_REQUEST = 1 37*2f2c4c7aSAndroid Build Coastguard WorkerNLM_F_ACK = 4 38*2f2c4c7aSAndroid Build Coastguard WorkerNLM_F_REPLACE = 0x100 39*2f2c4c7aSAndroid Build Coastguard WorkerNLM_F_EXCL = 0x200 40*2f2c4c7aSAndroid Build Coastguard WorkerNLM_F_CREATE = 0x400 41*2f2c4c7aSAndroid Build Coastguard WorkerNLM_F_DUMP = 0x300 42*2f2c4c7aSAndroid Build Coastguard Worker 43*2f2c4c7aSAndroid Build Coastguard Worker# Message types. 44*2f2c4c7aSAndroid Build Coastguard WorkerNLMSG_ERROR = 2 45*2f2c4c7aSAndroid Build Coastguard WorkerNLMSG_DONE = 3 46*2f2c4c7aSAndroid Build Coastguard Worker 47*2f2c4c7aSAndroid Build Coastguard Worker# Data structure formats. 48*2f2c4c7aSAndroid Build Coastguard Worker# These aren't constants, they're classes. So, pylint: disable=invalid-name 49*2f2c4c7aSAndroid Build Coastguard WorkerNLMsgHdr = cstruct.Struct("NLMsgHdr", "=LHHLL", "length type flags seq pid") 50*2f2c4c7aSAndroid Build Coastguard WorkerNLMsgErr = cstruct.Struct("NLMsgErr", "=i", "error") 51*2f2c4c7aSAndroid Build Coastguard WorkerNLAttr = cstruct.Struct("NLAttr", "=HH", "nla_len nla_type") 52*2f2c4c7aSAndroid Build Coastguard Worker 53*2f2c4c7aSAndroid Build Coastguard Worker# Alignment / padding. 54*2f2c4c7aSAndroid Build Coastguard WorkerNLA_ALIGNTO = 4 55*2f2c4c7aSAndroid Build Coastguard Worker 56*2f2c4c7aSAndroid Build Coastguard Worker# List of attributes that can appear more than once in a given netlink message. 57*2f2c4c7aSAndroid Build Coastguard Worker# These can appear more than once but don't seem to contain any data. 58*2f2c4c7aSAndroid Build Coastguard WorkerDUP_ATTRS_OK = ["INET_DIAG_NONE", "IFLA_PAD"] 59*2f2c4c7aSAndroid Build Coastguard Worker 60*2f2c4c7aSAndroid Build Coastguard Worker 61*2f2c4c7aSAndroid Build Coastguard Workerdef MakeConstantPrefixes(prefixes): 62*2f2c4c7aSAndroid Build Coastguard Worker return sorted(prefixes, key=len, reverse=True) 63*2f2c4c7aSAndroid Build Coastguard Worker 64*2f2c4c7aSAndroid Build Coastguard Worker 65*2f2c4c7aSAndroid Build Coastguard Workerclass NetlinkSocket(object): 66*2f2c4c7aSAndroid Build Coastguard Worker """A basic netlink socket object.""" 67*2f2c4c7aSAndroid Build Coastguard Worker 68*2f2c4c7aSAndroid Build Coastguard Worker BUFSIZE = 65536 69*2f2c4c7aSAndroid Build Coastguard Worker DEBUG = False 70*2f2c4c7aSAndroid Build Coastguard Worker # List of netlink messages to print, e.g., [], ["NEIGH", "ROUTE"], or ["ALL"] 71*2f2c4c7aSAndroid Build Coastguard Worker NL_DEBUG = [] 72*2f2c4c7aSAndroid Build Coastguard Worker 73*2f2c4c7aSAndroid Build Coastguard Worker def _Debug(self, s): 74*2f2c4c7aSAndroid Build Coastguard Worker if self.DEBUG: 75*2f2c4c7aSAndroid Build Coastguard Worker print(s) 76*2f2c4c7aSAndroid Build Coastguard Worker 77*2f2c4c7aSAndroid Build Coastguard Worker def _NlAttr(self, nla_type, data): 78*2f2c4c7aSAndroid Build Coastguard Worker assert isinstance(data, bytes) 79*2f2c4c7aSAndroid Build Coastguard Worker datalen = len(data) 80*2f2c4c7aSAndroid Build Coastguard Worker # Pad the data if it's not a multiple of NLA_ALIGNTO bytes long. 81*2f2c4c7aSAndroid Build Coastguard Worker padding = b"\x00" * util.GetPadLength(NLA_ALIGNTO, datalen) 82*2f2c4c7aSAndroid Build Coastguard Worker nla_len = datalen + len(NLAttr) 83*2f2c4c7aSAndroid Build Coastguard Worker return NLAttr((nla_len, nla_type)).Pack() + data + padding 84*2f2c4c7aSAndroid Build Coastguard Worker 85*2f2c4c7aSAndroid Build Coastguard Worker def _NlAttrIPAddress(self, nla_type, family, address): 86*2f2c4c7aSAndroid Build Coastguard Worker return self._NlAttr(nla_type, socket.inet_pton(family, address)) 87*2f2c4c7aSAndroid Build Coastguard Worker 88*2f2c4c7aSAndroid Build Coastguard Worker def _NlAttrStr(self, nla_type, value): 89*2f2c4c7aSAndroid Build Coastguard Worker value = value + "\x00" 90*2f2c4c7aSAndroid Build Coastguard Worker return self._NlAttr(nla_type, value.encode("UTF-8")) 91*2f2c4c7aSAndroid Build Coastguard Worker 92*2f2c4c7aSAndroid Build Coastguard Worker def _NlAttrU32(self, nla_type, value): 93*2f2c4c7aSAndroid Build Coastguard Worker return self._NlAttr(nla_type, struct.pack("=I", value)) 94*2f2c4c7aSAndroid Build Coastguard Worker 95*2f2c4c7aSAndroid Build Coastguard Worker @staticmethod 96*2f2c4c7aSAndroid Build Coastguard Worker def _GetConstantName(module, value, prefix): 97*2f2c4c7aSAndroid Build Coastguard Worker def FirstMatching(name, prefixlist): 98*2f2c4c7aSAndroid Build Coastguard Worker for prefix in prefixlist: 99*2f2c4c7aSAndroid Build Coastguard Worker if name.startswith(prefix): 100*2f2c4c7aSAndroid Build Coastguard Worker return prefix 101*2f2c4c7aSAndroid Build Coastguard Worker return None 102*2f2c4c7aSAndroid Build Coastguard Worker 103*2f2c4c7aSAndroid Build Coastguard Worker thismodule = sys.modules[module] 104*2f2c4c7aSAndroid Build Coastguard Worker constant_prefixes = getattr(thismodule, "CONSTANT_PREFIXES", []) 105*2f2c4c7aSAndroid Build Coastguard Worker for name in dir(thismodule): 106*2f2c4c7aSAndroid Build Coastguard Worker if value != getattr(thismodule, name) or not name.isupper(): 107*2f2c4c7aSAndroid Build Coastguard Worker continue 108*2f2c4c7aSAndroid Build Coastguard Worker # If the module explicitly specifies prefixes, only return this name if 109*2f2c4c7aSAndroid Build Coastguard Worker # the passed-in prefix is the longest prefix that matches the name. 110*2f2c4c7aSAndroid Build Coastguard Worker # This ensures, for example, that passing in a prefix of "IFA_" and a 111*2f2c4c7aSAndroid Build Coastguard Worker # value of 1 returns "IFA_ADDRESS" instead of "IFA_F_SECONDARY". 112*2f2c4c7aSAndroid Build Coastguard Worker # The longest matching prefix is always the first matching prefix because 113*2f2c4c7aSAndroid Build Coastguard Worker # CONSTANT_PREFIXES must be sorted longest first. 114*2f2c4c7aSAndroid Build Coastguard Worker if constant_prefixes and prefix != FirstMatching(name, constant_prefixes): 115*2f2c4c7aSAndroid Build Coastguard Worker continue 116*2f2c4c7aSAndroid Build Coastguard Worker if name.startswith(prefix): 117*2f2c4c7aSAndroid Build Coastguard Worker return name 118*2f2c4c7aSAndroid Build Coastguard Worker return value 119*2f2c4c7aSAndroid Build Coastguard Worker 120*2f2c4c7aSAndroid Build Coastguard Worker def _Decode(self, command, msg, nla_type, nla_data, nested): 121*2f2c4c7aSAndroid Build Coastguard Worker """No-op, nonspecific version of decode.""" 122*2f2c4c7aSAndroid Build Coastguard Worker return nla_type, nla_data 123*2f2c4c7aSAndroid Build Coastguard Worker 124*2f2c4c7aSAndroid Build Coastguard Worker def _ReadNlAttr(self, data): 125*2f2c4c7aSAndroid Build Coastguard Worker # Read the nlattr header. 126*2f2c4c7aSAndroid Build Coastguard Worker nla, data = cstruct.Read(data, NLAttr) 127*2f2c4c7aSAndroid Build Coastguard Worker 128*2f2c4c7aSAndroid Build Coastguard Worker # Read the data. 129*2f2c4c7aSAndroid Build Coastguard Worker datalen = nla.nla_len - len(nla) 130*2f2c4c7aSAndroid Build Coastguard Worker padded_len = util.GetPadLength(NLA_ALIGNTO, datalen) + datalen 131*2f2c4c7aSAndroid Build Coastguard Worker nla_data, data = data[:datalen], data[padded_len:] 132*2f2c4c7aSAndroid Build Coastguard Worker 133*2f2c4c7aSAndroid Build Coastguard Worker return nla, nla_data, data 134*2f2c4c7aSAndroid Build Coastguard Worker 135*2f2c4c7aSAndroid Build Coastguard Worker def _ParseAttributes(self, command, msg, data, nested): 136*2f2c4c7aSAndroid Build Coastguard Worker """Parses and decodes netlink attributes. 137*2f2c4c7aSAndroid Build Coastguard Worker 138*2f2c4c7aSAndroid Build Coastguard Worker Takes a block of NLAttr data structures, decodes them using Decode, and 139*2f2c4c7aSAndroid Build Coastguard Worker returns the result in a dict keyed by attribute number. 140*2f2c4c7aSAndroid Build Coastguard Worker 141*2f2c4c7aSAndroid Build Coastguard Worker Args: 142*2f2c4c7aSAndroid Build Coastguard Worker command: An integer, the rtnetlink command being carried out. 143*2f2c4c7aSAndroid Build Coastguard Worker msg: A Struct, the type of the data after the netlink header. 144*2f2c4c7aSAndroid Build Coastguard Worker data: A byte string containing a sequence of NLAttr data structures. 145*2f2c4c7aSAndroid Build Coastguard Worker nested: A list, outermost first, of each of the attributes the NLAttrs are 146*2f2c4c7aSAndroid Build Coastguard Worker nested inside. Empty for non-nested attributes. 147*2f2c4c7aSAndroid Build Coastguard Worker 148*2f2c4c7aSAndroid Build Coastguard Worker Returns: 149*2f2c4c7aSAndroid Build Coastguard Worker A dictionary mapping attribute types (integers) to decoded values. 150*2f2c4c7aSAndroid Build Coastguard Worker 151*2f2c4c7aSAndroid Build Coastguard Worker Raises: 152*2f2c4c7aSAndroid Build Coastguard Worker ValueError: There was a duplicate attribute type. 153*2f2c4c7aSAndroid Build Coastguard Worker """ 154*2f2c4c7aSAndroid Build Coastguard Worker attributes = {} 155*2f2c4c7aSAndroid Build Coastguard Worker while data: 156*2f2c4c7aSAndroid Build Coastguard Worker nla, nla_data, data = self._ReadNlAttr(data) 157*2f2c4c7aSAndroid Build Coastguard Worker 158*2f2c4c7aSAndroid Build Coastguard Worker # If it's an attribute we know about, try to decode it. 159*2f2c4c7aSAndroid Build Coastguard Worker nla_name, nla_data = self._Decode(command, msg, nla.nla_type, nla_data, nested) 160*2f2c4c7aSAndroid Build Coastguard Worker 161*2f2c4c7aSAndroid Build Coastguard Worker if nla_name in attributes and nla_name not in DUP_ATTRS_OK: 162*2f2c4c7aSAndroid Build Coastguard Worker raise ValueError("Duplicate attribute %s" % nla_name) 163*2f2c4c7aSAndroid Build Coastguard Worker 164*2f2c4c7aSAndroid Build Coastguard Worker attributes[nla_name] = nla_data 165*2f2c4c7aSAndroid Build Coastguard Worker if not nested: 166*2f2c4c7aSAndroid Build Coastguard Worker self._Debug(" %s" % (str((nla_name, nla_data)))) 167*2f2c4c7aSAndroid Build Coastguard Worker 168*2f2c4c7aSAndroid Build Coastguard Worker return attributes 169*2f2c4c7aSAndroid Build Coastguard Worker 170*2f2c4c7aSAndroid Build Coastguard Worker def _OpenNetlinkSocket(self, family, groups): 171*2f2c4c7aSAndroid Build Coastguard Worker sock = socket.socket(socket.AF_NETLINK, socket.SOCK_RAW, family) 172*2f2c4c7aSAndroid Build Coastguard Worker if groups: 173*2f2c4c7aSAndroid Build Coastguard Worker sock.bind((0, groups)) 174*2f2c4c7aSAndroid Build Coastguard Worker sock.connect((0, 0)) # The kernel. 175*2f2c4c7aSAndroid Build Coastguard Worker return sock 176*2f2c4c7aSAndroid Build Coastguard Worker 177*2f2c4c7aSAndroid Build Coastguard Worker def __init__(self, family, groups=None): 178*2f2c4c7aSAndroid Build Coastguard Worker # Global sequence number. 179*2f2c4c7aSAndroid Build Coastguard Worker self.seq = 0 180*2f2c4c7aSAndroid Build Coastguard Worker self.sock = self._OpenNetlinkSocket(family, groups) 181*2f2c4c7aSAndroid Build Coastguard Worker self.pid = self.sock.getsockname()[1] 182*2f2c4c7aSAndroid Build Coastguard Worker 183*2f2c4c7aSAndroid Build Coastguard Worker def close(self): 184*2f2c4c7aSAndroid Build Coastguard Worker self.sock.close() 185*2f2c4c7aSAndroid Build Coastguard Worker self.sock = None 186*2f2c4c7aSAndroid Build Coastguard Worker 187*2f2c4c7aSAndroid Build Coastguard Worker def __del__(self): 188*2f2c4c7aSAndroid Build Coastguard Worker if self.sock: 189*2f2c4c7aSAndroid Build Coastguard Worker self.close() 190*2f2c4c7aSAndroid Build Coastguard Worker 191*2f2c4c7aSAndroid Build Coastguard Worker def MaybeDebugCommand(self, command, flags, data): 192*2f2c4c7aSAndroid Build Coastguard Worker # Default no-op implementation to be overridden by subclasses. 193*2f2c4c7aSAndroid Build Coastguard Worker pass 194*2f2c4c7aSAndroid Build Coastguard Worker 195*2f2c4c7aSAndroid Build Coastguard Worker def _Send(self, msg): 196*2f2c4c7aSAndroid Build Coastguard Worker # self._Debug(msg.encode("hex")) 197*2f2c4c7aSAndroid Build Coastguard Worker self.seq += 1 198*2f2c4c7aSAndroid Build Coastguard Worker self.sock.send(msg) 199*2f2c4c7aSAndroid Build Coastguard Worker 200*2f2c4c7aSAndroid Build Coastguard Worker def _Recv(self): 201*2f2c4c7aSAndroid Build Coastguard Worker data = self.sock.recv(self.BUFSIZE) 202*2f2c4c7aSAndroid Build Coastguard Worker # self._Debug(data.encode("hex")) 203*2f2c4c7aSAndroid Build Coastguard Worker return data 204*2f2c4c7aSAndroid Build Coastguard Worker 205*2f2c4c7aSAndroid Build Coastguard Worker def _ExpectDone(self): 206*2f2c4c7aSAndroid Build Coastguard Worker response = self._Recv() 207*2f2c4c7aSAndroid Build Coastguard Worker hdr = NLMsgHdr(response) 208*2f2c4c7aSAndroid Build Coastguard Worker if hdr.type != NLMSG_DONE: 209*2f2c4c7aSAndroid Build Coastguard Worker raise ValueError("Expected DONE, got type %d" % hdr.type) 210*2f2c4c7aSAndroid Build Coastguard Worker 211*2f2c4c7aSAndroid Build Coastguard Worker def _ParseAck(self, response): 212*2f2c4c7aSAndroid Build Coastguard Worker # Find the error code. 213*2f2c4c7aSAndroid Build Coastguard Worker hdr, data = cstruct.Read(response, NLMsgHdr) 214*2f2c4c7aSAndroid Build Coastguard Worker if hdr.type == NLMSG_ERROR: 215*2f2c4c7aSAndroid Build Coastguard Worker error = -NLMsgErr(data).error 216*2f2c4c7aSAndroid Build Coastguard Worker if error: 217*2f2c4c7aSAndroid Build Coastguard Worker raise IOError(error, os.strerror(error)) 218*2f2c4c7aSAndroid Build Coastguard Worker else: 219*2f2c4c7aSAndroid Build Coastguard Worker raise ValueError("Expected ACK, got type %d" % hdr.type) 220*2f2c4c7aSAndroid Build Coastguard Worker 221*2f2c4c7aSAndroid Build Coastguard Worker def _ExpectAck(self): 222*2f2c4c7aSAndroid Build Coastguard Worker response = self._Recv() 223*2f2c4c7aSAndroid Build Coastguard Worker self._ParseAck(response) 224*2f2c4c7aSAndroid Build Coastguard Worker 225*2f2c4c7aSAndroid Build Coastguard Worker def _SendNlRequest(self, command, data, flags): 226*2f2c4c7aSAndroid Build Coastguard Worker """Sends a netlink request and expects an ack.""" 227*2f2c4c7aSAndroid Build Coastguard Worker length = len(NLMsgHdr) + len(data) 228*2f2c4c7aSAndroid Build Coastguard Worker nlmsg = NLMsgHdr((length, command, flags, self.seq, self.pid)).Pack() 229*2f2c4c7aSAndroid Build Coastguard Worker 230*2f2c4c7aSAndroid Build Coastguard Worker self.MaybeDebugCommand(command, flags, nlmsg + data) 231*2f2c4c7aSAndroid Build Coastguard Worker 232*2f2c4c7aSAndroid Build Coastguard Worker # Send the message. 233*2f2c4c7aSAndroid Build Coastguard Worker self._Send(nlmsg + data) 234*2f2c4c7aSAndroid Build Coastguard Worker 235*2f2c4c7aSAndroid Build Coastguard Worker if flags & NLM_F_ACK: 236*2f2c4c7aSAndroid Build Coastguard Worker self._ExpectAck() 237*2f2c4c7aSAndroid Build Coastguard Worker 238*2f2c4c7aSAndroid Build Coastguard Worker def _ParseNLMsg(self, data, msgtype): 239*2f2c4c7aSAndroid Build Coastguard Worker """Parses a Netlink message into a header and a dictionary of attributes.""" 240*2f2c4c7aSAndroid Build Coastguard Worker nlmsghdr, data = cstruct.Read(data, NLMsgHdr) 241*2f2c4c7aSAndroid Build Coastguard Worker self._Debug(" %s" % nlmsghdr) 242*2f2c4c7aSAndroid Build Coastguard Worker 243*2f2c4c7aSAndroid Build Coastguard Worker if nlmsghdr.type == NLMSG_ERROR or nlmsghdr.type == NLMSG_DONE: 244*2f2c4c7aSAndroid Build Coastguard Worker print("done") 245*2f2c4c7aSAndroid Build Coastguard Worker return (None, None), data 246*2f2c4c7aSAndroid Build Coastguard Worker 247*2f2c4c7aSAndroid Build Coastguard Worker nlmsg, data = cstruct.Read(data, msgtype) 248*2f2c4c7aSAndroid Build Coastguard Worker self._Debug(" %s" % nlmsg) 249*2f2c4c7aSAndroid Build Coastguard Worker 250*2f2c4c7aSAndroid Build Coastguard Worker # Parse the attributes in the nlmsg. 251*2f2c4c7aSAndroid Build Coastguard Worker attrlen = nlmsghdr.length - len(nlmsghdr) - len(nlmsg) 252*2f2c4c7aSAndroid Build Coastguard Worker attributes = self._ParseAttributes(nlmsghdr.type, nlmsg, data[:attrlen], []) 253*2f2c4c7aSAndroid Build Coastguard Worker data = data[attrlen:] 254*2f2c4c7aSAndroid Build Coastguard Worker return (nlmsg, attributes), data 255*2f2c4c7aSAndroid Build Coastguard Worker 256*2f2c4c7aSAndroid Build Coastguard Worker def _GetMsg(self, msgtype): 257*2f2c4c7aSAndroid Build Coastguard Worker data = self._Recv() 258*2f2c4c7aSAndroid Build Coastguard Worker if NLMsgHdr(data).type == NLMSG_ERROR: 259*2f2c4c7aSAndroid Build Coastguard Worker self._ParseAck(data) 260*2f2c4c7aSAndroid Build Coastguard Worker return self._ParseNLMsg(data, msgtype)[0] 261*2f2c4c7aSAndroid Build Coastguard Worker 262*2f2c4c7aSAndroid Build Coastguard Worker def _GetMsgList(self, msgtype, data, expect_done): 263*2f2c4c7aSAndroid Build Coastguard Worker out = [] 264*2f2c4c7aSAndroid Build Coastguard Worker while data: 265*2f2c4c7aSAndroid Build Coastguard Worker msg, data = self._ParseNLMsg(data, msgtype) 266*2f2c4c7aSAndroid Build Coastguard Worker if msg is None: 267*2f2c4c7aSAndroid Build Coastguard Worker break 268*2f2c4c7aSAndroid Build Coastguard Worker out.append(msg) 269*2f2c4c7aSAndroid Build Coastguard Worker if expect_done: 270*2f2c4c7aSAndroid Build Coastguard Worker self._ExpectDone() 271*2f2c4c7aSAndroid Build Coastguard Worker return out 272*2f2c4c7aSAndroid Build Coastguard Worker 273*2f2c4c7aSAndroid Build Coastguard Worker def _Dump(self, command, msg, msgtype, attrs=b""): 274*2f2c4c7aSAndroid Build Coastguard Worker """Sends a dump request and returns a list of decoded messages. 275*2f2c4c7aSAndroid Build Coastguard Worker 276*2f2c4c7aSAndroid Build Coastguard Worker Args: 277*2f2c4c7aSAndroid Build Coastguard Worker command: An integer, the command to run (e.g., RTM_NEWADDR). 278*2f2c4c7aSAndroid Build Coastguard Worker msg: A struct, the request (e.g., a RTMsg). May be None. 279*2f2c4c7aSAndroid Build Coastguard Worker msgtype: A cstruct.Struct, the data type to parse the dump results as. 280*2f2c4c7aSAndroid Build Coastguard Worker attrs: A string, the raw bytes of any request attributes to include. 281*2f2c4c7aSAndroid Build Coastguard Worker 282*2f2c4c7aSAndroid Build Coastguard Worker Returns: 283*2f2c4c7aSAndroid Build Coastguard Worker A list of (msg, attrs) tuples where msg is of type msgtype and attrs is 284*2f2c4c7aSAndroid Build Coastguard Worker a dict of attributes. 285*2f2c4c7aSAndroid Build Coastguard Worker """ 286*2f2c4c7aSAndroid Build Coastguard Worker # Create a netlink dump request containing the msg. 287*2f2c4c7aSAndroid Build Coastguard Worker flags = NLM_F_DUMP | NLM_F_REQUEST 288*2f2c4c7aSAndroid Build Coastguard Worker msg = b"" if msg is None else msg.Pack() 289*2f2c4c7aSAndroid Build Coastguard Worker length = len(NLMsgHdr) + len(msg) + len(attrs) 290*2f2c4c7aSAndroid Build Coastguard Worker nlmsghdr = NLMsgHdr((length, command, flags, self.seq, self.pid)) 291*2f2c4c7aSAndroid Build Coastguard Worker 292*2f2c4c7aSAndroid Build Coastguard Worker # Send the request. 293*2f2c4c7aSAndroid Build Coastguard Worker request = nlmsghdr.Pack() + msg + attrs 294*2f2c4c7aSAndroid Build Coastguard Worker self.MaybeDebugCommand(command, flags, request) 295*2f2c4c7aSAndroid Build Coastguard Worker self._Send(request) 296*2f2c4c7aSAndroid Build Coastguard Worker 297*2f2c4c7aSAndroid Build Coastguard Worker # Keep reading netlink messages until we get a NLMSG_DONE. 298*2f2c4c7aSAndroid Build Coastguard Worker out = [] 299*2f2c4c7aSAndroid Build Coastguard Worker while True: 300*2f2c4c7aSAndroid Build Coastguard Worker data = self._Recv() 301*2f2c4c7aSAndroid Build Coastguard Worker response_type = NLMsgHdr(data).type 302*2f2c4c7aSAndroid Build Coastguard Worker if response_type == NLMSG_DONE: 303*2f2c4c7aSAndroid Build Coastguard Worker break 304*2f2c4c7aSAndroid Build Coastguard Worker elif response_type == NLMSG_ERROR: 305*2f2c4c7aSAndroid Build Coastguard Worker # Likely means that the kernel didn't like our dump request. 306*2f2c4c7aSAndroid Build Coastguard Worker # Parse the error and throw an exception. 307*2f2c4c7aSAndroid Build Coastguard Worker self._ParseAck(data) 308*2f2c4c7aSAndroid Build Coastguard Worker out.extend(self._GetMsgList(msgtype, data, False)) 309*2f2c4c7aSAndroid Build Coastguard Worker 310*2f2c4c7aSAndroid Build Coastguard Worker return out 311