svinota / pyroute2

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

RTM_GETNSID fails; generates message of size 25 instead of 28 #496

Closed thediveo closed 6 years ago

thediveo commented 6 years ago

I'm trying to do a IPRoute().nlm_request(req, RTM_GETNSID). I'm using pyroute2 0.5.0.

from pyroute2 import IPRoute
import socket
from pyroute2.netlink import NLM_F_REQUEST
import pyroute2.netlink.rtnl as rtnl
import pyroute2.netlink.rtnl.nsidmsg as nsidmsg

netstack = IPRoute()
with open('/proc/{}/ns/net'.format(12345), "r") as netnsf: # PID 12345
    req = nsidmsg.nsidmsg()
    req['rtgen_family'] = 0
    req['attrs'] = [('NETNSA_FD', netnsf.fileno())]
    req.encode()
    ret = netstack.nlm_request(req, rtnl.RTM_GETNSID, NLM_F_REQUEST)

The request fails with error 22, invalid argument. Strace shows this, indicating that only 25 octets are indicated in the header:

sendto(5, {{len=25, type=0x5a /* NLMSG_??? */, flags=NLM_F_REQUEST, seq=255, pid=31204}, "\x00\x00\x00\x00\x08\x00\x03\x00\x06"}, 28, 0, {sa_family=AF_NETLINK, nl_pid=0, nl_groups=00000000}, 12) = 28

As the FD should be encoded as uint32, I would expect at least three more octets for the FD.

Comparing this to a RTM_GETNSID request from lsns I see that the request should have a length of 28.

thediveo commented 6 years ago

Arrrrgh :) Now, if I trick the message encoder as follows (notice the superfluous duplicate with a dummy FD value):

req['attrs'] = [('NETNSA_FD', netnsf.fileno()), ('NETNSA_FD', 0)]

...then the request succeeds and gives me back the expected results!

svinota commented 6 years ago

Bad. Definitively a bug. To be fixed asap.

svinota commented 6 years ago

The issue was not in the NETNSA_FD per se, but in the rtgenmsg padding. Fixed.