xref: /freebsd/contrib/wpa/src/common/wpa_helpers.c (revision 67350cb56a69468c118bd4ccf6e361b7ebfa9eb4)
15b9c547cSRui Paulo /*
25b9c547cSRui Paulo  * wpa_supplicant ctrl_iface helpers
35b9c547cSRui Paulo  * Copyright (c) 2010-2011, Atheros Communications, Inc.
45b9c547cSRui Paulo  * Copyright (c) 2011-2012, Qualcomm Atheros, Inc.
55b9c547cSRui Paulo  *
65b9c547cSRui Paulo  * This software may be distributed under the terms of the BSD license.
75b9c547cSRui Paulo  * See README for more details.
85b9c547cSRui Paulo  */
95b9c547cSRui Paulo 
105b9c547cSRui Paulo #include "includes.h"
115b9c547cSRui Paulo #include <time.h>
125b9c547cSRui Paulo 
135b9c547cSRui Paulo #include "common.h"
145b9c547cSRui Paulo #include "wpa_ctrl.h"
155b9c547cSRui Paulo #include "wpa_helpers.h"
165b9c547cSRui Paulo 
175b9c547cSRui Paulo 
185b9c547cSRui Paulo char *wpas_ctrl_path = "/var/run/wpa_supplicant/";
195b9c547cSRui Paulo static int default_timeout = 60;
205b9c547cSRui Paulo 
215b9c547cSRui Paulo 
wpa_open_ctrl(const char * ifname)225b9c547cSRui Paulo static struct wpa_ctrl * wpa_open_ctrl(const char *ifname)
235b9c547cSRui Paulo {
245b9c547cSRui Paulo 	char buf[128];
255b9c547cSRui Paulo 	struct wpa_ctrl *ctrl;
265b9c547cSRui Paulo 
275b9c547cSRui Paulo 	os_snprintf(buf, sizeof(buf), "%s%s", wpas_ctrl_path, ifname);
285b9c547cSRui Paulo 	ctrl = wpa_ctrl_open(buf);
295b9c547cSRui Paulo 	if (ctrl == NULL)
305b9c547cSRui Paulo 		printf("wpa_command: wpa_ctrl_open(%s) failed\n", buf);
315b9c547cSRui Paulo 	return ctrl;
325b9c547cSRui Paulo }
335b9c547cSRui Paulo 
345b9c547cSRui Paulo 
wpa_command(const char * ifname,const char * cmd)355b9c547cSRui Paulo int wpa_command(const char *ifname, const char *cmd)
365b9c547cSRui Paulo {
375b9c547cSRui Paulo 	struct wpa_ctrl *ctrl;
385b9c547cSRui Paulo 	char buf[128];
395b9c547cSRui Paulo 	size_t len;
405b9c547cSRui Paulo 
415b9c547cSRui Paulo 	printf("wpa_command(ifname='%s', cmd='%s')\n", ifname, cmd);
425b9c547cSRui Paulo 	ctrl = wpa_open_ctrl(ifname);
435b9c547cSRui Paulo 	if (ctrl == NULL)
445b9c547cSRui Paulo 		return -1;
455b9c547cSRui Paulo 	len = sizeof(buf);
465b9c547cSRui Paulo 	if (wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len, NULL) < 0) {
475b9c547cSRui Paulo 		printf("wpa_command: wpa_ctrl_request failed\n");
485b9c547cSRui Paulo 		wpa_ctrl_close(ctrl);
495b9c547cSRui Paulo 		return -1;
505b9c547cSRui Paulo 	}
515b9c547cSRui Paulo 	wpa_ctrl_close(ctrl);
525b9c547cSRui Paulo 	buf[len] = '\0';
535b9c547cSRui Paulo 	if (strncmp(buf, "FAIL", 4) == 0) {
545b9c547cSRui Paulo 		printf("wpa_command: Command failed (FAIL received)\n");
555b9c547cSRui Paulo 		return -1;
565b9c547cSRui Paulo 	}
575b9c547cSRui Paulo 	return 0;
585b9c547cSRui Paulo }
595b9c547cSRui Paulo 
605b9c547cSRui Paulo 
wpa_command_resp(const char * ifname,const char * cmd,char * resp,size_t resp_size)615b9c547cSRui Paulo int wpa_command_resp(const char *ifname, const char *cmd,
625b9c547cSRui Paulo 		     char *resp, size_t resp_size)
635b9c547cSRui Paulo {
645b9c547cSRui Paulo 	struct wpa_ctrl *ctrl;
655b9c547cSRui Paulo 	size_t len;
665b9c547cSRui Paulo 
675b9c547cSRui Paulo 	printf("wpa_command(ifname='%s', cmd='%s')\n", ifname, cmd);
685b9c547cSRui Paulo 	ctrl = wpa_open_ctrl(ifname);
695b9c547cSRui Paulo 	if (ctrl == NULL)
705b9c547cSRui Paulo 		return -1;
715b9c547cSRui Paulo 	len = resp_size;
725b9c547cSRui Paulo 	if (wpa_ctrl_request(ctrl, cmd, strlen(cmd), resp, &len, NULL) < 0) {
735b9c547cSRui Paulo 		printf("wpa_command: wpa_ctrl_request failed\n");
745b9c547cSRui Paulo 		wpa_ctrl_close(ctrl);
755b9c547cSRui Paulo 		return -1;
765b9c547cSRui Paulo 	}
775b9c547cSRui Paulo 	wpa_ctrl_close(ctrl);
785b9c547cSRui Paulo 	resp[len] = '\0';
795b9c547cSRui Paulo 	return 0;
805b9c547cSRui Paulo }
815b9c547cSRui Paulo 
825b9c547cSRui Paulo 
open_wpa_mon(const char * ifname)835b9c547cSRui Paulo struct wpa_ctrl * open_wpa_mon(const char *ifname)
845b9c547cSRui Paulo {
855b9c547cSRui Paulo 	struct wpa_ctrl *ctrl;
865b9c547cSRui Paulo 
875b9c547cSRui Paulo 	ctrl = wpa_open_ctrl(ifname);
885b9c547cSRui Paulo 	if (ctrl == NULL)
895b9c547cSRui Paulo 		return NULL;
905b9c547cSRui Paulo 	if (wpa_ctrl_attach(ctrl) < 0) {
915b9c547cSRui Paulo 		wpa_ctrl_close(ctrl);
925b9c547cSRui Paulo 		return NULL;
935b9c547cSRui Paulo 	}
945b9c547cSRui Paulo 
955b9c547cSRui Paulo 	return ctrl;
965b9c547cSRui Paulo }
975b9c547cSRui Paulo 
985b9c547cSRui Paulo 
get_wpa_cli_event2(struct wpa_ctrl * mon,const char * event,const char * event2,char * buf,size_t buf_size)995b9c547cSRui Paulo int get_wpa_cli_event2(struct wpa_ctrl *mon,
1005b9c547cSRui Paulo 		       const char *event, const char *event2,
1015b9c547cSRui Paulo 		       char *buf, size_t buf_size)
1025b9c547cSRui Paulo {
1035b9c547cSRui Paulo 	int fd, ret;
1045b9c547cSRui Paulo 	fd_set rfd;
1055b9c547cSRui Paulo 	char *pos;
1065b9c547cSRui Paulo 	struct timeval tv;
1075b9c547cSRui Paulo 	time_t start, now;
1085b9c547cSRui Paulo 
1095b9c547cSRui Paulo 	printf("Waiting for wpa_cli event %s\n", event);
1105b9c547cSRui Paulo 	fd = wpa_ctrl_get_fd(mon);
1115b9c547cSRui Paulo 	if (fd < 0)
1125b9c547cSRui Paulo 		return -1;
1135b9c547cSRui Paulo 
1145b9c547cSRui Paulo 	time(&start);
1155b9c547cSRui Paulo 	while (1) {
1165b9c547cSRui Paulo 		size_t len;
1175b9c547cSRui Paulo 
1185b9c547cSRui Paulo 		FD_ZERO(&rfd);
1195b9c547cSRui Paulo 		FD_SET(fd, &rfd);
1205b9c547cSRui Paulo 		tv.tv_sec = default_timeout;
1215b9c547cSRui Paulo 		tv.tv_usec = 0;
1225b9c547cSRui Paulo 		ret = select(fd + 1, &rfd, NULL, NULL, &tv);
1235b9c547cSRui Paulo 		if (ret == 0) {
1245b9c547cSRui Paulo 			printf("Timeout on waiting for event %s\n", event);
1255b9c547cSRui Paulo 			return -1;
1265b9c547cSRui Paulo 		}
1275b9c547cSRui Paulo 		if (ret < 0) {
1285b9c547cSRui Paulo 			printf("select: %s\n", strerror(errno));
1295b9c547cSRui Paulo 			return -1;
1305b9c547cSRui Paulo 		}
1315b9c547cSRui Paulo 		len = buf_size;
1325b9c547cSRui Paulo 		if (wpa_ctrl_recv(mon, buf, &len) < 0) {
1335b9c547cSRui Paulo 			printf("Failure while waiting for event %s\n", event);
1345b9c547cSRui Paulo 			return -1;
1355b9c547cSRui Paulo 		}
1365b9c547cSRui Paulo 		if (len == buf_size)
1375b9c547cSRui Paulo 			len--;
1385b9c547cSRui Paulo 		buf[len] = '\0';
1395b9c547cSRui Paulo 
1405b9c547cSRui Paulo 		pos = strchr(buf, '>');
1415b9c547cSRui Paulo 		if (pos &&
1425b9c547cSRui Paulo 		    (strncmp(pos + 1, event, strlen(event)) == 0 ||
1435b9c547cSRui Paulo 		     (event2 &&
1445b9c547cSRui Paulo 		      strncmp(pos + 1, event2, strlen(event2)) == 0)))
1455b9c547cSRui Paulo 			return 0; /* Event found */
1465b9c547cSRui Paulo 
1475b9c547cSRui Paulo 		time(&now);
1485b9c547cSRui Paulo 		if ((int) (now - start) > default_timeout) {
1495b9c547cSRui Paulo 			printf("Timeout on waiting for event %s\n", event);
1505b9c547cSRui Paulo 			return -1;
1515b9c547cSRui Paulo 		}
1525b9c547cSRui Paulo 	}
1535b9c547cSRui Paulo }
1545b9c547cSRui Paulo 
1555b9c547cSRui Paulo 
get_wpa_cli_event(struct wpa_ctrl * mon,const char * event,char * buf,size_t buf_size)1565b9c547cSRui Paulo int get_wpa_cli_event(struct wpa_ctrl *mon,
1575b9c547cSRui Paulo 		      const char *event, char *buf, size_t buf_size)
1585b9c547cSRui Paulo {
1595b9c547cSRui Paulo 	return get_wpa_cli_event2(mon, event, NULL, buf, buf_size);
1605b9c547cSRui Paulo }
1615b9c547cSRui Paulo 
1625b9c547cSRui Paulo 
get_wpa_status(const char * ifname,const char * field,char * obuf,size_t obuf_size)1635b9c547cSRui Paulo int get_wpa_status(const char *ifname, const char *field, char *obuf,
1645b9c547cSRui Paulo 		   size_t obuf_size)
1655b9c547cSRui Paulo {
1665b9c547cSRui Paulo 	struct wpa_ctrl *ctrl;
1675b9c547cSRui Paulo 	char buf[4096];
1685b9c547cSRui Paulo 	char *pos, *end;
1695b9c547cSRui Paulo 	size_t len, flen;
1705b9c547cSRui Paulo 
1715b9c547cSRui Paulo 	ctrl = wpa_open_ctrl(ifname);
1725b9c547cSRui Paulo 	if (ctrl == NULL)
1735b9c547cSRui Paulo 		return -1;
1745b9c547cSRui Paulo 	len = sizeof(buf);
175780fb4a2SCy Schubert 	if (wpa_ctrl_request(ctrl, "STATUS-NO_EVENTS", 16, buf, &len,
176780fb4a2SCy Schubert 			     NULL) < 0) {
1775b9c547cSRui Paulo 		wpa_ctrl_close(ctrl);
1785b9c547cSRui Paulo 		return -1;
1795b9c547cSRui Paulo 	}
1805b9c547cSRui Paulo 	wpa_ctrl_close(ctrl);
1815b9c547cSRui Paulo 	buf[len] = '\0';
1825b9c547cSRui Paulo 
1835b9c547cSRui Paulo 	flen = strlen(field);
1845b9c547cSRui Paulo 	pos = buf;
1855b9c547cSRui Paulo 	while (pos + flen < buf + len) {
1865b9c547cSRui Paulo 		if (pos > buf) {
1875b9c547cSRui Paulo 			if (*pos != '\n') {
1885b9c547cSRui Paulo 				pos++;
1895b9c547cSRui Paulo 				continue;
1905b9c547cSRui Paulo 			}
1915b9c547cSRui Paulo 			pos++;
1925b9c547cSRui Paulo 		}
1935b9c547cSRui Paulo 		if (strncmp(pos, field, flen) != 0 || pos[flen] != '=') {
1945b9c547cSRui Paulo 			pos++;
1955b9c547cSRui Paulo 			continue;
1965b9c547cSRui Paulo 		}
1975b9c547cSRui Paulo 		pos += flen + 1;
1985b9c547cSRui Paulo 		end = strchr(pos, '\n');
1995b9c547cSRui Paulo 		if (end == NULL)
2005b9c547cSRui Paulo 			return -1;
2015b9c547cSRui Paulo 		*end++ = '\0';
2025b9c547cSRui Paulo 		if (end - pos > (int) obuf_size)
2035b9c547cSRui Paulo 			return -1;
2045b9c547cSRui Paulo 		memcpy(obuf, pos, end - pos);
2055b9c547cSRui Paulo 		return 0;
2065b9c547cSRui Paulo 	}
2075b9c547cSRui Paulo 
2085b9c547cSRui Paulo 	return -1;
2095b9c547cSRui Paulo }
2105b9c547cSRui Paulo 
2115b9c547cSRui Paulo 
wait_ip_addr(const char * ifname,int timeout)2125b9c547cSRui Paulo int wait_ip_addr(const char *ifname, int timeout)
2135b9c547cSRui Paulo {
2145b9c547cSRui Paulo 	char ip[30];
2155b9c547cSRui Paulo 	int count = timeout;
2165b9c547cSRui Paulo 	struct wpa_ctrl *ctrl;
2175b9c547cSRui Paulo 
2185b9c547cSRui Paulo 	while (count > 0) {
2195b9c547cSRui Paulo 		printf("%s: ifname='%s' - %d seconds remaining\n",
2205b9c547cSRui Paulo 		       __func__, ifname, count);
2215b9c547cSRui Paulo 		count--;
2225b9c547cSRui Paulo 		if (get_wpa_status(ifname, "ip_address", ip, sizeof(ip)) == 0
2235b9c547cSRui Paulo 		    && strlen(ip) > 0) {
2245b9c547cSRui Paulo 			printf("IP address found: '%s'\n", ip);
225*85732ac8SCy Schubert 			if (strncmp(ip, "169.254.", 8) != 0)
2265b9c547cSRui Paulo 				return 0;
2275b9c547cSRui Paulo 		}
2285b9c547cSRui Paulo 		ctrl = wpa_open_ctrl(ifname);
2295b9c547cSRui Paulo 		if (ctrl == NULL)
2305b9c547cSRui Paulo 			return -1;
2315b9c547cSRui Paulo 		wpa_ctrl_close(ctrl);
2325b9c547cSRui Paulo 		sleep(1);
2335b9c547cSRui Paulo 	}
2345b9c547cSRui Paulo 	printf("%s: Could not get IP address for ifname='%s'", __func__,
2355b9c547cSRui Paulo 	       ifname);
2365b9c547cSRui Paulo 	return -1;
2375b9c547cSRui Paulo }
2385b9c547cSRui Paulo 
2395b9c547cSRui Paulo 
add_network(const char * ifname)2405b9c547cSRui Paulo int add_network(const char *ifname)
2415b9c547cSRui Paulo {
2425b9c547cSRui Paulo 	char res[30];
2435b9c547cSRui Paulo 
2445b9c547cSRui Paulo 	if (wpa_command_resp(ifname, "ADD_NETWORK", res, sizeof(res)) < 0)
2455b9c547cSRui Paulo 		return -1;
2465b9c547cSRui Paulo 	return atoi(res);
2475b9c547cSRui Paulo }
2485b9c547cSRui Paulo 
2495b9c547cSRui Paulo 
set_network(const char * ifname,int id,const char * field,const char * value)2505b9c547cSRui Paulo int set_network(const char *ifname, int id, const char *field,
2515b9c547cSRui Paulo 		const char *value)
2525b9c547cSRui Paulo {
2535b9c547cSRui Paulo 	char buf[200];
2545b9c547cSRui Paulo 	snprintf(buf, sizeof(buf), "SET_NETWORK %d %s %s", id, field, value);
2555b9c547cSRui Paulo 	return wpa_command(ifname, buf);
2565b9c547cSRui Paulo }
2575b9c547cSRui Paulo 
2585b9c547cSRui Paulo 
set_network_quoted(const char * ifname,int id,const char * field,const char * value)2595b9c547cSRui Paulo int set_network_quoted(const char *ifname, int id, const char *field,
2605b9c547cSRui Paulo 		       const char *value)
2615b9c547cSRui Paulo {
2625b9c547cSRui Paulo 	char buf[200];
2635b9c547cSRui Paulo 	snprintf(buf, sizeof(buf), "SET_NETWORK %d %s \"%s\"",
2645b9c547cSRui Paulo 		 id, field, value);
2655b9c547cSRui Paulo 	return wpa_command(ifname, buf);
2665b9c547cSRui Paulo }
2675b9c547cSRui Paulo 
2685b9c547cSRui Paulo 
add_cred(const char * ifname)2695b9c547cSRui Paulo int add_cred(const char *ifname)
2705b9c547cSRui Paulo {
2715b9c547cSRui Paulo 	char res[30];
2725b9c547cSRui Paulo 
2735b9c547cSRui Paulo 	if (wpa_command_resp(ifname, "ADD_CRED", res, sizeof(res)) < 0)
2745b9c547cSRui Paulo 		return -1;
2755b9c547cSRui Paulo 	return atoi(res);
2765b9c547cSRui Paulo }
2775b9c547cSRui Paulo 
2785b9c547cSRui Paulo 
set_cred(const char * ifname,int id,const char * field,const char * value)2795b9c547cSRui Paulo int set_cred(const char *ifname, int id, const char *field, const char *value)
2805b9c547cSRui Paulo {
2815b9c547cSRui Paulo 	char buf[200];
2825b9c547cSRui Paulo 	snprintf(buf, sizeof(buf), "SET_CRED %d %s %s", id, field, value);
2835b9c547cSRui Paulo 	return wpa_command(ifname, buf);
2845b9c547cSRui Paulo }
2855b9c547cSRui Paulo 
2865b9c547cSRui Paulo 
set_cred_quoted(const char * ifname,int id,const char * field,const char * value)2875b9c547cSRui Paulo int set_cred_quoted(const char *ifname, int id, const char *field,
2885b9c547cSRui Paulo 		    const char *value)
2895b9c547cSRui Paulo {
2905b9c547cSRui Paulo 	char buf[200];
2915b9c547cSRui Paulo 	snprintf(buf, sizeof(buf), "SET_CRED %d %s \"%s\"",
2925b9c547cSRui Paulo 		 id, field, value);
2935b9c547cSRui Paulo 	return wpa_command(ifname, buf);
2945b9c547cSRui Paulo }
295