18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WPA Supplicant / UNIX domain socket -based control interface
38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
58d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This program is free software; you can redistribute it and/or modify
68d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * it under the terms of the GNU General Public License version 2 as
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * published by the Free Software Foundation.
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * license.
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * See README and COPYING for more details.
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h"
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <sys/un.h>
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <sys/stat.h>
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <grp.h>
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <stddef.h>
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef ANDROID
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <cutils/sockets.h>
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* ANDROID */
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/common.h"
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/eloop.h"
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/list.h"
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eapol_supp/eapol_supp_sm.h"
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "config.h"
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa_supplicant_i.h"
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ctrl_iface.h"
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Per-interface ctrl_iface */
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * struct wpa_ctrl_dst - Internal data structure of control interface monitors
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This structure is used to store information about registered control
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * interface monitors into struct wpa_supplicant. This data is private to
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * ctrl_iface_unix.c and should not be touched directly from other files.
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_ctrl_dst {
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct dl_list list;
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct sockaddr_un addr;
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	socklen_t addrlen;
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int debug_level;
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int errors;
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct ctrl_iface_priv {
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s;
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int sock;
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct dl_list ctrl_dst;
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_ctrl_iface_send(struct ctrl_iface_priv *priv,
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   int level, const char *buf,
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   size_t len);
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_ctrl_iface_attach(struct ctrl_iface_priv *priv,
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    struct sockaddr_un *from,
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    socklen_t fromlen)
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_ctrl_dst *dst;
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dst = os_zalloc(sizeof(*dst));
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dst == NULL)
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(&dst->addr, from, sizeof(struct sockaddr_un));
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dst->addrlen = fromlen;
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dst->debug_level = MSG_INFO;
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_add(&priv->ctrl_dst, &dst->list);
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached",
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    (u8 *) from->sun_path,
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    fromlen - offsetof(struct sockaddr_un, sun_path));
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_ctrl_iface_detach(struct ctrl_iface_priv *priv,
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    struct sockaddr_un *from,
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    socklen_t fromlen)
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_ctrl_dst *dst;
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(dst, &priv->ctrl_dst, struct wpa_ctrl_dst, list) {
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (fromlen == dst->addrlen &&
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    os_memcmp(from->sun_path, dst->addr.sun_path,
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      fromlen - offsetof(struct sockaddr_un, sun_path))
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    == 0) {
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dl_list_del(&dst->list);
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(dst);
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor detached",
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    (u8 *) from->sun_path,
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    fromlen -
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    offsetof(struct sockaddr_un, sun_path));
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return 0;
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_ctrl_iface_level(struct ctrl_iface_priv *priv,
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   struct sockaddr_un *from,
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   socklen_t fromlen,
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   char *level)
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_ctrl_dst *dst;
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level);
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(dst, &priv->ctrl_dst, struct wpa_ctrl_dst, list) {
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (fromlen == dst->addrlen &&
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    os_memcmp(from->sun_path, dst->addr.sun_path,
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      fromlen - offsetof(struct sockaddr_un, sun_path))
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    == 0) {
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_hexdump(MSG_DEBUG, "CTRL_IFACE changed monitor "
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    "level", (u8 *) from->sun_path,
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    fromlen -
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    offsetof(struct sockaddr_un, sun_path));
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dst->debug_level = atoi(level);
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return 0;
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx,
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      void *sock_ctx)
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s = eloop_ctx;
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct ctrl_iface_priv *priv = sock_ctx;
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char buf[4096];
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct sockaddr_un from;
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	socklen_t fromlen = sizeof(from);
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *reply = NULL;
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t reply_len = 0;
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int new_attached = 0;
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       (struct sockaddr *) &from, &fromlen);
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0) {
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		perror("recvfrom(ctrl_iface)");
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf[res] = '\0';
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_strcmp(buf, "ATTACH") == 0) {
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_supplicant_ctrl_iface_attach(priv, &from, fromlen))
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			reply_len = 1;
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else {
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			new_attached = 1;
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			reply_len = 2;
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (os_strcmp(buf, "DETACH") == 0) {
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_supplicant_ctrl_iface_detach(priv, &from, fromlen))
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			reply_len = 1;
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			reply_len = 2;
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (os_strncmp(buf, "LEVEL ", 6) == 0) {
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_supplicant_ctrl_iface_level(priv, &from, fromlen,
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						    buf + 6))
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			reply_len = 1;
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			reply_len = 2;
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		reply = wpa_supplicant_ctrl_iface_process(wpa_s, buf,
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt							  &reply_len);
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (reply) {
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       fromlen);
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(reply);
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (reply_len == 1) {
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       fromlen);
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (reply_len == 2) {
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sendto(sock, "OK\n", 3, 0, (struct sockaddr *) &from,
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       fromlen);
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (new_attached)
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eapol_sm_notify_ctrl_attached(wpa_s->eapol);
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic char * wpa_supplicant_ctrl_iface_path(struct wpa_supplicant *wpa_s)
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *buf;
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len;
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *pbuf, *dir = NULL, *gid_str = NULL;
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->conf->ctrl_interface == NULL)
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pbuf = os_strdup(wpa_s->conf->ctrl_interface);
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pbuf == NULL)
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_strncmp(pbuf, "DIR=", 4) == 0) {
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dir = pbuf + 4;
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		gid_str = os_strstr(dir, " GROUP=");
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (gid_str) {
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			*gid_str = '\0';
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			gid_str += 7;
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dir = pbuf;
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = os_strlen(dir) + os_strlen(wpa_s->ifname) + 2;
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = os_malloc(len);
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL) {
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(pbuf);
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = os_snprintf(buf, len, "%s/%s", dir, wpa_s->ifname);
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0 || (size_t) res >= len) {
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(pbuf);
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(buf);
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef __CYGWIN__
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Windows/WinPcap uses interface names that are not suitable
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * as a file name - convert invalid chars to underscores */
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		char *pos = buf;
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (*pos) {
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (*pos == '\\')
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				*pos = '_';
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos++;
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* __CYGWIN__ */
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(pbuf);
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return buf;
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_ctrl_iface_msg_cb(void *ctx, int level,
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     const char *txt, size_t len)
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s == NULL || wpa_s->ctrl_iface == NULL)
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_supplicant_ctrl_iface_send(wpa_s->ctrl_iface, level, txt, len);
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct ctrl_iface_priv *
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s)
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct ctrl_iface_priv *priv;
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct sockaddr_un addr;
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *fname = NULL;
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gid_t gid = 0;
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int gid_set = 0;
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *buf, *dir = NULL, *gid_str = NULL;
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct group *grp;
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *endp;
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	priv = os_zalloc(sizeof(*priv));
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (priv == NULL)
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_init(&priv->ctrl_dst);
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	priv->wpa_s = wpa_s;
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	priv->sock = -1;
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->conf->ctrl_interface == NULL)
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return priv;
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = os_strdup(wpa_s->conf->ctrl_interface);
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef ANDROID
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_snprintf(addr.sun_path, sizeof(addr.sun_path), "wpa_%s",
2840dc7a27a4d3b8328028ced3a71bd331e77981166Irfan Sheriff		    wpa_s->ifname);
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	priv->sock = android_get_control_socket(addr.sun_path);
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (priv->sock >= 0)
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto havesock;
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* ANDROID */
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_strncmp(buf, "DIR=", 4) == 0) {
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dir = buf + 4;
2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		gid_str = os_strstr(dir, " GROUP=");
2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (gid_str) {
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			*gid_str = '\0';
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			gid_str += 7;
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dir = buf;
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		gid_str = wpa_s->conf->ctrl_interface_group;
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (mkdir(dir, S_IRWXU | S_IRWXG) < 0) {
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (errno == EEXIST) {
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "Using existing control "
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "interface directory.");
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			perror("mkdir[ctrl_interface]");
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto fail;
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (gid_str) {
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		grp = getgrnam(gid_str);
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (grp) {
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			gid = grp->gr_gid;
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			gid_set = 1;
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d"
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   " (from group name '%s')",
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   (int) gid, gid_str);
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/* Group name not found - try to parse this as gid */
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			gid = strtol(gid_str, &endp, 10);
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (*gid_str == '\0' || *endp != '\0') {
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_ERROR, "CTRL: Invalid group "
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "'%s'", gid_str);
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				goto fail;
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			gid_set = 1;
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d",
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   (int) gid);
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (gid_set && chown(dir, -1, gid) < 0) {
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		perror("chown[ctrl_interface]");
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Make sure the group can enter and read the directory */
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (gid_set &&
3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    chmod(dir, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP) < 0) {
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "CTRL: chmod[ctrl_interface]: %s",
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   strerror(errno));
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_strlen(dir) + 1 + os_strlen(wpa_s->ifname) >=
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    sizeof(addr.sun_path)) {
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "ctrl_iface path limit exceeded");
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	priv->sock = socket(PF_UNIX, SOCK_DGRAM, 0);
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (priv->sock < 0) {
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		perror("socket(PF_UNIX)");
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&addr, 0, sizeof(addr));
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	addr.sun_len = sizeof(addr);
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* __FreeBSD__ */
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	addr.sun_family = AF_UNIX;
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	fname = wpa_supplicant_ctrl_iface_path(wpa_s);
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (fname == NULL)
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   strerror(errno));
3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (connect(priv->sock, (struct sockaddr *) &addr,
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    sizeof(addr)) < 0) {
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   " allow connections - assuming it was left"
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "over from forced program termination");
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (unlink(fname) < 0) {
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				perror("unlink[ctrl_iface]");
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_ERROR, "Could not unlink "
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "existing ctrl_iface socket '%s'",
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   fname);
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				goto fail;
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (bind(priv->sock, (struct sockaddr *) &addr,
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 sizeof(addr)) < 0) {
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				perror("bind(PF_UNIX)");
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				goto fail;
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "ctrl_iface socket '%s'", fname);
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "be in use - cannot override it");
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "not used anymore", fname);
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(fname);
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			fname = NULL;
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto fail;
3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (gid_set && chown(fname, -1, gid) < 0) {
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		perror("chown[ctrl_interface/ifname]");
4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		perror("chmod[ctrl_interface/ifname]");
4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(fname);
4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef ANDROID
4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidthavesock:
4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* ANDROID */
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_read_sock(priv->sock, wpa_supplicant_ctrl_iface_receive,
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 wpa_s, priv);
4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg_register_cb(wpa_supplicant_ctrl_iface_msg_cb);
4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(buf);
4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return priv;
4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfail:
4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (priv->sock >= 0)
4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		close(priv->sock);
4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(priv);
4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (fname) {
4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		unlink(fname);
4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(fname);
4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(buf);
4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv)
4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_ctrl_dst *dst, *prev;
4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (priv->sock > -1) {
4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		char *fname;
4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		char *buf, *dir = NULL, *gid_str = NULL;
4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_unregister_read_sock(priv->sock);
4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!dl_list_empty(&priv->ctrl_dst)) {
4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/*
4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * Wait a second before closing the control socket if
4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * there are any attached monitors in order to allow
4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * them to receive any pending messages.
4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 */
4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "CTRL_IFACE wait for attached "
4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "monitors to receive messages");
4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_sleep(1, 0);
4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		close(priv->sock);
4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		priv->sock = -1;
4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		fname = wpa_supplicant_ctrl_iface_path(priv->wpa_s);
4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (fname) {
4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			unlink(fname);
4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(fname);
4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		buf = os_strdup(priv->wpa_s->conf->ctrl_interface);
4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (buf == NULL)
4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto free_dst;
4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_strncmp(buf, "DIR=", 4) == 0) {
4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dir = buf + 4;
4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			gid_str = os_strstr(dir, " GROUP=");
4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (gid_str) {
4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				*gid_str = '\0';
4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				gid_str += 7;
4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else
4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dir = buf;
4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (rmdir(dir) < 0) {
4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (errno == ENOTEMPTY) {
4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_DEBUG, "Control interface "
4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "directory not empty - leaving it "
4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "behind");
4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			} else {
4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				perror("rmdir[ctrl_interface]");
4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(buf);
4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfree_dst:
4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each_safe(dst, prev, &priv->ctrl_dst, struct wpa_ctrl_dst,
4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      list)
4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(dst);
4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(priv);
4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_supplicant_ctrl_iface_send - Send a control interface packet to monitors
4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @priv: Pointer to private data from wpa_supplicant_ctrl_iface_init()
4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @level: Priority level of the message
4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buf: Message data
4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: Message length
4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Send a packet to all monitor programs attached to the control interface.
5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_ctrl_iface_send(struct ctrl_iface_priv *priv,
5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   int level, const char *buf,
5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   size_t len)
5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_ctrl_dst *dst, *next;
5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char levelstr[10];
5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int idx, res;
5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct msghdr msg;
5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct iovec io[2];
5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (priv->sock < 0 || dl_list_empty(&priv->ctrl_dst))
5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0 || (size_t) res >= sizeof(levelstr))
5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	io[0].iov_base = levelstr;
5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	io[0].iov_len = os_strlen(levelstr);
5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	io[1].iov_base = (char *) buf;
5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	io[1].iov_len = len;
5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	msg.msg_iov = io;
5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	msg.msg_iovlen = 2;
5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	idx = 0;
5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each_safe(dst, next, &priv->ctrl_dst, struct wpa_ctrl_dst,
5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      list) {
5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (level >= dst->debug_level) {
5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor send",
5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    (u8 *) dst->addr.sun_path, dst->addrlen -
5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    offsetof(struct sockaddr_un, sun_path));
5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			msg.msg_name = (void *) &dst->addr;
5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			msg.msg_namelen = dst->addrlen;
5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (sendmsg(priv->sock, &msg, 0) < 0) {
5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				int _errno = errno;
5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: "
5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "%d - %s",
5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   idx, errno, strerror(errno));
5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				dst->errors++;
5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				if (dst->errors > 1000 ||
5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    (_errno != ENOBUFS && dst->errors > 10) ||
5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    _errno == ENOENT) {
5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					wpa_supplicant_ctrl_iface_detach(
5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						priv, &dst->addr,
5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						dst->addrlen);
5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				}
5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			} else
5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				dst->errors = 0;
5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		idx++;
5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_supplicant_ctrl_iface_wait(struct ctrl_iface_priv *priv)
5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char buf[256];
5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct sockaddr_un from;
5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	socklen_t fromlen = sizeof(from);
5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (;;) {
5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "CTRL_IFACE - %s - wait for monitor to "
5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "attach", priv->wpa_s->ifname);
5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_wait_for_read_sock(priv->sock);
5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = recvfrom(priv->sock, buf, sizeof(buf) - 1, 0,
5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       (struct sockaddr *) &from, &fromlen);
5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (res < 0) {
5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			perror("recvfrom(ctrl_iface)");
5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		buf[res] = '\0';
5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_strcmp(buf, "ATTACH") == 0) {
5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/* handle ATTACH signal of first monitor interface */
5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (!wpa_supplicant_ctrl_iface_attach(priv, &from,
5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt							      fromlen)) {
5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				sendto(priv->sock, "OK\n", 3, 0,
5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       (struct sockaddr *) &from, fromlen);
5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				/* OK to continue */
5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return;
5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			} else {
5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				sendto(priv->sock, "FAIL\n", 5, 0,
5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       (struct sockaddr *) &from, fromlen);
5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/* return FAIL for all other signals */
5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sendto(priv->sock, "FAIL\n", 5, 0,
5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       (struct sockaddr *) &from, fromlen);
5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Global ctrl_iface */
5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct ctrl_iface_global_priv {
6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_global *global;
6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int sock;
6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx,
6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						     void *sock_ctx)
6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_global *global = eloop_ctx;
6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char buf[256];
6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct sockaddr_un from;
6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	socklen_t fromlen = sizeof(from);
6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *reply;
6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t reply_len;
6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       (struct sockaddr *) &from, &fromlen);
6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0) {
6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		perror("recvfrom(ctrl_iface)");
6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf[res] = '\0';
6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	reply = wpa_supplicant_global_ctrl_iface_process(global, buf,
6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt							 &reply_len);
6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (reply) {
6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       fromlen);
6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(reply);
6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (reply_len) {
6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       fromlen);
6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct ctrl_iface_global_priv *
6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_supplicant_global_ctrl_iface_init(struct wpa_global *global)
6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct ctrl_iface_global_priv *priv;
6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct sockaddr_un addr;
6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	priv = os_zalloc(sizeof(*priv));
6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (priv == NULL)
6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	priv->global = global;
6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	priv->sock = -1;
6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (global->params.ctrl_interface == NULL)
6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return priv;
6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef ANDROID
6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	priv->sock = android_get_control_socket(global->params.ctrl_interface);
6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (priv->sock >= 0)
6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto havesock;
6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* ANDROID */
6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "Global control interface '%s'",
6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   global->params.ctrl_interface);
6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	priv->sock = socket(PF_UNIX, SOCK_DGRAM, 0);
6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (priv->sock < 0) {
6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		perror("socket(PF_UNIX)");
6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&addr, 0, sizeof(addr));
6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	addr.sun_len = sizeof(addr);
6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* __FreeBSD__ */
6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	addr.sun_family = AF_UNIX;
6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_strlcpy(addr.sun_path, global->params.ctrl_interface,
6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   sizeof(addr.sun_path));
6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		perror("bind(PF_UNIX)");
6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (connect(priv->sock, (struct sockaddr *) &addr,
6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    sizeof(addr)) < 0) {
6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   " allow connections - assuming it was left"
6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "over from forced program termination");
6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (unlink(global->params.ctrl_interface) < 0) {
6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				perror("unlink[ctrl_iface]");
6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_ERROR, "Could not unlink "
6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "existing ctrl_iface socket '%s'",
6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   global->params.ctrl_interface);
6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				goto fail;
6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (bind(priv->sock, (struct sockaddr *) &addr,
6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 sizeof(addr)) < 0) {
6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				perror("bind(PF_UNIX)");
6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				goto fail;
6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "ctrl_iface socket '%s'",
6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   global->params.ctrl_interface);
6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "be in use - cannot override it");
7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "not used anymore",
7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   global->params.ctrl_interface);
7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto fail;
7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef ANDROID
7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidthavesock:
7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* ANDROID */
7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_read_sock(priv->sock,
7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 wpa_supplicant_global_ctrl_iface_receive,
7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 global, NULL);
7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return priv;
7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfail:
7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (priv->sock >= 0)
7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		close(priv->sock);
7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(priv);
7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid
7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_supplicant_global_ctrl_iface_deinit(struct ctrl_iface_global_priv *priv)
7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (priv->sock >= 0) {
7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_unregister_read_sock(priv->sock);
7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		close(priv->sock);
7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (priv->global->params.ctrl_interface)
7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		unlink(priv->global->params.ctrl_interface);
7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(priv);
7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
735