11f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt/*
21f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Common driver-related functions
31f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Copyright (c) 2003-2011, Jouni Malinen <j@w1.fi>
41f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *
5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details.
71f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */
81f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
91f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "includes.h"
101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "utils/common.h"
111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "driver.h"
121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtvoid wpa_scan_results_free(struct wpa_scan_results *res)
141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	size_t i;
161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (res == NULL)
181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return;
191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	for (i = 0; i < res->num; i++)
211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		os_free(res->res[i]);
221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	os_free(res->res);
231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	os_free(res);
241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtconst char * event_to_string(enum wpa_event_type event)
281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#define E2S(n) case EVENT_ ## n: return #n
301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	switch (event) {
311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	E2S(ASSOC);
321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	E2S(DISASSOC);
331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	E2S(MICHAEL_MIC_FAILURE);
341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	E2S(SCAN_RESULTS);
351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	E2S(ASSOCINFO);
361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	E2S(INTERFACE_STATUS);
371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	E2S(PMKID_CANDIDATE);
381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	E2S(STKSTART);
391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	E2S(TDLS);
401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	E2S(FT_RESPONSE);
411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	E2S(IBSS_RSN_START);
421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	E2S(AUTH);
431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	E2S(DEAUTH);
441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	E2S(ASSOC_REJECT);
451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	E2S(AUTH_TIMED_OUT);
461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	E2S(ASSOC_TIMED_OUT);
471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	E2S(WPS_BUTTON_PUSHED);
481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	E2S(TX_STATUS);
491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	E2S(RX_FROM_UNKNOWN);
501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	E2S(RX_MGMT);
511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	E2S(REMAIN_ON_CHANNEL);
521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	E2S(CANCEL_REMAIN_ON_CHANNEL);
531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	E2S(RX_PROBE_REQ);
541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	E2S(NEW_STA);
551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	E2S(EAPOL_RX);
561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	E2S(SIGNAL_CHANGE);
571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	E2S(INTERFACE_ENABLED);
581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	E2S(INTERFACE_DISABLED);
591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	E2S(CHANNEL_LIST_CHANGED);
601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	E2S(INTERFACE_UNAVAILABLE);
611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	E2S(BEST_CHANNEL);
621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	E2S(UNPROT_DEAUTH);
631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	E2S(UNPROT_DISASSOC);
641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	E2S(STATION_LOW_ACK);
651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	E2S(IBSS_PEER_LOST);
661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	E2S(DRIVER_GTK_REKEY);
671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	E2S(SCHED_SCAN_STOPPED);
681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	E2S(DRIVER_CLIENT_POLL_OK);
691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	E2S(EAPOL_TX_STATUS);
7004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	E2S(CH_SWITCH);
7161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	E2S(WNM);
72f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	E2S(CONNECT_FAILED_REASON);
73ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	E2S(DFS_RADAR_DETECTED);
74ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	E2S(DFS_CAC_FINISHED);
75ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	E2S(DFS_CAC_ABORTED);
76ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	E2S(DFS_NOP_FINISHED);
77b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt	E2S(SURVEY);
78fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	E2S(SCAN_STARTED);
79cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	E2S(AVOID_FREQUENCIES);
806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	E2S(NEW_PEER_CANDIDATE);
816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	E2S(ACS_CHANNEL_SELECTED);
827f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt	E2S(DFS_CAC_STARTED);
831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return "UNKNOWN";
861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#undef E2S
871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
88661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt
89661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt
90661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidtconst char * channel_width_to_string(enum chan_width width)
91661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt{
92661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	switch (width) {
93661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	case CHAN_WIDTH_20_NOHT:
94661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		return "20 MHz (no HT)";
95661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	case CHAN_WIDTH_20:
96661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		return "20 MHz";
97661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	case CHAN_WIDTH_40:
98661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		return "40 MHz";
99661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	case CHAN_WIDTH_80:
100661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		return "80 MHz";
101661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	case CHAN_WIDTH_80P80:
102661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		return "80+80 MHz";
103661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	case CHAN_WIDTH_160:
104661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		return "160 MHz";
105661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	default:
106661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		return "unknown";
107661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	}
108661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt}
1096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
1106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
1116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtint ht_supported(const struct hostapd_hw_modes *mode)
1126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{
1136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (!(mode->flags & HOSTAPD_MODE_FLAG_HT_INFO_KNOWN)) {
1146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		/*
1156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		 * The driver did not indicate whether it supports HT. Assume
1166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		 * it does to avoid connection issues.
1176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		 */
1186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return 1;
1196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
1206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
1216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	/*
1226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	 * IEEE Std 802.11n-2009 20.1.1:
1236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	 * An HT non-AP STA shall support all EQM rates for one spatial stream.
1246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	 */
1256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	return mode->mcs_set[0] == 0xff;
1266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}
1276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
1286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
1296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtint vht_supported(const struct hostapd_hw_modes *mode)
1306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{
1316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (!(mode->flags & HOSTAPD_MODE_FLAG_VHT_INFO_KNOWN)) {
1326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		/*
1336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		 * The driver did not indicate whether it supports VHT. Assume
1346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		 * it does to avoid connection issues.
1356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		 */
1366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return 1;
1376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
1386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
1396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	/*
1406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	 * A VHT non-AP STA shall support MCS 0-7 for one spatial stream.
1416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	 * TODO: Verify if this complies with the standard
1426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	 */
1436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	return (mode->vht_mcs_set[0] & 0x3) != 3;
1446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}
1456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
1466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
1476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int wpa_check_wowlan_trigger(const char *start, const char *trigger,
1486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt				    int capa_trigger, u8 *param_trigger)
1496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{
1506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (os_strcmp(start, trigger) != 0)
1516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return 0;
1526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (!capa_trigger)
1536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return 0;
1546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
1556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	*param_trigger = 1;
1566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	return 1;
1576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}
1586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
1596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
1606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstruct wowlan_triggers *
1616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtwpa_get_wowlan_triggers(const char *wowlan_triggers,
1626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			const struct wpa_driver_capa *capa)
1636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{
1646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	struct wowlan_triggers *triggers;
1656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	char *start, *end, *buf;
1666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	int last;
1676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
1686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (!wowlan_triggers)
1696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return NULL;
1706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
1716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	buf = os_strdup(wowlan_triggers);
1726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (buf == NULL)
1736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return NULL;
1746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
1756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	triggers = os_zalloc(sizeof(*triggers));
1766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (triggers == NULL)
1776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		goto out;
1786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
1796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#define CHECK_TRIGGER(trigger) \
1806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	wpa_check_wowlan_trigger(start, #trigger,			\
1816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt				  capa->wowlan_triggers.trigger,	\
1826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt				  &triggers->trigger)
1836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
1846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	start = buf;
1856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	while (*start != '\0') {
1866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		while (isblank(*start))
1876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			start++;
1886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (*start == '\0')
1896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			break;
1906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		end = start;
1916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		while (!isblank(*end) && *end != '\0')
1926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			end++;
1936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		last = *end == '\0';
1946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		*end = '\0';
1956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
1966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (!CHECK_TRIGGER(any) &&
1976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		    !CHECK_TRIGGER(disconnect) &&
1986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		    !CHECK_TRIGGER(magic_pkt) &&
1996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		    !CHECK_TRIGGER(gtk_rekey_failure) &&
2006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		    !CHECK_TRIGGER(eap_identity_req) &&
2016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		    !CHECK_TRIGGER(four_way_handshake) &&
2026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		    !CHECK_TRIGGER(rfkill_release)) {
2036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			wpa_printf(MSG_DEBUG,
2046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt				   "Unknown/unsupported wowlan trigger '%s'",
2056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt				   start);
2066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			os_free(triggers);
2076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			triggers = NULL;
2086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			goto out;
2096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		}
2106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
2116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (last)
2126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			break;
2136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		start = end + 1;
2146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
2156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#undef CHECK_TRIGGER
2166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
2176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtout:
2186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	os_free(buf);
2196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	return triggers;
2206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}
221