From ba5931c7b2f418fd3538abb8950b09fd9fb1558c Mon Sep 17 00:00:00 2001 From: Vijaya Kumar Abbaraju Date: Mon, 8 Apr 2024 03:15:16 -0700 Subject: [PATCH] Changes in Hostapd to Support PAC --- src/ap/ap_drv_ops.h | 11 ++++ src/ap/hostapd.c | 47 ++++++++++++++++- src/ap/sta_info.h | 6 +++ src/drivers/driver.h | 12 +++++ src/drivers/driver_wired.c | 102 +++++++++++++++++++++++++++++++++---- src/drivers/drivers.mak | 4 ++ src/utils/json.c | 42 +++++++++++++++ src/utils/json.h | 5 +- 8 files changed, 218 insertions(+), 11 deletions(-) diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h index 5738c1c97..cd23965c6 100644 --- a/src/ap/ap_drv_ops.h +++ b/src/ap/ap_drv_ops.h @@ -391,4 +391,15 @@ hostapd_drv_set_band(struct hostapd_data *hapd, enum set_band band) return hapd->driver->set_band(hapd->drv_priv, band); } +#ifdef CONFIG_SONIC_HOSTAPD +static inline int +hostapd_drv_auth_resp_send(struct hostapd_data *hapd, char *intf, u8 *addr, + char *status, void *param) +{ + if (!hapd->driver || !hapd->driver->auth_resp_send) + return -1; + return hapd->driver->auth_resp_send(intf, addr, status, param); +} +#endif + #endif /* AP_DRV_OPS */ diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c index b37f49f9a..5f101c400 100644 --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c @@ -176,8 +176,10 @@ static void hostapd_clear_old(struct hostapd_iface *iface) * allow them to use the BSS anymore. */ for (j = 0; j < iface->num_bss; j++) { +#ifndef CONFIG_SONIC_HOSTAPD hostapd_flush_old_stations(iface->bss[j], WLAN_REASON_PREV_AUTH_NOT_VALID); +#endif #ifdef CONFIG_WEP hostapd_broadcast_wep_clear(iface->bss[j]); #endif /* CONFIG_WEP */ @@ -186,6 +188,11 @@ static void hostapd_clear_old(struct hostapd_iface *iface) /* TODO: update dynamic data based on changed configuration * items (e.g., open/close sockets, etc.) */ radius_client_flush(iface->bss[j]->radius, 0); +#ifdef CONFIG_SONIC_HOSTAPD + radius_close_auth_sockets(iface->bss[j]->radius); + radius_close_acct_sockets(iface->bss[j]->radius); +#endif + #endif /* CONFIG_NO_RADIUS */ } } @@ -2163,6 +2170,17 @@ static int hostapd_setup_interface_complete_sync(struct hostapd_iface *iface, for (j = 0; j < iface->num_bss; j++) hostapd_neighbor_set_own_report(iface->bss[j]); + +#ifdef CONFIG_SONIC_HOSTAPD +#ifdef HOSTAPD + if (hapd->driver->auth_resp_send) + { + wpa_printf(MSG_DEBUG, "%s: Informing PAC - method_change - enable.", + iface->bss[0]->conf->iface); + hapd->driver->auth_resp_send(hapd->conf->iface, NULL, "method_change", (void *)"enable"); + } +#endif +#endif return 0; @@ -2213,6 +2231,18 @@ int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err) if (err) { wpa_printf(MSG_ERROR, "Interface initialization failed"); + +#ifdef CONFIG_SONIC_HOSTAPD +#ifdef HOSTAPD + if (hapd->driver->auth_resp_send) + { + wpa_printf(MSG_DEBUG, "%s: Error occured. Informing PAC - method_change - disable.", + iface->bss[0]->conf->iface); + hapd->driver->auth_resp_send(iface->bss[0]->conf->iface, NULL, "method_change", (void *)"disable"); + } +#endif +#endif + hostapd_set_state(iface, HAPD_IFACE_DISABLED); iface->need_to_start_in_sync = 0; wpa_msg(hapd->msg_ctx, MSG_INFO, AP_EVENT_DISABLED); @@ -2651,8 +2681,11 @@ void hostapd_interface_deinit_free(struct hostapd_iface *iface) hostapd_interface_free(iface); } - +#ifdef CONFIG_SONIC_HOSTAPD +void hostapd_deinit_driver(const struct wpa_driver_ops *driver, +#else static void hostapd_deinit_driver(const struct wpa_driver_ops *driver, +#endif void *drv_priv, struct hostapd_iface *hapd_iface) { @@ -2777,6 +2810,18 @@ int hostapd_disable_iface(struct hostapd_iface *hapd_iface) wpa_printf(MSG_DEBUG, "Interface %s disabled", hapd_iface->bss[0]->conf->iface); + +#ifdef CONFIG_SONIC_HOSTAPD +#ifdef HOSTAPD + if (driver->auth_resp_send) + { + wpa_printf(MSG_DEBUG, "%s: Informing PAC - method_change - disable.", + hapd_iface->bss[0]->conf->iface); + driver->auth_resp_send(hapd_iface->bss[0]->conf->iface, NULL, "method_change", (void *)"disable"); + } +#endif +#endif + hostapd_set_state(hapd_iface, HAPD_IFACE_DISABLED); return 0; } diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h index ef485618a..3af977772 100644 --- a/src/ap/sta_info.h +++ b/src/ap/sta_info.h @@ -14,6 +14,9 @@ #include "vlan.h" #include "common/wpa_common.h" #include "common/ieee802_11_defs.h" +#ifdef CONFIG_SONIC_RADIUS +#include "radius/radius_attr_parse.h" +#endif /* STA flags */ #define WLAN_STA_AUTH BIT(0) @@ -286,6 +289,9 @@ struct sta_info { unsigned int airtime_weight; struct os_reltime backlogged_until; #endif /* CONFIG_AIRTIME_POLICY */ +#ifdef CONFIG_SONIC_RADIUS + attrInfo_t attr_info; +#endif }; diff --git a/src/drivers/driver.h b/src/drivers/driver.h index bb890994a..43289a22c 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -4464,6 +4464,18 @@ struct wpa_driver_ops { * explicitly allow reception of broadcast Public Action frames. */ int (*dpp_listen)(void *priv, bool enable); + +#ifdef CONFIG_SONIC_HOSTAPD +/** + * auth_resp_send - send status to PAC + * @intf: interface + * @addr: station mac address + * @status: reply status + * @param: status parameters + * Returns: 0 on success, -1 on failure + * */ + int (*auth_resp_send)(char *intf, u8 *addr, char *status, void *param); +#endif }; /** diff --git a/src/drivers/driver_wired.c b/src/drivers/driver_wired.c index c7537b7c3..af972aa32 100644 --- a/src/drivers/driver_wired.c +++ b/src/drivers/driver_wired.c @@ -13,6 +13,13 @@ #include "eloop.h" #include "driver.h" #include "driver_wired_common.h" +#include "common/eapol_common.h" +#ifdef CONFIG_SONIC_HOSTAPD +#ifdef HOSTAPD +#include "ap/hostapd.h" +#include "ap/sta_info.h" +#endif +#endif #include #undef IFNAMSIZ @@ -33,21 +40,28 @@ #pragma pack(push, 1) #endif /* _MSC_VER */ +#if 0 struct ieee8023_hdr { u8 dest[6]; u8 src[6]; u16 ethertype; } STRUCT_PACKED; +#endif #ifdef _MSC_VER #pragma pack(pop) #endif /* _MSC_VER */ +#ifdef HOSTAPD +extern int wired_driver_auth_resp_send(char *intf, u8 *addr, char *status, void *param); +#endif struct wpa_driver_wired_data { struct driver_wired_common_data common; +#ifndef CONFIG_SONIC_HOSTAPD int dhcp_sock; /* socket for dhcp packets */ +#endif int use_pae_group_addr; }; @@ -84,6 +98,9 @@ static void handle_data(void *ctx, unsigned char *buf, size_t len) u8 *pos, *sa; size_t left; union wpa_event_data event; + struct sta_info *sta = NULL; + struct hostapd_data *hapd = ctx; + struct ieee802_1x_hdr *hdr_802_1x = NULL; /* must contain at least ieee8023_hdr 6 byte source, 6 byte dest, * 2 byte ethertype */ @@ -98,6 +115,51 @@ static void handle_data(void *ctx, unsigned char *buf, size_t len) switch (ntohs(hdr->ethertype)) { case ETH_P_PAE: wpa_printf(MSG_MSGDUMP, "Received EAPOL packet"); + + if (hapd->driver->auth_resp_send) + { + hostapd_logger(hapd, hdr->src, HOSTAPD_MODULE_IEEE8021X, + HOSTAPD_LEVEL_DEBUG, + "Received EAPOL packet. Get the associated station"); + + sta = ap_get_sta(hapd, hdr->src); + + pos = (u8 *) (hdr + 1); + hdr_802_1x = (struct ieee802_1x_hdr *)pos; + + if (!sta){ + if (IEEE802_1X_TYPE_EAPOL_START == hdr_802_1x->type) { + + /* Inform PAC */ + hostapd_logger(hapd, hdr->src, HOSTAPD_MODULE_IEEE8021X, + HOSTAPD_LEVEL_DEBUG, + "Received EAPOL START packet. Informing PAC"); + hapd->driver->auth_resp_send(hapd->conf->iface, hdr->src, "new_client", NULL); + } + else if (IEEE802_1X_TYPE_EAPOL_LOGOFF == hdr_802_1x->type) + { + /* Inform PAC */ + hostapd_logger(hapd, hdr->src, HOSTAPD_MODULE_IEEE8021X, + HOSTAPD_LEVEL_DEBUG, + "Received EAPOL LOGOFF packet. Informing PAC"); + + hapd->driver->auth_resp_send(hapd->conf->iface, hdr->src, "client_disconnected", NULL); + } + return; + } + + /* check if the client is getting de-authenticated. + if yes, then ignore any triggers during this state */ + + if (sta->flags & WLAN_STA_PENDING_DEAUTH_CB) + { + hostapd_logger(hapd, hdr->src, HOSTAPD_MODULE_IEEE8021X, + HOSTAPD_LEVEL_DEBUG, + "Received EAPOL packet of type %d while client is getting de-authenticated. Ignoring EAPOL packet", hdr_802_1x->type); + return; + } + } + sa = hdr->src; os_memset(&event, 0, sizeof(event)); event.new_sta.addr = sa; @@ -131,7 +193,7 @@ static void handle_read(int sock, void *eloop_ctx, void *sock_ctx) handle_data(eloop_ctx, buf, len); } - +#ifndef CONFIG_SONIC_HOSTAPD static void handle_dhcp(int sock, void *eloop_ctx, void *sock_ctx) { int len; @@ -162,6 +224,7 @@ static void handle_dhcp(int sock, void *eloop_ctx, void *sock_ctx) event.new_sta.addr = mac_address; wpa_supplicant_event(eloop_ctx, EVENT_NEW_STA, &event); } +#endif #endif /* __linux__ */ @@ -170,8 +233,15 @@ static int wired_init_sockets(struct wpa_driver_wired_data *drv, u8 *own_addr) #ifdef __linux__ struct ifreq ifr; struct sockaddr_ll addr; + +#ifndef CONFIG_SONIC_HOSTAPD struct sockaddr_in addr2; int n = 1; +#endif + +#define SOCK_RCV_BUF_LEN (1024 * 1024) + + int recv_buf_len = SOCK_RCV_BUF_LEN; drv->common.sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_PAE)); if (drv->common.sock < 0) { @@ -180,12 +250,21 @@ static int wired_init_sockets(struct wpa_driver_wired_data *drv, u8 *own_addr) return -1; } + if (setsockopt(drv->common.sock, SOL_SOCKET, SO_RCVBUF, &recv_buf_len, sizeof(recv_buf_len)) == -1) + { + wpa_printf(MSG_INFO, "Could not set the read socket buffer size"); + close(drv->common.sock); + return -1; + } + if (eloop_register_read_sock(drv->common.sock, handle_read, drv->common.ctx, NULL)) { wpa_printf(MSG_INFO, "Could not register read socket"); return -1; } + wpa_printf(MSG_DEBUG, "Getting the ifindex for interface %s", + drv->common.ifname); os_memset(&ifr, 0, sizeof(ifr)); os_strlcpy(ifr.ifr_name, drv->common.ifname, sizeof(ifr.ifr_name)); if (ioctl(drv->common.sock, SIOCGIFINDEX, &ifr) != 0) { @@ -229,6 +308,7 @@ static int wired_init_sockets(struct wpa_driver_wired_data *drv, u8 *own_addr) } os_memcpy(own_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN); +#ifndef CONFIG_SONIC_HOSTAPD /* 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", @@ -275,7 +355,7 @@ static int wired_init_sockets(struct wpa_driver_wired_data *drv, u8 *own_addr) wpa_printf(MSG_ERROR, "bind: %s", strerror(errno)); return -1; } - +#endif return 0; #else /* __linux__ */ return -1; @@ -322,7 +402,6 @@ static int wired_send_eapol(void *priv, const u8 *addr, return res; } - static void * wired_driver_hapd_init(struct hostapd_data *hapd, struct wpa_init_params *params) { @@ -338,17 +417,19 @@ static void * wired_driver_hapd_init(struct hostapd_data *hapd, drv->common.ctx = hapd; os_strlcpy(drv->common.ifname, params->ifname, sizeof(drv->common.ifname)); + wpa_printf(MSG_INFO, + "drv->common.ifname received is %s", drv->common.ifname); + drv->use_pae_group_addr = params->use_pae_group_addr; if (wired_init_sockets(drv, params->own_addr)) { os_free(drv); return NULL; } - + return drv; } - static void wired_driver_hapd_deinit(void *priv) { struct wpa_driver_wired_data *drv = priv; @@ -357,12 +438,13 @@ static void wired_driver_hapd_deinit(void *priv) eloop_unregister_read_sock(drv->common.sock); close(drv->common.sock); } - +#ifndef CONFIG_SONIC_HOSTAPD if (drv->dhcp_sock >= 0) { eloop_unregister_read_sock(drv->dhcp_sock); close(drv->dhcp_sock); } - +#endif + os_free(drv); } @@ -392,7 +474,6 @@ static void wpa_driver_wired_deinit(void *priv) os_free(drv); } - const struct wpa_driver_ops wpa_driver_wired_ops = { .name = "wired", .desc = "Wired Ethernet driver", @@ -402,6 +483,9 @@ const struct wpa_driver_ops wpa_driver_wired_ops = { .get_ssid = driver_wired_get_ssid, .get_bssid = driver_wired_get_bssid, .get_capa = driver_wired_get_capa, - .init = wpa_driver_wired_init, +#ifdef HOSTAPD + .auth_resp_send = wired_driver_auth_resp_send, +#endif + .init = wpa_driver_wired_init, .deinit = wpa_driver_wired_deinit, }; diff --git a/src/drivers/drivers.mak b/src/drivers/drivers.mak index 5ed624eda..42061dfb2 100644 --- a/src/drivers/drivers.mak +++ b/src/drivers/drivers.mak @@ -18,6 +18,10 @@ DRV_OBJS += ../src/drivers/driver_wired.o NEED_DRV_WIRED_COMMON=1 endif +ifdef CONFIG_SONIC_HOSTAPD +DRV_OBJS += ../src/drivers/driver_wired_sonic.o +endif + ifdef CONFIG_DRIVER_MACSEC_SONIC DRV_CFLAGS += -DCONFIG_DRIVER_MACSEC_SONIC DRV_OBJS += ../src/drivers/driver_macsec_sonic.o diff --git a/src/utils/json.c b/src/utils/json.c index dd12f1b6e..6e3e08a29 100644 --- a/src/utils/json.c +++ b/src/utils/json.c @@ -688,3 +688,45 @@ void json_value_sep(struct wpabuf *json) { wpabuf_put_u8(json, ','); } + +#ifdef CONFIG_SONIC_HOSTAPD +int json_get_array_size(struct json_token *array) +{ + struct json_token *child = NULL; + int size = 0; + + if (array == NULL) + { + return 0; + } + + child = array->child; + + while(child != NULL) + { + size++; + child = child->sibling; + } + + return (int)size; +} + +struct json_token* json_get_array_item(struct json_token *array, int index) +{ + struct json_token *current_child = NULL; + + if ((array == NULL) || (index < 0)) + { + return NULL; + } + + current_child = array->child; + while ((current_child != NULL) && (index > 0)) + { + index--; + current_child = current_child->sibling; + } + + return current_child; +} +#endif diff --git a/src/utils/json.h b/src/utils/json.h index 8448bb0c5..684f7ce30 100644 --- a/src/utils/json.h +++ b/src/utils/json.h @@ -53,5 +53,8 @@ void json_end_object(struct wpabuf *json); void json_start_array(struct wpabuf *json, const char *name); void json_end_array(struct wpabuf *json); void json_value_sep(struct wpabuf *json); - +#ifdef CONFIG_SONIC_HOSTAPD +int json_get_array_size(struct json_token *array); +struct json_token* json_get_array_item(struct json_token *array, int index); +#endif #endif /* JSON_H */