> ++static void
> ++wpa_driver_openbsd_event_receive(int sock, void *global, void *sock_ctx)
> ++{
> ++ struct openbsd_driver_data *drv = sock_ctx;
> ++ struct rt_msghdr *rtm;
> ++ struct if_ieee80211_data *ifie;
> ++ char *rtmmsg;
> ++ ssize_t n;
> ++
> ++ rtmmsg = os_zalloc(RTM_READSZ);
> ++ if (rtmmsg == NULL) {
> ++ wpa_printf(MSG_ERROR, "Can't allocate space for routing
> message");
> ++ return;
> ++ }
> ++
> ++ do {
> ++ n = read(sock, rtmmsg, RTM_READSZ);
> ++ } while (n == -1 && errno == EINTR);
> ++
> ++ if (n == -1)
> ++ goto done;
> ++
> ++ rtm = (struct rt_msghdr *)rtmmsg;
> ++
> ++ if ((size_t)n < sizeof(rtm->rtm_msglen) ||
> ++ n < rtm->rtm_msglen ||
> ++ rtm->rtm_version != RTM_VERSION)
> ++ goto done;
Other programs reading messages from the route socket handle this
slightly differently. They don't treat a read() as a single message,
instead they loop over it, looking at the first part, deciding whether
to act on it ("is it the right rtm_version, are we interested in the
RTM_*?"), if not then they skip rtm_msglen bytes and start again.
See e.g. rtmsg_process() in usr.sbin/snmpd/kroute.c.
> ++
> ++ if (rtm->rtm_index != drv->ifindex)
> ++ goto done;
> ++
> ++ switch (rtm->rtm_type) {
> ++ case RTM_80211INFO:
> ++ ifie = &((struct if_ieee80211_msghdr *)rtm)->ifim_ifie;
> ++
> ++ if ((ifie->ifie_nwid_len != drv->nwid_len) ||
> ++ (os_memcmp(drv->nwid, ifie->ifie_nwid,
> ++ ifie->ifie_nwid_len) != 0) ||
> ++ (os_memcmp(drv->addr, ifie->ifie_addr,
> ++ IEEE80211_ADDR_LEN) != 0)) {
> ++ os_memcpy(drv->addr, ifie->ifie_addr,
> ++ IEEE80211_ADDR_LEN);
> ++
> ++ os_memcpy(drv->nwid, ifie->ifie_nwid,
> ++ ifie->ifie_nwid_len);
> ++ drv->nwid_len = ifie->ifie_nwid_len;
> ++
> ++ /* Emit ASSOC event */
> ++ wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL);
> ++ }
> ++ break;
> ++ case RTM_IFINFO:
> ++ /* This is here so we can react to suspend/resume.
> ++ *
> ++ * This is a bit rough, sometimes there are two or more
> ++ * IFINFOs notifying us that the device just got "up"
> ++ * again. It doesn't seem to hurt to issue multiple
> ++ * EVENT_ASSOC in those cases though.
> ++ */
> ++ if (rtm->rtm_flags & RTF_UP)
> ++ wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL);
> ++ break;
> ++ default:
> ++ ;;
> ++ }
> ++
> ++
> ++done:
> ++ os_free(rtmmsg);
> ++}
> ++
> + static void *
> + wpa_driver_openbsd_init(void *ctx, const char *ifname)
> + {
> +@@ -103,9 +190,21 @@ wpa_driver_openbsd_init(void *ctx, const char *ifname)
> + if (drv->sock < 0)
> + goto fail;
> +
> ++ drv->rtsock = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC);
> ++ if (drv->rtsock < 0)
> ++ goto fail;
> ++
> + drv->ctx = ctx;
> + os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
> +
> ++ drv->ifindex = if_nametoindex(drv->ifname);
> ++ if (drv->ifindex == 0) /* No interface with that name */
> ++ goto fail;
> ++
> ++ drv->nwid_len = wpa_driver_openbsd_get_ssid(drv, drv->nwid);
> ++ wpa_driver_openbsd_get_bssid(drv, drv->addr);
> ++
> ++ eloop_register_read_sock(drv->rtsock, wpa_driver_openbsd_event_receive,
> NULL, drv);
> + return drv;
> +
> + fail:
> +@@ -119,7 +218,11 @@ wpa_driver_openbsd_deinit(void *priv)
> + {
> + struct openbsd_driver_data *drv = priv;
> +
> ++ eloop_unregister_read_sock(drv->rtsock);
> ++
> + close(drv->sock);
> ++ close(drv->rtsock);
> ++
> + os_free(drv);
> + }
> +
>
>
>
> On 2018 Dec 13 (Thu) at 19:30:11 +0100 (+0100), Gregor Best wrote:
> :
> :Hi Mikolaj et al,
> :
> :Mikolaj Kucharski <[email protected]> writes:
> :
> :>
> :> Here is debug output of one day session, with suspend in the middle
> :> when going home, back to work and home again.
> :> [...]
> :> Tomorrow I may give you example of above log when walking around the
> :> office, to compare events while switching APs.
> :> [...]
> :
> :That'd be good, thank you.
> :
> :> The other day I did testing by walking around and it works most of the
> :> time, however there is a race somewhere, as while I was walking around
> :> I sometimes ended up without connection and ifconfig(8) at the same
> :> time was showing:
> :>
> :> status: active
> :> ieee80211: join lighthouse chan 100 bssid <random-ap-close> <level>dBm
> wpaprotos wpa2 wpaakms 802.1x wpaciphers ccmp wpagroupcipher ccmp
> :>
> :> like network should work, but it didn't and connection was totally
> :> offline.
> :
> :> This is very empirical, but it looked to me, when I walked
> :> slower to give wpa_supplicant time to reassoc with each access point on
> :> the way it all worked. When I got bored and walked faster, passing by
> :> multiple APs on the way and with reassocs happening one after another,
> :> before previous assoc was able to finish and me finally stopping, I
> :> ended up with iwn0 card with status active, but no connectivity.
> :> Restarting slaacd(8) or dhclient(8) was not helping as problem was layer
> :> below them.
> :> [...]
> :
> :Yeah, I've got the feeling that wpa_supplicant really doesn't like
> :getting poked while it's doing its thing. Maybe I've got to work on the
> :timing here a bit or sort of deduplicate ASSOC events after multiple
> :IFINFO/802INFO are received.
> :
> :> [...]
> :> I think your diff makes sense and with handling of RTM_IFINFO it's good
> :> progress in correct direction. I even took your diff and tested with
> :> latest wpa_supplicant 2.7 and it works there too.
> :> [...]
> :
> :That is good to hear. I'm planning on sending this upstream as soon as
> :we've agreed it's more or less working.
> :
> :> [...]
> :> If you would like to see any specific info tomorrow, please let me know
> :> I will try to arrange something. After that I'll go offline for family
> :> time.
> :> [...]
> :
> :I'm afraid I don't have anything more specific I could ask you to test.
> :Thanks a bunch for your help this far. I'll just have to walk around my
> :university some time next week, I'm not at work then anyway :)
> :
> :> [...]
> :>> ++ if (rtm->rtm_type == RTM_80211INFO) {
> :>> ++ printf("RTM_80211INFO received\n");
> :>
> :> This printf(3) should be removed or changed into wpa_printf(). For my tests
> :> I've used wpa_printf(MSG_DEBUG, ...), which I think is good enough balance
> :> of being not noisy in logs by default, but still providing info when there
> :> is a need via debug flag to the cli. However this is your call and giving
> :> the current sparsity of debug log lines in this c-file, I would just remove
> :> it.
> :> [...]
> :
> :Absolutely. This was an oversight that I wanted to remove before sending
> :out the patch. Same for the weird indentation :)
> :
> :--
> : Gregor
>
>
>
> --
> If someone had told me I would be Pope one day, I would have studied
> harder.
> -- Pope John Paul I
>