driver_ndis_.c

Go to the documentation of this file.
00001 
00016 #include <stdlib.h>
00017 #include <stdio.h>
00018 #include <string.h>
00019 #include <sys/unistd.h>
00020 #include <sys/types.h>
00021 #ifndef CONFIG_NATIVE_WINDOWS
00022 #include <sys/socket.h>
00023 #include <netinet/in.h>
00024 #endif /* CONFIG_NATIVE_WINDOWS */
00025 
00026 #include "common.h"
00027 #include "driver.h"
00028 #include "wpa_supplicant.h"
00029 #include "l2_packet.h"
00030 #include "eloop.h"
00031 #include "wpa.h"
00032 
00033 /* Keep this event processing in a separate file and without WinPcap headers to
00034  * avoid conflicts with some of the header files. */
00035 struct _ADAPTER;
00036 typedef struct _ADAPTER * LPADAPTER;
00037 #include "driver_ndis.h"
00038 
00039 
00040 void wpa_driver_ndis_event_connect(struct wpa_driver_ndis_data *drv);
00041 void wpa_driver_ndis_event_disconnect(struct wpa_driver_ndis_data *drv);
00042 void wpa_driver_ndis_event_media_specific(struct wpa_driver_ndis_data *drv,
00043                                           const u8 *data, size_t data_len);
00044 
00045 
00046 enum event_types { EVENT_CONNECT, EVENT_DISCONNECT,
00047                    EVENT_MEDIA_SPECIFIC };
00048 
00049 /* Event data:
00050  * enum event_types (as int, i.e., 4 octets)
00051  * InstanceName length (1 octet)
00052  * InstanceName (variable len)
00053  * data length (1 octet, optional)
00054  * data (variable len, optional)
00055  */
00056 
00057 
00058 static void wpa_driver_ndis_event_cb(int sock, void *eloop_ctx, void *sock_ctx)
00059 {
00060         struct wpa_driver_ndis_data *drv = eloop_ctx;
00061         u8 buf[512], *pos, *data = NULL;
00062         int res, i, desc_len;
00063         enum event_types type;
00064         unsigned char instance_len;
00065         char *instance;
00066         size_t data_len = 0;
00067 
00068         res = recv(sock, buf, sizeof(buf), 0);
00069         if (res < 0) {
00070                 perror("wpa_driver_ndis_event_cb - recv");
00071                 return;
00072         }
00073         wpa_hexdump(MSG_MSGDUMP, "NDIS: received event data", buf, res);
00074         if (res < sizeof(int) + 1)
00075                 return;
00076         type = *((int *) buf);
00077         pos = buf + sizeof(int);
00078         wpa_printf(MSG_DEBUG, "NDIS: event - type %d", type);
00079         instance_len = *pos++;
00080         if (instance_len > buf + res - pos) {
00081                 wpa_printf(MSG_DEBUG, "NDIS: event InstanceName overflow");
00082                 return;
00083         }
00084         instance = pos;
00085         pos += instance_len;
00086         wpa_hexdump_ascii(MSG_MSGDUMP, "NDIS: event InstanceName",
00087                           instance, instance_len);
00088 
00089         if (buf + res - pos > 1) {
00090                 data_len = *pos++;
00091                 if (data_len > buf + res - pos) {
00092                         wpa_printf(MSG_DEBUG, "NDIS: event data overflow");
00093                         return;
00094                 }
00095                 data = pos;
00096                 wpa_hexdump(MSG_MSGDUMP, "NDIS: event data", data, data_len);
00097         }
00098 
00099         if (drv->adapter_desc) {
00100                 desc_len = strlen(drv->adapter_desc);
00101                 if (instance_len < desc_len ||
00102                     strncmp(drv->adapter_desc, instance, desc_len)) {
00103                         wpa_printf(MSG_DEBUG, "NDIS: ignored event for "
00104                                    "another adapter");
00105                         return;
00106                 }
00107 
00108                 /* InstanceName:
00109                  * <driver desc> #<num>
00110                  * <driver desc> #<num> - <intermediate drv name> Miniport
00111                  */
00112                 for (i = desc_len + 1; i < instance_len; i++) {
00113                         if (instance[i] == '-') {
00114                                 wpa_printf(MSG_DEBUG, "NDIS: ignored event "
00115                                            "for intermediate miniport");
00116                                 return;
00117                         }
00118                 }
00119         }
00120 
00121         switch (type) {
00122         case EVENT_CONNECT:
00123                 wpa_driver_ndis_event_connect(drv);
00124                 break;
00125         case EVENT_DISCONNECT:
00126                 wpa_driver_ndis_event_disconnect(drv);
00127                 break;
00128         case EVENT_MEDIA_SPECIFIC:
00129                 wpa_driver_ndis_event_media_specific(drv, data, data_len);
00130                 break;
00131         }
00132 }
00133 
00134 
00135 int wpa_driver_register_event_cb(struct wpa_driver_ndis_data *drv)
00136 {
00137         struct sockaddr_in addr;
00138 
00139         drv->event_sock = socket(PF_INET, SOCK_DGRAM, 0);
00140         if (drv->event_sock < 0) {
00141                 perror("socket");
00142                 return -1;
00143         }
00144 
00145         /* These events are received from an external program, ndis_events,
00146          * which is converting WMI events to more "UNIX-like" input for
00147          * wpa_supplicant, i.e., UDP packets that can be received through the
00148          * eloop mechanism. */
00149         memset(&addr, 0, sizeof(addr));
00150         addr.sin_family = AF_INET;
00151         addr.sin_addr.s_addr = htonl((127 << 24) | 1);
00152         addr.sin_port = htons(9876);
00153         if (bind(drv->event_sock, (struct sockaddr *) &addr, sizeof(addr)) < 0)
00154         {
00155                 perror("bind");
00156                 close(drv->event_sock);
00157                 drv->event_sock = -1;
00158                 return -1;
00159         }
00160 
00161         eloop_register_read_sock(drv->event_sock, wpa_driver_ndis_event_cb,
00162                                  drv, NULL);
00163 
00164         return 0;
00165 }
00166 

Generated on Sat May 6 21:13:33 2006 for wpa_supplicant by  doxygen 1.4.2