Hi all,

I am experiencing trouble with using Bird over IPv6 inside a VRF, and reduced
this down to a problem with IPv6 `bind`.

I have a VRF called "vrf_freifunk", with some GRE tunnel devices in it:

> 3: vrf_freifunk: <NOARP,MASTER,UP,LOWER_UP> mtu 65536 qdisc noqueue state UP 
> group default qlen 1000
>     link/ether 6e:6d:9f:5d:f3:f2 brd ff:ff:ff:ff:ff:ff
> 12: tun-up-a_ak@NONE: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1280 qdisc noqueue 
> master vrf_freifunk state UNKNOWN group default qlen 1000
>     link/gre 82.165.162.239 peer 185.66.195.0
>     inet 100.64.3.21/31 scope global tun-up-a_ak
>        valid_lft forever preferred_lft forever
>     inet6 2a03:2260:0:194::2/64 scope global 
>        valid_lft forever preferred_lft forever
>     inet6 fe80::200:5efe:52a5:a2ef/64 scope link 
>        valid_lft forever preferred_lft forever

Now I am running the following python script to reproduce the problem:

> #!/usr/bin/python3                                                            
>                                                                               
>                                                        
> import socket
> 
> s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP)
> s.setsockopt(socket.SOL_SOCKET, socket.SO_BINDTODEVICE, b"vrf_freifunk")
> s.bind(("100.64.3.21", 188))
> 
> s = socket.socket(socket.AF_INET6, socket.SOCK_STREAM, socket.IPPROTO_TCP)
> s.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 1)
> s.setsockopt(socket.SOL_SOCKET, socket.SO_BINDTODEVICE, b"vrf_freifunk")
> s.bind(("2a03:2260:0:194::2", 188))

The IPv4 block completes successfully, but doing the same with IPv6 in the
second block fails saying:

> Traceback (most recent call last):
>   File "./test.py", line 11, in <module>
>     s.bind(("2a03:2260:0:194::2", 188))
> OSError: [Errno 99] Cannot assign requested address

If instead, in the last line, I use the IPv6 address of eth0 (which is not
inside this VRF), the `bind` call succeeds.  On the other hand, when I try using
the eth0 IPv4 address in the first block, `bind` fails as expected because the
address is not inside `vrf_freifunk`.
If I replace `vrf_freifunk` by `tun-up-a_ak` (which is more like what Bird
does), the behavior remains the same.

I think this is a kernel bug, it seems like setting `SO_BINDTODEVICE` on the
IPv6 socket is just ignored entirely.

This is using a Debian stable backports kernel:

> $ uname -a
> Linux gw1.saar.freifunk.net 4.18.0-0.bpo.3-amd64 #1 SMP Debian 
> 4.18.20-2~bpo9+1 (2018-12-08) x86_64 GNU/Linux

Any help debugging this would be appreciated.
Kind regards,
Ralf

Reply via email to