Hi,

On Tue, 29 Mar 2022 17:28:23 +0900
Yuichiro NAITO <naito.yuich...@gmail.com> wrote:
> There is one thing I'm worrying about.
> Ifconfig doesn't show wgrtable value with your patch.
> In my use case as follows, it seems that setting `wgrtable 1` is
> ignored.
> 
> ```
> # route -T1 add default `cat /etc/mygate`
> # ifconfig wg0 create wgport 7111 wgkey `cat /etc/mykey.wg0`
> # ifconfig wg0 up
> # ifconfig wg0 wgrtable 1
> # ifconfig wg0
> wg0: flags=80c3<UP,BROADCAST,RUNNING,NOARP,MULTICAST> mtu 1420
>         index 6 priority 0 llprio 3
>         wgport 7111
>         wgpubkey e/CYTG1RGqT4jmrY0Fom8cAdtOWP7F/gBVwamyINRlg=
>         groups: wg
> ```

Thank you for pointing this out.

In this case, wg0 is binding 7111/udp on rdomain 0.  So I have
supposed ignoring "wgrtable 1" is correct.  But if we configure
wgrtable when creating,

 % doas ifconfig wg0 create wgport 7111 wgrtable 1 wgkey `openssl rand -base64 
32` up
 % doas ifconfig wg0 
 wg0: flags=80c3<UP,BROADCAST,RUNNING,NOARP,MULTICAST> mtu 1420
         index 13 priority 0 llprio 3
         wgport 7111
         wgrtable 1
         wgpubkey /4v4hsi426MsVZojJ0rwRvk8kK0jSckjcU2Z1L/k5W8=
         groups: wg
 % 

It displays "wgrtable 1".  And actually

 % netstat -T0 -naf inet | grep 7111                                 
 % netstat -T1 -naf inet | grep 7111                                 
 udp          0      0  *.7111                 *.*                   
 % 

it binds 7111/udp on rtable 1.

So I start wondering why binding 7111/udp on table 1 fails with
EADDRINUSE when 7111/udp on rtable 0 is used.

