svinota / pyroute2

Python Netlink and PF_ROUTE library — network configuration and monitoring
https://pyroute2.org/
Other
948 stars 243 forks source link

NFTables.get_rules(): Invalid argument #559

Open tomkcook opened 5 years ago

tomkcook commented 5 years ago
$ sudo python
Python 2.7.9 (default, Sep 17 2016, 20:26:04) 
[GCC 4.9.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import pyroute2
>>> nft = pyroute2.NFTables()
>>> nft.get_rules()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.7/dist-packages/pyroute2-0.5.3-py2.7.egg/pyroute2/nftables/main.py", line 34, in get_rules
    return self.request_get(nfgen_msg(), NFT_MSG_GETRULE)
  File "/usr/local/lib/python2.7/dist-packages/pyroute2-0.5.3-py2.7.egg/pyroute2/netlink/nfnetlink/nftsocket.py", line 412, in request_get
    msg_flags, terminate=terminate)
  File "/usr/local/lib/python2.7/dist-packages/pyroute2-0.5.3-py2.7.egg/pyroute2/netlink/nlsocket.py", line 352, in nlm_request
    return tuple(self._genlm_request(*argv, **kwarg))
  File "/usr/local/lib/python2.7/dist-packages/pyroute2-0.5.3-py2.7.egg/pyroute2/netlink/nlsocket.py", line 836, in nlm_request
    callback=callback):
  File "/usr/local/lib/python2.7/dist-packages/pyroute2-0.5.3-py2.7.egg/pyroute2/netlink/nlsocket.py", line 355, in get
    return tuple(self._genlm_get(*argv, **kwarg))
  File "/usr/local/lib/python2.7/dist-packages/pyroute2-0.5.3-py2.7.egg/pyroute2/netlink/nlsocket.py", line 679, in get
    raise msg['header']['error']
pyroute2.netlink.exceptions.NetlinkError: (22, 'Invalid argument')
$ uname -r
4.4.50-hypriotos-v7+
$ pip freeze
pyroute2==0.5.3

I'll have a look into debugging this, but I'm not exactly sure where to start.

svinota commented 5 years ago

Is it possible that the nftables are not supported by the kernel you run the code on? I couldn't reproduce.

pallas commented 4 years ago

What version of Linux are you using? Linux 5.4 got a lot stricter about nested attributes. Specifically, it looks like pyroute2 is not setting NLA_F_NESTED on some/all NLAs and nla_parse_nested will reject these attrs.

pallas commented 4 years ago

So I'm definitely seeing this in other code. An NLA with nla_flags = NLA_F_NESTED is setting the right type in encode, but in the kernel attr->nla_type & NLA_F_NESTED is false.

pallas commented 4 years ago

But I can't figure out why, since the pyroute2 code seems to be doing the right thing.

pallas commented 4 years ago

Actually, I figured out the issue. If you append an NLA directly, it does not set the NESTED bit. If you extract the attrs from the NLA and append that, it does. Sorry for hijacking this thread.

svinota commented 4 years ago

@pallas np, you're probably right. I just can not reproduce the issue. Do you know the conditions? It works starting at least from kernel version 4.19.x and up to net-next. I'll try older versions later, if I will have time.

pallas commented 4 years ago

Yeah, I do. Sorry if this is a bit abstract, but if you have a top_level_thing of type genlmsg class with *nested_thing in the nla_map, and you try to do

tlt = top_level_thing()
nt = nested_thing()
tlt['attrs'].append(('NESTED_THINGS', [nl]))

it does not set the NESTED bit. If instead you do

tlt = top_level_thing()
nt = nested_thing()
tlt['attrs'].append(('NESTED_THINGS', [{'attrs': nt['attrs']}]))

then the NESTED bit is set.

I ended up making the above transformation in https://github.com/pallas/wgnlpy/commit/cb37bf269cbec72439f59183762046c653c39f1a to get that project working on Linux 5.4, but I think the check might have come in with Linux 5.2.

pallas commented 4 years ago

And specifically, I have not tried this with NFTables. (Hence the apology for hijacking the thread.)