1*2f2c4c7aSAndroid Build Coastguard Worker#!/usr/bin/python3 2*2f2c4c7aSAndroid Build Coastguard Worker# 3*2f2c4c7aSAndroid Build Coastguard Worker# Copyright 2017 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"""Classes for generic netlink.""" 18*2f2c4c7aSAndroid Build Coastguard Worker 19*2f2c4c7aSAndroid Build Coastguard Workerimport collections 20*2f2c4c7aSAndroid Build Coastguard Workerfrom socket import * # pylint: disable=wildcard-import 21*2f2c4c7aSAndroid Build Coastguard Workerimport struct 22*2f2c4c7aSAndroid Build Coastguard Worker 23*2f2c4c7aSAndroid Build Coastguard Workerimport cstruct 24*2f2c4c7aSAndroid Build Coastguard Workerimport netlink 25*2f2c4c7aSAndroid Build Coastguard Worker 26*2f2c4c7aSAndroid Build Coastguard Worker### Generic netlink constants. See include/uapi/linux/genetlink.h. 27*2f2c4c7aSAndroid Build Coastguard Worker# The generic netlink control family. 28*2f2c4c7aSAndroid Build Coastguard WorkerGENL_ID_CTRL = 16 29*2f2c4c7aSAndroid Build Coastguard Worker 30*2f2c4c7aSAndroid Build Coastguard Worker# Commands. 31*2f2c4c7aSAndroid Build Coastguard WorkerCTRL_CMD_GETFAMILY = 3 32*2f2c4c7aSAndroid Build Coastguard Worker 33*2f2c4c7aSAndroid Build Coastguard Worker# Attributes. 34*2f2c4c7aSAndroid Build Coastguard WorkerCTRL_ATTR_FAMILY_ID = 1 35*2f2c4c7aSAndroid Build Coastguard WorkerCTRL_ATTR_FAMILY_NAME = 2 36*2f2c4c7aSAndroid Build Coastguard WorkerCTRL_ATTR_VERSION = 3 37*2f2c4c7aSAndroid Build Coastguard WorkerCTRL_ATTR_HDRSIZE = 4 38*2f2c4c7aSAndroid Build Coastguard WorkerCTRL_ATTR_MAXATTR = 5 39*2f2c4c7aSAndroid Build Coastguard WorkerCTRL_ATTR_OPS = 6 40*2f2c4c7aSAndroid Build Coastguard WorkerCTRL_ATTR_MCAST_GROUPS = 7 41*2f2c4c7aSAndroid Build Coastguard Worker 42*2f2c4c7aSAndroid Build Coastguard Worker# Attributes netsted inside CTRL_ATTR_OPS. 43*2f2c4c7aSAndroid Build Coastguard WorkerCTRL_ATTR_OP_ID = 1 44*2f2c4c7aSAndroid Build Coastguard WorkerCTRL_ATTR_OP_FLAGS = 2 45*2f2c4c7aSAndroid Build Coastguard Worker 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 WorkerGenlmsghdr = cstruct.Struct("genlmsghdr", "BBxx", "cmd version") 50*2f2c4c7aSAndroid Build Coastguard Worker 51*2f2c4c7aSAndroid Build Coastguard Worker 52*2f2c4c7aSAndroid Build Coastguard Workerclass GenericNetlink(netlink.NetlinkSocket): 53*2f2c4c7aSAndroid Build Coastguard Worker """Base class for all generic netlink classes.""" 54*2f2c4c7aSAndroid Build Coastguard Worker 55*2f2c4c7aSAndroid Build Coastguard Worker NL_DEBUG = [] 56*2f2c4c7aSAndroid Build Coastguard Worker 57*2f2c4c7aSAndroid Build Coastguard Worker def __init__(self): 58*2f2c4c7aSAndroid Build Coastguard Worker super(GenericNetlink, self).__init__(netlink.NETLINK_GENERIC) 59*2f2c4c7aSAndroid Build Coastguard Worker 60*2f2c4c7aSAndroid Build Coastguard Worker def _SendCommand(self, family, command, version, data, flags): 61*2f2c4c7aSAndroid Build Coastguard Worker genlmsghdr = Genlmsghdr((command, version)) 62*2f2c4c7aSAndroid Build Coastguard Worker self._SendNlRequest(family, genlmsghdr.Pack() + data, flags) 63*2f2c4c7aSAndroid Build Coastguard Worker 64*2f2c4c7aSAndroid Build Coastguard Worker def _Dump(self, family, command, version): 65*2f2c4c7aSAndroid Build Coastguard Worker msg = Genlmsghdr((command, version)) 66*2f2c4c7aSAndroid Build Coastguard Worker return super(GenericNetlink, self)._Dump(family, msg, Genlmsghdr) 67*2f2c4c7aSAndroid Build Coastguard Worker 68*2f2c4c7aSAndroid Build Coastguard Worker 69*2f2c4c7aSAndroid Build Coastguard Workerclass GenericNetlinkControl(GenericNetlink): 70*2f2c4c7aSAndroid Build Coastguard Worker """Generic netlink control class. 71*2f2c4c7aSAndroid Build Coastguard Worker 72*2f2c4c7aSAndroid Build Coastguard Worker This interface is used to manage other generic netlink families. We currently 73*2f2c4c7aSAndroid Build Coastguard Worker use it only to find the family ID for address families of interest.""" 74*2f2c4c7aSAndroid Build Coastguard Worker 75*2f2c4c7aSAndroid Build Coastguard Worker def _DecodeOps(self, data): 76*2f2c4c7aSAndroid Build Coastguard Worker ops = [] 77*2f2c4c7aSAndroid Build Coastguard Worker Op = collections.namedtuple("Op", ["id", "flags"]) 78*2f2c4c7aSAndroid Build Coastguard Worker # TODO: call _ParseAttributes on the nested data instead of manual parsing. 79*2f2c4c7aSAndroid Build Coastguard Worker while data: 80*2f2c4c7aSAndroid Build Coastguard Worker # Skip the nest marker. 81*2f2c4c7aSAndroid Build Coastguard Worker datalen, index, data = data[:2], data[2:4], data[4:] 82*2f2c4c7aSAndroid Build Coastguard Worker 83*2f2c4c7aSAndroid Build Coastguard Worker nla, nla_data, data = self._ReadNlAttr(data) 84*2f2c4c7aSAndroid Build Coastguard Worker if nla.nla_type != CTRL_ATTR_OP_ID: 85*2f2c4c7aSAndroid Build Coastguard Worker raise ValueError("Expected CTRL_ATTR_OP_ID, got %d" % nla.nla_type) 86*2f2c4c7aSAndroid Build Coastguard Worker op_id = struct.unpack("=I", nla_data)[0] 87*2f2c4c7aSAndroid Build Coastguard Worker 88*2f2c4c7aSAndroid Build Coastguard Worker nla, nla_data, data = self._ReadNlAttr(data) 89*2f2c4c7aSAndroid Build Coastguard Worker if nla.nla_type != CTRL_ATTR_OP_FLAGS: 90*2f2c4c7aSAndroid Build Coastguard Worker raise ValueError("Expected CTRL_ATTR_OP_FLAGS, got %d" % nla.type) 91*2f2c4c7aSAndroid Build Coastguard Worker op_flags = struct.unpack("=I", nla_data)[0] 92*2f2c4c7aSAndroid Build Coastguard Worker 93*2f2c4c7aSAndroid Build Coastguard Worker ops.append(Op(op_id, op_flags)) 94*2f2c4c7aSAndroid Build Coastguard Worker return ops 95*2f2c4c7aSAndroid Build Coastguard Worker 96*2f2c4c7aSAndroid Build Coastguard Worker def _Decode(self, command, msg, nla_type, nla_data, nested): 97*2f2c4c7aSAndroid Build Coastguard Worker """Decodes generic netlink control attributes to human-readable format.""" 98*2f2c4c7aSAndroid Build Coastguard Worker 99*2f2c4c7aSAndroid Build Coastguard Worker name = self._GetConstantName(__name__, nla_type, "CTRL_ATTR_") 100*2f2c4c7aSAndroid Build Coastguard Worker 101*2f2c4c7aSAndroid Build Coastguard Worker if name == "CTRL_ATTR_FAMILY_ID": 102*2f2c4c7aSAndroid Build Coastguard Worker data = struct.unpack("=H", nla_data)[0] 103*2f2c4c7aSAndroid Build Coastguard Worker elif name == "CTRL_ATTR_FAMILY_NAME": 104*2f2c4c7aSAndroid Build Coastguard Worker data = nla_data.strip(b"\x00") 105*2f2c4c7aSAndroid Build Coastguard Worker elif name in ["CTRL_ATTR_VERSION", "CTRL_ATTR_HDRSIZE", "CTRL_ATTR_MAXATTR"]: 106*2f2c4c7aSAndroid Build Coastguard Worker data = struct.unpack("=I", nla_data)[0] 107*2f2c4c7aSAndroid Build Coastguard Worker elif name == "CTRL_ATTR_OPS": 108*2f2c4c7aSAndroid Build Coastguard Worker data = self._DecodeOps(nla_data) 109*2f2c4c7aSAndroid Build Coastguard Worker else: 110*2f2c4c7aSAndroid Build Coastguard Worker data = nla_data 111*2f2c4c7aSAndroid Build Coastguard Worker 112*2f2c4c7aSAndroid Build Coastguard Worker return name, data 113*2f2c4c7aSAndroid Build Coastguard Worker 114*2f2c4c7aSAndroid Build Coastguard Worker def GetFamily(self, name): 115*2f2c4c7aSAndroid Build Coastguard Worker """Returns the family ID for the specified family name.""" 116*2f2c4c7aSAndroid Build Coastguard Worker data = self._NlAttrStr(CTRL_ATTR_FAMILY_NAME, name) 117*2f2c4c7aSAndroid Build Coastguard Worker self._SendCommand(GENL_ID_CTRL, CTRL_CMD_GETFAMILY, 0, data, netlink.NLM_F_REQUEST) 118*2f2c4c7aSAndroid Build Coastguard Worker hdr, attrs = self._GetMsg(Genlmsghdr) 119*2f2c4c7aSAndroid Build Coastguard Worker return attrs["CTRL_ATTR_FAMILY_ID"] 120*2f2c4c7aSAndroid Build Coastguard Worker 121*2f2c4c7aSAndroid Build Coastguard Worker 122*2f2c4c7aSAndroid Build Coastguard Workerif __name__ == "__main__": 123*2f2c4c7aSAndroid Build Coastguard Worker g = GenericNetlinkControl() 124*2f2c4c7aSAndroid Build Coastguard Worker print(g.GetFamily("tcp_metrics")) 125