1#!/usr/local/bin/python3 2import struct 3from ctypes import c_int64 4from ctypes import c_long 5from ctypes import sizeof 6from ctypes import Structure 7from enum import Enum 8 9from atf_python.sys.netlink.attrs import NlAttr 10from atf_python.sys.netlink.attrs import NlAttrIp4 11from atf_python.sys.netlink.attrs import NlAttrIp6 12from atf_python.sys.netlink.attrs import NlAttrNested 13from atf_python.sys.netlink.attrs import NlAttrS32 14from atf_python.sys.netlink.attrs import NlAttrStr 15from atf_python.sys.netlink.attrs import NlAttrU16 16from atf_python.sys.netlink.attrs import NlAttrU32 17from atf_python.sys.netlink.attrs import NlAttrU8 18from atf_python.sys.netlink.base_headers import GenlMsgHdr 19from atf_python.sys.netlink.message import NlMsgCategory 20from atf_python.sys.netlink.message import NlMsgProps 21from atf_python.sys.netlink.message import StdNetlinkMessage 22from atf_python.sys.netlink.utils import AttrDescr 23from atf_python.sys.netlink.utils import enum_or_int 24from atf_python.sys.netlink.utils import prepare_attrs_map 25 26 27class NetlinkGenlMessage(StdNetlinkMessage): 28 messages = [] 29 nl_attrs_map = {} 30 family_name = None 31 32 def __init__(self, helper, family_id, cmd=0): 33 super().__init__(helper, family_id) 34 self.base_hdr = GenlMsgHdr(cmd=enum_or_int(cmd)) 35 36 def parse_base_header(self, data): 37 if len(data) < sizeof(GenlMsgHdr): 38 raise ValueError("length less than GenlMsgHdr header") 39 ghdr = GenlMsgHdr.from_buffer_copy(data) 40 return (ghdr, sizeof(GenlMsgHdr)) 41 42 def _get_msg_type(self): 43 return self.base_hdr.cmd 44 45 def print_nl_header(self, prepend=""): 46 # len=44, type=RTM_DELROUTE, flags=NLM_F_REQUEST|NLM_F_ACK, seq=1641163704, pid=0 # noqa: E501 47 hdr = self.nl_hdr 48 print( 49 "{}len={}, family={}, flags={}(0x{:X}), seq={}, pid={}".format( 50 prepend, 51 hdr.nlmsg_len, 52 self.family_name, 53 self.get_nlm_flags_str(), 54 hdr.nlmsg_flags, 55 hdr.nlmsg_seq, 56 hdr.nlmsg_pid, 57 ) 58 ) 59 60 def print_base_header(self, hdr, prepend=""): 61 print( 62 "{}cmd={} version={} reserved={}".format( 63 prepend, self.msg_name, hdr.version, hdr.reserved 64 ) 65 ) 66 67 68GenlCtrlFamilyName = "nlctrl" 69 70 71class GenlCtrlMsgType(Enum): 72 CTRL_CMD_UNSPEC = 0 73 CTRL_CMD_NEWFAMILY = 1 74 CTRL_CMD_DELFAMILY = 2 75 CTRL_CMD_GETFAMILY = 3 76 CTRL_CMD_NEWOPS = 4 77 CTRL_CMD_DELOPS = 5 78 CTRL_CMD_GETOPS = 6 79 CTRL_CMD_NEWMCAST_GRP = 7 80 CTRL_CMD_DELMCAST_GRP = 8 81 CTRL_CMD_GETMCAST_GRP = 9 82 CTRL_CMD_GETPOLICY = 10 83 84 85class GenlCtrlAttrType(Enum): 86 CTRL_ATTR_FAMILY_ID = 1 87 CTRL_ATTR_FAMILY_NAME = 2 88 CTRL_ATTR_VERSION = 3 89 CTRL_ATTR_HDRSIZE = 4 90 CTRL_ATTR_MAXATTR = 5 91 CTRL_ATTR_OPS = 6 92 CTRL_ATTR_MCAST_GROUPS = 7 93 CTRL_ATTR_POLICY = 8 94 CTRL_ATTR_OP_POLICY = 9 95 CTRL_ATTR_OP = 10 96 97 98class GenlCtrlAttrOpType(Enum): 99 CTRL_ATTR_OP_ID = 1 100 CTRL_ATTR_OP_FLAGS = 2 101 102 103class GenlCtrlAttrMcastGroupsType(Enum): 104 CTRL_ATTR_MCAST_GRP_NAME = 1 105 CTRL_ATTR_MCAST_GRP_ID = 2 106 107 108genl_ctrl_attrs = prepare_attrs_map( 109 [ 110 AttrDescr(GenlCtrlAttrType.CTRL_ATTR_FAMILY_ID, NlAttrU16), 111 AttrDescr(GenlCtrlAttrType.CTRL_ATTR_FAMILY_NAME, NlAttrStr), 112 AttrDescr(GenlCtrlAttrType.CTRL_ATTR_VERSION, NlAttrU32), 113 AttrDescr(GenlCtrlAttrType.CTRL_ATTR_HDRSIZE, NlAttrU32), 114 AttrDescr(GenlCtrlAttrType.CTRL_ATTR_MAXATTR, NlAttrU32), 115 AttrDescr( 116 GenlCtrlAttrType.CTRL_ATTR_OPS, 117 NlAttrNested, 118 [ 119 AttrDescr(GenlCtrlAttrOpType.CTRL_ATTR_OP_ID, NlAttrU32), 120 AttrDescr(GenlCtrlAttrOpType.CTRL_ATTR_OP_FLAGS, NlAttrU32), 121 ], 122 True, 123 ), 124 AttrDescr( 125 GenlCtrlAttrType.CTRL_ATTR_MCAST_GROUPS, 126 NlAttrNested, 127 [ 128 AttrDescr( 129 GenlCtrlAttrMcastGroupsType.CTRL_ATTR_MCAST_GRP_NAME, NlAttrStr 130 ), 131 AttrDescr( 132 GenlCtrlAttrMcastGroupsType.CTRL_ATTR_MCAST_GRP_ID, NlAttrU32 133 ), 134 ], 135 True, 136 ), 137 ] 138) 139 140 141class NetlinkGenlCtrlMessage(NetlinkGenlMessage): 142 messages = [ 143 NlMsgProps(GenlCtrlMsgType.CTRL_CMD_NEWFAMILY, NlMsgCategory.NEW), 144 NlMsgProps(GenlCtrlMsgType.CTRL_CMD_GETFAMILY, NlMsgCategory.GET), 145 NlMsgProps(GenlCtrlMsgType.CTRL_CMD_DELFAMILY, NlMsgCategory.DELETE), 146 ] 147 nl_attrs_map = genl_ctrl_attrs 148 family_name = GenlCtrlFamilyName 149 150 151CarpFamilyName = "carp" 152 153 154class CarpMsgType(Enum): 155 CARP_NL_CMD_UNSPEC = 0 156 CARP_NL_CMD_GET = 1 157 CARP_NL_CMD_SET = 2 158 159 160class CarpAttrType(Enum): 161 CARP_NL_UNSPEC = 0 162 CARP_NL_VHID = 1 163 CARP_NL_STATE = 2 164 CARP_NL_ADVBASE = 3 165 CARP_NL_ADVSKEW = 4 166 CARP_NL_KEY = 5 167 CARP_NL_IFINDEX = 6 168 CARP_NL_ADDR = 7 169 CARP_NL_ADDR6 = 8 170 CARP_NL_IFNAME = 9 171 172 173carp_gen_attrs = prepare_attrs_map( 174 [ 175 AttrDescr(CarpAttrType.CARP_NL_VHID, NlAttrU32), 176 AttrDescr(CarpAttrType.CARP_NL_STATE, NlAttrU32), 177 AttrDescr(CarpAttrType.CARP_NL_ADVBASE, NlAttrS32), 178 AttrDescr(CarpAttrType.CARP_NL_ADVSKEW, NlAttrS32), 179 AttrDescr(CarpAttrType.CARP_NL_KEY, NlAttr), 180 AttrDescr(CarpAttrType.CARP_NL_IFINDEX, NlAttrU32), 181 AttrDescr(CarpAttrType.CARP_NL_ADDR, NlAttrIp4), 182 AttrDescr(CarpAttrType.CARP_NL_ADDR6, NlAttrIp6), 183 AttrDescr(CarpAttrType.CARP_NL_IFNAME, NlAttrStr), 184 ] 185) 186 187 188class CarpGenMessage(NetlinkGenlMessage): 189 messages = [ 190 NlMsgProps(CarpMsgType.CARP_NL_CMD_GET, NlMsgCategory.GET), 191 NlMsgProps(CarpMsgType.CARP_NL_CMD_SET, NlMsgCategory.NEW), 192 ] 193 nl_attrs_map = carp_gen_attrs 194 family_name = CarpFamilyName 195 196 197KtestFamilyName = "ktest" 198 199 200class KtestMsgType(Enum): 201 KTEST_CMD_UNSPEC = 0 202 KTEST_CMD_LIST = 1 203 KTEST_CMD_RUN = 2 204 KTEST_CMD_NEWTEST = 3 205 KTEST_CMD_NEWMESSAGE = 4 206 207 208class KtestAttrType(Enum): 209 KTEST_ATTR_MOD_NAME = 1 210 KTEST_ATTR_TEST_NAME = 2 211 KTEST_ATTR_TEST_DESCR = 3 212 KTEST_ATTR_TEST_META = 4 213 214 215class KtestLogMsgType(Enum): 216 KTEST_MSG_START = 1 217 KTEST_MSG_END = 2 218 KTEST_MSG_LOG = 3 219 KTEST_MSG_FAIL = 4 220 221 222class KtestMsgAttrType(Enum): 223 KTEST_MSG_ATTR_TS = 1 224 KTEST_MSG_ATTR_FUNC = 2 225 KTEST_MSG_ATTR_FILE = 3 226 KTEST_MSG_ATTR_LINE = 4 227 KTEST_MSG_ATTR_TEXT = 5 228 KTEST_MSG_ATTR_LEVEL = 6 229 KTEST_MSG_ATTR_META = 7 230 231 232class timespec(Structure): 233 _fields_ = [ 234 ("tv_sec", c_int64), 235 ("tv_nsec", c_long), 236 ] 237 238 239class NlAttrTS(NlAttr): 240 DATA_LEN = sizeof(timespec) 241 242 def __init__(self, nla_type, val): 243 self.ts = val 244 super().__init__(nla_type, b"") 245 246 @property 247 def nla_len(self): 248 return NlAttr.HDR_LEN + self.DATA_LEN 249 250 def _print_attr_value(self): 251 return " tv_sec={} tv_nsec={}".format(self.ts.tv_sec, self.ts.tv_nsec) 252 253 @staticmethod 254 def _validate(data): 255 assert len(data) == NlAttr.HDR_LEN + NlAttrTS.DATA_LEN 256 nla_len, nla_type = struct.unpack("@HH", data[: NlAttr.HDR_LEN]) 257 assert nla_len == NlAttr.HDR_LEN + NlAttrTS.DATA_LEN 258 259 @classmethod 260 def _parse(cls, data): 261 nla_len, nla_type = struct.unpack("@HH", data[: NlAttr.HDR_LEN]) 262 val = timespec.from_buffer_copy(data[NlAttr.HDR_LEN :]) 263 return cls(nla_type, val) 264 265 def __bytes__(self): 266 return self._to_bytes(bytes(self.ts)) 267 268 269ktest_info_attrs = prepare_attrs_map( 270 [ 271 AttrDescr(KtestAttrType.KTEST_ATTR_MOD_NAME, NlAttrStr), 272 AttrDescr(KtestAttrType.KTEST_ATTR_TEST_NAME, NlAttrStr), 273 AttrDescr(KtestAttrType.KTEST_ATTR_TEST_DESCR, NlAttrStr), 274 ] 275) 276 277 278ktest_msg_attrs = prepare_attrs_map( 279 [ 280 AttrDescr(KtestMsgAttrType.KTEST_MSG_ATTR_FUNC, NlAttrStr), 281 AttrDescr(KtestMsgAttrType.KTEST_MSG_ATTR_FILE, NlAttrStr), 282 AttrDescr(KtestMsgAttrType.KTEST_MSG_ATTR_LINE, NlAttrU32), 283 AttrDescr(KtestMsgAttrType.KTEST_MSG_ATTR_TEXT, NlAttrStr), 284 AttrDescr(KtestMsgAttrType.KTEST_MSG_ATTR_LEVEL, NlAttrU8), 285 AttrDescr(KtestMsgAttrType.KTEST_MSG_ATTR_TS, NlAttrTS), 286 ] 287) 288 289 290class KtestInfoMessage(NetlinkGenlMessage): 291 messages = [ 292 NlMsgProps(KtestMsgType.KTEST_CMD_LIST, NlMsgCategory.GET), 293 NlMsgProps(KtestMsgType.KTEST_CMD_RUN, NlMsgCategory.NEW), 294 NlMsgProps(KtestMsgType.KTEST_CMD_NEWTEST, NlMsgCategory.NEW), 295 ] 296 nl_attrs_map = ktest_info_attrs 297 family_name = KtestFamilyName 298 299 300class KtestMsgMessage(NetlinkGenlMessage): 301 messages = [ 302 NlMsgProps(KtestMsgType.KTEST_CMD_NEWMESSAGE, NlMsgCategory.NEW), 303 ] 304 nl_attrs_map = ktest_msg_attrs 305 family_name = KtestFamilyName 306 307 308handler_classes = { 309 CarpFamilyName: [CarpGenMessage], 310 GenlCtrlFamilyName: [NetlinkGenlCtrlMessage], 311 KtestFamilyName: [KtestInfoMessage, KtestMsgMessage], 312} 313