> ++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
> 

Reply via email to