static int parse_mntr_flags(int *_argc, char ***_argv,
			    struct nl_msg *msg)
{
	struct nl_msg *flags;
	int err = -ENOBUFS;
	enum nl80211_mntr_flags flag;
	int argc = *_argc;
	char **argv = *_argv;

	flags = nlmsg_alloc();
	if (!flags)
		return -ENOMEM;

	while (argc) {
		int ok = 0;
		for (flag = __NL80211_MNTR_FLAG_INVALID;
		     flag <= NL80211_MNTR_FLAG_MAX; flag++) {
			if (strcmp(*argv, mntr_flags[flag]) == 0) {
				ok = 1;
				/*
				 * This shouldn't be adding "flag" if that is
				 * zero, but due to a problem in the kernel's
				 * nl80211 code (using NLA_NESTED policy) it
				 * will reject an empty nested attribute but
				 * not one that contains an invalid attribute
				 */
				NLA_PUT_FLAG(flags, flag);
				break;
			}
		}
		if (!ok) {
			err = -EINVAL;
			goto out;
		}
		argc--;
		argv++;
	}

	nla_put_nested(msg, NL80211_ATTR_MNTR_FLAGS, flags);
	err = 0;
 nla_put_failure:
 out:
	nlmsg_free(flags);

	*_argc = argc;
	*_argv = argv;

	return err;
}
示例#2
0
// Has to be a separate function because of gotos, ew
void nl80211_parseflags(int nflags, int *in_flags, struct nl_msg *msg) {
#ifdef HAVE_LINUX_NETLINK
	struct nl_msg *flags;
	unsigned int x;
	enum nl80211_mntr_flags flag = NL80211_MNTR_FLAG_MAX;

	if ((flags = nlmsg_alloc()) == NULL) {
		return;
	}

	for (x = 0; x < nflags; x++) {
		switch (in_flags[x]) {
			case nl80211_mntr_flag_none:
				continue;
				break;
			case nl80211_mntr_flag_fcsfail:
				flag = NL80211_MNTR_FLAG_FCSFAIL;
				break;
			case nl80211_mntr_flag_plcpfail:
				flag = NL80211_MNTR_FLAG_PLCPFAIL;
				break;
			case nl80211_mntr_flag_control:
				flag = NL80211_MNTR_FLAG_CONTROL;
				break;
			case nl80211_mntr_flag_otherbss:
				flag = NL80211_MNTR_FLAG_OTHER_BSS;
				break;
			case nl80211_mntr_flag_cookframe:
				flag = NL80211_MNTR_FLAG_COOK_FRAMES;
				break;
		}

		NLA_PUT_FLAG(flags, flag);
	}

	nla_put_nested(msg, NL80211_ATTR_MNTR_FLAGS, flags);

nla_put_failure:
	nlmsg_free(flags);
#endif
}
示例#3
0
static int handle_wowlan_enable(struct nl80211_state *state, struct nl_cb *cb,
				struct nl_msg *msg, int argc, char **argv,
				enum id_input id)
{
	struct nlattr *wowlan, *pattern;
	struct nl_msg *patterns = NULL;
	enum {
		PS_REG,
		PS_PAT,
	} parse_state = PS_REG;
	int err = -ENOBUFS;
	unsigned char *pat, *mask;
	size_t patlen;
	int patnum = 0;

	wowlan = nla_nest_start(msg, NL80211_ATTR_WOWLAN_TRIGGERS);
	if (!wowlan)
		return -ENOBUFS;

