aboutsummaryrefslogtreecommitdiffstats
path: root/hostapd/ctrl_iface.c
diff options
context:
space:
mode:
Diffstat (limited to 'hostapd/ctrl_iface.c')
-rw-r--r--hostapd/ctrl_iface.c274
1 files changed, 273 insertions, 1 deletions
diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
index 7587e03..1b8bede 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -523,7 +523,8 @@ static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd,
ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n"
"ssid=%s\n",
MAC2STR(hapd->own_addr),
- hapd->conf->ssid.ssid);
+ wpa_ssid_txt(hapd->conf->ssid.ssid,
+ hapd->conf->ssid.ssid_len));
if (ret < 0 || ret >= end - pos)
return pos - buf;
pos += ret;
@@ -618,6 +619,12 @@ static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd,
return pos - buf;
pos += ret;
} else if (hapd->conf->wpa &&
+ hapd->conf->wpa_group == WPA_CIPHER_GCMP) {
+ ret = os_snprintf(pos, end - pos, "group_cipher=GCMP\n");
+ if (ret < 0 || ret >= end - pos)
+ return pos - buf;
+ pos += ret;
+ } else if (hapd->conf->wpa &&
hapd->conf->wpa_group == WPA_CIPHER_TKIP) {
ret = os_snprintf(pos, end - pos, "group_cipher=TKIP\n");
if (ret < 0 || ret >= end - pos)
@@ -637,6 +644,12 @@ static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd,
return pos - buf;
pos += ret;
}
+ if (hapd->conf->rsn_pairwise & WPA_CIPHER_GCMP) {
+ ret = os_snprintf(pos, end - pos, "GCMP ");
+ if (ret < 0 || ret >= end - pos)
+ return pos - buf;
+ pos += ret;
+ }
if (hapd->conf->rsn_pairwise & WPA_CIPHER_TKIP) {
ret = os_snprintf(pos, end - pos, "TKIP ");
if (ret < 0 || ret >= end - pos)
@@ -662,6 +675,12 @@ static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd,
return pos - buf;
pos += ret;
}
+ if (hapd->conf->wpa_pairwise & WPA_CIPHER_GCMP) {
+ ret = os_snprintf(pos, end - pos, "GCMP ");
+ if (ret < 0 || ret >= end - pos)
+ return pos - buf;
+ pos += ret;
+ }
if (hapd->conf->wpa_pairwise & WPA_CIPHER_TKIP) {
ret = os_snprintf(pos, end - pos, "TKIP ");
if (ret < 0 || ret >= end - pos)
@@ -746,6 +765,36 @@ static int hostapd_ctrl_iface_get(struct hostapd_data *hapd, char *cmd,
}
+static int hostapd_ctrl_iface_enable(struct hostapd_iface *iface)
+{
+ if (hostapd_enable_iface(iface) < 0) {
+ wpa_printf(MSG_ERROR, "Enabling of interface failed");
+ return -1;
+ }
+ return 0;
+}
+
+
+static int hostapd_ctrl_iface_reload(struct hostapd_iface *iface)
+{
+ if (hostapd_reload_iface(iface) < 0) {
+ wpa_printf(MSG_ERROR, "Reloading of interface failed");
+ return -1;
+ }
+ return 0;
+}
+
+
+static int hostapd_ctrl_iface_disable(struct hostapd_iface *iface)
+{
+ if (hostapd_disable_iface(iface) < 0) {
+ wpa_printf(MSG_ERROR, "Disabling of interface failed");
+ return -1;
+ }
+ return 0;
+}
+
+
static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
void *sock_ctx)
{
@@ -898,6 +947,15 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
} else if (os_strncmp(buf, "GET ", 4) == 0) {
reply_len = hostapd_ctrl_iface_get(hapd, buf + 4, reply,
reply_size);
+ } else if (os_strncmp(buf, "ENABLE", 6) == 0) {
+ if (hostapd_ctrl_iface_enable(hapd->iface))
+ reply_len = -1;
+ } else if (os_strncmp(buf, "RELOAD", 6) == 0) {
+ if (hostapd_ctrl_iface_reload(hapd->iface))
+ reply_len = -1;
+ } else if (os_strncmp(buf, "DISABLE", 7) == 0) {
+ if (hostapd_ctrl_iface_disable(hapd->iface))
+ reply_len = -1;
} else {
os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
reply_len = 16;
@@ -1091,6 +1149,220 @@ void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd)
}
+static int hostapd_ctrl_iface_add(struct hapd_interfaces *interfaces,
+ char *buf)
+{
+ if (hostapd_add_iface(interfaces, buf) < 0) {
+ wpa_printf(MSG_ERROR, "Adding interface %s failed", buf);
+ return -1;
+ }
+ return 0;
+}
+
+
+static int hostapd_ctrl_iface_remove(struct hapd_interfaces *interfaces,
+ char *buf)
+{
+ if (hostapd_remove_iface(interfaces, buf) < 0) {
+ wpa_printf(MSG_ERROR, "Removing interface %s failed", buf);
+ return -1;
+ }
+ return 0;
+}
+
+
+static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx,
+ void *sock_ctx)
+{
+ void *interfaces = eloop_ctx;
+ char buf[256];
+ int res;
+ struct sockaddr_un from;
+ socklen_t fromlen = sizeof(from);
+ char reply[24];
+ int reply_len;
+
+ res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
+ (struct sockaddr *) &from, &fromlen);
+ if (res < 0) {
+ perror("recvfrom(ctrl_iface)");
+ return;
+ }
+ buf[res] = '\0';
+
+ os_memcpy(reply, "OK\n", 3);
+ reply_len = 3;
+
+ if (os_strcmp(buf, "PING") == 0) {
+ os_memcpy(reply, "PONG\n", 5);
+ reply_len = 5;
+ } else if (os_strncmp(buf, "ADD ", 4) == 0) {
+ if (hostapd_ctrl_iface_add(interfaces, buf + 4) < 0)
+ reply_len = -1;
+ } else if (os_strncmp(buf, "REMOVE ", 7) == 0) {
+ if (hostapd_ctrl_iface_remove(interfaces, buf + 7) < 0)
+ reply_len = -1;
+ } else {
+ wpa_printf(MSG_DEBUG, "Unrecognized global ctrl_iface command "
+ "ignored");
+ reply_len = -1;
+ }
+
+ if (reply_len < 0) {
+ os_memcpy(reply, "FAIL\n", 5);
+ reply_len = 5;
+ }
+
+ sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen);
+}
+
+
+static char * hostapd_global_ctrl_iface_path(struct hapd_interfaces *interface)
+{
+ char *buf;
+ size_t len;
+
+ if (interface->global_iface_path == NULL)
+ return NULL;
+
+ len = os_strlen(interface->global_iface_path) +
+ os_strlen(interface->global_iface_name) + 2;
+ buf = os_malloc(len);
+ if (buf == NULL)
+ return NULL;
+
+ os_snprintf(buf, len, "%s/%s", interface->global_iface_path,
+ interface->global_iface_name);
+ buf[len - 1] = '\0';
+ return buf;
+}
+
+
+int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface)
+{
+ struct sockaddr_un addr;
+ int s = -1;
+ char *fname = NULL;
+
+ if (interface->global_iface_path == NULL) {
+ wpa_printf(MSG_DEBUG, "ctrl_iface not configured!");
+ return 0;
+ }
+
+ if (mkdir(interface->global_iface_path, S_IRWXU | S_IRWXG) < 0) {
+ if (errno == EEXIST) {
+ wpa_printf(MSG_DEBUG, "Using existing control "
+ "interface directory.");
+ } else {
+ perror("mkdir[ctrl_interface]");
+ goto fail;
+ }
+ }
+
+ if (os_strlen(interface->global_iface_path) + 1 +
+ os_strlen(interface->global_iface_name) >= sizeof(addr.sun_path))
+ goto fail;
+
+ s = socket(PF_UNIX, SOCK_DGRAM, 0);
+ if (s < 0) {
+ perror("socket(PF_UNIX)");
+ goto fail;
+ }
+
+ os_memset(&addr, 0, sizeof(addr));
+#ifdef __FreeBSD__
+ addr.sun_len = sizeof(addr);
+#endif /* __FreeBSD__ */
+ addr.sun_family = AF_UNIX;
+ fname = hostapd_global_ctrl_iface_path(interface);
+ if (fname == NULL)
+ goto fail;
+ os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
+ if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+ wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
+ strerror(errno));
+ if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+ wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
+ " allow connections - assuming it was left"
+ "over from forced program termination");
+ if (unlink(fname) < 0) {
+ perror("unlink[ctrl_iface]");
+ wpa_printf(MSG_ERROR, "Could not unlink "
+ "existing ctrl_iface socket '%s'",
+ fname);
+ goto fail;
+ }
+ if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
+ 0) {
+ perror("bind(PF_UNIX)");
+ goto fail;
+ }
+ wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
+ "ctrl_iface socket '%s'", fname);
+ } else {
+ wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
+ "be in use - cannot override it");
+ wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
+ "not used anymore", fname);
+ os_free(fname);
+ fname = NULL;
+ goto fail;
+ }
+ }
+
+ if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
+ perror("chmod[ctrl_interface/ifname]");
+ goto fail;
+ }
+ os_free(fname);
+
+ interface->global_ctrl_sock = s;
+ eloop_register_read_sock(s, hostapd_global_ctrl_iface_receive,
+ interface, NULL);
+
+ return 0;
+
+fail:
+ if (s >= 0)
+ close(s);
+ if (fname) {
+ unlink(fname);
+ os_free(fname);
+ }
+ return -1;
+}
+
+
+void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interfaces)
+{
+ char *fname = NULL;
+
+ if (interfaces->global_ctrl_sock > -1) {
+ eloop_unregister_read_sock(interfaces->global_ctrl_sock);
+ close(interfaces->global_ctrl_sock);
+ interfaces->global_ctrl_sock = -1;
+ fname = hostapd_global_ctrl_iface_path(interfaces);
+ if (fname) {
+ unlink(fname);
+ os_free(fname);
+ }
+
+ if (interfaces->global_iface_path &&
+ rmdir(interfaces->global_iface_path) < 0) {
+ if (errno == ENOTEMPTY) {
+ wpa_printf(MSG_DEBUG, "Control interface "
+ "directory not empty - leaving it "
+ "behind");
+ } else {
+ perror("rmdir[ctrl_interface]");
+ }
+ }
+ os_free(interfaces->global_iface_path);
+ interfaces->global_iface_path = NULL;
+ }
+}
+
+
static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
const char *buf, size_t len)
{