1845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/*
2845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * WPA Supplicant / UDP socket -based control interface
3845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Copyright (c) 2004-2005, Jouni Malinen <j@w1.fi>
4845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *
5845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * This program is free software; you can redistribute it and/or modify
6845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * it under the terms of the GNU General Public License version 2 as
7845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * published by the Free Software Foundation.
8845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *
9845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Alternatively, this software may be distributed under the terms of BSD
10845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * license.
11845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *
12845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * See README and COPYING for more details.
13845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
14845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
15845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#include "includes.h"
16845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
17845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#include "common.h"
18845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#include "eloop.h"
19845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#include "config.h"
20845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#include "eapol_sm.h"
21845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#include "wpa_supplicant_i.h"
22845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#include "ctrl_iface.h"
23845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#include "wpa_ctrl.h"
24845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
25845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
26845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#define COOKIE_LEN 8
27845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
28845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/* Per-interface ctrl_iface */
29845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
30845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/**
31845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * struct wpa_ctrl_dst - Internal data structure of control interface monitors
32845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *
33845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * This structure is used to store information about registered control
34845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * interface monitors into struct wpa_supplicant. This data is private to
35845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * ctrl_iface_udp.c and should not be touched directly from other files.
36845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
37845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstruct wpa_ctrl_dst {
38845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct wpa_ctrl_dst *next;
39845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct sockaddr_in addr;
40845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	socklen_t addrlen;
41845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	int debug_level;
42845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	int errors;
43845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project};
44845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
45845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
46845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstruct ctrl_iface_priv {
47845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct wpa_supplicant *wpa_s;
48845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	int sock;
49845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct wpa_ctrl_dst *ctrl_dst;
50845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	u8 cookie[COOKIE_LEN];
51845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project};
52845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
53845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
54845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic void wpa_supplicant_ctrl_iface_send(struct ctrl_iface_priv *priv,
55845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   int level, const char *buf,
56845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   size_t len);
57845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
58845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
59845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic int wpa_supplicant_ctrl_iface_attach(struct ctrl_iface_priv *priv,
60845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					    struct sockaddr_in *from,
61845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					    socklen_t fromlen)
62845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
63845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct wpa_ctrl_dst *dst;
64845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
65845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	dst = os_zalloc(sizeof(*dst));
66845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (dst == NULL)
67845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return -1;
68845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_memcpy(&dst->addr, from, sizeof(struct sockaddr_in));
69845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	dst->addrlen = fromlen;
70845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	dst->debug_level = MSG_INFO;
71845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	dst->next = priv->ctrl_dst;
72845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	priv->ctrl_dst = dst;
73845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor attached %s:%d",
74845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		   inet_ntoa(from->sin_addr), ntohs(from->sin_port));
75845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return 0;
76845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
77845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
78845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
79845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic int wpa_supplicant_ctrl_iface_detach(struct ctrl_iface_priv *priv,
80845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					    struct sockaddr_in *from,
81845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					    socklen_t fromlen)
82845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
83845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct wpa_ctrl_dst *dst, *prev = NULL;
84845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
85845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	dst = priv->ctrl_dst;
86845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	while (dst) {
87845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		if (from->sin_addr.s_addr == dst->addr.sin_addr.s_addr &&
88845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		    from->sin_port == dst->addr.sin_port) {
89845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			if (prev == NULL)
90845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				priv->ctrl_dst = dst->next;
91845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			else
92845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				prev->next = dst->next;
93845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			os_free(dst);
94845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor detached "
95845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				   "%s:%d", inet_ntoa(from->sin_addr),
96845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				   ntohs(from->sin_port));
97845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			return 0;
98845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		}
99845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		prev = dst;
100845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		dst = dst->next;
101845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
102845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return -1;
103845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
104845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
105845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
106845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic int wpa_supplicant_ctrl_iface_level(struct ctrl_iface_priv *priv,
107845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   struct sockaddr_in *from,
108845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   socklen_t fromlen,
109845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   char *level)
110845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
111845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct wpa_ctrl_dst *dst;
112845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
113845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level);
114845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
115845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	dst = priv->ctrl_dst;
116845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	while (dst) {
117845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		if (from->sin_addr.s_addr == dst->addr.sin_addr.s_addr &&
118845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		    from->sin_port == dst->addr.sin_port) {
119845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			wpa_printf(MSG_DEBUG, "CTRL_IFACE changed monitor "
120845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				   "level %s:%d", inet_ntoa(from->sin_addr),
121845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				   ntohs(from->sin_port));
122845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			dst->debug_level = atoi(level);
123845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			return 0;
124845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		}
125845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		dst = dst->next;
126845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
127845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
128845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return -1;
129845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
130845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
131845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
132845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic char *
133845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectwpa_supplicant_ctrl_iface_get_cookie(struct ctrl_iface_priv *priv,
134845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				     size_t *reply_len)
135845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
136845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	char *reply;
137845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	reply = os_malloc(7 + 2 * COOKIE_LEN + 1);
138845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (reply == NULL) {
139845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		*reply_len = 1;
140845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
141845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
142845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
143845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_memcpy(reply, "COOKIE=", 7);
144845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1,
145845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			 priv->cookie, COOKIE_LEN);
146845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
147845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	*reply_len = 7 + 2 * COOKIE_LEN;
148845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return reply;
149845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
150845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
151845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
152845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx,
153845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					      void *sock_ctx)
154845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
155845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct wpa_supplicant *wpa_s = eloop_ctx;
156845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct ctrl_iface_priv *priv = sock_ctx;
157845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	char buf[256], *pos;
158845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	int res;
159845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct sockaddr_in from;
160845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	socklen_t fromlen = sizeof(from);
161845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	char *reply = NULL;
162845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	size_t reply_len = 0;
163845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	int new_attached = 0;
164845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	u8 cookie[COOKIE_LEN];
165845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
166845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
167845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		       (struct sockaddr *) &from, &fromlen);
168845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (res < 0) {
169845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		perror("recvfrom(ctrl_iface)");
170845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return;
171845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
172845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (from.sin_addr.s_addr != htonl((127 << 24) | 1)) {
173845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		/*
174845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		 * The OS networking stack is expected to drop this kind of
175845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		 * frames since the socket is bound to only localhost address.
176845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		 * Just in case, drop the frame if it is coming from any other
177845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		 * address.
178845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		 */
179845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_DEBUG, "CTRL: Drop packet from unexpected "
180845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   "source %s", inet_ntoa(from.sin_addr));
181845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return;
182845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
183845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	buf[res] = '\0';
184845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
185845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (os_strcmp(buf, "GET_COOKIE") == 0) {
186845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		reply = wpa_supplicant_ctrl_iface_get_cookie(priv, &reply_len);
187845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		goto done;
188845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
189845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
190845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	/*
191845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * Require that the client includes a prefix with the 'cookie' value
192845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * fetched with GET_COOKIE command. This is used to verify that the
193845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * client has access to a bidirectional link over UDP in order to
194845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * avoid attacks using forged localhost IP address even if the OS does
195845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * not block such frames from remote destinations.
196845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 */
197845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (os_strncmp(buf, "COOKIE=", 7) != 0) {
198845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_DEBUG, "CTLR: No cookie in the request - "
199845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   "drop request");
200845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return;
201845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
202845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
203845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (hexstr2bin(buf + 7, cookie, COOKIE_LEN) < 0) {
204845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie format in the "
205845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   "request - drop request");
206845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return;
207845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
208845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
209845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (os_memcmp(cookie, priv->cookie, COOKIE_LEN) != 0) {
210845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie in the request - "
211845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   "drop request");
212845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return;
213845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
214845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
215845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	pos = buf + 7 + 2 * COOKIE_LEN;
216845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	while (*pos == ' ')
217845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		pos++;
218845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
219845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (os_strcmp(pos, "ATTACH") == 0) {
220845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		if (wpa_supplicant_ctrl_iface_attach(priv, &from, fromlen))
221845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			reply_len = 1;
222845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		else {
223845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			new_attached = 1;
224845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			reply_len = 2;
225845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		}
226845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	} else if (os_strcmp(pos, "DETACH") == 0) {
227845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		if (wpa_supplicant_ctrl_iface_detach(priv, &from, fromlen))
228845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			reply_len = 1;
229845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		else
230845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			reply_len = 2;
231845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	} else if (os_strncmp(pos, "LEVEL ", 6) == 0) {
232845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		if (wpa_supplicant_ctrl_iface_level(priv, &from, fromlen,
233845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project						    pos + 6))
234845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			reply_len = 1;
235845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		else
236845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			reply_len = 2;
237845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	} else {
238845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		reply = wpa_supplicant_ctrl_iface_process(wpa_s, pos,
239845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project							  &reply_len);
240845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
241845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
242845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project done:
243845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (reply) {
244845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
245845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		       fromlen);
246845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		os_free(reply);
247845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	} else if (reply_len == 1) {
248845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
249845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		       fromlen);
250845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	} else if (reply_len == 2) {
251845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		sendto(sock, "OK\n", 3, 0, (struct sockaddr *) &from,
252845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		       fromlen);
253845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
254845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
255845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (new_attached)
256845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		eapol_sm_notify_ctrl_attached(wpa_s->eapol);
257845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
258845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
259845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
260845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic void wpa_supplicant_ctrl_iface_msg_cb(void *ctx, int level,
261845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					     const char *txt, size_t len)
262845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
263845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct wpa_supplicant *wpa_s = ctx;
264845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (wpa_s == NULL || wpa_s->ctrl_iface == NULL)
265845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return;
266845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_supplicant_ctrl_iface_send(wpa_s->ctrl_iface, level, txt, len);
267845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
268845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
269845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
270845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstruct ctrl_iface_priv *
271845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectwpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s)
272845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
273845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct ctrl_iface_priv *priv;
274845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct sockaddr_in addr;
275845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
276845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	priv = os_zalloc(sizeof(*priv));
277845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (priv == NULL)
278845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
279845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	priv->wpa_s = wpa_s;
280845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	priv->sock = -1;
281845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_get_random(priv->cookie, COOKIE_LEN);
282845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
283845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (wpa_s->conf->ctrl_interface == NULL)
284845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return priv;
285845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
286845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	priv->sock = socket(PF_INET, SOCK_DGRAM, 0);
287845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (priv->sock < 0) {
288845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		perror("socket(PF_INET)");
289845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		goto fail;
290845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
291845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
292845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_memset(&addr, 0, sizeof(addr));
293845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	addr.sin_family = AF_INET;
294845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	addr.sin_addr.s_addr = htonl((127 << 24) | 1);
295845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	addr.sin_port = htons(WPA_CTRL_IFACE_PORT);
296845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
297845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		perror("bind(AF_INET)");
298845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		goto fail;
299845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
300845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
301845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	eloop_register_read_sock(priv->sock, wpa_supplicant_ctrl_iface_receive,
302845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				 wpa_s, priv);
303845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_msg_register_cb(wpa_supplicant_ctrl_iface_msg_cb);
304845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
305845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return priv;
306845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
307845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectfail:
308845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (priv->sock >= 0)
309845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		close(priv->sock);
310845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_free(priv);
311845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return NULL;
312845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
313845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
314845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
315845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectvoid wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv)
316845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
317845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct wpa_ctrl_dst *dst, *prev;
318845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
319845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (priv->sock > -1) {
320845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		eloop_unregister_read_sock(priv->sock);
321845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		if (priv->ctrl_dst) {
322845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			/*
323845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			 * Wait a second before closing the control socket if
324845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			 * there are any attached monitors in order to allow
325845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			 * them to receive any pending messages.
326845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			 */
327845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			wpa_printf(MSG_DEBUG, "CTRL_IFACE wait for attached "
328845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				   "monitors to receive messages");
329845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			os_sleep(1, 0);
330845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		}
331845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		close(priv->sock);
332845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		priv->sock = -1;
333845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
334845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
335845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	dst = priv->ctrl_dst;
336845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	while (dst) {
337845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		prev = dst;
338845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		dst = dst->next;
339845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		os_free(prev);
340845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
341845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_free(priv);
342845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
343845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
344845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
345845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic void wpa_supplicant_ctrl_iface_send(struct ctrl_iface_priv *priv,
346845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   int level, const char *buf,
347845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   size_t len)
348845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
349845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct wpa_ctrl_dst *dst, *next;
350845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	char levelstr[10];
351845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	int idx;
352845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	char *sbuf;
353845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	int llen;
354845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
355845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	dst = priv->ctrl_dst;
356845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (priv->sock < 0 || dst == NULL)
357845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return;
358845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
359845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
360845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
361845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	llen = os_strlen(levelstr);
362845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sbuf = os_malloc(llen + len);
363845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (sbuf == NULL)
364845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return;
365845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
366845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_memcpy(sbuf, levelstr, llen);
367845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_memcpy(sbuf + llen, buf, len);
368845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
369845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	idx = 0;
370845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	while (dst) {
371845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		next = dst->next;
372845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		if (level >= dst->debug_level) {
373845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor send %s:%d",
374845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				   inet_ntoa(dst->addr.sin_addr),
375845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				   ntohs(dst->addr.sin_port));
376845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			if (sendto(priv->sock, sbuf, llen + len, 0,
377845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				   (struct sockaddr *) &dst->addr,
378845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				   sizeof(dst->addr)) < 0) {
379845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				perror("sendto(CTRL_IFACE monitor)");
380845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				dst->errors++;
381845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				if (dst->errors > 10) {
382845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					wpa_supplicant_ctrl_iface_detach(
383845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project						priv, &dst->addr,
384845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project						dst->addrlen);
385845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				}
386845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			} else
387845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				dst->errors = 0;
388845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		}
389845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		idx++;
390845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		dst = next;
391845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
392845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_free(sbuf);
393845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
394845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
395845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
396845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectvoid wpa_supplicant_ctrl_iface_wait(struct ctrl_iface_priv *priv)
397845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
398845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_printf(MSG_DEBUG, "CTRL_IFACE - %s - wait for monitor",
399845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		   priv->wpa_s->ifname);
400845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	eloop_wait_for_read_sock(priv->sock);
401845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
402845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
403845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
404845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/* Global ctrl_iface */
405845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
406845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstruct ctrl_iface_global_priv {
407845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	int sock;
408845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	u8 cookie[COOKIE_LEN];
409845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project};
410845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
411845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
412845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic char *
413845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectwpa_supplicant_global_get_cookie(struct ctrl_iface_global_priv *priv,
414845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				 size_t *reply_len)
415845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
416845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	char *reply;
417845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	reply = os_malloc(7 + 2 * COOKIE_LEN + 1);
418845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (reply == NULL) {
419845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		*reply_len = 1;
420845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
421845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
422845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
423845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_memcpy(reply, "COOKIE=", 7);
424845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1,
425845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			 priv->cookie, COOKIE_LEN);
426845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
427845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	*reply_len = 7 + 2 * COOKIE_LEN;
428845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return reply;
429845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
430845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
431845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
432845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx,
433845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project						     void *sock_ctx)
434845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
435845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct wpa_global *global = eloop_ctx;
436845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct ctrl_iface_global_priv *priv = sock_ctx;
437845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	char buf[256], *pos;
438845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	int res;
439845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct sockaddr_in from;
440845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	socklen_t fromlen = sizeof(from);
441845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	char *reply;
442845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	size_t reply_len;
443845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	u8 cookie[COOKIE_LEN];
444845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
445845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
446845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		       (struct sockaddr *) &from, &fromlen);
447845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (res < 0) {
448845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		perror("recvfrom(ctrl_iface)");
449845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return;
450845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
451845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (from.sin_addr.s_addr != htonl((127 << 24) | 1)) {
452845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		/*
453845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		 * The OS networking stack is expected to drop this kind of
454845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		 * frames since the socket is bound to only localhost address.
455845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		 * Just in case, drop the frame if it is coming from any other
456845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		 * address.
457845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		 */
458845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_DEBUG, "CTRL: Drop packet from unexpected "
459845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   "source %s", inet_ntoa(from.sin_addr));
460845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return;
461845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
462845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	buf[res] = '\0';
463845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
464845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (os_strcmp(buf, "GET_COOKIE") == 0) {
465845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		reply = wpa_supplicant_global_get_cookie(priv, &reply_len);
466845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		goto done;
467845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
468845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
469845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (os_strncmp(buf, "COOKIE=", 7) != 0) {
470845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_DEBUG, "CTLR: No cookie in the request - "
471845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   "drop request");
472845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return;
473845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
474845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
475845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (hexstr2bin(buf + 7, cookie, COOKIE_LEN) < 0) {
476845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie format in the "
477845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   "request - drop request");
478845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return;
479845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
480845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
481845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (os_memcmp(cookie, priv->cookie, COOKIE_LEN) != 0) {
482845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie in the request - "
483845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   "drop request");
484845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return;
485845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
486845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
487845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	pos = buf + 7 + 2 * COOKIE_LEN;
488845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	while (*pos == ' ')
489845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		pos++;
490845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
491845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	reply = wpa_supplicant_global_ctrl_iface_process(global, pos,
492845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project							 &reply_len);
493845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
494845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project done:
495845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (reply) {
496845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
497845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		       fromlen);
498845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		os_free(reply);
499845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	} else if (reply_len) {
500845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
501845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		       fromlen);
502845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
503845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
504845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
505845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
506845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstruct ctrl_iface_global_priv *
507845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectwpa_supplicant_global_ctrl_iface_init(struct wpa_global *global)
508845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
509845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct ctrl_iface_global_priv *priv;
510845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct sockaddr_in addr;
511845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
512845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	priv = os_zalloc(sizeof(*priv));
513845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (priv == NULL)
514845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
515845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	priv->sock = -1;
516845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_get_random(priv->cookie, COOKIE_LEN);
517845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
518845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (global->params.ctrl_interface == NULL)
519845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return priv;
520845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
521845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_printf(MSG_DEBUG, "Global control interface '%s'",
522845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		   global->params.ctrl_interface);
523845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
524845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	priv->sock = socket(PF_INET, SOCK_DGRAM, 0);
525845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (priv->sock < 0) {
526845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		perror("socket(PF_INET)");
527845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		goto fail;
528845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
529845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
530845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_memset(&addr, 0, sizeof(addr));
531845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	addr.sin_family = AF_INET;
532845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	addr.sin_addr.s_addr = htonl((127 << 24) | 1);
533845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	addr.sin_port = htons(WPA_GLOBAL_CTRL_IFACE_PORT);
534845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
535845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		perror("bind(AF_INET)");
536845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		goto fail;
537845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
538845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
539845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	eloop_register_read_sock(priv->sock,
540845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				 wpa_supplicant_global_ctrl_iface_receive,
541845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				 global, priv);
542845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
543845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return priv;
544845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
545845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectfail:
546845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (priv->sock >= 0)
547845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		close(priv->sock);
548845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_free(priv);
549845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return NULL;
550845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
551845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
552845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
553845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectvoid
554845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectwpa_supplicant_global_ctrl_iface_deinit(struct ctrl_iface_global_priv *priv)
555845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
556845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (priv->sock >= 0) {
557845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		eloop_unregister_read_sock(priv->sock);
558845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		close(priv->sock);
559845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
560845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_free(priv);
561845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
562