Fri Jan 1 14:57:14 2021 UTC ()
wpa: If route socket overflows, sync drivers to system interfaces

Messages such as RTM_IFNFO or RTM_IFANNOUNCE could have been lost.
As such, sync the state of our internal driver to the state of the
system interfaces as reported by getifaddrs(2).

This change requires the routing socket be placed in non-blocking
mode. While here, set the routing and inet sockets to close on exec.


(roy)
diff -r1.37 -r1.38 src/external/bsd/wpa/dist/src/drivers/driver_bsd.c

cvs diff -r1.37 -r1.38 src/external/bsd/wpa/dist/src/drivers/driver_bsd.c (expand / switch to unified diff)

--- src/external/bsd/wpa/dist/src/drivers/driver_bsd.c 2020/07/21 10:34:16 1.37
+++ src/external/bsd/wpa/dist/src/drivers/driver_bsd.c 2021/01/01 14:57:14 1.38
@@ -6,27 +6,29 @@ @@ -6,27 +6,29 @@
6 * This software may be distributed under the terms of the BSD license. 6 * This software may be distributed under the terms of the BSD license.
7 * See README for more details. 7 * See README for more details.
8 */ 8 */
9 9
10#include "includes.h" 10#include "includes.h"
11#include <sys/ioctl.h> 11#include <sys/ioctl.h>
12 12
13#include "common.h" 13#include "common.h"
14#include "driver.h" 14#include "driver.h"
15#include "eloop.h" 15#include "eloop.h"
16#include "common/ieee802_11_defs.h" 16#include "common/ieee802_11_defs.h"
17#include "common/wpa_common.h" 17#include "common/wpa_common.h"
18 18
 19#include <ifaddrs.h>
19#include <net/if.h> 20#include <net/if.h>
 21#include <net/if_dl.h>
