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 # 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. So what wg(4) should do for this case is "nothing". 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);