1 /* 1 2 * This file implement the Wireless Extensions 3 * 4 * Authors : Jean Tourrilhes - HPL - <jt@hp 5 * Copyright (c) 1997-2007 Jean Tourrilhes, Al 6 * 7 * (As all part of the Linux kernel, this file 8 */ 9 10 #include <linux/wireless.h> 11 #include <linux/netdevice.h> 12 #include <linux/etherdevice.h> 13 #include <linux/export.h> 14 #include <net/iw_handler.h> 15 #include <net/arp.h> 16 #include <net/wext.h> 17 18 static inline struct iw_spy_data *get_spydata( 19 { 20 /* This is the new way */ 21 if (dev->wireless_data) 22 return dev->wireless_data->spy 23 return NULL; 24 } 25 26 int iw_handler_set_spy(struct net_device * 27 struct iw_request_info 28 union iwreq_data * 29 char * 30 { 31 struct iw_spy_data * spydata = get_ 32 struct sockaddr * address = (str 33 34 /* Make sure driver is not buggy or us 35 if (!spydata) 36 return -EOPNOTSUPP; 37 38 /* Disable spy collection while we cop 39 * While we copy addresses, any call t 40 * will NOP. This is OK, as anyway the 41 spydata->spy_number = 0; 42 43 /* We want to operate without locking, 44 * most likely will happen in the inte 45 * have its own locking constraints an 46 * The rtnl_lock() make sure we don't 47 * This make sure wireless_spy_update( 48 * is temporarily disabled. */ 49 smp_wmb(); 50 51 /* Are there are addresses to copy? */ 52 if (wrqu->data.length > 0) { 53 int i; 54 55 /* Copy addresses */ 56 for (i = 0; i < wrqu->data.len 57 memcpy(spydata->spy_ad 58 ETH_ALEN); 59 /* Reset stats */ 60 memset(spydata->spy_stat, 0, 61 sizeof(struct iw_qualit 62 } 63 64 /* Make sure above is updated before r 65 smp_wmb(); 66 67 /* Enable addresses */ 68 spydata->spy_number = wrqu->data.lengt 69 70 return 0; 71 } 72 EXPORT_SYMBOL(iw_handler_set_spy); 73 74 int iw_handler_get_spy(struct net_device * 75 struct iw_request_info 76 union iwreq_data * 77 char * 78 { 79 struct iw_spy_data * spydata = get_ 80 struct sockaddr * address = (str 81 int i; 82 83 /* Make sure driver is not buggy or us 84 if (!spydata) 85 return -EOPNOTSUPP; 86 87 wrqu->data.length = spydata->spy_numbe 88 89 /* Copy addresses. */ 90 for (i = 0; i < spydata->spy_number; i 91 memcpy(address[i].sa_data, spy 92 address[i].sa_family = AF_UNIX 93 } 94 /* Copy stats to the user buffer (just 95 if (spydata->spy_number > 0) 96 memcpy(extra + (sizeof(struct 97 spydata->spy_stat, 98 sizeof(struct iw_qualit 99 /* Reset updated flags. */ 100 for (i = 0; i < spydata->spy_number; i 101 spydata->spy_stat[i].updated & 102 return 0; 103 } 104 EXPORT_SYMBOL(iw_handler_get_spy); 105 106 /*-------------------------------------------- 107 /* 108 * Standard Wireless Handler : set spy thresho 109 */ 110 int iw_handler_set_thrspy(struct net_device * 111 struct iw_request_in 112 union iwreq_data * 113 char * 114 { 115 struct iw_spy_data * spydata = get_ 116 struct iw_thrspy * threshold = (s 117 118 /* Make sure driver is not buggy or us 119 if (!spydata) 120 return -EOPNOTSUPP; 121 122 /* Just do it */ 123 spydata->spy_thr_low = threshold->low; 124 spydata->spy_thr_high = threshold->hig 125 126 /* Clear flag */ 127 memset(spydata->spy_thr_under, '\0', s 128 129 return 0; 130 } 131 EXPORT_SYMBOL(iw_handler_set_thrspy); 132 133 /*-------------------------------------------- 134 /* 135 * Standard Wireless Handler : get spy thresho 136 */ 137 int iw_handler_get_thrspy(struct net_device * 138 struct iw_request_in 139 union iwreq_data * 140 char * 141 { 142 struct iw_spy_data * spydata = get_ 143 struct iw_thrspy * threshold = (s 144 145 /* Make sure driver is not buggy or us 146 if (!spydata) 147 return -EOPNOTSUPP; 148 149 /* Just do it */ 150 threshold->low = spydata->spy_thr_low; 151 threshold->high = spydata->spy_thr_hig 152 153 return 0; 154 } 155 EXPORT_SYMBOL(iw_handler_get_thrspy); 156 157 /*-------------------------------------------- 158 /* 159 * Prepare and send a Spy Threshold event 160 */ 161 static void iw_send_thrspy_event(struct net_de 162 struct iw_spy 163 unsigned char 164 struct iw_qua 165 { 166 union iwreq_data wrqu; 167 struct iw_thrspy threshold; 168 169 /* Init */ 170 wrqu.data.length = 1; 171 wrqu.data.flags = 0; 172 /* Copy address */ 173 memcpy(threshold.addr.sa_data, address 174 threshold.addr.sa_family = ARPHRD_ETHE 175 /* Copy stats */ 176 threshold.qual = *wstats; 177 /* Copy also thresholds */ 178 threshold.low = spydata->spy_thr_low; 179 threshold.high = spydata->spy_thr_high 180 181 /* Send event to user space */ 182 wireless_send_event(dev, SIOCGIWTHRSPY 183 } 184 185 /* ------------------------------------------- 186 /* 187 * Call for the driver to update the spy data. 188 * For now, the spy data is a simple array. As 189 * small, this is good enough. If we wanted to 190 * spy addresses, we should use something more 191 */ 192 void wireless_spy_update(struct net_device * 193 unsigned char * 194 struct iw_quality * 195 { 196 struct iw_spy_data * spydata = get_ 197 int i; 198 int match = -1; 199 200 /* Make sure driver is not buggy or us 201 if (!spydata) 202 return; 203 204 /* Update all records that match */ 205 for (i = 0; i < spydata->spy_number; i 206 if (ether_addr_equal(address, 207 memcpy(&(spydata->spy_ 208 sizeof(struct i 209 match = i; 210 } 211 212 /* Generate an event if we cross the s 213 * To avoid event storms, we have a si 214 * event only when we go under the low 215 * high threshold. */ 216 if (match >= 0) { 217 if (spydata->spy_thr_under[mat 218 if (wstats->level > sp 219 spydata->spy_t 220 iw_send_thrspy 221 222 } 223 } else { 224 if (wstats->level < sp 225 spydata->spy_t 226 iw_send_thrspy 227 228 } 229 } 230 } 231 } 232 EXPORT_SYMBOL(wireless_spy_update); 233
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.