static void * wpa_driver_wired_init(void *ctx, const char *ifname) { struct wpa_driver_wired_data *drv; int flags; drv = os_zalloc(sizeof(*drv)); if (drv == NULL) return NULL; os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); drv->ctx = ctx; #ifdef __linux__ drv->pf_sock = socket(PF_PACKET, SOCK_DGRAM, 0); if (drv->pf_sock < 0) perror("socket(PF_PACKET)"); #else /* __linux__ */ drv->pf_sock = -1; #endif /* __linux__ */ if (wpa_driver_wired_get_ifflags(ifname, &flags) == 0 && !(flags & IFF_UP) && wpa_driver_wired_set_ifflags(ifname, flags | IFF_UP) == 0) { drv->iff_up = 1; } if (wired_multicast_membership(drv->pf_sock, if_nametoindex(drv->ifname), pae_group_addr, 1) == 0) { wpa_printf(MSG_DEBUG, "%s: Added multicast membership with " "packet socket", __func__); drv->membership = 1; } else if (wpa_driver_wired_multi(ifname, pae_group_addr, 1) == 0) { wpa_printf(MSG_DEBUG, "%s: Added multicast membership with " "SIOCADDMULTI", __func__); drv->multi = 1; } else if (wpa_driver_wired_get_ifflags(ifname, &flags) < 0) { wpa_printf(MSG_INFO, "%s: Could not get interface " "flags", __func__); os_free(drv); return NULL; } else if (flags & IFF_ALLMULTI) { wpa_printf(MSG_DEBUG, "%s: Interface is already configured " "for multicast", __func__); } else if (wpa_driver_wired_set_ifflags(ifname, flags | IFF_ALLMULTI) < 0) { wpa_printf(MSG_INFO, "%s: Failed to enable allmulti", __func__); os_free(drv); return NULL; } else { wpa_printf(MSG_DEBUG, "%s: Enabled allmulti mode", __func__); drv->iff_allmulti = 1; } return drv; }
static void wpa_driver_wired_deinit(void *priv) { struct wpa_driver_wired_data *drv = priv; int flags; if (drv->membership && wired_multicast_membership(drv->pf_sock, if_nametoindex(drv->ifname), pae_group_addr, 0) < 0) { wpa_printf(MSG_DEBUG, "%s: Failed to remove PAE multicast " "group (PACKET)", __func__); } if (drv->multi && wpa_driver_wired_multi(drv->ifname, pae_group_addr, 0) < 0) { wpa_printf(MSG_DEBUG, "%s: Failed to remove PAE multicast " "group (SIOCDELMULTI)", __func__); } if (drv->iff_allmulti && (wpa_driver_wired_get_ifflags(drv->ifname, &flags) < 0 || wpa_driver_wired_set_ifflags(drv->ifname, flags & ~IFF_ALLMULTI) < 0)) { wpa_printf(MSG_DEBUG, "%s: Failed to disable allmulti mode", __func__); } if (drv->iff_up && wpa_driver_wired_get_ifflags(drv->ifname, &flags) == 0 && (flags & IFF_UP) && wpa_driver_wired_set_ifflags(drv->ifname, flags & ~IFF_UP) < 0) { wpa_printf(MSG_DEBUG, "%s: Failed to set the interface down", __func__); } if (drv->pf_sock != -1) close(drv->pf_sock); os_free(drv); }
void driver_wired_deinit_common(struct driver_wired_common_data *common) { int flags; if (common->membership && wired_multicast_membership(common->pf_sock, if_nametoindex(common->ifname), pae_group_addr, 0) < 0) { wpa_printf(MSG_DEBUG, "%s: Failed to remove PAE multicast group (PACKET)", __func__); } if (common->multi && driver_wired_multi(common->ifname, pae_group_addr, 0) < 0) { wpa_printf(MSG_DEBUG, "%s: Failed to remove PAE multicast group (SIOCDELMULTI)", __func__); } if (common->iff_allmulti && (driver_wired_get_ifflags(common->ifname, &flags) < 0 || driver_wired_set_ifflags(common->ifname, flags & ~IFF_ALLMULTI) < 0)) { wpa_printf(MSG_DEBUG, "%s: Failed to disable allmulti mode", __func__); } if (common->iff_up && driver_wired_get_ifflags(common->ifname, &flags) == 0 && (flags & IFF_UP) && driver_wired_set_ifflags(common->ifname, flags & ~IFF_UP) < 0) { wpa_printf(MSG_DEBUG, "%s: Failed to set the interface down", __func__); } if (common->pf_sock != -1) close(common->pf_sock); }
static void * wpa_driver_wired_init(void *ctx, const char *ifname) { struct wpa_driver_wired_data *drv; int flags, status; drv = os_zalloc(sizeof(*drv)); if (drv == NULL) return NULL; os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); drv->ctx = ctx; #ifdef __linux__ drv->pf_sock = socket(PF_PACKET, SOCK_DGRAM, 0); if (drv->pf_sock < 0) wpa_printf(MSG_ERROR, "socket(PF_PACKET): %s", strerror(errno)); #else /* __linux__ */ drv->pf_sock = -1; #endif /* __linux__ */ if (wpa_driver_wired_get_ifflags(ifname, &flags) == 0 && !(flags & IFF_UP) && wpa_driver_wired_set_ifflags(ifname, flags | IFF_UP) == 0) { drv->iff_up = 1; } if (wired_multicast_membership(drv->pf_sock, if_nametoindex(drv->ifname), pae_group_addr, 1) == 0) { wpa_printf(MSG_DEBUG, "%s: Added multicast membership with " "packet socket", __func__); drv->membership = 1; } else if (wpa_driver_wired_multi(ifname, pae_group_addr, 1) == 0) { wpa_printf(MSG_DEBUG, "%s: Added multicast membership with " "SIOCADDMULTI", __func__); drv->multi = 1; } else if (wpa_driver_wired_get_ifflags(ifname, &flags) < 0) { wpa_printf(MSG_INFO, "%s: Could not get interface " "flags", __func__); os_free(drv); return NULL; } else if (flags & IFF_ALLMULTI) { wpa_printf(MSG_DEBUG, "%s: Interface is already configured " "for multicast", __func__); } else if (wpa_driver_wired_set_ifflags(ifname, flags | IFF_ALLMULTI) < 0) { wpa_printf(MSG_INFO, "%s: Failed to enable allmulti", __func__); os_free(drv); return NULL; } else { wpa_printf(MSG_DEBUG, "%s: Enabled allmulti mode", __func__); drv->iff_allmulti = 1; } #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) { int status; wpa_printf(MSG_DEBUG, "%s: waiting for link to become active", __func__); while (wpa_driver_wired_get_ifstatus(ifname, &status) == 0 && status == 0) sleep(1); } #endif /* defined(__FreeBSD__) || defined(__DragonFly__) || defined(FreeBSD_kernel__) */ return drv; }
static int wired_init_sockets(struct wpa_driver_wired_data *drv, u8 *own_addr) { #ifdef __linux__ struct ifreq ifr; struct sockaddr_ll addr; struct sockaddr_in addr2; int n = 1; drv->sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_PAE)); if (drv->sock < 0) { wpa_printf(MSG_ERROR, "socket[PF_PACKET,SOCK_RAW]: %s", strerror(errno)); return -1; } if (eloop_register_read_sock(drv->sock, handle_read, drv->ctx, NULL)) { wpa_printf(MSG_INFO, "Could not register read socket"); return -1; } os_memset(&ifr, 0, sizeof(ifr)); os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name)); if (ioctl(drv->sock, SIOCGIFINDEX, &ifr) != 0) { wpa_printf(MSG_ERROR, "ioctl(SIOCGIFINDEX): %s", strerror(errno)); return -1; } os_memset(&addr, 0, sizeof(addr)); addr.sll_family = AF_PACKET; addr.sll_ifindex = ifr.ifr_ifindex; wpa_printf(MSG_DEBUG, "Opening raw packet socket for ifindex %d", addr.sll_ifindex); if (bind(drv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { wpa_printf(MSG_ERROR, "bind: %s", strerror(errno)); return -1; } /* filter multicast address */ if (wired_multicast_membership(drv->sock, ifr.ifr_ifindex, pae_group_addr, 1) < 0) { wpa_printf(MSG_ERROR, "wired: Failed to add multicast group " "membership"); return -1; } os_memset(&ifr, 0, sizeof(ifr)); os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name)); if (ioctl(drv->sock, SIOCGIFHWADDR, &ifr) != 0) { wpa_printf(MSG_ERROR, "ioctl(SIOCGIFHWADDR): %s", strerror(errno)); return -1; } if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) { wpa_printf(MSG_INFO, "Invalid HW-addr family 0x%04x", ifr.ifr_hwaddr.sa_family); return -1; } os_memcpy(own_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN); /* setup dhcp listen socket for sta detection */ if ((drv->dhcp_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { wpa_printf(MSG_ERROR, "socket call failed for dhcp: %s", strerror(errno)); return -1; } if (eloop_register_read_sock(drv->dhcp_sock, handle_dhcp, drv->ctx, NULL)) { wpa_printf(MSG_INFO, "Could not register read socket"); return -1; } os_memset(&addr2, 0, sizeof(addr2)); addr2.sin_family = AF_INET; addr2.sin_port = htons(67); addr2.sin_addr.s_addr = INADDR_ANY; if (setsockopt(drv->dhcp_sock, SOL_SOCKET, SO_REUSEADDR, (char *) &n, sizeof(n)) == -1) { wpa_printf(MSG_ERROR, "setsockopt[SOL_SOCKET,SO_REUSEADDR]: %s", strerror(errno)); return -1; } if (setsockopt(drv->dhcp_sock, SOL_SOCKET, SO_BROADCAST, (char *) &n, sizeof(n)) == -1) { wpa_printf(MSG_ERROR, "setsockopt[SOL_SOCKET,SO_BROADCAST]: %s", strerror(errno)); return -1; } os_memset(&ifr, 0, sizeof(ifr)); os_strlcpy(ifr.ifr_ifrn.ifrn_name, drv->ifname, IFNAMSIZ); if (setsockopt(drv->dhcp_sock, SOL_SOCKET, SO_BINDTODEVICE, (char *) &ifr, sizeof(ifr)) < 0) { wpa_printf(MSG_ERROR, "setsockopt[SOL_SOCKET,SO_BINDTODEVICE]: %s", strerror(errno)); return -1; } if (bind(drv->dhcp_sock, (struct sockaddr *) &addr2, sizeof(struct sockaddr)) == -1) { wpa_printf(MSG_ERROR, "bind: %s", strerror(errno)); return -1; } return 0; #else /* __linux__ */ return -1; #endif /* __linux__ */ }
int driver_wired_init_common(struct driver_wired_common_data *common, const char *ifname, void *ctx) { int flags; os_strlcpy(common->ifname, ifname, sizeof(common->ifname)); common->ctx = ctx; #ifdef __linux__ common->pf_sock = socket(PF_PACKET, SOCK_DGRAM, 0); if (common->pf_sock < 0) wpa_printf(MSG_ERROR, "socket(PF_PACKET): %s", strerror(errno)); #else /* __linux__ */ common->pf_sock = -1; #endif /* __linux__ */ if (driver_wired_get_ifflags(ifname, &flags) == 0 && !(flags & IFF_UP) && driver_wired_set_ifflags(ifname, flags | IFF_UP) == 0) common->iff_up = 1; if (wired_multicast_membership(common->pf_sock, if_nametoindex(common->ifname), pae_group_addr, 1) == 0) { wpa_printf(MSG_DEBUG, "%s: Added multicast membership with packet socket", __func__); common->membership = 1; } else if (driver_wired_multi(ifname, pae_group_addr, 1) == 0) { wpa_printf(MSG_DEBUG, "%s: Added multicast membership with SIOCADDMULTI", __func__); common->multi = 1; } else if (driver_wired_get_ifflags(ifname, &flags) < 0) { wpa_printf(MSG_INFO, "%s: Could not get interface flags", __func__); return -1; } else if (flags & IFF_ALLMULTI) { wpa_printf(MSG_DEBUG, "%s: Interface is already configured for multicast", __func__); } else if (driver_wired_set_ifflags(ifname, flags | IFF_ALLMULTI) < 0) { wpa_printf(MSG_INFO, "%s: Failed to enable allmulti", __func__); return -1; } else { wpa_printf(MSG_DEBUG, "%s: Enabled allmulti mode", __func__); common->iff_allmulti = 1; } #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) { int status; wpa_printf(MSG_DEBUG, "%s: waiting for link to become active", __func__); while (driver_wired_get_ifstatus(ifname, &status) == 0 && status == 0) sleep(1); } #endif /* defined(__FreeBSD__) || defined(__DragonFly__) || defined(FreeBSD_kernel__) */ return 0; }