Please note: This project is no longer active. The website is kept online for historic purposes only.
If you´re looking for a Linux driver for your Atheros WLAN device, you should continue here .

ChipsetFeatures/Roaming: ath_roam.c

File ath_roam.c, 11.2 kB (added by sangho@winlab.rutgers.edu, 12 years ago)

ath_roam.c

Line 
1 #include <sys/types.h>
2 #include <sys/file.h>
3 #include <sys/ioctl.h>
4 #include <sys/socket.h>
5
6 #include <netinet/ether.h>
7
8 #include <linux/if.h>
9 #include <iwlib.h>
10
11 #include <stdio.h>
12 #include <string.h>
13 #include <unistd.h>
14
15 #define IEEE80211_IOCTL_SETPARAM        (SIOCIWFIRSTPRIV+0)
16 #define  IEEE80211_ADDR_LEN 6           /* size of 802.11 address */
17 #define IEEE80211_IOCTL_SETMLME         (SIOCIWFIRSTPRIV+16)
18
19 /* copied without modification from atheros_ng code trunk */
20 struct ath_stats {
21         u_int32_t       ast_watchdog;   /* device reset by watchdog */
22         u_int32_t       ast_hardware;   /* fatal hardware error interrupts */
23         u_int32_t       ast_bmiss;      /* beacon miss interrupts */
24         u_int32_t       ast_rxorn;      /* rx overrun interrupts */
25         u_int32_t       ast_rxeol;      /* rx eol interrupts */
26         u_int32_t       ast_txurn;      /* tx underrun interrupts */
27         u_int32_t       ast_mib;        /* mib interrupts */
28         u_int32_t       ast_tx_packets; /* packet sent on the interface */
29         u_int32_t       ast_tx_mgmt;    /* management frames transmitted */
30         u_int32_t       ast_tx_discard; /* frames discarded prior to assoc */
31         u_int32_t       ast_tx_invalid; /* frames discarded due to is device gone */
32         u_int32_t       ast_tx_qstop;   /* tx queue stopped because it's full */
33         u_int32_t       ast_tx_encap;   /* tx encapsulation failed */
34         u_int32_t       ast_tx_nonode;  /* tx failed due to of no node */
35         u_int32_t       ast_tx_nobuf;   /* tx failed due to of no tx buffer (data) */
36         u_int32_t       ast_tx_nobufmgt;/* tx failed due to of no tx buffer (mgmt)*/
37         u_int32_t       ast_tx_xretries;/* tx failed due to of too many retries */
38         u_int32_t       ast_tx_fifoerr; /* tx failed due to of FIFO underrun */
39         u_int32_t       ast_tx_filtered;/* tx failed due to xmit filtered */
40         u_int32_t       ast_tx_shortretry;/* tx on-chip retries (short) */
41         u_int32_t       ast_tx_longretry;/* tx on-chip retries (long) */
42         u_int32_t       ast_tx_badrate; /* tx failed due to of bogus xmit rate */
43         u_int32_t       ast_tx_noack;   /* tx frames with no ack marked */
44         u_int32_t       ast_tx_rts;     /* tx frames with rts enabled */
45         u_int32_t       ast_tx_cts;     /* tx frames with cts enabled */
46         u_int32_t       ast_tx_shortpre;/* tx frames with short preamble */
47         u_int32_t       ast_tx_altrate; /* tx frames with alternate rate */
48         u_int32_t       ast_tx_protect; /* tx frames with protection */
49         u_int32_t       ast_rx_orn;     /* rx failed due to of desc overrun */
50         u_int32_t       ast_rx_crcerr;  /* rx failed due to of bad CRC */
51         u_int32_t       ast_rx_fifoerr; /* rx failed due to of FIFO overrun */
52         u_int32_t       ast_rx_badcrypt;/* rx failed due to of decryption */
53         u_int32_t       ast_rx_badmic;  /* rx failed due to of MIC failure */
54         u_int32_t       ast_rx_phyerr;  /* rx PHY error summary count */
55         u_int32_t       ast_rx_phy[32]; /* rx PHY error per-code counts */
56         u_int32_t       ast_rx_tooshort;/* rx discarded due to frame too short */
57         u_int32_t       ast_rx_toobig;  /* rx discarded due to frame too large */
58         u_int32_t       ast_rx_nobuf;   /* rx setup failed due to of no skbuff */
59         u_int32_t       ast_rx_packets; /* packet recv on the interface */
60         u_int32_t       ast_rx_mgt;     /* management frames received */
61         u_int32_t       ast_rx_ctl;     /* control frames received */
62         int8_t          ast_tx_rssi;    /* tx rssi of last ack */
63         int8_t          ast_rx_rssi;    /* rx rssi from histogram */
64         u_int32_t       ast_be_xmit;    /* beacons transmitted */
65         u_int32_t       ast_be_nobuf;   /* no skbuff available for beacon */
66         u_int32_t       ast_per_cal;    /* periodic calibration calls */
67         u_int32_t       ast_per_calfail;/* periodic calibration failed */
68         u_int32_t       ast_per_rfgain; /* periodic calibration rfgain reset */
69         u_int32_t       ast_rate_calls; /* rate control checks */
70         u_int32_t       ast_rate_raise; /* rate control raised xmit rate */
71         u_int32_t       ast_rate_drop;  /* rate control dropped xmit rate */
72         u_int32_t       ast_ant_defswitch;/* rx/default antenna switches */
73         u_int32_t       ast_ant_txswitch;/* tx antenna switches */
74         u_int32_t       ast_ant_rx[8];  /* rx frames with antenna */
75         u_int32_t       ast_ant_tx[8];  /* tx frames with antenna */
76 };
77
78 /*
79  * MLME state manipulation request.  IEEE80211_MLME_ASSOC
80  * only makes sense when operating as a station.  The other
81  * requests can be used when operating as a station or an
82  * ap (to effect a station).
83  */
84 struct ieee80211req_mlme {
85         u_int8_t        im_op;          /* operation to perform */
86 #define IEEE80211_MLME_ASSOC            1       /* associate station */
87 #define IEEE80211_MLME_DISASSOC         2       /* disassociate station */
88 #define IEEE80211_MLME_DEAUTH           3       /* deauthenticate station */
89 #define IEEE80211_MLME_AUTHORIZE        4       /* authorize station */
90 #define IEEE80211_MLME_UNAUTHORIZE      5       /* unauthorize station */
91         u_int16_t       im_reason;      /* 802.11 reason code */
92         u_int8_t        im_macaddr[IEEE80211_ADDR_LEN];
93 };
94
95 enum {
96         IEEE80211_PARAM_TURBO           = 1,    /* turbo mode */
97         IEEE80211_PARAM_MODE            = 2,    /* phy mode (11a, 11b, etc.) */
98         IEEE80211_PARAM_AUTHMODE        = 3,    /* authentication mode */
99         IEEE80211_PARAM_PROTMODE        = 4,    /* 802.11g protection */
100         IEEE80211_PARAM_MCASTCIPHER     = 5,    /* multicast/default cipher */
101         IEEE80211_PARAM_MCASTKEYLEN     = 6,    /* multicast key length */
102         IEEE80211_PARAM_UCASTCIPHERS    = 7,    /* unicast cipher suites */
103         IEEE80211_PARAM_UCASTCIPHER     = 8,    /* unicast cipher */
104         IEEE80211_PARAM_UCASTKEYLEN     = 9,    /* unicast key length */
105         IEEE80211_PARAM_WPA             = 10,   /* WPA mode (0,1,2) */
106         IEEE80211_PARAM_ROAMING         = 12,   /* roaming mode */
107         IEEE80211_PARAM_PRIVACY         = 13,   /* privacy invoked */
108         IEEE80211_PARAM_COUNTERMEASURES = 14,   /* WPA/TKIP countermeasures */
109         IEEE80211_PARAM_DROPUNENCRYPTED = 15,   /* discard unencrypted frames */
110         IEEE80211_PARAM_DRIVER_CAPS     = 16,   /* driver capabilities */
111         IEEE80211_PARAM_MACCMD          = 17,   /* MAC ACL operation */
112         IEEE80211_PARAM_WMM             = 18,   /* WMM mode (on, off) */
113         IEEE80211_PARAM_HIDESSID        = 19,   /* hide SSID mode (on, off) */
114         IEEE80211_PARAM_APBRIDGE        = 20,   /* AP inter-sta bridging */
115         IEEE80211_PARAM_KEYMGTALGS      = 21,   /* key management algorithms */
116         IEEE80211_PARAM_RSNCAPS         = 22,   /* RSN capabilities */
117         IEEE80211_PARAM_INACT           = 23,   /* station inactivity timeout */
118         IEEE80211_PARAM_INACT_AUTH      = 24,   /* station auth inact timeout */
119         IEEE80211_PARAM_INACT_INIT      = 25,   /* station init inact timeout */
120         IEEE80211_PARAM_ABOLT           = 26,   /* Atheros Adv. Capabilities */
121         IEEE80211_PARAM_DTIM_PERIOD     = 28,   /* DTIM period (beacons) */
122         IEEE80211_PARAM_BEACON_INTERVAL = 29,   /* beacon interval (ms) */
123         IEEE80211_PARAM_DOTH            = 30,   /* 11.h is on/off */
124         IEEE80211_PARAM_PWRTARGET       = 31,   /* Current Channel Pwr Constraint */
125         IEEE80211_PARAM_GENREASSOC      = 32,   /* Generate a reassociation request */
126         IEEE80211_PARAM_COMPRESSION     = 33,   /* compression */
127         IEEE80211_PARAM_FF              = 34,   /* fast frames support  */
128         IEEE80211_PARAM_XR              = 35,   /* XR support */
129         IEEE80211_PARAM_BURST           = 36,   /* burst mode */
130         IEEE80211_PARAM_PUREG           = 37,   /* pure 11g (no 11b stations) */
131         IEEE80211_PARAM_AR              = 38,   /* AR support */
132         IEEE80211_PARAM_WDS             = 39,   /* Enable 4 address processing */
133         IEEE80211_PARAM_BGSCAN          = 40,   /* bg scanning (on, off) */
134         IEEE80211_PARAM_BGSCAN_IDLE     = 41,   /* bg scan idle threshold */
135         IEEE80211_PARAM_BGSCAN_INTERVAL = 42,   /* bg scan interval */
136         IEEE80211_PARAM_MCAST_RATE      = 43,   /* Multicast Tx Rate */
137         IEEE80211_PARAM_COVERAGE_CLASS  = 44,   /* coverage class */
138         IEEE80211_PARAM_COUNTRY_IE      = 45,   /* enable country IE */
139         IEEE80211_PARAM_SCANVALID       = 46,   /* scan cache valid threshold */
140         IEEE80211_PARAM_ROAM_RSSI_11A   = 47,   /* rssi threshold in 11a */
141         IEEE80211_PARAM_ROAM_RSSI_11B   = 48,   /* rssi threshold in 11b */
142         IEEE80211_PARAM_ROAM_RSSI_11G   = 49,   /* rssi threshold in 11g */
143         IEEE80211_PARAM_ROAM_RATE_11A   = 50,   /* tx rate threshold in 11a */
144         IEEE80211_PARAM_ROAM_RATE_11B   = 51,   /* tx rate threshold in 11b */
145         IEEE80211_PARAM_ROAM_RATE_11G   = 52,   /* tx rate threshold in 11g */
146         IEEE80211_PARAM_UAPSDINFO       = 53,   /* value for qos info field */
147         IEEE80211_PARAM_SLEEP           = 54,   /* force sleep/wake */
148         IEEE80211_PARAM_QOSNULL         = 55,   /* force sleep/wake */
149         IEEE80211_PARAM_PSPOLL          = 56,   /* force ps-poll generation (sta only) */
150         IEEE80211_PARAM_EOSPDROP        = 57,   /* force uapsd EOSP drop (ap only) */
151         IEEE80211_PARAM_MARKDFS         = 58,   /* mark a dfs interference channel when found */
152         IEEE80211_PARAM_REGCLASS        = 59,   /* enable regclass ids in country IE */
153 };
154
155 unsigned int ath_get_missed_beacon_count(int socket, char *device);
156 int ath_associate(int socket, char *device, char *mac);
157 int ath_disassoc(int socket, char *device, char *addr);
158
159 #ifdef ATHEROS_SUPPORT
160 static int set80211param(int socket, char *device, int op, int arg)
161 {
162   struct iwreq iwr;
163
164   memset(&iwr, 0, sizeof(iwr));
165   strncpy(iwr.ifr_name, device, IFNAMSIZ);
166   iwr.u.mode = op;
167   memcpy(iwr.u.name+sizeof(__u32), &arg, sizeof(arg));
168
169   if (ioctl(socket, IEEE80211_IOCTL_SETPARAM, &iwr) < 0) {
170     log_text(FATAL, "%s: ioctl() for atheros card (%s) failed (op: %d, arg: %d)\n", __FUNCTION__, device, op, arg);
171     return -1;
172   }
173
174   /*
175   log_text(DEBUG, "ioctl() for atheros card (%s) ok (op: %d, arg: %d)\n", __FUNCTION__, device, op, arg);
176   */
177
178   return 0;
179 }
180
181 static int set80211priv(int socket, char *device, int op, void *data, int len)
182 {
183   struct iwreq iwr;
184
185   memset(&iwr, 0, sizeof(iwr));
186   strncpy(iwr.ifr_name, device, IFNAMSIZ);
187   if (len < IFNAMSIZ) {
188     /* Argument data fits inline; put it there */
189     memcpy(iwr.u.name, data, len);
190   } else {
191     /*
192      * Argument data too big for inline transfer; setup a
193      * parameter block instead; the kernel will transfer
194      * the data for the driver.
195      */
196     iwr.u.data.pointer = data;
197     iwr.u.data.length = len;
198   }
199
200   if (ioctl(socket, op, &iwr) < 0) {
201     log_text(FATAL, "%s: private ioctl() for atheros card (%s) failed (op: %d)\n", __FUNCTION__, device, op);
202     return -1;
203   }
204
205   return 0;
206 }
207 #endif
208
209
210 int ath_associate(int socket, char *device, char *mac)
211 {
212 #ifdef ATHEROS_SUPPORT
213   struct ieee80211req_mlme mlme;
214   struct ether_addr *bin_mac;
215   int ret = 0;
216
217   bin_mac = ether_aton(mac);
218   memset(&mlme, 0, sizeof(mlme));
219   mlme.im_op = IEEE80211_MLME_ASSOC;
220   memcpy(mlme.im_macaddr, bin_mac->ether_addr_octet, IEEE80211_ADDR_LEN);
221
222   DBG_PRINT("%s(%02X:%02X:%02X:%02X:%02X:%02X)\n",
223       __FUNCTION__,
224       mlme.im_op[0] & 0xFF,
225       mlme.im_op[1] & 0xFF,
226       mlme.im_op[2] & 0xFF,
227       mlme.im_op[3] & 0xFF,
228       mlme.im_op[4] & 0xFF,
229       mlme.im_op[5] & 0xFF);
230
231   /* no privacy needed */
232   if (set80211param(socket, device, IEEE80211_PARAM_PRIVACY, 0) < 0)
233     ret = -1;
234
235   /* we take care of roaming, not the driver */
236   if (set80211param(socket, device, IEEE80211_PARAM_ROAMING, 2) < 0)
237     ret += -1;
238
239   /* assoc using a private ioctl */
240   if (set80211priv(socket, device, IEEE80211_IOCTL_SETMLME, &mlme, sizeof(mlme)) < 0)
241     ret += -1;
242
243   return ret;
244 #else
245
246   return -99;
247 #endif
248
249 }
250
251 int ath_disassoc(int socket, char *device, char *addr)
252 {
253 #ifdef ATHEROS_SUPPORT
254   struct ieee80211req_mlme mlme;
255   struct ether_addr *bin_mac;
256
257   bin_mac = ether_aton(addr);
258
259   DBG_PRINT("%s(%02X:%02X:%02X:%02X:%02X:%02X)\n",
260       __FUNCTION__,
261       bin_mac->ether_addr_octet[0] & 0xFF,
262       bin_mac->ether_addr_octet[1] & 0xFF,
263       bin_mac->ether_addr_octet[2] & 0xFF,
264       bin_mac->ether_addr_octet[3] & 0xFF,
265       bin_mac->ether_addr_octet[4] & 0xFF,
266       bin_mac->ether_addr_octet[5] & 0xFF);
267
268   mlme.im_op = IEEE80211_MLME_DISASSOC;
269   mlme.im_reason = 1;
270   memcpy(mlme.im_macaddr, bin_mac->ether_addr_octet, IEEE80211_ADDR_LEN);
271   return set80211priv(socket, device, IEEE80211_IOCTL_SETMLME, &mlme, sizeof(mlme));
272 #else
273
274   return -99;
275 #endif
276
277 }