Path: blob/main/tests/atf_python/sys/netlink/attrs.py
39553 views
import socket1import struct2from enum import Enum34from atf_python.sys.netlink.utils import align45from atf_python.sys.netlink.utils import enum_or_int678class NlAttr(object):9HDR_LEN = 4 # sizeof(struct nlattr)1011def __init__(self, nla_type, data):12if isinstance(nla_type, Enum):13self._nla_type = nla_type.value14self._enum = nla_type15else:16self._nla_type = nla_type17self._enum = None18self.nla_list = []19self._data = data2021@property22def nla_type(self):23return self._nla_type & 0x3FFF2425@property26def nla_len(self):27return len(self._data) + 42829def add_nla(self, nla):30self.nla_list.append(nla)3132def print_attr(self, prepend=""):33if self._enum is not None:34type_str = self._enum.name35else:36type_str = "nla#{}".format(self.nla_type)37print(38"{}len={} type={}({}){}".format(39prepend, self.nla_len, type_str, self.nla_type, self._print_attr_value()40)41)4243@staticmethod44def _validate(data):45if len(data) < 4:46raise ValueError("attribute too short")47nla_len, nla_type = struct.unpack("@HH", data[:4])48if nla_len > len(data):49raise ValueError("attribute length too big")50if nla_len < 4:51raise ValueError("attribute length too short")5253@classmethod54def _parse(cls, data):55nla_len, nla_type = struct.unpack("@HH", data[:4])56return cls(nla_type, data[4:])5758@classmethod59def from_bytes(cls, data, attr_type_enum=None):60cls._validate(data)61attr = cls._parse(data)62attr._enum = attr_type_enum63return attr6465def _to_bytes(self, data: bytes):66ret = data67if align4(len(ret)) != len(ret):68ret = data + bytes(align4(len(ret)) - len(ret))69return struct.pack("@HH", len(data) + 4, self._nla_type) + ret7071def __bytes__(self):72return self._to_bytes(self._data)7374def _print_attr_value(self):75return " " + " ".join(["x{:02X}".format(b) for b in self._data])767778class NlAttrNested(NlAttr):79def __init__(self, nla_type, val):80super().__init__(nla_type, b"")81self.nla_list = val8283def get_nla(self, nla_type):84nla_type_raw = enum_or_int(nla_type)85for nla in self.nla_list:86if nla.nla_type == nla_type_raw:87return nla88return None8990@property91def nla_len(self):92return align4(len(b"".join([bytes(nla) for nla in self.nla_list]))) + 49394def print_attr(self, prepend=""):95if self._enum is not None:96type_str = self._enum.name97else:98type_str = "nla#{}".format(self.nla_type)99print(100"{}len={} type={}({}) {{".format(101prepend, self.nla_len, type_str, self.nla_type102)103)104for nla in self.nla_list:105nla.print_attr(prepend + " ")106print("{}}}".format(prepend))107108def __bytes__(self):109return self._to_bytes(b"".join([bytes(nla) for nla in self.nla_list]))110111112class NlAttrU32(NlAttr):113def __init__(self, nla_type, val):114self.u32 = enum_or_int(val)115super().__init__(nla_type, b"")116117@property118def nla_len(self):119return 8120121def _print_attr_value(self):122return " val={}".format(self.u32)123124@staticmethod125def _validate(data):126assert len(data) == 8127nla_len, nla_type = struct.unpack("@HH", data[:4])128assert nla_len == 8129130@classmethod131def _parse(cls, data):132nla_len, nla_type, val = struct.unpack("@HHI", data)133return cls(nla_type, val)134135def __bytes__(self):136return self._to_bytes(struct.pack("@I", self.u32))137138139class NlAttrS32(NlAttr):140def __init__(self, nla_type, val):141self.s32 = enum_or_int(val)142super().__init__(nla_type, b"")143144@property145def nla_len(self):146return 8147148def _print_attr_value(self):149return " val={}".format(self.s32)150151@staticmethod152def _validate(data):153assert len(data) == 8154nla_len, nla_type = struct.unpack("@HH", data[:4])155assert nla_len == 8156157@classmethod158def _parse(cls, data):159nla_len, nla_type, val = struct.unpack("@HHi", data)160return cls(nla_type, val)161162def __bytes__(self):163return self._to_bytes(struct.pack("@i", self.s32))164165166class NlAttrU16(NlAttr):167def __init__(self, nla_type, val):168self.u16 = enum_or_int(val)169super().__init__(nla_type, b"")170171@property172def nla_len(self):173return 6174175def _print_attr_value(self):176return " val={}".format(self.u16)177178@staticmethod179def _validate(data):180assert len(data) == 6181nla_len, nla_type = struct.unpack("@HH", data[:4])182assert nla_len == 6183184@classmethod185def _parse(cls, data):186nla_len, nla_type, val = struct.unpack("@HHH", data)187return cls(nla_type, val)188189def __bytes__(self):190return self._to_bytes(struct.pack("@H", self.u16))191192193class NlAttrU8(NlAttr):194def __init__(self, nla_type, val):195self.u8 = enum_or_int(val)196super().__init__(nla_type, b"")197198@property199def nla_len(self):200return 5201202def _print_attr_value(self):203return " val={}".format(self.u8)204205@staticmethod206def _validate(data):207assert len(data) == 5208nla_len, nla_type = struct.unpack("@HH", data[:4])209assert nla_len == 5210211@classmethod212def _parse(cls, data):213nla_len, nla_type, val = struct.unpack("@HHB", data)214return cls(nla_type, val)215216def __bytes__(self):217return self._to_bytes(struct.pack("@B", self.u8))218219220class NlAttrIp(NlAttr):221def __init__(self, nla_type, addr: str):222super().__init__(nla_type, b"")223self.addr = addr224if ":" in self.addr:225self.family = socket.AF_INET6226else:227self.family = socket.AF_INET228229@staticmethod230def _validate(data):231nla_len, nla_type = struct.unpack("@HH", data[:4])232data_len = nla_len - 4233if data_len != 4 and data_len != 16:234raise ValueError(235"Error validating attr {}: nla_len is not valid".format( # noqa: E501236nla_type237)238)239240@property241def nla_len(self):242if self.family == socket.AF_INET6:243return 20244else:245return 8246return align4(len(self._data)) + 4247248@classmethod249def _parse(cls, data):250nla_len, nla_type = struct.unpack("@HH", data[:4])251data_len = len(data) - 4252if data_len == 4:253addr = socket.inet_ntop(socket.AF_INET, data[4:8])254else:255addr = socket.inet_ntop(socket.AF_INET6, data[4:20])256return cls(nla_type, addr)257258def __bytes__(self):259return self._to_bytes(socket.inet_pton(self.family, self.addr))260261def _print_attr_value(self):262return " addr={}".format(self.addr)263264265class NlAttrIp4(NlAttrIp):266def __init__(self, nla_type, addr: str):267super().__init__(nla_type, addr)268assert self.family == socket.AF_INET269270271class NlAttrIp6(NlAttrIp):272def __init__(self, nla_type, addr: str):273super().__init__(nla_type, addr)274assert self.family == socket.AF_INET6275276277class NlAttrStr(NlAttr):278def __init__(self, nla_type, text):279super().__init__(nla_type, b"")280self.text = text281282@staticmethod283def _validate(data):284NlAttr._validate(data)285try:286data[4:].decode("utf-8")287except Exception as e:288raise ValueError("wrong utf-8 string: {}".format(e))289290@property291def nla_len(self):292return len(self.text) + 5293294@classmethod295def _parse(cls, data):296text = data[4:-1].decode("utf-8")297nla_len, nla_type = struct.unpack("@HH", data[:4])298return cls(nla_type, text)299300def __bytes__(self):301return self._to_bytes(bytes(self.text, encoding="utf-8") + bytes(1))302303def _print_attr_value(self):304return ' val="{}"'.format(self.text)305306307class NlAttrStrn(NlAttr):308def __init__(self, nla_type, text):309super().__init__(nla_type, b"")310self.text = text311312@staticmethod313def _validate(data):314NlAttr._validate(data)315try:316data[4:].decode("utf-8")317except Exception as e:318raise ValueError("wrong utf-8 string: {}".format(e))319320@property321def nla_len(self):322return len(self.text) + 4323324@classmethod325def _parse(cls, data):326text = data[4:].decode("utf-8")327nla_len, nla_type = struct.unpack("@HH", data[:4])328return cls(nla_type, text)329330def __bytes__(self):331return self._to_bytes(bytes(self.text, encoding="utf-8"))332333def _print_attr_value(self):334return ' val="{}"'.format(self.text)335336337