20#include <net/if_media.h> 22#include <net/if_media.h>
21 23
22#ifdef __NetBSD__ 24#ifdef __NetBSD__
23#include <net/if_ether.h> 25#include <net/if_ether.h>
24#else 26#else
25#include <net/ethernet.h> 27#include <net/ethernet.h>
26#endif 28#endif
27#include <net/route.h> 29#include <net/route.h>
28 30
29#ifdef __DragonFly__ 31#ifdef __DragonFly__
30#include <netproto/802_11/ieee80211_ioctl.h> 32#include <netproto/802_11/ieee80211_ioctl.h>
31#include <netproto/802_11/ieee80211_dragonfly.h> 33#include <netproto/802_11/ieee80211_dragonfly.h>
32#else /* __DragonFly__ */ 34#else /* __DragonFly__ */
@@ -605,46 +607,152 @@ bsd_set_freq(void *priv, struct hostapd_ @@ -605,46 +607,152 @@ bsd_set_freq(void *priv, struct hostapd_
605 607
606static int 608static int
607bsd_set_opt_ie(void *priv, const u8 *ie, size_t ie_len) 609bsd_set_opt_ie(void *priv, const u8 *ie, size_t ie_len)
608{ 610{
609#ifdef IEEE80211_IOC_APPIE 611#ifdef IEEE80211_IOC_APPIE
610 wpa_printf(MSG_DEBUG, "%s: set WPA+RSN ie (len %lu)", __func__, 612 wpa_printf(MSG_DEBUG, "%s: set WPA+RSN ie (len %lu)", __func__,
611 (unsigned long)ie_len); 613 (unsigned long)ie_len);
612 return bsd_set80211(priv, IEEE80211_IOC_APPIE, IEEE80211_APPIE_WPA, 614 return bsd_set80211(priv, IEEE80211_IOC_APPIE, IEEE80211_APPIE_WPA,
613 ie, ie_len); 615 ie, ie_len);
614#endif /* IEEE80211_IOC_APPIE */ 616#endif /* IEEE80211_IOC_APPIE */
615 return 0; 617 return 0;
616} 618}
617 619
 620#ifdef SO_RERROR
 621static void
 622bsd_route_overflow(int sock, void *ctx, struct bsd_driver_global *global)
 623{
 624 char event_buf[2048]; /* max size of a single route(4) msg */
 625 int n;
 626 struct ifaddrs *ifaddrs, *ifa;
 627 struct bsd_driver_data *drv;
 628 struct sockaddr_dl *sdl;
 629 union wpa_event_data event;
 630
 631 /* We need to match the system state, so drain the route
 632 * socket to avoid stale messages. */
 633 do {
 634 n = read(sock, event_buf, sizeof(event_buf));
 635 } while (n != -1 || errno == ENOBUFS);
 636
 637 if (getifaddrs(&ifaddrs) == -1) {
 638 wpa_printf(MSG_ERROR, "%s getifaddrs() failed: %s",
 639 __func__, strerror(errno));
 640 return;
 641 }
 642
 643 /* add or update existing interfaces */
 644 for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
 645 if (ifa->ifa_addr == NULL ||
 646 ifa->ifa_addr->sa_family != AF_LINK)
 647 continue;
 648 sdl = (struct sockaddr_dl *)(void *)ifa->ifa_addr;
 649 drv = bsd_get_drvname(global, ifa->ifa_name);
 650 if (drv != NULL &&
 651 (drv->ifindex != sdl->sdl_index || drv->if_removed)) {
 652 wpa_printf(MSG_DEBUG,
 653 "RTM_IFANNOUNCE: Interface '%s' added",
 654 drv->ifname);
 655 drv->ifindex = sdl->sdl_index;
 656 drv->if_removed = 0;
 657 event.interface_status.ievent = EVENT_INTERFACE_ADDED;
 658 os_strlcpy(event.interface_status.ifname, ifa->ifa_name,
 659 sizeof(event.interface_status.ifname));
 660 wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS,
 661 &event);
 662 }
 663 if (drv == NULL &&
 664 (drv = bsd_get_drvindex(global, sdl->sdl_index)) != NULL) {
 665 /* Driver name is invalid */
 666 wpa_printf(MSG_DEBUG,
 667 "RTM_IFANNOUNCE: Interface '%s' removed",
 668 drv->ifname);
 669 drv->if_removed = 1;
 670 event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
 671 os_strlcpy(event.interface_status.ifname, drv->ifname,
 672 sizeof(event.interface_status.ifname));
 673 wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS,
 674 &event);
 675 }
 676 }
 677
 678 /* punt missing interfaces and update flags */
 679 dl_list_for_each(drv, &global->ifaces, struct bsd_driver_data, list) {
 680 for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
 681 if (ifa->ifa_addr == NULL ||
 682 ifa->ifa_addr->sa_family != AF_LINK)
 683 continue;
 684 sdl = (struct sockaddr_dl *)(void *)ifa->ifa_addr;
 685 if (os_strcmp(drv->ifname, ifa->ifa_name) == 0)
 686 break;
 687 }
 688 if (ifa == NULL && !drv->if_removed) {
 689 wpa_printf(MSG_DEBUG,
 690 "RTM_IFANNOUNCE: Interface '%s' removed",
 691 drv->ifname);
 692 drv->if_removed = 1;
 693 event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
 694 os_strlcpy(event.interface_status.ifname, drv->ifname,
 695 sizeof(event.interface_status.ifname));
 696 wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS,
 697 &event);
 698 }
 699 if (ifa == NULL)
 700 continue;
 701
 702 if ((ifa->ifa_flags & IFF_UP) == 0 &&
 703 (drv->flags & IFF_UP) != 0) {
 704 wpa_printf(MSG_DEBUG, "RTM_IFINFO: Interface '%s' DOWN",
 705 drv->ifname);
 706 wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_DISABLED,
 707 NULL);
 708 } else if ((ifa->ifa_flags & IFF_UP) != 0 &&
 709 (drv->flags & IFF_UP) == 0) {
 710 wpa_printf(MSG_DEBUG, "RTM_IFINFO: Interface '%s' UP",
 711 drv->ifname);
 712 wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED,
 713 NULL);
 714 }
 715 drv->flags = ifa->ifa_flags;
 716 }
 717
 718 freeifaddrs(ifaddrs);
 719}
 720#endif
 721
