xref: /aosp_15_r20/kernel/tests/net/test/genetlink.py (revision 2f2c4c7ab4226c71756b9c31670392fdd6887c4f)
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