	while (argc) {
		switch (parse_state) {
		case PS_REG:
			if (strcmp(argv[0], "any") == 0)
				NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_ANY);
			else if (strcmp(argv[0], "disconnect") == 0)
				NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_DISCONNECT);
			else if (strcmp(argv[0], "magic-packet") == 0)
				NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT);
			else if (strcmp(argv[0], "gtk-rekey-failure") == 0)
				NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE);
			else if (strcmp(argv[0], "eap-identity-request") == 0)
				NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST);
			else if (strcmp(argv[0], "4way-handshake") == 0)
				NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE);
			else if (strcmp(argv[0], "rfkill-release") == 0)
				NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE);
			else if (strcmp(argv[0], "patterns") == 0) {
				parse_state = PS_PAT;
				patterns = nlmsg_alloc();
				if (!patterns) {
					err = -ENOMEM;
					goto nla_put_failure;
				}
			} else {
				err = 1;
				goto nla_put_failure;
			}
			break;
		case PS_PAT:
			if (parse_hex_mask(argv[0], &pat, &patlen, &mask)) {
				err = 1;
				goto nla_put_failure;
			}
			pattern = nla_nest_start(patterns, ++patnum);
			NLA_PUT(patterns, NL80211_WOWLAN_PKTPAT_MASK,
				DIV_ROUND_UP(patlen, 8), mask);
			NLA_PUT(patterns, NL80211_WOWLAN_PKTPAT_PATTERN,
				patlen, pat);
			nla_nest_end(patterns, pattern);
			free(mask);
			free(pat);
			break;
		}
		argv++;
		argc--;
	}

	if (patterns)
		nla_put_nested(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN,
				patterns);

	nla_nest_end(msg, wowlan);
	err = 0;
 nla_put_failure:
	nlmsg_free(patterns);
	return err;
}
示例#4
0
文件: wowlan.c 项目: resfi/resfi
static int handle_wowlan_enable(struct nl80211_state *state,
				struct nl_msg *msg, int argc, char **argv,
				enum id_input id)
{
	struct nlattr *wowlan, *pattern;
	struct nl_msg *patterns = NULL;
	enum {
		PS_REG,
		PS_PAT,
	} parse_state = PS_REG;
	int err = -ENOBUFS;
	unsigned char *pat, *mask;
	size_t patlen;
	int patnum = 0, pkt_offset;
	char *eptr, *value1, *value2, *sptr = NULL;

	wowlan = nla_nest_start(msg, NL80211_ATTR_WOWLAN_TRIGGERS);
	if (!wowlan)
		return -ENOBUFS;

