📄 ctrl_iface.c
字号:
/* * WPA Supplicant / UNIX domain and UDP socket -based control interface * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */#include <stdlib.h>#include <stdio.h>#include <string.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <errno.h>#ifndef CONFIG_NATIVE_WINDOWS#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <sys/un.h>#include <sys/uio.h>#endif /* CONFIG_NATIVE_WINDOWS */#include "common.h"#include "eloop.h"#include "wpa.h"#include "wpa_supplicant.h"#include "config.h"#include "eapol_sm.h"#include "wpa_supplicant_i.h"#include "ctrl_iface.h"#include "l2_packet.h"#include "preauth.h"#include "wpa_ctrl.h"#include "eap.h"#ifdef CONFIG_CTRL_IFACE_UDP#define CTRL_IFACE_SOCK struct sockaddr_in#else /* CONFIG_CTRL_IFACE_UDP */#define CTRL_IFACE_SOCK struct sockaddr_un#endif /* CONFIG_CTRL_IFACE_UDP *//** * struct wpa_ctrl_dst - Internal data structure of control interface monitors * * This structure is used to store information about registered control * interface monitors into struct wpa_supplicant. This data is private to * ctrl_iface.c and should not be touched directly from other files. */struct wpa_ctrl_dst { struct wpa_ctrl_dst *next; CTRL_IFACE_SOCK addr; socklen_t addrlen; int debug_level; int errors;};static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s, char *cmd){ char *value; int ret = 0; value = strchr(cmd, ' '); if (value == NULL) return -1; *value++ = '\0'; wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value); if (strcasecmp(cmd, "EAPOL::heldPeriod") == 0) { eapol_sm_configure(wpa_s->eapol, atoi(value), -1, -1, -1); } else if (strcasecmp(cmd, "EAPOL::authPeriod") == 0) { eapol_sm_configure(wpa_s->eapol, -1, atoi(value), -1, -1); } else if (strcasecmp(cmd, "EAPOL::startPeriod") == 0) { eapol_sm_configure(wpa_s->eapol, -1, -1, atoi(value), -1); } else if (strcasecmp(cmd, "EAPOL::maxStart") == 0) { eapol_sm_configure(wpa_s->eapol, -1, -1, -1, atoi(value)); } else if (strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) { if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME, atoi(value))) ret = -1; } else if (strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") == 0) { if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD, atoi(value))) ret = -1; } else if (strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) { if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, atoi(value))) ret = -1; } else ret = -1; return ret;}static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s, char *addr){ u8 bssid[ETH_ALEN]; if (hwaddr_aton(addr, bssid)) { wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH: invalid address " "'%s'", addr); return -1; } wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid)); rsn_preauth_deinit(wpa_s->wpa); if (rsn_preauth_init(wpa_s->wpa, bssid, wpa_s->current_ssid)) return -1; return 0;}static int wpa_supplicant_ctrl_iface_attach(struct wpa_supplicant *wpa_s, CTRL_IFACE_SOCK *from, socklen_t fromlen){ struct wpa_ctrl_dst *dst; dst = malloc(sizeof(*dst)); if (dst == NULL) return -1; memset(dst, 0, sizeof(*dst)); memcpy(&dst->addr, from, sizeof(CTRL_IFACE_SOCK)); dst->addrlen = fromlen; dst->debug_level = MSG_INFO; dst->next = wpa_s->ctrl_dst; wpa_s->ctrl_dst = dst;#ifdef CONFIG_CTRL_IFACE_UDP wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor attached %s:%d", inet_ntoa(from->sin_addr), ntohs(from->sin_port));#else /* CONFIG_CTRL_IFACE_UDP */ wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached", (u8 *) from->sun_path, fromlen - sizeof(from->sun_family));#endif /* CONFIG_CTRL_IFACE_UDP */ return 0;}static int wpa_supplicant_ctrl_iface_detach(struct wpa_supplicant *wpa_s, CTRL_IFACE_SOCK *from, socklen_t fromlen){ struct wpa_ctrl_dst *dst, *prev = NULL; dst = wpa_s->ctrl_dst; while (dst) {#ifdef CONFIG_CTRL_IFACE_UDP if (from->sin_addr.s_addr == dst->addr.sin_addr.s_addr && from->sin_port == dst->addr.sin_port) { if (prev == NULL) wpa_s->ctrl_dst = dst->next; else prev->next = dst->next; free(dst); wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor detached " "%s:%d", inet_ntoa(from->sin_addr), ntohs(from->sin_port)); return 0; }#else /* CONFIG_CTRL_IFACE_UDP */ if (fromlen == dst->addrlen && memcmp(from->sun_path, dst->addr.sun_path, fromlen - sizeof(from->sun_family)) == 0) { if (prev == NULL) wpa_s->ctrl_dst = dst->next; else prev->next = dst->next; free(dst); wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor detached", (u8 *) from->sun_path, fromlen - sizeof(from->sun_family)); return 0; }#endif /* CONFIG_CTRL_IFACE_UDP */ prev = dst; dst = dst->next; } return -1;}static int wpa_supplicant_ctrl_iface_level(struct wpa_supplicant *wpa_s, CTRL_IFACE_SOCK *from, socklen_t fromlen, char *level){ struct wpa_ctrl_dst *dst; wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level); dst = wpa_s->ctrl_dst; while (dst) {#ifdef CONFIG_CTRL_IFACE_UDP if (from->sin_addr.s_addr == dst->addr.sin_addr.s_addr && from->sin_port == dst->addr.sin_port) { wpa_printf(MSG_DEBUG, "CTRL_IFACE changed monitor " "level %s:%d", inet_ntoa(from->sin_addr), ntohs(from->sin_port)); dst->debug_level = atoi(level); return 0; }#else /* CONFIG_CTRL_IFACE_UDP */ if (fromlen == dst->addrlen && memcmp(from->sun_path, dst->addr.sun_path, fromlen - sizeof(from->sun_family)) == 0) { wpa_hexdump(MSG_DEBUG, "CTRL_IFACE changed monitor " "level", (u8 *) from->sun_path, fromlen - sizeof(from->sun_family)); dst->debug_level = atoi(level); return 0; }#endif /* CONFIG_CTRL_IFACE_UDP */ dst = dst->next; } return -1;}static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s, char *rsp){ char *pos, *id_pos; int id; struct wpa_ssid *ssid; pos = strchr(rsp, '-'); if (pos == NULL) return -1; *pos++ = '\0'; id_pos = pos; pos = strchr(pos, ':'); if (pos == NULL) return -1; *pos++ = '\0'; id = atoi(id_pos); wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id); wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value", (u8 *) pos, strlen(pos)); ssid = wpa_config_get_network(wpa_s->conf, id); if (ssid == NULL) { wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d " "to update", id); return -1; } if (strcmp(rsp, "IDENTITY") == 0) { free(ssid->identity); ssid->identity = (u8 *) strdup(pos); ssid->identity_len = strlen(pos); ssid->pending_req_identity = 0; if (ssid == wpa_s->current_ssid) wpa_s->reassociate = 1; } else if (strcmp(rsp, "PASSWORD") == 0) { free(ssid->password); ssid->password = (u8 *) strdup(pos); ssid->password_len = strlen(pos); ssid->pending_req_password = 0; if (ssid == wpa_s->current_ssid) wpa_s->reassociate = 1; } else if (strcmp(rsp, "NEW_PASSWORD") == 0) { free(ssid->new_password); ssid->new_password = (u8 *) strdup(pos); ssid->new_password_len = strlen(pos); ssid->pending_req_new_password = 0; if (ssid == wpa_s->current_ssid) wpa_s->reassociate = 1; } else if (strcmp(rsp, "PIN") == 0) { free(ssid->pin); ssid->pin = strdup(pos); ssid->pending_req_pin = 0; if (ssid == wpa_s->current_ssid) wpa_s->reassociate = 1; } else if (strcmp(rsp, "OTP") == 0) { free(ssid->otp); ssid->otp = (u8 *) strdup(pos); ssid->otp_len = strlen(pos); free(ssid->pending_req_otp); ssid->pending_req_otp = NULL; ssid->pending_req_otp_len = 0; } else if (strcmp(rsp, "PASSPHRASE") == 0) { free(ssid->private_key_passwd); ssid->private_key_passwd = (u8 *) strdup(pos); ssid->pending_req_passphrase = 0; if (ssid == wpa_s->current_ssid) wpa_s->reassociate = 1; } else { wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", rsp); return -1; } return 0;}static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s, const char *params, char *buf, size_t buflen){ char *pos, *end, tmp[30]; int res, verbose; verbose = strcmp(params, "-VERBOSE") == 0; pos = buf; end = buf + buflen; if (wpa_s->wpa_state >= WPA_ASSOCIATED) { pos += snprintf(pos, end - pos, "bssid=" MACSTR "\n", MAC2STR(wpa_s->bssid)); if (wpa_s->current_ssid) { pos += snprintf(pos, end - pos, "ssid=%s\n", wpa_ssid_txt(wpa_s->current_ssid->ssid, wpa_s->current_ssid-> ssid_len)); } pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose); } pos += snprintf(pos, end - pos, "wpa_state=%s\n", wpa_supplicant_state_txt(wpa_s->wpa_state)); if (wpa_s->l2 && l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0) pos += snprintf(pos, end - pos, "ip_address=%s\n", tmp); if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X || wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) { res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos, verbose); if (res >= 0) pos += res; } res = rsn_preauth_get_status(wpa_s->wpa, pos, end - pos, verbose); if (res >= 0) pos += res; return pos - buf;}static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s, char *cmd){ char *pos; int id; struct wpa_ssid *ssid; u8 bssid[ETH_ALEN]; /* cmd: "<network id> <BSSID>" */ pos = strchr(cmd, ' '); if (pos == NULL) return -1; *pos++ = '\0'; id = atoi(cmd); wpa_printf(MSG_DEBUG, "CTRL_IFACE: id=%d bssid='%s'", id, pos); if (hwaddr_aton(pos, bssid)) { wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", pos); return -1; } ssid = wpa_config_get_network(wpa_s->conf, id); if (ssid == NULL) { wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d " "to update", id); return -1; } memcpy(ssid->bssid, bssid, ETH_ALEN); ssid->bssid_set = memcmp(bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) != 0; return 0;}static int wpa_supplicant_ctrl_iface_list_networks( struct wpa_supplicant *wpa_s, char *buf, size_t buflen){ char *pos, *end; struct wpa_ssid *ssid; pos = buf; end = buf + buflen; pos += snprintf(pos, end - pos, "network id / ssid / bssid / flags\n"); ssid = wpa_s->conf->ssid; while (ssid) { pos += snprintf(pos, end - pos, "%d\t%s", ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); if (ssid->bssid_set) { pos += snprintf(pos, end - pos, "\t" MACSTR, MAC2STR(ssid->bssid)); } else { pos += snprintf(pos, end - pos, "\tany"); } pos += snprintf(pos, end - pos, "\t%s%s", ssid == wpa_s->current_ssid ? "[CURRENT]" : "", ssid->disabled ? "[DISABLED]" : ""); pos += snprintf(pos, end - pos, "\n"); ssid = ssid->next; } return pos - buf;}static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher){ int first = 1; pos += snprintf(pos, end - pos, "-"); if (cipher & WPA_CIPHER_NONE) { pos += snprintf(pos, end - pos, "%sNONE", first ? "" : "+"); first = 0; } if (cipher & WPA_CIPHER_WEP40) { pos += snprintf(pos, end - pos, "%sWEP40", first ? "" : "+"); first = 0; } if (cipher & WPA_CIPHER_WEP104) { pos += snprintf(pos, end - pos, "%sWEP104", first ? "" : "+"); first = 0; } if (cipher & WPA_CIPHER_TKIP) { pos += snprintf(pos, end - pos, "%sTKIP", first ? "" : "+"); first = 0; } if (cipher & WPA_CIPHER_CCMP) { pos += snprintf(pos, end - pos, "%sCCMP", first ? "" : "+"); first = 0; } return pos;}static char * wpa_supplicant_ie_txt(struct wpa_supplicant *wpa_s, char *pos, char *end, const char *proto, const u8 *ie, size_t ie_len){ struct wpa_ie_data data; int first; pos += snprintf(pos, end - pos, "[%s-", proto); if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) { pos += snprintf(pos, end - pos, "?]"); return pos; } first = 1; if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) { pos += snprintf(pos, end - pos, "%sEAP", first ? "" : "+"); first = 0; } if (data.key_mgmt & WPA_KEY_MGMT_PSK) { pos += snprintf(pos, end - pos, "%sPSK", first ? "" : "+"); first = 0; } if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) { pos += snprintf(pos, end - pos, "%sNone", first ? "" : "+"); first = 0; } pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher); if (data.capabilities & WPA_CAPABILITY_PREAUTH) pos += snprintf(pos, end - pos, "-preauth"); pos += snprintf(pos, end - pos, "]"); return pos;}static int wpa_supplicant_ctrl_iface_scan_results( struct wpa_supplicant *wpa_s, char *buf, size_t buflen){ char *pos, *end; struct wpa_scan_result *res; int i; if (wpa_s->scan_results == NULL && wpa_supplicant_get_scan_results(wpa_s) < 0) return 0; pos = buf; end = buf + buflen; pos += snprintf(pos, end - pos, "bssid / frequency / signal level / " "flags / ssid\n"); for (i = 0; i < wpa_s->num_scan_results; i++) { res = &wpa_s->scan_results[i]; pos += snprintf(pos, end - pos, MACSTR "\t%d\t%d\t", MAC2STR(res->bssid), res->freq, res->level); if (res->wpa_ie_len) { pos = wpa_supplicant_ie_txt(wpa_s, pos, end, "WPA", res->wpa_ie, res->wpa_ie_len); } if (res->rsn_ie_len) { pos = wpa_supplicant_ie_txt(wpa_s, pos, end, "WPA2", res->rsn_ie, res->rsn_ie_len); } if (!res->wpa_ie_len && !res->rsn_ie_len && res->caps & IEEE80211_CAP_PRIVACY) pos += snprintf(pos, end - pos, "[WEP]"); if (res->caps & IEEE80211_CAP_IBSS) pos += snprintf(pos, end - pos, "[IBSS]"); pos += snprintf(pos, end - pos, "\t%s", wpa_ssid_txt(res->ssid, res->ssid_len)); pos += snprintf(pos, end - pos, "\n"); } return pos - buf;}static int wpa_supplicant_ctrl_iface_select_network( struct wpa_supplicant *wpa_s, char *cmd){ int id; struct wpa_ssid *ssid; /* cmd: "<network id>" or "any" */ if (strcmp(cmd, "any") == 0) { wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any"); ssid = wpa_s->conf->ssid; while (ssid) { ssid->disabled = 0; ssid = ssid->next; } wpa_s->reassociate = 1; wpa_supplicant_req_scan(wpa_s, 0, 0); return 0; } id = atoi(cmd); wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id); ssid = wpa_config_get_network(wpa_s->conf, id); if (ssid == NULL) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -