]>
git.ipfire.org Git - thirdparty/hostap.git/blob - tests/hwsim/netlink.py
2 # (Generic) Netlink message generation/parsing
3 # Copyright (c) 2007 Johannes Berg <johannes@sipsolutions.net>
4 # Copyright (c) 2014 Intel Corporation
6 # This software may be distributed under the terms of the BSD license.
7 # See README for more details.
25 def __init__(self
, attr_type
, data
, *values
):
26 self
._type
= attr_type
28 self
._data
= struct
.pack(data
, *values
)
33 hdr
= struct
.pack("HH", len(self
._data
) + 4, self
._type
)
34 length
= len(self
._data
)
35 pad
= ((length
+ 4 - 1) & ~
3) - length
36 return hdr
+ self
._data
+ b
'\x00' * pad
39 return '<Attr type %d, data "%s">' % (self
._type
, repr(self
._data
))
42 return struct
.unpack('H', self
._data
)[0]
44 return struct
.unpack('h', self
._data
)[0]
46 return struct
.unpack('I', self
._data
)[0]
48 return struct
.unpack('i', self
._data
)[0]
52 return self
._data
.split('\0')[0]
54 return parse_attributes(self
._data
)
57 def __init__(self
, attr_type
, data
):
58 Attr
.__init
__(self
, attr_type
, "%ds" % len(data
), data
)
60 class NulStrAttr(Attr
):
61 def __init__(self
, attr_type
, data
):
62 Attr
.__init
__(self
, attr_type
, "%dsB" % len(data
), data
, 0)
65 def __init__(self
, attr_type
, val
):
66 Attr
.__init
__(self
, attr_type
, "I", val
)
69 def __init__(self
, attr_type
, val
):
70 Attr
.__init
__(self
, attr_type
, "B", val
)
73 def __init__(self
, attr_type
):
74 Attr
.__init
__(self
, attr_type
, b
"")
77 def __init__(self
, attr_type
, attrs
):
83 for attr
in self
.attrs
:
84 contents
.append(attr
._dump
())
85 contents
= ''.join(contents
)
86 length
= len(contents
)
87 hdr
= struct
.pack("HH", length
+4, self
.type)
100 NETLINK_FIB_LOOKUP
= 10
101 NETLINK_CONNECTOR
= 11
102 NETLINK_NETFILTER
= 12
105 NETLINK_KOBJECT_UEVENT
= 15
108 class Message(object):
109 def __init__(self
, msg_type
, flags
=0, seq
=-1, payload
=None):
114 payload
= payload
or []
115 if isinstance(payload
, list):
116 self
.payload
= bytes()
118 self
.payload
+= attr
._dump
()
120 self
.payload
= payload
122 def send(self
, conn
):
124 self
.seq
= conn
.seq()
127 length
= len(self
.payload
)
129 hdr
= struct
.pack("IHHII", length
+ 4*4, self
.type,
130 self
.flags
, self
.seq
, self
.pid
)
131 conn
.send(hdr
+ self
.payload
)
134 return '<netlink.Message type=%d, pid=%d, seq=%d, flags=0x%x "%s">' % (
135 self
.type, self
.pid
, self
.seq
, self
.flags
, repr(self
.payload
))
139 assert self
.type == NLMSG_ERROR
140 return struct
.unpack("i", self
.payload
[:4])[0]
142 def send_and_recv(self
, conn
):
146 if m
.seq
== self
.seq
:
149 class Connection(object):
150 def __init__(self
, nltype
, groups
=0, unexpected_msg_handler
=None):
151 self
.descriptor
= socket
.socket(socket
.AF_NETLINK
,
152 socket
.SOCK_RAW
, nltype
)
153 self
.descriptor
.setsockopt(socket
.SOL_SOCKET
, socket
.SO_SNDBUF
, 65536)
154 self
.descriptor
.setsockopt(socket
.SOL_SOCKET
, socket
.SO_RCVBUF
, 65536)
155 self
.descriptor
.bind((0, groups
))
156 self
.pid
, self
.groups
= self
.descriptor
.getsockname()
158 self
.unexpected
= unexpected_msg_handler
160 self
.descriptor
.send(msg
)
162 contents
= self
.descriptor
.recv(16384)
163 # XXX: python doesn't give us message flags, check
164 # len(contents) vs. msglen for TRUNC
165 msglen
, msg_type
, flags
, seq
, pid
= struct
.unpack("IHHII",
167 msg
= Message(msg_type
, flags
, seq
, contents
[16:])
169 if msg
.type == NLMSG_ERROR
:
173 err
= OSError("Netlink error: %s (%d)" % (
174 os
.strerror(-errno
), -errno
))
182 def parse_attributes(data
):
185 attr_len
, attr_type
= struct
.unpack("HH", data
[:4])
186 attrs
[attr_type
] = Attr(attr_type
, data
[4:attr_len
])
187 attr_len
= ((attr_len
+ 4 - 1) & ~
3)
188 data
= data
[attr_len
:]
194 CTRL_CMD_NEWFAMILY
= 1
195 CTRL_CMD_DELFAMILY
= 2
196 CTRL_CMD_GETFAMILY
= 3
202 CTRL_ATTR_FAMILY_ID
= 1
203 CTRL_ATTR_FAMILY_NAME
= 2
204 CTRL_ATTR_VERSION
= 3
205 CTRL_ATTR_HDRSIZE
= 4
206 CTRL_ATTR_MAXATTR
= 5
209 class GenlHdr(object):
210 def __init__(self
, cmd
, version
=0):
212 self
.version
= version
214 return struct
.pack("BBxx", self
.cmd
, self
.version
)
216 def _genl_hdr_parse(data
):
217 return GenlHdr(*struct
.unpack("BBxx", data
))
219 GENL_ID_CTRL
= NLMSG_MIN_TYPE
221 class GenlMessage(Message
):
222 def __init__(self
, family
, cmd
, attrs
=[], flags
=0):
223 Message
.__init
__(self
, family
, flags
=flags
, payload
=[GenlHdr(cmd
)] + attrs
)
225 class GenlController(object):
226 def __init__(self
, conn
):
228 def get_family_id(self
, family
):
229 a
= NulStrAttr(CTRL_ATTR_FAMILY_NAME
, family
)
230 m
= GenlMessage(GENL_ID_CTRL
, CTRL_CMD_GETFAMILY
, flags
=NLM_F_REQUEST
, attrs
=[a
])
233 gh
= _genl_hdr_parse(m
.payload
[:4])
234 attrs
= parse_attributes(m
.payload
[4:])
235 return attrs
[CTRL_ATTR_FAMILY_ID
].u16()
237 genl_controller
= GenlController(Connection(NETLINK_GENERIC
))