#!/usr/local/bin/python3 import struct from ctypes import c_int64 from ctypes import c_long from ctypes import sizeof from ctypes import Structure from enum import Enum from atf_python.sys.netlink.attrs import NlAttr from atf_python.sys.netlink.attrs import NlAttrIp4 from atf_python.sys.netlink.attrs import NlAttrIp6 from atf_python.sys.netlink.attrs import NlAttrNested from atf_python.sys.netlink.attrs import NlAttrS32 from atf_python.sys.netlink.attrs import NlAttrStr from atf_python.sys.netlink.attrs import NlAttrU16 from atf_python.sys.netlink.attrs import NlAttrU32 from atf_python.sys.netlink.attrs import NlAttrU8 from atf_python.sys.netlink.base_headers import GenlMsgHdr from atf_python.sys.netlink.message import NlMsgCategory from atf_python.sys.netlink.message import NlMsgProps from atf_python.sys.netlink.message import StdNetlinkMessage from atf_python.sys.netlink.utils import AttrDescr from atf_python.sys.netlink.utils import enum_or_int from atf_python.sys.netlink.utils import prepare_attrs_map class NetlinkGenlMessage(StdNetlinkMessage): messages = [] nl_attrs_map = {} family_name = None def __init__(self, helper, family_id, cmd=0): super().__init__(helper, family_id) self.base_hdr = GenlMsgHdr(cmd=enum_or_int(cmd)) def parse_base_header(self, data): if len(data) < sizeof(GenlMsgHdr): raise ValueError("length less than GenlMsgHdr header") ghdr = GenlMsgHdr.from_buffer_copy(data) return (ghdr, sizeof(GenlMsgHdr)) def _get_msg_type(self): return self.base_hdr.cmd def print_nl_header(self, prepend=""): # len=44, type=RTM_DELROUTE, flags=NLM_F_REQUEST|NLM_F_ACK, seq=1641163704, pid=0 # noqa: E501 hdr = self.nl_hdr print( "{}len={}, family={}, flags={}(0x{:X}), seq={}, pid={}".format( prepend, hdr.nlmsg_len, self.family_name, self.get_nlm_flags_str(), hdr.nlmsg_flags, hdr.nlmsg_seq, hdr.nlmsg_pid, ) ) def print_base_header(self, hdr, prepend=""): print( "{}cmd={} version={} reserved={}".format( prepend, self.msg_name, hdr.version, hdr.reserved ) ) GenlCtrlFamilyName = "nlctrl" class GenlCtrlMsgType(Enum): CTRL_CMD_UNSPEC = 0 CTRL_CMD_NEWFAMILY = 1 CTRL_CMD_DELFAMILY = 2 CTRL_CMD_GETFAMILY = 3 CTRL_CMD_NEWOPS = 4 CTRL_CMD_DELOPS = 5 CTRL_CMD_GETOPS = 6 CTRL_CMD_NEWMCAST_GRP = 7 CTRL_CMD_DELMCAST_GRP = 8 CTRL_CMD_GETMCAST_GRP = 9 CTRL_CMD_GETPOLICY = 10 class GenlCtrlAttrType(Enum): CTRL_ATTR_FAMILY_ID = 1 CTRL_ATTR_FAMILY_NAME = 2 CTRL_ATTR_VERSION = 3 CTRL_ATTR_HDRSIZE = 4 CTRL_ATTR_MAXATTR = 5 CTRL_ATTR_OPS = 6 CTRL_ATTR_MCAST_GROUPS = 7 CTRL_ATTR_POLICY = 8 CTRL_ATTR_OP_POLICY = 9 CTRL_ATTR_OP = 10 class GenlCtrlAttrOpType(Enum): CTRL_ATTR_OP_ID = 1 CTRL_ATTR_OP_FLAGS = 2 class GenlCtrlAttrMcastGroupsType(Enum): CTRL_ATTR_MCAST_GRP_NAME = 1 CTRL_ATTR_MCAST_GRP_ID = 2 genl_ctrl_attrs = prepare_attrs_map( [ AttrDescr(GenlCtrlAttrType.CTRL_ATTR_FAMILY_ID, NlAttrU16), AttrDescr(GenlCtrlAttrType.CTRL_ATTR_FAMILY_NAME, NlAttrStr), AttrDescr(GenlCtrlAttrType.CTRL_ATTR_VERSION, NlAttrU32), AttrDescr(GenlCtrlAttrType.CTRL_ATTR_HDRSIZE, NlAttrU32), AttrDescr(GenlCtrlAttrType.CTRL_ATTR_MAXATTR, NlAttrU32), AttrDescr( GenlCtrlAttrType.CTRL_ATTR_OPS, NlAttrNested, [ AttrDescr(GenlCtrlAttrOpType.CTRL_ATTR_OP_ID, NlAttrU32), AttrDescr(GenlCtrlAttrOpType.CTRL_ATTR_OP_FLAGS, NlAttrU32), ], True, ), AttrDescr( GenlCtrlAttrType.CTRL_ATTR_MCAST_GROUPS, NlAttrNested, [ AttrDescr( GenlCtrlAttrMcastGroupsType.CTRL_ATTR_MCAST_GRP_NAME, NlAttrStr ), AttrDescr( GenlCtrlAttrMcastGroupsType.CTRL_ATTR_MCAST_GRP_ID, NlAttrU32 ), ], True, ), ] ) class NetlinkGenlCtrlMessage(NetlinkGenlMessage): messages = [ NlMsgProps(GenlCtrlMsgType.CTRL_CMD_NEWFAMILY, NlMsgCategory.NEW), NlMsgProps(GenlCtrlMsgType.CTRL_CMD_GETFAMILY, NlMsgCategory.GET), NlMsgProps(GenlCtrlMsgType.CTRL_CMD_DELFAMILY, NlMsgCategory.DELETE), ] nl_attrs_map = genl_ctrl_attrs family_name = GenlCtrlFamilyName CarpFamilyName = "carp" class CarpMsgType(Enum): CARP_NL_CMD_UNSPEC = 0 CARP_NL_CMD_GET = 1 CARP_NL_CMD_SET = 2 class CarpAttrType(Enum): CARP_NL_UNSPEC = 0 CARP_NL_VHID = 1 CARP_NL_STATE = 2 CARP_NL_ADVBASE = 3 CARP_NL_ADVSKEW = 4 CARP_NL_KEY = 5 CARP_NL_IFINDEX = 6 CARP_NL_ADDR = 7 CARP_NL_ADDR6 = 8 CARP_NL_IFNAME = 9 carp_gen_attrs = prepare_attrs_map( [ AttrDescr(CarpAttrType.CARP_NL_VHID, NlAttrU32), AttrDescr(CarpAttrType.CARP_NL_STATE, NlAttrU32), AttrDescr(CarpAttrType.CARP_NL_ADVBASE, NlAttrS32), AttrDescr(CarpAttrType.CARP_NL_ADVSKEW, NlAttrS32), AttrDescr(CarpAttrType.CARP_NL_KEY, NlAttr), AttrDescr(CarpAttrType.CARP_NL_IFINDEX, NlAttrU32), AttrDescr(CarpAttrType.CARP_NL_ADDR, NlAttrIp4), AttrDescr(CarpAttrType.CARP_NL_ADDR6, NlAttrIp6), AttrDescr(CarpAttrType.CARP_NL_IFNAME, NlAttrStr), ] ) class CarpGenMessage(NetlinkGenlMessage): messages = [ NlMsgProps(CarpMsgType.CARP_NL_CMD_GET, NlMsgCategory.GET), NlMsgProps(CarpMsgType.CARP_NL_CMD_SET, NlMsgCategory.NEW), ] nl_attrs_map = carp_gen_attrs family_name = CarpFamilyName KtestFamilyName = "ktest" class KtestMsgType(Enum): KTEST_CMD_UNSPEC = 0 KTEST_CMD_LIST = 1 KTEST_CMD_RUN = 2 KTEST_CMD_NEWTEST = 3 KTEST_CMD_NEWMESSAGE = 4 class KtestAttrType(Enum): KTEST_ATTR_MOD_NAME = 1 KTEST_ATTR_TEST_NAME = 2 KTEST_ATTR_TEST_DESCR = 3 KTEST_ATTR_TEST_META = 4 class KtestLogMsgType(Enum): KTEST_MSG_START = 1 KTEST_MSG_END = 2 KTEST_MSG_LOG = 3 KTEST_MSG_FAIL = 4 class KtestMsgAttrType(Enum): KTEST_MSG_ATTR_TS = 1 KTEST_MSG_ATTR_FUNC = 2 KTEST_MSG_ATTR_FILE = 3 KTEST_MSG_ATTR_LINE = 4 KTEST_MSG_ATTR_TEXT = 5 KTEST_MSG_ATTR_LEVEL = 6 KTEST_MSG_ATTR_META = 7 class timespec(Structure): _fields_ = [ ("tv_sec", c_int64), ("tv_nsec", c_long), ] class NlAttrTS(NlAttr): DATA_LEN = sizeof(timespec) def __init__(self, nla_type, val): self.ts = val super().__init__(nla_type, b"") @property def nla_len(self): return NlAttr.HDR_LEN + self.DATA_LEN def _print_attr_value(self): return " tv_sec={} tv_nsec={}".format(self.ts.tv_sec, self.ts.tv_nsec) @staticmethod def _validate(data): assert len(data) == NlAttr.HDR_LEN + NlAttrTS.DATA_LEN nla_len, nla_type = struct.unpack("@HH", data[: NlAttr.HDR_LEN]) assert nla_len == NlAttr.HDR_LEN + NlAttrTS.DATA_LEN @classmethod def _parse(cls, data): nla_len, nla_type = struct.unpack("@HH", data[: NlAttr.HDR_LEN]) val = timespec.from_buffer_copy(data[NlAttr.HDR_LEN :]) return cls(nla_type, val) def __bytes__(self): return self._to_bytes(bytes(self.ts)) ktest_info_attrs = prepare_attrs_map( [ AttrDescr(KtestAttrType.KTEST_ATTR_MOD_NAME, NlAttrStr), AttrDescr(KtestAttrType.KTEST_ATTR_TEST_NAME, NlAttrStr), AttrDescr(KtestAttrType.KTEST_ATTR_TEST_DESCR, NlAttrStr), ] ) ktest_msg_attrs = prepare_attrs_map( [ AttrDescr(KtestMsgAttrType.KTEST_MSG_ATTR_FUNC, NlAttrStr), AttrDescr(KtestMsgAttrType.KTEST_MSG_ATTR_FILE, NlAttrStr), AttrDescr(KtestMsgAttrType.KTEST_MSG_ATTR_LINE, NlAttrU32), AttrDescr(KtestMsgAttrType.KTEST_MSG_ATTR_TEXT, NlAttrStr), AttrDescr(KtestMsgAttrType.KTEST_MSG_ATTR_LEVEL, NlAttrU8), AttrDescr(KtestMsgAttrType.KTEST_MSG_ATTR_TS, NlAttrTS), ] ) class KtestInfoMessage(NetlinkGenlMessage): messages = [ NlMsgProps(KtestMsgType.KTEST_CMD_LIST, NlMsgCategory.GET), NlMsgProps(KtestMsgType.KTEST_CMD_RUN, NlMsgCategory.NEW), NlMsgProps(KtestMsgType.KTEST_CMD_NEWTEST, NlMsgCategory.NEW), ] nl_attrs_map = ktest_info_attrs family_name = KtestFamilyName class KtestMsgMessage(NetlinkGenlMessage): messages = [ NlMsgProps(KtestMsgType.KTEST_CMD_NEWMESSAGE, NlMsgCategory.NEW), ] nl_attrs_map = ktest_msg_attrs family_name = KtestFamilyName handler_classes = { CarpFamilyName: [CarpGenMessage], GenlCtrlFamilyName: [NetlinkGenlCtrlMessage], KtestFamilyName: [KtestInfoMessage, KtestMsgMessage], }