xref: /netbsd-src/external/bsd/wpa/dist/src/common/wpa_helpers.c (revision 0a73ee0a32b4208ab171f89f408b38fd4c664291)
13c260e60Schristos /*
23c260e60Schristos  * wpa_supplicant ctrl_iface helpers
33c260e60Schristos  * Copyright (c) 2010-2011, Atheros Communications, Inc.
43c260e60Schristos  * Copyright (c) 2011-2012, Qualcomm Atheros, Inc.
53c260e60Schristos  *
63c260e60Schristos  * This software may be distributed under the terms of the BSD license.
73c260e60Schristos  * See README for more details.
83c260e60Schristos  */
93c260e60Schristos 
103c260e60Schristos #include "includes.h"
113c260e60Schristos #include <time.h>
123c260e60Schristos 
133c260e60Schristos #include "common.h"
143c260e60Schristos #include "wpa_ctrl.h"
153c260e60Schristos #include "wpa_helpers.h"
163c260e60Schristos 
173c260e60Schristos 
183c260e60Schristos char *wpas_ctrl_path = "/var/run/wpa_supplicant/";
193c260e60Schristos static int default_timeout = 60;
203c260e60Schristos 
213c260e60Schristos 
wpa_open_ctrl(const char * ifname)223c260e60Schristos static struct wpa_ctrl * wpa_open_ctrl(const char *ifname)
233c260e60Schristos {
243c260e60Schristos 	char buf[128];
253c260e60Schristos 	struct wpa_ctrl *ctrl;
263c260e60Schristos 
273c260e60Schristos 	os_snprintf(buf, sizeof(buf), "%s%s", wpas_ctrl_path, ifname);
283c260e60Schristos 	ctrl = wpa_ctrl_open(buf);
293c260e60Schristos 	if (ctrl == NULL)
303c260e60Schristos 		printf("wpa_command: wpa_ctrl_open(%s) failed\n", buf);
313c260e60Schristos 	return ctrl;
323c260e60Schristos }
333c260e60Schristos 
343c260e60Schristos 
wpa_command(const char * ifname,const char * cmd)353c260e60Schristos int wpa_command(const char *ifname, const char *cmd)
363c260e60Schristos {
373c260e60Schristos 	struct wpa_ctrl *ctrl;
383c260e60Schristos 	char buf[128];
393c260e60Schristos 	size_t len;
403c260e60Schristos 
413c260e60Schristos 	printf("wpa_command(ifname='%s', cmd='%s')\n", ifname, cmd);
423c260e60Schristos 	ctrl = wpa_open_ctrl(ifname);
433c260e60Schristos 	if (ctrl == NULL)
443c260e60Schristos 		return -1;
453c260e60Schristos 	len = sizeof(buf);
463c260e60Schristos 	if (wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len, NULL) < 0) {
473c260e60Schristos 		printf("wpa_command: wpa_ctrl_request failed\n");
483c260e60Schristos 		wpa_ctrl_close(ctrl);
493c260e60Schristos 		return -1;
503c260e60Schristos 	}
513c260e60Schristos 	wpa_ctrl_close(ctrl);
523c260e60Schristos 	buf[len] = '\0';
533c260e60Schristos 	if (strncmp(buf, "FAIL", 4) == 0) {
543c260e60Schristos 		printf("wpa_command: Command failed (FAIL received)\n");
553c260e60Schristos 		return -1;
563c260e60Schristos 	}
573c260e60Schristos 	return 0;
583c260e60Schristos }
593c260e60Schristos 
603c260e60Schristos 
wpa_command_resp(const char * ifname,const char * cmd,char * resp,size_t resp_size)613c260e60Schristos int wpa_command_resp(const char *ifname, const char *cmd,
623c260e60Schristos 		     char *resp, size_t resp_size)
633c260e60Schristos {
643c260e60Schristos 	struct wpa_ctrl *ctrl;
653c260e60Schristos 	size_t len;
663c260e60Schristos 
673c260e60Schristos 	printf("wpa_command(ifname='%s', cmd='%s')\n", ifname, cmd);
683c260e60Schristos 	ctrl = wpa_open_ctrl(ifname);
693c260e60Schristos 	if (ctrl == NULL)
703c260e60Schristos 		return -1;
713c260e60Schristos 	len = resp_size;
723c260e60Schristos 	if (wpa_ctrl_request(ctrl, cmd, strlen(cmd), resp, &len, NULL) < 0) {
733c260e60Schristos 		printf("wpa_command: wpa_ctrl_request failed\n");
743c260e60Schristos 		wpa_ctrl_close(ctrl);
753c260e60Schristos 		return -1;
763c260e60Schristos 	}
773c260e60Schristos 	wpa_ctrl_close(ctrl);
783c260e60Schristos 	resp[len] = '\0';
793c260e60Schristos 	return 0;
803c260e60Schristos }
813c260e60Schristos 
823c260e60Schristos 
open_wpa_mon(const char * ifname)833c260e60Schristos struct wpa_ctrl * open_wpa_mon(const char *ifname)
843c260e60Schristos {
853c260e60Schristos 	struct wpa_ctrl *ctrl;
863c260e60Schristos 
873c260e60Schristos 	ctrl = wpa_open_ctrl(ifname);
883c260e60Schristos 	if (ctrl == NULL)
893c260e60Schristos 		return NULL;
903c260e60Schristos 	if (wpa_ctrl_attach(ctrl) < 0) {
913c260e60Schristos 		wpa_ctrl_close(ctrl);
923c260e60Schristos 		return NULL;
933c260e60Schristos 	}
943c260e60Schristos 
953c260e60Schristos 	return ctrl;
963c260e60Schristos }
973c260e60Schristos 
983c260e60Schristos 
get_wpa_cli_event2(struct wpa_ctrl * mon,const char * event,const char * event2,char * buf,size_t buf_size)993c260e60Schristos int get_wpa_cli_event2(struct wpa_ctrl *mon,
1003c260e60Schristos 		       const char *event, const char *event2,
1013c260e60Schristos 		       char *buf, size_t buf_size)
1023c260e60Schristos {
1033c260e60Schristos 	int fd, ret;
1043c260e60Schristos 	fd_set rfd;
1053c260e60Schristos 	char *pos;
1063c260e60Schristos 	struct timeval tv;
1073c260e60Schristos 	time_t start, now;
1083c260e60Schristos 
1093c260e60Schristos 	printf("Waiting for wpa_cli event %s\n", event);
1103c260e60Schristos 	fd = wpa_ctrl_get_fd(mon);
1113c260e60Schristos 	if (fd < 0)
1123c260e60Schristos 		return -1;
1133c260e60Schristos 
1143c260e60Schristos 	time(&start);
1153c260e60Schristos 	while (1) {
1163c260e60Schristos 		size_t len;
1173c260e60Schristos 
1183c260e60Schristos 		FD_ZERO(&rfd);
1193c260e60Schristos 		FD_SET(fd, &rfd);
1203c260e60Schristos 		tv.tv_sec = default_timeout;
1213c260e60Schristos 		tv.tv_usec = 0;
1223c260e60Schristos 		ret = select(fd + 1, &rfd, NULL, NULL, &tv);
1233c260e60Schristos 		if (ret == 0) {
1243c260e60Schristos 			printf("Timeout on waiting for event %s\n", event);
1253c260e60Schristos 			return -1;
1263c260e60Schristos 		}
1273c260e60Schristos 		if (ret < 0) {
1283c260e60Schristos 			printf("select: %s\n", strerror(errno));
1293c260e60Schristos 			return -1;
1303c260e60Schristos 		}
1313c260e60Schristos 		len = buf_size;
1323c260e60Schristos 		if (wpa_ctrl_recv(mon, buf, &len) < 0) {
1333c260e60Schristos 			printf("Failure while waiting for event %s\n", event);
1343c260e60Schristos 			return -1;
1353c260e60Schristos 		}
1363c260e60Schristos 		if (len == buf_size)
1373c260e60Schristos 			len--;
1383c260e60Schristos 		buf[len] = '\0';
1393c260e60Schristos 
1403c260e60Schristos 		pos = strchr(buf, '>');
1413c260e60Schristos 		if (pos &&
1423c260e60Schristos 		    (strncmp(pos + 1, event, strlen(event)) == 0 ||
1433c260e60Schristos 		     (event2 &&
1443c260e60Schristos 		      strncmp(pos + 1, event2, strlen(event2)) == 0)))
1453c260e60Schristos 			return 0; /* Event found */
1463c260e60Schristos 
1473c260e60Schristos 		time(&now);
1483c260e60Schristos 		if ((int) (now - start) > default_timeout) {
1493c260e60Schristos 			printf("Timeout on waiting for event %s\n", event);
1503c260e60Schristos 			return -1;
1513c260e60Schristos 		}
1523c260e60Schristos 	}
1533c260e60Schristos }
1543c260e60Schristos 
1553c260e60Schristos 
get_wpa_cli_event(struct wpa_ctrl * mon,const char * event,char * buf,size_t buf_size)1563c260e60Schristos int get_wpa_cli_event(struct wpa_ctrl *mon,
1573c260e60Schristos 		      const char *event, char *buf, size_t buf_size)
1583c260e60Schristos {
1593c260e60Schristos 	return get_wpa_cli_event2(mon, event, NULL, buf, buf_size);
1603c260e60Schristos }
1613c260e60Schristos 
1623c260e60Schristos 
get_wpa_status(const char * ifname,const char * field,char * obuf,size_t obuf_size)1633c260e60Schristos int get_wpa_status(const char *ifname, const char *field, char *obuf,
1643c260e60Schristos 		   size_t obuf_size)
1653c260e60Schristos {
1663c260e60Schristos 	struct wpa_ctrl *ctrl;
1673c260e60Schristos 	char buf[4096];
1683c260e60Schristos 	char *pos, *end;
1693c260e60Schristos 	size_t len, flen;
1703c260e60Schristos 
1713c260e60Schristos 	ctrl = wpa_open_ctrl(ifname);
1723c260e60Schristos 	if (ctrl == NULL)
1733c260e60Schristos 		return -1;
1743c260e60Schristos 	len = sizeof(buf);
17536ebd06eSchristos 	if (wpa_ctrl_request(ctrl, "STATUS-NO_EVENTS", 16, buf, &len,
17636ebd06eSchristos 			     NULL) < 0) {
1773c260e60Schristos 		wpa_ctrl_close(ctrl);
1783c260e60Schristos 		return -1;
1793c260e60Schristos 	}
1803c260e60Schristos 	wpa_ctrl_close(ctrl);
1813c260e60Schristos 	buf[len] = '\0';
1823c260e60Schristos 
1833c260e60Schristos 	flen = strlen(field);
1843c260e60Schristos 	pos = buf;
1853c260e60Schristos 	while (pos + flen < buf + len) {
1863c260e60Schristos 		if (pos > buf) {
1873c260e60Schristos 			if (*pos != '\n') {
1883c260e60Schristos 				pos++;
1893c260e60Schristos 				continue;
1903c260e60Schristos 			}
1913c260e60Schristos 			pos++;
1923c260e60Schristos 		}
1933c260e60Schristos 		if (strncmp(pos, field, flen) != 0 || pos[flen] != '=') {
1943c260e60Schristos 			pos++;
1953c260e60Schristos 			continue;
1963c260e60Schristos 		}
1973c260e60Schristos 		pos += flen + 1;
1983c260e60Schristos 		end = strchr(pos, '\n');
1993c260e60Schristos 		if (end == NULL)
2003c260e60Schristos 			return -1;
2013c260e60Schristos 		*end++ = '\0';
2023c260e60Schristos 		if (end - pos > (int) obuf_size)
2033c260e60Schristos 			return -1;
2043c260e60Schristos 		memcpy(obuf, pos, end - pos);
2053c260e60Schristos 		return 0;
2063c260e60Schristos 	}
2073c260e60Schristos 
2083c260e60Schristos 	return -1;
2093c260e60Schristos }
2103c260e60Schristos 
2113c260e60Schristos 
wait_ip_addr(const char * ifname,int timeout)2123c260e60Schristos int wait_ip_addr(const char *ifname, int timeout)
2133c260e60Schristos {
2143c260e60Schristos 	char ip[30];
2153c260e60Schristos 	int count = timeout;
2163c260e60Schristos 	struct wpa_ctrl *ctrl;
2173c260e60Schristos 
2183c260e60Schristos 	while (count > 0) {
2193c260e60Schristos 		printf("%s: ifname='%s' - %d seconds remaining\n",
2203c260e60Schristos 		       __func__, ifname, count);
2213c260e60Schristos 		count--;
2223c260e60Schristos 		if (get_wpa_status(ifname, "ip_address", ip, sizeof(ip)) == 0
2233c260e60Schristos 		    && strlen(ip) > 0) {
2243c260e60Schristos 			printf("IP address found: '%s'\n", ip);
225*0a73ee0aSchristos 			if (strncmp(ip, "169.254.", 8) != 0)
2263c260e60Schristos 				return 0;
2273c260e60Schristos 		}
2283c260e60Schristos 		ctrl = wpa_open_ctrl(ifname);
2293c260e60Schristos 		if (ctrl == NULL)
2303c260e60Schristos 			return -1;
2313c260e60Schristos 		wpa_ctrl_close(ctrl);
2323c260e60Schristos 		sleep(1);
2333c260e60Schristos 	}
2343c260e60Schristos 	printf("%s: Could not get IP address for ifname='%s'", __func__,
2353c260e60Schristos 	       ifname);
2363c260e60Schristos 	return -1;
2373c260e60Schristos }
2383c260e60Schristos 
2393c260e60Schristos 
add_network(const char * ifname)2403c260e60Schristos int add_network(const char *ifname)
2413c260e60Schristos {
2423c260e60Schristos 	char res[30];
2433c260e60Schristos 
2443c260e60Schristos 	if (wpa_command_resp(ifname, "ADD_NETWORK", res, sizeof(res)) < 0)
2453c260e60Schristos 		return -1;
2463c260e60Schristos 	return atoi(res);
2473c260e60Schristos }
2483c260e60Schristos 
2493c260e60Schristos 
set_network(const char * ifname,int id,const char * field,const char * value)2503c260e60Schristos int set_network(const char *ifname, int id, const char *field,
2513c260e60Schristos 		const char *value)
2523c260e60Schristos {
2533c260e60Schristos 	char buf[200];
2543c260e60Schristos 	snprintf(buf, sizeof(buf), "SET_NETWORK %d %s %s", id, field, value);
2553c260e60Schristos 	return wpa_command(ifname, buf);
2563c260e60Schristos }
2573c260e60Schristos 
2583c260e60Schristos 
set_network_quoted(const char * ifname,int id,const char * field,const char * value)2593c260e60Schristos int set_network_quoted(const char *ifname, int id, const char *field,
2603c260e60Schristos 		       const char *value)
2613c260e60Schristos {
2623c260e60Schristos 	char buf[200];
2633c260e60Schristos 	snprintf(buf, sizeof(buf), "SET_NETWORK %d %s \"%s\"",
2643c260e60Schristos 		 id, field, value);
2653c260e60Schristos 	return wpa_command(ifname, buf);
2663c260e60Schristos }
2673c260e60Schristos 
2683c260e60Schristos 
add_cred(const char * ifname)2693c260e60Schristos int add_cred(const char *ifname)
2703c260e60Schristos {
2713c260e60Schristos 	char res[30];
2723c260e60Schristos 
2733c260e60Schristos 	if (wpa_command_resp(ifname, "ADD_CRED", res, sizeof(res)) < 0)
2743c260e60Schristos 		return -1;
2753c260e60Schristos 	return atoi(res);
2763c260e60Schristos }
2773c260e60Schristos 
2783c260e60Schristos 
set_cred(const char * ifname,int id,const char * field,const char * value)2793c260e60Schristos int set_cred(const char *ifname, int id, const char *field, const char *value)
2803c260e60Schristos {
2813c260e60Schristos 	char buf[200];
2823c260e60Schristos 	snprintf(buf, sizeof(buf), "SET_CRED %d %s %s", id, field, value);
2833c260e60Schristos 	return wpa_command(ifname, buf);
2843c260e60Schristos }
2853c260e60Schristos 
2863c260e60Schristos 
set_cred_quoted(const char * ifname,int id,const char * field,const char * value)2873c260e60Schristos int set_cred_quoted(const char *ifname, int id, const char *field,
2883c260e60Schristos 		    const char *value)
2893c260e60Schristos {
2903c260e60Schristos 	char buf[200];
2913c260e60Schristos 	snprintf(buf, sizeof(buf), "SET_CRED %d %s \"%s\"",
2923c260e60Schristos 		 id, field, value);
2933c260e60Schristos 	return wpa_command(ifname, buf);
2943c260e60Schristos }
295