3 * Bill Paul <wpaul@windriver.com>. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by Bill Paul.
16 * 4. Neither the name of the author nor the names of any co-contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
30 * THE POSSIBILITY OF SUCH DAMAGE.
32 * $FreeBSD: head/usr.sbin/wpa/wpa_supplicant/Packet32.c 189220 2009-03-01 08:01:38Z sam $
37 * This file implements a small portion of the Winpcap API for the
38 * Windows NDIS interface in wpa_supplicant. It provides just enough
39 * routines to fool wpa_supplicant into thinking it's really running
40 * in a Windows environment.
43 #include <sys/types.h>
44 #include <sys/param.h>
45 #include <sys/socket.h>
46 #include <sys/ioctl.h>
47 #include <sys/errno.h>
48 #include <sys/sysctl.h>
49 #include <sys/fcntl.h>
51 #include <net/if_dl.h>
52 #include <net/if_var.h>
54 #include <netinet/in.h>
55 #include <arpa/inet.h>
58 #include <net/route.h>
60 #include <netproto/802_11/ieee80211_ioctl.h>
70 #define OID_802_11_ADD_KEY 0x0d01011D
72 typedef ULONGLONG NDIS_802_11_KEY_RSC
;
73 typedef UCHAR NDIS_802_11_MAC_ADDRESS
[6];
75 typedef struct NDIS_802_11_KEY
{
79 NDIS_802_11_MAC_ADDRESS BSSID
;
80 NDIS_802_11_KEY_RSC KeyRSC
;
84 typedef struct NDIS_802_11_KEY_COMPAT
{
88 NDIS_802_11_MAC_ADDRESS BSSID
;
89 UCHAR Pad
[6]; /* Make struct layout match Windows. */
90 NDIS_802_11_KEY_RSC KeyRSC
;
94 } NDIS_802_11_KEY_COMPAT
;
106 PacketGetVersion(void)
108 return("FreeBSD WinPcap compatibility shim v1.0");
112 PacketOpenAdapter(CHAR
*iface
)
118 struct ieee80211req ireq
;
120 s
= socket(PF_INET
, SOCK_DGRAM
, 0);
125 a
= malloc(sizeof(struct adapter
));
130 if (strncmp(iface
, "\\Device\\NPF_", 12) == 0)
132 else if (strncmp(iface
, "\\DEVICE\\", 8) == 0)
134 snprintf(a
->name
, IFNAMSIZ
, "%s", iface
);
136 /* Turn off net80211 roaming */
137 bzero((char *)&ireq
, sizeof(ireq
));
138 strncpy(ireq
.i_name
, iface
, sizeof (ifr
.ifr_name
));
139 ireq
.i_type
= IEEE80211_IOC_ROAMING
;
140 if (ioctl(a
->socket
, SIOCG80211
, &ireq
) == 0) {
141 a
->prev_roaming
= ireq
.i_val
;
142 ireq
.i_val
= IEEE80211_ROAMING_MANUAL
;
143 if (ioctl(a
->socket
, SIOCS80211
, &ireq
) < 0)
145 "Could not set IEEE80211_ROAMING_MANUAL\n");
148 bzero((char *)&ifr
, sizeof(ifr
));
149 strncpy(ifr
.ifr_name
, iface
, sizeof (ifr
.ifr_name
));
150 if (ioctl(a
->socket
, SIOCGIFFLAGS
, (caddr_t
)&ifr
) < 0) {
155 ifr
.ifr_flags
|= IFF_UP
;
156 if (ioctl(a
->socket
, SIOCSIFFLAGS
, (caddr_t
)&ifr
) < 0) {
166 PacketRequest(void *iface
, BOOLEAN set
, PACKET_OID_DATA
*oid
)
171 NDIS_802_11_KEY
*old
;
172 NDIS_802_11_KEY_COMPAT
*new;
173 PACKET_OID_DATA
*o
= NULL
;
179 bzero((char *)&ifr
, sizeof(ifr
));
182 * This hack is necessary to work around a difference
183 * betwee the GNU C and Microsoft C compilers. The NDIS_802_11_KEY
184 * structure has a uint64_t in it, right after an array of
185 * chars. The Microsoft compiler inserts padding right before
186 * the 64-bit value to align it on a 64-bit boundary, but
187 * GCC only aligns it on a 32-bit boundary. Trying to pass
188 * the GCC-formatted structure to an NDIS binary driver
189 * fails because some of the fields appear to be at the
192 * To get around this, if we detect someone is trying to do
193 * a set operation on OID_802_11_ADD_KEY, we shuffle the data
194 * into a properly padded structure and pass that into the
195 * driver instead. This allows the driver_ndis.c code supplied
196 * with wpa_supplicant to work unmodified.
199 if (set
== TRUE
&& oid
->Oid
== OID_802_11_ADD_KEY
) {
200 old
= (NDIS_802_11_KEY
*)&oid
->Data
;
201 o
= malloc(sizeof(PACKET_OID_DATA
) +
202 sizeof(NDIS_802_11_KEY_COMPAT
) + old
->KeyLength
);
205 bzero((char *)o
, sizeof(PACKET_OID_DATA
) +
206 sizeof(NDIS_802_11_KEY_COMPAT
) + old
->KeyLength
);
208 o
->Length
= sizeof(NDIS_802_11_KEY_COMPAT
) + old
->KeyLength
;
209 new = (NDIS_802_11_KEY_COMPAT
*)&o
->Data
;
210 new->KeyRSC
= old
->KeyRSC
;
211 new->Length
= o
->Length
;
212 new->KeyIndex
= old
->KeyIndex
;
213 new->KeyLength
= old
->KeyLength
;
214 bcopy(old
->BSSID
, new->BSSID
, sizeof(NDIS_802_11_MAC_ADDRESS
));
215 bcopy(old
->KeyMaterial
, (char *)new +
216 sizeof(NDIS_802_11_KEY_COMPAT
), new->KeyLength
);
217 ifr
.ifr_data
= (caddr_t
)o
;
219 ifr
.ifr_data
= (caddr_t
)oid
;
221 strlcpy(ifr
.ifr_name
, a
->name
, sizeof(ifr
.ifr_name
));
224 retval
= ioctl(a
->socket
, SIOCSDRVSPEC
, &ifr
);
226 retval
= ioctl(a
->socket
, SIOCGDRVSPEC
, &ifr
);
238 PacketGetAdapterNames(CHAR
*namelist
, ULONG
*len
)
242 struct if_msghdr
*ifm
;
243 struct sockaddr_dl
*sdl
;
244 char *buf
, *lim
, *next
;
257 mib
[2] = 0; /* protocol */
258 mib
[3] = 0; /* wildcard address family */
259 mib
[4] = NET_RT_IFLIST
;
260 mib
[5] = 0; /* no flags */
262 if (sysctl (mib
, 6, NULL
, &needed
, NULL
, 0) < 0)
265 buf
= malloc (needed
);
269 if (sysctl (mib
, 6, buf
, &needed
, NULL
, 0) < 0) {
276 /* Generate interface name list. */
280 ifm
= (struct if_msghdr
*)next
;
281 if (ifm
->ifm_type
== RTM_IFINFO
) {
282 sdl
= (struct sockaddr_dl
*)(ifm
+ 1);
283 if (strnstr(sdl
->sdl_data
, "wlan", sdl
->sdl_nlen
)) {
284 if ((spc
+ sdl
->sdl_nlen
) > *len
) {
288 strncpy(plist
, sdl
->sdl_data
, sdl
->sdl_nlen
);
289 plist
+= (sdl
->sdl_nlen
+ 1);
290 spc
+= (sdl
->sdl_nlen
+ 1);
294 next
+= ifm
->ifm_msglen
;
298 /* Insert an extra "" as a spacer */
304 * Now generate the interface description list. There
305 * must be a unique description for each interface, and
306 * they have to match what the ndis_events program will
307 * feed in later. To keep this simple, we just repeat
308 * the interface list over again.
313 ifm
= (struct if_msghdr
*)next
;
314 if (ifm
->ifm_type
== RTM_IFINFO
) {
315 sdl
= (struct sockaddr_dl
*)(ifm
+ 1);
316 if (strnstr(sdl
->sdl_data
, "wlan", sdl
->sdl_nlen
)) {
317 if ((spc
+ sdl
->sdl_nlen
) > *len
) {
321 strncpy(plist
, sdl
->sdl_data
, sdl
->sdl_nlen
);
322 plist
+= (sdl
->sdl_nlen
+ 1);
323 spc
+= (sdl
->sdl_nlen
+ 1);
327 next
+= ifm
->ifm_msglen
;
338 PacketCloseAdapter(void *iface
)
342 struct ieee80211req ireq
;
349 /* Reset net80211 roaming */
350 bzero((char *)&ireq
, sizeof(ireq
));
351 strncpy(ireq
.i_name
, a
->name
, sizeof (ifr
.ifr_name
));
352 ireq
.i_type
= IEEE80211_IOC_ROAMING
;
353 ireq
.i_val
= a
->prev_roaming
;
354 ioctl(a
->socket
, SIOCS80211
, &ireq
);
356 bzero((char *)&ifr
, sizeof(ifr
));
357 strncpy(ifr
.ifr_name
, a
->name
, sizeof (ifr
.ifr_name
));
358 ioctl(a
->socket
, SIOCGIFFLAGS
, (caddr_t
)&ifr
);
359 ifr
.ifr_flags
&= ~IFF_UP
;
360 ioctl(a
->socket
, SIOCSIFFLAGS
, (caddr_t
)&ifr
);