driver_common.c revision 6c0da2bb83f6915d8260912362692d1a742e057b
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);
821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return "UNKNOWN";
851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#undef E2S
861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
87661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt
88661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt
89661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidtconst char * channel_width_to_string(enum chan_width width)
90661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt{
91661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	switch (width) {
92661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	case CHAN_WIDTH_20_NOHT:
93661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		return "20 MHz (no HT)";
94661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	case CHAN_WIDTH_20:
95661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		return "20 MHz";
96661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	case CHAN_WIDTH_40:
97661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		return "40 MHz";
98661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	case CHAN_WIDTH_80:
99661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		return "80 MHz";
100661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	case CHAN_WIDTH_80P80:
101661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		return "80+80 MHz";
102661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	case CHAN_WIDTH_160:
103661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		return "160 MHz";
104661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	default:
105661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		return "unknown";
106661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	}
107661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt}
1086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
1096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
1106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtint ht_supported(const struct hostapd_hw_modes *mode)
1116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{
1126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (!(mode->flags & HOSTAPD_MODE_FLAG_HT_INFO_KNOWN)) {
1136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		/*
1146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		 * The driver did not indicate whether it supports HT. Assume
1156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		 * it does to avoid connection issues.
1166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		 */
1176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return 1;
1186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
1196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
1206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	/*
1216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	 * IEEE Std 802.11n-2009 20.1.1:
1226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	 * An HT non-AP STA shall support all EQM rates for one spatial stream.
1236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	 */
1246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	return mode->mcs_set[0] == 0xff;
1256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}
1266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
1276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
1286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtint vht_supported(const struct hostapd_hw_modes *mode)
1296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{
1306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (!(mode->flags & HOSTAPD_MODE_FLAG_VHT_INFO_KNOWN)) {
1316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		/*
1326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		 * The driver did not indicate whether it supports VHT. Assume
1336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		 * it does to avoid connection issues.
1346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		 */
1356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return 1;
1366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
1376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
1386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	/*
1396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	 * A VHT non-AP STA shall support MCS 0-7 for one spatial stream.
1406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	 * TODO: Verify if this complies with the standard
1416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	 */
1426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	return (mode->vht_mcs_set[0] & 0x3) != 3;
1436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}
1446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
1456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
1466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int wpa_check_wowlan_trigger(const char *start, const char *trigger,
1476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt				    int capa_trigger, u8 *param_trigger)
1486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{
1496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (os_strcmp(start, trigger) != 0)
1506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return 0;
1516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (!capa_trigger)
1526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return 0;
1536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
1546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	*param_trigger = 1;
1556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	return 1;
1566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}
1576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
1586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
1596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstruct wowlan_triggers *
1606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtwpa_get_wowlan_triggers(const char *wowlan_triggers,
1616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			const struct wpa_driver_capa *capa)
1626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{
1636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	struct wowlan_triggers *triggers;
1646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	char *start, *end, *buf;
1656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	int last;
1666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
1676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (!wowlan_triggers)
1686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return NULL;
1696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
1706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	buf = os_strdup(wowlan_triggers);
1716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (buf == NULL)
1726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return NULL;
1736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
1746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	triggers = os_zalloc(sizeof(*triggers));
1756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (triggers == NULL)
1766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		goto out;
1776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
1786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#define CHECK_TRIGGER(trigger) \
1796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	wpa_check_wowlan_trigger(start, #trigger,			\
1806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt				  capa->wowlan_triggers.trigger,	\
1816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt				  &triggers->trigger)
1826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
1836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	start = buf;
1846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	while (*start != '\0') {
1856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		while (isblank(*start))
1866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			start++;
1876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (*start == '\0')
1886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			break;
1896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		end = start;
1906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		while (!isblank(*end) && *end != '\0')
1916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			end++;
1926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		last = *end == '\0';
1936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		*end = '\0';
1946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
1956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (!CHECK_TRIGGER(any) &&
1966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		    !CHECK_TRIGGER(disconnect) &&
1976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		    !CHECK_TRIGGER(magic_pkt) &&
1986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		    !CHECK_TRIGGER(gtk_rekey_failure) &&
1996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		    !CHECK_TRIGGER(eap_identity_req) &&
2006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		    !CHECK_TRIGGER(four_way_handshake) &&
2016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		    !CHECK_TRIGGER(rfkill_release)) {
2026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			wpa_printf(MSG_DEBUG,
2036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt				   "Unknown/unsupported wowlan trigger '%s'",
2046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt				   start);
2056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			os_free(triggers);
2066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			triggers = NULL;
2076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			goto out;
2086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		}
2096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
2106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (last)
2116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			break;
2126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		start = end + 1;
2136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
2146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#undef CHECK_TRIGGER
2156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
2166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtout:
2176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	os_free(buf);
2186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	return triggers;
2196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}
220