	while (argc) {
		switch (parse_state) {
		case PS_REG:
			if (strcmp(argv[0], "any") == 0)
				NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_ANY);
			else if (strcmp(argv[0], "disconnect") == 0)
				NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_DISCONNECT);
			else if (strcmp(argv[0], "magic-packet") == 0)
				NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT);
			else if (strcmp(argv[0], "gtk-rekey-failure") == 0)
				NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE);
			else if (strcmp(argv[0], "eap-identity-request") == 0)
				NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST);
			else if (strcmp(argv[0], "4way-handshake") == 0)
				NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE);
			else if (strcmp(argv[0], "rfkill-release") == 0)
				NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE);
			else if (strcmp(argv[0], "tcp") == 0) {
				argv++;
				argc--;
				if (!argc) {
					err = 1;
					goto nla_put_failure;
				}
				err = wowlan_parse_tcp_file(msg, argv[0]);
				if (err)
					goto nla_put_failure;
			} else if (strcmp(argv[0], "patterns") == 0) {
				parse_state = PS_PAT;
				patterns = nlmsg_alloc();
				if (!patterns) {
					err = -ENOMEM;
					goto nla_put_failure;
				}
			} else if (strcmp(argv[0], "net-detect") == 0) {
				argv++;
				argc--;
				if (!argc) {
					err = 1;
					goto nla_put_failure;
				}
				err = wowlan_parse_net_detect(msg, &argc, &argv);
				if (err)
					goto nla_put_failure;
				continue;
			} else {
				err = 1;
				goto nla_put_failure;
			}
			break;
		case PS_PAT:
			value1 = strtok_r(argv[0], "+", &sptr);
			value2 = strtok_r(NULL, "+", &sptr);

			if (!value2) {
				pkt_offset = 0;
				value2 = value1;
			} else {
				pkt_offset = strtoul(value1, &eptr, 10);
				if (eptr != value1 + strlen(value1)) {
					err = 1;
					goto nla_put_failure;
				}
			}

			if (parse_hex_mask(value2, &pat, &patlen, &mask)) {
				err = 1;
				goto nla_put_failure;
			}

			pattern = nla_nest_start(patterns, ++patnum);
			NLA_PUT(patterns, NL80211_PKTPAT_MASK,
				DIV_ROUND_UP(patlen, 8), mask);
			NLA_PUT(patterns, NL80211_PKTPAT_PATTERN, patlen, pat);
			NLA_PUT_U32(patterns, NL80211_PKTPAT_OFFSET,
				    pkt_offset);
			nla_nest_end(patterns, pattern);
			free(mask);
			free(pat);
			break;
		}
		argv++;
		argc--;
	}

	if (patterns)
		nla_put_nested(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN,
				patterns);

	nla_nest_end(msg, wowlan);
	err = 0;
 nla_put_failure:
	nlmsg_free(patterns);
	return err;
}
static int nl80211_set_wowlan_triggers(struct i802_bss *bss, int enable)
{
	struct nl_msg *msg, *pats = NULL;
	struct wpa_driver_nl80211_data *drv = bss->drv;
	struct nlattr *wowtrig, *pat;
	int i, ret = -1;
	int filters;

	bss->drv->wowlan_enabled = !!enable;

	msg = nlmsg_alloc();
	if (!msg)
		return -ENOMEM;

	genlmsg_put(msg, 0, 0, drv->global->nl80211_id, 0,
		    0, NL80211_CMD_SET_WOWLAN, 0);

	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->drv->first_bss.ifindex);
	wowtrig = nla_nest_start(msg, NL80211_ATTR_WOWLAN_TRIGGERS);

	if (!wowtrig) {
		ret = -ENOBUFS;
		goto nla_put_failure;
	}

	if (!enable) {
		NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_ANY);
	} else {
		pats = nlmsg_alloc();
		if (!pats) {
			ret = -ENOMEM;
			goto nla_put_failure;
		}

		/* In ginger filter 0 and 1 are always set but in ICS we
		 * only enable unicast. Make sure to always set it, otherwise
		 * unicast packets will be dropped.
		 * bcast packets are dropped and handled by the firmware */

		filters = bss->drv->wowlan_triggers |= 1;

		for (i = 0; i < NR_RX_FILTERS; i++) {
			if (filters & (1 << i)) {
				struct rx_filter *rx_filter = &rx_filters[i];
				int patnr = 1;
				u8 *pattern = nl80211_rx_filter_get_pattern(rx_filter,bss);

				if (!pattern)
					continue;

				pat = nla_nest_start(pats, patnr++);
				NLA_PUT(pats, NL80211_WOWLAN_PKTPAT_MASK,
					rx_filter->mask_len,
					rx_filter->mask);
				NLA_PUT(pats, NL80211_WOWLAN_PKTPAT_PATTERN,
					rx_filter->pattern_len,
					pattern);

				nla_nest_end(pats, pat);
			}
		}
	}

	if (pats)
		nla_put_nested(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN, pats);

	nla_nest_end(msg, wowtrig);

	ret = send_and_recv_msgs(bss->drv, msg, NULL, NULL);

	if (ret < 0)
		wpa_printf(MSG_ERROR, "Failed to set WoWLAN trigger:%d\n", ret);

	if (pats)
		nlmsg_free(pats);

	return 0;