> On 3/28/22 15:59, YASUOKA Masahiko wrote:
>> On Mon, 28 Mar 2022 15:20:02 +0900
>> Yuichiro NAITO <naito.yuich...@gmail.com> wrote:
>>> Thanks for the explanation.
>>> I understand how your patch works.
>>>
>>> I want to ask the goal of your patch.
>>> It seems just removing 'Address already in use' message.
>>> Is my guessing right?
>> Yes.  There is nothing to do, since the command is to bind the same
>> port, protocol, and domain of prevous.
>> The code seems to do such the skip already, but it lacks consideration
>> for rtable_l2(rtable) != rtable case.
>> 
>>> On 3/28/22 14:01, YASUOKA Masahiko wrote:
>>>> Hi,
>>>> On Mon, 28 Mar 2022 12:12:39 +0900
>>>> Yuichiro NAITO <naito.yuich...@gmail.com> wrote:
>>>>> On 3/27/22 18:25, YASUOKA Masahiko wrote:
>>>>>> Hi,
>>>>>> On Wed, 9 Mar 2022 15:28:44 +0900
>>>>>> Yuichiro NAITO <naito.yuich...@gmail.com> wrote:
>>>>>>> I see 'Address already in use' message,
>>>>>>> when I change wgrtable for a running wg interface.
>>>>>>> It doesn't make sense to me.
>>>>>>>
>>>>>>> It can be reproduced by the following command sequence.
>>>>>>>
>>>>>>> ```
>>>>>>> # route -T1 add default `cat /etc/mygate`
>>>>>>> # ifconfig wg0 create wgport 7111 wgkey `cat /etc/mykey.wg0`
>>>>>>> # ifconfig wg0 up
>>>>>>> # ifconfig wg0 wgrtable 1
>>>>>>> ifconfig: SIOCSWG: Address already in use
>>>>>>> ```
>>>>>>>
>>>>>>> When I down wg0 interface before changing wgrtable,
>>>>>>> It succeeds and no messages are shown.
>>>>>>>
>>>>>>> I investigated the reason why 'Address already in use' is shown.
>>>>>>>
>>>>>>> If wgrtable is specified by ifconfig argument,
>>>>>>> `wg_ioctl_set` function in `sys/net/if_wg.c` is called.
>>>>>>>
>>>>>>> And if the wg interface is running, `wg_bind` function is called.
>>>>>>> `wg_bind` creates new sockets (IPv4 and 6) and replace them from old
>>>>>>> ones.
>>>>>>>
>>>>>>> If only wgrtable is changed, `wg_bind` binds as same port as existing
>>>>>>> sockets.
>>>>>>> So 'Address already in use' is shown.
>>>>>>>
>>>>>>> Here is a simple patch to close existing sockets before `wg_bind`.
>>>>>>> It works for me but I'm not 100% sure this is right fix.
>>>>>>>
>>>>>>> Any other ideas?
>>>>>>>
>>>>>>> ```
>>>>>>> diff --git a/sys/net/if_wg.c b/sys/net/if_wg.c
>>>>>>> index 4dae3e3c976..0159664fb34 100644
>>>>>>> --- a/sys/net/if_wg.c
>>>>>>> +++ b/sys/net/if_wg.c
>>>>>>> @@ -2253,11 +2253,14 @@ wg_ioctl_set(struct wg_softc *sc, struct
>>>>>>> wg_data_io *data)
>>>>>>>         if (port != sc->sc_udp_port || rtable != sc->sc_udp_rtable) {
>>>>>>>                 TAILQ_FOREACH(peer, &sc->sc_peer_seq, p_seq_entry)
>>>>>>>                         wg_peer_clear_src(peer);
>>>>>>>
>>>>>>> -               if (sc->sc_if.if_flags & IFF_RUNNING)
>>>>>>> +               if (sc->sc_if.if_flags & IFF_RUNNING) {
>>>>>>> +                       if (port == sc->sc_udp_port)
>>>>>>> +                               wg_unbind(sc);
>>>>>>>                         if ((ret = wg_bind(sc, &port, &rtable)) != 0)
>>>>>>>                                 goto error;
>>>>>>> +               }
>>>>>>>
>>>>>>>                 sc->sc_udp_port = port;
>>>>>>>                 sc->sc_udp_rtable = rtable;
>>>>>>>         }
>>>>>>> ```
>>>>>> If rdomain 1 exists, the error will not shown.
>>>>>>     # ifconfig vether0 rdomain 1 up
>>>>>>     # ifconfig wg0 create wgport 7111 wgkey `openssl rand -base64 32` up
>>>>>>     # ifconfig wg0 wgrtable 1
>>>>>>     #
>>>>>
>>>>> Yes, if rdomain 1 is created before `ifconfig wg0 wgrtable 1`,
>>>>> setting wgrtable succeeds and there is no problem.
>>>>>
>>>>>> In the case which you reported to, it is supposed that rtable 1 exists
>>>>>> but rdomain 1 doesn't exist.
>>>>>> Even when "wgtable 1" is configured, becase there is no dedicated
>>>>>> rdomain, rdomain 0 will be used to bind the UDP port.
>>>>>
>>>>> Exactly, it's the case that I reported and want to fix.
>>>>>
>>>>>> So what wg(4) should do for this case is "nothing".
>>>>>
>>>>> I'm a little bit confused.
>>>>> As you said, I can confirm your patch doesn't set wgrtable in my use
>>>>> case.
>>>>> It is not the result that I wanted.
>>>>      # ifconfig wg0 create wgport 7111 wgkey `openssl rand -base64 32` up
>>>>      -> bind 7111/udp on rdomain 0  (1)
>>>> is expected. (1)
>>>>      # ifconfig wg0 wgrtable 1
>>>>      -> bind 7111/udp on rdomain 0  (2)
>>>> is expected, since there is no "domain 1".
>>>> If trying to do (1) and (2), then it causes EADDRINUSE since it is to
>>>> bind the same port, proto, and domain.  The latest diff is skip (2)
>>>> properly.
>>>> Previous
>>>>
>>>>>>     -    if (port != sc->sc_udp_port || rtable != sc->sc_udp_rtable) {
>>>> "rtable != sc->sc_udp_rtable" was wrong since rdomain for rtable may
>>>> not exist.  This is the cause of EADDRINUSE.
>>>>
>>>>>> So the diff is updated.
>>>>>> ok?
>>>>>> Index: sys/net/if_wg.c
>>>>>> ===================================================================
>>>>>> RCS file: /disk/cvs/openbsd/src/sys/net/if_wg.c,v
>>>>>> retrieving revision 1.22
>>>>>> diff -u -p -r1.22 if_wg.c
>>>>>> --- sys/net/if_wg.c      22 Feb 2022 01:15:02 -0000      1.22
>>>>>> +++ sys/net/if_wg.c      27 Mar 2022 09:17:08 -0000
>>>>>> @@ -2250,7 +2250,8 @@ wg_ioctl_set(struct wg_softc *sc, struct
>>>>>>          else
>>>>>>                  rtable = sc->sc_udp_rtable;
>>>>>>     -    if (port != sc->sc_udp_port || rtable != sc->sc_udp_rtable) {
>>>>>> +        if (port != sc->sc_udp_port ||
>>>>>> +            rtable_l2(rtable) != sc->sc_udp_rtable) {
>>>>>>                  TAILQ_FOREACH(peer, &sc->sc_peer_seq, p_seq_entry)
>>>>>>                          wg_peer_clear_src(peer);
>>>>>>     
>>>>>
>>>>> -- 
>>>>> Yuichiro NAITO (naito.yuich...@gmail.com)
>>>>>
>>>
>>> -- 
>>> Yuichiro NAITO (naito.yuich...@gmail.com)
>>>
> 
> -- 
> Yuichiro NAITO (naito.yuich...@gmail.com)

Reply via email to