618static void 722static void
619bsd_wireless_event_receive(int sock, void *ctx, void *sock_ctx) 723bsd_wireless_event_receive(int sock, void *ctx, void *sock_ctx)
620{ 724{
621 char event_buf[2048]; /* max size of a single route(4) msg */ 725 char event_buf[2048]; /* max size of a single route(4) msg */
622 struct bsd_driver_global *global = sock_ctx; 726 struct bsd_driver_global *global = sock_ctx;
623 struct bsd_driver_data *drv; 727 struct bsd_driver_data *drv;
624 struct if_announcemsghdr *ifan; 728 struct if_announcemsghdr *ifan;
625 struct if_msghdr *ifm; 729 struct if_msghdr *ifm;
626 struct rt_msghdr *rtm; 730 struct rt_msghdr *rtm;
627 union wpa_event_data event; 731 union wpa_event_data event;
628 struct ieee80211_michael_event *mic; 732 struct ieee80211_michael_event *mic;
629 struct ieee80211_leave_event *leave; 733 struct ieee80211_leave_event *leave;
630 struct ieee80211_join_event *join; 734 struct ieee80211_join_event *join;
631 int n; 735 int n;
632 736
633 n = read(sock, event_buf, sizeof(event_buf)); 737 n = read(sock, event_buf, sizeof(event_buf));
634 if (n < 0) { 738 if (n < 0) {
635 if (errno != EINTR && errno != EAGAIN) 739 if (errno != EINTR && errno != EAGAIN)
636 wpa_printf(MSG_ERROR, "%s read() failed: %s", 740 wpa_printf(MSG_ERROR, "%s read() failed: %s",
637 __func__, strerror(errno)); 741 __func__, strerror(errno));
 742#ifdef SO_RERROR
 743 if (errno == ENOBUFS)
 744 bsd_route_overflow(sock, ctx, sock_ctx);
 745#endif
638 return; 746 return;
639 } 747 }
640 748
641 rtm = (struct rt_msghdr *) event_buf; 749 rtm = (struct rt_msghdr *) event_buf;
642 if (rtm->rtm_version != RTM_VERSION) { 750 if (rtm->rtm_version != RTM_VERSION) {
643 wpa_printf(MSG_DEBUG, "Invalid routing message version=%d", 751 wpa_printf(MSG_DEBUG, "Invalid routing message version=%d",
644 rtm->rtm_version); 752 rtm->rtm_version);
645 return; 753 return;
646 } 754 }
647 os_memset(&event, 0, sizeof(event)); 755 os_memset(&event, 0, sizeof(event));
648 switch (rtm->rtm_type) { 756 switch (rtm->rtm_type) {
649 case RTM_IEEE80211: 757 case RTM_IEEE80211:
650 ifan = (struct if_announcemsghdr *) rtm; 758 ifan = (struct if_announcemsghdr *) rtm;
@@ -1550,34 +1658,34 @@ bsd_global_init(void *ctx) @@ -1550,34 +1658,34 @@ bsd_global_init(void *ctx)
1550 unsigned char msgfilter[] = { 1658 unsigned char msgfilter[] = {
1551 RTM_IEEE80211, 1659 RTM_IEEE80211,
1552 RTM_IFINFO, RTM_IFANNOUNCE, 1660 RTM_IFINFO, RTM_IFANNOUNCE,
1553 }; 1661 };
1554#endif 1662#endif
1555 1663
1556 global = os_zalloc(sizeof(*global)); 1664 global = os_zalloc(sizeof(*global));
1557 if (global == NULL) 1665 if (global == NULL)
1558 return NULL; 1666 return NULL;
1559 1667
1560 global->ctx = ctx; 1668 global->ctx = ctx;
1561 dl_list_init(&global->ifaces); 1669 dl_list_init(&global->ifaces);
1562 1670
1563 global->sock = socket(PF_INET, SOCK_DGRAM, 0); 1671 global->sock = socket(PF_INET, SOCK_DGRAM|SOCK_CLOEXEC, 0);
1564 if (global->sock < 0) { 1672 if (global->sock < 0) {
1565 wpa_printf(MSG_ERROR, "socket[PF_INET,SOCK_DGRAM]: %s", 1673 wpa_printf(MSG_ERROR, "socket[PF_INET,SOCK_DGRAM]: %s",
1566 strerror(errno)); 1674 strerror(errno));
1567 goto fail1; 1675 goto fail1;
1568 } 1676 }
1569 1677
1570 global->route = socket(PF_ROUTE, SOCK_RAW, 0); 1678 global->route = socket(PF_ROUTE, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
1571 if (global->route < 0) { 1679 if (global->route < 0) {
1572 wpa_printf(MSG_ERROR, "socket[PF_ROUTE,SOCK_RAW]: %s", 1680 wpa_printf(MSG_ERROR, "socket[PF_ROUTE,SOCK_RAW]: %s",
1573 strerror(errno)); 1681 strerror(errno));
1574 goto fail; 1682 goto fail;
1575 } 1683 }
1576 1684
1577#ifdef RO_MSGFILTER 1685#ifdef RO_MSGFILTER
1578 if (setsockopt(global->route, PF_ROUTE, RO_MSGFILTER, 1686 if (setsockopt(global->route, PF_ROUTE, RO_MSGFILTER,
1579 &msgfilter, sizeof(msgfilter)) < 0) 1687 &msgfilter, sizeof(msgfilter)) < 0)
1580 wpa_printf(MSG_ERROR, "socket[PF_ROUTE,RO_MSGFILTER]: %s", 1688 wpa_printf(MSG_ERROR, "socket[PF_ROUTE,RO_MSGFILTER]: %s",
1581 strerror(errno)); 1689 strerror(errno));
1582#endif 1690#endif
1583 1691