nla_put_failure:
	nlmsg_free(msg);
	return ret;
}
示例#6
0
文件: util.c 项目: greearb/iw-ct
int parse_keys(struct nl_msg *msg, char **argv[], int *argc)
{
	struct nlattr *keys;
	int i = 0;
	bool have_default = false;
	char *arg = **argv;
	char keybuf[13];
	int pos = 0;

	if (!*argc)
		return 1;

	if (!memcmp(&arg[pos], "psk", 3)) {
		char psk_keybuf[32];
		int cipher_suite, akm_suite;

		if (*argc < 4)
			goto explain;

		pos+=3;
		if (arg[pos] != ':')
			goto explain;
		pos++;

		NLA_PUT_U32(msg, NL80211_ATTR_WPA_VERSIONS, NL80211_WPA_VERSION_2);

		if (strlen(&arg[pos]) != (sizeof(psk_keybuf) * 2) || !hex2bin(&arg[pos], psk_keybuf)) {
			printf("Bad PSK\n");
			return -EINVAL;
		}

		NLA_PUT(msg, NL80211_ATTR_PMK, 32, psk_keybuf);
		NLA_PUT_U32(msg, NL80211_ATTR_AUTH_TYPE, NL80211_AUTHTYPE_OPEN_SYSTEM);

		*argv += 1;
		*argc -= 1;
		arg = **argv;

		akm_suite = parse_akm_suite(arg);
		if (akm_suite < 0)
			goto explain;

		NLA_PUT_U32(msg, NL80211_ATTR_AKM_SUITES, akm_suite);

		*argv += 1;
		*argc -= 1;
		arg = **argv;

		cipher_suite = parse_cipher_suite(arg);
		if (cipher_suite < 0)
			goto explain;

		NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE, cipher_suite);

		*argv += 1;
		*argc -= 1;
		arg = **argv;

		cipher_suite = parse_cipher_suite(arg);
		if (cipher_suite < 0)
			goto explain;

		NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP, cipher_suite);

		*argv += 1;
		*argc -= 1;
		return 0;
	}

	NLA_PUT_FLAG(msg, NL80211_ATTR_PRIVACY);

	keys = nla_nest_start(msg, NL80211_ATTR_KEYS);
	if (!keys)
		return -ENOBUFS;

	do {
		int keylen;
		struct nlattr *key = nla_nest_start(msg, ++i);
		char *keydata;

		arg = **argv;
		pos = 0;

		if (!key)
			return -ENOBUFS;

		if (arg[pos] == 'd') {
			NLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT);
			pos++;
			if (arg[pos] == ':')
				pos++;
			have_default = true;
		}

		if (!isdigit(arg[pos]))
			goto explain;
		NLA_PUT_U8(msg, NL80211_KEY_IDX, arg[pos++] - '0');
		if (arg[pos++] != ':')
			goto explain;
		keydata = arg + pos;
		switch (strlen(keydata)) {
		case 10:
			keydata = hex2bin(keydata, keybuf);
			/* fall through */
		case 5:
			NLA_PUT_U32(msg, NL80211_KEY_CIPHER, 0x000FAC01);
			keylen = 5;
			break;
		case 26:
			keydata = hex2bin(keydata, keybuf);
			/* fall through */
		case 13:
			NLA_PUT_U32(msg, NL80211_KEY_CIPHER, 0x000FAC05);
			keylen = 13;
			break;
		default:
			goto explain;
		}

		if (!keydata)
			goto explain;

		NLA_PUT(msg, NL80211_KEY_DATA, keylen, keydata);

		*argv += 1;
		*argc -= 1;

		/* one key should be TX key */
		if (!have_default && !*argc)
			NLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT);

		nla_nest_end(msg, key);
	} while (*argc);

	nla_nest_end(msg, keys);

	return 0;
 nla_put_failure:
	return -ENOBUFS;
 explain:
	fprintf(stderr, "key must be [d:]index:data where\n"
			"  'd:'     means default (transmit) key\n"
			"  'index:' is a single digit (0-3)\n"
			"  'data'   must be 5 or 13 ascii chars\n"
			"           or 10 or 26 hex digits\n"
			"for example: d:2:6162636465 is the same as d:2:abcde\n"
			"or psk:data <AKM Suite> <pairwise CIPHER> <groupwise CIPHER> where\n"
			"  'data' is the PSK (output of wpa_passphrase and the CIPHER can be CCMP or GCMP\n"
			"for example: psk:0123456789abcdef PSK CCMP CCMP\n"
			"The allowed AKM suites are PSK, FT/PSK, PSK/SHA-256\n"
			"The allowed Cipher suites are TKIP, CCMP, GCMP, GCMP-256, CCMP-256\n");
	return 2;
}